summaryrefslogtreecommitdiff
path: root/chromium/content
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-24 12:15:48 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:30:04 +0000
commitb014812705fc80bff0a5c120dfcef88f349816dc (patch)
tree25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/content
parent9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff)
downloadqtwebengine-chromium-b014812705fc80bff0a5c120dfcef88f349816dc.tar.gz
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content')
-rw-r--r--chromium/content/BUILD.gn4
-rw-r--r--chromium/content/DEPS6
-rw-r--r--chromium/content/OWNERS6
-rw-r--r--chromium/content/app/BUILD.gn11
-rw-r--r--chromium/content/app/content_main_runner_impl.cc (renamed from chromium/content/app/content_main_runner.cc)433
-rw-r--r--chromium/content/app/content_main_runner_impl.h89
-rw-r--r--chromium/content/app/content_service_manager_main_delegate.cc15
-rw-r--r--chromium/content/app/content_service_manager_main_delegate.h10
-rw-r--r--chromium/content/app/strings/content_strings.grd128
-rw-r--r--chromium/content/app/strings/translations/content_strings_am.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_ar.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_bg.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_bn.xtb46
-rw-r--r--chromium/content/app/strings/translations/content_strings_ca.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_cs.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_da.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_de.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_el.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_en-GB.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_es-419.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_es.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_et.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_fa.xtb52
-rw-r--r--chromium/content/app/strings/translations/content_strings_fi.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_fil.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_fr.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_gu.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_hi.xtb54
-rw-r--r--chromium/content/app/strings/translations/content_strings_hr.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_hu.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_id.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_it.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_iw.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_ja.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_kn.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_ko.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_lt.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_lv.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_ml.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_mr.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_ms.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_nl.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_no.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_pl.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-BR.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-PT.xtb46
-rw-r--r--chromium/content/app/strings/translations/content_strings_ro.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_ru.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_sk.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_sl.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_sr.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_sv.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_sw.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_ta.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_te.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_th.xtb46
-rw-r--r--chromium/content/app/strings/translations/content_strings_tr.xtb46
-rw-r--r--chromium/content/app/strings/translations/content_strings_uk.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_vi.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-CN.xtb44
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-TW.xtb44
-rw-r--r--chromium/content/browser/BUILD.gn252
-rw-r--r--chromium/content/browser/DEPS17
-rw-r--r--chromium/content/browser/OWNERS2
-rw-r--r--chromium/content/browser/accessibility/accessibility_action_browsertest.cc8
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc4
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc4
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc534
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc80
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h7
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc156
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm92
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.cc234
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc22
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc75
-rw-r--r--chromium/content/browser/accessibility/captioning_controller.cc2
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc12
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc3
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc18
-rw-r--r--chromium/content/browser/accessibility/fullscreen_browsertest.cc4
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc28
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.cc24
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.h22
-rw-r--r--chromium/content/browser/android/OWNERS4
-rw-r--r--chromium/content/browser/android/app_web_message_port.cc8
-rw-r--r--chromium/content/browser/android/content_protocol_handler_impl.cc5
-rw-r--r--chromium/content/browser/android/content_ui_event_handler.cc220
-rw-r--r--chromium/content/browser/android/content_ui_event_handler.h82
-rw-r--r--chromium/content/browser/android/content_video_view.cc24
-rw-r--r--chromium/content/browser/android/content_view_core.cc139
-rw-r--r--chromium/content/browser/android/content_view_core.h47
-rw-r--r--chromium/content/browser/android/content_view_render_view.cc7
-rw-r--r--chromium/content/browser/android/content_view_render_view.h2
-rw-r--r--chromium/content/browser/android/content_view_statics.cc10
-rw-r--r--chromium/content/browser/android/gesture_listener_manager.cc24
-rw-r--r--chromium/content/browser/android/gesture_listener_manager.h11
-rw-r--r--chromium/content/browser/android/ime_adapter_android.cc9
-rw-r--r--chromium/content/browser/android/interstitial_page_delegate_android.cc95
-rw-r--r--chromium/content/browser/android/interstitial_page_delegate_android.h54
-rw-r--r--chromium/content/browser/android/java/java_bridge_thread.cc1
-rw-r--r--chromium/content/browser/android/overscroll_controller_android_unittest.cc7
-rw-r--r--chromium/content/browser/android/string_message_codec.cc145
-rw-r--r--chromium/content/browser/android/string_message_codec.h33
-rw-r--r--chromium/content/browser/android/string_message_codec_unittest.cc139
-rw-r--r--chromium/content/browser/android/synchronous_compositor_browser_filter.cc124
-rw-r--r--chromium/content/browser/android/synchronous_compositor_browser_filter.h53
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc145
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h10
-rw-r--r--chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc66
-rw-r--r--chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h18
-rw-r--r--chromium/content/browser/android/url_request_content_job.cc1
-rw-r--r--chromium/content/browser/android/url_request_content_job_unittest.cc2
-rw-r--r--chromium/content/browser/appcache/OWNERS3
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache_unittest.cc1
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.cc39
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.h12
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc35
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.h19
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc27
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.h1
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl_unittest.cc1
-rw-r--r--chromium/content/browser/appcache/appcache_subresource_url_factory.cc10
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.cc3
-rw-r--r--chromium/content/browser/appcache/appcache_url_loader_job.h3
-rw-r--r--chromium/content/browser/background_fetch/background_fetch.proto40
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.cc124
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_context.h17
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.cc190
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager.h21
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc489
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc53
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h43
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc43
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc6
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h3
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc14
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h4
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc23
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.cc43
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller.h11
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc4
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_metrics.cc27
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_metrics.h31
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.cc11
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler.h5
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc2
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_impl.cc12
-rw-r--r--chromium/content/browser/background_fetch/background_fetch_service_unittest.cc18
-rw-r--r--chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc9
-rw-r--r--chromium/content/browser/background_fetch/mock_background_fetch_delegate.h8
-rw-r--r--chromium/content/browser/background_fetch/storage/README.md28
-rw-r--r--chromium/content/browser/background_fetch/storage/create_metadata_task.cc22
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.cc54
-rw-r--r--chromium/content/browser/background_fetch/storage/database_helpers.h29
-rw-r--r--chromium/content/browser/background_fetch/storage/delete_registration_task.cc2
-rw-r--r--chromium/content/browser/background_fetch/storage/get_num_requests_task.cc88
-rw-r--r--chromium/content/browser/background_fetch/storage/get_num_requests_task.h53
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc111
-rw-r--r--chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h61
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc7
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc106
-rw-r--r--chromium/content/browser/background_fetch/storage/mark_request_complete_task.h60
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc161
-rw-r--r--chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h72
-rw-r--r--chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc48
-rw-r--r--chromium/content/browser/background_fetch/storage/update_registration_ui_task.h7
-rw-r--r--chromium/content/browser/background_sync/background_sync_context.cc19
-rw-r--r--chromium/content/browser/background_sync/background_sync_context.h9
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.cc41
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.h12
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager_unittest.cc112
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc3
-rw-r--r--chromium/content/browser/bad_message.h17
-rw-r--r--chromium/content/browser/blob_storage/blob_url_unittest.cc1
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.cc25
-rw-r--r--chromium/content/browser/blob_storage/chrome_blob_storage_context.h15
-rw-r--r--chromium/content/browser/browser_associated_interface_unittest.cc2
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc85
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h3
-rw-r--r--chromium/content/browser/browser_context.cc38
-rw-r--r--chromium/content/browser/browser_main.cc13
-rw-r--r--chromium/content/browser/browser_main.h7
-rw-r--r--chromium/content/browser/browser_main_loop.cc301
-rw-r--r--chromium/content/browser/browser_main_loop.h48
-rw-r--r--chromium/content/browser/browser_main_loop_unittest.cc2
-rw-r--r--chromium/content/browser/browser_main_runner.cc269
-rw-r--r--chromium/content/browser/browser_main_runner_impl.cc256
-rw-r--r--chromium/content/browser/browser_main_runner_impl.h65
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc78
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h24
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc10
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_message_filter.h5
-rw-r--r--chromium/content/browser/browser_process_sub_thread.cc57
-rw-r--r--chromium/content/browser/browser_process_sub_thread.h4
-rw-r--r--chromium/content/browser/browser_side_navigation_browsertest.cc258
-rw-r--r--chromium/content/browser/browser_thread_unittest.cc82
-rw-r--r--chromium/content/browser/browsing_data/OWNERS2
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc79
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h7
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc94
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl.cc117
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl_browsertest.cc90
-rw-r--r--chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc386
-rw-r--r--chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc2
-rw-r--r--chromium/content/browser/browsing_data/conditional_cache_deletion_helper.h2
-rw-r--r--chromium/content/browser/byte_stream.cc8
-rw-r--r--chromium/content/browser/byte_stream.h6
-rw-r--r--chromium/content/browser/byte_stream_unittest.cc14
-rw-r--r--chromium/content/browser/cache_storage/OWNERS1
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.cc104
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.h27
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc164
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h38
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc364
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.cc5
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc117
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc152
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.h54
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc335
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_quota_client.cc30
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_quota_client.h9
-rw-r--r--chromium/content/browser/child_process_launcher.cc55
-rw-r--r--chromium/content/browser/child_process_launcher.h20
-rw-r--r--chromium/content/browser/child_process_launcher_helper.h29
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.cc46
-rw-r--r--chromium/content/browser/child_process_launcher_helper_fuchsia.cc17
-rw-r--r--chromium/content/browser/child_process_launcher_helper_linux.cc43
-rw-r--r--chromium/content/browser/child_process_launcher_helper_mac.cc30
-rw-r--r--chromium/content/browser/child_process_launcher_helper_posix.cc7
-rw-r--r--chromium/content/browser/child_process_launcher_helper_posix.h4
-rw-r--r--chromium/content/browser/child_process_launcher_helper_win.cc17
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc10
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.mm1
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map_unittest.mm2
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.cc2
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.h7
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc84
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h26
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.cc50
-rw-r--r--chromium/content/browser/compositor/gpu_output_surface_mac.h23
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc135
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h19
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc23
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.h12
-rw-r--r--chromium/content/browser/compositor/in_process_display_client.cc32
-rw-r--r--chromium/content/browser/compositor/in_process_display_client.h20
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc21
-rw-r--r--chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h11
-rw-r--r--chromium/content/browser/compositor/reflector_impl_unittest.cc16
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.cc54
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.h22
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc3
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.cc135
-rw-r--r--chromium/content/browser/compositor/viz_process_transport_factory.h29
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc19
-rw-r--r--chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h4
-rw-r--r--chromium/content/browser/cookie_store/BUILD.gn11
-rw-r--r--chromium/content/browser/cookie_store/OWNERS8
-rw-r--r--chromium/content/browser/cookie_store/cookie_change_subscription.cc182
-rw-r--r--chromium/content/browser/cookie_store/cookie_change_subscription.h114
-rw-r--r--chromium/content/browser/cookie_store/cookie_change_subscriptions.proto27
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_context.cc117
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_context.h98
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_host.cc38
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_host.h59
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager.cc530
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager.h228
-rw-r--r--chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc863
-rw-r--r--chromium/content/browser/dedicated_worker/dedicated_worker_host.cc62
-rw-r--r--chromium/content/browser/dedicated_worker/dedicated_worker_host.h8
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_browsertest.cc1
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc11
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h1
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler.cc2
-rw-r--r--chromium/content/browser/devtools/devtools_io_context.cc523
-rw-r--r--chromium/content/browser/devtools/devtools_io_context.h53
-rw-r--r--chromium/content/browser/devtools/devtools_manager.cc1
-rw-r--r--chromium/content/browser/devtools/devtools_manager_unittest.cc5
-rw-r--r--chromium/content/browser/devtools/devtools_network_interceptor.cc2
-rw-r--r--chromium/content/browser/devtools/devtools_network_interceptor.h6
-rw-r--r--chromium/content/browser/devtools/devtools_session.cc6
-rw-r--r--chromium/content/browser/devtools/devtools_session.h4
-rw-r--r--chromium/content/browser/devtools/devtools_stream_blob.cc251
-rw-r--r--chromium/content/browser/devtools/devtools_stream_blob.h94
-rw-r--r--chromium/content/browser/devtools/devtools_stream_file.cc142
-rw-r--r--chromium/content/browser/devtools/devtools_stream_file.h44
-rw-r--r--chromium/content/browser/devtools/devtools_stream_pipe.cc133
-rw-r--r--chromium/content/browser/devtools/devtools_stream_pipe.h55
-rw-r--r--chromium/content/browser/devtools/devtools_target_registry.cc4
-rw-r--r--chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc45
-rw-r--r--chromium/content/browser/devtools/devtools_url_loader_interceptor.cc165
-rw-r--r--chromium/content/browser/devtools/devtools_url_loader_interceptor.h4
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer.cc5
-rw-r--r--chromium/content/browser/devtools/devtools_video_consumer_unittest.cc3
-rw-r--r--chromium/content/browser/devtools/forwarding_agent_host.cc6
-rw-r--r--chromium/content/browser/devtools/forwarding_agent_host.h1
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc210
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.cc18
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc16
-rw-r--r--chromium/content/browser/devtools/protocol/io_handler.cc17
-rw-r--r--chromium/content/browser/devtools/protocol/memory_handler.cc48
-rw-r--r--chromium/content/browser/devtools/protocol/memory_handler.h14
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc313
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.h36
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc294
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h40
-rw-r--r--chromium/content/browser/devtools/protocol/system_info_handler.cc3
-rw-r--r--chromium/content/browser/devtools/protocol/target_auto_attacher.cc6
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.cc11
-rw-r--r--chromium/content/browser/devtools/protocol/target_handler.h5
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc19
-rw-r--r--chromium/content/browser/devtools/protocol_config.json11
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc67
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h42
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.cc3
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.h2
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_manager.cc3
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc3
-rw-r--r--chromium/content/browser/dom_storage/OWNERS3
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc19
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database.h2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database_unittest.cc16
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo.cc2
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo.h1
-rw-r--r--chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc382
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo.cc835
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo.h176
-rw-r--r--chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc762
-rw-r--r--chromium/content/browser/dom_storage/session_storage_data_map.cc105
-rw-r--r--chromium/content/browser/dom_storage/session_storage_data_map.h107
-rw-r--r--chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc186
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc7
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.h6
-rw-r--r--chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.cc165
-rw-r--r--chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.h106
-rw-r--r--chromium/content/browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc376
-rw-r--r--chromium/content/browser/dom_storage/session_storage_metadata.cc427
-rw-r--r--chromium/content/browser/dom_storage/session_storage_metadata.h182
-rw-r--r--chromium/content/browser/dom_storage/session_storage_metadata_unittest.cc480
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc178
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h158
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc458
-rw-r--r--chromium/content/browser/download/blob_download_url_loader_factory_getter.cc4
-rw-r--r--chromium/content/browser/download/byte_stream_input_stream.cc5
-rw-r--r--chromium/content/browser/download/byte_stream_input_stream.h2
-rw-r--r--chromium/content/browser/download/download_browsertest.cc150
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc644
-rw-r--r--chromium/content/browser/download/download_manager_impl.h92
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc45
-rw-r--r--chromium/content/browser/download/download_request_core.cc10
-rw-r--r--chromium/content/browser/download/download_url_loader_factory_getter_impl.cc25
-rw-r--r--chromium/content/browser/download/download_url_loader_factory_getter_impl.h39
-rw-r--r--chromium/content/browser/download/download_utils.cc1
-rw-r--r--chromium/content/browser/download/drag_download_file_browsertest.cc8
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.cc6
-rw-r--r--chromium/content/browser/download/network_download_url_loader_factory_getter.cc22
-rw-r--r--chromium/content/browser/download/network_download_url_loader_factory_getter.h10
-rw-r--r--chromium/content/browser/download/save_package.cc28
-rw-r--r--chromium/content/browser/download/save_package.h5
-rw-r--r--chromium/content/browser/download/save_package_unittest.cc4
-rw-r--r--chromium/content/browser/download/url_downloader_factory.cc4
-rw-r--r--chromium/content/browser/download/url_downloader_factory.h7
-rw-r--r--chromium/content/browser/file_url_loader_factory.cc23
-rw-r--r--chromium/content/browser/fileapi/OWNERS2
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc16
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc2
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory.cc644
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory.h31
-rw-r--r--chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc817
-rw-r--r--chromium/content/browser/fileapi/fileapi_browsertest.cc2
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.h1
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc8
-rw-r--r--chromium/content/browser/find_request_manager.cc71
-rw-r--r--chromium/content/browser/find_request_manager.h32
-rw-r--r--chromium/content/browser/frame_host/OWNERS3
-rw-r--r--chromium/content/browser/frame_host/ancestor_throttle.cc45
-rw-r--r--chromium/content/browser/frame_host/ancestor_throttle.h5
-rw-r--r--chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc1418
-rw-r--r--chromium/content/browser/frame_host/blocked_scheme_navigation_throttle.cc (renamed from chromium/content/browser/frame_host/data_url_navigation_throttle.cc)30
-rw-r--r--chromium/content/browser/frame_host/blocked_scheme_navigation_throttle.h35
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc124
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h57
-rw-r--r--chromium/content/browser/frame_host/data_url_navigation_browsertest.cc1032
-rw-r--r--chromium/content/browser/frame_host/data_url_navigation_throttle.h33
-rw-r--r--chromium/content/browser/frame_host/form_submission_throttle.cc7
-rw-r--r--chromium/content/browser/frame_host/form_submission_throttle_browsertest.cc2
-rw-r--r--chromium/content/browser/frame_host/frame_navigation_entry.cc12
-rw-r--r--chromium/content/browser/frame_host/frame_navigation_entry.h60
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc50
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node_blame_context.cc12
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc2
-rw-r--r--chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc158
-rw-r--r--chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h70
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc74
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h9
-rw-r--r--chromium/content/browser/frame_host/keep_alive_handle_factory.cc37
-rw-r--r--chromium/content/browser/frame_host/keep_alive_handle_factory.h6
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc8
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.h6
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc216
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h25
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc132
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc63
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc63
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h30
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc3
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc86
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h21
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc172
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc41
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc444
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h57
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.cc10
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.h29
-rw-r--r--chromium/content/browser/frame_host/navigator.cc18
-rw-r--r--chromium/content/browser/frame_host/navigator.h39
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc198
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h61
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc117
-rw-r--r--chromium/content/browser/frame_host/popup_menu_helper_mac.h16
-rw-r--r--chromium/content/browser/frame_host/popup_menu_helper_mac.mm47
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc4
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h18
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc2
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc723
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h198
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc596
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc83
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h9
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc510
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc307
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc68
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h17
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc53
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.h6
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc45
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h19
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc16
-rw-r--r--chromium/content/browser/frame_host/webui_navigation_browsertest.cc238
-rw-r--r--chromium/content/browser/frame_host/webui_navigation_throttle.cc59
-rw-r--r--chromium/content/browser/frame_host/webui_navigation_throttle.h46
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc406
-rw-r--r--chromium/content/browser/gpu/compositor_util.h13
-rw-r--r--chromium/content/browser/gpu/gpu_client_impl.cc (renamed from chromium/content/browser/gpu/gpu_client.cc)73
-rw-r--r--chromium/content/browser/gpu/gpu_client_impl.h (renamed from chromium/content/browser/gpu/gpu_client.h)31
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc51
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h27
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc127
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h26
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc2
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h3
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_testing_autogen.cc130
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h2
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc107
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc124
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h10
-rw-r--r--chromium/content/browser/histogram_internals_request_job.cc92
-rw-r--r--chromium/content/browser/histogram_internals_request_job.h52
-rw-r--r--chromium/content/browser/histogram_internals_url_loader.cc36
-rw-r--r--chromium/content/browser/histogram_internals_url_loader.h18
-rw-r--r--chromium/content/browser/histograms_internals_ui.cc113
-rw-r--r--chromium/content/browser/histograms_internals_ui.h25
-rw-r--r--chromium/content/browser/hyphenation/hyphenation_impl.h1
-rw-r--r--chromium/content/browser/indexed_db/OWNERS3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc62
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc134
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc32
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc60
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.h4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc4
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc50
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.h7
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc39
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_write_batch.h3
-rw-r--r--chromium/content/browser/indexed_db/leveldb/mock_level_db.h4
-rw-r--r--chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h2
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.h25
-rw-r--r--chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h2
-rw-r--r--chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h2
-rw-r--r--chromium/content/browser/initiator_csp_context.cc55
-rw-r--r--chromium/content/browser/initiator_csp_context.h42
-rw-r--r--chromium/content/browser/isolated_origin_browsertest.cc112
-rw-r--r--chromium/content/browser/keyboard_lock/keyboard_lock_metrics.h26
-rw-r--r--chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc59
-rw-r--r--chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h1
-rw-r--r--chromium/content/browser/keyboard_lock_browsertest.cc598
-rw-r--r--chromium/content/browser/keyboard_lock_browsertest.h16
-rw-r--r--chromium/content/browser/keyboard_lock_browsertest_mac.mm39
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl.cc8
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl.h1
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl_unittest.cc179
-rw-r--r--chromium/content/browser/linux_ipc_browsertest.cc3
-rw-r--r--chromium/content/browser/loader/cors_file_origin_browsertest.cc2
-rw-r--r--chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc22
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.cc434
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler.h62
-rw-r--r--chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc54
-rw-r--r--chromium/content/browser/loader/data_pipe_to_source_stream_unittest.cc4
-rw-r--r--chromium/content/browser/loader/loader_browsertest.cc (renamed from chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc)415
-rw-r--r--chromium/content/browser/loader/mime_sniffing_resource_handler.cc24
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.cc62
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler.h5
-rw-r--r--chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc14
-rw-r--r--chromium/content/browser/loader/navigation_loader_util.cc58
-rw-r--r--chromium/content/browser/loader/navigation_loader_util.h34
-rw-r--r--chromium/content/browser/loader/navigation_metrics.cc25
-rw-r--r--chromium/content/browser/loader/navigation_metrics.h32
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.cc182
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.h83
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.cc16
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_delegate.h31
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc1412
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h110
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.cc169
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.h105
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc (renamed from chromium/content/browser/loader/navigation_url_loader_network_service_unittest.cc)64
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_network_service.cc1344
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_network_service.h93
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc51
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.cc25
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.h12
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.cc23
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.h7
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc755
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h60
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc8
-rw-r--r--chromium/content/browser/loader/resource_hints_impl.cc4
-rw-r--r--chromium/content/browser/loader/resource_loader.cc59
-rw-r--r--chromium/content/browser/loader/resource_loader.h13
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc4
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc25
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc42
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h55
-rw-r--r--chromium/content/browser/loader/resource_requester_info.cc3
-rw-r--r--chromium/content/browser/loader/source_stream_to_data_pipe_unittest.cc4
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.cc1
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc3
-rw-r--r--chromium/content/browser/loader/url_loader_factory_impl_unittest.cc34
-rw-r--r--chromium/content/browser/mach_broker_mac.h8
-rw-r--r--chromium/content/browser/mach_broker_mac.mm8
-rw-r--r--chromium/content/browser/manifest/manifest_browsertest.cc13
-rw-r--r--chromium/content/browser/manifest/manifest_icon_selector.cc4
-rw-r--r--chromium/content/browser/manifest/manifest_icon_selector_unittest.cc52
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.cc11
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.h11
-rw-r--r--chromium/content/browser/media/OWNERS4
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.cc3
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.cc219
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker.h86
-rw-r--r--chromium/content/browser/media/audio_input_stream_broker_unittest.cc278
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker.cc164
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker.h74
-rw-r--r--chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc374
-rw-r--r--chromium/content/browser/media/audio_muting_session.cc22
-rw-r--r--chromium/content/browser/media/audio_muting_session.h32
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.cc157
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker.h79
-rw-r--r--chromium/content/browser/media/audio_output_stream_broker_unittest.cc281
-rw-r--r--chromium/content/browser/media/audio_stream_broker.cc85
-rw-r--r--chromium/content/browser/media/audio_stream_broker.h139
-rw-r--r--chromium/content/browser/media/capture/OWNERS3
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc1
-rw-r--r--chromium/content/browser/media/capture/aura_window_video_capture_device.cc171
-rw-r--r--chromium/content/browser/media/capture/aura_window_video_capture_device.h57
-rw-r--r--chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc358
-rw-r--r--chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc267
-rw-r--r--chromium/content/browser/media/capture/content_capture_device_browsertest_base.h129
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.cc5
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc8
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc16
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc11
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_uma_types.h2
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc19
-rw-r--r--chromium/content/browser/media/capture/fake_video_capture_stack.cc159
-rw-r--r--chromium/content/browser/media/capture/fake_video_capture_stack.h80
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device.cc173
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device.h33
-rw-r--r--chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc108
-rw-r--r--chromium/content/browser/media/capture/frame_test_util.cc93
-rw-r--r--chromium/content/browser/media/capture/frame_test_util.h64
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc373
-rw-r--r--chromium/content/browser/media/capture/lame_window_capturer_chromeos.h139
-rw-r--r--chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc11
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc5
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.h1
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc13
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc705
-rw-r--r--chromium/content/browser/media/cdm_registry_impl_unittest.cc61
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc74
-rw-r--r--chromium/content/browser/media/flinging_renderer.cc100
-rw-r--r--chromium/content/browser/media/flinging_renderer.h62
-rw-r--r--chromium/content/browser/media/flinging_renderer_unittest.cc84
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory.cc256
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory.h144
-rw-r--r--chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc711
-rw-r--r--chromium/content/browser/media/key_system_support_impl.cc10
-rw-r--r--chromium/content/browser/media/key_system_support_impl_unittest.cc42
-rw-r--r--chromium/content/browser/media/keyboard_mic_registration.cc31
-rw-r--r--chromium/content/browser/media/keyboard_mic_registration.h31
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc2
-rw-r--r--chromium/content/browser/media/media_devices_util.cc62
-rw-r--r--chromium/content/browser/media/media_devices_util.h33
-rw-r--r--chromium/content/browser/media/media_interface_proxy.cc36
-rw-r--r--chromium/content/browser/media/media_interface_proxy.h2
-rw-r--r--chromium/content/browser/media/media_internals.cc3
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc43
-rw-r--r--chromium/content/browser/media/media_source_browsertest.cc36
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc133
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h35
-rw-r--r--chromium/content/browser/media/session/audio_focus_manager_unittest.cc9
-rw-r--r--chromium/content/browser/media/session/media_session_android.cc8
-rw-r--r--chromium/content/browser/media/session/media_session_android.h3
-rw-r--r--chromium/content/browser/media/session/media_session_impl.cc4
-rw-r--r--chromium/content/browser/media/session/media_session_impl.h10
-rw-r--r--chromium/content/browser/media/session/media_session_impl_browsertest.cc28
-rw-r--r--chromium/content/browser/media/session/mock_media_session_observer.h2
-rw-r--r--chromium/content/browser/media/url_provision_fetcher.cc73
-rw-r--r--chromium/content/browser/media/url_provision_fetcher.h20
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl.cc3
-rw-r--r--chromium/content/browser/memory/memory_coordinator_impl_unittest.cc18
-rw-r--r--chromium/content/browser/message_port_provider.cc6
-rw-r--r--chromium/content/browser/net/accept_header_browsertest.cc2
-rw-r--r--chromium/content/browser/network_service_browsertest.cc41
-rw-r--r--chromium/content/browser/network_service_client.cc82
-rw-r--r--chromium/content/browser/network_service_client.h20
-rw-r--r--chromium/content/browser/network_service_instance.cc1
-rw-r--r--chromium/content/browser/network_service_restart_browsertest.cc317
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.cc23
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl.h1
-rw-r--r--chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc89
-rw-r--r--chromium/content/browser/notifications/notification_database.cc2
-rw-r--r--chromium/content/browser/notifications/notification_database_data.proto16
-rw-r--r--chromium/content/browser/notifications/notification_database_data_conversions.cc48
-rw-r--r--chromium/content/browser/notifications/notification_database_data_unittest.cc63
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc24
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.h11
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc14
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.cc326
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.h133
-rw-r--r--chromium/content/browser/oop_browsertest.cc4
-rw-r--r--chromium/content/browser/payments/payment_app_browsertest.cc30
-rw-r--r--chromium/content/browser/payments/payment_app_content_unittest_base.cc32
-rw-r--r--chromium/content/browser/payments/payment_app_content_unittest_base.h3
-rw-r--r--chromium/content/browser/payments/payment_app_context_impl.cc7
-rw-r--r--chromium/content/browser/payments/payment_app_database.cc16
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.cc4
-rw-r--r--chromium/content/browser/payments/payment_app_info_fetcher.h4
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl.cc150
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl.h5
-rw-r--r--chromium/content/browser/payments/payment_app_provider_impl_unittest.cc53
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.cc14
-rw-r--r--chromium/content/browser/payments/payment_instrument_icon_fetcher.h4
-rw-r--r--chromium/content/browser/permissions/permission_service_context.h3
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc109
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.h1
-rw-r--r--chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc55
-rw-r--r--chromium/content/browser/picture_in_picture/overlay_surface_embedder.h9
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc96
-rw-r--r--chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h20
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.cc6
-rw-r--r--chromium/content/browser/pointer_lock_browsertest.cc6
-rw-r--r--chromium/content/browser/power_monitor_browsertest.cc10
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc19
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.cc121
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.h48
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc173
-rw-r--r--chromium/content/browser/process_internals/BUILD.gn (renamed from chromium/content/public/common/zygote_features.gni)8
-rw-r--r--chromium/content/browser/process_internals/OWNERS2
-rw-r--r--chromium/content/browser/process_internals/process_internals.mojom17
-rw-r--r--chromium/content/browser/process_internals/process_internals_handler_impl.cc44
-rw-r--r--chromium/content/browser/process_internals/process_internals_handler_impl.h35
-rw-r--r--chromium/content/browser/process_internals/process_internals_ui.cc73
-rw-r--r--chromium/content/browser/process_internals/process_internals_ui.h46
-rw-r--r--chromium/content/browser/renderer_host/DEPS3
-rw-r--r--chromium/content/browser/renderer_host/OWNERS16
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h80
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm315
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.cc2
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl.h3
-rw-r--r--chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc11
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc349
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h17
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock.cc60
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock.h68
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc172
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc392
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h84
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc48
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h13
-rw-r--r--chromium/content/browser/renderer_host/direct_manipulation_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/embedded_frame_sink_impl.cc (renamed from chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc)34
-rw-r--r--chromium/content/browser/renderer_host/embedded_frame_sink_impl.h (renamed from chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h)42
-rw-r--r--chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.cc89
-rw-r--r--chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.h74
-rw-r--r--chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc (renamed from chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc)200
-rw-r--r--chromium/content/browser/renderer_host/file_utilities_host_impl.cc2
-rw-r--r--chromium/content/browser/renderer_host/file_utilities_host_impl.h6
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.cc24
-rw-r--r--chromium/content/browser/renderer_host/frame_connector_delegate.h44
-rw-r--r--chromium/content/browser/renderer_host/frame_sink_provider_impl.cc20
-rw-r--r--chromium/content/browser/renderer_host/frame_sink_provider_impl.h5
-rw-r--r--chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/fling_browsertest.cc75
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.cc121
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller.h35
-rw-r--r--chromium/content/browser/renderer_host/input/fling_controller_unittest.cc50
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler.cc91
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler.h49
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_mac.h27
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm36
-rw-r--r--chromium/content/browser/renderer_host/input/fling_scheduler_unittest.cc162
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.cc19
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.h10
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc29
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h3
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_client.h9
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_config_helper.cc23
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc44
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h36
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc67
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc706
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl.h290
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc407
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc2350
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc110
-rw-r--r--chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h63
-rw-r--r--chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.cc15
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h15
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_web.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc77
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h8
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc26
-rw-r--r--chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc59
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc130
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h14
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc322
-rw-r--r--chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc17
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target.h4
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc10
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc34
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h5
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc28
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h7
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.h9
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm90
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_driver.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h3
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc6
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc7
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller.cc114
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller.h42
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h40
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc415
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_browsertest.cc327
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.cc27
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter.h16
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc490
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc78
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h21
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_client.h5
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc41
-rw-r--r--chromium/content/browser/renderer_host/input/touch_input_browsertest.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc36
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h36
-rw-r--r--chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc67
-rw-r--r--chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h33
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc18
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.h5
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc18
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm21
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc6
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_delegate_impl.h2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc12
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.h6
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc266
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h203
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc529
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc11
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_stream_handle.h4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc28
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc140
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler.h23
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc11
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc390
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.h207
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc628
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener.cc206
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener.h129
-rw-r--r--chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc248
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc71
-rw-r--r--chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h6
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc75
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h19
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.cc307
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager.h48
-rw-r--r--chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc51
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc18
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h17
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc53
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc198
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h52
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc15
-rw-r--r--chromium/content/browser/renderer_host/media/mock_video_capture_provider.h2
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc237
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h149
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc176
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.cc140
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.h109
-rw-r--r--chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc337
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc272
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h109
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc368
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc199
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h84
-rw-r--r--chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc500
-rw-r--r--chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h2
-rw-r--r--chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h6
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc27
-rw-r--r--chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc26
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_browsertest.cc29
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc58
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc60
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h15
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h9
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc63
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc14
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h8
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h1
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc9
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_unittest.cc19
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc13
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc14
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm12
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc74
-rw-r--r--chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h67
-rw-r--r--chromium/content/browser/renderer_host/overscroll_configuration.cc11
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc77
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h31
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller_unittest.cc266
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h1
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc92
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.h4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h1
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc114
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc33
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h17
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h1
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc55
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc93
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc1
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc27
-rw-r--r--chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc14
-rw-r--r--chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h7
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc28
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h1
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc98
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc378
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h101
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc29
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h3
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc20
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.cc13
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.h15
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_browsertest.cc282
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h5
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc778
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h196
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc329
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h40
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc3
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h25
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm48
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h7
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc1270
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc320
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h76
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc262
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h74
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc1206
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc224
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h100
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc13
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc115
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h39
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc25
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc32
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h15
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm102
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc15
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h3
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h86
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm281
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm91
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.cc67
-rw-r--r--chromium/content/browser/renderer_host/render_widget_targeter.h17
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.cc3
-rw-r--r--chromium/content/browser/renderer_host/text_input_manager.h8
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc3
-rw-r--r--chromium/content/browser/renderer_interface_binders.cc35
-rw-r--r--chromium/content/browser/resources/BUILD.gn13
-rw-r--r--chromium/content/browser/resources/appcache/OWNERS3
-rw-r--r--chromium/content/browser/resources/gpu/browser_bridge.js4
-rw-r--r--chromium/content/browser/resources/gpu/info_view.html23
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js281
-rw-r--r--chromium/content/browser/resources/histograms/BUILD.gn18
-rw-r--r--chromium/content/browser/resources/histograms/OWNERS1
-rw-r--r--chromium/content/browser/resources/histograms/histograms_internals.html18
-rw-r--r--chromium/content/browser/resources/histograms/histograms_internals.js37
-rw-r--r--chromium/content/browser/resources/media/client_renderer.js14
-rw-r--r--chromium/content/browser/resources/media/main.js4
-rw-r--r--chromium/content/browser/resources/media/peer_connection_update_table.js2
-rw-r--r--chromium/content/browser/resources/media/ssrc_info_manager.js2
-rw-r--r--chromium/content/browser/resources/media/stats_table.js10
-rw-r--r--chromium/content/browser/resources/media/timeline_graph_view.js6
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.js2
-rw-r--r--chromium/content/browser/resources/process/process_internals.html16
-rw-r--r--chromium/content/browser/resources/process/process_internals.js33
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.js4
-rw-r--r--chromium/content/browser/sandbox_parameters_mac.mm3
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h2
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider.cc1
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider.h2
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider_unittest.cc18
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc5
-rw-r--r--chromium/content/browser/service_manager/common_browser_interfaces.cc2
-rw-r--r--chromium/content/browser/service_manager/service_manager_context.cc116
-rw-r--r--chromium/content/browser/service_worker/OWNERS1
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc213
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h35
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc214
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc131
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h57
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc27
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_info.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_info.h43
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc172
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h48
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core_observer.h23
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.cc30
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc43
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc195
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.cc13
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.h14
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc21
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h16
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc15
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc41
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h23
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc28
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc53
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle.cc62
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle.h49
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle_unittest.cc125
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.cc22
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.h20
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_loader.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_loader.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_reader.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_script_reader.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc313
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc37
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_handle_core.h13
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader.h10
-rw-r--r--chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc5
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.cc36
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.h20
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc176
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h82
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc69
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc21
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc23
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h11
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.cc44
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_object_host.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc85
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc70
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h12
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.cc18
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_loader_factory.h22
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc29
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_test_utils.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc136
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h23
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc67
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.h5
-rw-r--r--chromium/content/browser/shape_detection/shape_detection_browsertest.cc4
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.cc197
-rw-r--r--chromium/content/browser/shared_worker/mock_shared_worker.h132
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc151
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.h28
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host_unittest.cc263
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.cc14
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader.h33
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc10
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h13
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.cc130
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.h17
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc537
-rw-r--r--chromium/content/browser/shared_worker/worker_browsertest.cc29
-rw-r--r--chromium/content/browser/site_instance_impl.cc21
-rw-r--r--chromium/content/browser/site_instance_impl.h25
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc18
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc1004
-rw-r--r--chromium/content/browser/site_per_process_hit_test_browsertest.cc591
-rw-r--r--chromium/content/browser/speech/speech_recognition_browsertest.cc228
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.cc253
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.h103
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.cc4
-rw-r--r--chromium/content/browser/speech/speech_recognition_engine.h4
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.cc31
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.h6
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc145
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.h51
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.cc77
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc142
-rw-r--r--chromium/content/browser/startup_task_runner.cc1
-rw-r--r--chromium/content/browser/storage_partition_impl.cc148
-rw-r--r--chromium/content/browser/storage_partition_impl.h33
-rw-r--r--chromium/content/browser/storage_partition_impl_browsertest.cc80
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc16
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc72
-rw-r--r--chromium/content/browser/streams/stream.cc8
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_browsertest.cc29
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc39
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.h4
-rw-r--r--chromium/content/browser/tracing/cast_tracing_agent.cc19
-rw-r--r--chromium/content/browser/tracing/cast_tracing_agent.h4
-rw-r--r--chromium/content/browser/tracing/cros_tracing_agent.cc26
-rw-r--r--chromium/content/browser/tracing/cros_tracing_agent.h7
-rw-r--r--chromium/content/browser/tracing/etw_tracing_agent_win.cc17
-rw-r--r--chromium/content/browser/tracing/etw_tracing_agent_win.h2
-rw-r--r--chromium/content/browser/tracing/memory_instrumentation_browsertest.cc6
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.cc59
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.h15
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc16
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc54
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h11
-rw-r--r--chromium/content/browser/url_loader_factory_getter.cc51
-rw-r--r--chromium/content/browser/url_loader_factory_getter.h20
-rw-r--r--chromium/content/browser/utility_process_host.cc44
-rw-r--r--chromium/content/browser/utility_process_host.h2
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_browsertest.cc1
-rw-r--r--chromium/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc25
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc39
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc119
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h27
-rw-r--r--chromium/content/browser/web_contents/web_contents_delegate_unittest.cc51
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc361
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h73
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc620
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc125
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc46
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h25
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc5
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc96
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h8
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm29
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm6
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc63
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher.h15
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc11
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h5
-rw-r--r--chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc19
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.cc242
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain.h24
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc6
-rw-r--r--chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc217
-rw-r--r--chromium/content/browser/web_package/signed_exchange_consts.h9
-rw-r--r--chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc185
-rw-r--r--chromium/content/browser/web_package/signed_exchange_devtools_proxy.h86
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.cc178
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler.h10
-rw-r--r--chromium/content/browser/web_package/signed_exchange_handler_unittest.cc314
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header.cc129
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header.h14
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header_parser.cc61
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header_parser.h12
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc43
-rw-r--r--chromium/content/browser/web_package/signed_exchange_header_unittest.cc24
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.cc107
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier.h11
-rw-r--r--chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc282
-rw-r--r--chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.cc8
-rw-r--r--chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h1
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.cc47
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.h35
-rw-r--r--chromium/content/browser/web_package/web_package_loader.cc29
-rw-r--r--chromium/content/browser/web_package/web_package_loader.h17
-rw-r--r--chromium/content/browser/web_package/web_package_prefetch_handler.cc29
-rw-r--r--chromium/content/browser/web_package/web_package_prefetch_handler.h8
-rw-r--r--chromium/content/browser/web_package/web_package_request_handler.cc24
-rw-r--r--chromium/content/browser/web_package/web_package_request_handler.h7
-rw-r--r--chromium/content/browser/web_package/web_package_request_handler_browsertest.cc6
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.cc77
-rw-r--r--chromium/content/browser/webauth/authenticator_impl_unittest.cc454
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.cc37
-rw-r--r--chromium/content/browser/webauth/authenticator_type_converters.h9
-rw-r--r--chromium/content/browser/webauth/virtual_authenticator.cc3
-rw-r--r--chromium/content/browser/webauth/webauth_browsertest.cc7
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_browsertest.cc62
-rw-r--r--chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc4
-rw-r--r--chromium/content/browser/webrtc/webrtc_browsertest.cc14
-rw-r--r--chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc4
-rw-r--r--chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc247
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.cc25
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals.h5
-rw-r--r--chromium/content/browser/webrtc/webrtc_internals_unittest.cc1
-rw-r--r--chromium/content/browser/websockets/README.md2
-rw-r--r--chromium/content/browser/websockets/websocket_manager.cc40
-rw-r--r--chromium/content/browser/websockets/websocket_manager.h23
-rw-r--r--chromium/content/browser/websockets/websocket_manager_unittest.cc2
-rw-r--r--chromium/content/browser/webui/content_web_ui_controller_factory.cc18
-rw-r--r--chromium/content/browser/webui/url_data_manager.cc1
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc7
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc19
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h5
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_unittest.cc20
-rw-r--r--chromium/content/browser/webui/web_ui_impl.cc11
-rw-r--r--chromium/content/browser/webui/web_ui_impl.h1
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc2
-rw-r--r--chromium/content/browser/webui/web_ui_url_loader_factory.cc12
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.cc323
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.h103
-rw-r--r--chromium/content/browser/zygote_host/zygote_handle_linux.cc30
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.cc297
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.h71
-rw-r--r--chromium/content/child/BUILD.gn7
-rw-r--r--chromium/content/child/OWNERS11
-rw-r--r--chromium/content/child/assert_matching_enums.cc2
-rw-r--r--chromium/content/child/blink_platform_impl.cc21
-rw-r--r--chromium/content/child/blink_platform_impl.h6
-rw-r--r--chromium/content/child/child_histogram_fetcher_impl.cc2
-rw-r--r--chromium/content/child/child_process.cc4
-rw-r--r--chromium/content/child/child_process_sandbox_support_impl_linux.cc11
-rw-r--r--chromium/content/child/child_thread_impl.cc54
-rw-r--r--chromium/content/child/child_thread_impl.h16
-rw-r--r--chromium/content/child/runtime_features.cc102
-rw-r--r--chromium/content/child/webfallbackthemeengine_impl.cc215
-rw-r--r--chromium/content/child/webfallbackthemeengine_impl.h40
-rw-r--r--chromium/content/child/webthemeengine_impl_android.cc1
-rw-r--r--chromium/content/child/webthemeengine_impl_default.cc1
-rw-r--r--chromium/content/common/BUILD.gn45
-rw-r--r--chromium/content/common/DEPS6
-rw-r--r--chromium/content/common/OWNERS10
-rw-r--r--chromium/content/common/associated_interface_provider_impl.h1
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_messages.h15
-rw-r--r--chromium/content/common/cache_storage/OWNERS1
-rw-r--r--chromium/content/common/cache_storage/cache_storage.typemap19
-rw-r--r--chromium/content/common/cache_storage/cache_storage_mojom_traits.cc75
-rw-r--r--chromium/content/common/cache_storage/cache_storage_types.cc19
-rw-r--r--chromium/content/common/cache_storage/cache_storage_types.h52
-rw-r--r--chromium/content/common/child_process_host_impl.cc3
-rw-r--r--chromium/content/common/child_process_host_impl.h2
-rw-r--r--chromium/content/common/common_param_traits_unittest.cc22
-rw-r--r--chromium/content/common/common_sandbox_support_linux.cc28
-rw-r--r--chromium/content/common/content_message_generator.h12
-rw-r--r--chromium/content/common/content_param_traits.cc141
-rw-r--r--chromium/content/common/content_param_traits.h47
-rw-r--r--chromium/content/common/content_param_traits_macros.h8
-rw-r--r--chromium/content/common/content_paths.cc8
-rw-r--r--chromium/content/common/content_security_policy/content_security_policy.cc51
-rw-r--r--chromium/content/common/content_security_policy/content_security_policy.h4
-rw-r--r--chromium/content/common/content_security_policy/content_security_policy_unittest.cc207
-rw-r--r--chromium/content/common/content_security_policy/csp_context.cc39
-rw-r--r--chromium/content/common/content_security_policy/csp_context.h16
-rw-r--r--chromium/content/common/content_security_policy/csp_context_unittest.cc94
-rw-r--r--chromium/content/common/content_security_policy/csp_directive.cc4
-rw-r--r--chromium/content/common/content_security_policy/csp_directive.h1
-rw-r--r--chromium/content/common/content_security_policy/csp_source_list.cc26
-rw-r--r--chromium/content/common/content_security_policy/csp_source_list.h5
-rw-r--r--chromium/content/common/content_security_policy/csp_source_list_unittest.cc25
-rw-r--r--chromium/content/common/cursors/webcursor_aura.cc5
-rw-r--r--chromium/content/common/dom_storage/OWNERS3
-rw-r--r--chromium/content/common/external_ipc_dumper.cc3
-rw-r--r--chromium/content/common/file_utilities.mojom15
-rw-r--r--chromium/content/common/fileapi/OWNERS2
-rw-r--r--chromium/content/common/frame.mojom27
-rw-r--r--chromium/content/common/frame_messages.h149
-rw-r--r--chromium/content/common/frame_resize_params.cc19
-rw-r--r--chromium/content/common/frame_sink_provider.mojom9
-rw-r--r--chromium/content/common/frame_visual_properties.cc19
-rw-r--r--chromium/content/common/frame_visual_properties.h (renamed from chromium/content/common/frame_resize_params.h)26
-rw-r--r--chromium/content/common/input/event_with_latency_info.h8
-rw-r--r--chromium/content/common/input/event_with_latency_info_unittest.cc34
-rw-r--r--chromium/content/common/input/input_event_struct_traits.cc24
-rw-r--r--chromium/content/common/input/input_event_struct_traits.h4
-rw-r--r--chromium/content/common/input/input_handler.mojom12
-rw-r--r--chromium/content/common/input/input_param_traits_unittest.cc121
-rw-r--r--chromium/content/common/input/sync_compositor_messages.h82
-rw-r--r--chromium/content/common/input/synchronous_compositor.typemap1
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.cc33
-rw-r--r--chromium/content/common/input/touch_action_optional_struct_traits.cc2
-rw-r--r--chromium/content/common/input/web_touch_event_traits.cc8
-rw-r--r--chromium/content/common/input/web_touch_event_traits.h5
-rw-r--r--chromium/content/common/input_messages.h230
-rw-r--r--chromium/content/common/inter_process_time_ticks_converter.cc96
-rw-r--r--chromium/content/common/inter_process_time_ticks_converter.h185
-rw-r--r--chromium/content/common/inter_process_time_ticks_converter_unittest.cc265
-rw-r--r--chromium/content/common/manifest_share_target_util_unittest.cc266
-rw-r--r--chromium/content/common/media/audio_messages.h136
-rw-r--r--chromium/content/common/media/cdm_info.cc24
-rw-r--r--chromium/content/common/media/media_devices.cc13
-rw-r--r--chromium/content/common/media/media_devices.h10
-rw-r--r--chromium/content/common/media/media_player_delegate_messages.h38
-rw-r--r--chromium/content/common/media/media_stream_param_traits.h3
-rw-r--r--chromium/content/common/media/renderer_audio_input_stream_factory.mojom17
-rw-r--r--chromium/content/common/native_types.mojom2
-rw-r--r--chromium/content/common/native_types.typemap5
-rw-r--r--chromium/content/common/native_types_mac.typemap1
-rw-r--r--chromium/content/common/navigation_params.cc6
-rw-r--r--chromium/content/common/navigation_params.h14
-rw-r--r--chromium/content/common/navigation_subresource_loader_params.cc1
-rw-r--r--chromium/content/common/navigation_subresource_loader_params.h9
-rw-r--r--chromium/content/common/notifications/notification_struct_traits.cc2
-rw-r--r--chromium/content/common/origin_trials/OWNERS13
-rw-r--r--chromium/content/common/origin_trials/trial_policy_impl.cc44
-rw-r--r--chromium/content/common/origin_trials/trial_policy_impl.h42
-rw-r--r--chromium/content/common/origin_util.cc22
-rw-r--r--chromium/content/common/page_state_serialization_unittest.cc6
-rw-r--r--chromium/content/common/platform_notification_messages.h57
-rw-r--r--chromium/content/common/possibly_associated_interface_ptr.h1
-rw-r--r--chromium/content/common/possibly_associated_wrapper_shared_url_loader_factory.h18
-rw-r--r--chromium/content/common/presentation/presentation.typemap14
-rw-r--r--chromium/content/common/presentation/presentation_struct_traits.cc34
-rw-r--r--chromium/content/common/presentation/presentation_struct_traits.h156
-rw-r--r--chromium/content/common/render_frame_metadata.mojom27
-rw-r--r--chromium/content/common/render_frame_metadata_struct_traits.cc10
-rw-r--r--chromium/content/common/render_frame_metadata_struct_traits.h37
-rw-r--r--chromium/content/common/renderer.mojom31
-rw-r--r--chromium/content/common/resize_params.cc25
-rw-r--r--chromium/content/common/resource_messages.h2
-rw-r--r--chromium/content/common/resource_timing_info.h39
-rw-r--r--chromium/content/common/sandbox_init_mac.cc8
-rw-r--r--chromium/content/common/sandbox_policy_fuchsia.cc43
-rw-r--r--chromium/content/common/send_zygote_child_ping_linux.cc21
-rw-r--r--chromium/content/common/service_manager/service_manager_connection_impl.cc34
-rw-r--r--chromium/content/common/service_worker/BUILD.gn11
-rw-r--r--chromium/content/common/service_worker/dispatch_fetch_event_params.mojom20
-rw-r--r--chromium/content/common/service_worker/embedded_worker.mojom4
-rw-r--r--chromium/content/common/service_worker/service_worker_container.mojom2
-rw-r--r--chromium/content/common/service_worker/service_worker_event_dispatcher.mojom29
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.cc8
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.h13
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc28
-rw-r--r--chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h33
-rw-r--r--chromium/content/common/service_worker/service_worker_loader_helpers.cc43
-rw-r--r--chromium/content/common/service_worker/service_worker_loader_helpers.h10
-rw-r--r--chromium/content/common/service_worker/service_worker_messages.h22
-rw-r--r--chromium/content/common/service_worker/service_worker_provider.mojom11
-rw-r--r--chromium/content/common/service_worker/service_worker_types.cc57
-rw-r--r--chromium/content/common/service_worker/service_worker_types.h6
-rw-r--r--chromium/content/common/service_worker/service_worker_types.proto41
-rw-r--r--chromium/content/common/service_worker/service_worker_types_unittest.cc65
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.cc21
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.h5
-rw-r--r--chromium/content/common/single_request_url_loader_factory.cc5
-rw-r--r--chromium/content/common/single_request_url_loader_factory.h1
-rw-r--r--chromium/content/common/speech_recognition_messages.h121
-rw-r--r--chromium/content/common/speech_recognizer.mojom95
-rw-r--r--chromium/content/common/swapped_out_messages.cc6
-rw-r--r--chromium/content/common/throttling_url_loader.cc2
-rw-r--r--chromium/content/common/throttling_url_loader_unittest.cc12
-rw-r--r--chromium/content/common/typemaps.gni1
-rw-r--r--chromium/content/common/url_loader_factory_bundle.cc5
-rw-r--r--chromium/content/common/url_loader_factory_bundle.h2
-rw-r--r--chromium/content/common/url_schemes.cc17
-rw-r--r--chromium/content/common/url_schemes.h6
-rw-r--r--chromium/content/common/user_agent.cc48
-rw-r--r--chromium/content/common/view_messages.h68
-rw-r--r--chromium/content/common/visual_properties.cc18
-rw-r--r--chromium/content/common/visual_properties.h (renamed from chromium/content/common/resize_params.h)50
-rw-r--r--chromium/content/common/wrapper_shared_url_loader_factory.cc26
-rw-r--r--chromium/content/common/wrapper_shared_url_loader_factory.h88
-rw-r--r--chromium/content/common/zygote_commands_linux.h54
-rw-r--r--chromium/content/content_resources.grd5
-rw-r--r--chromium/content/gpu/BUILD.gn4
-rw-r--r--chromium/content/gpu/gpu_child_thread.cc3
-rw-r--r--chromium/content/gpu/gpu_main.cc8
-rw-r--r--chromium/content/gpu/gpu_service_factory.cc6
-rw-r--r--chromium/content/gpu/gpu_service_factory.h3
-rw-r--r--chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc10
-rw-r--r--chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h2
-rw-r--r--chromium/content/ppapi_plugin/ppapi_plugin_main.cc2
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.cc4
-rw-r--r--chromium/content/public/android/BUILD.gn57
-rw-r--r--chromium/content/public/android/OWNERS1
-rw-r--r--chromium/content/public/app/content_main_delegate.cc7
-rw-r--r--chromium/content/public/app/content_main_delegate.h13
-rw-r--r--chromium/content/public/app/mojo/content_browser_manifest.json289
-rw-r--r--chromium/content/public/app/mojo/content_gpu_manifest.json24
-rw-r--r--chromium/content/public/app/mojo/content_packaged_services_manifest.json2
-rw-r--r--chromium/content/public/app/mojo/content_plugin_manifest.json14
-rw-r--r--chromium/content/public/app/mojo/content_renderer_manifest.json57
-rw-r--r--chromium/content/public/app/mojo/content_utility_manifest.json20
-rw-r--r--chromium/content/public/browser/BUILD.gn26
-rw-r--r--chromium/content/public/browser/DEPS1
-rw-r--r--chromium/content/public/browser/android/compositor_client.h3
-rw-r--r--chromium/content/public/browser/android/content_view_layer_renderer.h13
-rw-r--r--chromium/content/public/browser/audio_service_info.cc26
-rw-r--r--chromium/content/public/browser/audio_service_info.h20
-rw-r--r--chromium/content/public/browser/background_fetch_delegate.h26
-rw-r--r--chromium/content/public/browser/background_fetch_description.cc31
-rw-r--r--chromium/content/public/browser/background_fetch_description.h45
-rw-r--r--chromium/content/public/browser/background_tracing_manager.h17
-rw-r--r--chromium/content/public/browser/browser_child_process_host.h11
-rw-r--r--chromium/content/public/browser/browser_child_process_observer.h18
-rw-r--r--chromium/content/public/browser/browser_context.h18
-rw-r--r--chromium/content/public/browser/browser_main_parts.cc4
-rw-r--r--chromium/content/public/browser/browser_main_parts.h2
-rw-r--r--chromium/content/public/browser/browsing_data_filter_builder.h25
-rw-r--r--chromium/content/public/browser/browsing_data_remover.h16
-rw-r--r--chromium/content/public/browser/child_process_termination_info.h39
-rw-r--r--chromium/content/public/browser/content_browser_client.cc28
-rw-r--r--chromium/content/public/browser/content_browser_client.h56
-rw-r--r--chromium/content/public/browser/desktop_capture.cc7
-rw-r--r--chromium/content/public/browser/devtools_agent_host.h4
-rw-r--r--chromium/content/public/browser/download_manager.h15
-rw-r--r--chromium/content/public/browser/download_manager_delegate.cc4
-rw-r--r--chromium/content/public/browser/download_manager_delegate.h6
-rw-r--r--chromium/content/public/browser/file_url_loader.h1
-rw-r--r--chromium/content/public/browser/gpu_client.h31
-rw-r--r--chromium/content/public/browser/gpu_data_manager.h4
-rw-r--r--chromium/content/public/browser/gpu_utils.cc59
-rw-r--r--chromium/content/public/browser/keyboard_event_processing_result.h3
-rw-r--r--chromium/content/public/browser/manifest_icon_selector.h7
-rw-r--r--chromium/content/public/browser/native_web_keyboard_event.h5
-rw-r--r--chromium/content/public/browser/navigation_controller.h10
-rw-r--r--chromium/content/public/browser/navigation_handle.cc1
-rw-r--r--chromium/content/public/browser/navigation_handle.h16
-rw-r--r--chromium/content/public/browser/network_service_instance.h3
-rw-r--r--chromium/content/public/browser/notification_database_data.h45
-rw-r--r--chromium/content/public/browser/notification_event_dispatcher.h3
-rw-r--r--chromium/content/public/browser/notification_types.h15
-rw-r--r--chromium/content/public/browser/overlay_window.h13
-rw-r--r--chromium/content/public/browser/overscroll_configuration.h3
-rw-r--r--chromium/content/public/browser/page_navigator.h7
-rw-r--r--chromium/content/public/browser/payment_app_provider.h11
-rw-r--r--chromium/content/public/browser/picture_in_picture_window_controller.h12
-rw-r--r--chromium/content/public/browser/presentation_service_delegate.h25
-rw-r--r--chromium/content/public/browser/provision_fetcher_factory.h6
-rw-r--r--chromium/content/public/browser/provision_fetcher_impl.cc13
-rw-r--r--chromium/content/public/browser/provision_fetcher_impl.h11
-rw-r--r--chromium/content/public/browser/render_frame_host.h9
-rw-r--r--chromium/content/public/browser/render_frame_metadata_provider.h7
-rw-r--r--chromium/content/public/browser/render_process_host.h58
-rw-r--r--chromium/content/public/browser/render_process_host_observer.h8
-rw-r--r--chromium/content/public/browser/render_widget_host.h22
-rw-r--r--chromium/content/public/browser/render_widget_host_observer.h33
-rw-r--r--chromium/content/public/browser/render_widget_host_view.h38
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host_delegate.cc8
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host_delegate.h6
-rw-r--r--chromium/content/public/browser/resource_hints.h12
-rw-r--r--chromium/content/public/browser/resource_request_info.h8
-rw-r--r--chromium/content/public/browser/screen_orientation_delegate.h2
-rw-r--r--chromium/content/public/browser/service_worker_context_observer.h6
-rw-r--r--chromium/content/public/browser/site_isolation_policy.cc9
-rw-r--r--chromium/content/public/browser/site_isolation_policy.h3
-rw-r--r--chromium/content/public/browser/speech_recognition_manager.h6
-rw-r--r--chromium/content/public/browser/speech_recognition_session_config.h7
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.cc3
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.h10
-rw-r--r--chromium/content/public/browser/storage_partition.h36
-rw-r--r--chromium/content/public/browser/trace_uploader.h7
-rw-r--r--chromium/content/public/browser/url_loader_request_interceptor.h48
-rw-r--r--chromium/content/public/browser/web_contents.cc2
-rw-r--r--chromium/content/public/browser/web_contents.h78
-rw-r--r--chromium/content/public/browser/web_contents_delegate.cc7
-rw-r--r--chromium/content/public/browser/web_contents_delegate.h25
-rw-r--r--chromium/content/public/browser/web_contents_observer.h8
-rw-r--r--chromium/content/public/browser/web_ui_message_handler.h2
-rw-r--r--chromium/content/public/browser/webrtc_log.h4
-rw-r--r--chromium/content/public/browser/zygote_host_linux.h42
-rw-r--r--chromium/content/public/common/BUILD.gn53
-rw-r--r--chromium/content/public/common/browser_side_navigation_policy.cc15
-rw-r--r--chromium/content/public/common/browser_side_navigation_policy.h2
-rw-r--r--chromium/content/public/common/cdm_info.h30
-rw-r--r--chromium/content/public/common/common_param_traits_macros.h6
-rw-r--r--chromium/content/public/common/common_sandbox_support_linux.h16
-rw-r--r--chromium/content/public/common/content_client.cc2
-rw-r--r--chromium/content/public/common/content_client.h12
-rw-r--r--chromium/content/public/common/content_descriptors.h9
-rw-r--r--chromium/content/public/common/content_features.cc155
-rw-r--r--chromium/content/public/common/content_features.h35
-rw-r--r--chromium/content/public/common/content_switches.cc32
-rw-r--r--chromium/content/public/common/content_switches.h14
-rw-r--r--chromium/content/public/common/load_timing_info.mojom33
-rw-r--r--chromium/content/public/common/load_timing_info.typemap14
-rw-r--r--chromium/content/public/common/load_timing_info_struct_traits.cc40
-rw-r--r--chromium/content/public/common/load_timing_info_struct_traits.h109
-rw-r--r--chromium/content/public/common/manifest.cc60
-rw-r--r--chromium/content/public/common/manifest.h177
-rw-r--r--chromium/content/public/common/manifest.typemap27
-rw-r--r--chromium/content/public/common/manifest_share_target_util.cc127
-rw-r--r--chromium/content/public/common/manifest_share_target_util.h37
-rw-r--r--chromium/content/public/common/manifest_struct_traits.cc153
-rw-r--r--chromium/content/public/common/manifest_struct_traits.h16
-rw-r--r--chromium/content/public/common/manifest_util.h4
-rw-r--r--chromium/content/public/common/media_stream_request.cc32
-rw-r--r--chromium/content/public/common/media_stream_request.h13
-rw-r--r--chromium/content/public/common/mojo_channel_switches.cc13
-rw-r--r--chromium/content/public/common/mojo_channel_switches.h16
-rw-r--r--chromium/content/public/common/origin_trial_policy.cc22
-rw-r--r--chromium/content/public/common/origin_trial_policy.h25
-rw-r--r--chromium/content/public/common/page_state.h14
-rw-r--r--chromium/content/public/common/platform_notification_data.h4
-rw-r--r--chromium/content/public/common/presentation_info.cc24
-rw-r--r--chromium/content/public/common/presentation_info.h69
-rw-r--r--chromium/content/public/common/resource_load_info.mojom50
-rw-r--r--chromium/content/public/common/result_codes.h7
-rw-r--r--chromium/content/public/common/sandboxed_process_launcher_delegate.cc8
-rw-r--r--chromium/content/public/common/sandboxed_process_launcher_delegate.h6
-rw-r--r--chromium/content/public/common/send_zygote_child_ping_linux.h18
-rw-r--r--chromium/content/public/common/speech_recognition_error.h2
-rw-r--r--chromium/content/public/common/speech_recognition_error.mojom34
-rw-r--r--chromium/content/public/common/speech_recognition_error.typemap14
-rw-r--r--chromium/content/public/common/speech_recognition_error_struct_traits.cc22
-rw-r--r--chromium/content/public/common/speech_recognition_error_struct_traits.h152
-rw-r--r--chromium/content/public/common/speech_recognition_grammar.h35
-rw-r--r--chromium/content/public/common/speech_recognition_grammar.mojom12
-rw-r--r--chromium/content/public/common/speech_recognition_result.mojom29
-rw-r--r--chromium/content/public/common/speech_recognition_result.typemap16
-rw-r--r--chromium/content/public/common/speech_recognition_result_struct_traits.cc29
-rw-r--r--chromium/content/public/common/speech_recognition_result_struct_traits.h47
-rw-r--r--chromium/content/public/common/stop_find_action.h15
-rw-r--r--chromium/content/public/common/typemaps.gni4
-rw-r--r--chromium/content/public/common/url_constants.cc2
-rw-r--r--chromium/content/public/common/url_constants.h2
-rw-r--r--chromium/content/public/common/weak_wrapper_shared_url_loader_factory.cc47
-rw-r--r--chromium/content/public/common/weak_wrapper_shared_url_loader_factory.h47
-rw-r--r--chromium/content/public/common/web_preferences.cc2
-rw-r--r--chromium/content/public/common/web_preferences.h8
-rw-r--r--chromium/content/public/common/zygote_fork_delegate_linux.h87
-rw-r--r--chromium/content/public/common/zygote_handle.h45
-rw-r--r--chromium/content/public/renderer/BUILD.gn36
-rw-r--r--chromium/content/public/renderer/content_renderer_client.cc19
-rw-r--r--chromium/content/public/renderer/content_renderer_client.h23
-rw-r--r--chromium/content/public/renderer/key_system_support.cc9
-rw-r--r--chromium/content/public/renderer/key_system_support.h10
-rw-r--r--chromium/content/public/renderer/media_stream_audio_renderer.h2
-rw-r--r--chromium/content/public/renderer/media_stream_renderer_factory.h4
-rw-r--r--chromium/content/public/renderer/media_stream_utils.cc2
-rw-r--r--chromium/content/public/renderer/pepper_plugin_instance.h17
-rw-r--r--chromium/content/public/renderer/render_thread.h10
-rw-r--r--chromium/content/public/renderer/render_view.h6
-rw-r--r--chromium/content/public/renderer/request_peer.h1
-rw-r--r--chromium/content/public/renderer/url_loader_throttle_provider.h3
-rw-r--r--chromium/content/public/renderer/websocket_handshake_throttle_provider.h38
-rw-r--r--chromium/content/public/test/android/BUILD.gn24
-rw-r--r--chromium/content/renderer/BUILD.gn582
-rw-r--r--chromium/content/renderer/DEPS1
-rw-r--r--chromium/content/renderer/OWNERS4
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc128
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.h5
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.cc52
-rw-r--r--chromium/content/renderer/accessibility/render_accessibility_impl.cc8
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_filter.cc208
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_filter.h112
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy.cc1
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.cc171
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.h84
-rw-r--r--chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc6
-rw-r--r--chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h3
-rw-r--r--chromium/content/renderer/appcache/OWNERS3
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.cc154
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.h36
-rw-r--r--chromium/content/renderer/browser_render_view_browsertest.cc97
-rw-r--r--chromium/content/renderer/cache_storage/OWNERS7
-rw-r--r--chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc481
-rw-r--r--chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h103
-rw-r--r--chromium/content/renderer/categorized_worker_pool.cc42
-rw-r--r--chromium/content/renderer/categorized_worker_pool.h15
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper.cc30
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper_unittest.cc11
-rw-r--r--chromium/content/renderer/child_frame_compositor.h17
-rw-r--r--chromium/content/renderer/content_security_policy_util.cc17
-rw-r--r--chromium/content/renderer/content_security_policy_util.h7
-rw-r--r--chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc2
-rw-r--r--chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc59
-rw-r--r--chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h12
-rw-r--r--chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h7
-rw-r--r--chromium/content/renderer/dom_serializer_browsertest.cc5
-rw-r--r--chromium/content/renderer/dom_storage/DEPS3
-rw-r--r--chromium/content/renderer/dom_storage/OWNERS5
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_area.cc214
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_area.h10
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc6
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_areas.cc35
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc25
-rw-r--r--chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h2
-rw-r--r--chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc2
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc1
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.cc3
-rw-r--r--chromium/content/renderer/fileapi/OWNERS1
-rw-r--r--chromium/content/renderer/fileapi/webfilewriter_base_unittest.cc1
-rw-r--r--chromium/content/renderer/gpu/actions_parser.cc8
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.cc66
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.h9
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.cc159
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.h21
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor_delegate.h3
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor_unittest.cc2
-rw-r--r--chromium/content/renderer/idle_user_detector.cc22
-rw-r--r--chromium/content/renderer/idle_user_detector.h27
-rw-r--r--chromium/content/renderer/image_downloader/image_downloader_base.cc2
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc8
-rw-r--r--chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h1
-rw-r--r--chromium/content/renderer/indexed_db/mock_webidbcallbacks.h2
-rw-r--r--chromium/content/renderer/indexed_db/webidbcursor_impl.cc1
-rw-r--r--chromium/content/renderer/input/frame_input_handler_impl.cc3
-rw-r--r--chromium/content/renderer/input/frame_input_handler_impl.h3
-rw-r--r--chromium/content/renderer/input/input_event_filter.cc317
-rw-r--r--chromium/content/renderer/input/input_event_filter.h148
-rw-r--r--chromium/content/renderer/input/input_event_filter_ipc_names.cc25
-rw-r--r--chromium/content/renderer/input/input_event_filter_unittest.cc573
-rw-r--r--chromium/content/renderer/input/input_event_prediction.cc160
-rw-r--r--chromium/content/renderer/input/input_event_prediction.h66
-rw-r--r--chromium/content/renderer/input/input_event_prediction_unittest.cc213
-rw-r--r--chromium/content/renderer/input/input_handler_manager.cc301
-rw-r--r--chromium/content/renderer/input/input_handler_manager.h175
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.cc121
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.h80
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.cc69
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.h15
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue_unittest.cc58
-rw-r--r--chromium/content/renderer/input/main_thread_input_event_filter.cc40
-rw-r--r--chromium/content/renderer/input/main_thread_input_event_filter.h43
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.cc49
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.h7
-rw-r--r--chromium/content/renderer/input/scoped_web_input_event_with_latency_info.cc4
-rw-r--r--chromium/content/renderer/input/widget_input_handler_impl.h1
-rw-r--r--chromium/content/renderer/input/widget_input_handler_manager.cc48
-rw-r--r--chromium/content/renderer/input/widget_input_handler_manager.h1
-rw-r--r--chromium/content/renderer/installedapp/related_apps_fetcher.cc8
-rw-r--r--chromium/content/renderer/installedapp/related_apps_fetcher.h4
-rw-r--r--chromium/content/renderer/layout_test_dependencies.h4
-rw-r--r--chromium/content/renderer/loader/child_url_loader_factory_bundle.cc68
-rw-r--r--chromium/content/renderer/loader/child_url_loader_factory_bundle.h7
-rw-r--r--chromium/content/renderer/loader/navigation_response_override_parameters.cc17
-rw-r--r--chromium/content/renderer/loader/navigation_response_override_parameters.h33
-rw-r--r--chromium/content/renderer/loader/request_extra_data.cc2
-rw-r--r--chromium/content/renderer/loader/request_extra_data.h33
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher.cc236
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher.h37
-rw-r--r--chromium/content/renderer/loader/resource_dispatcher_unittest.cc88
-rw-r--r--chromium/content/renderer/loader/shared_memory_data_consumer_handle.cc1
-rw-r--r--chromium/content/renderer/loader/sync_load_context.cc122
-rw-r--r--chromium/content/renderer/loader/sync_load_context.h14
-rw-r--r--chromium/content/renderer/loader/sync_load_response.h5
-rw-r--r--chromium/content/renderer/loader/test_request_peer.cc3
-rw-r--r--chromium/content/renderer/loader/test_request_peer.h5
-rw-r--r--chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h1
-rw-r--r--chromium/content/renderer/loader/url_loader_client_impl.h8
-rw-r--r--chromium/content/renderer/loader/url_loader_client_impl_unittest.cc9
-rw-r--r--chromium/content/renderer/loader/url_response_body_consumer_unittest.cc10
-rw-r--r--chromium/content/renderer/loader/web_data_consumer_handle_impl.cc6
-rw-r--r--chromium/content/renderer/loader/web_data_consumer_handle_impl.h1
-rw-r--r--chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc40
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl.cc139
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl.h26
-rw-r--r--chromium/content/renderer/loader/web_url_loader_impl_unittest.cc48
-rw-r--r--chromium/content/renderer/loader/web_url_request_util.cc44
-rw-r--r--chromium/content/renderer/loader/web_url_request_util.h14
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.cc8
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.h8
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.cc60
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.h38
-rw-r--r--chromium/content/renderer/manifest/manifest_parser_unittest.cc603
-rw-r--r--chromium/content/renderer/manifest/manifest_uma_util.cc4
-rw-r--r--chromium/content/renderer/manifest/manifest_uma_util.h8
-rw-r--r--chromium/content/renderer/media/audio_device_factory.cc70
-rw-r--r--chromium/content/renderer/media/audio_device_factory.h39
-rw-r--r--chromium/content/renderer/media/audio_input_ipc_factory.cc44
-rw-r--r--chromium/content/renderer/media/audio_input_ipc_factory.h10
-rw-r--r--chromium/content/renderer/media/audio_input_message_filter.cc230
-rw-r--r--chromium/content/renderer/media/audio_input_message_filter.h101
-rw-r--r--chromium/content/renderer/media/audio_message_filter.cc232
-rw-r--r--chromium/content/renderer/media/audio_message_filter.h108
-rw-r--r--chromium/content/renderer/media/audio_message_filter_unittest.cc194
-rw-r--r--chromium/content/renderer/media/audio_output_ipc_factory.cc21
-rw-r--r--chromium/content/renderer/media/audio_output_ipc_factory.h20
-rw-r--r--chromium/content/renderer/media/audio_output_ipc_factory_unittest.cc22
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.cc34
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.h40
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc224
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache.h23
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc145
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache_impl.h23
-rw-r--r--chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc107
-rw-r--r--chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc75
-rw-r--r--chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h43
-rw-r--r--chromium/content/renderer/media/media_factory.cc105
-rw-r--r--chromium/content/renderer/media/media_factory.h2
-rw-r--r--chromium/content/renderer/media/media_interface_factory.cc14
-rw-r--r--chromium/content/renderer/media/media_interface_factory.h2
-rw-r--r--chromium/content/renderer/media/mock_audio_device_factory.cc3
-rw-r--r--chromium/content/renderer/media/mock_audio_device_factory.h41
-rw-r--r--chromium/content/renderer/media/mojo_audio_input_ipc.cc26
-rw-r--r--chromium/content/renderer/media/mojo_audio_input_ipc.h16
-rw-r--r--chromium/content/renderer/media/mojo_audio_input_ipc_unittest.cc74
-rw-r--r--chromium/content/renderer/media/mojo_audio_output_ipc.cc86
-rw-r--r--chromium/content/renderer/media/mojo_audio_output_ipc.h34
-rw-r--r--chromium/content/renderer/media/mojo_audio_output_ipc_unittest.cc115
-rw-r--r--chromium/content/renderer/media/render_media_log.h1
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.cc36
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.h20
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc28
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc92
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.h49
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc1
-rw-r--r--chromium/content/renderer/media/stream/apply_constraints_processor.cc2
-rw-r--r--chromium/content/renderer/media/stream/apply_constraints_processor.h1
-rw-r--r--chromium/content/renderer/media/stream/external_media_stream_audio_source.cc3
-rw-r--r--chromium/content/renderer/media/stream/local_media_stream_audio_source.cc7
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor.cc3
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc1
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor_options.h4
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc20
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_source.cc4
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_source.h3
-rw-r--r--chromium/content/renderer/media/stream/media_stream_audio_unittest.cc6
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util.cc11
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util.h10
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc208
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h9
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc442
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc29
-rw-r--r--chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc106
-rw-r--r--chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc8
-rw-r--r--chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h7
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_capturer_source_unittest.cc2
-rw-r--r--chromium/content/renderer/media/stream/media_stream_video_source.h5
-rw-r--r--chromium/content/renderer/media/stream/mock_media_stream_registry.cc2
-rw-r--r--chromium/content/renderer/media/stream/mock_media_stream_video_source.cc1
-rw-r--r--chromium/content/renderer/media/stream/mock_media_stream_video_source.h2
-rw-r--r--chromium/content/renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h2
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source.cc68
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source.h12
-rw-r--r--chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc2
-rw-r--r--chromium/content/renderer/media/stream/secure_display_link_tracker.h1
-rw-r--r--chromium/content/renderer/media/stream/track_audio_renderer.cc19
-rw-r--r--chromium/content/renderer/media/stream/track_audio_renderer.h9
-rw-r--r--chromium/content/renderer/media/stream/user_media_client_impl.h1
-rw-r--r--chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc6
-rw-r--r--chromium/content/renderer/media/stream/user_media_processor.cc58
-rw-r--r--chromium/content/renderer/media/stream/webaudio_media_stream_source.cc2
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms.cc113
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms.h27
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc63
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h30
-rw-r--r--chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc134
-rw-r--r--chromium/content/renderer/media/video_capture_impl.cc155
-rw-r--r--chromium/content/renderer/media/video_capture_impl.h19
-rw-r--r--chromium/content/renderer/media/video_capture_impl_manager_unittest.cc4
-rw-r--r--chromium/content/renderer/media/video_capture_impl_unittest.cc11
-rw-r--r--chromium/content/renderer/media/webrtc/audio_codec_factory.cc10
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc25
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc1
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc8
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc5
-rw-r--r--chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h6
-rw-r--r--chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h7
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h6
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_remote_audio_source.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_tracker.cc19
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_certificate_generator.h1
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_data_channel_handler.cc1
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_error.cc61
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_error.h21
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc28
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h32
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc8
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_parameters.cc158
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_parameters.h33
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_parameters_unittest.cc165
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h1
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc88
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_rtp_sender.h6
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder.cc48
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder.h6
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc18
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_encoder.cc58
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_encoder.h5
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc11
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h7
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc26
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_renderer.h5
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc64
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h1
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc1
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc95
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.cc8
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc4
-rw-r--r--chromium/content/renderer/media/webrtc_logging_noop.cc11
-rw-r--r--chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc41
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc2
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc4
-rw-r--r--chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc11
-rw-r--r--chromium/content/renderer/media_recorder/audio_track_opus_encoder.cc6
-rw-r--r--chromium/content/renderer/media_recorder/audio_track_pcm_encoder.cc2
-rw-r--r--chromium/content/renderer/media_recorder/audio_track_recorder_unittest.cc35
-rw-r--r--chromium/content/renderer/media_recorder/h264_encoder.h1
-rw-r--r--chromium/content/renderer/media_recorder/media_recorder_handler.h1
-rw-r--r--chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc3
-rw-r--r--chromium/content/renderer/media_recorder/vea_encoder.cc14
-rw-r--r--chromium/content/renderer/media_recorder/vea_encoder.h7
-rw-r--r--chromium/content/renderer/media_recorder/vpx_encoder.h1
-rw-r--r--chromium/content/renderer/mojo/blink_interface_provider_impl.h4
-rw-r--r--chromium/content/renderer/mojo/blink_interface_registry_impl.h1
-rw-r--r--chromium/content/renderer/mus/BUILD.gn1
-rw-r--r--chromium/content/renderer/mus/OWNERS2
-rw-r--r--chromium/content/renderer/mus/mus_embedded_frame.cc2
-rw-r--r--chromium/content/renderer/mus/renderer_window_tree_client.cc8
-rw-r--r--chromium/content/renderer/mus/renderer_window_tree_client.h5
-rw-r--r--chromium/content/renderer/notifications/notification_data_conversions.cc60
-rw-r--r--chromium/content/renderer/notifications/notification_data_conversions.h4
-rw-r--r--chromium/content/renderer/notifications/notification_data_conversions_unittest.cc139
-rw-r--r--chromium/content/renderer/notifications/notification_dispatcher.cc57
-rw-r--r--chromium/content/renderer/notifications/notification_dispatcher.h48
-rw-r--r--chromium/content/renderer/notifications/notification_manager.cc221
-rw-r--r--chromium/content/renderer/notifications/notification_manager.h84
-rw-r--r--chromium/content/renderer/origin_trials/OWNERS1
-rw-r--r--chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc33
-rw-r--r--chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h49
-rw-r--r--chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc4
-rw-r--r--chromium/content/renderer/pepper/event_conversion.cc31
-rw-r--r--chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc18
-rw-r--r--chromium/content/renderer/pepper/fake_pepper_plugin_instance.h8
-rw-r--r--chromium/content/renderer/pepper/fullscreen_container.h7
-rw-r--r--chromium/content/renderer/pepper/pepper_audio_output_host.cc6
-rw-r--r--chromium/content/renderer/pepper/pepper_compositor_host.cc37
-rw-r--r--chromium/content/renderer/pepper/pepper_compositor_host.h10
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.cc3
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc1
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.cc28
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc35
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_input.cc26
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_input.h4
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output.cc9
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output.h3
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc19
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc160
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.h19
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.h2
-rw-r--r--chromium/content/renderer/pepper/pepper_url_request_unittest.cc6
-rw-r--r--chromium/content/renderer/pepper/pepper_video_encoder_host.h4
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.cc72
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.h5
-rw-r--r--chromium/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc13
-rw-r--r--chromium/content/renderer/pepper/plugin_module.cc1
-rw-r--r--chromium/content/renderer/pepper/ppb_flash_message_loop_impl.cc1
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc3
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.h4
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.cc1
-rw-r--r--chromium/content/renderer/pepper/resource_converter.cc3
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.cc10
-rw-r--r--chromium/content/renderer/presentation/OWNERS1
-rw-r--r--chromium/content/renderer/presentation/presentation_dispatcher.cc46
-rw-r--r--chromium/content/renderer/presentation/presentation_dispatcher.h67
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_client.cc4
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_client.h6
-rw-r--r--chromium/content/renderer/render_frame_impl.cc677
-rw-r--r--chromium/content/renderer/render_frame_impl.h95
-rw-r--r--chromium/content/renderer/render_frame_impl_browsertest.cc69
-rw-r--r--chromium/content/renderer/render_frame_proxy.cc180
-rw-r--r--chromium/content/renderer/render_frame_proxy.h48
-rw-r--r--chromium/content/renderer/render_process_impl.cc8
-rw-r--r--chromium/content/renderer/render_thread_impl.cc312
-rw-r--r--chromium/content/renderer/render_thread_impl.h50
-rw-r--r--chromium/content/renderer/render_thread_impl_browsertest.cc23
-rw-r--r--chromium/content/renderer/render_view_browsertest.cc49
-rw-r--r--chromium/content/renderer/render_view_browsertest_mac.mm9
-rw-r--r--chromium/content/renderer/render_view_impl.cc210
-rw-r--r--chromium/content/renderer/render_view_impl.h28
-rw-r--r--chromium/content/renderer/render_view_impl_android.cc1
-rw-r--r--chromium/content/renderer/render_widget.cc410
-rw-r--r--chromium/content/renderer/render_widget.h64
-rw-r--r--chromium/content/renderer/render_widget_browsertest.cc90
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.cc18
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.h11
-rw-r--r--chromium/content/renderer/render_widget_unittest.cc144
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.cc199
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.h37
-rw-r--r--chromium/content/renderer/renderer_main.cc17
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_linux.cc2
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_mac.mm13
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_win.cc5
-rw-r--r--chromium/content/renderer/resizing_mode_selector.cc12
-rw-r--r--chromium/content/renderer/resizing_mode_selector.h5
-rw-r--r--chromium/content/renderer/service_worker/controller_service_worker_connector.cc48
-rw-r--r--chromium/content/renderer/service_worker/controller_service_worker_connector.h32
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc27
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h14
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.cc302
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.h39
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc205
-rw-r--r--chromium/content/renderer/service_worker/service_worker_dispatcher.cc158
-rw-r--r--chromium/content/renderer/service_worker/service_worker_dispatcher.h104
-rw-r--r--chromium/content/renderer/service_worker/service_worker_dispatcher_unittest.cc117
-rw-r--r--chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc25
-rw-r--r--chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h9
-rw-r--r--chromium/content/renderer/service_worker/service_worker_message_filter.cc3
-rw-r--r--chromium/content/renderer/service_worker/service_worker_message_filter.h3
-rw-r--r--chromium/content/renderer/service_worker/service_worker_network_provider.cc46
-rw-r--r--chromium/content/renderer/service_worker/service_worker_network_provider.h18
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_context.cc150
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_context.h56
-rw-r--r--chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc234
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader.cc80
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader.h18
-rw-r--r--chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc17
-rw-r--r--chromium/content/renderer/service_worker/service_worker_type_converters.cc7
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_impl.cc72
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_impl.h96
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h1
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc18
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_provider_impl.h3
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc376
-rw-r--r--chromium/content/renderer/service_worker/web_service_worker_registration_impl.h225
-rw-r--r--chromium/content/renderer/service_worker/worker_fetch_context_impl.cc180
-rw-r--r--chromium/content/renderer/service_worker/worker_fetch_context_impl.h88
-rw-r--r--chromium/content/renderer/shared_memory_seqlock_reader.cc62
-rw-r--r--chromium/content/renderer/shared_memory_seqlock_reader.h78
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc43
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.cc242
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.h85
-rw-r--r--chromium/content/renderer/visual_state_browsertest.cc4
-rw-r--r--chromium/content/renderer/web_ui_extension.cc1
-rw-r--r--chromium/content/renderer/webfileutilities_impl.cc55
-rw-r--r--chromium/content/renderer/webfileutilities_impl.h36
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.cc5
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.h1
-rw-r--r--chromium/content/renderer/worker_thread_message_filter.cc1
-rw-r--r--chromium/content/shell/BUILD.gn70
-rw-r--r--chromium/content/shell/android/BUILD.gn22
-rw-r--r--chromium/content/shell/common/layout_test.mojom5
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_messages.h5
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_switches.cc11
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_switches.h3
-rw-r--r--chromium/content/shell/common/leak_detection_result.h19
-rw-r--r--chromium/content/shell/common/shell_content_client.cc6
-rw-r--r--chromium/content/shell/common/shell_content_client.h3
-rw-r--r--chromium/content/shell/common/shell_messages.h15
-rw-r--r--chromium/content/shell/common/shell_origin_trial_policy.cc13
-rw-r--r--chromium/content/shell/common/shell_origin_trial_policy.h8
-rw-r--r--chromium/content/shell/common/shell_switches.cc4
-rw-r--r--chromium/content/shell/common/shell_switches.h4
-rw-r--r--chromium/content/shell/test_runner/BUILD.gn46
-rw-r--r--chromium/content/test/BUILD.gn390
-rw-r--r--chromium/content/utility/BUILD.gn3
-rw-r--r--chromium/content/utility/DEPS1
-rw-r--r--chromium/content/utility/utility_service_factory.cc6
-rw-r--r--chromium/content/zygote/OWNERS8
-rw-r--r--chromium/content/zygote/zygote_browsertest.cc4
-rw-r--r--chromium/content/zygote/zygote_linux.cc668
-rw-r--r--chromium/content/zygote/zygote_linux.h152
-rw-r--r--chromium/content/zygote/zygote_main.h22
-rw-r--r--chromium/content/zygote/zygote_main_linux.cc244
1916 files changed, 69713 insertions, 54808 deletions
diff --git a/chromium/content/BUILD.gn b/chromium/content/BUILD.gn
index 7c567481db6..09962146a24 100644
--- a/chromium/content/BUILD.gn
+++ b/chromium/content/BUILD.gn
@@ -91,11 +91,8 @@ if (is_component_build) {
sources = [
"//services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc",
"common/sandbox_init_linux.cc",
- "common/send_zygote_child_ping_linux.cc",
"public/common/content_switches.cc",
"public/common/content_switches.h",
- "public/common/mojo_channel_switches.cc",
- "public/common/mojo_channel_switches.h",
]
set_sources_assignment_filter(sources_assignment_filter)
deps = [
@@ -127,6 +124,7 @@ grit("resources") {
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
deps = [
+ "//content/browser/process_internals:mojo_bindings_js",
"//content/public/app:browser_manifest",
"//content/public/app:gpu_manifest",
"//content/public/app:packaged_services_manifest",
diff --git a/chromium/content/DEPS b/chromium/content/DEPS
index c11b886fbd6..1ec0d628f39 100644
--- a/chromium/content/DEPS
+++ b/chromium/content/DEPS
@@ -10,11 +10,8 @@ include_rules = [
"+content/public/common",
"+content/public/test",
"+content/test",
-
"+blink/public/resources/grit",
-
"+cc",
- "-cc/blink",
"-components",
# Content can depend on components that are:
@@ -35,7 +32,6 @@ include_rules = [
"+dbus",
"+gpu",
"+media",
- "+mojo/common",
"+mojo/edk/embedder",
"+mojo/edk/js",
"+mojo/message_pump",
@@ -46,6 +42,8 @@ include_rules = [
"+sandbox",
"+services/proxy_resolver/public/mojom",
"+services/service_manager/embedder",
+ "+services/service_manager/sandbox",
+ "+services/service_manager/zygote",
"+skia",
# In general, content/ should not rely on google_apis, since URLs
diff --git a/chromium/content/OWNERS b/chromium/content/OWNERS
index 53d2f572750..239b4e6552c 100644
--- a/chromium/content/OWNERS
+++ b/chromium/content/OWNERS
@@ -28,4 +28,10 @@ per-file *.sb=rsesek@chromium.org
# For Fuchsia-specific changes:
per-file *_fuchsia*=file://build/fuchsia/OWNERS
+# For Mac-specific changes:
+per-file *_mac*=ellyjones@chromium.org
+per-file *_mac*=tapted@chromium.org
+per-file *.mm=ellyjones@chromium.org
+per-file *.mm=tapted@chromium.org
+
# COMPONENT: Internals>Core
diff --git a/chromium/content/app/BUILD.gn b/chromium/content/app/BUILD.gn
index 8d8f2826384..518bcc9435d 100644
--- a/chromium/content/app/BUILD.gn
+++ b/chromium/content/app/BUILD.gn
@@ -71,10 +71,10 @@ template("implement_content_app") {
content_app_deps += [ "//content/ppapi_plugin:ppapi_plugin_sources" ]
}
- # Compile content_main_runner.cc in a separate target to exempt from GN
- # header checking without exempting any other source file. This file includes
- # headers of all process types and varies significantly per platform in
- # between browser and child. Otherwise it would require many "nogncheck"
+ # Compile content_main_runner_impl.[h, cc] in a separate target to exempt from
+ # GN header checking without exempting any other source file. These files
+ # includes headers of all process types and varies significantly per platform
+ # in between browser and child. Otherwise it would require many "nogncheck"
# annotations that would both be useless and add noise.
#
# This will generate :content_main_runner_both, :content_main_runner_browser,
@@ -84,7 +84,8 @@ template("implement_content_app") {
check_includes = false
sources = [
- "content_main_runner.cc",
+ "content_main_runner_impl.cc",
+ "content_main_runner_impl.h",
]
configs += extra_configs
diff --git a/chromium/content/app/content_main_runner.cc b/chromium/content/app/content_main_runner_impl.cc
index d1e6e7d28d4..83e8990edf1 100644
--- a/chromium/content/app/content_main_runner.cc
+++ b/chromium/content/app/content_main_runner_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/public/app/content_main_runner.h"
+#include "content/app/content_main_runner_impl.h"
#include <stddef.h>
#include <stdlib.h>
@@ -34,17 +34,16 @@
#include "base/process/memory.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
#include "components/tracing/common/trace_startup.h"
#include "content/app/mojo/mojo_init.h"
+#include "content/browser/browser_process_sub_thread.h"
#include "content/common/url_schemes.h"
-#include "content/public/app/content_main.h"
#include "content/public/app/content_main_delegate.h"
-#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_descriptor_keys.h"
#include "content/public/common/content_features.h"
@@ -52,13 +51,15 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/sandbox_init.h"
-#include "content/public/common/zygote_buildflags.h"
#include "gin/v8_initializer.h"
#include "media/base/media.h"
#include "media/media_buildflags.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/service_manager/embedder/switches.h"
#include "services/service_manager/sandbox/sandbox_type.h"
+#include "services/service_manager/sandbox/switches.h"
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
@@ -69,15 +70,13 @@
#include <cstring>
#include "base/trace_event/trace_event_etw_export_win.h"
-#include "sandbox/win/src/sandbox_types.h"
#include "ui/display/win/dpi.h"
#elif defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/power_monitor/power_monitor_device_source.h"
#include "content/browser/mach_broker_mac.h"
#endif // OS_WIN
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <signal.h>
#include "base/file_descriptor_store.h"
@@ -85,26 +84,27 @@
#include "content/public/common/content_descriptors.h"
#if !defined(OS_MACOSX)
-#include "content/public/common/zygote_fork_delegate_linux.h"
+#include "services/service_manager/zygote/common/zygote_fork_delegate_linux.h"
#endif
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
-#include "content/zygote/zygote_main.h"
#include "sandbox/linux/services/libc_interceptor.h"
+#include "services/service_manager/zygote/zygote_main.h"
#endif
-#endif // OS_POSIX
+#endif // OS_POSIX || OS_FUCHSIA
#if defined(OS_LINUX)
#include "base/native_library.h"
#include "base/rand_util.h"
#include "content/common/font_config_ipc_linux.h"
-#include "content/public/common/common_sandbox_support_linux.h"
+#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/blink/public/platform/web_font_render_style.h"
#include "third_party/boringssl/src/include/openssl/crypto.h"
#include "third_party/boringssl/src/include/openssl/rand.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include "third_party/skia/include/ports/SkFontMgr.h"
#include "third_party/skia/include/ports/SkFontMgr_android.h"
+#include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck
#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/common/pepper_plugin_list.h"
@@ -116,9 +116,6 @@
#include "content/public/common/content_client.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck
-#endif
#endif // OS_LINUX
#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
@@ -143,11 +140,11 @@
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
#include "content/browser/sandbox_host_linux.h"
-#include "content/browser/zygote_host/zygote_communication_linux.h"
-#include "content/browser/zygote_host/zygote_host_impl_linux.h"
-#include "content/public/common/common_sandbox_support_linux.h"
-#include "content/public/common/zygote_handle.h"
#include "media/base/media_switches.h"
+#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
+#include "services/service_manager/zygote/common/zygote_handle.h"
+#include "services/service_manager/zygote/host/zygote_communication_linux.h"
+#include "services/service_manager/zygote/host/zygote_host_impl_linux.h"
#endif
namespace content {
@@ -189,16 +186,17 @@ void InitializeFieldTrialAndFeatureList(
// browser process.
field_trial_list->reset(new base::FieldTrialList(nullptr));
- // Ensure any field trials in browser are reflected into the child
- // process.
-#if defined(OS_POSIX)
+// Ensure any field trials in browser are reflected into the child
+// process.
+#if defined(OS_WIN)
+ base::FieldTrialList::CreateTrialsFromCommandLine(
+ command_line, switches::kFieldTrialHandle, -1);
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
// On POSIX systems that use the zygote, we get the trials from a shared
// memory segment backed by an fd instead of the command line.
base::FieldTrialList::CreateTrialsFromCommandLine(
- command_line, switches::kFieldTrialHandle, kFieldTrialDescriptor);
-#else
- base::FieldTrialList::CreateTrialsFromCommandLine(
- command_line, switches::kFieldTrialHandle, -1);
+ command_line, switches::kFieldTrialHandle,
+ service_manager::kFieldTrialDescriptor);
#endif
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
@@ -278,7 +276,6 @@ pid_t LaunchZygoteHelper(base::CommandLine* cmd_line,
// to the zygote/renderers.
static const char* const kForwardSwitches[] = {
switches::kAndroidFontsPath, switches::kClearKeyCdmPathForTesting,
- switches::kEnableHeapProfiling,
switches::kEnableLogging, // Support, e.g., --enable-logging=stderr.
// Need to tell the zygote that it is headless so that we don't try to use
// the wrong type of main delegate.
@@ -290,7 +287,7 @@ pid_t LaunchZygoteHelper(base::CommandLine* cmd_line,
switches::kVModule,
};
cmd_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
- kForwardSwitches, arraysize(kForwardSwitches));
+ kForwardSwitches, base::size(kForwardSwitches));
GetContentClient()->browser()->AppendExtraCommandLineSwitches(cmd_line, -1);
@@ -298,9 +295,10 @@ pid_t LaunchZygoteHelper(base::CommandLine* cmd_line,
// sandboxed processes to talk to it.
base::FileHandleMappingVector additional_remapped_fds;
additional_remapped_fds.emplace_back(
- SandboxHostLinux::GetInstance()->GetChildSocket(), GetSandboxFD());
+ SandboxHostLinux::GetInstance()->GetChildSocket(),
+ service_manager::GetSandboxFD());
- return ZygoteHostImpl::GetInstance()->LaunchZygote(
+ return service_manager::ZygoteHostImpl::GetInstance()->LaunchZygote(
cmd_line, control_fd, std::move(additional_remapped_fds));
}
@@ -314,20 +312,20 @@ void InitializeZygoteSandboxForBrowserProcess(
SandboxHostLinux::GetInstance()->Init();
if (parsed_command_line.HasSwitch(switches::kNoZygote) &&
- !parsed_command_line.HasSwitch(switches::kNoSandbox)) {
+ !parsed_command_line.HasSwitch(service_manager::switches::kNoSandbox)) {
LOG(ERROR) << "--no-sandbox should be used together with --no--zygote";
exit(EXIT_FAILURE);
}
// Tickle the zygote host so it forks now.
- ZygoteHostImpl::GetInstance()->Init(parsed_command_line);
- ZygoteHandle generic_zygote =
- CreateGenericZygote(base::BindOnce(LaunchZygoteHelper));
+ service_manager::ZygoteHostImpl::GetInstance()->Init(parsed_command_line);
+ service_manager::ZygoteHandle generic_zygote =
+ service_manager::CreateGenericZygote(base::BindOnce(LaunchZygoteHelper));
// TODO(kerrnel): Investigate doing this without the ZygoteHostImpl as a
// proxy. It is currently done this way due to concerns about race
// conditions.
- ZygoteHostImpl::GetInstance()->SetRendererSandboxStatus(
+ service_manager::ZygoteHostImpl::GetInstance()->SetRendererSandboxStatus(
generic_zygote->GetSandboxStatus());
}
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
@@ -391,11 +389,10 @@ void PreSandboxInit() {
// Ensure access to the library CDMs before the sandbox is turned on.
PreloadLibraryCdms();
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
InitializeWebRtcModule();
-#endif
- SkFontConfigInterface::SetGlobal(new FontConfigIPC(GetSandboxFD()))->unref();
+ SkFontConfigInterface::SetGlobal(
+ sk_make_sp<FontConfigIPC>(service_manager::GetSandboxFD()));
// Set the android SkFontMgr for blink. We need to ensure this is done
// before the sandbox is initialized to allow the font manager to access
@@ -435,6 +432,12 @@ void PreSandboxInit() {
#endif // OS_LINUX
+bool IsRootProcess() {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ return command_line.GetSwitchValueASCII(switches::kProcessType).empty();
+}
+
} // namespace
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
@@ -517,7 +520,8 @@ int RunZygote(ContentMainDelegate* delegate) {
#endif
};
- std::vector<std::unique_ptr<ZygoteForkDelegate>> zygote_fork_delegates;
+ std::vector<std::unique_ptr<service_manager::ZygoteForkDelegate>>
+ zygote_fork_delegates;
if (delegate) {
delegate->ZygoteStarting(&zygote_fork_delegates);
media::InitializeMediaLibrary();
@@ -528,8 +532,9 @@ int RunZygote(ContentMainDelegate* delegate) {
#endif
// This function call can return multiple times, once per fork().
- if (!ZygoteMain(std::move(zygote_fork_delegates)))
+ if (!service_manager::ZygoteMain(std::move(zygote_fork_delegates))) {
return 1;
+ }
if (delegate)
delegate->ZygoteForked();
@@ -557,7 +562,7 @@ int RunZygote(ContentMainDelegate* delegate) {
if (sandbox_type == service_manager::SANDBOX_TYPE_PROFILING)
sandbox::SetUseLocaltimeOverride(false);
- for (size_t i = 0; i < arraysize(kMainFunctions); ++i) {
+ for (size_t i = 0; i < base::size(kMainFunctions); ++i) {
if (process_type == kMainFunctions[i].name)
return kMainFunctions[i].function(main_params);
}
@@ -580,64 +585,75 @@ static void RegisterMainThreadFactories() {
#else
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kSingleProcess)) {
- LOG(FATAL) <<
- "--single-process is not supported in chrome multiple dll browser.";
+ LOG(FATAL)
+ << "--single-process is not supported in chrome multiple dll browser.";
}
if (command_line.HasSwitch(switches::kInProcessGPU)) {
- LOG(FATAL) <<
- "--in-process-gpu is not supported in chrome multiple dll browser.";
+ LOG(FATAL)
+ << "--in-process-gpu is not supported in chrome multiple dll browser.";
}
#endif // !CHROME_MULTIPLE_DLL_BROWSER && !CHROME_MULTIPLE_DLL_CHILD
}
-// Run the FooMain() for a given process type.
-// If |process_type| is empty, runs BrowserMain().
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+// Run the main function for browser process.
// Returns the exit code for this process.
-int RunNamedProcessTypeMain(
- const std::string& process_type,
+int RunBrowserProcessMain(
const MainFunctionParams& main_function_params,
- ContentMainDelegate* delegate) {
- static const MainFunction kMainFunctions[] = {
-#if !defined(CHROME_MULTIPLE_DLL_CHILD)
- { "", BrowserMain },
+ ContentMainDelegate* delegate,
+ std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
+ if (delegate) {
+ int exit_code = delegate->RunProcess("", main_function_params);
+#if defined(OS_ANDROID)
+ // In Android's browser process, the negative exit code doesn't mean the
+ // default behavior should be used as the UI message loop is managed by
+ // the Java and the browser process's default behavior is always
+ // overridden.
+ return exit_code;
#endif
+ if (exit_code >= 0)
+ return exit_code;
+ }
+ // GetServiceManagerTaskRunnerForEmbedderProcess() needs to be invoked before
+ // Run() for the browser process.
+ DCHECK(service_manager_thread);
+ return BrowserMain(main_function_params, std::move(service_manager_thread));
+}
+#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
+
+// Run the FooMain() for a given process type.
+// Returns the exit code for this process.
+int RunOtherNamedProcessTypeMain(const std::string& process_type,
+ const MainFunctionParams& main_function_params,
+ ContentMainDelegate* delegate) {
#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
+ static const MainFunction kMainFunctions[] = {
#if BUILDFLAG(ENABLE_PLUGINS)
- { switches::kPpapiPluginProcess, PpapiPluginMain },
- { switches::kPpapiBrokerProcess, PpapiBrokerMain },
+ {switches::kPpapiPluginProcess, PpapiPluginMain},
+ {switches::kPpapiBrokerProcess, PpapiBrokerMain},
#endif // ENABLE_PLUGINS
- { switches::kUtilityProcess, UtilityMain },
- { switches::kRendererProcess, RendererMain },
- { switches::kGpuProcess, GpuMain },
-#endif // !CHROME_MULTIPLE_DLL_BROWSER
+ {switches::kUtilityProcess, UtilityMain},
+ {switches::kRendererProcess, RendererMain},
+ {switches::kGpuProcess, GpuMain},
};
- RegisterMainThreadFactories();
-
- for (size_t i = 0; i < arraysize(kMainFunctions); ++i) {
+ for (size_t i = 0; i < base::size(kMainFunctions); ++i) {
if (process_type == kMainFunctions[i].name) {
if (delegate) {
- int exit_code = delegate->RunProcess(process_type,
- main_function_params);
-#if defined(OS_ANDROID)
- // In Android's browser process, the negative exit code doesn't mean the
- // default behavior should be used as the UI message loop is managed by
- // the Java and the browser process's default behavior is always
- // overridden.
- if (process_type.empty())
- return exit_code;
-#endif
+ int exit_code =
+ delegate->RunProcess(process_type, main_function_params);
if (exit_code >= 0)
return exit_code;
}
return kMainFunctions[i].function(main_function_params);
}
}
+#endif // !CHROME_MULTIPLE_DLL_BROWSER
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
// Zygote startup is special -- see RunZygote comments above
// for why we don't use ZygoteMain directly.
- if (process_type == switches::kZygoteProcess)
+ if (process_type == service_manager::switches::kZygoteProcess)
return RunZygote(delegate);
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
@@ -649,106 +665,118 @@ int RunNamedProcessTypeMain(
return 1;
}
-class ContentMainRunnerImpl : public ContentMainRunner {
- public:
- ContentMainRunnerImpl() {
+// static
+ContentMainRunnerImpl* ContentMainRunnerImpl::Create() {
+ return new ContentMainRunnerImpl();
+}
+
+ContentMainRunnerImpl::ContentMainRunnerImpl() {
#if defined(OS_WIN)
- memset(&sandbox_info_, 0, sizeof(sandbox_info_));
+ memset(&sandbox_info_, 0, sizeof(sandbox_info_));
#endif
- }
+}
- ~ContentMainRunnerImpl() override {
- if (is_initialized_ && !is_shutdown_)
- Shutdown();
- }
+ContentMainRunnerImpl::~ContentMainRunnerImpl() {
+ if (is_initialized_ && !is_shutdown_)
+ Shutdown();
+}
- int TerminateForFatalInitializationError() {
- if (delegate_)
- return delegate_->TerminateForFatalInitializationError();
+int ContentMainRunnerImpl::TerminateForFatalInitializationError() {
+ if (delegate_)
+ return delegate_->TerminateForFatalInitializationError();
- CHECK(false);
- return 0;
- }
+ CHECK(false);
+ return 0;
+}
- int Initialize(const ContentMainParams& params) override {
- ui_task_ = params.ui_task;
- created_main_parts_closure_ = params.created_main_parts_closure;
+int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) {
+ ui_task_ = params.ui_task;
+ created_main_parts_closure_ = params.created_main_parts_closure;
#if defined(OS_WIN)
- sandbox_info_ = *params.sandbox_info;
+ sandbox_info_ = *params.sandbox_info;
#else // !OS_WIN
#if defined(OS_MACOSX)
- autorelease_pool_ = params.autorelease_pool;
+ autorelease_pool_ = params.autorelease_pool;
#endif // defined(OS_MACOSX)
#if defined(OS_ANDROID)
- // See note at the initialization of ExitManager, below; basically,
- // only Android builds have the ctor/dtor handlers set up to use
- // TRACE_EVENT right away.
- TRACE_EVENT0("startup,benchmark,rail", "ContentMainRunnerImpl::Initialize");
+ // See note at the initialization of ExitManager, below; basically,
+ // only Android builds have the ctor/dtor handlers set up to use
+ // TRACE_EVENT right away.
+ TRACE_EVENT0("startup,benchmark,rail", "ContentMainRunnerImpl::Initialize");
#endif // OS_ANDROID
- base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
- ALLOW_UNUSED_LOCAL(g_fds);
+ base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
+ ALLOW_UNUSED_LOCAL(g_fds);
// On Android, the ipc_fd is passed through the Java service.
#if !defined(OS_ANDROID)
- g_fds->Set(kMojoIPCChannel,
- kMojoIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
+ g_fds->Set(service_manager::kMojoIPCChannel,
+ service_manager::kMojoIPCChannel +
+ base::GlobalDescriptors::kBaseDescriptor);
- g_fds->Set(
- kFieldTrialDescriptor,
- kFieldTrialDescriptor + base::GlobalDescriptors::kBaseDescriptor);
+ g_fds->Set(service_manager::kFieldTrialDescriptor,
+ service_manager::kFieldTrialDescriptor +
+ base::GlobalDescriptors::kBaseDescriptor);
#endif // !OS_ANDROID
#if defined(OS_LINUX) || defined(OS_OPENBSD)
- g_fds->Set(kCrashDumpSignal,
- kCrashDumpSignal + base::GlobalDescriptors::kBaseDescriptor);
+ g_fds->Set(service_manager::kCrashDumpSignal,
+ service_manager::kCrashDumpSignal +
+ base::GlobalDescriptors::kBaseDescriptor);
#endif // OS_LINUX || OS_OPENBSD
#endif // !OS_WIN
- is_initialized_ = true;
- delegate_ = params.delegate;
+ is_initialized_ = true;
+ delegate_ = params.delegate;
- // The exit manager is in charge of calling the dtors of singleton objects.
- // On Android, AtExitManager is set up when library is loaded.
- // A consequence of this is that you can't use the ctor/dtor-based
- // TRACE_EVENT methods on Linux or iOS builds till after we set this up.
+// The exit manager is in charge of calling the dtors of singleton objects.
+// On Android, AtExitManager is set up when library is loaded.
+// A consequence of this is that you can't use the ctor/dtor-based
+// TRACE_EVENT methods on Linux or iOS builds till after we set this up.
#if !defined(OS_ANDROID)
- if (!ui_task_) {
- // When running browser tests, don't create a second AtExitManager as that
- // interfers with shutdown when objects created before ContentMain is
- // called are destructed when it returns.
- exit_manager_.reset(new base::AtExitManager);
- }
+ if (!ui_task_) {
+ // When running browser tests, don't create a second AtExitManager as that
+ // interfers with shutdown when objects created before ContentMain is
+ // called are destructed when it returns.
+ exit_manager_.reset(new base::AtExitManager);
+ }
#endif // !OS_ANDROID
- int exit_code = 0;
- if (delegate_ && delegate_->BasicStartupComplete(&exit_code))
- return exit_code;
-
- completed_basic_startup_ = true;
+ int exit_code = 0;
+ if (delegate_ && delegate_->BasicStartupComplete(&exit_code))
+ return exit_code;
+ completed_basic_startup_ = true;
+
+ // We will need to use data from resources.pak in later cl, so load the file
+ // now.
+ if (IsRootProcess()) {
+ ui::DataPack* data_pack = delegate_->LoadServiceManifestDataPack();
+ // TODO(ranj): Read manifest from this data pack.
+ ignore_result(data_pack);
+ }
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- std::string process_type =
- command_line.GetSwitchValueASCII(switches::kProcessType);
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ std::string process_type =
+ command_line.GetSwitchValueASCII(switches::kProcessType);
#if defined(OS_WIN)
- if (command_line.HasSwitch(switches::kDeviceScaleFactor)) {
- std::string scale_factor_string = command_line.GetSwitchValueASCII(
- switches::kDeviceScaleFactor);
- double scale_factor = 0;
- if (base::StringToDouble(scale_factor_string, &scale_factor))
- display::win::SetDefaultDeviceScaleFactor(scale_factor);
- }
+ if (command_line.HasSwitch(switches::kDeviceScaleFactor)) {
+ std::string scale_factor_string =
+ command_line.GetSwitchValueASCII(switches::kDeviceScaleFactor);
+ double scale_factor = 0;
+ if (base::StringToDouble(scale_factor_string, &scale_factor))
+ display::win::SetDefaultDeviceScaleFactor(scale_factor);
+ }
#endif
- if (!GetContentClient())
- SetContentClient(&empty_content_client_);
- ContentClientInitializer::Set(process_type, delegate_);
+ if (!GetContentClient())
+ SetContentClient(&empty_content_client_);
+ ContentClientInitializer::Set(process_type, delegate_);
#if !defined(OS_ANDROID)
// Enable startup tracing asap to avoid early TRACE_EVENT calls being
@@ -757,7 +785,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
//
// Startup tracing flags are not (and should not) passed to Zygote
// processes. We will enable tracing when forked, if needed.
- if (process_type != switches::kZygoteProcess)
+ if (process_type != service_manager::switches::kZygoteProcess)
tracing::EnableStartupTracingIfNeeded();
#endif // !OS_ANDROID
@@ -778,7 +806,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
// We need to allocate the IO Ports before the Sandbox is initialized or
// the first instance of PowerMonitor is created.
// It's important not to allocate the ports for processes which don't
- // register with the power monitor - see crbug.com/88867.
+ // register with the power monitor - see https://crbug.com/88867.
if (process_type.empty() ||
(delegate_ &&
delegate_->ProcessRegistersWithSystemProcess(process_type))) {
@@ -797,7 +825,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
// unexpected absence has security implications.
CHECK(base::allocator::IsAllocatorInitialized());
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
if (!process_type.empty()) {
// When you hit Ctrl-C in a terminal running the browser
// process, a SIGINT is delivered to the entire process group.
@@ -836,6 +864,13 @@ class ContentMainRunnerImpl : public ContentMainRunner {
InitializeV8IfNeeded(command_line, process_type);
+ blink::TrialTokenValidator::SetOriginTrialPolicyGetter(
+ base::BindRepeating([]() -> blink::OriginTrialPolicy* {
+ if (auto* client = GetContentClient())
+ return client->GetOriginTrialPolicy();
+ return nullptr;
+ }));
+
#if !defined(OFFICIAL_BUILD)
#if defined(OS_WIN)
bool should_enable_stack_dump = !process_type.empty();
@@ -894,92 +929,82 @@ class ContentMainRunnerImpl : public ContentMainRunner {
// Return -1 to indicate no early termination.
return -1;
- }
+}
- int Run() override {
- DCHECK(is_initialized_);
- DCHECK(!is_shutdown_);
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- std::string process_type =
- command_line.GetSwitchValueASCII(switches::kProcessType);
+int ContentMainRunnerImpl::Run() {
+ DCHECK(is_initialized_);
+ DCHECK(!is_shutdown_);
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ std::string process_type =
+ command_line.GetSwitchValueASCII(switches::kProcessType);
- // Run this logic on all child processes. Zygotes will run this at a later
- // point in time when the command line has been updated.
- std::unique_ptr<base::FieldTrialList> field_trial_list;
- if (!process_type.empty() && process_type != switches::kZygoteProcess)
- InitializeFieldTrialAndFeatureList(&field_trial_list);
+ // Run this logic on all child processes. Zygotes will run this at a later
+ // point in time when the command line has been updated.
+ std::unique_ptr<base::FieldTrialList> field_trial_list;
+ if (!process_type.empty() &&
+ process_type != service_manager::switches::kZygoteProcess)
+ InitializeFieldTrialAndFeatureList(&field_trial_list);
- MainFunctionParams main_params(command_line);
- main_params.ui_task = ui_task_;
- main_params.created_main_parts_closure = created_main_parts_closure_;
+ MainFunctionParams main_params(command_line);
+ main_params.ui_task = ui_task_;
+ main_params.created_main_parts_closure = created_main_parts_closure_;
#if defined(OS_WIN)
- main_params.sandbox_info = &sandbox_info_;
+ main_params.sandbox_info = &sandbox_info_;
#elif defined(OS_MACOSX)
- main_params.autorelease_pool = autorelease_pool_;
+ main_params.autorelease_pool = autorelease_pool_;
#endif
- return RunNamedProcessTypeMain(process_type, main_params, delegate_);
+ RegisterMainThreadFactories();
+
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+ // The thread used to start the ServiceManager is handed-off to
+ // BrowserMain() which may elect to promote it (e.g. to BrowserThread::IO).
+ if (process_type.empty()) {
+ return RunBrowserProcessMain(main_params, delegate_,
+ std::move(service_manager_thread_));
}
+#endif
- void Shutdown() override {
- DCHECK(is_initialized_);
- DCHECK(!is_shutdown_);
+ return RunOtherNamedProcessTypeMain(process_type, main_params, delegate_);
+}
- if (completed_basic_startup_ && delegate_) {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- std::string process_type =
- command_line.GetSwitchValueASCII(switches::kProcessType);
+void ContentMainRunnerImpl::Shutdown() {
+ DCHECK(is_initialized_);
+ DCHECK(!is_shutdown_);
- delegate_->ProcessExiting(process_type);
- }
+ if (completed_basic_startup_ && delegate_) {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ std::string process_type =
+ command_line.GetSwitchValueASCII(switches::kProcessType);
+
+ delegate_->ProcessExiting(process_type);
+ }
#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
- _CrtDumpMemoryLeaks();
+ _CrtDumpMemoryLeaks();
#endif // _CRTDBG_MAP_ALLOC
#endif // OS_WIN
- exit_manager_.reset(nullptr);
-
- delegate_ = nullptr;
- is_shutdown_ = true;
- }
-
- private:
- // True if the runner has been initialized.
- bool is_initialized_ = false;
-
- // True if the runner has been shut down.
- bool is_shutdown_ = false;
+ exit_manager_.reset(nullptr);
- // True if basic startup was completed.
- bool completed_basic_startup_ = false;
-
- // Used if the embedder doesn't set one.
- ContentClient empty_content_client_;
-
- // The delegate will outlive this object.
- ContentMainDelegate* delegate_ = nullptr;
-
- std::unique_ptr<base::AtExitManager> exit_manager_;
-#if defined(OS_WIN)
- sandbox::SandboxInterfaceInfo sandbox_info_;
-#elif defined(OS_MACOSX)
- base::mac::ScopedNSAutoreleasePool* autorelease_pool_ = nullptr;
-#endif
-
- base::Closure* ui_task_ = nullptr;
-
- CreatedMainPartsClosure* created_main_parts_closure_ = nullptr;
+ delegate_ = nullptr;
+ is_shutdown_ = true;
+}
- DISALLOW_COPY_AND_ASSIGN(ContentMainRunnerImpl);
-};
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+scoped_refptr<base::SingleThreadTaskRunner>
+ContentMainRunnerImpl::GetServiceManagerTaskRunnerForEmbedderProcess() {
+ service_manager_thread_ = BrowserProcessSubThread::CreateIOThread();
+ return service_manager_thread_->task_runner();
+}
+#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
// static
ContentMainRunner* ContentMainRunner::Create() {
- return new ContentMainRunnerImpl();
+ return ContentMainRunnerImpl::Create();
}
} // namespace content
diff --git a/chromium/content/app/content_main_runner_impl.h b/chromium/content/app/content_main_runner_impl.h
new file mode 100644
index 00000000000..7fab6f739f7
--- /dev/null
+++ b/chromium/content/app/content_main_runner_impl.h
@@ -0,0 +1,89 @@
+// 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_APP_CONTENT_MAIN_RUNNER_IMPL_H_
+#define CONTENT_APP_CONTENT_MAIN_RUNNER_IMPL_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "build/build_config.h"
+#include "content/public/app/content_main.h"
+#include "content/public/app/content_main_runner.h"
+#include "content/public/common/content_client.h"
+
+#if defined(OS_WIN)
+#include "sandbox/win/src/sandbox_types.h"
+#elif defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif // OS_WIN
+
+namespace base {
+class AtExitManager;
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace content {
+class BrowserProcessSubThread;
+class ContentMainDelegate;
+struct ContentMainParams;
+
+class ContentMainRunnerImpl : public ContentMainRunner {
+ public:
+ static ContentMainRunnerImpl* Create();
+
+ ContentMainRunnerImpl();
+ ~ContentMainRunnerImpl() override;
+
+ int TerminateForFatalInitializationError();
+
+ // ContentMainRunner:
+ int Initialize(const ContentMainParams& params) override;
+ int Run() override;
+ void Shutdown() override;
+
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+ // Creates a thread and returns the SingleThreadTaskRunner on which
+ // ServiceManager should run.
+ scoped_refptr<base::SingleThreadTaskRunner>
+ GetServiceManagerTaskRunnerForEmbedderProcess();
+#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
+
+ private:
+ // True if the runner has been initialized.
+ bool is_initialized_ = false;
+
+ // True if the runner has been shut down.
+ bool is_shutdown_ = false;
+
+ // True if basic startup was completed.
+ bool completed_basic_startup_ = false;
+
+ // Used if the embedder doesn't set one.
+ ContentClient empty_content_client_;
+
+ // The delegate will outlive this object.
+ ContentMainDelegate* delegate_ = nullptr;
+
+ std::unique_ptr<base::AtExitManager> exit_manager_;
+
+#if defined(OS_WIN)
+ sandbox::SandboxInterfaceInfo sandbox_info_;
+#elif defined(OS_MACOSX)
+ base::mac::ScopedNSAutoreleasePool* autorelease_pool_ = nullptr;
+#endif
+
+ std::unique_ptr<BrowserProcessSubThread> service_manager_thread_;
+
+ base::Closure* ui_task_ = nullptr;
+
+ CreatedMainPartsClosure* created_main_parts_closure_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentMainRunnerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_APP_CONTENT_MAIN_RUNNER_IMPL_H_
diff --git a/chromium/content/app/content_service_manager_main_delegate.cc b/chromium/content/app/content_service_manager_main_delegate.cc
index 62dceb57886..f3132ac7103 100644
--- a/chromium/content/app/content_service_manager_main_delegate.cc
+++ b/chromium/content/app/content_service_manager_main_delegate.cc
@@ -5,10 +5,11 @@
#include "content/app/content_service_manager_main_delegate.h"
#include "base/command_line.h"
+#include "content/app/content_main_runner_impl.h"
#include "content/public/app/content_main_delegate.h"
-#include "content/public/app/content_main_runner.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_names.mojom.h"
+#include "services/service_manager/embedder/switches.h"
#include "services/service_manager/runner/common/client_util.h"
namespace content {
@@ -16,7 +17,7 @@ namespace content {
ContentServiceManagerMainDelegate::ContentServiceManagerMainDelegate(
const ContentMainParams& params)
: content_main_params_(params),
- content_main_runner_(ContentMainRunner::Create()) {}
+ content_main_runner_(ContentMainRunnerImpl::Create()) {}
ContentServiceManagerMainDelegate::~ContentServiceManagerMainDelegate() =
default;
@@ -44,7 +45,8 @@ bool ContentServiceManagerMainDelegate::IsEmbedderSubprocess() {
type == switches::kPpapiBrokerProcess ||
type == switches::kPpapiPluginProcess ||
type == switches::kRendererProcess ||
- type == switches::kUtilityProcess || type == switches::kZygoteProcess;
+ type == switches::kUtilityProcess ||
+ type == service_manager::switches::kZygoteProcess;
}
int ContentServiceManagerMainDelegate::RunEmbedderProcess() {
@@ -124,4 +126,11 @@ ContentServiceManagerMainDelegate::CreateEmbeddedService(
return nullptr;
}
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+scoped_refptr<base::SingleThreadTaskRunner> ContentServiceManagerMainDelegate::
+ GetServiceManagerTaskRunnerForEmbedderProcess() {
+ return content_main_runner_->GetServiceManagerTaskRunnerForEmbedderProcess();
+}
+#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
+
} // namespace content
diff --git a/chromium/content/app/content_service_manager_main_delegate.h b/chromium/content/app/content_service_manager_main_delegate.h
index 4393a8fac23..a6ab54a14bc 100644
--- a/chromium/content/app/content_service_manager_main_delegate.h
+++ b/chromium/content/app/content_service_manager_main_delegate.h
@@ -8,13 +8,15 @@
#include <memory>
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "content/public/app/content_main.h"
#include "services/service_manager/embedder/main_delegate.h"
namespace content {
-class ContentMainRunner;
+class ContentMainRunnerImpl;
class ContentServiceManagerMainDelegate : public service_manager::MainDelegate {
public:
@@ -23,6 +25,10 @@ class ContentServiceManagerMainDelegate : public service_manager::MainDelegate {
// service_manager::MainDelegate:
int Initialize(const InitializeParams& params) override;
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+ scoped_refptr<base::SingleThreadTaskRunner>
+ GetServiceManagerTaskRunnerForEmbedderProcess() override;
+#endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
bool IsEmbedderSubprocess() override;
int RunEmbedderProcess() override;
void ShutDownEmbedderProcess() override;
@@ -42,7 +48,7 @@ class ContentServiceManagerMainDelegate : public service_manager::MainDelegate {
private:
ContentMainParams content_main_params_;
- std::unique_ptr<ContentMainRunner> content_main_runner_;
+ std::unique_ptr<ContentMainRunnerImpl> content_main_runner_;
#if defined(OS_ANDROID)
bool initialized_ = false;
diff --git a/chromium/content/app/strings/content_strings.grd b/chromium/content/app/strings/content_strings.grd
index d847258a81d..e2ea8177ef6 100644
--- a/chromium/content/app/strings/content_strings.grd
+++ b/chromium/content/app/strings/content_strings.grd
@@ -269,6 +269,123 @@ below:
<message name="IDS_AX_ROLE_DISCLOSURE_TRIANGLE" desc="Accessibility role description for a disclosure triangle, a control shaped like a triangle that expands or collapses to show or hide extra content">
disclosure triangle
</message>
+ <message name="IDS_AX_ROLE_DOC_ABSTRACT" desc="Accessibility role description for abstract, meaning the summary of the contents of an article or book">
+ abstract
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ACKNOWLEDGMENTS" desc="Accessibility role description for acknowledgments">
+ acknowledgments
+ </message>
+ <message name="IDS_AX_ROLE_DOC_AFTERWORD" desc="Accessibility role description for afterword">
+ afterword
+ </message>
+ <message name="IDS_AX_ROLE_DOC_APPENDIX" desc="Accessibility role description for appendix, meaning the summary of the contents of an article or book">
+ appendix
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BACKLINK" desc="Accessibility role description for back link">
+ back link
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BIBLIO_ENTRY" desc="Accessibility role description for bibliography entry">
+ bibliography entry
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BIBLIOGRAPHY" desc="Accessibility role description for bibliography">
+ bibliography
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BIBLIO_REF" desc="Accessibility role description for bibliography reference">
+ bibliography reference
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CHAPTER" desc="Accessibility role description for chapter">
+ chapter
+ </message>
+ <message name="IDS_AX_ROLE_DOC_COLOPHON" desc="Accessibility role description for colophon">
+ colophon
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CONCLUSION" desc="Accessibility role description for conclusion">
+ conclusion
+ </message>
+ <message name="IDS_AX_ROLE_DOC_COVER" desc="Accessibility role description for cover">
+ cover
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CREDIT" desc="Accessibility role description for credit, a public acknowledgement of someone who was responsible for helping with something">
+ credit
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CREDITS" desc="Accessibility role description for credits">
+ credits
+ </message>
+ <message name="IDS_AX_ROLE_DOC_DEDICATION" desc="Accessibility role description for dedication">
+ dedication
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ENDNOTE" desc="Accessibility role description for endnote">
+ endnote
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ENDNOTES" desc="Accessibility role description for endnotes">
+ endnotes
+ </message>
+ <message name="IDS_AX_ROLE_DOC_EPIGRAPH" desc="Accessibility role description for epigraph">
+ epigraph
+ </message>
+ <message name="IDS_AX_ROLE_DOC_EPILOGUE" desc="Accessibility role description for epilogue">
+ epilogue
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ERRATA" desc="Accessibility role description for errata">
+ errata
+ </message>
+ <message name="IDS_AX_ROLE_DOC_EXAMPLE" desc="Accessibility role description for example">
+ example
+ </message>
+ <message name="IDS_AX_ROLE_DOC_FOOTNOTE" desc="Accessibility role description for footnote">
+ footnote
+ </message>
+ <message name="IDS_AX_ROLE_DOC_FOREWORD" desc="Accessibility role description for foreword">
+ foreword
+ </message>
+ <message name="IDS_AX_ROLE_DOC_GLOSSARY" desc="Accessibility role description for glossary">
+ glossary
+ </message>
+ <message name="IDS_AX_ROLE_DOC_GLOSS_REF" desc="Accessibility role description for glossary reference">
+ glossary reference
+ </message>
+ <message name="IDS_AX_ROLE_DOC_INDEX" desc="Accessibility role description for index">
+ index
+ </message>
+ <message name="IDS_AX_ROLE_DOC_INTRODUCTION" desc="Accessibility role description for introduction">
+ introduction
+ </message>
+ <message name="IDS_AX_ROLE_DOC_NOTE_REF" desc="Accessibility role description for note reference">
+ note reference
+ </message>
+ <message name="IDS_AX_ROLE_DOC_NOTICE" desc="Accessibility role description for notice">
+ notice
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PAGE_BREAK" desc="Accessibility role description for page break">
+ page break
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PAGE_LIST" desc="Accessibility role description for page list">
+ page list
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PART" desc="Accessibility role description for part, as in a part of a book">
+ part
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PREFACE" desc="Accessibility role description for preface">
+ preface
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PROLOGUE" desc="Accessibility role description for prologue">
+ prologue
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PULLQUOTE" desc="Accessibility role description for pullquote">
+ pullquote
+ </message>
+ <message name="IDS_AX_ROLE_DOC_QNA" desc="Accessibility role description for Q+A (questions and answers)">
+ Q&amp;A
+ </message>
+ <message name="IDS_AX_ROLE_DOC_SUBTITLE" desc="Accessibility role description for subtitle">
+ subtitle
+ </message>
+ <message name="IDS_AX_ROLE_DOC_TIP" desc="Accessibility role description for tip, as in a suggestion or idea">
+ tip
+ </message>
+ <message name="IDS_AX_ROLE_DOC_TOC" desc="Accessibility role description for table of contents">
+ table of contents
+ </message>
<message name="IDS_AX_ROLE_FEED" desc="Accessibility role description for a scrollable list of articles.">
feed
</message>
@@ -281,6 +398,15 @@ below:
<message name="IDS_AX_ROLE_FOOTER" desc="Accessibility role description for footers">
footer
</message>
+ <message name="IDS_AX_ROLE_GRAPHICS_DOCUMENT" desc="Accessibility role description for graphics document">
+ graphics document
+ </message>
+ <message name="IDS_AX_ROLE_GRAPHICS_OBJECT" desc="Accessibility role description for graphics object">
+ graphics object
+ </message>
+ <message name="IDS_AX_ROLE_GRAPHICS_SYMBOL" desc="Accessibility role description for graphics symbol">
+ graphics symbol
+ </message>
<message name="IDS_AX_AUTOFILL_POPUP_ACCESSIBLE_NODE_DATA" desc="The accessibility text to speak when we display an autofill popup">
Autofill
</message>
@@ -810,7 +936,7 @@ below:
Picture-in-Picture
</message>
<message name="IDS_MEDIA_PICTURE_IN_PICTURE_INTERSTITIAL_TEXT" desc="Text message shown to user when in picture in picture mode. When a video is in picture in picture mode, an interstitial with this text appears where the video player is positioned. The video continues to play back in another window that gives the experience that the video is 'popped out'.">
- Now in Picture-in-Picture mode
+ This video is playing in Picture-in-Picture
</message>
<message name="IDS_MEDIA_REMOTING_CAST_TEXT" desc="Text message shown to the user when casting a video to a known remote device.">
Now casting to <ph name="DEVICE_FRIENDLY_NAME">$1<ex>Living Room TV</ex></ph>
diff --git a/chromium/content/app/strings/translations/content_strings_am.xtb b/chromium/content/app/strings/translations/content_strings_am.xtb
index 336cfe9cac9..6e66f3b1caa 100644
--- a/chromium/content/app/strings/translations/content_strings_am.xtb
+++ b/chromium/content/app/strings/translations/content_strings_am.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">ማሟያ</translation>
<translation id="1206619573307042055">መልሶ መልስ</translation>
<translation id="1206693055195146388">ተንሸራታች</translation>
+<translation id="1211441953136645838">የግርጌ ማስታወሻ</translation>
<translation id="1281252709823657822">መገናኛ</translation>
+<translation id="1335095011850992622">ክሬዲቶች</translation>
<translation id="1342835525016946179">ጽሑፍ</translation>
<translation id="1359897965706325498">ሰንደቅ</translation>
<translation id="1589122976691792535">ክልል</translation>
<translation id="1591562245178063882">በዚህ ወር</translation>
<translation id="1637811476055996098">ፋይሎችን ይምረጡ</translation>
+<translation id="1650423536718072820">ጥቅስ</translation>
<translation id="1729654308190250600">እባክዎ ባዶ ያልሆነ የኢሜይል አድራሻ ያስገቡ።</translation>
<translation id="1758486001363313524">ሌላ...</translation>
<translation id="1806710327868736751">የማንቂያ_መገናኛ</translation>
<translation id="1821985195704844674">የዛፍ ፍርግርግ</translation>
<translation id="1822429046913737220">ጥዋት/ከሰዓት</translation>
<translation id="1832974991323546415">በርቀት መሳሪያ ላይ አጫውት</translation>
+<translation id="1907737156431278478">ምሳሌ</translation>
<translation id="1921819250265091946">ቀቀ</translation>
<translation id="1930711995431081526">ሁኔታ</translation>
<translation id="1938124657309484470">ዋጋ <ph name="MAXIMUM_DATE_OR_TIME" /> ወይም ከዚያ በፊት መሆን አለበት።</translation>
<translation id="1993104285338243655">ወደ ማንጸባረቅ ተቀይሯል</translation>
<translation id="2060505056492490888">«<ph name="DOT" />» በ«<ph name="INVALIDDOMAIN" />» ውስጥ በተሳሳተ ቦታ ላይ ነው የገባው።</translation>
<translation id="2148716181193084225">ዛሬ</translation>
+<translation id="2158401438286456825">የገጽ ዝርዝር</translation>
<translation id="2226276347425096477">እባክዎ ይህ ጽሑፍ ወደ <ph name="MAX_CHARACTERS" /> ወይም ከዚያ በታች ቁምፊዎች ያሳጥሩት (በአሁኑ ጊዜ <ph name="CURRENT_LENGTH" /> ቁምፊዎችን እየተጠቀሙ ነዎት)።</translation>
<translation id="2247351761944213033">ሳምንት <ph name="WEEKNUMBER" />፣ <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ትራክ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">አመልካች ሳጥን</translation>
+<translation id="2311842470354187719">ገጽ ከፋይ</translation>
<translation id="2335594187091864976">የቀን እና የሰዓት መራጭ</translation>
<translation id="248395913932153421">ቀን</translation>
<translation id="2507943997699731163">እባክዎ ይህን መስክ ይሙሉት።</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">አጫውት</translation>
<translation id="2613802280814924224">እባክዎ የሚሰራ ዋጋ ያስገቡ። የሚቀርበው ዋጋ <ph name="VALID_VALUE" /> ነው።</translation>
<translation id="2653659639078652383">አስገባ</translation>
+<translation id="2657045182931379222">ግራፊካዊ ነገር</translation>
<translation id="2674318244760992338">ግርጌ</translation>
<translation id="2709516037105925701">ራስ-ሙላ</translation>
<translation id="2723001399770238859">ድምጽ</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">እባክዎ ይህን ጽሑፍ ወደ <ph name="MIN_CHARACTERS" /> ቁምፊዎች ወይም ከዚያ በላይ ያራዝሙት (አሁን እየተጠቀሙ ያሉት <ph name="CURRENT_LENGTH" />ቁምፊዎችን ነው)።</translation>
<translation id="383465348367842624">ከ«<ph name="ATSIGN" />» በፊት የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
<translation id="3846214748874656680">ከሙሉ ማያገጽ ውጣ</translation>
+<translation id="3920932319529768807">ድምዳሜ</translation>
<translation id="3924558731517983934">መተግበሪያ</translation>
+<translation id="3944740393230681990">ቅድመ-ታሪክ</translation>
<translation id="3960700977367013758">የማሸብለያ አሞሌ</translation>
<translation id="4103419683916926126">ሚሊሰኮንዶች</translation>
<translation id="4151657705144244502">ግራፊክ</translation>
+<translation id="4193965531860883258">መቅድም</translation>
<translation id="4201051445878709314">ቀዳሚውን ወር አሳይ</translation>
<translation id="421884353938374759">color picker</translation>
<translation id="4248100235867064564">የምናሌ አሞሌ</translation>
<translation id="4254339807215791271">የይዘት መረጃ</translation>
<translation id="4360991593054037559">እባክዎ የሚሰራ ዋጋ ያስገቡ። ሁለቱ የሚቀርቡ ዋጋዎች <ph name="VALID_VALUE_LOW" /> እና <ph name="VALID_VALUE_HIGHER" /> ናቸው።</translation>
+<translation id="4384583879834880242">ጥያቄ እና መልስ</translation>
<translation id="4413860115965805769">የምናሌ አዝራር</translation>
+<translation id="4446524499724042288">የሙዳየ ቃላት ዋቢ</translation>
<translation id="4522570452068850558">ዝርዝሮች</translation>
<translation id="4597532268155981612">ቅጽ</translation>
<translation id="4661075872484491155">ዛፍ</translation>
<translation id="4664250907885839816">ከ«<ph name="ATSIGN" />» በኋላ የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
+<translation id="4668956016107839909">ቅጥያዎች</translation>
+<translation id="4742539557769756338">ሽፋን</translation>
<translation id="4757246831282535685">የትር ፓነል</translation>
<translation id="4763480195061959176">ቪዲዮ</translation>
<translation id="479989351350248267">ፈልግ</translation>
<translation id="4812940957355064477">እባክዎ ቁጥር ያስገቡ።</translation>
+<translation id="4912536737030637138">የዋቢ መጽሐፍት ግቤት</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ተመርጠዋል</translation>
<translation id="4992066212339426712">ድምጸ-ከል አንሳ</translation>
<translation id="49969490063480558">እባክዎ ከ«<ph name="ATSIGN" />» በኋላ አንድ ክፍል ያስገቡ። «<ph name="INVALIDADDRESS" />» ያልተሟላ ነው።</translation>
<translation id="5034860022980953847">የሂደት አመልካች</translation>
+<translation id="5093189678851173835">የተቀረጸ ጽሑፍ</translation>
<translation id="5117590920725113268">ቀጣዩን ወር አሳይ</translation>
<translation id="512758898067543763">የረድፍ ራስጌ</translation>
+<translation id="5143125788380636750">ድሕረ ታሪክ</translation>
+<translation id="5153163864850940242">ይህ ቪዲዮ ስዕል-በስዕል ውስጥ እያጫወተ ነው</translation>
<translation id="5164977714490026579">ዋጋ ከ<ph name="MINIMUM" /> የሚበልጥ ወይም ከእሱ እኩል መሆን አለበት።</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> ፔታ</translation>
<translation id="5307600278924710095">እባክዎ አንድ ክፍል ያስገቡና «<ph name="ATSIGN" />»ን ያስከትሉ። «<ph name="INVALIDADDRESS" />» ያልተሟላ ነው።</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">ድምፅ-ከልን አንሳ</translation>
<translation id="561939826962581046">ሰዓት</translation>
<translation id="5630795885300617244">10 ሴ ለመዝለል ወደ ግራ ወይም ቀኝ ሁለቴ መታ ያድርጉ</translation>
+<translation id="5631759159893697722">ረቂቅ</translation>
<translation id="5641012560118721995">መልሶ ማጫወትን ለአፍታ አቁም</translation>
<translation id="5643186887447432888">አዝራር</translation>
<translation id="5677946354068040947">ተጨማሪ አማራጮች</translation>
+<translation id="576709008726043716">መግቢያ</translation>
<translation id="57838592816432529">ድምጽ ይዝጉ</translation>
<translation id="5860033963881614850">አጥፋ</translation>
<translation id="588258955323874662">ሙሉ ገጽ ዕይታ</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">ዓመት</translation>
<translation id="6023896073578205740">የዝርዝር ሳጥን</translation>
<translation id="6101327004457443354">የድምጹ ትራክ ድምጸ-ከል አንሳ</translation>
+<translation id="6150588977291308318">ዋቢ መጽሐፍት</translation>
<translation id="6164829606128959761">ሜትር</translation>
+<translation id="6166809985690652833">ድሕረ ቃል</translation>
+<translation id="6213469881011901533">ሙዳየ ቃላት</translation>
<translation id="6398862346408813489">የወር መምረጫ ፓነል አሳይ</translation>
<translation id="6404546809543547843">የኦዲዮ ሰዓት አንፏቃቂ</translation>
+<translation id="6453774872122745852">ምስጋና</translation>
<translation id="648732519525291180">ሰዓት መራጭ</translation>
<translation id="6550675742724504774">አማራጮች</translation>
-<translation id="6564313821541007458">አሁን በስዕል-ውስጥ-ስዕል ሁነታ ውስጥ</translation>
<translation id="658823671542763450">ወደ ሙሉ ገጽ ዕይታ ግባ</translation>
<translation id="663493177488814956">ምግብ</translation>
<translation id="6637586476836377253">የምዝግብ ማስታወሻ</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">ጠቃሚ የመሣሪያ ምክር</translation>
<translation id="6790428901817661496">አጫውት</translation>
<translation id="6820355525329141109">ተሰኪን መጫን አልተቻለም።</translation>
+<translation id="6820615603175220800">የዋቢ መጽሐፍት ማጣቀሻ</translation>
<translation id="6843725295806269523">ድምጸ-ከል ያድርጉ</translation>
<translation id="6853785296079745596">የተዘጉ የስዕል መግለጫዎችን ይደብቁ</translation>
<translation id="6885760532393684712">ማውጫ</translation>
+<translation id="689129560213475294">ኮሎፎን</translation>
<translation id="6934078000481955284">የጽሑፍ ጥቅስ</translation>
<translation id="6941933287844615239">ማህደረ መረጃን አውርድ</translation>
<translation id="6989848892321993519">እባክዎ ይህን ጽሑፍ ወደ <ph name="MIN_CHARACTERS" /> ወይም ከዚያ በላይ ቁምፊዎች ያራዝሙት (አሁን እየተጠቀሙ ያሉት 1 ቁምፊ ነው)።</translation>
<translation id="709897737746224366">እባክዎ የተጠየቀውን ቅርጸት ያዛምዱ።</translation>
+<translation id="7139483182332611405">መቅድም</translation>
<translation id="7223624360433298498">ያለፈው ጊዜ</translation>
<translation id="7263440858009898357">እባክዎ በዝርዝሩ ውስጥ አንድ ንጥል ይምረጡ።</translation>
<translation id="727747134524199931">የአምድ ራስጌ</translation>
+<translation id="7353453495576941748">ክሬዲት</translation>
<translation id="7364796246159120393">ፋይል ምረጥ</translation>
<translation id="739024184232394898">ሌላ...</translation>
+<translation id="7405738980073107433">ግርጌ ማስታወሻዎች</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> ቴባ</translation>
<translation id="7491962110804786152">TAB</translation>
<translation id="7514365320538308">አውርድ</translation>
+<translation id="7529102961911894712">የጀርባ አገናኝ</translation>
+<translation id="7647456547678091388">ጠቃሚ ምክር</translation>
+<translation id="7661956066982048809">ግራፊካዊ ሰነድ</translation>
<translation id="7673697353781729403">ሰዓቶች</translation>
+<translation id="7681220483256441252">መረጃ ጠቋሚ</translation>
<translation id="7720026100085573005">ቀሪ ጊዜ</translation>
<translation id="7740016676195725605">የተዘጉ የስዕል መግለጫዎችን ማሳየት አቁም</translation>
<translation id="7740050170769002709">የኤች ቲ ኤም ኤል ይዘት</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">መክፈያ</translation>
<translation id="795667975304826397">ምንም ፋይል አልተመረጠም</translation>
<translation id="8053789581856978548">የጽሑፍ መስክ ፈልግ</translation>
+<translation id="8057695513531652401">ማስታወቂያ</translation>
+<translation id="8105797009065549151">ማስታወሻ ማጣቀሻ</translation>
<translation id="8115662671911883373">የተዘጉ የስዕል መግለጫዎችን ማሳየት ጀምር</translation>
<translation id="8117451130807776954">በዚህ ሳምንት</translation>
<translation id="819205353528511139">ፊልሙን በሙሉ ማያ ገጽ ሁነታ አጫውት</translation>
<translation id="8199524924445686405">ዓዓዓዓ</translation>
<translation id="8284326494547611709">መግለጫ ጽሑፎች</translation>
<translation id="835897206747267392">ልክ ያልሆነ እሴት።</translation>
+<translation id="8415319359811155763">ክፍለ አካል</translation>
<translation id="8433900881053900389">የመሣሪያ አሞሌ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ፋይሎች</translation>
<translation id="8451268428117625855">እባክዎ ፋይል ይምረጡ።</translation>
<translation id="8461852803063341183">የሬዲዮ አዝራር</translation>
+<translation id="8474886197722836894">መታሰቢያነቱ</translation>
+<translation id="8531739829932800271">እርማት</translation>
<translation id="8534579021159131403">ደቂቃዎች</translation>
<translation id="8541249477527128034">የማህደረ መረጃ ቁጥጥር</translation>
+<translation id="8550857728288566671">ሥዕላዊ ምልክት</translation>
<translation id="8583702881314752957">የብየና ዝርዝር</translation>
<translation id="8597182159515967513">ርዕስ</translation>
+<translation id="860475260694818407">ማውጫ</translation>
<translation id="8613126697340063924">በርቀት መልሶ ማጫወትን ተቆጣጠር</translation>
+<translation id="862370744433916922">የግርጌ ጽሑፍ</translation>
<translation id="8741316211671074806">በስዕል-ውስጥ-ስዕል</translation>
<translation id="8750798805984357768">እባክዎ ከእነዚህ አማራጮች ውስጥ አንዱን ይምረጡ።</translation>
<translation id="8785498733064193001">መልሶ ማጫወት ይጀምሩ</translation>
+<translation id="8808573423886751634">ምዕራፍ</translation>
<translation id="8845239796550121995">አሁን ወደ የእርስዎ ቴሌቪዥን cast በማድረግ ላይ</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">የቪዲዮ መልሶ ማጫወት ስህተት</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">ሌላ...</translation>
<translation id="9138385573473225930">ማንቂያ</translation>
<translation id="9155987714137265666"><ph name="WEEK" />፣ የሚጀምረው በ<ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">የግርጌ ማስታወሻ</translation>
<translation id="947831847158436616">ሕዋስ</translation>
<translation id="966787709310836684">ምናሌ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ar.xtb b/chromium/content/app/strings/translations/content_strings_ar.xtb
index c5fb18d95ae..1b74c3db7b1 100644
--- a/chromium/content/app/strings/translations/content_strings_ar.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ar.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">تكميلي</translation>
<translation id="1206619573307042055">صورة بها نص متحرك</translation>
<translation id="1206693055195146388">شريط تمرير</translation>
+<translation id="1211441953136645838">تعليق ختامي</translation>
<translation id="1281252709823657822">مربع حوار</translation>
+<translation id="1335095011850992622">إسهامات</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">إعلان بانر</translation>
<translation id="1589122976691792535">منطقة</translation>
<translation id="1591562245178063882">هذا الشهر</translation>
<translation id="1637811476055996098">اختيار الملفات</translation>
+<translation id="1650423536718072820">اقتباس مستمد</translation>
<translation id="1729654308190250600">يُرجى إدخال عنوان البريد الإلكتروني وعدم ترك الحق فارغًا.</translation>
<translation id="1758486001363313524">آخر...</translation>
<translation id="1806710327868736751">مربع حوار_للتنبيه</translation>
<translation id="1821985195704844674">شبكة متفرعة</translation>
<translation id="1822429046913737220">صباحًا/مساءً</translation>
<translation id="1832974991323546415">تشغيل على جهاز بعيد</translation>
+<translation id="1907737156431278478">مثال</translation>
<translation id="1921819250265091946">يوم</translation>
<translation id="1930711995431081526">الحالة</translation>
<translation id="1938124657309484470">يجب أن تكون القيمة <ph name="MAXIMUM_DATE_OR_TIME" /> أو قبل ذلك.</translation>
<translation id="1993104285338243655">تم التبديل إلى النسخ المطابق.</translation>
<translation id="2060505056492490888">تم استخدام "<ph name="DOT" />" في موضع خاطئ في "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">اليوم</translation>
+<translation id="2158401438286456825">قائمة صفحات</translation>
<translation id="2226276347425096477">يُرجى اختصار هذا النص حتى يصل إلى <ph name="MAX_CHARACTERS" /> من الحروف أو أقل (أنت الآن تستخدم <ph name="CURRENT_LENGTH" /> من الحروف).</translation>
<translation id="2247351761944213033">الأسبوع <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
<translation id="2277199496770840904">المقطع الصوتي <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">مربع اختيار</translation>
+<translation id="2311842470354187719">فاصل صفحة</translation>
<translation id="2335594187091864976">منتقي التاريخ والوقت</translation>
<translation id="248395913932153421">يوم</translation>
<translation id="2507943997699731163">يُرجى ملء هذا الحقل.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">تشغيل</translation>
<translation id="2613802280814924224">يُرجى إدخال قيمة صالحة. علمًا بأن أقرب قيمة صالحة هي <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">إرسال</translation>
+<translation id="2657045182931379222">كائن رسومي</translation>
<translation id="2674318244760992338">تذييل</translation>
<translation id="2709516037105925701">الملء التلقائي</translation>
<translation id="2723001399770238859">الصوت</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">يُرجى إطالة هذا النص إلى <ph name="MIN_CHARACTERS" /> من الحروف أو أكثر (أنت تستخدم حاليًا <ph name="CURRENT_LENGTH" /> من الحروف).</translation>
<translation id="383465348367842624">الجزء المتبوع بالعلامة "<ph name="ATSIGN" />" يجب ألا يشتمل على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">خروج من عرض ملء الشاشة</translation>
+<translation id="3920932319529768807">خاتمة</translation>
<translation id="3924558731517983934">التطبيق</translation>
+<translation id="3944740393230681990">فاتحة</translation>
<translation id="3960700977367013758">شريط التمرير</translation>
<translation id="4103419683916926126">مللي ثانية</translation>
<translation id="4151657705144244502">الرسم</translation>
+<translation id="4193965531860883258">مقدمة</translation>
<translation id="4201051445878709314">عرض الشهر السابق</translation>
<translation id="421884353938374759">علبة الألوان</translation>
<translation id="4248100235867064564">شريط قوائم</translation>
<translation id="4254339807215791271">معلومات المحتوى</translation>
<translation id="4360991593054037559">يُرجى إدخال قيمة صالحة. علمًا بأن القيم الصالحة تتراوح بين <ph name="VALID_VALUE_LOW" /> و<ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">سين وجيم</translation>
<translation id="4413860115965805769">زر القائمة</translation>
+<translation id="4446524499724042288">مرجع مسرد مصطلحات</translation>
<translation id="4522570452068850558">التفاصيل</translation>
<translation id="4597532268155981612">نموذج</translation>
<translation id="4661075872484491155">متفرع</translation>
<translation id="4664250907885839816">يجب ألا يشتمل الجزء الذي يلي العلامة "<ph name="ATSIGN" />" على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">ملحق</translation>
+<translation id="4742539557769756338">غلاف</translation>
<translation id="4757246831282535685">لوحة علامة التبويب</translation>
<translation id="4763480195061959176">فيديو</translation>
<translation id="479989351350248267">بحث</translation>
<translation id="4812940957355064477">يُرجى إدخال عدد.</translation>
+<translation id="4912536737030637138">إدخال قائمة مراجع</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> محددة</translation>
<translation id="4992066212339426712">إعادة الصوت</translation>
<translation id="49969490063480558">يُرجى إدخال الجزء الذي يلي العلامة "<ph name="ATSIGN" />"، حيث إن "<ph name="INVALIDADDRESS" />" غير مكتمل.</translation>
<translation id="5034860022980953847">مؤشر التقدم</translation>
+<translation id="5093189678851173835">عبارة مقتبسة</translation>
<translation id="5117590920725113268">عرض الشهر التالي</translation>
<translation id="512758898067543763">عنوان الصف</translation>
+<translation id="5143125788380636750">تتِّمة</translation>
+<translation id="5153163864850940242">يتم تشغيل هذا الفيديو في الوضع "نافذة ضمن النافذة".</translation>
<translation id="5164977714490026579">يجب أن تكون القيمة أكبر من أو تساوي <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> بيتابايت</translation>
<translation id="5307600278924710095">يُرجى إدخال جزء متبوع بعلامة "<ph name="ATSIGN" />"، حيث إن "<ph name="INVALIDADDRESS" />" غير مكتمل.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">إعادة الصوت</translation>
<translation id="561939826962581046">الوقت</translation>
<translation id="5630795885300617244">انقر مرّتين جهة اليمين أو اليسار لتخطي 10 ثوانٍ.</translation>
+<translation id="5631759159893697722">نبذة مختصرة</translation>
<translation id="5641012560118721995">إيقاف التشغيل مؤقتًا</translation>
<translation id="5643186887447432888">زر</translation>
<translation id="5677946354068040947">خيارات إضافية</translation>
+<translation id="576709008726043716">مقدمة</translation>
<translation id="57838592816432529">كتم الصوت</translation>
<translation id="5860033963881614850">إيقاف</translation>
<translation id="588258955323874662">ملء الشاشة</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">عام</translation>
<translation id="6023896073578205740">مربع القائمة</translation>
<translation id="6101327004457443354">إعادة صوت المقطع الصوتي</translation>
+<translation id="6150588977291308318">قائمة مراجع</translation>
<translation id="6164829606128959761">متر</translation>
+<translation id="6166809985690652833">كلمة ختامية</translation>
+<translation id="6213469881011901533">مسرد مصطلحات</translation>
<translation id="6398862346408813489">عرض لوحة تحديد الشهر</translation>
<translation id="6404546809543547843">شريط تمرير وقت الصوت</translation>
+<translation id="6453774872122745852">شكر وتقدير</translation>
<translation id="648732519525291180">منتقي الوقت</translation>
<translation id="6550675742724504774">خيارات</translation>
-<translation id="6564313821541007458">أنت الآن في وضع نافذة ضمن النافذة.</translation>
<translation id="658823671542763450">تشغيل وضع ملء الشاشة</translation>
<translation id="663493177488814956">البطاقات</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">تلميح</translation>
<translation id="6790428901817661496">التشغيل</translation>
<translation id="6820355525329141109">تعذر تحميل المكوّن الإضافي.</translation>
+<translation id="6820615603175220800">مرجع قائمة مراجع</translation>
<translation id="6843725295806269523">كتم الصوت</translation>
<translation id="6853785296079745596">إخفاء الترجمة والشرح</translation>
<translation id="6885760532393684712">الدليل</translation>
+<translation id="689129560213475294">إشارة ناشر</translation>
<translation id="6934078000481955284">علامة اقتباس فقرة</translation>
<translation id="6941933287844615239">تنزيل وسائط</translation>
<translation id="6989848892321993519">يُرجى إطالة هذا النص إلى <ph name="MIN_CHARACTERS" /> من الحروف أو أكثر (أنت الآن تستخدم حرفًا واحدًا).</translation>
<translation id="709897737746224366">يُرجى مطابقة التنسيق المطلوب.</translation>
+<translation id="7139483182332611405">تمهيد</translation>
<translation id="7223624360433298498">المدة المنقضية</translation>
<translation id="7263440858009898357">يُرجى تحديد عنصر من القائمة.</translation>
<translation id="727747134524199931">عنوان العمود</translation>
+<translation id="7353453495576941748">إسهام</translation>
<translation id="7364796246159120393">اختيار ملفّ</translation>
<translation id="739024184232394898">آخر...</translation>
+<translation id="7405738980073107433">تعليقات ختامية</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> تيرابايت</translation>
<translation id="7491962110804786152">علامة تبويب</translation>
<translation id="7514365320538308">تنزيل</translation>
+<translation id="7529102961911894712">رابط رجوع</translation>
+<translation id="7647456547678091388">نصيحة</translation>
+<translation id="7661956066982048809">مستند رسومي</translation>
<translation id="7673697353781729403">ساعات</translation>
+<translation id="7681220483256441252">فهرس</translation>
<translation id="7720026100085573005">المدة المتبقية</translation>
<translation id="7740016676195725605">إيقاف عرض الترجمة والشرح</translation>
<translation id="7740050170769002709">‏محتوى HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">أداة التقسيم</translation>
<translation id="795667975304826397">ّلم يتمّ اختيار أيّ ملفّ</translation>
<translation id="8053789581856978548">الحقل النصي للبحث</translation>
+<translation id="8057695513531652401">ملاحظة</translation>
+<translation id="8105797009065549151">ملاحظة مرجعية</translation>
<translation id="8115662671911883373">بدء عرض الترجمة والشرح</translation>
<translation id="8117451130807776954">هذا الأسبوع</translation>
<translation id="819205353528511139">تشغيل الفيلم في وضع ملء الشاشة</translation>
<translation id="8199524924445686405">سنة</translation>
<translation id="8284326494547611709">الترجمة والشرح</translation>
<translation id="835897206747267392">قيمة غير صحيحة</translation>
+<translation id="8415319359811155763">جزء</translation>
<translation id="8433900881053900389">شريط الأدوات</translation>
<translation id="8444882422881193423">عدد الملفات: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">يُرجى تحديد ملف.</translation>
<translation id="8461852803063341183">زر الاختيار</translation>
+<translation id="8474886197722836894">إهداء</translation>
+<translation id="8531739829932800271">قائمة بالأخطاء</translation>
<translation id="8534579021159131403">دقائق</translation>
<translation id="8541249477527128034">التحكم في الوسائط</translation>
+<translation id="8550857728288566671">رمز رسومي</translation>
<translation id="8583702881314752957">قائمة تعريف</translation>
<translation id="8597182159515967513">العنوان</translation>
+<translation id="860475260694818407">جدول المحتويات</translation>
<translation id="8613126697340063924">التحكم في التشغيل عن بعد</translation>
+<translation id="862370744433916922">ترجمة مصاحِبة</translation>
<translation id="8741316211671074806">نافذة ضمن النافذة</translation>
<translation id="8750798805984357768">يُرجى اختيار أحد هذه الخيارات.</translation>
<translation id="8785498733064193001">بدء التشغيل</translation>
+<translation id="8808573423886751634">فصل</translation>
<translation id="8845239796550121995">يتم الآن الإرسال إلى جهاز التلفزيون</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">خطأ في تشغيل الفيديو.</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">آخر...</translation>
<translation id="9138385573473225930">تنبيه</translation>
<translation id="9155987714137265666"><ph name="WEEK" />، ابتداء من <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">حاشية سُفلية</translation>
<translation id="947831847158436616">خلية</translation>
<translation id="966787709310836684">القائمة</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_bg.xtb b/chromium/content/app/strings/translations/content_strings_bg.xtb
index c767e2faddf..14dc2f943d5 100644
--- a/chromium/content/app/strings/translations/content_strings_bg.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bg.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">допълнение</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">плъзгач</translation>
+<translation id="1211441953136645838">бележка в края</translation>
<translation id="1281252709823657822">диалогов прозорец</translation>
+<translation id="1335095011850992622">признания за източника</translation>
<translation id="1342835525016946179">статия</translation>
<translation id="1359897965706325498">банер</translation>
<translation id="1589122976691792535">регион</translation>
<translation id="1591562245178063882">Този месец</translation>
<translation id="1637811476055996098">Избор на файлове</translation>
+<translation id="1650423536718072820">изнесен цитат</translation>
<translation id="1729654308190250600">Моля, въведете имейл адрес.</translation>
<translation id="1758486001363313524">Други...</translation>
<translation id="1806710327868736751">диалогов прозорец със сигнал</translation>
<translation id="1821985195704844674">дървовидна таблица</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">възпроизвеждане на отдалечено устройство</translation>
+<translation id="1907737156431278478">пример</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">състояние</translation>
<translation id="1938124657309484470">Стойността трябва да е <ph name="MAXIMUM_DATE_OR_TIME" /> или по-рано.</translation>
<translation id="1993104285338243655">Превключихте към дублиране</translation>
<translation id="2060505056492490888">„<ph name="DOT" />“ се използва на неправилна позиция в/ъв „<ph name="INVALIDDOMAIN" />“.</translation>
<translation id="2148716181193084225">Днес</translation>
+<translation id="2158401438286456825">списък със страниците</translation>
<translation id="2226276347425096477">Моля, съкратете този текст до <ph name="MAX_CHARACTERS" /> знака или по-малко (понастоящем използвате <ph name="CURRENT_LENGTH" /> знака).</translation>
<translation id="2247351761944213033">Седмица <ph name="WEEKNUMBER" />, <ph name="YEAR" /> г.</translation>
<translation id="2277199496770840904">Запис <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">квадратче за отметка</translation>
+<translation id="2311842470354187719">разделител на страници</translation>
<translation id="2335594187091864976">инструмент за избор на дата и час</translation>
<translation id="248395913932153421">Ден</translation>
<translation id="2507943997699731163">Моля, попълнете това поле.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">пускане</translation>
<translation id="2613802280814924224">Моля, въведете валидна стойност. Най-близката такава е <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Изпращане</translation>
+<translation id="2657045182931379222">графичен обект</translation>
<translation id="2674318244760992338">долен колонтитул</translation>
<translation id="2709516037105925701">Автоматично попълване</translation>
<translation id="2723001399770238859">звук</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Моля, удължете този текст поне до <ph name="MIN_CHARACTERS" /> знака (понастоящем използвате <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Текстът преди „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="3846214748874656680">Изход от цял екран</translation>
+<translation id="3920932319529768807">заключение</translation>
<translation id="3924558731517983934">приложение</translation>
+<translation id="3944740393230681990">пролог</translation>
<translation id="3960700977367013758">лента за превъртане</translation>
<translation id="4103419683916926126">Милисекунди</translation>
<translation id="4151657705144244502">графика</translation>
+<translation id="4193965531860883258">предговор</translation>
<translation id="4201051445878709314">Показване на предишния месец</translation>
<translation id="421884353938374759">инструмент за избор на цветове</translation>
<translation id="4248100235867064564">лента с менюта</translation>
<translation id="4254339807215791271">информация за съдържанието</translation>
<translation id="4360991593054037559">Моля, въведете валидна стойност. Двете най-близки такива са <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Въпроси и отговори</translation>
<translation id="4413860115965805769">бутон за меню</translation>
+<translation id="4446524499724042288">препратка към определение в терминологичния речник</translation>
<translation id="4522570452068850558">Подробности</translation>
<translation id="4597532268155981612">формуляр</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Текстът след „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4668956016107839909">приложение</translation>
+<translation id="4742539557769756338">корица</translation>
<translation id="4757246831282535685">панел с раздели</translation>
<translation id="4763480195061959176">видео</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Моля, въведете номер.</translation>
+<translation id="4912536737030637138">библиографски запис</translation>
<translation id="4975562563186953947">Избрани: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Включване на звука</translation>
<translation id="49969490063480558">Моля, въведете текст след „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ е непълно.</translation>
<translation id="5034860022980953847">индикатор за напредък</translation>
+<translation id="5093189678851173835">епиграф</translation>
<translation id="5117590920725113268">Показване на следващия месец</translation>
<translation id="512758898067543763">заглавка на ред</translation>
+<translation id="5143125788380636750">епилог</translation>
+<translation id="5153163864850940242">Този видеоклип се възпроизвежда в режим „Картина в картината“</translation>
<translation id="5164977714490026579">Стойността трябва да е по-голяма или равна на <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> ПБ</translation>
<translation id="5307600278924710095">Моля, въведете текст преди „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ е непълно.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">пускане на звука</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Докоснете два пъти стрелката наляво или надясно, за да пропуснете 10 сек</translation>
+<translation id="5631759159893697722">резюме</translation>
<translation id="5641012560118721995">поставяне на възпроизвеждането на пауза</translation>
<translation id="5643186887447432888">бутон</translation>
<translation id="5677946354068040947">още опции</translation>
+<translation id="576709008726043716">въведение</translation>
<translation id="57838592816432529">Заглушаване</translation>
<translation id="5860033963881614850">Изключено</translation>
<translation id="588258955323874662">Цял екран</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Година</translation>
<translation id="6023896073578205740">списъчно поле</translation>
<translation id="6101327004457443354">пускане на аудиозаписа</translation>
+<translation id="6150588977291308318">библиография</translation>
<translation id="6164829606128959761">индикатор</translation>
+<translation id="6166809985690652833">послеслов</translation>
+<translation id="6213469881011901533">терминологичен речник</translation>
<translation id="6398862346408813489">Показване на панела за избиране на месец</translation>
<translation id="6404546809543547843">времеви плъзгач за аудиозаписа</translation>
+<translation id="6453774872122745852">признания</translation>
<translation id="648732519525291180">инструмент за избор на час</translation>
<translation id="6550675742724504774">Опции</translation>
-<translation id="6564313821541007458">Гледате в режим „Картина в картината“</translation>
<translation id="658823671542763450">вход за цял екран</translation>
<translation id="663493177488814956">емисия</translation>
<translation id="6637586476836377253">регистрационен файл</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">подсказка</translation>
<translation id="6790428901817661496">Пускане</translation>
<translation id="6820355525329141109">Приставката не можа да се зареди.</translation>
+<translation id="6820615603175220800">препратка към библиографски запис</translation>
<translation id="6843725295806269523">заглушаване</translation>
<translation id="6853785296079745596">скриване на надписите</translation>
<translation id="6885760532393684712">директория</translation>
+<translation id="689129560213475294">колофон</translation>
<translation id="6934078000481955284">блоков цитат</translation>
<translation id="6941933287844615239">изтегляне на мултимедията</translation>
<translation id="6989848892321993519">Моля, удължете този текст до поне <ph name="MIN_CHARACTERS" /> знака (понастоящем използвате 1 знак).</translation>
<translation id="709897737746224366">Моля, спазвайте изисквания формат.</translation>
+<translation id="7139483182332611405">предисловие</translation>
<translation id="7223624360433298498">изминало време</translation>
<translation id="7263440858009898357">Моля, изберете елемент в списъка.</translation>
<translation id="727747134524199931">заглавка на колона</translation>
+<translation id="7353453495576941748">признание за източника</translation>
<translation id="7364796246159120393">Избор на файл</translation>
<translation id="739024184232394898">Други...</translation>
+<translation id="7405738980073107433">бележки в края</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> ТБ</translation>
<translation id="7491962110804786152">раздел</translation>
<translation id="7514365320538308">Изтегляне</translation>
+<translation id="7529102961911894712">препратка</translation>
+<translation id="7647456547678091388">съвет</translation>
+<translation id="7661956066982048809">графичен документ</translation>
<translation id="7673697353781729403">Часове</translation>
+<translation id="7681220483256441252">показалец</translation>
<translation id="7720026100085573005">оставащо време</translation>
<translation id="7740016676195725605">спиране на показването на надписите</translation>
<translation id="7740050170769002709">HTML съдържание</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">разделител</translation>
<translation id="795667975304826397">Няма избран файл</translation>
<translation id="8053789581856978548">текстово поле за търсене</translation>
+<translation id="8057695513531652401">известие</translation>
+<translation id="8105797009065549151">препратка към бележка</translation>
<translation id="8115662671911883373">започване на показването на надписите</translation>
<translation id="8117451130807776954">Тази седмица</translation>
<translation id="819205353528511139">пускане на филма в режим на цял екран</translation>
<translation id="8199524924445686405">гггг</translation>
<translation id="8284326494547611709">Надписи</translation>
<translation id="835897206747267392">Невалидна стойност.</translation>
+<translation id="8415319359811155763">част</translation>
<translation id="8433900881053900389">лента с инструменти</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> файла</translation>
<translation id="8451268428117625855">Моля, изберете файл.</translation>
<translation id="8461852803063341183">бутон за избор</translation>
+<translation id="8474886197722836894">посвещение</translation>
+<translation id="8531739829932800271">списък с печатните грешки</translation>
<translation id="8534579021159131403">Минути</translation>
<translation id="8541249477527128034">медийна контрола</translation>
+<translation id="8550857728288566671">графичен символ</translation>
<translation id="8583702881314752957">списък с дефиниции</translation>
<translation id="8597182159515967513">заглавие</translation>
+<translation id="860475260694818407">съдържание</translation>
<translation id="8613126697340063924">управление на отдалеченото възпроизвеждане</translation>
+<translation id="862370744433916922">подзаглавие</translation>
<translation id="8741316211671074806">Картина в картината</translation>
<translation id="8750798805984357768">Моля, изберете една от тези опции.</translation>
<translation id="8785498733064193001">начало на възпроизвеждането</translation>
+<translation id="8808573423886751634">глава</translation>
<translation id="8845239796550121995">В момента се предава към телевизора ви</translation>
<translation id="8851136666856101339">основен елемент</translation>
<translation id="8875657656876809964">Грешка при възпроизвеждането на видеоклипа</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Други...</translation>
<translation id="9138385573473225930">сигнал</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> – започва от <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">бележка под линия</translation>
<translation id="947831847158436616">клетка</translation>
<translation id="966787709310836684">меню</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_bn.xtb b/chromium/content/app/strings/translations/content_strings_bn.xtb
index d99fd33af1e..e0bf864e511 100644
--- a/chromium/content/app/strings/translations/content_strings_bn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bn.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">পরিপূরক</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">স্লাইডার</translation>
+<translation id="1211441953136645838">এন্ডনোট</translation>
<translation id="1281252709823657822">ডায়ালগ</translation>
+<translation id="1335095011850992622">ক্রেডিট</translation>
<translation id="1342835525016946179">নিবন্ধ</translation>
<translation id="1359897965706325498">ব্যানার</translation>
<translation id="1589122976691792535">অঞ্চল</translation>
<translation id="1591562245178063882">এই মাস</translation>
<translation id="1637811476055996098">ফাইল বেছে নিন</translation>
+<translation id="1650423536718072820">পুলকোট</translation>
<translation id="1729654308190250600">দয়া করে একটি খালি না থাকা ইমেল ঠিকানা লিখুন৷</translation>
<translation id="1758486001363313524">অন্যান্য...</translation>
<translation id="1806710327868736751">সতর্কতার_ডায়ালগ</translation>
<translation id="1821985195704844674">ট্রি গ্রিড</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">রিমোট ডিভাইসে প্লে করুন</translation>
+<translation id="1907737156431278478">উদাহরণ</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">স্থিতি</translation>
<translation id="1938124657309484470">মানকে অবশ্যই <ph name="MAXIMUM_DATE_OR_TIME" /> বা আগের হতে হবে৷</translation>
<translation id="1993104285338243655">মিররিং এ পরিবর্তন করা হয়েছে</translation>
<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN" />' এ একটি ভুল অবস্থানে '<ph name="DOT" />' ব্যবহৃত হয়েছে৷</translation>
<translation id="2148716181193084225">আজ</translation>
+<translation id="2158401438286456825">পৃষ্ঠা তালিকা</translation>
<translation id="2226276347425096477">দয়া করে এই পাঠ্যটি <ph name="MAX_CHARACTERS" />টি অক্ষর বা তার কমে (আপনি বর্তমানে <ph name="CURRENT_LENGTH" />টি অক্ষর ব্যবহার করছেন) সংক্ষিপ্ত করুন৷</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" /> সপ্তাহ, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ট্র্যাক <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">চেকবাক্স</translation>
+<translation id="2311842470354187719">পৃষ্ঠা বিরতি</translation>
<translation id="2335594187091864976">তারিখ এবং সময় চয়নকারি</translation>
<translation id="248395913932153421">দিন</translation>
<translation id="2507943997699731163">দয়া করে এই ক্ষেত্রটি পূরণ করুন৷</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">চালনা করুন</translation>
<translation id="2613802280814924224">দয়া করে একটি বৈধ মান লিখুন৷ কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE" />৷</translation>
<translation id="2653659639078652383">জমা দিন</translation>
+<translation id="2657045182931379222">গ্রাফিক্স অবজেক্ট</translation>
<translation id="2674318244760992338">পাদলেখ</translation>
<translation id="2709516037105925701">স্বয়ংপূরণ</translation>
<translation id="2723001399770238859">অডিও</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">দয়া করে এই পাঠ্যকে ন্যূনতম <ph name="MIN_CHARACTERS" /> অক্ষরের বা তার বেশি (আপনি বর্তমানে <ph name="CURRENT_LENGTH" />টি অক্ষর ব্যবহার করেছেন) দৈর্ঘের করুন।</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
<translation id="3846214748874656680">পূর্ণস্ক্রীন থেকে প্রস্থান করুন</translation>
+<translation id="3920932319529768807">সিদ্ধান্ত</translation>
<translation id="3924558731517983934">অ্যাপ্লিকেশান</translation>
+<translation id="3944740393230681990">ভূমিকা</translation>
<translation id="3960700977367013758">স্ক্রোল বার</translation>
<translation id="4103419683916926126">মিলিসেকেন্ড</translation>
<translation id="4151657705144244502">গ্রাফিক</translation>
+<translation id="4193965531860883258">মুখবন্ধ</translation>
<translation id="4201051445878709314">পূর্ববর্তী মাস দেখান</translation>
<translation id="421884353938374759">রঙ চয়নকারী</translation>
<translation id="4248100235867064564">মেনু বার</translation>
<translation id="4254339807215791271">সামগ্রীর তথ্য</translation>
<translation id="4360991593054037559">দয়া করে একটি বৈধ মান লিখুন৷ দুটি কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE_LOW" /> এবং <ph name="VALID_VALUE_HIGHER" />৷</translation>
+<translation id="4384583879834880242">প্রশ্ন এবং উত্তর</translation>
<translation id="4413860115965805769">মেনু বোতাম</translation>
+<translation id="4446524499724042288">শব্দকোষের রেফারেন্স</translation>
<translation id="4522570452068850558">বিশদ বিবরণ</translation>
<translation id="4597532268155981612">ফর্ম</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
+<translation id="4668956016107839909">পরিশিষ্ট</translation>
+<translation id="4742539557769756338">কভার</translation>
<translation id="4757246831282535685">ট্যাব প্যানেল</translation>
<translation id="4763480195061959176">ভিডিও</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">দয়া করে একটি সংখ্যা লিখুন৷</translation>
+<translation id="4912536737030637138">বিবলিওগ্রাফি এন্ট্রি</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" />টি নির্বাচিত</translation>
<translation id="4992066212339426712">সশব্দ করুন</translation>
<translation id="49969490063480558">দয়া করে '<ph name="ATSIGN" />' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS" />' অসম্পূর্ণ৷</translation>
<translation id="5034860022980953847">অগ্রগতি সূচক</translation>
+<translation id="5093189678851173835">এপিগ্রাফ</translation>
<translation id="5117590920725113268">পরবর্তী মাস দেখান</translation>
<translation id="512758898067543763">সারি শিরোলেখ</translation>
+<translation id="5143125788380636750">উপসংহার</translation>
+<translation id="5153163864850940242">এই ভিডিওটি ছবির-মধ্যে-ছবিতে চালানো হচ্ছে</translation>
<translation id="5164977714490026579">মানটি অবশ্যই <ph name="MINIMUM" />এর চেয়ে বেশি বা সমান হবে৷</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS" />' অসম্পূর্ণ৷</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">সশব্দ</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">১০ সেকেন্ড আগে পরে করার জন্য বাঁ অথবা ডান দিকে ডবল ট্যাপ করুন</translation>
+<translation id="5631759159893697722">বিমূর্ত</translation>
<translation id="5641012560118721995">প্লেব্যাক বিরতি</translation>
<translation id="5643186887447432888">বোতাম</translation>
<translation id="5677946354068040947">আরও বিকল্প</translation>
+<translation id="576709008726043716">পরিচয়</translation>
<translation id="57838592816432529">নিঃশব্দ করুন</translation>
<translation id="5860033963881614850">বন্ধ করুন</translation>
<translation id="588258955323874662">সম্পূর্নস্ক্রীণ</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">বছর</translation>
<translation id="6023896073578205740">তালিকা বাক্স</translation>
<translation id="6101327004457443354">অডিও ট্র্যাক সশব্দ করুন</translation>
+<translation id="6150588977291308318">বিবলিওগ্রাফি</translation>
<translation id="6164829606128959761">মিটার</translation>
+<translation id="6166809985690652833">পরিশিষ্ট</translation>
+<translation id="6213469881011901533">শব্দকোষ</translation>
<translation id="6398862346408813489">মাস নির্বাচনের প্যানেল দেখান</translation>
<translation id="6404546809543547843">অডিও সময় স্ক্রাবার</translation>
+<translation id="6453774872122745852">কৃতজ্ঞতা স্বীকার</translation>
<translation id="648732519525291180">সময় চয়নকারি</translation>
<translation id="6550675742724504774">বিকল্পসমূহ</translation>
-<translation id="6564313821541007458">এখন ছবির-মধ্যে-ছবি মোডে</translation>
<translation id="658823671542763450">পূর্ণ স্ক্রীনে প্রবেশ করুন</translation>
<translation id="663493177488814956">ফিড</translation>
<translation id="6637586476836377253">লগ</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">সরঞ্জামটিপ</translation>
<translation id="6790428901817661496">চালু করুন</translation>
<translation id="6820355525329141109">প্লাগ ইন লোড করা যায়নি।</translation>
+<translation id="6820615603175220800">বিবলিওগ্রাফি রেফারেন্স</translation>
<translation id="6843725295806269523">নিঃশব্দ</translation>
<translation id="6853785296079745596">বন্ধ করা পরিচয়লিপিগুলি লুকান</translation>
<translation id="6885760532393684712">ডিরেক্টরি</translation>
+<translation id="689129560213475294">বইটির সম্পর্কে</translation>
<translation id="6934078000481955284">ব্লক উদ্ধৃতি</translation>
<translation id="6941933287844615239">মিডিয়া ডাউনলোড করুন</translation>
<translation id="6989848892321993519">দয়া করে এই পাঠ্যকে ন্যূনতম <ph name="MIN_CHARACTERS" /> অক্ষরের বা তার বেশি দৈর্ঘ্যের করুন (আপনি বর্তমানে ১টি অক্ষর ব্যবহার করেছেন)।</translation>
<translation id="709897737746224366">দয়া করে অনুরোধ হওয়া বিন্যাসটি মেলান৷</translation>
+<translation id="7139483182332611405">মুখবন্ধ</translation>
<translation id="7223624360433298498">অতিবাহিত সময়</translation>
<translation id="7263440858009898357">তালিকা থেকে একটি আইটেম নির্বাচন করুন৷ </translation>
<translation id="727747134524199931">কলাম শিরোলেখ</translation>
+<translation id="7353453495576941748">স্বীকৃতি</translation>
<translation id="7364796246159120393">ফাইল বেছে নিন</translation>
<translation id="739024184232394898">অন্যান্য...</translation>
+<translation id="7405738980073107433">এন্ডনোট</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">ট্যাব</translation>
<translation id="7514365320538308">ডাউনলোড করুন</translation>
+<translation id="7529102961911894712">ফিরে যাওয়ার লিঙ্ক</translation>
+<translation id="7647456547678091388">পরামর্শ</translation>
+<translation id="7661956066982048809">গ্রাফিক্স ডকুমেন্ট</translation>
<translation id="7673697353781729403">ঘণ্টা</translation>
+<translation id="7681220483256441252">সূচি</translation>
<translation id="7720026100085573005">অবশিষ্ট সময়</translation>
<translation id="7740016676195725605">বদ্ধ পরিচয়লিপিগুলির প্রদর্শন থামান</translation>
<translation id="7740050170769002709">HTML সামগ্রী</translation>
@@ -159,25 +191,34 @@
<translation id="7888071071722539607">ইমেল ঠিনাকাটিতে দয়া করে একটি '<ph name="ATSIGN" />' অন্তর্ভুক্ত করুন৷ '<ph name="INVALIDADDRESS" />' এ একটি '<ph name="ATSIGN" />' অনুপস্থিত৷</translation>
<translation id="7891486169920085145">স্প্লিটার</translation>
<translation id="795667975304826397">কোনও ফাইল চয়ন করা হয় নি</translation>
-<translation id="8053789581856978548">অনুসন্ধান পাঠ্য ফিল্ড</translation>
+<translation id="8053789581856978548">সার্চ পাঠ্য ফিল্ড</translation>
+<translation id="8057695513531652401">বিজ্ঞপ্তি</translation>
+<translation id="8105797009065549151">নোটের রেফারেন্স</translation>
<translation id="8115662671911883373">বন্ধ পরিচয়লিপিগুলির প্রদর্শন শুরু করুন</translation>
<translation id="8117451130807776954">এই সপ্তাহ</translation>
<translation id="819205353528511139">পূর্ণ স্ক্রিন মোডে চলচ্চিত্র চালান</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">পরিচয়লিপিগুলি</translation>
<translation id="835897206747267392">অকার্যকর মান৷</translation>
+<translation id="8415319359811155763">অংশ</translation>
<translation id="8433900881053900389">টুল দণ্ড</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> টি ফাইল</translation>
<translation id="8451268428117625855">দয়া করে একটি ফাইল নির্বাচন করুন৷</translation>
<translation id="8461852803063341183">রেডিও বোতাম</translation>
+<translation id="8474886197722836894">উৎসর্গ</translation>
+<translation id="8531739829932800271">ত্রুটি-বিচ্যুতি</translation>
<translation id="8534579021159131403">মিনিট</translation>
<translation id="8541249477527128034">মিডিয়া নিয়ন্ত্রণ</translation>
+<translation id="8550857728288566671">গ্রাফিক্স চিহ্ন</translation>
<translation id="8583702881314752957">সংজ্ঞার তালিকা</translation>
<translation id="8597182159515967513">শিরোনাম</translation>
+<translation id="860475260694818407">সূচিপত্র</translation>
<translation id="8613126697340063924">রিমোট প্লেব্যাক নিয়ন্ত্রণ করুন</translation>
+<translation id="862370744433916922">সাবটাইটেল</translation>
<translation id="8741316211671074806">ছবির-মধ্যে-ছবি</translation>
<translation id="8750798805984357768">দয়া করে বিকল্পগুলির একটি নির্বাচন করুন৷</translation>
<translation id="8785498733064193001">প্লেব্যাক শুরু করুন</translation>
+<translation id="8808573423886751634">অধ্যায়</translation>
<translation id="8845239796550121995">এখন আপনার TV তে কাস্ট করা হচ্ছে</translation>
<translation id="8851136666856101339">প্রধান</translation>
<translation id="8875657656876809964">ভিডিও প্লেব্যাকে সমস্যা</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">অন্যান্য...</translation>
<translation id="9138385573473225930">সতর্কতা</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> এ শুরু</translation>
+<translation id="9168329111483466115">ফুটনোট</translation>
<translation id="947831847158436616">কক্ষ</translation>
<translation id="966787709310836684">মেনু</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ca.xtb b/chromium/content/app/strings/translations/content_strings_ca.xtb
index 3dc39f7b671..fd56238d889 100644
--- a/chromium/content/app/strings/translations/content_strings_ca.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ca.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementari</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">control lliscant</translation>
+<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">quadre de diàleg</translation>
+<translation id="1335095011850992622">crèdits</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">bàner</translation>
<translation id="1589122976691792535">regió</translation>
<translation id="1591562245178063882">Aquest mes</translation>
<translation id="1637811476055996098">Trieu els fitxers</translation>
+<translation id="1650423536718072820">citació extreta</translation>
<translation id="1729654308190250600">Introduïu una adreça electrònica.</translation>
<translation id="1758486001363313524">Altres...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">quadrícula d'arbre</translation>
<translation id="1822429046913737220">a. m./p. m.</translation>
<translation id="1832974991323546415">reprodueix al dispositiu remot</translation>
+<translation id="1907737156431278478">exemple</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estat</translation>
<translation id="1938124657309484470">El valor ha de ser <ph name="MAXIMUM_DATE_OR_TIME" /> o anterior.</translation>
<translation id="1993104285338243655">S'ha canviat a projecció</translation>
<translation id="2060505056492490888">"<ph name="DOT" />" s'ha utilitzat en una posició incorrecta a "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Avui</translation>
+<translation id="2158401438286456825">llista de pàgines</translation>
<translation id="2226276347425096477">Escurceu aquest text a un màxim de <ph name="MAX_CHARACTERS" /> caràcters (ara n'esteu utilitzant <ph name="CURRENT_LENGTH" />).</translation>
<translation id="2247351761944213033">Setmana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casella de selecció</translation>
+<translation id="2311842470354187719">salt de pàgina</translation>
<translation id="2335594187091864976">selector de data i hora</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Empleneu aquest camp.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">reprodueix</translation>
<translation id="2613802280814924224">Introduïu un valor vàlid. El valor vàlid més proper és <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Envia</translation>
+<translation id="2657045182931379222">objecte gràfic</translation>
<translation id="2674318244760992338">peu</translation>
<translation id="2709516037105925701">Emplenament autom.</translation>
<translation id="2723001399770238859">àudio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Allargueu aquest text fins a un mínim de <ph name="MIN_CHARACTERS" /> caràcters (ara n'utilitzeu <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Un nom d'usuari seguit de "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Surt de la pantalla completa</translation>
+<translation id="3920932319529768807">conclusió</translation>
<translation id="3924558731517983934">aplicació</translation>
+<translation id="3944740393230681990">pròleg</translation>
<translation id="3960700977367013758">barra de desplaçament</translation>
<translation id="4103419683916926126">Mil·lisegons</translation>
<translation id="4151657705144244502">gràfic</translation>
+<translation id="4193965531860883258">preàmbul</translation>
<translation id="4201051445878709314">Mostra el mes anterior</translation>
<translation id="421884353938374759">selector de color</translation>
<translation id="4248100235867064564">barra de menús</translation>
<translation id="4254339807215791271">informació sobre el contingut</translation>
<translation id="4360991593054037559">Introduïu un valor vàlid. Els valors vàlids més propers són <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Preguntes</translation>
<translation id="4413860115965805769">botó de menú</translation>
+<translation id="4446524499724042288">referència del glossari</translation>
<translation id="4522570452068850558">Detalls</translation>
<translation id="4597532268155981612">formulari</translation>
<translation id="4661075872484491155">arbre</translation>
<translation id="4664250907885839816">Un domini precedit per "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apèndix</translation>
+<translation id="4742539557769756338">portada</translation>
<translation id="4757246831282535685">tauler de pestanyes</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">cerca</translation>
<translation id="4812940957355064477">Introduïu un número.</translation>
+<translation id="4912536737030637138">entrada bibliogràfica</translation>
<translation id="4975562563186953947">Elements seleccionats: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Activa el so</translation>
<translation id="49969490063480558">Introduïu un domini precedit per "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" no és una adreça electrònica completa.</translation>
<translation id="5034860022980953847">indicador de progrés</translation>
+<translation id="5093189678851173835">epígraf</translation>
<translation id="5117590920725113268">Mostra el mes següent</translation>
<translation id="512758898067543763">capçalera de la fila</translation>
+<translation id="5143125788380636750">epíleg</translation>
+<translation id="5153163864850940242">Aquest vídeo s'està reproduint en mode de pantalla en pantalla</translation>
<translation id="5164977714490026579">El valor ha de ser més gran o igual que <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Introduïu un nom d'usuari seguit de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" no és una adreça completa.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">activa el so</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Fes doble toc a l'esquerra o a la dreta per saltar 10 s</translation>
+<translation id="5631759159893697722">resum</translation>
<translation id="5641012560118721995">pausa la reproducció</translation>
<translation id="5643186887447432888">botó</translation>
<translation id="5677946354068040947">més opcions</translation>
+<translation id="576709008726043716">introducció</translation>
<translation id="57838592816432529">Silencia</translation>
<translation id="5860033963881614850">Desactivat</translation>
<translation id="588258955323874662">Pantalla completa</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Any</translation>
<translation id="6023896073578205740">quadre de llista</translation>
<translation id="6101327004457443354">activa el so de la pista d'àudio</translation>
+<translation id="6150588977291308318">bibliografia</translation>
<translation id="6164829606128959761">comptador</translation>
+<translation id="6166809985690652833">cloenda</translation>
+<translation id="6213469881011901533">glossari</translation>
<translation id="6398862346408813489">Mostra el tauler de la selecció de mes</translation>
<translation id="6404546809543547843">barra de moment de l'àudio</translation>
+<translation id="6453774872122745852">agraïments</translation>
<translation id="648732519525291180">selector d'hora</translation>
<translation id="6550675742724504774">Opcions</translation>
-<translation id="6564313821541007458">Ara en el mode de pantalla en pantalla</translation>
<translation id="658823671542763450">passa a pantalla completa</translation>
<translation id="663493177488814956">El meu tauler</translation>
<translation id="6637586476836377253">registre</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">descripció emergent</translation>
<translation id="6790428901817661496">Reprodueix</translation>
<translation id="6820355525329141109">El connector no s'ha pogut carregar.</translation>
+<translation id="6820615603175220800">referència bibliogràfica</translation>
<translation id="6843725295806269523">silencia</translation>
<translation id="6853785296079745596">amaga els subtítols ocults</translation>
<translation id="6885760532393684712">directori</translation>
+<translation id="689129560213475294">colofó</translation>
<translation id="6934078000481955284">cita en bloc</translation>
<translation id="6941933287844615239">baixa els fitxers multimèdia</translation>
<translation id="6989848892321993519">Allarga aquest text fins a <ph name="MIN_CHARACTERS" /> caràcters o més (ara n'utilitzes 1).</translation>
<translation id="709897737746224366">Feu servir el format sol·licitat.</translation>
+<translation id="7139483182332611405">prefaci</translation>
<translation id="7223624360433298498">temps transcorregut</translation>
<translation id="7263440858009898357">Seleccioneu un element de la llista.</translation>
<translation id="727747134524199931">capçalera de columna</translation>
+<translation id="7353453495576941748">crèdit</translation>
<translation id="7364796246159120393">Tria un fitxer</translation>
<translation id="739024184232394898">Altres...</translation>
+<translation id="7405738980073107433">notes finals</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">pestanya</translation>
<translation id="7514365320538308">Baixa</translation>
+<translation id="7529102961911894712">enllaç d'entrada</translation>
+<translation id="7647456547678091388">consell</translation>
+<translation id="7661956066982048809">document gràfic</translation>
<translation id="7673697353781729403">Hores</translation>
+<translation id="7681220483256441252">índex</translation>
<translation id="7720026100085573005">temps restant</translation>
<translation id="7740016676195725605">deixa de mostrar subtítols ocults</translation>
<translation id="7740050170769002709">Contingut HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">No s'ha triat cap fitxer</translation>
<translation id="8053789581856978548">camp de text de la cerca</translation>
+<translation id="8057695513531652401">avís</translation>
+<translation id="8105797009065549151">referència de la nota</translation>
<translation id="8115662671911883373">comença a mostrar subtítols ocults</translation>
<translation id="8117451130807776954">Aquesta setmana</translation>
<translation id="819205353528511139">reprodueix la pel·lícula en mode de pantalla completa</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtítols</translation>
<translation id="835897206747267392">Valor no vàlid.</translation>
+<translation id="8415319359811155763">part</translation>
<translation id="8433900881053900389">barra d'eines</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fitxers</translation>
<translation id="8451268428117625855">Seleccioneu un fitxer.</translation>
<translation id="8461852803063341183">botó d'opció</translation>
+<translation id="8474886197722836894">dedicatòria</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minuts</translation>
<translation id="8541249477527128034">control de mitjans</translation>
+<translation id="8550857728288566671">símbol gràfic</translation>
<translation id="8583702881314752957">llista de definicions</translation>
<translation id="8597182159515967513">Encapçalament</translation>
+<translation id="860475260694818407">taula de continguts</translation>
<translation id="8613126697340063924">reproducció amb comandament</translation>
+<translation id="862370744433916922">subtítol</translation>
<translation id="8741316211671074806">Pantalla en pantalla</translation>
<translation id="8750798805984357768">Seleccioneu una d'aquestes opcions.</translation>
<translation id="8785498733064193001">inicia la reproducció</translation>
+<translation id="8808573423886751634">capítol</translation>
<translation id="8845239796550121995">S'està emetent al televisor</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8875657656876809964">Error de reproducció del vídeo</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Altres...</translation>
<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir del dia <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">nota al peu</translation>
<translation id="947831847158436616">cel·la</translation>
<translation id="966787709310836684">menú</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_cs.xtb b/chromium/content/app/strings/translations/content_strings_cs.xtb
index bc5dc6c1164..f037cfd0ffe 100644
--- a/chromium/content/app/strings/translations/content_strings_cs.xtb
+++ b/chromium/content/app/strings/translations/content_strings_cs.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">doplňkové</translation>
<translation id="1206619573307042055">běžící text</translation>
<translation id="1206693055195146388">posuvník</translation>
+<translation id="1211441953136645838">koncová poznámka</translation>
<translation id="1281252709823657822">dialogové okno</translation>
+<translation id="1335095011850992622">poděkování</translation>
<translation id="1342835525016946179">čl</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">oblast</translation>
<translation id="1591562245178063882">Tento měsíc</translation>
<translation id="1637811476055996098">Zvolit soubory</translation>
+<translation id="1650423536718072820">citace</translation>
<translation id="1729654308190250600">Vyplňte e-mailovou adresu.</translation>
<translation id="1758486001363313524">Jiné…</translation>
<translation id="1806710327868736751">dialog upozornění</translation>
<translation id="1821985195704844674">stromová mřížka</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">přehrát ve vzdáleném zařízení</translation>
+<translation id="1907737156431278478">příklad</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stav</translation>
<translation id="1938124657309484470">Datum musí být <ph name="MAXIMUM_DATE_OR_TIME" /> nebo dříve.</translation>
<translation id="1993104285338243655">Přepnuto na zrcadlení</translation>
<translation id="2060505056492490888">Znak <ph name="DOT" /> v doméně <ph name="INVALIDDOMAIN" /> není použitý správně.</translation>
<translation id="2148716181193084225">Dnes</translation>
+<translation id="2158401438286456825">seznam stránek</translation>
<translation id="2226276347425096477">Zkraťte prosím tento text na <ph name="MAX_CHARACTERS" /> znaků nebo méně. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týden, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Stopa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">zaškrtávací políčko</translation>
+<translation id="2311842470354187719">konec stránky</translation>
<translation id="2335594187091864976">výběr data a času</translation>
<translation id="248395913932153421">Den</translation>
<translation id="2507943997699731163">Vyplňte prosím toto pole.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">přehrát</translation>
<translation id="2613802280814924224">Zadejte platnou hodnotu. Nejbližší platná hodnota je <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Odeslat</translation>
+<translation id="2657045182931379222">grafický objekt</translation>
<translation id="2674318244760992338">zápatí</translation>
<translation id="2709516037105925701">Automatické vyplňování</translation>
<translation id="2723001399770238859">zvuk</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Prodlužte prosím tento text na <ph name="MIN_CHARACTERS" /> či více znaků. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
<translation id="383465348367842624">Část před znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
<translation id="3846214748874656680">Ukončit režim na celou obrazovku</translation>
+<translation id="3920932319529768807">závěr</translation>
<translation id="3924558731517983934">aplikace</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">posuvník</translation>
<translation id="4103419683916926126">Milisekundy</translation>
<translation id="4151657705144244502">obrázek</translation>
+<translation id="4193965531860883258">předmluva</translation>
<translation id="4201051445878709314">Zobrazit předchozí měsíc</translation>
<translation id="421884353938374759">výběr barev</translation>
<translation id="4248100235867064564">panel nabídky</translation>
<translation id="4254339807215791271">informace o obsahu</translation>
<translation id="4360991593054037559">Zadejte platnou hodnotu. Dvě nejbližší hodnoty jsou <ph name="VALID_VALUE_LOW" /> a <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Dotazy</translation>
<translation id="4413860115965805769">tlačítko nabídky</translation>
+<translation id="4446524499724042288">odkaz na glosář</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4597532268155981612">formulář</translation>
<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Část za znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">příloha</translation>
+<translation id="4742539557769756338">titulní strana</translation>
<translation id="4757246831282535685">panel karty</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Zadejte prosím číslo.</translation>
+<translation id="4912536737030637138">bibliografická položka</translation>
<translation id="4975562563186953947">Vybráno: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Zapnout zvuk</translation>
<translation id="49969490063480558">Zadejte část za znakem <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> není úplná.</translation>
<translation id="5034860022980953847">indikátor průběhu</translation>
+<translation id="5093189678851173835">nápis</translation>
<translation id="5117590920725113268">Zobrazit další měsíc</translation>
<translation id="512758898067543763">záhlaví řádku</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Toto video se přehrává v režimu obrazu v obraze</translation>
<translation id="5164977714490026579">Hodnota musí být větší nebo rovna <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Zadejte část před znakem <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> není úplná.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">zapnout zvuk</translation>
<translation id="561939826962581046">čas</translation>
<translation id="5630795885300617244">Dvojitým klepnutím na šipku vlevo nebo vpravo přeskočíte o 10 s</translation>
+<translation id="5631759159893697722">abstrakt</translation>
<translation id="5641012560118721995">pozastavit přehrávání</translation>
<translation id="5643186887447432888">tlačítko</translation>
<translation id="5677946354068040947">další možnosti</translation>
+<translation id="576709008726043716">úvod</translation>
<translation id="57838592816432529">Ztlumit</translation>
<translation id="5860033963881614850">Vypnuto</translation>
<translation id="588258955323874662">Celá obrazovka</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Rok</translation>
<translation id="6023896073578205740">seznam</translation>
<translation id="6101327004457443354">zapnout zvukovou stopu</translation>
+<translation id="6150588977291308318">bibliografie</translation>
<translation id="6164829606128959761">měřič</translation>
+<translation id="6166809985690652833">doslov</translation>
+<translation id="6213469881011901533">glosář</translation>
<translation id="6398862346408813489">Zobrazit panel pro výběr měsíců</translation>
<translation id="6404546809543547843">posuvník času zvuku</translation>
+<translation id="6453774872122745852">poděkování</translation>
<translation id="648732519525291180">výběr času</translation>
<translation id="6550675742724504774">Možnosti</translation>
-<translation id="6564313821541007458">Je aktivní režim obrazu v obraze</translation>
<translation id="658823671542763450">přejít do režimu celé obrazovky</translation>
<translation id="663493177488814956">zdroj</translation>
<translation id="6637586476836377253">protokol</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">popisek</translation>
<translation id="6790428901817661496">Přehrát</translation>
<translation id="6820355525329141109">Plugin se nepodařilo načíst.</translation>
+<translation id="6820615603175220800">bibliografický odkaz</translation>
<translation id="6843725295806269523">ztlumit</translation>
<translation id="6853785296079745596">skrýt titulky</translation>
<translation id="6885760532393684712">adresář</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">bloková citace</translation>
<translation id="6941933287844615239">stáhnout média</translation>
<translation id="6989848892321993519">Prodlužte prosím tento text na <ph name="MIN_CHARACTERS" /> či více znaků. (Aktuálně má 1 znak.)</translation>
<translation id="709897737746224366">Zadejte hodnotu, která odpovídá požadovanému formátu.</translation>
+<translation id="7139483182332611405">předmluva</translation>
<translation id="7223624360433298498">přehraný čas</translation>
<translation id="7263440858009898357">Vyberte prosím v seznamu některou položku.</translation>
<translation id="727747134524199931">záhlaví sloupce</translation>
+<translation id="7353453495576941748">poděkování</translation>
<translation id="7364796246159120393">Vybrat soubor</translation>
<translation id="739024184232394898">Jiné…</translation>
+<translation id="7405738980073107433">koncové poznámky</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">karta</translation>
<translation id="7514365320538308">Stáhnout</translation>
+<translation id="7529102961911894712">zpětný odkaz</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafický dokument</translation>
<translation id="7673697353781729403">Hodiny</translation>
+<translation id="7681220483256441252">rejstřík</translation>
<translation id="7720026100085573005">zbývající čas</translation>
<translation id="7740016676195725605">ukončit zobrazování titulků</translation>
<translation id="7740050170769002709">Obsah ve formátu HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">rozdělovač</translation>
<translation id="795667975304826397">Soubor nevybrán</translation>
<translation id="8053789581856978548">pole pro vyhledání textu</translation>
+<translation id="8057695513531652401">oznámení</translation>
+<translation id="8105797009065549151">odkaz na poznámku</translation>
<translation id="8115662671911883373">zahájit zobrazování titulků</translation>
<translation id="8117451130807776954">Tento týden</translation>
<translation id="819205353528511139">přehrát film v režimu celé obrazovky</translation>
<translation id="8199524924445686405">rrrr</translation>
<translation id="8284326494547611709">Titulky</translation>
<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="8415319359811155763">část</translation>
<translation id="8433900881053900389">lišta</translation>
<translation id="8444882422881193423">Počet souborů: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Vyberte prosím soubor.</translation>
<translation id="8461852803063341183">přepínač</translation>
+<translation id="8474886197722836894">věnování</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minuty</translation>
<translation id="8541249477527128034">ovládání médií</translation>
+<translation id="8550857728288566671">grafický symbol</translation>
<translation id="8583702881314752957">seznam definic</translation>
<translation id="8597182159515967513">záhlaví</translation>
+<translation id="860475260694818407">obsah</translation>
<translation id="8613126697340063924">ovládání vzdáleného přehrávání</translation>
+<translation id="862370744433916922">titulek</translation>
<translation id="8741316211671074806">Obraz v obraze</translation>
<translation id="8750798805984357768">Vyberte jednu z těchto možností.</translation>
<translation id="8785498733064193001">zahájit přehrávání</translation>
+<translation id="8808573423886751634">kapitola</translation>
<translation id="8845239796550121995">Odesílání do televize</translation>
<translation id="8851136666856101339">hlavní</translation>
<translation id="8875657656876809964">Chyba přehrávání videa</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Jiné…</translation>
<translation id="9138385573473225930">upozornění</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, začíná <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">poznámka pod čarou</translation>
<translation id="947831847158436616">buňka</translation>
<translation id="966787709310836684">nabídka</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_da.xtb b/chromium/content/app/strings/translations/content_strings_da.xtb
index b8a7ed0cf04..b2b772fcf80 100644
--- a/chromium/content/app/strings/translations/content_strings_da.xtb
+++ b/chromium/content/app/strings/translations/content_strings_da.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">supplerende</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">skyder</translation>
+<translation id="1211441953136645838">slutnote</translation>
<translation id="1281252709823657822">dialogboks</translation>
+<translation id="1335095011850992622">anerkendelser</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">område</translation>
<translation id="1591562245178063882">Denne måned</translation>
<translation id="1637811476055996098">Vælg filer</translation>
+<translation id="1650423536718072820">opmærksomhedsskabende citat</translation>
<translation id="1729654308190250600">Angiv en mailadresse, der ikke er tom.</translation>
<translation id="1758486001363313524">Andet...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">trægitter</translation>
<translation id="1822429046913737220">f.m./e.m.</translation>
<translation id="1832974991323546415">afspil på en enhed via fjernadgang</translation>
+<translation id="1907737156431278478">eksempel</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Værdien må ikke være senere end <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
<translation id="1993104285338243655">Ændret til spejling</translation>
<translation id="2060505056492490888">"<ph name="DOT" />" er placeret forkert i "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">I dag</translation>
+<translation id="2158401438286456825">sideliste</translation>
<translation id="2226276347425096477">Forkort denne tekst til <ph name="MAX_CHARACTERS" /> tegn eller færre (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="2247351761944213033">Uge <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Spor <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">afkrydsningsfelt</translation>
+<translation id="2311842470354187719">sideskift</translation>
<translation id="2335594187091864976">dato- og tidsvælger</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Udfyld dette felt.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">afspil</translation>
<translation id="2613802280814924224">Angiv en gyldig værdi. Den nærmeste gyldige værdi er <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Indsend</translation>
+<translation id="2657045182931379222">grafikobjekt</translation>
<translation id="2674318244760992338">sidefod</translation>
<translation id="2709516037105925701">AutoFyld</translation>
<translation id="2723001399770238859">lyd</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Forlæng denne tekst til <ph name="MIN_CHARACTERS" /> eller flere tegn (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="383465348367842624">Den del, der kommer før "<ph name="ATSIGN" />", må ikke indeholde "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Afslut fuld skærm</translation>
+<translation id="3920932319529768807">konklusion</translation>
<translation id="3924558731517983934">applikation</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">rullepanel</translation>
<translation id="4103419683916926126">Millisekunder</translation>
<translation id="4151657705144244502">grafik</translation>
+<translation id="4193965531860883258">forord</translation>
<translation id="4201051445878709314">Vis den foregående måned</translation>
<translation id="421884353938374759">farvevælger</translation>
<translation id="4248100235867064564">menulinje</translation>
<translation id="4254339807215791271">indholdsoplysninger</translation>
<translation id="4360991593054037559">Angiv en gyldig værdi. De to nærmeste gyldige værdier er <ph name="VALID_VALUE_LOW" /> og <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Spørgsmål og svar</translation>
<translation id="4413860115965805769">menuknap</translation>
+<translation id="4446524499724042288">reference på ordliste</translation>
<translation id="4522570452068850558">Detaljer</translation>
<translation id="4597532268155981612">formular</translation>
<translation id="4661075872484491155">træ</translation>
<translation id="4664250907885839816">Den del, der kommer efter "<ph name="ATSIGN" />", må ikke indeholde symbolet "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">bilag</translation>
+<translation id="4742539557769756338">forside</translation>
<translation id="4757246831282535685">fanepanel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">søg</translation>
<translation id="4812940957355064477">Angiv et nummer.</translation>
+<translation id="4912536737030637138">bibliografipost</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> er valgt</translation>
<translation id="4992066212339426712">Slå lyden til</translation>
<translation id="49969490063480558">Angiv den del, der kommer efter "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" er ufuldstændig.</translation>
<translation id="5034860022980953847">statusindikator</translation>
+<translation id="5093189678851173835">motto</translation>
<translation id="5117590920725113268">Vis næste måned</translation>
<translation id="512758898067543763">rækkeoverskrift</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Denne video afspilles som integreret billede</translation>
<translation id="5164977714490026579">Værdien skal være større end eller lig med <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Angiv den del, der kommer før "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" er ufuldstændig.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">slå lyd til</translation>
<translation id="561939826962581046">tidspunkt</translation>
<translation id="5630795885300617244">Tryk to gange til venstre eller højre for at springe ti sekunder over</translation>
+<translation id="5631759159893697722">abstrakt</translation>
<translation id="5641012560118721995">pause</translation>
<translation id="5643186887447432888">knap</translation>
<translation id="5677946354068040947">flere valgmuligheder</translation>
+<translation id="576709008726043716">indledning</translation>
<translation id="57838592816432529">Slå lyden fra</translation>
<translation id="5860033963881614850">Fra</translation>
<translation id="588258955323874662">Fuld skærm</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">År</translation>
<translation id="6023896073578205740">listefelt</translation>
<translation id="6101327004457443354">slå lydspor til</translation>
+<translation id="6150588977291308318">bibliografi</translation>
<translation id="6164829606128959761">måler</translation>
+<translation id="6166809985690652833">efterskrift</translation>
+<translation id="6213469881011901533">ordliste</translation>
<translation id="6398862346408813489">Vis panel til valg af måned</translation>
<translation id="6404546809543547843">afspilningsbjælke for lyd</translation>
+<translation id="6453774872122745852">tak</translation>
<translation id="648732519525291180">tidsvælger</translation>
<translation id="6550675742724504774">Valgmuligheder</translation>
-<translation id="6564313821541007458">I øjeblikket i tilstanden Integreret billede</translation>
<translation id="658823671542763450">åbn fuld skærm</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">værktøjstip</translation>
<translation id="6790428901817661496">Afspil</translation>
<translation id="6820355525329141109">Pluginnet kunne ikke indlæses.</translation>
+<translation id="6820615603175220800">reference i bibliografi</translation>
<translation id="6843725295806269523">slå lyden fra</translation>
<translation id="6853785296079745596">skjul undertekster</translation>
<translation id="6885760532393684712">indeks</translation>
+<translation id="689129560213475294">slutskrift</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">download medier</translation>
<translation id="6989848892321993519">Forlæng denne tekst til <ph name="MIN_CHARACTERS" /> eller flere tegn (du bruger i øjeblikket ét tegn).</translation>
<translation id="709897737746224366">Find et match til det anmodede format.</translation>
+<translation id="7139483182332611405">forord</translation>
<translation id="7223624360433298498">forløbet tid</translation>
<translation id="7263440858009898357">Vælg et punkt på listen.</translation>
<translation id="727747134524199931">kolonneoverskrift</translation>
+<translation id="7353453495576941748">anerkendelse</translation>
<translation id="7364796246159120393">Vælg fil</translation>
<translation id="739024184232394898">Andet...</translation>
+<translation id="7405738980073107433">slutnoter</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">fane</translation>
<translation id="7514365320538308">Download</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafikdokument</translation>
<translation id="7673697353781729403">Timer</translation>
+<translation id="7681220483256441252">indeks</translation>
<translation id="7720026100085573005">resterende tid</translation>
<translation id="7740016676195725605">stop visning af undertekster</translation>
<translation id="7740050170769002709">HTML-indhold</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">splitter</translation>
<translation id="795667975304826397">Der er ikke valgt nogen fil</translation>
<translation id="8053789581856978548">tekstfelt til søgning</translation>
+<translation id="8057695513531652401">meddelelse</translation>
+<translation id="8105797009065549151">reference i noter</translation>
<translation id="8115662671911883373">start visning af undertekster</translation>
<translation id="8117451130807776954">Denne uge</translation>
<translation id="819205353528511139">afspil film i fuld skærm</translation>
<translation id="8199524924445686405">åååå</translation>
<translation id="8284326494547611709">Undertekster</translation>
<translation id="835897206747267392">Ugyldig værdi.</translation>
+<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">værktøjslinje</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
<translation id="8451268428117625855">Vælg en fil.</translation>
<translation id="8461852803063341183">alternativknap</translation>
+<translation id="8474886197722836894">dedikation</translation>
+<translation id="8531739829932800271">rettelser</translation>
<translation id="8534579021159131403">Minutter</translation>
<translation id="8541249477527128034">mediekontrol</translation>
+<translation id="8550857728288566671">grafiksymbol</translation>
<translation id="8583702881314752957">liste over definitioner</translation>
<translation id="8597182159515967513">overskrift</translation>
+<translation id="860475260694818407">indholdsfortegnelse</translation>
<translation id="8613126697340063924">kontrollér afspilning via fjernadgang</translation>
+<translation id="862370744433916922">undertitel</translation>
<translation id="8741316211671074806">Integreret billede</translation>
<translation id="8750798805984357768">Vælg en af disse muligheder.</translation>
<translation id="8785498733064193001">start afspilning</translation>
+<translation id="8808573423886751634">kapitel</translation>
<translation id="8845239796550121995">Caster nu til dit fjernsyn</translation>
<translation id="8851136666856101339">hovd</translation>
<translation id="8875657656876809964">Fejl under videoafspilning</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Andet...</translation>
<translation id="9138385573473225930">underretning</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, med start <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">fodnote</translation>
<translation id="947831847158436616">celle</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_de.xtb b/chromium/content/app/strings/translations/content_strings_de.xtb
index 5a7c5bef4e7..72ba8f81710 100644
--- a/chromium/content/app/strings/translations/content_strings_de.xtb
+++ b/chromium/content/app/strings/translations/content_strings_de.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">ergänzend</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">Schieberegler</translation>
+<translation id="1211441953136645838">Endnote</translation>
<translation id="1281252709823657822">Kleines Fenster</translation>
+<translation id="1335095011850992622">Mitwirkende</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">Banner</translation>
<translation id="1589122976691792535">Region</translation>
<translation id="1591562245178063882">Aktueller Monat</translation>
<translation id="1637811476055996098">Dateien auswählen</translation>
+<translation id="1650423536718072820">Textzitat</translation>
<translation id="1729654308190250600">Geben Sie eine E-Mail-Adresse ein.</translation>
<translation id="1758486001363313524">Andere...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">Baumraster</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">auf Remote-Gerät wiedergeben</translation>
+<translation id="1907737156431278478">Beispiel</translation>
<translation id="1921819250265091946">tt</translation>
<translation id="1930711995431081526">Status</translation>
<translation id="1938124657309484470">Verwenden Sie <ph name="MAXIMUM_DATE_OR_TIME" /> oder einen früheren Wert.</translation>
<translation id="1993104285338243655">Zu 1:1-Wiedergabe gewechselt</translation>
<translation id="2060505056492490888">Das Punktzeichen "<ph name="DOT" />" steht in "<ph name="INVALIDDOMAIN" />" an einer falschen Stelle.</translation>
<translation id="2148716181193084225">Heute</translation>
+<translation id="2158401438286456825">Seitenliste</translation>
<translation id="2226276347425096477">Kürzen Sie diesen Text auf max. <ph name="MAX_CHARACTERS" /> Zeichen. Zurzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
<translation id="2247351761944213033">Woche <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Titel <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">Kästchen</translation>
+<translation id="2311842470354187719">Seitenumbruch</translation>
<translation id="2335594187091864976">Datums- und Uhrzeitauswahl</translation>
<translation id="248395913932153421">Tag</translation>
<translation id="2507943997699731163">Füllen Sie dieses Feld aus.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">Wiedergeben</translation>
<translation id="2613802280814924224">Geben Sie einen gültigen Wert ein. Der nächstliegende gültige Wert ist <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Senden</translation>
+<translation id="2657045182931379222">Grafikobjekt</translation>
<translation id="2674318244760992338">Fußzeile</translation>
<translation id="2709516037105925701">AutoFill</translation>
<translation id="2723001399770238859">Audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Verlängern Sie diesen Text auf mindestens <ph name="MIN_CHARACTERS" /> Zeichen. Derzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
<translation id="383465348367842624">Vor dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
<translation id="3846214748874656680">Vollbildmodus beenden</translation>
+<translation id="3920932319529768807">Fazit</translation>
<translation id="3924558731517983934">Anwendung</translation>
+<translation id="3944740393230681990">Prolog</translation>
<translation id="3960700977367013758">Bildlaufleiste</translation>
<translation id="4103419683916926126">Millisekunden</translation>
<translation id="4151657705144244502">Grafik</translation>
+<translation id="4193965531860883258">Vorwort</translation>
<translation id="4201051445878709314">Vorherigen Monat anzeigen</translation>
<translation id="421884353938374759">color picker</translation>
<translation id="4248100235867064564">Menüleiste</translation>
<translation id="4254339807215791271">Inhaltsinformationen</translation>
<translation id="4360991593054037559">Geben Sie einen gültigen Wert ein. Die zwei nächstliegenden gültigen Werte sind <ph name="VALID_VALUE_LOW" /> und <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Fragen und Antworten</translation>
<translation id="4413860115965805769">Menüschaltfläche</translation>
+<translation id="4446524499724042288">Glossarreferenz</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4597532268155981612">Formular</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Nach dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
+<translation id="4668956016107839909">Anhang</translation>
+<translation id="4742539557769756338">Titelseite</translation>
<translation id="4757246831282535685">Tabsteuerfeld</translation>
<translation id="4763480195061959176">Video</translation>
<translation id="479989351350248267">Suchen</translation>
<translation id="4812940957355064477">Geben Sie eine Nummer ein.</translation>
+<translation id="4912536737030637138">Bibliografieeintrag</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ausgewählt</translation>
<translation id="4992066212339426712">Stummschaltung aufheben</translation>
<translation id="49969490063480558">Geben Sie etwas nach dem <ph name="ATSIGN" />-Zeichen ein. Die Angabe "<ph name="INVALIDADDRESS" />" ist unvollständig.</translation>
<translation id="5034860022980953847">Fortschrittsanzeige</translation>
+<translation id="5093189678851173835">Motto</translation>
<translation id="5117590920725113268">Nächsten Monat anzeigen</translation>
<translation id="512758898067543763">Zeilenüberschrift</translation>
+<translation id="5143125788380636750">Epilog</translation>
+<translation id="5153163864850940242">Dieses Video wird im Bild-in-Bild-Modus wiedergegeben</translation>
<translation id="5164977714490026579">Wert muss größer als oder gleich <ph name="MINIMUM" /> sein.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Geben Sie etwas vor dem <ph name="ATSIGN" />-Zeichen ein. Die Angabe "<ph name="INVALIDADDRESS" />" ist unvollständig.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">Ton an</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Tippen Sie links oder rechts doppelt, um 10 s zu überspringen</translation>
+<translation id="5631759159893697722">Zusammenfassung</translation>
<translation id="5641012560118721995">Wiedergabe anhalten</translation>
<translation id="5643186887447432888">Schaltfläche</translation>
<translation id="5677946354068040947">weitere Optionen</translation>
+<translation id="576709008726043716">Einleitung</translation>
<translation id="57838592816432529">Stummschalten</translation>
<translation id="5860033963881614850">Aus</translation>
<translation id="588258955323874662">Vollbild</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Jahr</translation>
<translation id="6023896073578205740">Listenfeld</translation>
<translation id="6101327004457443354">Ton anschalten</translation>
+<translation id="6150588977291308318">Bibliografie</translation>
<translation id="6164829606128959761">Messinstrument</translation>
+<translation id="6166809985690652833">Nachwort</translation>
+<translation id="6213469881011901533">Glossar</translation>
<translation id="6398862346408813489">Auswahlbereich für Monatsanzeige</translation>
<translation id="6404546809543547843">Audio-Zeitachse</translation>
+<translation id="6453774872122745852">Danksagung</translation>
<translation id="648732519525291180">Uhrzeitauswahl</translation>
<translation id="6550675742724504774">Optionen</translation>
-<translation id="6564313821541007458">Jetzt im Bild-in-Bild-Modus</translation>
<translation id="658823671542763450">Vollbildmodus aktivieren</translation>
<translation id="663493177488814956">Feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">Kurzinfo</translation>
<translation id="6790428901817661496">Wiedergabe</translation>
<translation id="6820355525329141109">Plug-in konnte nicht geladen werden.</translation>
+<translation id="6820615603175220800">Bibliografiereferenz</translation>
<translation id="6843725295806269523">Stumm</translation>
<translation id="6853785296079745596">Untertitel ausblenden</translation>
<translation id="6885760532393684712">Verzeichnis</translation>
+<translation id="689129560213475294">Kolophon</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">Medien herunterladen</translation>
<translation id="6989848892321993519">Verlängern Sie diesen Text auf mindestens <ph name="MIN_CHARACTERS" /> Zeichen. Derzeit verwenden Sie 1 Zeichen.</translation>
<translation id="709897737746224366">Ihre Eingabe muss mit dem geforderten Format übereinstimmen.</translation>
+<translation id="7139483182332611405">Vorbemerkung</translation>
<translation id="7223624360433298498">Vergangene Zeit</translation>
<translation id="7263440858009898357">Wählen Sie ein Element in der Liste aus.</translation>
<translation id="727747134524199931">Spaltenüberschrift</translation>
+<translation id="7353453495576941748">Danksagung</translation>
<translation id="7364796246159120393">Datei auswählen</translation>
<translation id="739024184232394898">Andere...</translation>
+<translation id="7405738980073107433">Endnoten</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Herunterladen</translation>
+<translation id="7529102961911894712">Rückverweis</translation>
+<translation id="7647456547678091388">Tipp</translation>
+<translation id="7661956066982048809">Grafikdokument</translation>
<translation id="7673697353781729403">Stunden</translation>
+<translation id="7681220483256441252">Index</translation>
<translation id="7720026100085573005">Verbleibende Zeit</translation>
<translation id="7740016676195725605">Keine Untertitel mehr anzeigen</translation>
<translation id="7740050170769002709">HTML-Inhalte</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">Teilungsfunktion</translation>
<translation id="795667975304826397">Keine ausgewählt</translation>
<translation id="8053789581856978548">Feld für den Suchtext</translation>
+<translation id="8057695513531652401">Bemerkung</translation>
+<translation id="8105797009065549151">Hinweisreferenz</translation>
<translation id="8115662671911883373">Untertitel ab sofort anzeigen</translation>
<translation id="8117451130807776954">Diese Woche</translation>
<translation id="819205353528511139">Film im Vollbildmodus ansehen</translation>
<translation id="8199524924445686405">jjjj</translation>
<translation id="8284326494547611709">Untertitel</translation>
<translation id="835897206747267392">Ungültiger Wert.</translation>
+<translation id="8415319359811155763">Teil</translation>
<translation id="8433900881053900389">Symbolleiste</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> Dateien</translation>
<translation id="8451268428117625855">Wählen Sie eine Datei aus.</translation>
<translation id="8461852803063341183">Optionsfeld</translation>
+<translation id="8474886197722836894">Widmung</translation>
+<translation id="8531739829932800271">Druckfehler</translation>
<translation id="8534579021159131403">Minuten</translation>
<translation id="8541249477527128034">Mediensteuerung</translation>
+<translation id="8550857728288566671">Grafiksymbol</translation>
<translation id="8583702881314752957">Definitionsliste</translation>
<translation id="8597182159515967513">Kopfzeile</translation>
+<translation id="860475260694818407">Inhaltsverzeichnis</translation>
<translation id="8613126697340063924">Remote-Wiedergabe steuern</translation>
+<translation id="862370744433916922">Untertitel</translation>
<translation id="8741316211671074806">Bild im Bild</translation>
<translation id="8750798805984357768">Wählen Sie eine dieser Optionen aus.</translation>
<translation id="8785498733064193001">Wiedergabe starten</translation>
+<translation id="8808573423886751634">Kapitel</translation>
<translation id="8845239796550121995">Wird gerade auf Ihren Fernseher gestreamt</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Videowiedergabefehler</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Andere...</translation>
<translation id="9138385573473225930">Benachrichtigung</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> ab dem <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">Fußnote</translation>
<translation id="947831847158436616">Zelle</translation>
<translation id="966787709310836684">Menü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_el.xtb b/chromium/content/app/strings/translations/content_strings_el.xtb
index 5d27f5de436..e80b9556f8b 100644
--- a/chromium/content/app/strings/translations/content_strings_el.xtb
+++ b/chromium/content/app/strings/translations/content_strings_el.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">συμπληρωματικό</translation>
<translation id="1206619573307042055">μαρκίζα</translation>
<translation id="1206693055195146388">ρυθμιστικό</translation>
+<translation id="1211441953136645838">σημείωση τέλους</translation>
<translation id="1281252709823657822">παράθυρο διαλόγου</translation>
+<translation id="1335095011850992622">συντελεστές</translation>
<translation id="1342835525016946179">άρθρο</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">περιοχή</translation>
<translation id="1591562245178063882">Αυτόν το μήνα</translation>
<translation id="1637811476055996098">Επιλογή αρχείων</translation>
+<translation id="1650423536718072820">ελκυστική φράση</translation>
<translation id="1729654308190250600">Καταχωρίστε μια διεύθυνση ηλεκτρονικού ταχυδρομείου.</translation>
<translation id="1758486001363313524">Άλλες…</translation>
<translation id="1806710327868736751">παράθυρο διαλόγου ειδοποιήσεων</translation>
<translation id="1821985195704844674">πλέγμα δέντρου</translation>
<translation id="1822429046913737220">Π.Μ./Μ.Μ.</translation>
<translation id="1832974991323546415">αναπαραγωγή σε απομακρυσμένη συσκευή</translation>
+<translation id="1907737156431278478">παράδειγμα</translation>
<translation id="1921819250265091946">ηη</translation>
<translation id="1930711995431081526">κατάσταση</translation>
<translation id="1938124657309484470">Η τιμή πρέπει να είναι <ph name="MAXIMUM_DATE_OR_TIME" /> ή προγενέστερη.</translation>
<translation id="1993104285338243655">Εναλλαγή σε κατοπτρισμό</translation>
<translation id="2060505056492490888">Το σύμβολο "<ph name="DOT" />" χρησιμοποιείται σε λάθος θέση στη διεύθυνση "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Σήμερα</translation>
+<translation id="2158401438286456825">λίστα σελίδων</translation>
<translation id="2226276347425096477">Κάντε πιο σύντομο αυτό το κείμενο ώστε να έχει το πολύ <ph name="MAX_CHARACTERS" /> χαρακτήρες (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH" /> χαρακτήρες).</translation>
<translation id="2247351761944213033">Εβδομάδα <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Κομμάτι <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">πλαίσιο ελέγχου</translation>
+<translation id="2311842470354187719">αλλαγή σελίδας</translation>
<translation id="2335594187091864976">εργαλείο επιλογής ημερομηνίας και ώρας</translation>
<translation id="248395913932153421">Ημέρα</translation>
<translation id="2507943997699731163">Συμπληρώστε αυτό το πεδίο.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">αναπαραγωγή</translation>
<translation id="2613802280814924224">Καταχωρίστε μια έγκυρη τιμή. Η κοντινότερη έγκυρη τιμή είναι <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Υποβολή</translation>
+<translation id="2657045182931379222">αντικείμενο γραφικών</translation>
<translation id="2674318244760992338">υποσέλιδο</translation>
<translation id="2709516037105925701">Αυτόματη συμπλήρωση</translation>
<translation id="2723001399770238859">ήχος</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Αυξήστε την έκταση αυτού του κειμένου στους <ph name="MIN_CHARACTERS" /> χαρακτήρες ή περισσότερο (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH" /> χαρακτήρες).</translation>
<translation id="383465348367842624">Το τμήμα της διεύθυνσης πριν το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Έξοδος από πλήρη οθόνη</translation>
+<translation id="3920932319529768807">συμπέρασμα</translation>
<translation id="3924558731517983934">εφαρμογή</translation>
+<translation id="3944740393230681990">πρόλογος</translation>
<translation id="3960700977367013758">γραμμή κύλισης</translation>
<translation id="4103419683916926126">Χιλιοστά του δευτερολέπτου</translation>
<translation id="4151657705144244502">γραφικό</translation>
+<translation id="4193965531860883258">εισαγωγή</translation>
<translation id="4201051445878709314">Εμφάνιση προηγούμενου μήνα</translation>
<translation id="421884353938374759">επιλογέας χρώματος</translation>
<translation id="4248100235867064564">γραμμή μενού</translation>
<translation id="4254339807215791271">πληροφορίες περιεχομένου</translation>
<translation id="4360991593054037559">Καταχωρίστε μια έγκυρη τιμή. Οι δύο πιο κοντινές έγκυρες τιμές είναι <ph name="VALID_VALUE_LOW" /> και <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Ερωτήσεις και απαντήσεις</translation>
<translation id="4413860115965805769">κουμπί μενού</translation>
+<translation id="4446524499724042288">αναφορά στο γλωσσάρι</translation>
<translation id="4522570452068850558">Λεπτομέρειες</translation>
<translation id="4597532268155981612">φόρμα</translation>
<translation id="4661075872484491155">δέντρο</translation>
<translation id="4664250907885839816">Το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">παράρτημα</translation>
+<translation id="4742539557769756338">εξώφυλλο</translation>
<translation id="4757246831282535685">παράθυρο καρτέλας</translation>
<translation id="4763480195061959176">βίντεο</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Εισαγάγετε έναν αριθμό.</translation>
+<translation id="4912536737030637138">βιβλιογραφική καταχώριση</translation>
<translation id="4975562563186953947">Επιλέχτηκαν <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Κατάργηση σίγασης</translation>
<translation id="49969490063480558">Καταχωρίστε το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />". Η διεύθυνση "<ph name="INVALIDADDRESS" />" δεν είναι πλήρης.</translation>
<translation id="5034860022980953847">ένδειξη προόδου</translation>
+<translation id="5093189678851173835">επιγραφή</translation>
<translation id="5117590920725113268">Εμφάνιση επόμενου μήνα</translation>
<translation id="512758898067543763">κεφαλίδα σειράς</translation>
+<translation id="5143125788380636750">επίλογος</translation>
+<translation id="5153163864850940242">Η αναπαραγωγή αυτού του βίντεο γίνεται σε λειτουργία Picture-in-Picture</translation>
<translation id="5164977714490026579">Η τιμή πρέπει να είναι μεγαλύτερη ή ίση του <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Καταχωρίστε το τμήμα της διεύθυνσης πριν το σύμβολο "<ph name="ATSIGN" />". Η διεύθυνση "<ph name="INVALIDADDRESS" />" δεν είναι πλήρης.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">κατάργηση σίγασης</translation>
<translation id="561939826962581046">ώρα</translation>
<translation id="5630795885300617244">Πατήστε δύο φορές αριστερά ή δεξιά, για να παραβλέψετε 10 δευτ.</translation>
+<translation id="5631759159893697722">περίληψη</translation>
<translation id="5641012560118721995">παύση αναπαραγωγής</translation>
<translation id="5643186887447432888">κουμπί</translation>
<translation id="5677946354068040947">περισσότερες επιλογές</translation>
+<translation id="576709008726043716">εισαγωγή</translation>
<translation id="57838592816432529">Σίγαση</translation>
<translation id="5860033963881614850">Απενεργοποιημένη</translation>
<translation id="588258955323874662">Πλήρης οθόνη</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Έτος</translation>
<translation id="6023896073578205740">πλαίσιο λίστας</translation>
<translation id="6101327004457443354">κατάργηση σίγασης ήχου</translation>
+<translation id="6150588977291308318">βιβλιογραφία</translation>
<translation id="6164829606128959761">μετρητής</translation>
+<translation id="6166809985690652833">επίλογος</translation>
+<translation id="6213469881011901533">γλωσσάρι</translation>
<translation id="6398862346408813489">Εμφάνιση παραθύρου επιλογής μήνα</translation>
<translation id="6404546809543547843">δείκτης χρόνου ήχου</translation>
+<translation id="6453774872122745852">ευχαριστίες</translation>
<translation id="648732519525291180">εργαλείο επιλογής ώρας</translation>
<translation id="6550675742724504774">Επιλογές</translation>
-<translation id="6564313821541007458">Η αναπαραγωγή γίνεται σε λειτουργία παράθεσης εικόνων</translation>
<translation id="658823671542763450">ενεργοποίηση πλήρους οθόνης</translation>
<translation id="663493177488814956">ροή</translation>
<translation id="6637586476836377253">αρχείο καταγραφής</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">επεξήγηση εργαλείου</translation>
<translation id="6790428901817661496">Αναπαραγωγή</translation>
<translation id="6820355525329141109">Δεν είναι δυνατή η φόρτωση της προσθήκης.</translation>
+<translation id="6820615603175220800">βιβλιογραφική αναφορά</translation>
<translation id="6843725295806269523">σίγαση</translation>
<translation id="6853785296079745596">απόκρυψη υπότιτλων</translation>
<translation id="6885760532393684712">κατάλογος</translation>
+<translation id="689129560213475294">εκδοτικό σήμα</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">λήψη μέσων</translation>
<translation id="6989848892321993519">Αυξήστε την έκταση αυτού του κειμένου στους <ph name="MIN_CHARACTERS" /> χαρακτήρες ή περισσότερο (αυτήν τη στιγμή χρησιμοποιείτε 1 χαρακτήρα).</translation>
<translation id="709897737746224366">Αντιστοιχίστε τη ζητούμενη μορφή.</translation>
+<translation id="7139483182332611405">πρόλογος</translation>
<translation id="7223624360433298498">χρόνος που παρήλθε</translation>
<translation id="7263440858009898357">Επιλέξτε ένα στοιχείο από τη λίστα.</translation>
<translation id="727747134524199931">κεφαλίδα στήλης</translation>
+<translation id="7353453495576941748">εύσημα</translation>
<translation id="7364796246159120393">Επιλογή αρχείου</translation>
<translation id="739024184232394898">Άλλες…</translation>
+<translation id="7405738980073107433">σημειώσεις τέλους</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">καρτέλα</translation>
<translation id="7514365320538308">Λήψη</translation>
+<translation id="7529102961911894712">σύνδεσμος επιστροφής</translation>
+<translation id="7647456547678091388">συμβουλή</translation>
+<translation id="7661956066982048809">έγγραφο γραφικών</translation>
<translation id="7673697353781729403">Ώρες</translation>
+<translation id="7681220483256441252">ευρετήριο</translation>
<translation id="7720026100085573005">χρόνος που απομένει</translation>
<translation id="7740016676195725605">διακοπή προβολής υπότιτλων</translation>
<translation id="7740050170769002709">Περιεχόμενο HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">διαχωριστής</translation>
<translation id="795667975304826397">Δεν επιλέχθηκε κανένα αρχείο.</translation>
<translation id="8053789581856978548">αναζήτηση πεδίου κειμένου</translation>
+<translation id="8057695513531652401">ειδοποίηση</translation>
+<translation id="8105797009065549151">παραπομπή</translation>
<translation id="8115662671911883373">έναρξη προβολής υπότιτλων</translation>
<translation id="8117451130807776954">Αυτήν την εβδομάδα</translation>
<translation id="819205353528511139">αναπαραγωγή ταινίας σε λειτουργία πλήρους οθόνης</translation>
<translation id="8199524924445686405">εεεε</translation>
<translation id="8284326494547611709">Υπότιτλοι</translation>
<translation id="835897206747267392">Μη έγκυρη τιμή.</translation>
+<translation id="8415319359811155763">τμήμα</translation>
<translation id="8433900881053900389">γραμμή εργαλείων</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> αρχεία</translation>
<translation id="8451268428117625855">Επιλέξτε ένα αρχείο.</translation>
<translation id="8461852803063341183">κουμπί επιλογής</translation>
+<translation id="8474886197722836894">αφιέρωση</translation>
+<translation id="8531739829932800271">τυπογραφικά λάθη</translation>
<translation id="8534579021159131403">Λεπτά</translation>
<translation id="8541249477527128034">έλεγχος μέσων</translation>
+<translation id="8550857728288566671">σύμβολο γραφικών</translation>
<translation id="8583702881314752957">λίστα ορισμών</translation>
<translation id="8597182159515967513">επικεφαλίδα</translation>
+<translation id="860475260694818407">πίνακας περιεχομένων</translation>
<translation id="8613126697340063924">έλεγχος απομακρυσμένης αναπαραγωγής</translation>
+<translation id="862370744433916922">υπότιτλος</translation>
<translation id="8741316211671074806">Picture-in-picture</translation>
<translation id="8750798805984357768">Ορίστε μία από αυτές τις επιλογές.</translation>
<translation id="8785498733064193001">έναρξη αναπαραγωγής</translation>
+<translation id="8808573423886751634">κεφάλαιο</translation>
<translation id="8845239796550121995">Γίνεται μετάδοση στην TV</translation>
<translation id="8851136666856101339">κύριο</translation>
<translation id="8875657656876809964">Σφάλμα αναπαραγωγής βίντεο</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Άλλες…</translation>
<translation id="9138385573473225930">ειδοποίηση</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, από τις <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">υποσημείωση</translation>
<translation id="947831847158436616">κελί</translation>
<translation id="966787709310836684">μενού</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_en-GB.xtb b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
index 615e3a4c5f0..30e75ecd7ae 100644
--- a/chromium/content/app/strings/translations/content_strings_en-GB.xtb
+++ b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementary</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">slider</translation>
+<translation id="1211441953136645838">endnote</translation>
<translation id="1281252709823657822">dialogue</translation>
+<translation id="1335095011850992622">credits</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">region</translation>
<translation id="1591562245178063882">This month</translation>
<translation id="1637811476055996098">Choose Files</translation>
+<translation id="1650423536718072820">pullquote</translation>
<translation id="1729654308190250600">Please enter a non-empty email address.</translation>
<translation id="1758486001363313524">Other...</translation>
<translation id="1806710327868736751">alert_dialogue</translation>
<translation id="1821985195704844674">tree grid</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">play on remote device</translation>
+<translation id="1907737156431278478">example</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Value must be <ph name="MAXIMUM_DATE_OR_TIME" /> or earlier.</translation>
<translation id="1993104285338243655">Switched to mirroring</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' is used at a wrong position in '<ph name="INVALIDDOMAIN" />'.</translation>
<translation id="2148716181193084225">Today</translation>
+<translation id="2158401438286456825">page list</translation>
<translation id="2226276347425096477">Please shorten this text to <ph name="MAX_CHARACTERS" /> characters or less (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">Tick box</translation>
+<translation id="2311842470354187719">page break</translation>
<translation id="2335594187091864976">date and time picker</translation>
<translation id="248395913932153421">Day</translation>
<translation id="2507943997699731163">Please fill in this field.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">play</translation>
<translation id="2613802280814924224">Please enter a valid value. The nearest valid value is <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Submit</translation>
+<translation id="2657045182931379222">graphics object</translation>
<translation id="2674318244760992338">footer</translation>
<translation id="2709516037105925701">Auto-fill</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Please lengthen this text to <ph name="MIN_CHARACTERS" /> characters or more (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
<translation id="383465348367842624">A part followed by '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="3846214748874656680">Exit full screen</translation>
+<translation id="3920932319529768807">conclusion</translation>
<translation id="3924558731517983934">application</translation>
+<translation id="3944740393230681990">prologue</translation>
<translation id="3960700977367013758">scroll bar</translation>
<translation id="4103419683916926126">Milliseconds</translation>
<translation id="4151657705144244502">graphic</translation>
+<translation id="4193965531860883258">foreword</translation>
<translation id="4201051445878709314">Show previous month</translation>
<translation id="421884353938374759">colour picker</translation>
<translation id="4248100235867064564">menu bar</translation>
<translation id="4254339807215791271">content info</translation>
<translation id="4360991593054037559">Please enter a valid value. The two nearest valid values are <ph name="VALID_VALUE_LOW" /> and <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
<translation id="4413860115965805769">menu button</translation>
+<translation id="4446524499724042288">glossary reference</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4597532268155981612">form</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A part following '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">appendix</translation>
+<translation id="4742539557769756338">cover</translation>
<translation id="4757246831282535685">tab panel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Please enter a number.</translation>
+<translation id="4912536737030637138">bibliography entry</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selected</translation>
<translation id="4992066212339426712">Unmute</translation>
<translation id="49969490063480558">Please enter a part following '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is incomplete.</translation>
<translation id="5034860022980953847">progress indicator</translation>
+<translation id="5093189678851173835">epigraph</translation>
<translation id="5117590920725113268">Show next month</translation>
<translation id="512758898067543763">row header</translation>
+<translation id="5143125788380636750">epilogue</translation>
+<translation id="5153163864850940242">This video is playing in Picture-in-Picture</translation>
<translation id="5164977714490026579">Value must be greater than or equal to <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Please enter a part followed by '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is incomplete.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">un-mute</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Double-tap left or right to skip 10s</translation>
+<translation id="5631759159893697722">abstract</translation>
<translation id="5641012560118721995">pause playback</translation>
<translation id="5643186887447432888">button</translation>
<translation id="5677946354068040947">more options</translation>
+<translation id="576709008726043716">introduction</translation>
<translation id="57838592816432529">Mute</translation>
<translation id="5860033963881614850">Off</translation>
<translation id="588258955323874662">Full screen</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Year</translation>
<translation id="6023896073578205740">list box</translation>
<translation id="6101327004457443354">un-mute audio track</translation>
+<translation id="6150588977291308318">bibliography</translation>
<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">afterword</translation>
+<translation id="6213469881011901533">glossary</translation>
<translation id="6398862346408813489">Show month selection panel</translation>
<translation id="6404546809543547843">audio time scrubber</translation>
+<translation id="6453774872122745852">acknowledgements</translation>
<translation id="648732519525291180">time picker</translation>
<translation id="6550675742724504774">Options</translation>
-<translation id="6564313821541007458">Now in picture-in-picture mode</translation>
<translation id="658823671542763450">enter full screen</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">tooltip</translation>
<translation id="6790428901817661496">Play</translation>
<translation id="6820355525329141109">Couldn't load plug-in.</translation>
+<translation id="6820615603175220800">bibliography reference</translation>
<translation id="6843725295806269523">mute</translation>
<translation id="6853785296079745596">hide closed captions</translation>
<translation id="6885760532393684712">directory</translation>
+<translation id="689129560213475294">colophon</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">download media</translation>
<translation id="6989848892321993519">Please lengthen this text to <ph name="MIN_CHARACTERS" /> characters or more (you are currently using 1 character).</translation>
<translation id="709897737746224366">Please match the format requested.</translation>
+<translation id="7139483182332611405">preface</translation>
<translation id="7223624360433298498">elapsed time</translation>
<translation id="7263440858009898357">Please select an item in the list.</translation>
<translation id="727747134524199931">column header</translation>
+<translation id="7353453495576941748">credit</translation>
<translation id="7364796246159120393">Choose file</translation>
<translation id="739024184232394898">Other...</translation>
+<translation id="7405738980073107433">endnotes</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Download</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">graphics document</translation>
<translation id="7673697353781729403">Hours</translation>
+<translation id="7681220483256441252">index</translation>
<translation id="7720026100085573005">remaining time</translation>
<translation id="7740016676195725605">stop displaying closed captions</translation>
<translation id="7740050170769002709">HTML content</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">splitter</translation>
<translation id="795667975304826397">No file chosen</translation>
<translation id="8053789581856978548">search text field</translation>
+<translation id="8057695513531652401">notice</translation>
+<translation id="8105797009065549151">note reference</translation>
<translation id="8115662671911883373">start displaying closed captions</translation>
<translation id="8117451130807776954">This week</translation>
<translation id="819205353528511139">play film in full screen mode</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Captions</translation>
<translation id="835897206747267392">Invalid value.</translation>
+<translation id="8415319359811155763">part</translation>
<translation id="8433900881053900389">toolbar</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> files</translation>
<translation id="8451268428117625855">Please select a file.</translation>
<translation id="8461852803063341183">radio button</translation>
+<translation id="8474886197722836894">dedication</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minutes</translation>
<translation id="8541249477527128034">media control</translation>
+<translation id="8550857728288566671">graphics symbol</translation>
<translation id="8583702881314752957">definition list</translation>
<translation id="8597182159515967513">heading</translation>
+<translation id="860475260694818407">table of contents</translation>
<translation id="8613126697340063924">control remote playback</translation>
+<translation id="862370744433916922">subtitle</translation>
<translation id="8741316211671074806">Picture-in-picture</translation>
<translation id="8750798805984357768">Please select one of these options.</translation>
<translation id="8785498733064193001">begin playback</translation>
+<translation id="8808573423886751634">chapter</translation>
<translation id="8845239796550121995">Now casting to your TV</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Video playback error</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Other...</translation>
<translation id="9138385573473225930">alert</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, starting on <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">footnote</translation>
<translation id="947831847158436616">cell</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_es-419.xtb b/chromium/content/app/strings/translations/content_strings_es-419.xtb
index 78a087575a5..b65c8e31e1c 100644
--- a/chromium/content/app/strings/translations/content_strings_es-419.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es-419.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementario</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">control deslizante</translation>
+<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">artículo</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">región</translation>
<translation id="1591562245178063882">Este mes</translation>
<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="1650423536718072820">cita inicial</translation>
<translation id="1729654308190250600">Ingresa una dirección de correo electrónico que no esté vacía.</translation>
<translation id="1758486001363313524">Otra...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">cuadrícula de árbol</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">jugar en el dispositivo remoto</translation>
+<translation id="1907737156431278478">ejemplo</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estado</translation>
<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
<translation id="1993104285338243655">Se cambió a duplicación</translation>
<translation id="2060505056492490888">El signo "<ph name="DOT" />" está colocado en una posición incorrecta en "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Hoy</translation>
+<translation id="2158401438286456825">listado de páginas</translation>
<translation id="2226276347425096477">Acorta este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente estás usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casilla de verificación</translation>
+<translation id="2311842470354187719">salto de página</translation>
<translation id="2335594187091864976">selector de fecha y hora</translation>
<translation id="248395913932153421">Día</translation>
<translation id="2507943997699731163">Completa este campo</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">reproducir</translation>
<translation id="2613802280814924224">Ingresa un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Enviar</translation>
+<translation id="2657045182931379222">objeto gráfico</translation>
<translation id="2674318244760992338">pie de página</translation>
<translation id="2709516037105925701">Autocompletar</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Alarga el texto a <ph name="MIN_CHARACTERS" /> o más caracteres (actualmente, usas <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="383465348367842624">El texto antes del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Salir de pantalla completa</translation>
+<translation id="3920932319529768807">conclusión</translation>
<translation id="3924558731517983934">aplicación</translation>
+<translation id="3944740393230681990">prólogo</translation>
<translation id="3960700977367013758">barra de desplazamiento</translation>
<translation id="4103419683916926126">Milisegundos</translation>
<translation id="4151657705144244502">gráfico</translation>
+<translation id="4193965531860883258">prefacio</translation>
<translation id="4201051445878709314">Mostrar el mes anterior</translation>
<translation id="421884353938374759">selector de color</translation>
<translation id="4248100235867064564">barra de menús</translation>
<translation id="4254339807215791271">información del contenido</translation>
<translation id="4360991593054037559">Ingresa un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW" /> y <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Preguntas y respuestas</translation>
<translation id="4413860115965805769">botón de menú</translation>
+<translation id="4446524499724042288">referencia de glosario</translation>
<translation id="4522570452068850558">Detalles</translation>
<translation id="4597532268155981612">formulario</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto después del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apéndice</translation>
+<translation id="4742539557769756338">portada</translation>
<translation id="4757246831282535685">panel de pestañas</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Debes ingresar un número.</translation>
+<translation id="4912536737030637138">entrada de bibliografía</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> elementos seleccionados</translation>
<translation id="4992066212339426712">Dejar de silenciar</translation>
<translation id="49969490063480558">Ingresa texto después del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
<translation id="5034860022980953847">indicador de progreso</translation>
+<translation id="5093189678851173835">epígrafe</translation>
<translation id="5117590920725113268">Mostrar el mes siguiente</translation>
<translation id="512758898067543763">encabezado de fila</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5153163864850940242">Este video se reproduce en el modo de pantalla en pantalla</translation>
<translation id="5164977714490026579">El valor debe ser mayor de o igual a <ph name="MINIMUM" /></translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Ingresa texto antes del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">desactivar silencio</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Presiona dos veces a la derecha o izquierda para omitir 10 s</translation>
+<translation id="5631759159893697722">resumen</translation>
<translation id="5641012560118721995">pausar reproducción</translation>
<translation id="5643186887447432888">botón</translation>
<translation id="5677946354068040947">más opciones</translation>
+<translation id="576709008726043716">introducción</translation>
<translation id="57838592816432529">Silenciar</translation>
<translation id="5860033963881614850">Desactivado</translation>
<translation id="588258955323874662">Pantalla completa</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Año</translation>
<translation id="6023896073578205740">cuadro de lista</translation>
<translation id="6101327004457443354">desactivar silencio de la pista de audio</translation>
+<translation id="6150588977291308318">bibliografía</translation>
<translation id="6164829606128959761">medidor</translation>
+<translation id="6166809985690652833">posfacio</translation>
+<translation id="6213469881011901533">glosario</translation>
<translation id="6398862346408813489">Mostrar el panel de selección de meses</translation>
<translation id="6404546809543547843">control deslizante de duración del audio</translation>
+<translation id="6453774872122745852">reconocimientos</translation>
<translation id="648732519525291180">selector de hora</translation>
<translation id="6550675742724504774">Opciones</translation>
-<translation id="6564313821541007458">Ahora en modo de pantalla en pantalla</translation>
<translation id="658823671542763450">ingresar a pantalla completa</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">rgstr</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">información sobre la herramienta</translation>
<translation id="6790428901817661496">Reproducir</translation>
<translation id="6820355525329141109">No se pudo cargar el complemento.</translation>
+<translation id="6820615603175220800">referencia bibliográfica</translation>
<translation id="6843725295806269523">silencio</translation>
<translation id="6853785296079745596">ocultar los subtítulos</translation>
<translation id="6885760532393684712">directorio</translation>
+<translation id="689129560213475294">colofón</translation>
<translation id="6934078000481955284">bloque entrecomillado</translation>
<translation id="6941933287844615239">descargar medios</translation>
<translation id="6989848892321993519">Extiende este texto para que tenga <ph name="MIN_CHARACTERS" /> caracteres o más (actualmente usas 1 carácter).</translation>
<translation id="709897737746224366">Haz coincidir el formato solicitado.</translation>
+<translation id="7139483182332611405">prefacio</translation>
<translation id="7223624360433298498">tiempo transcurrido</translation>
<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
<translation id="727747134524199931">encabezado de columna</translation>
+<translation id="7353453495576941748">crédito</translation>
<translation id="7364796246159120393">Seleccionar archivo</translation>
<translation id="739024184232394898">Otra...</translation>
+<translation id="7405738980073107433">notas finales</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Descargar</translation>
+<translation id="7529102961911894712">retrovínculo</translation>
+<translation id="7647456547678091388">sugerencia</translation>
+<translation id="7661956066982048809">documento gráfico</translation>
<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
<translation id="7720026100085573005">tiempo restante</translation>
<translation id="7740016676195725605">dejar de mostrar subtítulos</translation>
<translation id="7740050170769002709">Contenido HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">separador</translation>
<translation id="795667975304826397">No se eligió archivo</translation>
<translation id="8053789581856978548">campo de texto de búsqueda</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">nota de referencia</translation>
<translation id="8115662671911883373">empezar a mostrar subtítulos</translation>
<translation id="8117451130807776954">Esta semana</translation>
<translation id="819205353528511139">reproducir la película en modo de pantalla completa</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtítulos</translation>
<translation id="835897206747267392">Valor no válido.</translation>
+<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de herramientas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
<translation id="8451268428117625855">Selecciona un archivo.</translation>
<translation id="8461852803063341183">botón de selección</translation>
+<translation id="8474886197722836894">dedicatoria</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">control de medios</translation>
+<translation id="8550857728288566671">símbolo gráfico</translation>
<translation id="8583702881314752957">lista de definiciones</translation>
<translation id="8597182159515967513">cabecera</translation>
+<translation id="860475260694818407">índice</translation>
<translation id="8613126697340063924">controlar la reproducción remota</translation>
+<translation id="862370744433916922">subtítulo</translation>
<translation id="8741316211671074806">Pantalla en pantalla</translation>
<translation id="8750798805984357768">Selecciona una de estas opciones.</translation>
<translation id="8785498733064193001">comenzar la reproducción</translation>
+<translation id="8808573423886751634">capítulo</translation>
<translation id="8845239796550121995">Transmitiendo a tu TV</translation>
<translation id="8851136666856101339">ppal</translation>
<translation id="8875657656876809964">Error de reproducción de video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Otra...</translation>
<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir del <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">nota a pie de página</translation>
<translation id="947831847158436616">celda</translation>
<translation id="966787709310836684">menú</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_es.xtb b/chromium/content/app/strings/translations/content_strings_es.xtb
index ee4b514dd41..01abb818539 100644
--- a/chromium/content/app/strings/translations/content_strings_es.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementario</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">control deslizante</translation>
+<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">cuadro de diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">artículo</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">región</translation>
<translation id="1591562245178063882">Este mes</translation>
<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="1650423536718072820">cita</translation>
<translation id="1729654308190250600">Introduce una dirección de correo electrónico que no esté vacía.</translation>
<translation id="1758486001363313524">Otra...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">cuadrícula de árbol</translation>
<translation id="1822429046913737220">A.M./P.M.</translation>
<translation id="1832974991323546415">reproducir en dispositivo remoto</translation>
+<translation id="1907737156431278478">ejemplo</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estado</translation>
<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
<translation id="1993104285338243655">Se ha cambiado a proyección</translation>
<translation id="2060505056492490888">El signo "<ph name="DOT" />" está colocado en una posición incorrecta en la dirección "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Hoy</translation>
+<translation id="2158401438286456825">lista de páginas</translation>
<translation id="2226276347425096477">Reduce la longitud de este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres)</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casilla de verificación</translation>
+<translation id="2311842470354187719">salto de página</translation>
<translation id="2335594187091864976">selector de fecha y hora</translation>
<translation id="248395913932153421">Día</translation>
<translation id="2507943997699731163">Completa este campo</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">reproducir</translation>
<translation id="2613802280814924224">Introduce un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Enviar</translation>
+<translation id="2657045182931379222">objeto gráfico</translation>
<translation id="2674318244760992338">pie de página</translation>
<translation id="2709516037105925701">Autocompletar</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Aumenta la longitud del texto a <ph name="MIN_CHARACTERS" /> caracteres como mínimo (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="383465348367842624">El texto seguido del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Salir de pantalla completa</translation>
+<translation id="3920932319529768807">conclusión</translation>
<translation id="3924558731517983934">aplicación</translation>
+<translation id="3944740393230681990">prólogo</translation>
<translation id="3960700977367013758">barra de desplazamiento</translation>
<translation id="4103419683916926126">Millisegundos</translation>
<translation id="4151657705144244502">gráfico</translation>
+<translation id="4193965531860883258">prefacio</translation>
<translation id="4201051445878709314">Mostrar mes anterior</translation>
<translation id="421884353938374759">selector de color</translation>
<translation id="4248100235867064564">barra de menús</translation>
<translation id="4254339807215791271">información del contenido</translation>
<translation id="4360991593054037559">Introduce un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW" /> y <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Preguntas</translation>
<translation id="4413860115965805769">botón de menú</translation>
+<translation id="4446524499724042288">referencia de glosario</translation>
<translation id="4522570452068850558">Detalles</translation>
<translation id="4597532268155981612">formulario</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto detrás del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apéndice</translation>
+<translation id="4742539557769756338">portada</translation>
<translation id="4757246831282535685">panel de pestaña</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">buscar</translation>
<translation id="4812940957355064477">Debes introducir un número.</translation>
+<translation id="4912536737030637138">entrada bibliográfica</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> seleccionados</translation>
<translation id="4992066212339426712">Activar sonido</translation>
<translation id="49969490063480558">Introduce texto detrás del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
<translation id="5034860022980953847">indicador de progreso</translation>
+<translation id="5093189678851173835">epígrafe</translation>
<translation id="5117590920725113268">Mostrar mes siguiente</translation>
<translation id="512758898067543763">encabezado de fila</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5153163864850940242">Este vídeo se está reproduciendo en modo imagen en imagen</translation>
<translation id="5164977714490026579">El valor debe ser superior o igual a <ph name="MINIMUM" /></translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Introduce texto seguido del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">activar sonido</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Toca dos veces a la derecha o a la izquierda para saltar 10 segundos</translation>
+<translation id="5631759159893697722">resumen</translation>
<translation id="5641012560118721995">pausar reproducción</translation>
<translation id="5643186887447432888">botón</translation>
<translation id="5677946354068040947">más opciones</translation>
+<translation id="576709008726043716">introducción</translation>
<translation id="57838592816432529">Silenciar</translation>
<translation id="5860033963881614850">No</translation>
<translation id="588258955323874662">Pantalla completa</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Año</translation>
<translation id="6023896073578205740">cuadro de lista</translation>
<translation id="6101327004457443354">activar sonido de la pista de audio</translation>
+<translation id="6150588977291308318">bibliografía</translation>
<translation id="6164829606128959761">medidor</translation>
+<translation id="6166809985690652833">epílogo</translation>
+<translation id="6213469881011901533">glosario</translation>
<translation id="6398862346408813489">Mostrar panel para seleccionar el mes</translation>
<translation id="6404546809543547843">control deslizante de duración de audio</translation>
+<translation id="6453774872122745852">agradecimientos</translation>
<translation id="648732519525291180">selector de hora</translation>
<translation id="6550675742724504774">Configuración</translation>
-<translation id="6564313821541007458">Modo de imagen en imagen</translation>
<translation id="658823671542763450">activar pantalla completa</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">registro</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">descripción emergente</translation>
<translation id="6790428901817661496">Reproducir</translation>
<translation id="6820355525329141109">No se ha podido cargar el complemento.</translation>
+<translation id="6820615603175220800">referencia bibliográfica</translation>
<translation id="6843725295806269523">silenciar</translation>
<translation id="6853785296079745596">ocultar subtítulos</translation>
<translation id="6885760532393684712">directorio</translation>
+<translation id="689129560213475294">colofón</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">descargar archivos multimedia</translation>
<translation id="6989848892321993519">Aumenta la longitud de este texto a <ph name="MIN_CHARACTERS" /> caracteres o más (actualmente, el texto tiene 1 carácter).</translation>
<translation id="709897737746224366">Utiliza un formato que coincida con el solicitado</translation>
+<translation id="7139483182332611405">prefacio</translation>
<translation id="7223624360433298498">tiempo transcurrido</translation>
<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
<translation id="727747134524199931">encabezado de columna</translation>
+<translation id="7353453495576941748">crédito</translation>
<translation id="7364796246159120393">Seleccionar archivo</translation>
<translation id="739024184232394898">Otra...</translation>
+<translation id="7405738980073107433">notas finales</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tabulador</translation>
<translation id="7514365320538308">Descargar</translation>
+<translation id="7529102961911894712">enlace de retroceso</translation>
+<translation id="7647456547678091388">consejo</translation>
+<translation id="7661956066982048809">documento gráfico</translation>
<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
<translation id="7720026100085573005">tiempo restante</translation>
<translation id="7740016676195725605">dejar de mostrar subtítulos</translation>
<translation id="7740050170769002709">Contenido HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">Ningún archivo seleccionado</translation>
<translation id="8053789581856978548">campo para buscar texto</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">referencia de nota</translation>
<translation id="8115662671911883373">iniciar la visualización de subtítulos</translation>
<translation id="8117451130807776954">Esta semana</translation>
<translation id="819205353528511139">reproducir la película en modo de pantalla completa</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtítulos</translation>
<translation id="835897206747267392">Valor no válido</translation>
+<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de herramientas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
<translation id="8451268428117625855">Selecciona un archivo</translation>
<translation id="8461852803063341183">botón de selección</translation>
+<translation id="8474886197722836894">dedicatoria</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">control de medios</translation>
+<translation id="8550857728288566671">símbolo gráfico</translation>
<translation id="8583702881314752957">lista de definiciones</translation>
<translation id="8597182159515967513">cabecera</translation>
+<translation id="860475260694818407">índice</translation>
<translation id="8613126697340063924">reproducción de control remoto</translation>
+<translation id="862370744433916922">subtítulo</translation>
<translation id="8741316211671074806">Imagen en imagen</translation>
<translation id="8750798805984357768">Selecciona una de estas opciones</translation>
<translation id="8785498733064193001">iniciar reproducción</translation>
+<translation id="8808573423886751634">capítulo</translation>
<translation id="8845239796550121995">Se está enviando contenido a tu TV</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8875657656876809964">No se puede reproducir el vídeo</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Otra...</translation>
<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir del <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">nota al pie</translation>
<translation id="947831847158436616">celda</translation>
<translation id="966787709310836684">menú</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_et.xtb b/chromium/content/app/strings/translations/content_strings_et.xtb
index 33cf5d25364..c5ea1a2fef5 100644
--- a/chromium/content/app/strings/translations/content_strings_et.xtb
+++ b/chromium/content/app/strings/translations/content_strings_et.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">täiendav</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">liugur</translation>
+<translation id="1211441953136645838">järelmärkus</translation>
<translation id="1281252709823657822">dialoog</translation>
+<translation id="1335095011850992622">tiitrid</translation>
<translation id="1342835525016946179">artikkel</translation>
<translation id="1359897965706325498">bänner</translation>
<translation id="1589122976691792535">piirkond</translation>
<translation id="1591562245178063882">See kuu</translation>
<translation id="1637811476055996098">Vali failid</translation>
+<translation id="1650423536718072820">tsitaat</translation>
<translation id="1729654308190250600">Sisestage mittetühi e-posti aadress.</translation>
<translation id="1758486001363313524">Muu ...</translation>
<translation id="1806710327868736751">hoiatusdialoog</translation>
<translation id="1821985195704844674">puuruudustik</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">kaugseadmes esitamine</translation>
+<translation id="1907737156431278478">näide</translation>
<translation id="1921819250265091946">pp</translation>
<translation id="1930711995431081526">olek</translation>
<translation id="1938124657309484470">Väärtus peab olema <ph name="MAXIMUM_DATE_OR_TIME" /> või varasem.</translation>
<translation id="1993104285338243655">Lülitatud peegeldamisele</translation>
<translation id="2060505056492490888">Tähist „<ph name="DOT" />” on aadressis „<ph name="INVALIDDOMAIN" />” valesti kasutatud.</translation>
<translation id="2148716181193084225">Täna</translation>
+<translation id="2158401438286456825">lehtede loend</translation>
<translation id="2226276347425096477">Lühendage seda teksti <ph name="MAX_CHARACTERS" /> tähemärgini või rohkem (praegu kasutate <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
<translation id="2247351761944213033">Nädal <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. lugu</translation>
<translation id="2291999235780842123">märkeruut</translation>
+<translation id="2311842470354187719">leheküljepiir</translation>
<translation id="2335594187091864976">kuupäeva ja kellaaja valija</translation>
<translation id="248395913932153421">päev</translation>
<translation id="2507943997699731163">Täitke see väli.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">esitus</translation>
<translation id="2613802280814924224">Sisestage kehtiv väärtus. Lähim kehtiv väärtus on <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Esita</translation>
+<translation id="2657045182931379222">graafika objekt</translation>
<translation id="2674318244760992338">jalus</translation>
<translation id="2709516037105925701">Automaatne täitmine</translation>
<translation id="2723001399770238859">heli</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Pikendage teksti vähemalt <ph name="MIN_CHARACTERS" /> tähemärgini (kasutate praegu <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
<translation id="383465348367842624">Märgile „<ph name="ATSIGN" />” eelnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
<translation id="3846214748874656680">Täisekraanilt väljumine</translation>
+<translation id="3920932319529768807">kokkuvõte</translation>
<translation id="3924558731517983934">rakendus</translation>
+<translation id="3944740393230681990">proloog</translation>
<translation id="3960700977367013758">kerimisriba</translation>
<translation id="4103419683916926126">Millisekundid</translation>
<translation id="4151657705144244502">graafika</translation>
+<translation id="4193965531860883258">eessõna</translation>
<translation id="4201051445878709314">Eelmise kuu kuvamine</translation>
<translation id="421884353938374759">värvivalija</translation>
<translation id="4248100235867064564">menüüriba</translation>
<translation id="4254339807215791271">sisu teave</translation>
<translation id="4360991593054037559">Sisestage kehtiv väärtus. Kaks lähimat kehtivat väärtust on <ph name="VALID_VALUE_LOW" /> ja <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Küsimused ja vastused</translation>
<translation id="4413860115965805769">menüünupp</translation>
+<translation id="4446524499724042288">sõnastiku viide</translation>
<translation id="4522570452068850558">Üksikasjad</translation>
<translation id="4597532268155981612">vorm</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Märgile „<ph name="ATSIGN" />” järgnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4668956016107839909">lisa</translation>
+<translation id="4742539557769756338">kaas</translation>
<translation id="4757246831282535685">vahelehepaneel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">otsing</translation>
<translation id="4812940957355064477">Sisestage arv.</translation>
+<translation id="4912536737030637138">bibliograafia kirje</translation>
<translation id="4975562563186953947">Valitud on <ph name="SELECTED_COUNT" /> üksust</translation>
<translation id="4992066212339426712">Tühista vaigistus</translation>
<translation id="49969490063480558">Sisestage märgile „<ph name="ATSIGN" />” järgnev osa. Aadress „<ph name="INVALIDADDRESS" />” pole täielik.</translation>
<translation id="5034860022980953847">edenemise näidik</translation>
+<translation id="5093189678851173835">epigraaf</translation>
<translation id="5117590920725113268">Järgmise kuu kuvamine</translation>
<translation id="512758898067543763">rea päis</translation>
+<translation id="5143125788380636750">epiloog</translation>
+<translation id="5153163864850940242">Videot esitatakse pilt-pildis-režiimis</translation>
<translation id="5164977714490026579">Väärtus peab olema suurem või võrdne <ph name="MINIMUM" />-ga.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Sisestage märgile „<ph name="ATSIGN" />” eelnev osa. Aadress „<ph name="INVALIDADDRESS" />” pole täielik.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">vaigistuse tühistamine</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">10 sekundi võrra kerimiseks topeltpuudutage vasakul või paremal</translation>
+<translation id="5631759159893697722">abstraktne</translation>
<translation id="5641012560118721995">taasesituse peatamine</translation>
<translation id="5643186887447432888">nupp</translation>
<translation id="5677946354068040947">rohkem valikuid</translation>
+<translation id="576709008726043716">sissejuhatus</translation>
<translation id="57838592816432529">Vaigista</translation>
<translation id="5860033963881614850">Väljas</translation>
<translation id="588258955323874662">Täisekraan</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Aasta</translation>
<translation id="6023896073578205740">loendikast</translation>
<translation id="6101327004457443354">heliraja vaigistamise tühistamine</translation>
+<translation id="6150588977291308318">bibliograafia</translation>
<translation id="6164829606128959761">mõõdik</translation>
+<translation id="6166809985690652833">järelsõna</translation>
+<translation id="6213469881011901533">sõnastik</translation>
<translation id="6398862346408813489">Kuu valikupaneeli kuvamine</translation>
<translation id="6404546809543547843">heli ajamõõdik</translation>
+<translation id="6453774872122745852">tunnustused</translation>
<translation id="648732519525291180">kellaaja valija</translation>
<translation id="6550675742724504774">Valikud</translation>
-<translation id="6564313821541007458">Nüüd režiimis Pilt pildis</translation>
<translation id="658823671542763450">kuvamine täisekraanil</translation>
<translation id="663493177488814956">voog</translation>
<translation id="6637586476836377253">logi</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">tööriistavihje</translation>
<translation id="6790428901817661496">Esita</translation>
<translation id="6820355525329141109">Pistikprogrammi ei saanud laadida.</translation>
+<translation id="6820615603175220800">kasutatud kirjandus</translation>
<translation id="6843725295806269523">vaigista</translation>
<translation id="6853785296079745596">subtiitrite peitmine</translation>
<translation id="6885760532393684712">kataloog</translation>
+<translation id="689129560213475294">kolofoon</translation>
<translation id="6934078000481955284">plokktsitaat</translation>
<translation id="6941933287844615239">laadi meedia alla</translation>
<translation id="6989848892321993519">Pikendage teksti vähemalt <ph name="MIN_CHARACTERS" /> tähemärgini (kasutate praegu ühte tähemärki).</translation>
<translation id="709897737746224366">Vastendage nõutav vorming.</translation>
+<translation id="7139483182332611405">eessõna</translation>
<translation id="7223624360433298498">möödunud aeg</translation>
<translation id="7263440858009898357">Valige loendist element.</translation>
<translation id="727747134524199931">veeru päis</translation>
+<translation id="7353453495576941748">autor(id)</translation>
<translation id="7364796246159120393">Vali fail</translation>
<translation id="739024184232394898">Muu ...</translation>
+<translation id="7405738980073107433">järelmärkused</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">Tabulaator</translation>
<translation id="7514365320538308">Laadi alla</translation>
+<translation id="7529102961911894712">tagasilink</translation>
+<translation id="7647456547678091388">nõuanne</translation>
+<translation id="7661956066982048809">graafika dokument</translation>
<translation id="7673697353781729403">Tunnid</translation>
+<translation id="7681220483256441252">register</translation>
<translation id="7720026100085573005">järelejäänud aeg</translation>
<translation id="7740016676195725605">subtiitrite kuvamise peatamine</translation>
<translation id="7740050170769002709">HTML-sisu</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">jagaja</translation>
<translation id="795667975304826397">Pole valitud</translation>
<translation id="8053789581856978548">otsinguteksti väli</translation>
+<translation id="8057695513531652401">teatis</translation>
+<translation id="8105797009065549151">märkuse viide</translation>
<translation id="8115662671911883373">subtiitrite kuvamise alustamine</translation>
<translation id="8117451130807776954">See nädal</translation>
<translation id="819205353528511139">video esitus täisekraani režiimis</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtiitrid</translation>
<translation id="835897206747267392">Kehtetu väärtus.</translation>
+<translation id="8415319359811155763">osa</translation>
<translation id="8433900881053900389">tööriistariba</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
<translation id="8451268428117625855">Valige üks fail.</translation>
<translation id="8461852803063341183">raadionupp</translation>
+<translation id="8474886197722836894">pühendus</translation>
+<translation id="8531739829932800271">veaparandused</translation>
<translation id="8534579021159131403">Minutid</translation>
<translation id="8541249477527128034">meedia juhtimine</translation>
+<translation id="8550857728288566671">graafika sümbol</translation>
<translation id="8583702881314752957">definitsioonide loend</translation>
<translation id="8597182159515967513">pealkiri</translation>
+<translation id="860475260694818407">sisukord</translation>
<translation id="8613126697340063924">kaugesituse juhtimine</translation>
+<translation id="862370744433916922">alapealkiri</translation>
<translation id="8741316211671074806">Pilt pildis</translation>
<translation id="8750798805984357768">Tehke üks nendest valikutest.</translation>
<translation id="8785498733064193001">taasesituse alustamine</translation>
+<translation id="8808573423886751634">peatükk</translation>
<translation id="8845239796550121995">Kantakse nüüd üle telerisse</translation>
<translation id="8851136666856101339">pea</translation>
<translation id="8875657656876809964">Video taasesituse viga</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Muu ...</translation>
<translation id="9138385573473225930">hoiatus</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> alates kuupäevast <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">allmärkus</translation>
<translation id="947831847158436616">lahter</translation>
<translation id="966787709310836684">menüü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fa.xtb b/chromium/content/app/strings/translations/content_strings_fa.xtb
index e28aa3f0514..5f84dfcb4fd 100644
--- a/chromium/content/app/strings/translations/content_strings_fa.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fa.xtb
@@ -5,33 +5,39 @@
<translation id="1020833440720551630">بیصداکردن تراک صوتی</translation>
<translation id="10623998915015855">دکمه تغییر حالت</translation>
<translation id="1088086359088493902">ثانیه</translation>
-<translation id="1171774979989969504">لطفاً یک نشانی رایانامه وارد کنید.</translation>
+<translation id="1171774979989969504">لطفاً یک نشانی ایمیل وارد کنید.</translation>
<translation id="1178581264944972037">مکث</translation>
<translation id="1188858454923323853">تکمیلی</translation>
<translation id="1206619573307042055">نوشتار متحرک روی صفحه</translation>
<translation id="1206693055195146388">لغزنده</translation>
+<translation id="1211441953136645838">ته‌نویس</translation>
<translation id="1281252709823657822">کادر گفتگو</translation>
+<translation id="1335095011850992622">دست‌اندرکاران</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">برنما</translation>
<translation id="1589122976691792535">منطقه</translation>
<translation id="1591562245178063882">این ماه</translation>
<translation id="1637811476055996098">انتخاب فایل‌ها</translation>
-<translation id="1729654308190250600">لطفاً یک نشانی رایانامه غیرخالی وارد کنید.</translation>
+<translation id="1650423536718072820">نقل‌قول</translation>
+<translation id="1729654308190250600">لطفاً یک نشانی ایمیل غیرخالی وارد کنید.</translation>
<translation id="1758486001363313524">موارد دیگر...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">شبکه درختی</translation>
<translation id="1822429046913737220">ق.ظ/ب.ظ</translation>
<translation id="1832974991323546415">پخش در دستگاه راه دور</translation>
+<translation id="1907737156431278478">مثال</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">وضعیت</translation>
<translation id="1938124657309484470">مقدار باید <ph name="MAXIMUM_DATE_OR_TIME" /> یا قبل از آن باشد.</translation>
<translation id="1993104285338243655">به نمایش صفحه‌نمایش روی دستگاه دیگر تغییر یافت</translation>
<translation id="2060505056492490888">«<ph name="DOT" />» در «<ph name="INVALIDDOMAIN" />» در محل اشتباهی قرار دارد.</translation>
<translation id="2148716181193084225">امروز</translation>
+<translation id="2158401438286456825">فهرست صفحه</translation>
<translation id="2226276347425096477">لطفاً این متن را به اندازه <ph name="MAX_CHARACTERS" /> نویسه یا کمتر کوتاه کنید (شما در حال حاضر از <ph name="CURRENT_LENGTH" /> نویسه استفاده می‌کنید).</translation>
<translation id="2247351761944213033">هفته <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
<translation id="2277199496770840904">آهنگ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">کادر تأیید</translation>
+<translation id="2311842470354187719">جداساز صفحه</translation>
<translation id="2335594187091864976">انتخابگر تاریخ و زمان</translation>
<translation id="248395913932153421">روز</translation>
<translation id="2507943997699731163">لطفاً این قسمت را تکمیل کنید.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">پخش</translation>
<translation id="2613802280814924224">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقدار معتبر <ph name="VALID_VALUE" /> است.</translation>
<translation id="2653659639078652383">ارائه</translation>
+<translation id="2657045182931379222">شیء گرافیکی</translation>
<translation id="2674318244760992338">پانویس</translation>
<translation id="2709516037105925701">تکمیل خودکار</translation>
<translation id="2723001399770238859">صدا</translation>
@@ -47,7 +54,7 @@
<translation id="2759744352195237655">دکمه بازشو</translation>
<translation id="2761667185364618470">درصورتی‌که می‌خواهید ادامه دهید، این کادر را انتخاب کنید.</translation>
<translation id="2896972712917208084">گروه رادیویی</translation>
-<translation id="2908441821576996758">لطفاً لیستی از آدرس‌های رایانامه که با کاما از هم جدا شده‌اند را وارد کنید.</translation>
+<translation id="2908441821576996758">لطفاً لیستی از آدرس‌های ایمیل که با کاما از هم جدا شده‌اند را وارد کنید.</translation>
<translation id="2940813599313844715">شیء</translation>
<translation id="2942448076852699108">محتوای برجسته شده</translation>
<translation id="3040011195152428237">پیوند</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">لطفاً این نوشتار را به <ph name="MIN_CHARACTERS" /> نویسه یا بیشتر افزایش دهید (درحال حاضر از <ph name="CURRENT_LENGTH" /> نویسه استفاده می‌کنید).</translation>
<translation id="383465348367842624">قسمت قبل از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
<translation id="3846214748874656680">خروج از حالت تمام صفحه</translation>
+<translation id="3920932319529768807">نتیجه‌گیری</translation>
<translation id="3924558731517983934">برنامه</translation>
+<translation id="3944740393230681990">گفتار آغازین</translation>
<translation id="3960700977367013758">نوار پیمایش</translation>
<translation id="4103419683916926126">میلی‌ ثانیه</translation>
<translation id="4151657705144244502">گرافیک</translation>
+<translation id="4193965531860883258">پیش‌گفتار</translation>
<translation id="4201051445878709314">نمایش ماه قبلی</translation>
<translation id="421884353938374759">انتخابگر رنگ</translation>
<translation id="4248100235867064564">نوار منو</translation>
<translation id="4254339807215791271">اطلاعات محتوا</translation>
<translation id="4360991593054037559">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقادیر معتبر <ph name="VALID_VALUE_LOW" /> و <ph name="VALID_VALUE_HIGHER" /> هستند.</translation>
+<translation id="4384583879834880242">پرسش و پاسخ</translation>
<translation id="4413860115965805769">دکمه منو</translation>
+<translation id="4446524499724042288">مرجع واژه‌نامه</translation>
<translation id="4522570452068850558">جزئیات</translation>
<translation id="4597532268155981612">فرم</translation>
<translation id="4661075872484491155">درخت</translation>
<translation id="4664250907885839816">قسمت بعد از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
+<translation id="4668956016107839909">ضمیمه</translation>
+<translation id="4742539557769756338">جلد</translation>
<translation id="4757246831282535685">پانل برگه</translation>
<translation id="4763480195061959176">ویدئو</translation>
<translation id="479989351350248267">جستجو</translation>
<translation id="4812940957355064477">لطفاً شماره‌ای را وارد کنید.</translation>
+<translation id="4912536737030637138">ورودی فهرست منابع</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> انتخاب شد</translation>
<translation id="4992066212339426712">باصدا کردن</translation>
<translation id="49969490063480558">لطفاً قسمت بعد از «<ph name="ATSIGN" />» را وارد کنید. «<ph name="INVALIDADDRESS" />» ناقص است.</translation>
<translation id="5034860022980953847">نشانگر پیشرفت</translation>
+<translation id="5093189678851173835">نقل‌قول آغازین</translation>
<translation id="5117590920725113268">نمایش ماه بعدی</translation>
<translation id="512758898067543763">عنوان ردیف</translation>
+<translation id="5143125788380636750">گفتار پایانی</translation>
+<translation id="5153163864850940242">این ویدیو درحال پخش شدن در حالت «تصویر در تصویر» است</translation>
<translation id="5164977714490026579">مقدار باید بیشتر یا مساوی با <ph name="MINIMUM" /> باشد.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> پتابایت</translation>
<translation id="5307600278924710095">لطفاً قسمت قبل از «<ph name="ATSIGN" />» را وارد کنید. «<ph name="INVALIDADDRESS" />» ناقص است.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">صدادارکردن</translation>
<translation id="561939826962581046">زمان</translation>
<translation id="5630795885300617244">روی سمت راست یا چپ دو ضربه سریع بزنید تا ۱۰ ثانیه رد شود</translation>
+<translation id="5631759159893697722">انتزاعی</translation>
<translation id="5641012560118721995">مکث بازپخش</translation>
<translation id="5643186887447432888">دکمه</translation>
<translation id="5677946354068040947">گزینه‌های بیشتر</translation>
+<translation id="576709008726043716">مقدمه</translation>
<translation id="57838592816432529">بی‌صدا کردن</translation>
<translation id="5860033963881614850">خاموش</translation>
<translation id="588258955323874662">تمام صفحه</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">سال</translation>
<translation id="6023896073578205740">کادر فهرست</translation>
<translation id="6101327004457443354">صدادارکردن تراک صوتی</translation>
+<translation id="6150588977291308318">فهرست منابع</translation>
<translation id="6164829606128959761">متر</translation>
+<translation id="6166809985690652833">سخن پایانی</translation>
+<translation id="6213469881011901533">واژه‌نامه</translation>
<translation id="6398862346408813489">نمایش پانل انتخاب ماه</translation>
<translation id="6404546809543547843">انتخابگر زمان صدا</translation>
+<translation id="6453774872122745852">قدردانی</translation>
<translation id="648732519525291180">انتخابگر زمان</translation>
<translation id="6550675742724504774">گزینه‌ها</translation>
-<translation id="6564313821541007458">اکنون درحالت تصویردرتصویر</translation>
<translation id="658823671542763450">رفتن به حالت تمام صفحه</translation>
<translation id="663493177488814956">خبرمایه</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,49 +158,67 @@
<translation id="6755330956360078551">نکته ابزار</translation>
<translation id="6790428901817661496">پخش</translation>
<translation id="6820355525329141109">افزایه بارگیری نشد.</translation>
+<translation id="6820615603175220800">مرجع فهرست منابع</translation>
<translation id="6843725295806269523">بیصداکردن</translation>
<translation id="6853785296079745596">پنهان کردن زیرنویس ناشنوایان</translation>
<translation id="6885760532393684712">فهرست راهنما</translation>
+<translation id="689129560213475294">انجامه</translation>
<translation id="6934078000481955284">نقل‌قول</translation>
<translation id="6941933287844615239">بارگیری رسانه</translation>
<translation id="6989848892321993519">لطفاً این نوشتار را به <ph name="MIN_CHARACTERS" /> نویسه یا بیشتر افزایش دهید (درحال‌حاضر از ۱ نویسه استفاده می‌کنید).</translation>
<translation id="709897737746224366">لطفاً با قالب درخواستی مطابقت دهید.</translation>
+<translation id="7139483182332611405">پیش‌گفتار</translation>
<translation id="7223624360433298498">مدت سپری شده</translation>
<translation id="7263440858009898357">لطفاً یک مورد را در فهرست انتخاب کنید.</translation>
<translation id="727747134524199931">عنوان ستون</translation>
+<translation id="7353453495576941748">تأیید اعتبار</translation>
<translation id="7364796246159120393">انتخاب فایل</translation>
<translation id="739024184232394898">موارد دیگر...</translation>
+<translation id="7405738980073107433">ته‌نویس‌ها</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> ترابایت</translation>
<translation id="7491962110804786152">برگه</translation>
<translation id="7514365320538308">بارگیری</translation>
+<translation id="7529102961911894712">پیوند برگشت</translation>
+<translation id="7647456547678091388">نکته</translation>
+<translation id="7661956066982048809">سند گرافیکی</translation>
<translation id="7673697353781729403">ساعت</translation>
+<translation id="7681220483256441252">فهرست موضوعی</translation>
<translation id="7720026100085573005">زمان باقی‌مانده</translation>
<translation id="7740016676195725605">توقف نمایش زیرنویس ناشنوایان</translation>
<translation id="7740050170769002709">‏محتوای HTML</translation>
<translation id="7789962463072032349">مکث</translation>
<translation id="7802800022689234070">مثلث افشا</translation>
-<translation id="7888071071722539607">لطفاً نماد «<ph name="ATSIGN" />» را به نشانی رایانامه اضافه کنید. «<ph name="INVALIDADDRESS" />» در «<ph name="ATSIGN" />» موجود نیست.</translation>
+<translation id="7888071071722539607">لطفاً نماد «<ph name="ATSIGN" />» را به نشانی ایمیل اضافه کنید. «<ph name="INVALIDADDRESS" />» در «<ph name="ATSIGN" />» موجود نیست.</translation>
<translation id="7891486169920085145">تقسیم‌کننده</translation>
<translation id="795667975304826397">فایلی انتخاب نشده است</translation>
<translation id="8053789581856978548">فیلد نوشتاری جستجو</translation>
+<translation id="8057695513531652401">اطلاعیه</translation>
+<translation id="8105797009065549151">مرجع یادداشت</translation>
<translation id="8115662671911883373">شروع به نمایش زیرنویس ناشنوایان</translation>
<translation id="8117451130807776954">این هفته</translation>
<translation id="819205353528511139">پخش فیلم در حالت تمام صفحه</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">زیرنویس‌ها</translation>
<translation id="835897206747267392">مقدار نامعتبر.</translation>
+<translation id="8415319359811155763">بخش</translation>
<translation id="8433900881053900389">نوار ابزار</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> فایل</translation>
<translation id="8451268428117625855">لطفاً یک فایل انتخاب کنید.</translation>
<translation id="8461852803063341183">دکمه رادیو</translation>
+<translation id="8474886197722836894">تقدیم‌نامه</translation>
+<translation id="8531739829932800271">فهرست اشتباهات</translation>
<translation id="8534579021159131403">دقیقه</translation>
<translation id="8541249477527128034">کنترل رسانه</translation>
+<translation id="8550857728288566671">نماد گرافیکی</translation>
<translation id="8583702881314752957">فهرست معنی‌ها</translation>
<translation id="8597182159515967513">عنوان</translation>
+<translation id="860475260694818407">فهرست مطالب</translation>
<translation id="8613126697340063924">کنترل بازپخش راه دور</translation>
+<translation id="862370744433916922">زیرنویس</translation>
<translation id="8741316211671074806">تصویردرتصویر</translation>
<translation id="8750798805984357768">لطفاً یکی از این گزینه‌ها را انتخاب کنید.</translation>
<translation id="8785498733064193001">شروع بازپخش</translation>
+<translation id="8808573423886751634">فصل</translation>
<translation id="8845239796550121995">درحال ارسال محتوا به تلویزیون</translation>
<translation id="8851136666856101339">اصلی</translation>
<translation id="8875657656876809964">خطا در بازپخش ویدئو</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">موارد دیگر...</translation>
<translation id="9138385573473225930">هشدار</translation>
<translation id="9155987714137265666"><ph name="WEEK" />، شروع از <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">پانویس</translation>
<translation id="947831847158436616">سلول</translation>
<translation id="966787709310836684">منو</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fi.xtb b/chromium/content/app/strings/translations/content_strings_fi.xtb
index 4c444fa40fd..ffe7d7fb4e5 100644
--- a/chromium/content/app/strings/translations/content_strings_fi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fi.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">täydentävä</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">liukusäädin</translation>
+<translation id="1211441953136645838">loppuhuomautus</translation>
<translation id="1281252709823657822">valintaikkuna</translation>
+<translation id="1335095011850992622">tunnustukset</translation>
<translation id="1342835525016946179">artikkeli</translation>
<translation id="1359897965706325498">banneri</translation>
<translation id="1589122976691792535">alue</translation>
<translation id="1591562245178063882">Tässä kuussa</translation>
<translation id="1637811476055996098">Valitse tiedostot</translation>
+<translation id="1650423536718072820">erotettu lainaus</translation>
<translation id="1729654308190250600">Kirjoita ei-tyhjä sähköpostiosoite.</translation>
<translation id="1758486001363313524">Muu...</translation>
<translation id="1806710327868736751">ilmoitusvalintaikkuna</translation>
<translation id="1821985195704844674">puuruudukko</translation>
<translation id="1822429046913737220">AP/IP</translation>
<translation id="1832974991323546415">toista etälaitteella</translation>
+<translation id="1907737156431278478">esimerkki</translation>
<translation id="1921819250265091946">pp</translation>
<translation id="1930711995431081526">tila</translation>
<translation id="1938124657309484470">Arvon on oltava <ph name="MAXIMUM_DATE_OR_TIME" /> tai aiempi.</translation>
<translation id="1993104285338243655">Peilaus käynnissä</translation>
<translation id="2060505056492490888"><ph name="DOT" />-merkkiä on käytetty väärässä kohdassa osoitteessa <ph name="INVALIDDOMAIN" />.</translation>
<translation id="2148716181193084225">Tänään</translation>
+<translation id="2158401438286456825">sivuluettelo</translation>
<translation id="2226276347425096477">Lyhennä tämä teksti alle <ph name="MAX_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
<translation id="2247351761944213033">Viikko <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Kappale <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">valintaruutu</translation>
+<translation id="2311842470354187719">sivunvaihto</translation>
<translation id="2335594187091864976">päivämäärän ja ajan valitsin</translation>
<translation id="248395913932153421">Päivä</translation>
<translation id="2507943997699731163">Täytä tämä kenttä.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">toista</translation>
<translation id="2613802280814924224">Syötä kelvollinen arvo. Lähin kelvollinen arvo on <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Lähetä</translation>
+<translation id="2657045182931379222">grafiikkaobjekti</translation>
<translation id="2674318244760992338">alaviite</translation>
<translation id="2709516037105925701">Automaattinen täyttö</translation>
<translation id="2723001399770238859">ääni</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Pidennä tämä teksti yli <ph name="MIN_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
<translation id="383465348367842624"><ph name="ATSIGN" />-osaa ennen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
<translation id="3846214748874656680">Sulje koko näytön tila.</translation>
+<translation id="3920932319529768807">johtopäätös</translation>
<translation id="3924558731517983934">sovellus</translation>
+<translation id="3944740393230681990">prologi</translation>
<translation id="3960700977367013758">vierityspalkki</translation>
<translation id="4103419683916926126">Millisekuntia</translation>
<translation id="4151657705144244502">kuva</translation>
+<translation id="4193965531860883258">esipuhe</translation>
<translation id="4201051445878709314">Näytä edellinen kuukausi</translation>
<translation id="421884353938374759">värinvalitsin</translation>
<translation id="4248100235867064564">valikkopalkki</translation>
<translation id="4254339807215791271">sisällön tiedot</translation>
<translation id="4360991593054037559">Syötä kelvollinen arvo. Kaksi lähintä kelvollista arvoa ovat <ph name="VALID_VALUE_LOW" /> ja <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">K &amp; V</translation>
<translation id="4413860115965805769">valikkopainike</translation>
+<translation id="4446524499724042288">sanastoviittaus</translation>
<translation id="4522570452068850558">Tiedot</translation>
<translation id="4597532268155981612">lomake</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816"><ph name="ATSIGN" />-osan jälkeen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">liite</translation>
+<translation id="4742539557769756338">kansi</translation>
<translation id="4757246831282535685">välilehtipaneeli</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">haku</translation>
<translation id="4812940957355064477">Anna numero.</translation>
+<translation id="4912536737030637138">lähdeluettelomerkintä</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> valittu</translation>
<translation id="4992066212339426712">Poista mykistys</translation>
<translation id="49969490063480558">Kirjoita loppuun asti osoite, joka alkaa <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> on vielä kesken.</translation>
<translation id="5034860022980953847">etenemisen osoitin</translation>
+<translation id="5093189678851173835">epigrafi</translation>
<translation id="5117590920725113268">Näytä seuraava kuukausi</translation>
<translation id="512758898067543763">rivin otsikko</translation>
+<translation id="5143125788380636750">epilogi</translation>
+<translation id="5153163864850940242">Video toistetaan Kuva kuvassa ‑tilassa</translation>
<translation id="5164977714490026579">Arvon tulee olla suurempi tai yhtä suuri kuin <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> Pt</translation>
<translation id="5307600278924710095">Lisää <ph name="ATSIGN" />-osaa ennen tuleva osa. <ph name="INVALIDADDRESS" /> on puutteellinen.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">peruuta mykistys</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Ohita 10 sekuntia kaksoisnapauttamalla vasemmalle tai oikealle.</translation>
+<translation id="5631759159893697722">tiivistelmä</translation>
<translation id="5641012560118721995">keskeytä toisto</translation>
<translation id="5643186887447432888">painike</translation>
<translation id="5677946354068040947">lisäasetukset</translation>
+<translation id="576709008726043716">johdanto</translation>
<translation id="57838592816432529">Mykistä</translation>
<translation id="5860033963881614850">Pois käytöstä</translation>
<translation id="588258955323874662">Koko ruutu</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Vuosi</translation>
<translation id="6023896073578205740">luetteloruutu</translation>
<translation id="6101327004457443354">peruuta ääniraidan mykistys</translation>
+<translation id="6150588977291308318">lähdeluettelo</translation>
<translation id="6164829606128959761">mittari</translation>
+<translation id="6166809985690652833">jälkipuhe</translation>
+<translation id="6213469881011901533">sanasto</translation>
<translation id="6398862346408813489">Näytä kuukaudenvalintapaneeli</translation>
<translation id="6404546809543547843">äänen ajan liukusäädin</translation>
+<translation id="6453774872122745852">kiitokset</translation>
<translation id="648732519525291180">ajan valitsin</translation>
<translation id="6550675742724504774">Asetukset</translation>
-<translation id="6564313821541007458">Kuva kuvassa ‑tila nyt käytössä</translation>
<translation id="658823671542763450">siirry koko näytön tilaan</translation>
<translation id="663493177488814956">fiidi</translation>
<translation id="6637586476836377253">loki</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">työkaluvinkki</translation>
<translation id="6790428901817661496">Toista</translation>
<translation id="6820355525329141109">Laajennuksen lataaminen epäonnistui.</translation>
+<translation id="6820615603175220800">lähdeluetteloviittaus</translation>
<translation id="6843725295806269523">äänetön</translation>
<translation id="6853785296079745596">piilota tekstitykset</translation>
<translation id="6885760532393684712">hakemisto</translation>
+<translation id="689129560213475294">kolofoni</translation>
<translation id="6934078000481955284">muotoiltu lainaus</translation>
<translation id="6941933287844615239">lataa media</translation>
<translation id="6989848892321993519">Pidennä tämä teksti vähintään <ph name="MIN_CHARACTERS" /> merkkiin (tällä hetkellä käytössä 1 merkki).</translation>
<translation id="709897737746224366">Käytä pyydettyä muotoilua.</translation>
+<translation id="7139483182332611405">johdanto</translation>
<translation id="7223624360433298498">kulunut aika</translation>
<translation id="7263440858009898357">Valitse kohde luettelosta.</translation>
<translation id="727747134524199931">sarakkeen otsikko</translation>
+<translation id="7353453495576941748">tunnustus</translation>
<translation id="7364796246159120393">Valitse tiedosto</translation>
<translation id="739024184232394898">Muu...</translation>
+<translation id="7405738980073107433">loppuhuomautukset</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> Tt</translation>
<translation id="7491962110804786152">sarkain</translation>
<translation id="7514365320538308">Lataa</translation>
+<translation id="7529102961911894712">viittaajan linkki</translation>
+<translation id="7647456547678091388">vinkki</translation>
+<translation id="7661956066982048809">grafiikkadokumentti</translation>
<translation id="7673697353781729403">Tuntia</translation>
+<translation id="7681220483256441252">hakemisto</translation>
<translation id="7720026100085573005">jäljellä oleva aika</translation>
<translation id="7740016676195725605">älä näytä tekstityksiä</translation>
<translation id="7740050170769002709">HTML-sisältö</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">jakaja</translation>
<translation id="795667975304826397">Ei valittua tiedostoa</translation>
<translation id="8053789581856978548">hakutekstikenttä</translation>
+<translation id="8057695513531652401">ilmoitus</translation>
+<translation id="8105797009065549151">muistiinpanoviittaus</translation>
<translation id="8115662671911883373">näytä tekstitykset</translation>
<translation id="8117451130807776954">Tällä viikolla</translation>
<translation id="819205353528511139">toista elokuva koko näytön tilassa</translation>
<translation id="8199524924445686405">vvvv</translation>
<translation id="8284326494547611709">Tekstitykset</translation>
<translation id="835897206747267392">Virheellinen arvo.</translation>
+<translation id="8415319359811155763">osa</translation>
<translation id="8433900881053900389">työkalupalkki</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tiedostoa</translation>
<translation id="8451268428117625855">Valitse tiedosto.</translation>
<translation id="8461852803063341183">valintapainike</translation>
+<translation id="8474886197722836894">omistuskirjoitus</translation>
+<translation id="8531739829932800271">oikaisut</translation>
<translation id="8534579021159131403">Minuuttia</translation>
<translation id="8541249477527128034">median hallinta</translation>
+<translation id="8550857728288566671">grafiikkasymboli</translation>
<translation id="8583702881314752957">määritelmäluettelo</translation>
<translation id="8597182159515967513">otsikko</translation>
+<translation id="860475260694818407">sisällysluettelo</translation>
<translation id="8613126697340063924">hallinnoi etätoistoa</translation>
+<translation id="862370744433916922">alaotsikko</translation>
<translation id="8741316211671074806">Kuva kuvassa</translation>
<translation id="8750798805984357768">Valitse yksi vaihtoehdoista.</translation>
<translation id="8785498733064193001">aloita toisto</translation>
+<translation id="8808573423886751634">luku</translation>
<translation id="8845239796550121995">Suoratoistetaan televisioosi</translation>
<translation id="8851136666856101339">pää</translation>
<translation id="8875657656876809964">Videon toistovirhe</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Muu...</translation>
<translation id="9138385573473225930">ilmoitus</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, alkupäivä: <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">alaviite</translation>
<translation id="947831847158436616">solu</translation>
<translation id="966787709310836684">valikko</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fil.xtb b/chromium/content/app/strings/translations/content_strings_fil.xtb
index 0226e24ca57..7687fc29e30 100644
--- a/chromium/content/app/strings/translations/content_strings_fil.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fil.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementary</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">slider</translation>
+<translation id="1211441953136645838">endnote</translation>
<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">mga credit</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">rehiyon</translation>
<translation id="1591562245178063882">Buwang ito</translation>
<translation id="1637811476055996098">Pumili ng Mga File</translation>
+<translation id="1650423536718072820">pullquote</translation>
<translation id="1729654308190250600">Mangyaring maglagay ng isang non-empty na email address.</translation>
<translation id="1758486001363313524">Iba pa...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">tree grid</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">i-play sa malayuang device</translation>
+<translation id="1907737156431278478">halimbawa</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">katayuan</translation>
<translation id="1938124657309484470">Dapat <ph name="MAXIMUM_DATE_OR_TIME" /> o mas nauna ang value.</translation>
<translation id="1993104285338243655">Lumipat sa pag-mirror</translation>
<translation id="2060505056492490888">Ginamit ang '<ph name="DOT" />' sa maling posisyon sa '<ph name="INVALIDDOMAIN" />.'</translation>
<translation id="2148716181193084225">Ngayon</translation>
+<translation id="2158401438286456825">listahan ng page</translation>
<translation id="2226276347425096477">Mangyaring paikliin ang tekstong ito ng <ph name="MAX_CHARACTERS" /> (na) character o mas mababa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
<translation id="2247351761944213033">Linggo <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">checkbox</translation>
+<translation id="2311842470354187719">page break</translation>
<translation id="2335594187091864976">picker ng petsa at oras</translation>
<translation id="248395913932153421">Araw</translation>
<translation id="2507943997699731163">Pakipunan ang field na ito.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">i-play</translation>
<translation id="2613802280814924224">Mangyaring maglagay ng isang wastong value. Ang pinakamalapit na wastong value ay <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Isumite</translation>
+<translation id="2657045182931379222">object ng graphics</translation>
<translation id="2674318244760992338">footer</translation>
<translation id="2709516037105925701">AutoFill</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Pakihabaan ang text na ito hanggang <ph name="MIN_CHARACTERS" /> (na) character o higit pa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
<translation id="383465348367842624">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi bago ang '<ph name="ATSIGN" />.'</translation>
<translation id="3846214748874656680">Lumabas sa fullscreen</translation>
+<translation id="3920932319529768807">konklusyon</translation>
<translation id="3924558731517983934">application</translation>
+<translation id="3944740393230681990">prologue</translation>
<translation id="3960700977367013758">scroll bar</translation>
<translation id="4103419683916926126">Milliseconds</translation>
<translation id="4151657705144244502">graphic</translation>
+<translation id="4193965531860883258">foreword</translation>
<translation id="4201051445878709314">Ipakita ang nakaraang buwan</translation>
<translation id="421884353938374759">tagapili ng kulay</translation>
<translation id="4248100235867064564">menu bar</translation>
<translation id="4254339807215791271">impormasyon ng content</translation>
<translation id="4360991593054037559">Mangyaring maglagay ng isang wastong value. Ang dalawang pinakamalapit na wastong value ay <ph name="VALID_VALUE_LOW" /> at <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
<translation id="4413860115965805769">button ng menu</translation>
+<translation id="4446524499724042288">sanggunian sa glosaryo</translation>
<translation id="4522570452068850558">Mga Detalye</translation>
<translation id="4597532268155981612">form</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi pagkatapos ng '<ph name="ATSIGN" />.'</translation>
+<translation id="4668956016107839909">appendix</translation>
+<translation id="4742539557769756338">cover</translation>
<translation id="4757246831282535685">panel ng tab</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Mangyaring maglagay ng numero.</translation>
+<translation id="4912536737030637138">entry sa bibliograpiya</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ang napili</translation>
<translation id="4992066212339426712">I-unmute</translation>
<translation id="49969490063480558">Mangyaring maglagay ng isang bahagi pagkatapos ng '<ph name="ATSIGN" />.' Hindi kumpleto ang '<ph name="INVALIDADDRESS" />.'</translation>
<translation id="5034860022980953847">indicator ng pag-usad</translation>
+<translation id="5093189678851173835">epigraph</translation>
<translation id="5117590920725113268">Ipakita ang susunod na buwan</translation>
<translation id="512758898067543763">header ng row</translation>
+<translation id="5143125788380636750">epilogue</translation>
+<translation id="5153163864850940242">Nagpe-play ang video na ito sa Picture-in-Picture</translation>
<translation id="5164977714490026579">Dapat mas mataas kaysa sa o katumbas ng <ph name="MINIMUM" /> ang halaga.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> (na) PB</translation>
<translation id="5307600278924710095">Mangyaring maglagay ng isang bahagi na sinusundan ng '<ph name="ATSIGN" />.' Hindi kumpleto ang '<ph name="INVALIDADDRESS" />.'</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">i-unmute</translation>
<translation id="561939826962581046">oras</translation>
<translation id="5630795885300617244">Mag-double tap sa kaliwa o kanan upang lumaktaw nang 10s</translation>
+<translation id="5631759159893697722">abstract</translation>
<translation id="5641012560118721995">i-pause ang pag-playback</translation>
<translation id="5643186887447432888">button</translation>
<translation id="5677946354068040947">higit pang opsyon</translation>
+<translation id="576709008726043716">panimula</translation>
<translation id="57838592816432529">I-mute</translation>
<translation id="5860033963881614850">Naka-off</translation>
<translation id="588258955323874662">Fullscreen</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Taon</translation>
<translation id="6023896073578205740">kahon ng listahan</translation>
<translation id="6101327004457443354">i-unmute ang audio track</translation>
+<translation id="6150588977291308318">bibliograpiya</translation>
<translation id="6164829606128959761">metro</translation>
+<translation id="6166809985690652833">afterword</translation>
+<translation id="6213469881011901533">glosaryo</translation>
<translation id="6398862346408813489">Ipakita ang panel ng pagpipilian ng buwan</translation>
<translation id="6404546809543547843">scrubber ng oras ng audio</translation>
+<translation id="6453774872122745852">mga pagkilala</translation>
<translation id="648732519525291180">picker ng petsa</translation>
<translation id="6550675742724504774">Mga Pagpipilian</translation>
-<translation id="6564313821541007458">Nasa Picture-in-Picture mode ngayon</translation>
<translation id="658823671542763450">mag-full screen</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">tooltip</translation>
<translation id="6790428901817661496">I-play</translation>
<translation id="6820355525329141109">Hindi ma-load ang plugin.</translation>
+<translation id="6820615603175220800">sanggunian sa bibliograpiya</translation>
<translation id="6843725295806269523">i-mute</translation>
<translation id="6853785296079745596">itago ang mga nakasarang caption</translation>
<translation id="6885760532393684712">direktoryo</translation>
+<translation id="689129560213475294">colophon</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">i-download ang media</translation>
<translation id="6989848892321993519">Pakidagdagan ang text na ito nang hanggang <ph name="MIN_CHARACTERS" /> (na) character o higit pa (kasalukuyan kang gumagamit ng 1 character).</translation>
<translation id="709897737746224366">Pakitugma ang hiniling na format.</translation>
+<translation id="7139483182332611405">preface</translation>
<translation id="7223624360433298498">lumipas na oras</translation>
<translation id="7263440858009898357">Mangyaring pumili ng item sa listahan.</translation>
<translation id="727747134524199931">header ng column</translation>
+<translation id="7353453495576941748">credit</translation>
<translation id="7364796246159120393">Pumili ng File</translation>
<translation id="739024184232394898">Iba pa...</translation>
+<translation id="7405738980073107433">mga endnote</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> (na) TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">I-download</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">dokumento ng graphics</translation>
<translation id="7673697353781729403">Oras</translation>
+<translation id="7681220483256441252">index</translation>
<translation id="7720026100085573005">natitirang oras</translation>
<translation id="7740016676195725605">ihinto ang pagpapakita ng mga nakasarang caption</translation>
<translation id="7740050170769002709">HTML na nilalaman</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">splitter</translation>
<translation id="795667975304826397">Walang napiling file</translation>
<translation id="8053789581856978548">text field ng paghahanap</translation>
+<translation id="8057695513531652401">paunawa</translation>
+<translation id="8105797009065549151">sanggunian sa tala</translation>
<translation id="8115662671911883373">simulan ang pagpapakita ng mga nakasarang caption</translation>
<translation id="8117451130807776954">Linggong ito</translation>
<translation id="819205353528511139">i-play ang pelikula sa full screen mode</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Mga Caption</translation>
<translation id="835897206747267392">Di-wastong halaga.</translation>
+<translation id="8415319359811155763">bahagi</translation>
<translation id="8433900881053900389">toolbar</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> mga file</translation>
<translation id="8451268428117625855">Mangyaring pumili ng file.</translation>
<translation id="8461852803063341183">radio button</translation>
+<translation id="8474886197722836894">dedikasyon</translation>
+<translation id="8531739829932800271">mga erratum</translation>
<translation id="8534579021159131403">Minuto</translation>
<translation id="8541249477527128034">kontrol sa media</translation>
+<translation id="8550857728288566671">simbolo ng graphics</translation>
<translation id="8583702881314752957">listahan ng kahulugan</translation>
<translation id="8597182159515967513">heading</translation>
+<translation id="860475260694818407">talaan ng nilalaman</translation>
<translation id="8613126697340063924">kontrolin ang malayuang pag-playback</translation>
+<translation id="862370744433916922">subtitle</translation>
<translation id="8741316211671074806">Picture-in-Picture</translation>
<translation id="8750798805984357768">Mangyaring pumili ng isa sa mga opsyong ito.</translation>
<translation id="8785498733064193001">simulan ang pag-playback</translation>
+<translation id="8808573423886751634">kabanata</translation>
<translation id="8845239796550121995">Ikina-cast ngayon sa iyong TV</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Error sa pag-playback ng video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Iba pa...</translation>
<translation id="9138385573473225930">alerto</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, na magsisimula sa <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">footnote</translation>
<translation id="947831847158436616">cell</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fr.xtb b/chromium/content/app/strings/translations/content_strings_fr.xtb
index ef80e46d2c4..8e4af484697 100644
--- a/chromium/content/app/strings/translations/content_strings_fr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fr.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complémentaire</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">curseur</translation>
+<translation id="1211441953136645838">note de fin</translation>
<translation id="1281252709823657822">boîte de dialogue</translation>
+<translation id="1335095011850992622">crédits</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">bannière</translation>
<translation id="1589122976691792535">région</translation>
<translation id="1591562245178063882">Ce mois</translation>
<translation id="1637811476055996098">Sélect. fichiers</translation>
+<translation id="1650423536718072820">témoignage</translation>
<translation id="1729654308190250600">Veuillez saisir une adresse e-mail dans le champ correspondant.</translation>
<translation id="1758486001363313524">Autre…</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">arborescence</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">lire sur un appareil à distance</translation>
+<translation id="1907737156431278478">exemple</translation>
<translation id="1921819250265091946">jj</translation>
<translation id="1930711995431081526">état</translation>
<translation id="1938124657309484470">La date ou l'heure doit être égale ou antérieure à "<ph name="MAXIMUM_DATE_OR_TIME" />".</translation>
<translation id="1993104285338243655">Passage à la duplication d'écran</translation>
<translation id="2060505056492490888">L'emplacement du caractère "<ph name="DOT" />" est incorrect dans "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Aujourd'hui</translation>
+<translation id="2158401438286456825">liste des pages</translation>
<translation id="2226276347425096477">Veuillez réduire ce texte à <ph name="MAX_CHARACTERS" /> caractères maximum (il compte actuellement <ph name="CURRENT_LENGTH" /> caractères).</translation>
<translation id="2247351761944213033">Semaine <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Piste <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">case à cocher</translation>
+<translation id="2311842470354187719">saut de page</translation>
<translation id="2335594187091864976">outil de sélection de la date et de l'heure</translation>
<translation id="248395913932153421">Jour</translation>
<translation id="2507943997699731163">Veuillez renseigner ce champ.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">lire</translation>
<translation id="2613802280814924224">Veuillez saisir une valeur valide. La valeur valide la plus proche est "<ph name="VALID_VALUE" />".</translation>
<translation id="2653659639078652383">Valider</translation>
+<translation id="2657045182931379222">objet graphique</translation>
<translation id="2674318244760992338">pied de page</translation>
<translation id="2709516037105925701">Saisie automatique</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Veuillez allonger ce texte pour qu'il comporte au moins <ph name="MIN_CHARACTERS" /> caractères. Il en compte actuellement <ph name="CURRENT_LENGTH" />.</translation>
<translation id="383465348367842624">La partie suivie du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Quitter le mode plein écran</translation>
+<translation id="3920932319529768807">conclusion</translation>
<translation id="3924558731517983934">application</translation>
+<translation id="3944740393230681990">prologue</translation>
<translation id="3960700977367013758">barre de défilement</translation>
<translation id="4103419683916926126">Millisecondes</translation>
<translation id="4151657705144244502">élément graphique</translation>
+<translation id="4193965531860883258">avant-propos</translation>
<translation id="4201051445878709314">Afficher le mois précédent</translation>
<translation id="421884353938374759">palette couleurs</translation>
<translation id="4248100235867064564">barre de menu</translation>
<translation id="4254339807215791271">infos sur le contenu</translation>
<translation id="4360991593054037559">Veuillez saisir une valeur valide. Les deux valeurs valides les plus proches sont "<ph name="VALID_VALUE_LOW" />" et "<ph name="VALID_VALUE_HIGHER" />".</translation>
+<translation id="4384583879834880242">Questions/Réponses</translation>
<translation id="4413860115965805769">bouton de menu</translation>
+<translation id="4446524499724042288">référence de glossaire</translation>
<translation id="4522570452068850558">Détails</translation>
<translation id="4597532268155981612">formulaire</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">La partie précédée du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">annexe</translation>
+<translation id="4742539557769756338">couverture</translation>
<translation id="4757246831282535685">panneau des onglets</translation>
<translation id="4763480195061959176">vidéo</translation>
<translation id="479989351350248267">rechercher</translation>
<translation id="4812940957355064477">Veuillez saisir un nombre.</translation>
+<translation id="4912536737030637138">entrée bibliographique</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> élément(s) sélectionné(s)</translation>
<translation id="4992066212339426712">Réactiver le son</translation>
<translation id="49969490063480558">Veuillez saisir la partie manquante après le symbole "<ph name="ATSIGN" />". L'adresse "<ph name="INVALIDADDRESS" />" est incomplète.</translation>
<translation id="5034860022980953847">indicateur de progression</translation>
+<translation id="5093189678851173835">épigraphe</translation>
<translation id="5117590920725113268">Afficher le mois suivant</translation>
<translation id="512758898067543763">en-tête de ligne</translation>
+<translation id="5143125788380636750">épilogue</translation>
+<translation id="5153163864850940242">Cette vidéo est diffusée en mode PIP (Picture-in-Picture)</translation>
<translation id="5164977714490026579">Cette valeur doit être supérieure ou égale à <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> Po</translation>
<translation id="5307600278924710095">Veuillez saisir la partie manquante avant le caractère "<ph name="ATSIGN" />". L'adresse "<ph name="INVALIDADDRESS" />" est incomplète.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">réactiver le son</translation>
<translation id="561939826962581046">horodatage</translation>
<translation id="5630795885300617244">Appuyez deux fois à gauche/droite pour reculer/avancer de 10 s</translation>
+<translation id="5631759159893697722">résumé</translation>
<translation id="5641012560118721995">interrompre la lecture</translation>
<translation id="5643186887447432888">bouton</translation>
<translation id="5677946354068040947">plus d'options</translation>
+<translation id="576709008726043716">introduction</translation>
<translation id="57838592816432529">Couper le son</translation>
<translation id="5860033963881614850">Désactivé</translation>
<translation id="588258955323874662">Plein écran</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Année</translation>
<translation id="6023896073578205740">zone de liste</translation>
<translation id="6101327004457443354">réactiver le son de la piste audio</translation>
+<translation id="6150588977291308318">bibliographie</translation>
<translation id="6164829606128959761">outil de mesure</translation>
+<translation id="6166809985690652833">postface</translation>
+<translation id="6213469881011901533">glossaire</translation>
<translation id="6398862346408813489">Afficher le panneau de sélection du mois</translation>
<translation id="6404546809543547843">curseur durée audio</translation>
+<translation id="6453774872122745852">remerciements</translation>
<translation id="648732519525291180">outil de sélection de l'heure</translation>
<translation id="6550675742724504774">Options</translation>
-<translation id="6564313821541007458">Mode PIP (Picture-in-Picture) activé</translation>
<translation id="658823671542763450">activer le mode plein écran</translation>
<translation id="663493177488814956">flux</translation>
<translation id="6637586476836377253">journal</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">info-bulle</translation>
<translation id="6790428901817661496">Lire</translation>
<translation id="6820355525329141109">Impossible de charger le plug-in.</translation>
+<translation id="6820615603175220800">référence bibliographique</translation>
<translation id="6843725295806269523">muet</translation>
<translation id="6853785296079745596">masquer les sous-titres</translation>
<translation id="6885760532393684712">annuaire</translation>
+<translation id="689129560213475294">achevé d'imprimer</translation>
<translation id="6934078000481955284">bloc de citation</translation>
<translation id="6941933287844615239">télécharger des contenus multimédias</translation>
<translation id="6989848892321993519">Veuillez allonger ce texte pour qu'il comporte au moins <ph name="MIN_CHARACTERS" /> caractères. Il en compte actuellement un seul.</translation>
<translation id="709897737746224366">Veuillez respecter le format requis.</translation>
+<translation id="7139483182332611405">préface</translation>
<translation id="7223624360433298498">temps écoulé</translation>
<translation id="7263440858009898357">Sélectionnez un élément dans la liste.</translation>
<translation id="727747134524199931">en-tête de colonne</translation>
+<translation id="7353453495576941748">crédit</translation>
<translation id="7364796246159120393">Choisir un fichier</translation>
<translation id="739024184232394898">Autre…</translation>
+<translation id="7405738980073107433">notes de fin</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> To</translation>
<translation id="7491962110804786152">tabulation</translation>
<translation id="7514365320538308">Télécharger</translation>
+<translation id="7529102961911894712">lien entrant</translation>
+<translation id="7647456547678091388">conseil</translation>
+<translation id="7661956066982048809">document graphique</translation>
<translation id="7673697353781729403">Heures</translation>
+<translation id="7681220483256441252">index</translation>
<translation id="7720026100085573005">temps restant</translation>
<translation id="7740016676195725605">ne plus afficher les sous-titres</translation>
<translation id="7740050170769002709">Contenu HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">séparateur</translation>
<translation id="795667975304826397">Aucun fichier choisi</translation>
<translation id="8053789581856978548">champ de recherche de texte</translation>
+<translation id="8057695513531652401">notification</translation>
+<translation id="8105797009065549151">référence de note</translation>
<translation id="8115662671911883373">commencer à afficher les sous-titres</translation>
<translation id="8117451130807776954">Cette semaine</translation>
<translation id="819205353528511139">lire le film en mode plein écran</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Sous-titres</translation>
<translation id="835897206747267392">Valeur incorrecte</translation>
+<translation id="8415319359811155763">partie</translation>
<translation id="8433900881053900389">barre d'outils</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fichiers</translation>
<translation id="8451268428117625855">Veuillez sélectionner un fichier.</translation>
<translation id="8461852803063341183">case d'option</translation>
+<translation id="8474886197722836894">dédicace</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minutes</translation>
<translation id="8541249477527128034">commande multimédia</translation>
+<translation id="8550857728288566671">symbole graphique</translation>
<translation id="8583702881314752957">liste de définitions</translation>
<translation id="8597182159515967513">en-tête</translation>
+<translation id="860475260694818407">sommaire</translation>
<translation id="8613126697340063924">contrôler la lecture à distance</translation>
+<translation id="862370744433916922">sous-titre</translation>
<translation id="8741316211671074806">Picture-in-Picture</translation>
<translation id="8750798805984357768">Veuillez sélectionner l'une de ces options.</translation>
<translation id="8785498733064193001">commencer la lecture</translation>
+<translation id="8808573423886751634">chapitre</translation>
<translation id="8845239796550121995">En cours de diffusion sur votre téléviseur</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8875657656876809964">Erreur lors de la lecture de la vidéo</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Autre…</translation>
<translation id="9138385573473225930">alerte</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> (premier jour de la semaine : <ph name="WEEK_START_DATE" />)</translation>
+<translation id="9168329111483466115">note de bas de page</translation>
<translation id="947831847158436616">cellule</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_gu.xtb b/chromium/content/app/strings/translations/content_strings_gu.xtb
index bac0dca9195..52c5bc2b23d 100644
--- a/chromium/content/app/strings/translations/content_strings_gu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_gu.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">પૂરક</translation>
<translation id="1206619573307042055">માર્કી</translation>
<translation id="1206693055195146388">સ્લાઇડર</translation>
+<translation id="1211441953136645838">અંતિમ નોંધ</translation>
<translation id="1281252709823657822">સંવાદ</translation>
+<translation id="1335095011850992622">ક્રેડિટ</translation>
<translation id="1342835525016946179">લેખ</translation>
<translation id="1359897965706325498">બેનર</translation>
<translation id="1589122976691792535">પ્રદેશ</translation>
<translation id="1591562245178063882">આ મહિને</translation>
<translation id="1637811476055996098">ફાઇલો પસંદ કરો</translation>
+<translation id="1650423536718072820">પુલક્વોટ</translation>
<translation id="1729654308190250600">કૃપા કરીને એક બિન-ખાલી ઇમેઇલ સરનામું દાખલ કરો.</translation>
<translation id="1758486001363313524">અન્ય...</translation>
<translation id="1806710327868736751">ચેતવણી_સંવાદ</translation>
<translation id="1821985195704844674">ટ્રી ગ્રિડ</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">રિમોટ ઉપકરણ પર ચલાવો</translation>
+<translation id="1907737156431278478">ઉદાહરણ</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">સ્થિતિ</translation>
<translation id="1938124657309484470">મૂલ્ય <ph name="MAXIMUM_DATE_OR_TIME" /> અથવા પહેલાંનું હોવું આવશ્યક છે.</translation>
<translation id="1993104285338243655">મીરરીંગ પર સ્વિચ કર્યુંં</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' નો ઉપયોગ '<ph name="INVALIDDOMAIN" />' માં ખોટી જગ્યાએ થયો છે.</translation>
<translation id="2148716181193084225">આજે</translation>
+<translation id="2158401438286456825">પેજ સૂચિ</translation>
<translation id="2226276347425096477">કૃપા કરીને આ ટેક્સ્ટને <ph name="MAX_CHARACTERS" /> અક્ષર અથવા તેથી ઓછા સુધી નાનો કરો (તમે હાલમાં <ph name="CURRENT_LENGTH" /> અક્ષરોનો ઉપયોગ કરી રહ્યા છો).</translation>
<translation id="2247351761944213033">અઠવાડિયું <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ટ્રૅક <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ચેકબોક્સ</translation>
+<translation id="2311842470354187719">પેજ વિભાજન</translation>
<translation id="2335594187091864976">તારીખ અને સમય પીકર</translation>
<translation id="248395913932153421">દિવસ</translation>
<translation id="2507943997699731163">કૃપા કરીને આ ફીલ્ડ ભરો.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">ચલાવો</translation>
<translation id="2613802280814924224">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. નિકટતમ માન્ય મૂલ્ય <ph name="VALID_VALUE" /> છે.</translation>
<translation id="2653659639078652383">સબમિટ કરો</translation>
+<translation id="2657045182931379222">ગ્રાફિક્સ ઑબ્જેક્ટ</translation>
<translation id="2674318244760992338">ફૂટર</translation>
<translation id="2709516037105925701">સ્વતઃભરો</translation>
<translation id="2723001399770238859">ઑડિઓ</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">કૃપા કરીને આ ટેક્સ્ટને <ph name="MIN_CHARACTERS" /> અક્ષર અથવા તેથી વધુ સુધી લંબાવો (તમે હાલમાં <ph name="CURRENT_LENGTH" /> અક્ષરોનો ઉપયોગ કરી રહ્યાં છો).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' દ્વારા અનુસરાઈ રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
<translation id="3846214748874656680">પૂર્ણસ્ક્રીનથી બહાર નીકળો</translation>
+<translation id="3920932319529768807">સારાંશ</translation>
<translation id="3924558731517983934">ઍપ્લિકેશન</translation>
+<translation id="3944740393230681990">પ્રસ્તાવના</translation>
<translation id="3960700977367013758">સ્ક્રોલ બાર</translation>
<translation id="4103419683916926126">મીલીસેકન્ડ</translation>
<translation id="4151657705144244502">ગ્રાફિક</translation>
+<translation id="4193965531860883258">આમુખ</translation>
<translation id="4201051445878709314">પહેલાનો મહિનો દર્શાવો</translation>
<translation id="421884353938374759">રંગ ચૂંટનાર</translation>
<translation id="4248100235867064564">મેનૂ બાર</translation>
<translation id="4254339807215791271">સામગ્રી માહિતી</translation>
<translation id="4360991593054037559">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. બે નિકટતમ માન્ય મૂલ્યો <ph name="VALID_VALUE_LOW" /> અને <ph name="VALID_VALUE_HIGHER" /> છે.</translation>
+<translation id="4384583879834880242">પ્રશ્ન અને જવાબ</translation>
<translation id="4413860115965805769">મેનૂ બટન</translation>
+<translation id="4446524499724042288">શબ્દાવલીનો સંદર્ભ</translation>
<translation id="4522570452068850558">વિગતો</translation>
<translation id="4597532268155981612">ફોર્મ</translation>
<translation id="4661075872484491155">ટ્રી</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ને અનુસરી રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
+<translation id="4668956016107839909">જોડાણ</translation>
+<translation id="4742539557769756338">કવર</translation>
<translation id="4757246831282535685">ટેબ પેનલ</translation>
<translation id="4763480195061959176">વિડિઓ</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">કૃપા કરીને એક નંબર દાખલ કરો.</translation>
+<translation id="4912536737030637138">ગ્રંથસૂચિની એન્ટ્રી</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> પસંદ કર્યા</translation>
<translation id="4992066212339426712">અનમ્યૂટ કરો</translation>
<translation id="49969490063480558">કૃપા કરીને '<ph name="ATSIGN" />' ને અનુસરી રહેલો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS" />' અપૂર્ણ છે.</translation>
<translation id="5034860022980953847">પ્રગતિ સૂચક</translation>
+<translation id="5093189678851173835">શિલાલેખ</translation>
<translation id="5117590920725113268">આગલો મહિનો દર્શાવો</translation>
<translation id="512758898067543763">પંક્તિ હેડર</translation>
+<translation id="5143125788380636750">ઉપસંહાર</translation>
+<translation id="5153163864850940242">આ વીડિઓ ચિત્ર-માં-ચિત્ર મોડમાં ચાલી રહ્યો છે</translation>
<translation id="5164977714490026579">મૂલ્ય <ph name="MINIMUM" /> જેટલું અથવા આનાથી વધુ હોવું આવશ્યક છે.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">કૃપા કરીને '<ph name="ATSIGN" />' ની આગળનો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS" />' અપૂર્ણ છે.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">અનમ્યૂટ કરો</translation>
<translation id="561939826962581046">સમય</translation>
<translation id="5630795885300617244">10 સેકન્ડ છોડવા માટે ડાબે અથવા જમણે બે વાર ટૅપ કરો</translation>
+<translation id="5631759159893697722">અમૂર્ત</translation>
<translation id="5641012560118721995">પ્લેબેક થોભાવો</translation>
<translation id="5643186887447432888">બટન</translation>
<translation id="5677946354068040947">વધુ વિકલ્પો</translation>
+<translation id="576709008726043716">પ્રસ્તાવના</translation>
<translation id="57838592816432529">અવાજ બંધ કરો</translation>
<translation id="5860033963881614850">બંધ</translation>
<translation id="588258955323874662">પૂર્ણસ્ક્રીન</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">વર્ષ</translation>
<translation id="6023896073578205740">સૂચિ બૉક્સ</translation>
<translation id="6101327004457443354">ઑડિઓ ટ્રેક અનમ્યૂટ કરો</translation>
+<translation id="6150588977291308318">ગ્રંથસૂચિ</translation>
<translation id="6164829606128959761">મીટર</translation>
+<translation id="6166809985690652833">સમાપન ભાષણ</translation>
+<translation id="6213469881011901533">શબ્દાવલી</translation>
<translation id="6398862346408813489">મહિના પસંદગી પેનલ દર્શાવો</translation>
<translation id="6404546809543547843">ઑડિઓ સમય સ્ક્રબર</translation>
+<translation id="6453774872122745852">સ્વીકૃતિઓ</translation>
<translation id="648732519525291180">સમય પીકર</translation>
<translation id="6550675742724504774">વિકલ્પો</translation>
-<translation id="6564313821541007458">હાલમાં ચિત્ર-માં-ચિત્ર મોડમાં</translation>
<translation id="658823671542763450">પૂર્ણ સ્ક્રીનમાં દાખલ થાઓ</translation>
<translation id="663493177488814956">ફીડ</translation>
<translation id="6637586476836377253">લૉગ</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">ટૂલટીપ</translation>
<translation id="6790428901817661496">ચલાવો</translation>
<translation id="6820355525329141109">પ્લગિન લોડ કરી શક્યાં નથી.</translation>
+<translation id="6820615603175220800">ગ્રંથસૂચિનો સંદર્ભ</translation>
<translation id="6843725295806269523">બંધ કરો</translation>
<translation id="6853785296079745596">ઉપશીર્ષક છુપાવો</translation>
<translation id="6885760532393684712">નિર્દેશિકા</translation>
+<translation id="689129560213475294">પ્રકાશકની માહિતી</translation>
<translation id="6934078000481955284">બ્લૉકક્વોટ</translation>
<translation id="6941933287844615239">મીડિયા ડાઉનલોડ કરો</translation>
<translation id="6989848892321993519">કૃપા કરીને આ ટેક્સ્ટને <ph name="MIN_CHARACTERS" /> અથવા તેથી વધુ અક્ષર સુધી લંબાવો (તમે હાલમાં 1 અક્ષરનો ઉપયોગ કરી રહ્યાં છો).</translation>
<translation id="709897737746224366">કૃપા કરીને વિનંતી કરેલા ફોર્મેટ સાથે મેળ કરો.</translation>
+<translation id="7139483182332611405">પ્રસ્તાવના</translation>
<translation id="7223624360433298498">વીતેલો સમય</translation>
<translation id="7263440858009898357">કૃપા કરીને સૂચિમાંથી એક આઇટમ પસંદ કરો.</translation>
<translation id="727747134524199931">કૉલમ હેડર</translation>
+<translation id="7353453495576941748">ક્રેડિટ</translation>
<translation id="7364796246159120393">ફાઇલ પસંદ કરો</translation>
<translation id="739024184232394898">અન્ય...</translation>
+<translation id="7405738980073107433">અંતિમ નોંધ</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">ટેબ</translation>
<translation id="7514365320538308">ડાઉનલોડ કરો</translation>
+<translation id="7529102961911894712">બૅક લિંક</translation>
+<translation id="7647456547678091388">ટિપ</translation>
+<translation id="7661956066982048809">ગ્રાફિક્સ દસ્તાવેજ</translation>
<translation id="7673697353781729403">કલાક</translation>
+<translation id="7681220483256441252">અનુક્રમણિકા</translation>
<translation id="7720026100085573005">બાકીનો સમય</translation>
<translation id="7740016676195725605">વિગતવાર ઉપશીર્ષકનું પ્રદર્શન અટકાવો</translation>
<translation id="7740050170769002709">HTML સામગ્રી</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">વિભાજનકર્તા</translation>
<translation id="795667975304826397">કોઈ ફાઇલ પસંદ કરેલી નથી</translation>
<translation id="8053789581856978548">ટેક્સ્ટ ફીલ્ડ શોધો</translation>
+<translation id="8057695513531652401">સૂચના</translation>
+<translation id="8105797009065549151">નોંધ સંદર્ભ</translation>
<translation id="8115662671911883373">ઉપશીર્ષક પ્રદર્શન પ્રારંભ કરો</translation>
<translation id="8117451130807776954">આ અઠવાડિયે</translation>
<translation id="819205353528511139">પૂર્ણ સ્ક્રીન મોડમાં મૂવી ચલાવો</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">કૅપ્શન્સ</translation>
<translation id="835897206747267392">અમાન્ય મૂલ્ય.</translation>
+<translation id="8415319359811155763">ભાગ</translation>
<translation id="8433900881053900389">ટુલબાર</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ફાઇલો</translation>
<translation id="8451268428117625855">કૃપા કરીને કોઈ ફાઇલ પસંદ કરો.</translation>
<translation id="8461852803063341183">રેડિઓ બટન</translation>
+<translation id="8474886197722836894">સમર્પણ</translation>
+<translation id="8531739829932800271">ભૂલ સુધારાની સૂચિ</translation>
<translation id="8534579021159131403">મિનિટ</translation>
<translation id="8541249477527128034">મીડિયાનું નિયંત્રણ</translation>
+<translation id="8550857728288566671">ગ્રાફિક્સ પ્રતીક</translation>
<translation id="8583702881314752957">વિવરણ સૂચિ</translation>
<translation id="8597182159515967513">મથાળું</translation>
+<translation id="860475260694818407">અનુક્રમણિકા</translation>
<translation id="8613126697340063924">રિમોટ પ્લેબેકનું નિયંત્રણ કરો</translation>
+<translation id="862370744433916922">(સબટાઇટલ)</translation>
<translation id="8741316211671074806">ચિત્ર-માં-ચિત્ર</translation>
<translation id="8750798805984357768">કૃપા કરીને આ વિકલ્પોમાંથી કોઈ એક પસંદ કરો.</translation>
<translation id="8785498733064193001">પ્લેબૅક શરૂ કરો</translation>
+<translation id="8808573423886751634">પ્રકરણ</translation>
<translation id="8845239796550121995">હમણાં તમારા TV પર કાસ્ટ કરી રહ્યાં છીએ</translation>
<translation id="8851136666856101339">મુખ્ય</translation>
<translation id="8875657656876809964">વીડિઓ પ્લેબૅક ભૂલ</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">અન્ય...</translation>
<translation id="9138385573473225930">ચેતવણી</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> થી શરૂ કરીને</translation>
+<translation id="9168329111483466115">ફૂટનોટ</translation>
<translation id="947831847158436616">કોષ</translation>
<translation id="966787709310836684">મેનૂ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hi.xtb b/chromium/content/app/strings/translations/content_strings_hi.xtb
index bc6bdfe1537..422a5cf250b 100644
--- a/chromium/content/app/strings/translations/content_strings_hi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hi.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">पूरक</translation>
<translation id="1206619573307042055">मार्की</translation>
<translation id="1206693055195146388">स्लाइडर</translation>
+<translation id="1211441953136645838">एंड नोट</translation>
<translation id="1281252709823657822">संवाद</translation>
+<translation id="1335095011850992622">क्रेडिट</translation>
<translation id="1342835525016946179">लेख</translation>
<translation id="1359897965706325498">बैनर</translation>
<translation id="1589122976691792535">क्षेत्र</translation>
<translation id="1591562245178063882">इस माह</translation>
<translation id="1637811476055996098">फ़ाइलें चुनें</translation>
+<translation id="1650423536718072820">पुलकोट</translation>
<translation id="1729654308190250600">कृपया गैर-खाली ईमेल पता डालें.</translation>
<translation id="1758486001363313524">अन्य...</translation>
<translation id="1806710327868736751">सूचना संवाद</translation>
<translation id="1821985195704844674">ट्री ग्रिड</translation>
<translation id="1822429046913737220">पूर्वाह्न/अपराह्न</translation>
<translation id="1832974991323546415">दूरस्थ डिवाइस पर चलाएं</translation>
+<translation id="1907737156431278478">उदाहरण</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">स्थिति</translation>
<translation id="1938124657309484470">मान <ph name="MAXIMUM_DATE_OR_TIME" /> या पहले का होना चाहिए.</translation>
<translation id="1993104285338243655">स्क्रीन शेयर करने पर स्विच किया गया</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' का '<ph name="INVALIDDOMAIN" />' में गलत स्थान पर उपयोग किया गया है.</translation>
<translation id="2148716181193084225">आज</translation>
+<translation id="2158401438286456825">पेज सूची</translation>
<translation id="2226276347425096477">कृपया इस टेक्स्ट को <ph name="MAX_CHARACTERS" /> वर्णों या कम तक छोटा करें (वर्तमान में आप <ph name="CURRENT_LENGTH" /> वर्णों का उपयोग कर रहे हैं).</translation>
<translation id="2247351761944213033">सप्ताह <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ट्रैक <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">चेकबॉक्स</translation>
+<translation id="2311842470354187719">नया पेज</translation>
<translation id="2335594187091864976">दिनांक और समय पिकर</translation>
<translation id="248395913932153421">दिन</translation>
<translation id="2507943997699731163">कृपया इस फ़ील्ड को भरें.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">चलाएं</translation>
<translation id="2613802280814924224">कृपया कोई मान्य मान डालें. निकटतम मान्य मान <ph name="VALID_VALUE" /> है.</translation>
<translation id="2653659639078652383">सबमिट करें</translation>
+<translation id="2657045182931379222">ग्राफ़िक्स ऑब्जेक्ट</translation>
<translation id="2674318244760992338">पाद लेख</translation>
<translation id="2709516037105925701">ऑटोमैटिक भरना</translation>
<translation id="2723001399770238859">ऑडियो</translation>
@@ -51,11 +58,11 @@
<translation id="2940813599313844715">ऑब्जेक्ट</translation>
<translation id="2942448076852699108">हाइलाइट की गई सामग्री</translation>
<translation id="3040011195152428237">संपर्क</translation>
-<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
-<translation id="3075154866155599887">कृपया मान्य मान डालें. फ़ील्ड अधूरी है या उसमें एक अमान्य दिनांक है.</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> एमबी</translation>
+<translation id="3075154866155599887">कृपया सही मान डालें. फ़ील्ड अधूरी है या उसमें डाली गई तारीख गलत है.</translation>
<translation id="3078740164268491126">तालिका</translation>
<translation id="3086746722712840547">नोट</translation>
-<translation id="310520048233152454">कृपया URL लिखें.</translation>
+<translation id="310520048233152454">कृपया यूआरएल डालें.</translation>
<translation id="3175736971608411871">टाइमर</translation>
<translation id="3199563858620722075">कॉम्बो बॉक्स</translation>
<translation id="3450233048674729344">मान <ph name="MAXIMUM" /> से कम या इसके बराबर होना चाहिए.</translation>
@@ -64,36 +71,47 @@
<translation id="3639613635497528239">फ़िल्म के शेष सेकंड</translation>
<translation id="3706100364254443312">स्विच करें</translation>
<translation id="3732799496749320381">mm</translation>
-<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> जीबी</translation>
<translation id="3785482301506746191">फ़िल्म समय स्क्रबर</translation>
<translation id="3808586225841795776">शब्द</translation>
<translation id="3822383571486410024">कृपया इस लेख को <ph name="MIN_CHARACTERS" /> वर्णों या अधिक तक बढ़ाएं (वर्तमान में आप <ph name="CURRENT_LENGTH" /> वर्णों का उपयोग कर रहे हैं).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
<translation id="3846214748874656680">पूर्णस्क्रीन से बाहर निकलें</translation>
+<translation id="3920932319529768807">निष्कर्ष</translation>
<translation id="3924558731517983934">ऐप्लिकेशन</translation>
+<translation id="3944740393230681990">प्रस्तावना</translation>
<translation id="3960700977367013758">स्क्रॉल बार</translation>
<translation id="4103419683916926126">मिलीसेकंड</translation>
<translation id="4151657705144244502">ग्राफ़‍िक</translation>
+<translation id="4193965531860883258">भूमिका</translation>
<translation id="4201051445878709314">पिछला माह दिखाएं</translation>
<translation id="421884353938374759">रंग पिकर</translation>
<translation id="4248100235867064564">मेनू बार</translation>
<translation id="4254339807215791271">सामग्री की जानकारी</translation>
<translation id="4360991593054037559">कृपया कोई मान्य मान डालें. दो निकटतम मान्य मान <ph name="VALID_VALUE_LOW" /> और <ph name="VALID_VALUE_HIGHER" /> हैं.</translation>
+<translation id="4384583879834880242">सवाल और जवाब</translation>
<translation id="4413860115965805769">मेनू बटन</translation>
+<translation id="4446524499724042288">संदर्भ के लिए शब्दावली</translation>
<translation id="4522570452068850558">विवरण</translation>
<translation id="4597532268155981612">फ़ॉर्म</translation>
<translation id="4661075872484491155">ट्री</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
+<translation id="4668956016107839909">परिशिष्ट</translation>
+<translation id="4742539557769756338">कवर</translation>
<translation id="4757246831282535685">टैब फलक</translation>
<translation id="4763480195061959176">वीडियो</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">कृपया कोई संख्या डालें.</translation>
+<translation id="4912536737030637138">संदर्भ सूची प्रविष्टि</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> चुने गए</translation>
<translation id="4992066212339426712">अनम्यूट करें</translation>
<translation id="49969490063480558">कृपया '<ph name="ATSIGN" />' के बाद आने वाला भाग डालें. '<ph name="INVALIDADDRESS" />' अधूरा है.</translation>
<translation id="5034860022980953847">प्रगति संकेतक</translation>
+<translation id="5093189678851173835">इपिग्राफ़</translation>
<translation id="5117590920725113268">अगला माह दिखाएं</translation>
<translation id="512758898067543763">पंक्ति शीर्षलेख</translation>
+<translation id="5143125788380636750">उपसंहार</translation>
+<translation id="5153163864850940242">यह वीडियो पिक्चर में पिक्चर मोड में चल रहा है</translation>
<translation id="5164977714490026579">मान <ph name="MINIMUM" /> से कम या इसके बराबर होना चाहिए.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">कृपया '<ph name="ATSIGN" />' के पहले वाला भाग डालें. '<ph name="INVALIDADDRESS" />' अधूरा है.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">अनम्यूट करें</translation>
<translation id="561939826962581046">समय</translation>
<translation id="5630795885300617244">10 सेकंड आगे या पीछे जाने के लिए बाएं या दाएं पर दो बार टैप करें</translation>
+<translation id="5631759159893697722">संक्षेप</translation>
<translation id="5641012560118721995">प्लेबैक रोकें</translation>
<translation id="5643186887447432888">बटन</translation>
<translation id="5677946354068040947">अधिक विकल्प</translation>
+<translation id="576709008726043716">परिचय</translation>
<translation id="57838592816432529">म्यूट करें</translation>
<translation id="5860033963881614850">बंद</translation>
<translation id="588258955323874662">पूर्णस्‍क्रीन</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">वर्ष</translation>
<translation id="6023896073578205740">सूची बॉक्स</translation>
<translation id="6101327004457443354">ऑडियो ट्रैक अनम्यूट करें</translation>
+<translation id="6150588977291308318">संदर्भ सूची</translation>
<translation id="6164829606128959761">मीटर</translation>
+<translation id="6166809985690652833">उपसंहार</translation>
+<translation id="6213469881011901533">शब्दावली</translation>
<translation id="6398862346408813489">माह चयन फलक दिखाएं</translation>
<translation id="6404546809543547843">ऑडियो समय स्क्रबर</translation>
+<translation id="6453774872122745852">धन्यवाद</translation>
<translation id="648732519525291180">समय पिकर</translation>
<translation id="6550675742724504774">विकल्प</translation>
-<translation id="6564313821541007458">अब पिक्चर में पिक्चर मोड में</translation>
<translation id="658823671542763450">पूर्ण स्क्रीन में प्रवेश करें</translation>
<translation id="663493177488814956">फ़ीड</translation>
<translation id="6637586476836377253">लॉग</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">टूलटिप</translation>
<translation id="6790428901817661496">चलाएं</translation>
<translation id="6820355525329141109">प्लग इन लोड नहीं किया जा सका.</translation>
+<translation id="6820615603175220800">संदर्भ सूची का संदर्भ</translation>
<translation id="6843725295806269523">म्यूट करें</translation>
<translation id="6853785296079745596">बंद कैप्शन छिपाएं</translation>
<translation id="6885760532393684712">निर्देशिका</translation>
+<translation id="689129560213475294">कॉलफ़न</translation>
<translation id="6934078000481955284">ब्लॉककोट</translation>
<translation id="6941933287844615239">मीडिया डाउनलोड करें</translation>
<translation id="6989848892321993519">कृपया इस लेख को <ph name="MIN_CHARACTERS" /> या उससे ज़्यादा वर्णों तक बढ़ाएं (आप इस समय 1 वर्ण का उपयोग कर रहे हैं).</translation>
<translation id="709897737746224366">कृपया अनुरोधित प्रारूप का मिलान करें.</translation>
+<translation id="7139483182332611405">आमुख</translation>
<translation id="7223624360433298498">बीता हुआ समय</translation>
<translation id="7263440858009898357">कृपया सूची में किसी आइटम को चुनें.</translation>
<translation id="727747134524199931">स्तंभ शीर्षलेख</translation>
+<translation id="7353453495576941748">क्रेडिट</translation>
<translation id="7364796246159120393">फ़ाइल चुनें</translation>
<translation id="739024184232394898">अन्य...</translation>
+<translation id="7405738980073107433">एंडनोट</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">टैब</translation>
<translation id="7514365320538308">डाउनलोड करें</translation>
+<translation id="7529102961911894712">बैक लिंक</translation>
+<translation id="7647456547678091388">सलाह</translation>
+<translation id="7661956066982048809">ग्राफ़िक्स दस्तावेज़</translation>
<translation id="7673697353781729403">घंटे</translation>
+<translation id="7681220483256441252">इंडेक्स</translation>
<translation id="7720026100085573005">शेष समय</translation>
<translation id="7740016676195725605">बंद कैप्शन दिखाना रोकें</translation>
<translation id="7740050170769002709">HTML सामग्री</translation>
@@ -160,28 +192,37 @@
<translation id="7891486169920085145">विभाजक</translation>
<translation id="795667975304826397">कोई फाइल नहीं चुनी गई</translation>
<translation id="8053789581856978548">लेख फ़ील्ड खोजें</translation>
+<translation id="8057695513531652401">सूचना</translation>
+<translation id="8105797009065549151">नोट संदर्भ</translation>
<translation id="8115662671911883373">बंद कैप्शन दिखाना प्रारंभ करें</translation>
<translation id="8117451130807776954">इस सप्ताह</translation>
<translation id="819205353528511139">फ़िल्म को पूर्ण स्क्रीन मोड में चलाएं</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">कैप्शन</translation>
<translation id="835897206747267392">अमान्य मान.</translation>
+<translation id="8415319359811155763">भाग</translation>
<translation id="8433900881053900389">टूलबार</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फ़ाइल</translation>
<translation id="8451268428117625855">कृपया किसी फ़ाइल को चुनें.</translation>
<translation id="8461852803063341183">रेडियो बटन</translation>
+<translation id="8474886197722836894">लगन</translation>
+<translation id="8531739829932800271">गलतियां</translation>
<translation id="8534579021159131403">मिनट</translation>
<translation id="8541249477527128034">मीडिया नियंत्रण</translation>
+<translation id="8550857728288566671">ग्राफ़िक्स चिह्न</translation>
<translation id="8583702881314752957">परिभाषा सूची</translation>
<translation id="8597182159515967513">हेडिंग</translation>
+<translation id="860475260694818407">विषय सूची</translation>
<translation id="8613126697340063924">दूरस्थ प्लेबैक नियंत्रित करें</translation>
+<translation id="862370744433916922">सबटाइटल</translation>
<translation id="8741316211671074806">पिक्चर में पिक्चर</translation>
<translation id="8750798805984357768">कृपया इनमें से कोई विकल्प चुनें.</translation>
<translation id="8785498733064193001">प्लेबैक शुरू करें</translation>
+<translation id="8808573423886751634">पाठ</translation>
<translation id="8845239796550121995">अब आपके टीवी पर कास्ट हो रहा है</translation>
<translation id="8851136666856101339">मुख्य</translation>
<translation id="8875657656876809964">वीडियो चलाने में गड़बड़ी</translation>
-<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> केबी</translation>
<translation id="8987927404178983737">माह</translation>
<translation id="901493112792887934">वर्तमान समय, सेकंड में</translation>
<translation id="9048119486235211610">मार्गदर्शक</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">अन्य...</translation>
<translation id="9138385573473225930">सूचना</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> से प्रारंभ हो रहा है</translation>
+<translation id="9168329111483466115">फ़ुटनोट</translation>
<translation id="947831847158436616">सेल</translation>
<translation id="966787709310836684">मेनू</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hr.xtb b/chromium/content/app/strings/translations/content_strings_hr.xtb
index b2d751d3dfb..1f23cd9eec2 100644
--- a/chromium/content/app/strings/translations/content_strings_hr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hr.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">dopunski</translation>
<translation id="1206619573307042055">pomični tekst</translation>
<translation id="1206693055195146388">klizač</translation>
+<translation id="1211441953136645838">završna napomena</translation>
<translation id="1281252709823657822">dijalog</translation>
+<translation id="1335095011850992622">zasluge</translation>
<translation id="1342835525016946179">članak</translation>
<translation id="1359897965706325498">natpis</translation>
<translation id="1589122976691792535">regija</translation>
<translation id="1591562245178063882">Ovaj mjesec</translation>
<translation id="1637811476055996098">Odabir datoteka</translation>
+<translation id="1650423536718072820">izdvojeno</translation>
<translation id="1729654308190250600">Unesite e-adresu koja nije prazna vrijednost.</translation>
<translation id="1758486001363313524">Drugo...</translation>
<translation id="1806710327868736751">dijaloški okvir upozorenja</translation>
<translation id="1821985195704844674">rešetka u obliku stabla</translation>
<translation id="1822429046913737220">prijepodne/poslijepodne</translation>
<translation id="1832974991323546415">reproduciraj na udaljenom uređaju</translation>
+<translation id="1907737156431278478">primjer</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Vrijednost mora biti <ph name="MAXIMUM_DATE_OR_TIME" /> ili prije toga.</translation>
<translation id="1993104285338243655">Prebačeno na zrcaljenje</translation>
<translation id="2060505056492490888">Znak "<ph name="DOT" />" upotrebljava se na pogrešnom položaju u domeni "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Danas</translation>
+<translation id="2158401438286456825">popis stranica</translation>
<translation id="2226276347425096477">Skratite taj tekst na <ph name="MAX_CHARACTERS" /> znakova ili manje (trenutačno upotrebljavate <ph name="CURRENT_LENGTH" /> znakova).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. tjedan, <ph name="YEAR" />. godina</translation>
<translation id="2277199496770840904">Zapis <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">potvrdni okvir</translation>
+<translation id="2311842470354187719">prijelom stranice</translation>
<translation id="2335594187091864976">alat za odabir datuma i vremena</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Ispunite ovo polje.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">reprodukcija</translation>
<translation id="2613802280814924224">Unesite važeću vrijednost. Najbliža je važeća vrijednost <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Pošalji</translation>
+<translation id="2657045182931379222">grafički objekt</translation>
<translation id="2674318244760992338">podnožje</translation>
<translation id="2709516037105925701">Automatsko popunjavanje</translation>
<translation id="2723001399770238859">zvuk</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Produljite broj znakova u tekstu na minimalno <ph name="MIN_CHARACTERS" />. Trenutačno imate premalo znakova (<ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Dio adrese ispred znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Izlaz iz punog zaslona</translation>
+<translation id="3920932319529768807">zaključak</translation>
<translation id="3924558731517983934">aplikacija</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">klizač</translation>
<translation id="4103419683916926126">Milisekunde</translation>
<translation id="4151657705144244502">slika</translation>
+<translation id="4193965531860883258">predgovor</translation>
<translation id="4201051445878709314">Prikaži prethodni mjesec</translation>
<translation id="421884353938374759">odabir boja</translation>
<translation id="4248100235867064564">traka izbornika</translation>
<translation id="4254339807215791271">informacije o sadržaju</translation>
<translation id="4360991593054037559">Unesite važeću vrijednost. Dvije su najbliže važeće vrijednosti <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Pitanja i odgovori</translation>
<translation id="4413860115965805769">gumb izbornika</translation>
+<translation id="4446524499724042288">referenca iz pojmovnika</translation>
<translation id="4522570452068850558">Detalji</translation>
<translation id="4597532268155981612">obrazac</translation>
<translation id="4661075872484491155">stablo</translation>
<translation id="4664250907885839816">Dio adrese iza znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">dodatak</translation>
+<translation id="4742539557769756338">naslovnica</translation>
<translation id="4757246831282535685">ploča kartice</translation>
<translation id="4763480195061959176">videozapis</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Unesite broj.</translation>
+<translation id="4912536737030637138">bibliografski unos</translation>
<translation id="4975562563186953947">Odabrano: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Uključi zvuk</translation>
<translation id="49969490063480558">Unesite dio adrese iza znaka "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" nije potpuna e-adresa.</translation>
<translation id="5034860022980953847">pokazivač napretka</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Prikaži sljedeći mjesec</translation>
<translation id="512758898067543763">zaglavlje retka</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Ovaj se videozapis prikazuje u značajci slike u slici</translation>
<translation id="5164977714490026579">Vrijednost mora biti <ph name="MINIMUM" /> ili veća.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Unesite dio adrese ispred znaka "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" nije potpuna e-adresa.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">uključivanje zvuka</translation>
<translation id="561939826962581046">vrijeme</translation>
<translation id="5630795885300617244">Dvaput dodirnite lijevo ili desno za preskakanje od 10 s</translation>
+<translation id="5631759159893697722">sažetak</translation>
<translation id="5641012560118721995">pauziranje reprodukcije</translation>
<translation id="5643186887447432888">gumb</translation>
<translation id="5677946354068040947">više opcija</translation>
+<translation id="576709008726043716">uvod</translation>
<translation id="57838592816432529">Isključi zvuk</translation>
<translation id="5860033963881614850">Isključeno</translation>
<translation id="588258955323874662">Puni zaslon</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Godina</translation>
<translation id="6023896073578205740">okvir s popisom</translation>
<translation id="6101327004457443354">uključivanje zvučnog zapisa</translation>
+<translation id="6150588977291308318">bibliografija</translation>
<translation id="6164829606128959761">mjerač</translation>
+<translation id="6166809985690652833">pogovor</translation>
+<translation id="6213469881011901533">pojmovnik</translation>
<translation id="6398862346408813489">Prikaži ploču za odabir mjeseca</translation>
<translation id="6404546809543547843">klizač vremena audiozapisa</translation>
+<translation id="6453774872122745852">zahvale</translation>
<translation id="648732519525291180">alat za odabir vremena</translation>
<translation id="6550675742724504774">Opcije</translation>
-<translation id="6564313821541007458">Sada ste u načinu slike u slici</translation>
<translation id="658823671542763450">otvaranje na cijelom zaslonu</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">zap</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">opis</translation>
<translation id="6790428901817661496">Reproduciraj</translation>
<translation id="6820355525329141109">Nije bilo moguće učitati dodatak.</translation>
+<translation id="6820615603175220800">bibliografska referenca</translation>
<translation id="6843725295806269523">isključi ton</translation>
<translation id="6853785296079745596">sakrivanje titlova</translation>
<translation id="6885760532393684712">direktorij</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">uvučeni citat</translation>
<translation id="6941933287844615239">preuzmi medij</translation>
<translation id="6989848892321993519">Produljite broj znakova u tekstu na minimalno <ph name="MIN_CHARACTERS" /> (trenutačno imate 1 znak).</translation>
<translation id="709897737746224366">Udovoljite zadanom formatu.</translation>
+<translation id="7139483182332611405">predgovor</translation>
<translation id="7223624360433298498">proteklo vrijeme</translation>
<translation id="7263440858009898357">Odaberite stavku s popisa.</translation>
<translation id="727747134524199931">zaglavlje stupca</translation>
+<translation id="7353453495576941748">zasluga</translation>
<translation id="7364796246159120393">Odaberi datoteku</translation>
<translation id="739024184232394898">Drugo...</translation>
+<translation id="7405738980073107433">završne napomene</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">kart</translation>
<translation id="7514365320538308">Preuzmi</translation>
+<translation id="7529102961911894712">povratna veza</translation>
+<translation id="7647456547678091388">savjet</translation>
+<translation id="7661956066982048809">grafički dokument</translation>
<translation id="7673697353781729403">Sati</translation>
+<translation id="7681220483256441252">indeks</translation>
<translation id="7720026100085573005">preostalo vrijeme</translation>
<translation id="7740016676195725605">zaustavljanje prikazivanja titlova</translation>
<translation id="7740050170769002709">HTML sadržaj</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">razdjelnik</translation>
<translation id="795667975304826397">Nije odabrana niti jedna datoteka.</translation>
<translation id="8053789581856978548">pretraži tekstno polje</translation>
+<translation id="8057695513531652401">obavijest</translation>
+<translation id="8105797009065549151">referenca bilješke</translation>
<translation id="8115662671911883373">početak prikazivanja titlova</translation>
<translation id="8117451130807776954">Ovaj tjedan</translation>
<translation id="819205353528511139">reprodukcija filma na cijelom zaslonu</translation>
<translation id="8199524924445686405">gggg</translation>
<translation id="8284326494547611709">Titlovi</translation>
<translation id="835897206747267392">Nevažeća vrijednost.</translation>
+<translation id="8415319359811155763">dio</translation>
<translation id="8433900881053900389">alatna traka</translation>
<translation id="8444882422881193423">Broj datoteka: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Odaberite datoteku.</translation>
<translation id="8461852803063341183">izborni gumb</translation>
+<translation id="8474886197722836894">posveta</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minute</translation>
<translation id="8541249477527128034">kontrola medija</translation>
+<translation id="8550857728288566671">grafički simbol</translation>
<translation id="8583702881314752957">popis definicija</translation>
<translation id="8597182159515967513">naslov</translation>
+<translation id="860475260694818407">sadržaj</translation>
<translation id="8613126697340063924">upravljaj daljinskom reprodukcijom</translation>
+<translation id="862370744433916922">titl</translation>
<translation id="8741316211671074806">Slika u slici</translation>
<translation id="8750798805984357768">Izaberite jednu od tih opcija.</translation>
<translation id="8785498733064193001">početak reprodukcije</translation>
+<translation id="8808573423886751634">poglavlje</translation>
<translation id="8845239796550121995">Emitira se na televizoru</translation>
<translation id="8851136666856101339">glav</translation>
<translation id="8875657656876809964">Pogreška pri reprodukciji videozapisa</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Drugo...</translation>
<translation id="9138385573473225930">upozorenje</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, počevši od <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">fusnota</translation>
<translation id="947831847158436616">ćelija</translation>
<translation id="966787709310836684">izbornik</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hu.xtb b/chromium/content/app/strings/translations/content_strings_hu.xtb
index d8512555347..00378120757 100644
--- a/chromium/content/app/strings/translations/content_strings_hu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hu.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">kiegészítő</translation>
<translation id="1206619573307042055">fényújság</translation>
<translation id="1206693055195146388">csúszka</translation>
+<translation id="1211441953136645838">záró jegyzet</translation>
<translation id="1281252709823657822">párbeszédpanel</translation>
+<translation id="1335095011850992622">készítők</translation>
<translation id="1342835525016946179">cikk</translation>
<translation id="1359897965706325498">szalaghirdetés</translation>
<translation id="1589122976691792535">régió</translation>
<translation id="1591562245178063882">Ebben a hónapban</translation>
<translation id="1637811476055996098">Fájlok kiválasztása</translation>
+<translation id="1650423536718072820">kiemelt idézet</translation>
<translation id="1729654308190250600">Kérjük, ne hagyja üresen az e-mail-cím mezőjét.</translation>
<translation id="1758486001363313524">Más...</translation>
<translation id="1806710327868736751">értesítő párbeszédpanel</translation>
<translation id="1821985195704844674">farács</translation>
<translation id="1822429046913737220">de./du.</translation>
<translation id="1832974991323546415">lejátszás távoli eszközön</translation>
+<translation id="1907737156431278478">példa</translation>
<translation id="1921819250265091946">nn</translation>
<translation id="1930711995431081526">állapot</translation>
<translation id="1938124657309484470">Az érték <ph name="MAXIMUM_DATE_OR_TIME" /> vagy azt megelőző kell, hogy legyen.</translation>
<translation id="1993104285338243655">Átváltott tükrözésre</translation>
<translation id="2060505056492490888">A „<ph name="DOT" />” rossz helyen van a(z) „<ph name="INVALIDDOMAIN" />” címben.</translation>
<translation id="2148716181193084225">Ma</translation>
+<translation id="2158401438286456825">oldallista</translation>
<translation id="2226276347425096477">Kérjük, rövidítse le a szöveget legfeljebb <ph name="MAX_CHARACTERS" /> karakterre (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hét, <ph name="YEAR" /></translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. szám</translation>
<translation id="2291999235780842123">jelölőnégyzet</translation>
+<translation id="2311842470354187719">oldaltörés</translation>
<translation id="2335594187091864976">dátum- és időválasztó</translation>
<translation id="248395913932153421">nap</translation>
<translation id="2507943997699731163">Kérjük, töltse ki ezt a mezőt.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">lejátszás</translation>
<translation id="2613802280814924224">Kérjük, érvényes értéket adjon meg. A legközelebbi érvényes érték <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Elküldés</translation>
+<translation id="2657045182931379222">grafikus objektum</translation>
<translation id="2674318244760992338">lábléc</translation>
<translation id="2709516037105925701">Automatikus kitöltés</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Kérjük, <ph name="MIN_CHARACTERS" /> karakter hosszú vagy annál hosszabb szöveget adjon meg (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
<translation id="383465348367842624">A „<ph name="ATSIGN" />” előtti rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
<translation id="3846214748874656680">Teljes képernyő – ki</translation>
+<translation id="3920932319529768807">összefoglalás</translation>
<translation id="3924558731517983934">alkalmazás</translation>
+<translation id="3944740393230681990">prológus</translation>
<translation id="3960700977367013758">görgetősáv</translation>
<translation id="4103419683916926126">Ezredmásodperc</translation>
<translation id="4151657705144244502">grafika</translation>
+<translation id="4193965531860883258">előszó</translation>
<translation id="4201051445878709314">Az előző hónap megjelenítése</translation>
<translation id="421884353938374759">színválasztó</translation>
<translation id="4248100235867064564">menüsor</translation>
<translation id="4254339807215791271">tartalominformáció</translation>
<translation id="4360991593054037559">Kérjük, érvényes értéket adjon meg. A két legközelebbi érvényes érték <ph name="VALID_VALUE_LOW" /> és <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Kérdések és válaszok</translation>
<translation id="4413860115965805769">menügomb</translation>
+<translation id="4446524499724042288">szószedet-hivatkozás</translation>
<translation id="4522570452068850558">Részletek</translation>
<translation id="4597532268155981612">űrlap</translation>
<translation id="4661075872484491155">fa</translation>
<translation id="4664250907885839816">A „<ph name="ATSIGN" />” utáni rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
+<translation id="4668956016107839909">függelék</translation>
+<translation id="4742539557769756338">borító</translation>
<translation id="4757246831282535685">lappanel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Kérjük, adjon meg egy számot.</translation>
+<translation id="4912536737030637138">bibliográfiai bejegyzés</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> kiválasztva</translation>
<translation id="4992066212339426712">Némítás feloldása</translation>
<translation id="49969490063480558">Kérjük, adja meg a „<ph name="ATSIGN" />” utáni részt is. A(z) „<ph name="INVALIDADDRESS" />” cím nem teljes.</translation>
<translation id="5034860022980953847">folyamatjelző</translation>
+<translation id="5093189678851173835">mottó</translation>
<translation id="5117590920725113268">A következő hónap megjelenítése</translation>
<translation id="512758898067543763">sorfejléc</translation>
+<translation id="5143125788380636750">végszó</translation>
+<translation id="5153163864850940242">A videó lejátszása kép a képben módban történik</translation>
<translation id="5164977714490026579">Az érték legyen nagyobb vagy egyenlő, mint <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Kérjük, adja meg a „<ph name="ATSIGN" />” előtti részt is. A „<ph name="INVALIDADDRESS" />” cím nem teljes.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">némítás feloldása</translation>
<translation id="561939826962581046">idő</translation>
<translation id="5630795885300617244">A jobb/bal oldalon duplán koppintva ugorhat előre/vissza 10 másodpercet</translation>
+<translation id="5631759159893697722">absztrakt</translation>
<translation id="5641012560118721995">lejátszás szüneteltetése</translation>
<translation id="5643186887447432888">gomb</translation>
<translation id="5677946354068040947">további beállítások</translation>
+<translation id="576709008726043716">bevezetés</translation>
<translation id="57838592816432529">Némítás</translation>
<translation id="5860033963881614850">Kikapcsolva</translation>
<translation id="588258955323874662">Teljes képernyő</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Év</translation>
<translation id="6023896073578205740">listamező</translation>
<translation id="6101327004457443354">hangsáv némításának feloldása</translation>
+<translation id="6150588977291308318">bibliográfia</translation>
<translation id="6164829606128959761">mérő</translation>
+<translation id="6166809985690652833">utószó</translation>
+<translation id="6213469881011901533">szószedet</translation>
<translation id="6398862346408813489">A hónapválasztási panel megjelenítése</translation>
<translation id="6404546809543547843">hang idővonalának vezérlője</translation>
+<translation id="6453774872122745852">köszönetnyilvánítás</translation>
<translation id="648732519525291180">időválasztó</translation>
<translation id="6550675742724504774">Beállítások</translation>
-<translation id="6564313821541007458">Most kép a képben módban van</translation>
<translation id="658823671542763450">teljes képernyős nézet</translation>
<translation id="663493177488814956">hírcsatorna</translation>
<translation id="6637586476836377253">napló</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">elemleírás</translation>
<translation id="6790428901817661496">Játék</translation>
<translation id="6820355525329141109">Nem sikerült betölteni a beépülő modult.</translation>
+<translation id="6820615603175220800">bibliográfiai hivatkozás</translation>
<translation id="6843725295806269523">némítás</translation>
<translation id="6853785296079745596">feliratok elrejtése</translation>
<translation id="6885760532393684712">címtár</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">bekezdésszintű idézet</translation>
<translation id="6941933287844615239">médiafájlok letöltése</translation>
<translation id="6989848892321993519">Legalább <ph name="MIN_CHARACTERS" /> karakter hosszú szöveget adjon meg (jelenleg 1 karaktert használ).</translation>
<translation id="709897737746224366">Kérjük, tartsa magát a kívánt formátumhoz.</translation>
+<translation id="7139483182332611405">bevezető</translation>
<translation id="7223624360433298498">eltelt idő</translation>
<translation id="7263440858009898357">Kérjük, válasszon egyet a lista elemei közül.</translation>
<translation id="727747134524199931">oszlopfejléc</translation>
+<translation id="7353453495576941748">elismerés</translation>
<translation id="7364796246159120393">Fájl kiválasztása</translation>
<translation id="739024184232394898">Más...</translation>
+<translation id="7405738980073107433">záró jegyzetek</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Letöltés</translation>
+<translation id="7529102961911894712">visszamutató link</translation>
+<translation id="7647456547678091388">tipp</translation>
+<translation id="7661956066982048809">grafikus dokumentum</translation>
<translation id="7673697353781729403">Óra</translation>
+<translation id="7681220483256441252">tárgymutató</translation>
<translation id="7720026100085573005">hátralévő idő</translation>
<translation id="7740016676195725605">feliratok elrejtése</translation>
<translation id="7740050170769002709">HTML-tartalom</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">felosztó</translation>
<translation id="795667975304826397">Nincs fájl kiválasztva</translation>
<translation id="8053789581856978548">keresés a szövegmezőben</translation>
+<translation id="8057695513531652401">közlés</translation>
+<translation id="8105797009065549151">jegyzethivatkozás</translation>
<translation id="8115662671911883373">feliratok megjelenítése</translation>
<translation id="8117451130807776954">Ezen a héten</translation>
<translation id="819205353528511139">film lejátszása teljes képernyős nézetben</translation>
<translation id="8199524924445686405">éééé</translation>
<translation id="8284326494547611709">Feliratok</translation>
<translation id="835897206747267392">Érvénytelen érték.</translation>
+<translation id="8415319359811155763">rész</translation>
<translation id="8433900881053900389">eszköztár</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fájl</translation>
<translation id="8451268428117625855">Válasszon egy fájlt.</translation>
<translation id="8461852803063341183">választógomb</translation>
+<translation id="8474886197722836894">ajánlás</translation>
+<translation id="8531739829932800271">hibajegyzék</translation>
<translation id="8534579021159131403">Perc</translation>
<translation id="8541249477527128034">médiavezérlő</translation>
+<translation id="8550857728288566671">grafikus szimbólum</translation>
<translation id="8583702881314752957">definíciós lista</translation>
<translation id="8597182159515967513">fejléc</translation>
+<translation id="860475260694818407">tartalomjegyzék</translation>
<translation id="8613126697340063924">távoli lejátszás kezelése</translation>
+<translation id="862370744433916922">felirat</translation>
<translation id="8741316211671074806">Kép a képben</translation>
<translation id="8750798805984357768">Kérjük, válassza ki az egyik opciót.</translation>
<translation id="8785498733064193001">lejátszás indítása</translation>
+<translation id="8808573423886751634">fejezet</translation>
<translation id="8845239796550121995">Átküldés a tévére folyamatban</translation>
<translation id="8851136666856101339">fő</translation>
<translation id="8875657656876809964">Videólejátszási hiba</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Más...</translation>
<translation id="9138385573473225930">értesítés</translation>
<translation id="9155987714137265666"><ph name="WEEK" />. hét (<ph name="WEEK_START_DATE" />-i dátummal kezdődik)</translation>
+<translation id="9168329111483466115">lábjegyzet</translation>
<translation id="947831847158436616">cella</translation>
<translation id="966787709310836684">menü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_id.xtb b/chromium/content/app/strings/translations/content_strings_id.xtb
index e2289b71cfb..e0da8db2aec 100644
--- a/chromium/content/app/strings/translations/content_strings_id.xtb
+++ b/chromium/content/app/strings/translations/content_strings_id.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">komplementer</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">penggeser</translation>
+<translation id="1211441953136645838">catatan akhir</translation>
<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">daftar penghargaan</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">spanduk</translation>
<translation id="1589122976691792535">wilayah</translation>
<translation id="1591562245178063882">Bulan ini</translation>
<translation id="1637811476055996098">Pilih File</translation>
+<translation id="1650423536718072820">pullquote</translation>
<translation id="1729654308190250600">Jangan mengosongkan bidang alamat email.</translation>
<translation id="1758486001363313524">Lainnya...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">kisi pohon</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">putar di perangkat jarak jauh</translation>
+<translation id="1907737156431278478">contoh</translation>
<translation id="1921819250265091946">hh</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Tanggal harus <ph name="MAXIMUM_DATE_OR_TIME" /> atau lebih awal.</translation>
<translation id="1993104285338243655">Dialihkan ke pencerminan</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' digunakan pada posisi yang salah di '<ph name="INVALIDDOMAIN" />'.</translation>
<translation id="2148716181193084225">Hari ini</translation>
+<translation id="2158401438286456825">daftar halaman</translation>
<translation id="2226276347425096477">Pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> karakter atau kurang (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Lagu <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kotak centang</translation>
+<translation id="2311842470354187719">batas halaman</translation>
<translation id="2335594187091864976">pemilih tanggal dan waktu</translation>
<translation id="248395913932153421">Hari</translation>
<translation id="2507943997699731163">Harap isi bidang ini.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">main</translation>
<translation id="2613802280814924224">Masukkan nilai yang valid. Nilai valid terdekatnya adalah <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Kirim</translation>
+<translation id="2657045182931379222">objek grafis</translation>
<translation id="2674318244760992338">footer</translation>
<translation id="2709516037105925701">Isi-Otomatis</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Perpanjang teks ini hingga <ph name="MIN_CHARACTERS" /> karakter atau lebih (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
<translation id="383465348367842624">Bagian sebelum '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="3846214748874656680">Keluar dari layar penuh</translation>
+<translation id="3920932319529768807">kesimpulan</translation>
<translation id="3924558731517983934">aplikasi</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">bilah gulir</translation>
<translation id="4103419683916926126">Milidetik</translation>
<translation id="4151657705144244502">grafis</translation>
+<translation id="4193965531860883258">kata pengantar</translation>
<translation id="4201051445878709314">Tampilkan bulan sebelumnya</translation>
<translation id="421884353938374759">pemilih warna</translation>
<translation id="4248100235867064564">bilah menu</translation>
<translation id="4254339807215791271">info konten</translation>
<translation id="4360991593054037559">Masukkan nilai yang valid. Dua nilai valid terdekat adalah <ph name="VALID_VALUE_LOW" /> dan <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Tanya Jawab</translation>
<translation id="4413860115965805769">tombol menu</translation>
+<translation id="4446524499724042288">referensi glosarium</translation>
<translation id="4522570452068850558">Detail</translation>
<translation id="4597532268155981612">formulir</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Bagian setelah '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">lampiran</translation>
+<translation id="4742539557769756338">sampul</translation>
<translation id="4757246831282535685">panel tab</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Masukkan nomor.</translation>
+<translation id="4912536737030637138">entri bibliografi</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> dipilih</translation>
<translation id="4992066212339426712">Bunyikan</translation>
<translation id="49969490063480558">Masukkan bagian setelah '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
<translation id="5034860022980953847">indikator kemajuan</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Tampilkan bulan berikutnya</translation>
<translation id="512758898067543763">judul baris</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Video ini diputar dalam Picture-in-Picture</translation>
<translation id="5164977714490026579">Nilai harus lebih besar daripada atau sama dengan <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Masukkan bagian yang diikuti dengan '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">suarakan</translation>
<translation id="561939826962581046">waktu</translation>
<translation id="5630795885300617244">Tap dua kali ke kiri atau kanan untuk melewati 10 detik</translation>
+<translation id="5631759159893697722">abstrak</translation>
<translation id="5641012560118721995">jeda pemutaran</translation>
<translation id="5643186887447432888">tombol</translation>
<translation id="5677946354068040947">opsi lainnya</translation>
+<translation id="576709008726043716">pendahuluan</translation>
<translation id="57838592816432529">Bisukan</translation>
<translation id="5860033963881614850">Nonaktif</translation>
<translation id="588258955323874662">Layar Penuh</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Tahun</translation>
<translation id="6023896073578205740">kotak daftar</translation>
<translation id="6101327004457443354">suarakan trek audio</translation>
+<translation id="6150588977291308318">bibliografi</translation>
<translation id="6164829606128959761">pengukur</translation>
+<translation id="6166809985690652833">penutup</translation>
+<translation id="6213469881011901533">glosarium</translation>
<translation id="6398862346408813489">Tampilkan panel pilihan bulan</translation>
<translation id="6404546809543547843">scrubber waktu audio</translation>
+<translation id="6453774872122745852">ucapan terima kasih</translation>
<translation id="648732519525291180">pemilih waktu</translation>
<translation id="6550675742724504774">Opsi</translation>
-<translation id="6564313821541007458">Kini dalam mode Picture-in-Picture</translation>
<translation id="658823671542763450">masuk layar penuh</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">keterangan alat</translation>
<translation id="6790428901817661496">Putar</translation>
<translation id="6820355525329141109">Tidak dapat memuat plugin.</translation>
+<translation id="6820615603175220800">referensi bibliografi</translation>
<translation id="6843725295806269523">bisukan</translation>
<translation id="6853785296079745596">sembunyikan teks</translation>
<translation id="6885760532393684712">direktori</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">download media</translation>
<translation id="6989848892321993519">Perpanjang teks ini menjadi <ph name="MIN_CHARACTERS" /> karakter atau lebih (saat ini Anda menggunakan 1 karakter).</translation>
<translation id="709897737746224366">Sesuaikan dengan format yang diminta.</translation>
+<translation id="7139483182332611405">kata pengantar</translation>
<translation id="7223624360433298498">waktu berlalu</translation>
<translation id="7263440858009898357">Pilih item pada daftar.</translation>
<translation id="727747134524199931">judul kolom</translation>
+<translation id="7353453495576941748">daftar penghargaan</translation>
<translation id="7364796246159120393">Pilih File</translation>
<translation id="739024184232394898">Lainnya...</translation>
+<translation id="7405738980073107433">catatan akhir</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Download</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7647456547678091388">tips</translation>
+<translation id="7661956066982048809">dokumen grafis</translation>
<translation id="7673697353781729403">Jam</translation>
+<translation id="7681220483256441252">indeks</translation>
<translation id="7720026100085573005">sisa waktu</translation>
<translation id="7740016676195725605">berhenti menampilkan teks</translation>
<translation id="7740050170769002709">Konten HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">pemisah</translation>
<translation id="795667975304826397">Tidak ada file yang dipilih</translation>
<translation id="8053789581856978548">bidang teks penelusuran</translation>
+<translation id="8057695513531652401">pemberitahuan</translation>
+<translation id="8105797009065549151">referensi catatan</translation>
<translation id="8115662671911883373">mulai menampilkan teks</translation>
<translation id="8117451130807776954">Minggu ini</translation>
<translation id="819205353528511139">putar film dalam mode layar penuh</translation>
<translation id="8199524924445686405">tttt</translation>
<translation id="8284326494547611709">Teks</translation>
<translation id="835897206747267392">Nilai tidak valid.</translation>
+<translation id="8415319359811155763">bagian</translation>
<translation id="8433900881053900389">bilah alat</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
<translation id="8451268428117625855">Pilih file.</translation>
<translation id="8461852803063341183">tombol radio</translation>
+<translation id="8474886197722836894">persembahan</translation>
+<translation id="8531739829932800271">erratum</translation>
<translation id="8534579021159131403">Menit</translation>
<translation id="8541249477527128034">kontrol media</translation>
+<translation id="8550857728288566671">simbol grafis</translation>
<translation id="8583702881314752957">daftar definisi</translation>
<translation id="8597182159515967513">kepala</translation>
+<translation id="860475260694818407">daftar isi</translation>
<translation id="8613126697340063924">kontrol pemutaran jarak jauh</translation>
+<translation id="862370744433916922">subjudul</translation>
<translation id="8741316211671074806">Picture-in-Picture</translation>
<translation id="8750798805984357768">Pilih salah satu opsi berikut.</translation>
<translation id="8785498733064193001">mulai pemutaran</translation>
+<translation id="8808573423886751634">bab</translation>
<translation id="8845239796550121995">Sekarang sedang mentransmisi ke TV Anda</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Error pemutaran video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Lainnya...</translation>
<translation id="9138385573473225930">notifikasi</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, dimulai pada <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">catatan kaki</translation>
<translation id="947831847158436616">sel</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_it.xtb b/chromium/content/app/strings/translations/content_strings_it.xtb
index 305c8e96347..72572258b83 100644
--- a/chromium/content/app/strings/translations/content_strings_it.xtb
+++ b/chromium/content/app/strings/translations/content_strings_it.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">elementi complementari</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">dispositivo di scorrimento</translation>
+<translation id="1211441953136645838">nota finale</translation>
<translation id="1281252709823657822">finestra di dialogo</translation>
+<translation id="1335095011850992622">ringraziamenti</translation>
<translation id="1342835525016946179">articolo</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">regione</translation>
<translation id="1591562245178063882">Questo mese</translation>
<translation id="1637811476055996098">Scegli file</translation>
+<translation id="1650423536718072820">citazione</translation>
<translation id="1729654308190250600">Inserisci un indirizzo email valido.</translation>
<translation id="1758486001363313524">Altro...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">griglia ad albero</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">riproduci su dispositivo remoto</translation>
+<translation id="1907737156431278478">esempio</translation>
<translation id="1921819250265091946">gg</translation>
<translation id="1930711995431081526">stato</translation>
<translation id="1938124657309484470">Il valore deve essere <ph name="MAXIMUM_DATE_OR_TIME" /> o precedente.</translation>
<translation id="1993104285338243655">Sei passato a mirroring</translation>
<translation id="2060505056492490888">Il segno "<ph name="DOT" />" è utilizzato in una posizione errata in "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Oggi</translation>
+<translation id="2158401438286456825">elenco pagine</translation>
<translation id="2226276347425096477">Riduci questo testo a <ph name="MAX_CHARACTERS" /> caratteri o meno (attualmente stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
<translation id="2247351761944213033">Settimana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Traccia <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casella di controllo</translation>
+<translation id="2311842470354187719">interruzione di pagina</translation>
<translation id="2335594187091864976">selettore di data e ora</translation>
<translation id="248395913932153421">Giorno</translation>
<translation id="2507943997699731163">Compila questo campo.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">riproduci</translation>
<translation id="2613802280814924224">Inserisci un valore valido. Il valore valido più vicino è <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Invia</translation>
+<translation id="2657045182931379222">oggetto grafico</translation>
<translation id="2674318244760992338">piè di pagina</translation>
<translation id="2709516037105925701">Compilazione automatica</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Prolunga questo testo a <ph name="MIN_CHARACTERS" /> o più caratteri (al momento stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
<translation id="383465348367842624">Una parte seguita da "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Esci da schermo intero</translation>
+<translation id="3920932319529768807">conclusioni</translation>
<translation id="3924558731517983934">applicazione</translation>
+<translation id="3944740393230681990">prologo</translation>
<translation id="3960700977367013758">barra di scorrimento</translation>
<translation id="4103419683916926126">Millisecondi</translation>
<translation id="4151657705144244502">immagine</translation>
+<translation id="4193965531860883258">premessa</translation>
<translation id="4201051445878709314">Mostra mese precedente</translation>
<translation id="421884353938374759">selettore colori</translation>
<translation id="4248100235867064564">barra dei menu</translation>
<translation id="4254339807215791271">informazioni sui contenuti</translation>
<translation id="4360991593054037559">Inserisci un valore valido. I due valori validi più vicini sono <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Domande e risposte</translation>
<translation id="4413860115965805769">pulsante di menu</translation>
+<translation id="4446524499724042288">riferimento glossario</translation>
<translation id="4522570452068850558">Dettagli</translation>
<translation id="4597532268155981612">modulo</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Una parte che segue "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">appendice</translation>
+<translation id="4742539557769756338">copertina</translation>
<translation id="4757246831282535685">riquadro a schede</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">ricerca</translation>
<translation id="4812940957355064477">Inserisci un numero.</translation>
+<translation id="4912536737030637138">voce bibliografica</translation>
<translation id="4975562563186953947">Elementi selezionati: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Riattiva audio</translation>
<translation id="49969490063480558">Inserisci una parte dopo "<ph name="ATSIGN" />". Il valore "<ph name="INVALIDADDRESS" />" è incompleto.</translation>
<translation id="5034860022980953847">indicatore di avanzamento</translation>
+<translation id="5093189678851173835">epigrafe</translation>
<translation id="5117590920725113268">Mostra mese successivo</translation>
<translation id="512758898067543763">intestazione di riga</translation>
+<translation id="5143125788380636750">epilogo</translation>
+<translation id="5153163864850940242">Questo video è riprodotto in modalità picture in picture</translation>
<translation id="5164977714490026579">Il valore deve essere superiore o uguale a <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Inserisci una parte seguita da "<ph name="ATSIGN" />". Il valore "<ph name="INVALIDADDRESS" />" è incompleto.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">riattiva audio</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Tocca due volte a sinistra o destra per saltare di 10 secondi</translation>
+<translation id="5631759159893697722">abstract</translation>
<translation id="5641012560118721995">sospendi riproduzione</translation>
<translation id="5643186887447432888">pulsante</translation>
<translation id="5677946354068040947">altre opzioni</translation>
+<translation id="576709008726043716">introduzione</translation>
<translation id="57838592816432529">Disattiva audio</translation>
<translation id="5860033963881614850">Off</translation>
<translation id="588258955323874662">Schermo intero</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Anno</translation>
<translation id="6023896073578205740">casella di riepilogo</translation>
<translation id="6101327004457443354">riattiva traccia audio</translation>
+<translation id="6150588977291308318">bibliografia</translation>
<translation id="6164829606128959761">indicatore</translation>
+<translation id="6166809985690652833">postfazione</translation>
+<translation id="6213469881011901533">glossario</translation>
<translation id="6398862346408813489">Mostra il riquadro di selezione del mese</translation>
<translation id="6404546809543547843">dispositivo di scorrimento durata audio</translation>
+<translation id="6453774872122745852">riconoscimenti</translation>
<translation id="648732519525291180">selettore di ora</translation>
<translation id="6550675742724504774">Opzioni</translation>
-<translation id="6564313821541007458">Ora in modalità picture in picture</translation>
<translation id="658823671542763450">passa a schermo intero</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">descrizione comando</translation>
<translation id="6790428901817661496">Play</translation>
<translation id="6820355525329141109">Impossibile caricare il plug-in</translation>
+<translation id="6820615603175220800">riferimento bibliografico</translation>
<translation id="6843725295806269523">disattiva audio</translation>
<translation id="6853785296079745596">nascondi sottotitoli</translation>
<translation id="6885760532393684712">directory</translation>
+<translation id="689129560213475294">colophon</translation>
<translation id="6934078000481955284">citazione lunga</translation>
<translation id="6941933287844615239">scarica contenuti multimediali</translation>
<translation id="6989848892321993519">Prolunga questo testo a <ph name="MIN_CHARACTERS" /> o più caratteri (al momento stai utilizzando 1 carattere).</translation>
<translation id="709897737746224366">Rispetta il formato richiesto.</translation>
+<translation id="7139483182332611405">prefazione</translation>
<translation id="7223624360433298498">tempo trascorso</translation>
<translation id="7263440858009898357">Seleziona un elemento nell'elenco.</translation>
<translation id="727747134524199931">intestazione di colonna</translation>
+<translation id="7353453495576941748">ringraziamento</translation>
<translation id="7364796246159120393">Scegli file</translation>
<translation id="739024184232394898">Altro...</translation>
+<translation id="7405738980073107433">note finali</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">Tab</translation>
<translation id="7514365320538308">Scarica</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7647456547678091388">suggerimento</translation>
+<translation id="7661956066982048809">documento grafico</translation>
<translation id="7673697353781729403">Orario</translation>
+<translation id="7681220483256441252">indice</translation>
<translation id="7720026100085573005">tempo rimanente</translation>
<translation id="7740016676195725605">interrompi la visualizzazione dei sottotitoli</translation>
<translation id="7740050170769002709">Contenuti HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">barra di divisione</translation>
<translation id="795667975304826397">Nessun file selezionato</translation>
<translation id="8053789581856978548">campo di testo della ricerca</translation>
+<translation id="8057695513531652401">informativa</translation>
+<translation id="8105797009065549151">riferimento note</translation>
<translation id="8115662671911883373">avvia la visualizzazione dei sottotitoli</translation>
<translation id="8117451130807776954">Questa settimana</translation>
<translation id="819205353528511139">riproduci filmato in modalità a schermo intero</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Sottotitoli</translation>
<translation id="835897206747267392">Valore non valido.</translation>
+<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra degli strumenti</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
<translation id="8451268428117625855">Seleziona un file.</translation>
<translation id="8461852803063341183">pulsante di opzione</translation>
+<translation id="8474886197722836894">dedica</translation>
+<translation id="8531739829932800271">errata corrige</translation>
<translation id="8534579021159131403">Minuti</translation>
<translation id="8541249477527128034">controllo contenuti multimediali</translation>
+<translation id="8550857728288566671">simbolo grafico</translation>
<translation id="8583702881314752957">elenco di definizioni</translation>
<translation id="8597182159515967513">intestazione</translation>
+<translation id="860475260694818407">sommario</translation>
<translation id="8613126697340063924">gestisci riproduzione remota</translation>
+<translation id="862370744433916922">sottotitolo</translation>
<translation id="8741316211671074806">Picture in picture</translation>
<translation id="8750798805984357768">Seleziona una di queste opzioni.</translation>
<translation id="8785498733064193001">inizia riproduzione</translation>
+<translation id="8808573423886751634">capitolo</translation>
<translation id="8845239796550121995">Ora in fase di trasmissione alla TV</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Errore di riproduzione video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Altro...</translation>
<translation id="9138385573473225930">avviso</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partire dal giorno <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">piè di pagina</translation>
<translation id="947831847158436616">cella</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_iw.xtb b/chromium/content/app/strings/translations/content_strings_iw.xtb
index bd625140753..3a5a640f164 100644
--- a/chromium/content/app/strings/translations/content_strings_iw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_iw.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">משלים</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">מחוון</translation>
+<translation id="1211441953136645838">הערת סיום</translation>
<translation id="1281252709823657822">דו-שיח</translation>
+<translation id="1335095011850992622">קרדיטים</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">מודעת באנר</translation>
<translation id="1589122976691792535">אזור</translation>
<translation id="1591562245178063882">החודש</translation>
<translation id="1637811476055996098">בחר קבצים</translation>
+<translation id="1650423536718072820">ציטוט</translation>
<translation id="1729654308190250600">הזן ערך נדרש בשדה של כתובת האימייל.</translation>
<translation id="1758486001363313524">אחר...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">רשת של עץ</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">הפעלה במכשיר מרוחק</translation>
+<translation id="1907737156431278478">דוגמה</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">מצב</translation>
<translation id="1938124657309484470">על הערך להיות <ph name="MAXIMUM_DATE_OR_TIME" /> או מוקדם יותר.</translation>
<translation id="1993104285338243655">הועבר לשיקוף מסך</translation>
<translation id="2060505056492490888">נעשה שימוש ב-'<ph name="DOT" />' במיקום שגוי ב-'<ph name="INVALIDDOMAIN" />'.</translation>
<translation id="2148716181193084225">היום</translation>
+<translation id="2158401438286456825">רשימת דפים</translation>
<translation id="2226276347425096477">קצר טקסט זה ל-<ph name="MAX_CHARACTERS" /> תווים או פחות (אתה משתמש כעת ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
<translation id="2247351761944213033">שבוע <ph name="WEEKNUMBER" />‏, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">רצועה <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">תיבת סימון</translation>
+<translation id="2311842470354187719">מעבר דף</translation>
<translation id="2335594187091864976">בוחר תאריך ושעה</translation>
<translation id="248395913932153421">יום</translation>
<translation id="2507943997699731163">מלא שדה זה.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">הפעל</translation>
<translation id="2613802280814924224">הזן ערך חוקי. הערך החוקי הקרוב ביותר הוא <ph name="VALID_VALUE" /></translation>
<translation id="2653659639078652383">שלח</translation>
+<translation id="2657045182931379222">אובייקט גרפי</translation>
<translation id="2674318244760992338">כותרת תחתונה</translation>
<translation id="2709516037105925701">מילוי אוטומטי</translation>
<translation id="2723001399770238859">אודיו</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">הארך טקסט זה ל-<ph name="MIN_CHARACTERS" /> תווים או יותר (אתה משתמש כרגע ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
<translation id="383465348367842624">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="3846214748874656680">צא ממסך מלא</translation>
+<translation id="3920932319529768807">סיכום</translation>
<translation id="3924558731517983934">יישום</translation>
+<translation id="3944740393230681990">פרולוג</translation>
<translation id="3960700977367013758">סרגל גלילה</translation>
<translation id="4103419683916926126">אלפיות שנייה</translation>
<translation id="4151657705144244502">פריט גרפי</translation>
+<translation id="4193965531860883258">פתח דבר</translation>
<translation id="4201051445878709314">הצג חודש קודם</translation>
<translation id="421884353938374759">color picker</translation>
<translation id="4248100235867064564">שורת תפריטים</translation>
<translation id="4254339807215791271">פרטי תוכן</translation>
<translation id="4360991593054037559">הזן ערך חוקי. שני הערכים החוקיים הקרובים ביותר הם <ph name="VALID_VALUE_LOW" /> ו-<ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">שאלות ותשובות</translation>
<translation id="4413860115965805769">לחצן תפריט</translation>
+<translation id="4446524499724042288">הפניה למילון מונחים</translation>
<translation id="4522570452068850558">פרטים</translation>
<translation id="4597532268155981612">טופס</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">נספח</translation>
+<translation id="4742539557769756338">שער</translation>
<translation id="4757246831282535685">חלונית כרטיסיות</translation>
<translation id="4763480195061959176">סרטוני וידאו</translation>
<translation id="479989351350248267">Search</translation>
<translation id="4812940957355064477">יש להזין מספר.</translation>
+<translation id="4912536737030637138">ערך ביבליוגרפי</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> נבחרו</translation>
<translation id="4992066212339426712">בטל השתקה</translation>
<translation id="49969490063480558">הזן חלק ולאחריו '<ph name="ATSIGN" />'‏. השדה '<ph name="INVALIDADDRESS" />' אינו מלא.</translation>
<translation id="5034860022980953847">סימן ויזואלי להתקדמות</translation>
+<translation id="5093189678851173835">ציטוט בראש ספר</translation>
<translation id="5117590920725113268">הצג את החודש הבא</translation>
<translation id="512758898067543763">כותרת שורה</translation>
+<translation id="5143125788380636750">אפילוג</translation>
+<translation id="5153163864850940242">הסרטון הזה פועל במצב תמונה בתוך תמונה</translation>
<translation id="5164977714490026579">הערך חייב להיות גדול מ-<ph name="MINIMUM" /> או שווה לו.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">הזן חלק ולאחריו '<ph name="ATSIGN" />'‏. השדה '<ph name="INVALIDADDRESS" />' אינו מלא.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">בטל השתקה</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">הקשה כפולה בצד ימין או שמאל מדלגת על 10 שניות</translation>
+<translation id="5631759159893697722">תקציר</translation>
<translation id="5641012560118721995">השהה הפעלה</translation>
<translation id="5643186887447432888">לחצן</translation>
<translation id="5677946354068040947">אפשרויות נוספות</translation>
+<translation id="576709008726043716">מבוא</translation>
<translation id="57838592816432529">השתק</translation>
<translation id="5860033963881614850">כבוי</translation>
<translation id="588258955323874662">מסך מלא</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">שנה</translation>
<translation id="6023896073578205740">תיבת רשימה</translation>
<translation id="6101327004457443354">בטל השתקה של רצועת אודיו</translation>
+<translation id="6150588977291308318">ביבליוגרפיה</translation>
<translation id="6164829606128959761">מד</translation>
+<translation id="6166809985690652833">אחרית דבר</translation>
+<translation id="6213469881011901533">מילון מונחים</translation>
<translation id="6398862346408813489">הצג חלונית לבחירת חודש</translation>
<translation id="6404546809543547843">מסתיר משך אודיו</translation>
+<translation id="6453774872122745852">תודות</translation>
<translation id="648732519525291180">בוחר שעות</translation>
<translation id="6550675742724504774">אפשרויות</translation>
-<translation id="6564313821541007458">עכשיו במצב 'תמונה בתוך תמונה'</translation>
<translation id="658823671542763450">היכנס למסך מלא</translation>
<translation id="663493177488814956">פיד</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">הסבר קצר</translation>
<translation id="6790428901817661496">הפעל</translation>
<translation id="6820355525329141109">לא ניתן היה לטעון את הפלאגין.</translation>
+<translation id="6820615603175220800">הפניה לביבליוגרפיה</translation>
<translation id="6843725295806269523">השתק</translation>
<translation id="6853785296079745596">הסתר כתוביות סגורות</translation>
<translation id="6885760532393684712">ספריה</translation>
+<translation id="689129560213475294">קולופון</translation>
<translation id="6934078000481955284">‏רכיב blockquote</translation>
<translation id="6941933287844615239">הורד מדיה</translation>
<translation id="6989848892321993519">עליך להאריך את הטקסט ל-<ph name="MIN_CHARACTERS" /> תווים או יותר (אתה משתמש כרגע בתו אחד).</translation>
<translation id="709897737746224366">התאם את הפורמט המבוקש.</translation>
+<translation id="7139483182332611405">הקדמה</translation>
<translation id="7223624360433298498">זמן שחלף</translation>
<translation id="7263440858009898357">בחר פריט מהרשימה.</translation>
<translation id="727747134524199931">כותרת עמודה</translation>
+<translation id="7353453495576941748">קרדיט</translation>
<translation id="7364796246159120393">בחירת קובץ</translation>
<translation id="739024184232394898">אחר...</translation>
+<translation id="7405738980073107433">הערות סיום</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">הורד</translation>
+<translation id="7529102961911894712">קישור לאחור</translation>
+<translation id="7647456547678091388">טיפ</translation>
+<translation id="7661956066982048809">מסמך גרפי</translation>
<translation id="7673697353781729403">שעות</translation>
+<translation id="7681220483256441252">אינדקס</translation>
<translation id="7720026100085573005">זמן שנותר</translation>
<translation id="7740016676195725605">הפסק להציג כתוביות סגורות</translation>
<translation id="7740050170769002709">‏תוכן HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">מפצל</translation>
<translation id="795667975304826397">לא נבחר קובץ</translation>
<translation id="8053789581856978548">שדה טקסט לחיפוש</translation>
+<translation id="8057695513531652401">הודעה</translation>
+<translation id="8105797009065549151">הפניה להערה</translation>
<translation id="8115662671911883373">התחל להציג כתוביות סגורות</translation>
<translation id="8117451130807776954">השבוע</translation>
<translation id="819205353528511139">הפעל את הסרט במצב מסך מלא</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">כתוביות</translation>
<translation id="835897206747267392">ערך לא חוקי.</translation>
+<translation id="8415319359811155763">חלק</translation>
<translation id="8433900881053900389">סרגל כלים</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> קבצים</translation>
<translation id="8451268428117625855">בחר קובץ.</translation>
<translation id="8461852803063341183">לחצן בחירה</translation>
+<translation id="8474886197722836894">הקדשה</translation>
+<translation id="8531739829932800271">שגיאת דפוס</translation>
<translation id="8534579021159131403">דקות</translation>
<translation id="8541249477527128034">שליטה במדיה</translation>
+<translation id="8550857728288566671">סמל גרפי</translation>
<translation id="8583702881314752957">רשימת הגדרות</translation>
<translation id="8597182159515967513">כותרת</translation>
+<translation id="860475260694818407">תוכן העניינים</translation>
<translation id="8613126697340063924">שליטה בהפעלה מרחוק</translation>
+<translation id="862370744433916922">כותרת משנה</translation>
<translation id="8741316211671074806">תמונה בתוך תמונה</translation>
<translation id="8750798805984357768">בחר אחת מהאפשרויות הבאות.</translation>
<translation id="8785498733064193001">התחל בהפעלה</translation>
+<translation id="8808573423886751634">פרק</translation>
<translation id="8845239796550121995">מעביר תוכן לטלוויזיה</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">שגיאה בהפעלת הסרטון</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">אחר...</translation>
<translation id="9138385573473225930">התראה</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, שמתחיל בתאריך <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">הערת שוליים</translation>
<translation id="947831847158436616">תא</translation>
<translation id="966787709310836684">תפריט</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ja.xtb b/chromium/content/app/strings/translations/content_strings_ja.xtb
index 39ba9808af5..314178fe319 100644
--- a/chromium/content/app/strings/translations/content_strings_ja.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ja.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">捕捉</translation>
<translation id="1206619573307042055">マーキー</translation>
<translation id="1206693055195146388">スライダ</translation>
+<translation id="1211441953136645838">巻末注</translation>
<translation id="1281252709823657822">ダイアログ</translation>
+<translation id="1335095011850992622">クレジット</translation>
<translation id="1342835525016946179">記事</translation>
<translation id="1359897965706325498">バナー</translation>
<translation id="1589122976691792535">地域</translation>
<translation id="1591562245178063882">今月</translation>
<translation id="1637811476055996098">ファイル選択</translation>
+<translation id="1650423536718072820">引用</translation>
<translation id="1729654308190250600">メール アドレスを入力してください。</translation>
<translation id="1758486001363313524">その他...</translation>
<translation id="1806710327868736751">アラート ダイアログ</translation>
<translation id="1821985195704844674">ツリーグリッド</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">リモート デバイスで再生</translation>
+<translation id="1907737156431278478">例</translation>
<translation id="1921819250265091946">日</translation>
<translation id="1930711995431081526">ステータス</translation>
<translation id="1938124657309484470"><ph name="MAXIMUM_DATE_OR_TIME" /> 以前の値を指定する必要があります。</translation>
<translation id="1993104285338243655">ミラーリングに切り替わりました</translation>
<translation id="2060505056492490888">「<ph name="INVALIDDOMAIN" />」内の「<ph name="DOT" />」の位置が間違っています。</translation>
<translation id="2148716181193084225">今日</translation>
+<translation id="2158401438286456825">ページリスト</translation>
<translation id="2226276347425096477">このテキストを半角 <ph name="MAX_CHARACTERS" /> 文字以下にしてください(現時点で半角 <ph name="CURRENT_LENGTH" /> 文字です)。</translation>
<translation id="2247351761944213033"><ph name="YEAR" />年第<ph name="WEEKNUMBER" />週</translation>
<translation id="2277199496770840904">トラック <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">チェックボックス</translation>
+<translation id="2311842470354187719">改ページ</translation>
<translation id="2335594187091864976">日時選択ツール</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">このフィールドを入力してください。</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">再生</translation>
<translation id="2613802280814924224">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE" /> です。</translation>
<translation id="2653659639078652383">送信</translation>
+<translation id="2657045182931379222">図形オブジェクト</translation>
<translation id="2674318244760992338">フッター</translation>
<translation id="2709516037105925701">自動入力</translation>
<translation id="2723001399770238859">音声</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">このテキストは <ph name="MIN_CHARACTERS" /> 文字以上で指定してください(現在は <ph name="CURRENT_LENGTH" /> 文字です)。</translation>
<translation id="383465348367842624">「<ph name="ATSIGN" />」の前の文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
<translation id="3846214748874656680">全画面表示を終了</translation>
+<translation id="3920932319529768807">まとめ</translation>
<translation id="3924558731517983934">アプリケーション</translation>
+<translation id="3944740393230681990">プロローグ</translation>
<translation id="3960700977367013758">スクロールバー</translation>
<translation id="4103419683916926126">ミリ秒</translation>
<translation id="4151657705144244502">グラフィック</translation>
+<translation id="4193965531860883258">前書き</translation>
<translation id="4201051445878709314">前の月を表示</translation>
<translation id="421884353938374759">色の選択</translation>
<translation id="4248100235867064564">メニューバー</translation>
<translation id="4254339807215791271">コンテンツ情報</translation>
<translation id="4360991593054037559">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE_LOW" /> と <ph name="VALID_VALUE_HIGHER" /> です。</translation>
+<translation id="4384583879834880242">Q&A</translation>
<translation id="4413860115965805769">メニューボタン</translation>
+<translation id="4446524499724042288">用語参照</translation>
<translation id="4522570452068850558">詳細</translation>
<translation id="4597532268155981612">フォーム</translation>
<translation id="4661075872484491155">ツリー</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」に続く文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
+<translation id="4668956016107839909">付録</translation>
+<translation id="4742539557769756338">表紙</translation>
<translation id="4757246831282535685">タブパネル</translation>
<translation id="4763480195061959176">動画</translation>
<translation id="479989351350248267">検索</translation>
<translation id="4812940957355064477">数字を入力してください。</translation>
+<translation id="4912536737030637138">文献情報</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> 件選択</translation>
<translation id="4992066212339426712">ミュートを解除</translation>
<translation id="49969490063480558">「<ph name="INVALIDADDRESS" />」は完全なメールアドレスではありません。「<ph name="ATSIGN" />」に続く文字列を入力してください。</translation>
<translation id="5034860022980953847">プログレスバー</translation>
+<translation id="5093189678851173835">題辞</translation>
<translation id="5117590920725113268">次の月を表示</translation>
<translation id="512758898067543763">行見出し</translation>
+<translation id="5143125788380636750">エピローグ</translation>
+<translation id="5153163864850940242">この動画はピクチャー イン ピクチャーで再生されています</translation>
<translation id="5164977714490026579">値は <ph name="MINIMUM" /> 以上にする必要があります。</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">「<ph name="ATSIGN" />」の前の文字列を入力してください。「<ph name="INVALIDADDRESS" />」は完全なメール アドレスではありません。</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">ミュートを解除</translation>
<translation id="561939826962581046">日時</translation>
<translation id="5630795885300617244">左または右をダブルタップして 10 秒スキップします</translation>
+<translation id="5631759159893697722">概要</translation>
<translation id="5641012560118721995">再生を一時停止</translation>
<translation id="5643186887447432888">ボタン</translation>
<translation id="5677946354068040947">その他のオプション</translation>
+<translation id="576709008726043716">序論</translation>
<translation id="57838592816432529">ミュート</translation>
<translation id="5860033963881614850">オフ</translation>
<translation id="588258955323874662">全画面表示</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">年</translation>
<translation id="6023896073578205740">リストボックス</translation>
<translation id="6101327004457443354">音声トラックのミュートを解除</translation>
+<translation id="6150588977291308318">参考文献</translation>
<translation id="6164829606128959761">メーター</translation>
+<translation id="6166809985690652833">後書き</translation>
+<translation id="6213469881011901533">用語集</translation>
<translation id="6398862346408813489">月選択パネルを表示</translation>
<translation id="6404546809543547843">オーディオ再生バー</translation>
+<translation id="6453774872122745852">謝辞</translation>
<translation id="648732519525291180">時間選択ツール</translation>
<translation id="6550675742724504774">オプション</translation>
-<translation id="6564313821541007458">ピクチャー イン ピクチャー モードで表示中です</translation>
<translation id="658823671542763450">全画面表示</translation>
<translation id="663493177488814956">フィード</translation>
<translation id="6637586476836377253">ログ</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">ツールチップ</translation>
<translation id="6790428901817661496">再生</translation>
<translation id="6820355525329141109">プラグインを読み込むことができませんでした。</translation>
+<translation id="6820615603175220800">文献参照</translation>
<translation id="6843725295806269523">ミュート</translation>
<translation id="6853785296079745596">クローズド キャプションを非表示</translation>
<translation id="6885760532393684712">ディレクトリ</translation>
+<translation id="689129560213475294">奥付</translation>
<translation id="6934078000481955284">引用</translation>
<translation id="6941933287844615239">メディアをダウンロード</translation>
<translation id="6989848892321993519">このテキストは <ph name="MIN_CHARACTERS" /> 文字以上で指定してください(現在 1 文字で指定されています)。</translation>
<translation id="709897737746224366">指定されている形式で入力してください。</translation>
+<translation id="7139483182332611405">序文</translation>
<translation id="7223624360433298498">経過時間</translation>
<translation id="7263440858009898357">リスト内の項目を選択してください。</translation>
<translation id="727747134524199931">列見出し</translation>
+<translation id="7353453495576941748">クレジット</translation>
<translation id="7364796246159120393">ファイルを選択</translation>
<translation id="739024184232394898">その他...</translation>
+<translation id="7405738980073107433">巻末注</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">タブ</translation>
<translation id="7514365320538308">ダウンロード</translation>
+<translation id="7529102961911894712">言及リンク</translation>
+<translation id="7647456547678091388">ヒント</translation>
+<translation id="7661956066982048809">図形ドキュメント</translation>
<translation id="7673697353781729403">時間</translation>
+<translation id="7681220483256441252">索引</translation>
<translation id="7720026100085573005">残り時間</translation>
<translation id="7740016676195725605">クローズド キャプションの表示を終了</translation>
<translation id="7740050170769002709">HTML コンテンツ</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">分割バー</translation>
<translation id="795667975304826397">選択されていません</translation>
<translation id="8053789581856978548">検索テキスト欄</translation>
+<translation id="8057695513531652401">注記</translation>
+<translation id="8105797009065549151">備考</translation>
<translation id="8115662671911883373">クローズド キャプションの表示を開始</translation>
<translation id="8117451130807776954">今週</translation>
<translation id="819205353528511139">全画面表示モードで再生</translation>
<translation id="8199524924445686405"> 年 </translation>
<translation id="8284326494547611709">字幕</translation>
<translation id="835897206747267392">値が無効です。</translation>
+<translation id="8415319359811155763">部</translation>
<translation id="8433900881053900389">ツールバー</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ファイル</translation>
<translation id="8451268428117625855">ファイルを選択してください。</translation>
<translation id="8461852803063341183">ラジオボタン</translation>
+<translation id="8474886197722836894">献辞</translation>
+<translation id="8531739829932800271">正誤表</translation>
<translation id="8534579021159131403">分</translation>
<translation id="8541249477527128034">メディア管理</translation>
+<translation id="8550857728288566671">図形記号</translation>
<translation id="8583702881314752957">定義リスト</translation>
<translation id="8597182159515967513">見出し</translation>
+<translation id="860475260694818407">目次</translation>
<translation id="8613126697340063924">リモート再生をコントロール</translation>
+<translation id="862370744433916922">副題</translation>
<translation id="8741316211671074806">ピクチャー イン ピクチャー</translation>
<translation id="8750798805984357768">これらのオプションから 1 つ選択してください。</translation>
<translation id="8785498733064193001">再生を開始</translation>
+<translation id="8808573423886751634">章</translation>
<translation id="8845239796550121995">テレビにキャストしています</translation>
<translation id="8851136666856101339">本文</translation>
<translation id="8875657656876809964">動画再生エラー</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">その他...</translation>
<translation id="9138385573473225930">アラート</translation>
<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> から始まる <ph name="WEEK" /></translation>
+<translation id="9168329111483466115">脚注</translation>
<translation id="947831847158436616">セル</translation>
<translation id="966787709310836684">メニュー</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_kn.xtb b/chromium/content/app/strings/translations/content_strings_kn.xtb
index ba142f30101..02c6cdc5517 100644
--- a/chromium/content/app/strings/translations/content_strings_kn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_kn.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">ಪೂರಕವಾಗಿ</translation>
<translation id="1206619573307042055">ಮಾರ್ಕ್ಯೂ</translation>
<translation id="1206693055195146388">ಸ್ಲೈಡರ್</translation>
+<translation id="1211441953136645838">ಮುಕ್ತಾಯ ಟಿಪ್ಪಣಿ</translation>
<translation id="1281252709823657822">ಸಂವಾದ</translation>
+<translation id="1335095011850992622">ಕ್ರೆಡಿಟ್‌ಗಳು</translation>
<translation id="1342835525016946179">ಲೇಖನ</translation>
<translation id="1359897965706325498">ಬ್ಯಾನರ್</translation>
<translation id="1589122976691792535">ಪ್ರದೇಶ</translation>
<translation id="1591562245178063882">ಈ ತಿಂಗಳು</translation>
<translation id="1637811476055996098">ಫೈಲ್‌ಗಳನ್ನು ಆರಿಸಿ</translation>
+<translation id="1650423536718072820">ಪ್ರಮುಖ ಉಲ್ಲೇಖ</translation>
<translation id="1729654308190250600">ಖಾಲಿ-ಅಲ್ಲದ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ.</translation>
<translation id="1758486001363313524">ಇತರೆ...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">ಟ್ರೀ ಗ್ರಿಡ್</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">ರಿಮೋಟ್ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ</translation>
+<translation id="1907737156431278478">ಉದಾಹರಣೆ</translation>
<translation id="1921819250265091946">ದಿದಿ</translation>
<translation id="1930711995431081526">ಸ್ಥಿತಿ</translation>
<translation id="1938124657309484470">ಮೌಲ್ಯವು <ph name="MAXIMUM_DATE_OR_TIME" /> ಅಥವಾ ಹಿಂದಿನದ್ದಾಗಿರಬೇಕು.</translation>
<translation id="1993104285338243655">ಪ್ರತಿಬಿಂಬಿಸುವಿಕೆಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' ಅನ್ನು '<ph name="INVALIDDOMAIN" />' ನಲ್ಲಿ ತಪ್ಪಾದ ಸ್ಥಾನದಲ್ಲಿ ಬಳಸಲಾಗಿದೆ.</translation>
<translation id="2148716181193084225">ಇಂದು</translation>
+<translation id="2158401438286456825">ಪುಟ ಪಟ್ಟಿ</translation>
<translation id="2226276347425096477">ದಯವಿಟ್ಟು ಈ ಪಠ್ಯವನ್ನು <ph name="MAX_CHARACTERS" /> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಕಡಿಮೆಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತ <ph name="CURRENT_LENGTH" /> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
<translation id="2247351761944213033">ವಾರ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ಟ್ರ್ಯಾಕ್ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ಚೆಕ್‌ಬಾಕ್ಸ್</translation>
+<translation id="2311842470354187719">ಪುಟ ವಿಭಜನೆ</translation>
<translation id="2335594187091864976">ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ಪಿಕರ್</translation>
<translation id="248395913932153421">ದಿನ</translation>
<translation id="2507943997699731163">ದಯವಿಟ್ಟು ಈ ಕ್ಷೇತ್ರವನ್ನು ಭರ್ತಿ ಮಾಡಿ.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">ಪ್ಲೇ ಮಾಡಿ</translation>
<translation id="2613802280814924224">ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯವು <ph name="VALID_VALUE" /> ಆಗಿದೆ.</translation>
<translation id="2653659639078652383">ಸಲ್ಲಿಸು</translation>
+<translation id="2657045182931379222">ಗ್ರಾಫಿಕ್ಸ್ ವಸ್ತು</translation>
<translation id="2674318244760992338">ಅಡಿಟಿಪ್ಪಣಿ</translation>
<translation id="2709516037105925701">ಸ್ವಯಂತುಂಬುವಿಕೆ</translation>
<translation id="2723001399770238859">ಆಡಿಯೋ</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">ಈ ಪಠ್ಯವನ್ನು <ph name="MIN_CHARACTERS" /> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತವಾಗಿ <ph name="CURRENT_LENGTH" /> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
<translation id="3846214748874656680">ಪೂರ್ಣಪರದೆಯಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
+<translation id="3920932319529768807">ತೀರ್ಮಾನ</translation>
<translation id="3924558731517983934">ಅಪ್ಲಿಕೇಶನ್</translation>
+<translation id="3944740393230681990">ಪೀಠಿಕೆ</translation>
<translation id="3960700977367013758">ಸ್ಕ್ರಾಲ್ ಪಟ್ಟಿ</translation>
<translation id="4103419683916926126">ಮಿಲಿಸೆಕೆಂಡುಗಳು</translation>
<translation id="4151657705144244502">ಗ್ರಾಫಿಕ್</translation>
+<translation id="4193965531860883258">ಮುನ್ನುಡಿ</translation>
<translation id="4201051445878709314">ಹಿಂದಿನ ತಿಂಗಳು ತೋರಿಸು</translation>
<translation id="421884353938374759">ಬಣ್ಣದ ಆಯ್ಕೆಮಾಡುವಿಕೆ</translation>
<translation id="4248100235867064564">ಮೆನು ಬಾರ್‌</translation>
<translation id="4254339807215791271">ವಿಷಯ ಮಾಹಿತಿ</translation>
<translation id="4360991593054037559">ಮಾನ್ಯವಾದ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. <ph name="VALID_VALUE_LOW" /> ಮತ್ತು <ph name="VALID_VALUE_HIGHER" /> ಎರಡು ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯಗಳಾಗಿವೆ.</translation>
+<translation id="4384583879834880242">ಪ್ರಶ್ನೋತ್ತರ</translation>
<translation id="4413860115965805769">ಮೆನು ಬಟನ್</translation>
+<translation id="4446524499724042288">ಪದಕೋಶ ಉಲ್ಲೇಖ</translation>
<translation id="4522570452068850558">ವಿವರಗಳು</translation>
<translation id="4597532268155981612">ಫಾರ್ಮ್</translation>
<translation id="4661075872484491155">ಮರ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
+<translation id="4668956016107839909">ಅನುಬಂಧ</translation>
+<translation id="4742539557769756338">ಕವರ್</translation>
<translation id="4757246831282535685">ಟ್ಯಾಬ್ ಫಲಕ</translation>
<translation id="4763480195061959176">ವೀಡಿಯೊ</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">ದಯವಿಟ್ಟು ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="4912536737030637138">ಗ್ರಂಥಸೂಚಿ ನಮೂದು</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ</translation>
<translation id="4992066212339426712">ಅನ್‌ಮ್ಯೂಟ್</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' ನಂತರದ ಒಂದು ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS" />' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
<translation id="5034860022980953847">ಪ್ರಗತಿ ಸೂಚಕ</translation>
+<translation id="5093189678851173835">ಶಿಲಾಶಾಸನ</translation>
<translation id="5117590920725113268">ಮುಂದಿನ ತಿಂಗಳು ತೋರಿಸಿ</translation>
<translation id="512758898067543763">ಸಾಲಿನ ಶಿರೋನಾಮೆ</translation>
+<translation id="5143125788380636750">ಹಿನ್ನುಡಿ</translation>
+<translation id="5153163864850940242">ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರದಲ್ಲಿ ಈ ವೀಡಿಯೊ ಪ್ಲೇ ಆಗುತ್ತಿದೆ</translation>
<translation id="5164977714490026579">ಮೌಲ್ಯವು <ph name="MINIMUM" /> ಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಾಗಿರಬೇಕು ಅಥವಾ ಸಮನಾಗಿರಬೇಕು.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS" />' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡು</translation>
<translation id="561939826962581046">ಸಮಯ</translation>
<translation id="5630795885300617244">10ಸೆ ಸ್ಕಿಪ್ ಮಾಡಲು ಎಡಕ್ಕೆ ಅಥವಾ ಬಲಕ್ಕೆ ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ</translation>
+<translation id="5631759159893697722">ಸಾರಾಂಶ</translation>
<translation id="5641012560118721995">ಪ್ಲೇಬ್ಯಾಕ್ ವಿರಾಮಗೊಳಿಸು</translation>
<translation id="5643186887447432888">ಬಟನ್</translation>
<translation id="5677946354068040947">ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು</translation>
+<translation id="576709008726043716">ಪರಿಚಯ</translation>
<translation id="57838592816432529">ಮ್ಯೂಟ್</translation>
<translation id="5860033963881614850">ಆಫ್</translation>
<translation id="588258955323874662">ಪೂರ್ಣಪರದೆ</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">ವರ್ಷ</translation>
<translation id="6023896073578205740">ಪಟ್ಟಿಯ ಬಾಕ್ಸ್</translation>
<translation id="6101327004457443354">ಆಡಿಯೋ ಟ್ರ್ಯಾಕ್ ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡು</translation>
+<translation id="6150588977291308318">ಗ್ರಂಥಸೂಚಿ</translation>
<translation id="6164829606128959761">ಮೀಟರ್</translation>
+<translation id="6166809985690652833">ನಂತರದ</translation>
+<translation id="6213469881011901533">ಪದಕೋಶ</translation>
<translation id="6398862346408813489">ತಿಂಗಳ ಆಯ್ಕೆ ಪ್ಯಾನಲ್ ತೋರಿಸಿ</translation>
<translation id="6404546809543547843">ಆಡಿಯೊ ಸಮಯ ಸ್ಕ್ರಬ್ಬರ್</translation>
+<translation id="6453774872122745852">ಅಂಗೀಕಾರಗಳು</translation>
<translation id="648732519525291180">ಸಮಯ ಪಿಕರ್</translation>
<translation id="6550675742724504774">ಆಯ್ಕೆಗಳು</translation>
-<translation id="6564313821541007458">ಈಗ ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೋಡ್‌ನಲ್ಲಿ ಇದೆ</translation>
<translation id="658823671542763450">ಪೂರ್ಣ ಪರದೆ ನಮೂದಿಸು</translation>
<translation id="663493177488814956">ಫೀಡ್‌</translation>
<translation id="6637586476836377253">ಲಾಗ್</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">ಟೂಲ್‌ ಟಿಪ್‌</translation>
<translation id="6790428901817661496">ಪ್ಲೇ ಮಾಡು</translation>
<translation id="6820355525329141109">ಪ್ಲಗ್-ಇನ್ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.</translation>
+<translation id="6820615603175220800">ಗ್ರಂಥಸೂಚಿ ಉಲ್ಲೇಖ</translation>
<translation id="6843725295806269523">ಮ್ಯೂಟ್</translation>
<translation id="6853785296079745596">ಮುಚ್ಚಿರುವ ಶೀರ್ಷಿಕೆಗಳನ್ನು ಮರೆಮಾಡಿ</translation>
<translation id="6885760532393684712">ಡೈರೆಕ್ಟರಿ</translation>
+<translation id="689129560213475294">ಕೊಲೊಫೋನ್</translation>
<translation id="6934078000481955284">ಬ್ಲಾಕ್‌ಕೋಟ್</translation>
<translation id="6941933287844615239">ಮಾಧ್ಯಮ ಡೌನ್‌ಲೋಡ್</translation>
<translation id="6989848892321993519">ಈ ಪಠ್ಯವನ್ನು <ph name="MIN_CHARACTERS" /> ಅಥವಾ ಇದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿನ ಅಕ್ಷರಗಳಿಗೆ ಉದ್ದಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತ 1 ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
<translation id="709897737746224366">ದಯವಿಟ್ಟು ವಿನಂತಿಸಿದ ಸ್ವರೂಪವನ್ನು ಹೊಂದಿಸಿ.</translation>
+<translation id="7139483182332611405">ಮುನ್ನುಡಿ</translation>
<translation id="7223624360433298498">ಕಳೆದುಹೋದ ಸಮಯ</translation>
<translation id="7263440858009898357">ಪಟ್ಟಿಯಲ್ಲಿನ ಐಟಂ ಅನ್ನು ದಯವಿಟ್ಟು ಆಯ್ಕೆ ಮಾಡಿ.</translation>
<translation id="727747134524199931">ಕಾಲಮ್ ಶಿರೋನಾಮೆ</translation>
+<translation id="7353453495576941748">ಗೌರವ</translation>
<translation id="7364796246159120393">ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿ</translation>
<translation id="739024184232394898">ಇತರೆ...</translation>
+<translation id="7405738980073107433">ಅಂತಿಮ ಟಿಪ್ಪಣಿಗಳು</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">ಟ್ಯಾಬ್</translation>
<translation id="7514365320538308">ಡೌನ್‌ಲೋಡ್</translation>
+<translation id="7529102961911894712">ಬ್ಯಾಕ್‌ಲಿಂಕ್</translation>
+<translation id="7647456547678091388">ಸಲಹೆ</translation>
+<translation id="7661956066982048809">ಗ್ರಾಫಿಕ್ಸ್ ಡಾಕ್ಯುಮೆಂಟ್</translation>
<translation id="7673697353781729403">ಗಂಟೆಗಳು</translation>
+<translation id="7681220483256441252">ಸೂಚಿಕೆ</translation>
<translation id="7720026100085573005">ಉಳಿದಿರುವ ಸಮಯ</translation>
<translation id="7740016676195725605">ಮುಚ್ಚಲಾಗಿರುವ ಶೀರ್ಷಿಕೆಗಳ ಪ್ರದರ್ಶಿಸುವಿಕೆಯನ್ನು ನಿಲ್ಲಿಸಿ</translation>
<translation id="7740050170769002709">HTML ವಿಷಯ</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">ಛೇದಕ</translation>
<translation id="795667975304826397">ಯಾವುದೇ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ</translation>
<translation id="8053789581856978548">ಪಠ್ಯ ಕ್ಷೇತ್ರವನ್ನು ಹುಡುಕಿ</translation>
+<translation id="8057695513531652401">ಸೂಚನೆ</translation>
+<translation id="8105797009065549151">ಸೂಚನೆ ಉಲ್ಲೇಖ</translation>
<translation id="8115662671911883373">ಮುಚ್ಚಲಾಗಿರುವ ಶೀರ್ಷಿಕೆಗಳ ಪ್ರದರ್ಶಿಸುವಿಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ</translation>
<translation id="8117451130807776954">ಈ ವಾರ</translation>
<translation id="819205353528511139">ಪೂರ್ಣ ಪರದೆಯ ಮೋಡ್‌‌ನಲ್ಲಿ ಚಲನಚಿತ್ರವನ್ನು ಪ್ಲೇ ಮಾಡಿ</translation>
<translation id="8199524924445686405">ವವವವ</translation>
<translation id="8284326494547611709">ಶೀರ್ಷಿಕೆಗಳು</translation>
<translation id="835897206747267392">ಅಮಾನ್ಯ ಮೌಲ್ಯ.</translation>
+<translation id="8415319359811155763">ಭಾಗ</translation>
<translation id="8433900881053900389">ಟೂಲ್‌ಬಾರ್</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ಫೈಲ್‌ಗಳು</translation>
<translation id="8451268428117625855">ದಯವಿಟ್ಟು ಫೈಲ್ ಆಯ್ಕೆಮಾಡಿ.</translation>
<translation id="8461852803063341183">ರೇಡಿಯೋ ಬಟನ್</translation>
+<translation id="8474886197722836894">ಸಮರ್ಪಣೆ</translation>
+<translation id="8531739829932800271">ಎರ್ರಾಟಾ</translation>
<translation id="8534579021159131403">ನಿಮಿಷಗಳು</translation>
<translation id="8541249477527128034">ಮಾಧ್ಯಮ ನಿಯಂತ್ರಣ</translation>
+<translation id="8550857728288566671">ಗ್ರಾಫಿಕ್ಸ್ ಚಿಹ್ನೆ</translation>
<translation id="8583702881314752957">ವಿವರಣೆ ಪಟ್ಟಿ</translation>
<translation id="8597182159515967513">ಶೀರ್ಷಿಕೆ</translation>
+<translation id="860475260694818407">ಪರಿವಿಡಿ</translation>
<translation id="8613126697340063924">ರಿಮೋಟ್ ಪ್ಲೇಬ್ಯಾಕ್ ನಿಯಂತ್ರಿಸಿ</translation>
+<translation id="862370744433916922">ಉಪಶೀರ್ಷಿಕೆ</translation>
<translation id="8741316211671074806">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ</translation>
<translation id="8750798805984357768">ದಯವಿಟ್ಟು ಈ ಕೆಳಗಿನ ಆಯ್ಕೆಗಳಲ್ಲಿ ಒಂದನ್ನು ಆರಿಸಿ.</translation>
<translation id="8785498733064193001">ಪ್ಲೇಬ್ಯಾಕ್ ಪ್ರಾರಂಭಿಸಿ</translation>
+<translation id="8808573423886751634">ಅಧ್ಯಾಯ</translation>
<translation id="8845239796550121995">ಈಗ ನಿಮ್ಮ ಟಿವಿಯನ್ನು ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ</translation>
<translation id="8851136666856101339">ಮುಖ್ಯ</translation>
<translation id="8875657656876809964">ವೀಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್ ದೋಷ</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">ಇತರೆ...</translation>
<translation id="9138385573473225930">ಎಚ್ಚರಿಕೆ</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> ರಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ</translation>
+<translation id="9168329111483466115">ಅಡಿಟಿಪ್ಪಣಿ</translation>
<translation id="947831847158436616">ಸೆಲ್</translation>
<translation id="966787709310836684">ಮೆನು</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ko.xtb b/chromium/content/app/strings/translations/content_strings_ko.xtb
index 4fe6f5a5c08..0a7e051195e 100644
--- a/chromium/content/app/strings/translations/content_strings_ko.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ko.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">상호 보완</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">슬라이더</translation>
+<translation id="1211441953136645838">미주</translation>
<translation id="1281252709823657822">대화상자</translation>
+<translation id="1335095011850992622">저작권 표시</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">배너</translation>
<translation id="1589122976691792535">지역</translation>
<translation id="1591562245178063882">이번 달</translation>
<translation id="1637811476055996098">파일 선택</translation>
+<translation id="1650423536718072820">인용문</translation>
<translation id="1729654308190250600">비어 있지 않은 이메일 주소를 입력해 주세요.</translation>
<translation id="1758486001363313524">다른 일자...</translation>
<translation id="1806710327868736751">알림 대화상자</translation>
<translation id="1821985195704844674">트리 격자</translation>
<translation id="1822429046913737220">오전/오후</translation>
<translation id="1832974991323546415">원격 기기에서 재생</translation>
+<translation id="1907737156431278478">예시</translation>
<translation id="1921819250265091946">일</translation>
<translation id="1930711995431081526">상태</translation>
<translation id="1938124657309484470">값은 <ph name="MAXIMUM_DATE_OR_TIME" /> 이전이어야 합니다.</translation>
<translation id="1993104285338243655">미러링으로 전환됨</translation>
<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN" />'에서 '<ph name="DOT" />'의 위치가 잘못되었습니다.</translation>
<translation id="2148716181193084225">오늘</translation>
+<translation id="2158401438286456825">페이지 목록</translation>
<translation id="2226276347425096477">이 텍스트를 <ph name="MAX_CHARACTERS" />자 이하로 줄이세요(현재 <ph name="CURRENT_LENGTH" />자 사용 중).</translation>
<translation id="2247351761944213033"><ph name="YEAR" />, <ph name="WEEKNUMBER" />번째 주</translation>
<translation id="2277199496770840904"><ph name="NUMBER" />번 트랙</translation>
<translation id="2291999235780842123">체크박스</translation>
+<translation id="2311842470354187719">페이지 나누기</translation>
<translation id="2335594187091864976">날짜 및 시간 선택기</translation>
<translation id="248395913932153421">일</translation>
<translation id="2507943997699731163">이 입력란을 작성하세요.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">재생</translation>
<translation id="2613802280814924224">유효한 값을 입력해 주세요. 가장 근접한 유효 값은 <ph name="VALID_VALUE" />입니다.</translation>
<translation id="2653659639078652383">제출</translation>
+<translation id="2657045182931379222">그래픽 객체</translation>
<translation id="2674318244760992338">바닥글</translation>
<translation id="2709516037105925701">자동 완성</translation>
<translation id="2723001399770238859">오디오</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">이 텍스트를 <ph name="MIN_CHARACTERS" />자 이상으로 늘리세요(현재 <ph name="CURRENT_LENGTH" />자 사용 중).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' 앞 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
<translation id="3846214748874656680">전체화면 종료</translation>
+<translation id="3920932319529768807">결론</translation>
<translation id="3924558731517983934">애플리케이션</translation>
+<translation id="3944740393230681990">프롤로그</translation>
<translation id="3960700977367013758">스크롤바</translation>
<translation id="4103419683916926126">밀리초</translation>
<translation id="4151657705144244502">그래픽</translation>
+<translation id="4193965531860883258">서문</translation>
<translation id="4201051445878709314">이전 달 표시</translation>
<translation id="421884353938374759">color picker</translation>
<translation id="4248100235867064564">메뉴 표시줄</translation>
<translation id="4254339807215791271">콘텐츠 정보</translation>
<translation id="4360991593054037559">유효한 값을 입력해 주세요. 가장 근접한 유효 값 2개는 <ph name="VALID_VALUE_LOW" /> 및 <ph name="VALID_VALUE_HIGHER" />입니다.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
<translation id="4413860115965805769">메뉴 버튼</translation>
+<translation id="4446524499724042288">용어 참조</translation>
<translation id="4522570452068850558">세부정보</translation>
<translation id="4597532268155981612">양식</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' 다음 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
+<translation id="4668956016107839909">부록</translation>
+<translation id="4742539557769756338">표지</translation>
<translation id="4757246831282535685">탭 패널</translation>
<translation id="4763480195061959176">동영상</translation>
<translation id="479989351350248267">검색</translation>
<translation id="4812940957355064477">숫자를 입력하세요.</translation>
+<translation id="4912536737030637138">참고문헌 항목</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" />개 선택됨</translation>
<translation id="4992066212339426712">음소거 해제</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' 뒷 부분을 입력해 주세요. '<ph name="INVALIDADDRESS" />'(이)가 완전하지 않습니다.</translation>
<translation id="5034860022980953847">진행률 표시기</translation>
+<translation id="5093189678851173835">제명</translation>
<translation id="5117590920725113268">다음 달 표시</translation>
<translation id="512758898067543763">행 헤더</translation>
+<translation id="5143125788380636750">에필로그</translation>
+<translation id="5153163864850940242">이 동영상은 PIP 모드에서 재생 중입니다.</translation>
<translation id="5164977714490026579">값은 <ph name="MINIMUM" /> 이상이어야 합니다.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" />PB</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' 앞 부분을 입력해 주세요. '<ph name="INVALIDADDRESS" />'(이)가 완전하지 않습니다.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">음소거 해제</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">10초를 건너뛰려면 왼쪽이나 오른쪽을 두 번 탭하세요.</translation>
+<translation id="5631759159893697722">초록</translation>
<translation id="5641012560118721995">재생 일시중지</translation>
<translation id="5643186887447432888">버튼</translation>
<translation id="5677946354068040947">옵션 더보기</translation>
+<translation id="576709008726043716">소개</translation>
<translation id="57838592816432529">음소거</translation>
<translation id="5860033963881614850">사용 안함</translation>
<translation id="588258955323874662">전체화면</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">연도</translation>
<translation id="6023896073578205740">목록 상자</translation>
<translation id="6101327004457443354">오디오 트랙 음소거 해제</translation>
+<translation id="6150588977291308318">참고문헌</translation>
<translation id="6164829606128959761">미터</translation>
+<translation id="6166809985690652833">후기</translation>
+<translation id="6213469881011901533">용어설명</translation>
<translation id="6398862346408813489">월 선택 패널 표시</translation>
<translation id="6404546809543547843">오디오 시간 스크러버</translation>
+<translation id="6453774872122745852">감사의 말</translation>
<translation id="648732519525291180">시간 선택기</translation>
<translation id="6550675742724504774">옵션</translation>
-<translation id="6564313821541007458">PIP 모드입니다.</translation>
<translation id="658823671542763450">전체화면 열기</translation>
<translation id="663493177488814956">피드</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">도움말</translation>
<translation id="6790428901817661496">재생</translation>
<translation id="6820355525329141109">플러그인을 로드할 수 없습니다.</translation>
+<translation id="6820615603175220800">참고문헌 참조</translation>
<translation id="6843725295806269523">음소거</translation>
<translation id="6853785296079745596">캡션 숨기기</translation>
<translation id="6885760532393684712">디렉토리</translation>
+<translation id="689129560213475294">출판사 이름</translation>
<translation id="6934078000481955284">인용구</translation>
<translation id="6941933287844615239">미디어 다운로드</translation>
<translation id="6989848892321993519">이 텍스트를 <ph name="MIN_CHARACTERS" />자 이상으로 늘리세요(현재 1자 사용 중).</translation>
<translation id="709897737746224366">요청한 형식과 일치시키세요.</translation>
+<translation id="7139483182332611405">머리말</translation>
<translation id="7223624360433298498">경과 시간</translation>
<translation id="7263440858009898357">목록에서 항목을 선택하세요.</translation>
<translation id="727747134524199931">열 헤더</translation>
+<translation id="7353453495576941748">크레딧</translation>
<translation id="7364796246159120393">파일 선택</translation>
<translation id="739024184232394898">다른 주...</translation>
+<translation id="7405738980073107433">미주</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" />TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">다운로드</translation>
+<translation id="7529102961911894712">뒤로 링크</translation>
+<translation id="7647456547678091388">도움말</translation>
+<translation id="7661956066982048809">그래픽 문서</translation>
<translation id="7673697353781729403">시간</translation>
+<translation id="7681220483256441252">색인</translation>
<translation id="7720026100085573005">남은 시간</translation>
<translation id="7740016676195725605">캡션 표시 중지</translation>
<translation id="7740050170769002709">HTML 콘텐츠</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">분할선</translation>
<translation id="795667975304826397">선택된 파일 없음</translation>
<translation id="8053789581856978548">검색어 입력란</translation>
+<translation id="8057695513531652401">안내문</translation>
+<translation id="8105797009065549151">참고 자료</translation>
<translation id="8115662671911883373">캡션 표시 시작</translation>
<translation id="8117451130807776954">이번 주</translation>
<translation id="819205353528511139">전체화면 모드로 영화 재생</translation>
<translation id="8199524924445686405">연도</translation>
<translation id="8284326494547611709">자막</translation>
<translation id="835897206747267392">값이 잘못되었습니다.</translation>
+<translation id="8415319359811155763">부</translation>
<translation id="8433900881053900389">툴바</translation>
<translation id="8444882422881193423">파일 <ph name="NUMBER_OF_FILES" />개</translation>
<translation id="8451268428117625855">파일을 선택하세요.</translation>
<translation id="8461852803063341183">라디오 버튼</translation>
+<translation id="8474886197722836894">헌정사</translation>
+<translation id="8531739829932800271">정오표</translation>
<translation id="8534579021159131403">분</translation>
<translation id="8541249477527128034">미디어 컨트롤</translation>
+<translation id="8550857728288566671">그래픽 기호</translation>
<translation id="8583702881314752957">정의 목록</translation>
<translation id="8597182159515967513">항목</translation>
+<translation id="860475260694818407">목차</translation>
<translation id="8613126697340063924">원격 재생 제어</translation>
+<translation id="862370744433916922">부제</translation>
<translation id="8741316211671074806">PIP 모드</translation>
<translation id="8750798805984357768">다음 옵션 중 하나를 선택하세요.</translation>
<translation id="8785498733064193001">재생 시작</translation>
+<translation id="8808573423886751634">장</translation>
<translation id="8845239796550121995">TV로 전송 중</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">동영상 재생 오류</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">다른 달...</translation>
<translation id="9138385573473225930">알림</translation>
<translation id="9155987714137265666"><ph name="WEEK" />(<ph name="WEEK_START_DATE" />에 시작)</translation>
+<translation id="9168329111483466115">각주</translation>
<translation id="947831847158436616">셀</translation>
<translation id="966787709310836684">메뉴</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_lt.xtb b/chromium/content/app/strings/translations/content_strings_lt.xtb
index 495c954d071..7ce8525f36b 100644
--- a/chromium/content/app/strings/translations/content_strings_lt.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lt.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">papildomas</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">šliaužiklis</translation>
+<translation id="1211441953136645838">išnaša</translation>
<translation id="1281252709823657822">dialogo langas</translation>
+<translation id="1335095011850992622">titrai</translation>
<translation id="1342835525016946179">artikelis</translation>
<translation id="1359897965706325498">reklamjuostė</translation>
<translation id="1589122976691792535">regionas</translation>
<translation id="1591562245178063882">Šis mėnuo</translation>
<translation id="1637811476055996098">Pasirinkti failus</translation>
+<translation id="1650423536718072820">citata</translation>
<translation id="1729654308190250600">Įveskite el. pašto adresą (nepalikite lauko tuščio).</translation>
<translation id="1758486001363313524">Kita...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">medžio tinklelis</translation>
<translation id="1822429046913737220">iki pietų / po pietų</translation>
<translation id="1832974991323546415">leisti naudojant nuotolinį įrenginį</translation>
+<translation id="1907737156431278478">pavyzdys</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">būsena</translation>
<translation id="1938124657309484470">Vertė turi būti <ph name="MAXIMUM_DATE_OR_TIME" /> ar ankstesnė data.</translation>
<translation id="1993104285338243655">Perjungta į ekrano vaizdo bendrinimą</translation>
<translation id="2060505056492490888">„<ph name="DOT" />“ naudojamas netinkamoje „<ph name="INVALIDDOMAIN" />“ vietoje.</translation>
<translation id="2148716181193084225">Šiandien</translation>
+<translation id="2158401438286456825">puslapių sąrašas</translation>
<translation id="2226276347425096477">Sutrumpinkite šį tekstą iki <ph name="MAX_CHARACTERS" /> simb. ar mažiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> m. <ph name="WEEKNUMBER" /> sav.</translation>
<translation id="2277199496770840904"><ph name="NUMBER" /> takelis</translation>
<translation id="2291999235780842123">žymimasis laukelis</translation>
+<translation id="2311842470354187719">puslapio lūžis</translation>
<translation id="2335594187091864976">datos ir laiko rinkiklis</translation>
<translation id="248395913932153421">Diena</translation>
<translation id="2507943997699731163">Užpildykite šį lauką.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">paleisti</translation>
<translation id="2613802280814924224">Įveskite tinkamą vertę. Artimiausia tinkama vertė yra <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Pateikti</translation>
+<translation id="2657045182931379222">grafikos objektas</translation>
<translation id="2674318244760992338">poraštė</translation>
<translation id="2709516037105925701">Automatinis pildymas</translation>
<translation id="2723001399770238859">garso įrašas</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Pailginkite šį tekstą iki <ph name="MIN_CHARACTERS" /> simb. ar daugiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
<translation id="383465348367842624">Prieš „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="3846214748874656680">Išjungti viso ekrano režimą</translation>
+<translation id="3920932319529768807">išvada</translation>
<translation id="3924558731517983934">programa</translation>
+<translation id="3944740393230681990">prologas</translation>
<translation id="3960700977367013758">slinkties juosta</translation>
<translation id="4103419683916926126">Milisekundės</translation>
<translation id="4151657705144244502">grafinis elementas</translation>
+<translation id="4193965531860883258">pratarmė</translation>
<translation id="4201051445878709314">Rodyti ankstesnį mėnesį</translation>
<translation id="421884353938374759">spalvos parinkiklis</translation>
<translation id="4248100235867064564">meniu juosta</translation>
<translation id="4254339807215791271">turinio informacija</translation>
<translation id="4360991593054037559">Įveskite galiojančią vertę. Dvi artimiausios vertės yra <ph name="VALID_VALUE_LOW" /> ir <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Klausimai ir atsakymai</translation>
<translation id="4413860115965805769">meniu mygtukas</translation>
+<translation id="4446524499724042288">aiškinamojo terminų žodyno nuoroda</translation>
<translation id="4522570452068850558">Išsami informacija</translation>
<translation id="4597532268155981612">forma</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Po „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4668956016107839909">priedas</translation>
+<translation id="4742539557769756338">viršelis</translation>
<translation id="4757246831282535685">skirtuko skydelis</translation>
<translation id="4763480195061959176">vaizdo įrašas</translation>
<translation id="479989351350248267">ieškoti</translation>
<translation id="4812940957355064477">Įveskite skaičių.</translation>
+<translation id="4912536737030637138">bibliografijos įrašas</translation>
<translation id="4975562563186953947">Pasirinkta: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Įjungti garsą</translation>
<translation id="49969490063480558">Įveskite dalį po „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ nėra visas el. pašto adresas.</translation>
<translation id="5034860022980953847">eigos indikatorius</translation>
+<translation id="5093189678851173835">epigrafas</translation>
<translation id="5117590920725113268">Rodyti kitą mėnesį</translation>
<translation id="512758898067543763">eilutės antraštė</translation>
+<translation id="5143125788380636750">epilogas</translation>
+<translation id="5153163864850940242">Šis vaizdo įrašas leidžiamas kaip vaizdas vaizde</translation>
<translation id="5164977714490026579">Vertė turi būti <ph name="MINIMUM" /> arba didesnė.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Įveskite el. pašto adreso dalį iki „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ nėra visas el. pašto adresas.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">įjungti garsą</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Dukart palieskite kairėn arba dešinėn, kad praleistumėte 10 sek.</translation>
+<translation id="5631759159893697722">santrauka</translation>
<translation id="5641012560118721995">pristabdyti atkūrimą</translation>
<translation id="5643186887447432888">mygtukas</translation>
<translation id="5677946354068040947">daugiau parinkčių</translation>
+<translation id="576709008726043716">įžanga</translation>
<translation id="57838592816432529">Nutildyti</translation>
<translation id="5860033963881614850">Išjungta</translation>
<translation id="588258955323874662">Visas ekranas</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Metai</translation>
<translation id="6023896073578205740">sąrašo laukelis</translation>
<translation id="6101327004457443354">įjungti garso įrašo takelio garsą</translation>
+<translation id="6150588977291308318">bibliografija</translation>
<translation id="6164829606128959761">matuoklis</translation>
+<translation id="6166809985690652833">baigiamasis žodis</translation>
+<translation id="6213469881011901533">aiškinamasis terminų žodynas</translation>
<translation id="6398862346408813489">Rodyti mėnesio pasirinkimo skydelį</translation>
<translation id="6404546809543547843">garso laiko valdiklis</translation>
+<translation id="6453774872122745852">padėka</translation>
<translation id="648732519525291180">laiko rinkiklis</translation>
<translation id="6550675742724504774">Parinktys</translation>
-<translation id="6564313821541007458">Dabar įjungtas vaizdo vaizde režimas</translation>
<translation id="658823671542763450">įjungti viso ekrano režimą</translation>
<translation id="663493177488814956">sklaidos kanalas</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">patarimas</translation>
<translation id="6790428901817661496">Žaisti</translation>
<translation id="6820355525329141109">Nepavyko įkelti papildinio.</translation>
+<translation id="6820615603175220800">bibliografijos nuoroda</translation>
<translation id="6843725295806269523">nutildyti</translation>
<translation id="6853785296079745596">slėpti subtitrus</translation>
<translation id="6885760532393684712">katalogas</translation>
+<translation id="689129560213475294">informacija apie leidimą</translation>
<translation id="6934078000481955284">citata</translation>
<translation id="6941933287844615239">atsisiųsti mediją</translation>
<translation id="6989848892321993519">Pailginkite šį tekstą iki <ph name="MIN_CHARACTERS" /> simb. ar daugiau (šiuo metu naudojate 1 simbolį).</translation>
<translation id="709897737746224366">Priderinkite reikalaujamą formatą.</translation>
+<translation id="7139483182332611405">įvadas</translation>
<translation id="7223624360433298498">praėjęs laikas</translation>
<translation id="7263440858009898357">Pasirinkite sąraše pateiktą elementą.</translation>
<translation id="727747134524199931">stulpelio antraštė</translation>
+<translation id="7353453495576941748">padėka</translation>
<translation id="7364796246159120393">Pasirinkti failą</translation>
<translation id="739024184232394898">Kita...</translation>
+<translation id="7405738980073107433">išnašos</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">Tabuliavimo klavišas</translation>
<translation id="7514365320538308">Atsisiųsti</translation>
+<translation id="7529102961911894712">atgalinė nuoroda</translation>
+<translation id="7647456547678091388">patarimas</translation>
+<translation id="7661956066982048809">grafikos dokumentas</translation>
<translation id="7673697353781729403">Valandos</translation>
+<translation id="7681220483256441252">rodyklė</translation>
<translation id="7720026100085573005">likęs laikas</translation>
<translation id="7740016676195725605">nebepateikti subtitrų</translation>
<translation id="7740050170769002709">HTML turinys</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">skaidiklis</translation>
<translation id="795667975304826397">Nepasirinktas joks failas</translation>
<translation id="8053789581856978548">paieškos teksto laukas</translation>
+<translation id="8057695513531652401">pranešimas</translation>
+<translation id="8105797009065549151">pastabos nuoroda</translation>
<translation id="8115662671911883373">pateikti subtitrus</translation>
<translation id="8117451130807776954">Ši savaitė</translation>
<translation id="819205353528511139">paleisti filmą viso ekrano režimu</translation>
<translation id="8199524924445686405">mmmm</translation>
<translation id="8284326494547611709">Subtitrai</translation>
<translation id="835897206747267392">Neteisinga vertė.</translation>
+<translation id="8415319359811155763">dalis</translation>
<translation id="8433900881053900389">įrankių juosta</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> failai (-ų)</translation>
<translation id="8451268428117625855">Pasirinkite failą.</translation>
<translation id="8461852803063341183">akutė</translation>
+<translation id="8474886197722836894">dedikacija</translation>
+<translation id="8531739829932800271">spaudos klaidų sąrašas</translation>
<translation id="8534579021159131403">Minutės</translation>
<translation id="8541249477527128034">medijos valdiklis</translation>
+<translation id="8550857728288566671">grafikos simbolis</translation>
<translation id="8583702881314752957">apibrėžimų sąrašas</translation>
<translation id="8597182159515967513">antraštė</translation>
+<translation id="860475260694818407">turinys</translation>
<translation id="8613126697340063924">valdyti nuotolinį atkūrimą</translation>
+<translation id="862370744433916922">paantraštė</translation>
<translation id="8741316211671074806">Vaizdas vaizde</translation>
<translation id="8750798805984357768">Pasirinkite vieną iš šių parinkčių.</translation>
<translation id="8785498733064193001">pradėti atkūrimą</translation>
+<translation id="8808573423886751634">skyrius</translation>
<translation id="8845239796550121995">Dabar perduodama į TV</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Vaizdo įrašo atkūrimo klaida</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Kita...</translation>
<translation id="9138385573473225930">įspėjimas</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, nuo <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">išnaša</translation>
<translation id="947831847158436616">langelis</translation>
<translation id="966787709310836684">meniu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_lv.xtb b/chromium/content/app/strings/translations/content_strings_lv.xtb
index 24cd767e5fa..2b2273786b5 100644
--- a/chromium/content/app/strings/translations/content_strings_lv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lv.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">papildu</translation>
<translation id="1206619573307042055">slīdošais teksts</translation>
<translation id="1206693055195146388">slīdnis</translation>
+<translation id="1211441953136645838">beigu vēre</translation>
<translation id="1281252709823657822">dialoglodziņš</translation>
+<translation id="1335095011850992622">pateicības</translation>
<translation id="1342835525016946179">raksts</translation>
<translation id="1359897965706325498">reklāmkarogs</translation>
<translation id="1589122976691792535">reģions</translation>
<translation id="1591562245178063882">Šis mēnesis</translation>
<translation id="1637811476055996098">Izvēlēties failus</translation>
+<translation id="1650423536718072820">izvilkuma citāts</translation>
<translation id="1729654308190250600">Lūdzu, ievadiet e-pasta adresi.</translation>
<translation id="1758486001363313524">Cits...</translation>
<translation id="1806710327868736751">brīdinājuma dialoglodziņš</translation>
<translation id="1821985195704844674">koka režģis</translation>
<translation id="1822429046913737220">priekšpusdienā/pēcpusdienā</translation>
<translation id="1832974991323546415">atskaņot attālinātā ierīcē</translation>
+<translation id="1907737156431278478">piemērs</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">statuss</translation>
<translation id="1938124657309484470">Vērtībai ir jābūt “<ph name="MAXIMUM_DATE_OR_TIME" />” vai agrākam datumam vai laikam.</translation>
<translation id="1993104285338243655">Mainīts uz spoguļošanu</translation>
<translation id="2060505056492490888">Punkts (<ph name="DOT" />) atrodas nepareizā vietā (<ph name="INVALIDDOMAIN" />).</translation>
<translation id="2148716181193084225">Šodien</translation>
+<translation id="2158401438286456825">lapu saraksts</translation>
<translation id="2226276347425096477">Lūdzu, saīsiniet šo tekstu līdz <ph name="MAX_CHARACTERS" /> vai mazāk zīmēm (pašreiz tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. nedēļa, <ph name="YEAR" />. gads</translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. ieraksts</translation>
<translation id="2291999235780842123">izvēles rūtiņa</translation>
+<translation id="2311842470354187719">lappuses pārtraukums</translation>
<translation id="2335594187091864976">datuma un laika atlasītājs</translation>
<translation id="248395913932153421">Diena</translation>
<translation id="2507943997699731163">Aizpildiet šo lauku.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">atskaņot</translation>
<translation id="2613802280814924224">Lūdzu, ievadiet derīgu vērtību. Tuvākā derīgā vērtība ir <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Iesniegt</translation>
+<translation id="2657045182931379222">grafiskais objekts</translation>
<translation id="2674318244760992338">kājene</translation>
<translation id="2709516037105925701">Automātiskā aizpilde</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Lūdzu, papildiniet šo tekstu līdz vismaz <ph name="MIN_CHARACTERS" /> rakstzīmēm (pašlaik tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
<translation id="383465348367842624">Daļā, kas atrodas pirms zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
<translation id="3846214748874656680">Aizvērt pilnekrāna režīmu</translation>
+<translation id="3920932319529768807">nobeigums</translation>
<translation id="3924558731517983934">lietojumprogramma</translation>
+<translation id="3944740393230681990">prologs</translation>
<translation id="3960700977367013758">ritjosla</translation>
<translation id="4103419683916926126">Milisekundes</translation>
<translation id="4151657705144244502">grafiskais elements</translation>
+<translation id="4193965531860883258">priekšvārds</translation>
<translation id="4201051445878709314">Rādīt iepriekšējo mēnesi</translation>
<translation id="421884353938374759">krāsu izvēle</translation>
<translation id="4248100235867064564">izvēļņu josla</translation>
<translation id="4254339807215791271">satura informācija</translation>
<translation id="4360991593054037559">Lūdzu, ievadiet derīgu vērtību. Divas tuvākās derīgās vērtības ir <ph name="VALID_VALUE_LOW" /> un <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Jautājumi un atbildes</translation>
<translation id="4413860115965805769">izvēlnes poga</translation>
+<translation id="4446524499724042288">atsauce uz glosāriju</translation>
<translation id="4522570452068850558">Informācija</translation>
<translation id="4597532268155981612">veidlapa</translation>
<translation id="4661075872484491155">koks</translation>
<translation id="4664250907885839816">Daļā, kas atrodas aiz zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">pielikums</translation>
+<translation id="4742539557769756338">vāks</translation>
<translation id="4757246831282535685">ciļņu panelis</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">meklēt</translation>
<translation id="4812940957355064477">Lūdzu, ievadiet skaitli.</translation>
+<translation id="4912536737030637138">bibliogrāfijas ieraksts</translation>
<translation id="4975562563186953947">Atlasīti <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Ieslēgt skaņu</translation>
<translation id="49969490063480558">Lūdzu, ievadiet daļu, kas atrodas aiz zīmes <ph name="ATSIGN" />. “<ph name="INVALIDADDRESS" />” ir nepilna adrese.</translation>
<translation id="5034860022980953847">norises indikators</translation>
+<translation id="5093189678851173835">epigrāfs</translation>
<translation id="5117590920725113268">Rādīt nākamo mēnesi</translation>
<translation id="512758898067543763">rindas virsraksts</translation>
+<translation id="5143125788380636750">epilogs</translation>
+<translation id="5153163864850940242">Videoklips tiek atskaņots režīmā Attēls attēlā</translation>
<translation id="5164977714490026579">Vērtībai ir jābūt lielākai vai vienādai ar <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Lūdzu, ievadiet daļu, kas atrodas pirms zīmes <ph name="ATSIGN" />. “<ph name="INVALIDADDRESS" />” ir nepilna adrese.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">rādīt</translation>
<translation id="561939826962581046">laiks</translation>
<translation id="5630795885300617244">Veiciet dubultskārienu pa labi vai pa kreisi, lai izlaistu 10 s.</translation>
+<translation id="5631759159893697722">kopsavilkums</translation>
<translation id="5641012560118721995">pauzēt atskaņošanu</translation>
<translation id="5643186887447432888">poga</translation>
<translation id="5677946354068040947">citas opcijas</translation>
+<translation id="576709008726043716">ievads</translation>
<translation id="57838592816432529">Izslēgt skaņu</translation>
<translation id="5860033963881614850">Izsl.</translation>
<translation id="588258955323874662">Pilnekrāna</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Gads</translation>
<translation id="6023896073578205740">sarakstlodziņš</translation>
<translation id="6101327004457443354">ieslēgt audio ieraksta skaņu</translation>
+<translation id="6150588977291308318">bibliogrāfija</translation>
<translation id="6164829606128959761">mērītājs</translation>
+<translation id="6166809985690652833">pēcvārds</translation>
+<translation id="6213469881011901533">glosārijs</translation>
<translation id="6398862346408813489">Rādīt mēneša atlases paneli</translation>
<translation id="6404546809543547843">audio laika skalas slīdnis</translation>
+<translation id="6453774872122745852">pateicības</translation>
<translation id="648732519525291180">laika atlasītājs</translation>
<translation id="6550675742724504774">Opcijas</translation>
-<translation id="6564313821541007458">Notiek atskaņošana režīmā “Attēls attēlā”.</translation>
<translation id="658823671542763450">atvērt pilnekrāna režīmā</translation>
<translation id="663493177488814956">plūsma</translation>
<translation id="6637586476836377253">žurnāls</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">rīka padoms</translation>
<translation id="6790428901817661496">Atskaņot</translation>
<translation id="6820355525329141109">Nevarēja ielādēt spraudni.</translation>
+<translation id="6820615603175220800">bibliogrāfiskā atsauce</translation>
<translation id="6843725295806269523">izslēgt skaņu</translation>
<translation id="6853785296079745596">slēpt slēgtos parakstus</translation>
<translation id="6885760532393684712">katalogs</translation>
+<translation id="689129560213475294">izdošanas ziņas</translation>
<translation id="6934078000481955284">citāta bloks</translation>
<translation id="6941933287844615239">lejupielādēt multivides failus</translation>
<translation id="6989848892321993519">Lūdzu, papildiniet šo tekstu līdz vismaz <ph name="MIN_CHARACTERS" /> rakstzīmēm (pašlaik tas ietver 1 rakstzīmi).</translation>
<translation id="709897737746224366">Pieskaņojiet vērtību prasītajam formātam.</translation>
+<translation id="7139483182332611405">ievadraksts</translation>
<translation id="7223624360433298498">pagājušais laiks</translation>
<translation id="7263440858009898357">Atlasiet vienumu sarakstā.</translation>
<translation id="727747134524199931">slejas virsraksts</translation>
+<translation id="7353453495576941748">pateicība</translation>
<translation id="7364796246159120393">Izvēlēties failu</translation>
<translation id="739024184232394898">Cits...</translation>
+<translation id="7405738980073107433">beigu vēres</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">cilne</translation>
<translation id="7514365320538308">Lejupielādēt</translation>
+<translation id="7529102961911894712">atpakaļsaite</translation>
+<translation id="7647456547678091388">padoms</translation>
+<translation id="7661956066982048809">grafikas dokuments</translation>
<translation id="7673697353781729403">Stundas</translation>
+<translation id="7681220483256441252">rādītājs</translation>
<translation id="7720026100085573005">atlikušais laiks</translation>
<translation id="7740016676195725605">apturēt slēgto parakstu rādīšanu</translation>
<translation id="7740050170769002709">HTML saturs</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">sadalītājs</translation>
<translation id="795667975304826397">Nav izvēlēts neviens fails</translation>
<translation id="8053789581856978548">meklēšanas teksta lauks</translation>
+<translation id="8057695513531652401">paziņojums</translation>
+<translation id="8105797009065549151">vēres atsauce</translation>
<translation id="8115662671911883373">sākt slēgto parakstu rādīšanu</translation>
<translation id="8117451130807776954">Šī nedēļa</translation>
<translation id="819205353528511139">atskaņot filmu pilnekrāna režīmā</translation>
<translation id="8199524924445686405">gggg</translation>
<translation id="8284326494547611709">Paraksti</translation>
<translation id="835897206747267392">Nederīga vērtība.</translation>
+<translation id="8415319359811155763">daļa</translation>
<translation id="8433900881053900389">rīkjosla</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
<translation id="8451268428117625855">Lūdzu, atlasiet failu.</translation>
<translation id="8461852803063341183">radiopoga</translation>
+<translation id="8474886197722836894">veltījums</translation>
+<translation id="8531739829932800271">iespiedkļūdu saraksts</translation>
<translation id="8534579021159131403">Minūtes</translation>
<translation id="8541249477527128034">multivides vadība</translation>
+<translation id="8550857728288566671">grafiskais simbols</translation>
<translation id="8583702881314752957">definīciju saraksts</translation>
<translation id="8597182159515967513">Virsraksts</translation>
+<translation id="860475260694818407">satura rādītājs</translation>
<translation id="8613126697340063924">kontrolēt attālināto atskaņošanu</translation>
+<translation id="862370744433916922">apakšvirsraksts</translation>
<translation id="8741316211671074806">Attēls attēlā</translation>
<translation id="8750798805984357768">Lūdzu, atlasiet vienu no šīm opcijām.</translation>
<translation id="8785498733064193001">sākt atskaņošanu</translation>
+<translation id="8808573423886751634">nodaļa</translation>
<translation id="8845239796550121995">Pašlaik notiek apraide uz jūsu TV</translation>
<translation id="8851136666856101339">galvenais</translation>
<translation id="8875657656876809964">Videoklipa atskaņošanas kļūda</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Cits...</translation>
<translation id="9138385573473225930">brīdinājums</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, sākot no: <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">vēre</translation>
<translation id="947831847158436616">šūna</translation>
<translation id="966787709310836684">izvēlne</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ml.xtb b/chromium/content/app/strings/translations/content_strings_ml.xtb
index 66589c22bc4..5b07795a2db 100644
--- a/chromium/content/app/strings/translations/content_strings_ml.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ml.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">കോംപ്ലിമെന്ററി</translation>
<translation id="1206619573307042055">മാർക്യൂ</translation>
<translation id="1206693055195146388">സ്ലൈഡർ</translation>
+<translation id="1211441953136645838">അന്തിമ കുറിപ്പ്</translation>
<translation id="1281252709823657822">ഡയലോഗ്</translation>
+<translation id="1335095011850992622">ക്രെഡിറ്റുകൾ</translation>
<translation id="1342835525016946179">ലേഖനം</translation>
<translation id="1359897965706325498">ബാനർ</translation>
<translation id="1589122976691792535">പ്രദേശം</translation>
<translation id="1591562245178063882">ഈ മാസം</translation>
<translation id="1637811476055996098">ഫയലുകൾ തിരഞ്ഞെടുക്കുക</translation>
+<translation id="1650423536718072820">പുൾക്വോട്ട്</translation>
<translation id="1729654308190250600">ശൂന്യമായിടാതെ, ഇമെയിൽ വിലാസം നൽകുക.</translation>
<translation id="1758486001363313524">മറ്റുള്ളവ...</translation>
<translation id="1806710327868736751">അലേർട്ട്_ഡയലോഗ്</translation>
<translation id="1821985195704844674">ട്രീ ഗ്രിഡ്</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">വിദൂര ഉപകരണത്തിൽ പ്ലേ ചെയ്യുക</translation>
+<translation id="1907737156431278478">ഉദാഹരണം</translation>
<translation id="1921819250265091946">തീയതി</translation>
<translation id="1930711995431081526">നില</translation>
<translation id="1938124657309484470">മൂല്യം <ph name="MAXIMUM_DATE_OR_TIME" /> എന്നതോ അതിനുമുമ്പുള്ള തീയതിയോ ആയിരിക്കണം.</translation>
<translation id="1993104285338243655">മിററിംഗിലേക്ക് മാറി</translation>
<translation id="2060505056492490888">'<ph name="DOT" />', '<ph name="INVALIDDOMAIN" />' എന്നതിൽ തെറ്റായ സ്ഥാനത്താണ് ഉപയോഗിച്ചിരിക്കുന്നത്.</translation>
<translation id="2148716181193084225">ഇന്ന്</translation>
+<translation id="2158401438286456825">പേജ് ലിസ്റ്റ്</translation>
<translation id="2226276347425096477">ഈ വാചകത്തെ <ph name="MAX_CHARACTERS" /> അല്ലെങ്കില്‍ അതില്‍‌ക്കുറവ് പ്രതീകങ്ങളായി ദയവായി കുറയ്ക്കുക (നിങ്ങള്‍ നിലവില്‍ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങള്‍ ഉപയോഗിക്കുകയാണ്).</translation>
<translation id="2247351761944213033">ആഴ്‌ച <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ട്രാക്ക് <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ചെക്ക്‌ബോക്‌സ്</translation>
+<translation id="2311842470354187719">പേജ് ബ്രേക്ക്</translation>
<translation id="2335594187091864976">തീയതിയും സമയ പിക്കറും</translation>
<translation id="248395913932153421">ദിവസം</translation>
<translation id="2507943997699731163">ദയവായി ഈ ഫീല്‍ഡ് പൂരിപ്പിക്കുക.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">പ്ലേ ചെയ്യുക</translation>
<translation id="2613802280814924224">സാധുവായ ഒരു മൂല്യം നൽകുക. ഏറ്റവുമടുത്ത സാധുവായ മൂല്യം <ph name="VALID_VALUE" /> ആണ്.</translation>
<translation id="2653659639078652383">സമര്‍പ്പിക്കൂ</translation>
+<translation id="2657045182931379222">ഗ്രാഫിക്‌സ് ഒബ്‌ജക്‌റ്റ്</translation>
<translation id="2674318244760992338">അടിക്കുറിപ്പ്</translation>
<translation id="2709516037105925701">ഓട്ടോഫില്‍</translation>
<translation id="2723001399770238859">ഓഡിയോ</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">ഈ ടെക്‌സ്റ്റിന്റെ ദൈർഘ്യം <ph name="MIN_CHARACTERS" /> അല്ലെങ്കിൽ അതിൽക്കൂടുതൽ പ്രതീകങ്ങൾ നൽകി കൂട്ടുക. (നിങ്ങൾ നിലവിൽ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങളാണ് ഉപയോഗിക്കുന്നത്).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഒരു ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
<translation id="3846214748874656680">പൂർണ്ണ സ്‌ക്രീനിൽ നിന്ന് പുറത്തുകടക്കുക</translation>
+<translation id="3920932319529768807">ഉപസംഹാരം</translation>
<translation id="3924558731517983934">അപ്ലിക്കേഷൻ</translation>
+<translation id="3944740393230681990">ആമുഖം</translation>
<translation id="3960700977367013758">സ്‌ക്രോൾ ബാർ</translation>
<translation id="4103419683916926126">മില്ലിസെക്കൻഡ്</translation>
<translation id="4151657705144244502">ഗ്രാഫിക്</translation>
+<translation id="4193965531860883258">മുഖവുര</translation>
<translation id="4201051445878709314">മുൻ മാസം കാണിക്കുക</translation>
<translation id="421884353938374759">വർണ്ണ പിക്കർ</translation>
<translation id="4248100235867064564">മെനു ബാർ</translation>
<translation id="4254339807215791271">ഉള്ളടക്ക വിവരം</translation>
<translation id="4360991593054037559">സാധുവായ മൂല്യം നൽകുക. സാധുവായ ഏറ്റവുമടുത്ത രണ്ട് മൂല്യങ്ങൾ <ph name="VALID_VALUE_LOW" />, <ph name="VALID_VALUE_HIGHER" /> എന്നിവയാണ്.</translation>
+<translation id="4384583879834880242">ചോദ്യോത്തരം</translation>
<translation id="4413860115965805769">മെനു ബട്ടൺ</translation>
+<translation id="4446524499724042288">പദസഞ്ചയ റെഫറൻസ്</translation>
<translation id="4522570452068850558">വിശദാംശങ്ങൾ‌</translation>
<translation id="4597532268155981612">ഫോം</translation>
<translation id="4661075872484491155">ട്രീ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
+<translation id="4668956016107839909">അനുബന്ധം</translation>
+<translation id="4742539557769756338">കവർ</translation>
<translation id="4757246831282535685">ടാബ് പാനൽ</translation>
<translation id="4763480195061959176">വീഡിയോ</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">ഒരു നമ്പർ നൽകുക.</translation>
+<translation id="4912536737030637138">ഗ്രന്ഥസൂചി എൻട്രി</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> തിരഞ്ഞെടുത്തു</translation>
<translation id="4992066212339426712">അൺമ്യൂട്ടുചെയ്യുക</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS" />' അപൂർണ്ണമാണ്.</translation>
<translation id="5034860022980953847">'പ്രോഗ്രസ്' ഇൻഡിക്കേറ്റർ</translation>
+<translation id="5093189678851173835">ശിലാലേഖ</translation>
<translation id="5117590920725113268">അടുത്ത മാസം കാണിക്കുക</translation>
<translation id="512758898067543763">വരി ശീർഷകം</translation>
+<translation id="5143125788380636750">ഉപസംഹാരം</translation>
+<translation id="5153163864850940242">'ചിത്രത്തിനുള്ളിലെ ചിത്രം' മോഡിലാണ് ഈ വീഡിയോ പ്ലേ ചേയ്യുന്നത്</translation>
<translation id="5164977714490026579">മൂല്യം <ph name="MINIMUM" /> എന്നതില്‍ കൂടുതലോ സമമോ ആയിരിക്കണം.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS" />' അപൂർണ്ണമാണ്.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">ശബ്‌ദമുള്ളതാക്കുക</translation>
<translation id="561939826962581046">സമയം</translation>
<translation id="5630795885300617244">10 സെക്കൻഡ് ഒഴിവാക്കാൻ ഇടത്തോട്ടോ വലത്തോട്ടോ രണ്ടുതവണ ടാപ്പ് ചെയ്യുക</translation>
+<translation id="5631759159893697722">സംക്ഷേപം</translation>
<translation id="5641012560118721995">പ്ലേബാക്ക് താൽക്കാലികമായി നിർത്തുക</translation>
<translation id="5643186887447432888">ബട്ടൺ</translation>
<translation id="5677946354068040947">കൂടുതൽ ഓപ്‌ഷനുകൾ</translation>
+<translation id="576709008726043716">ആമുഖം</translation>
<translation id="57838592816432529">മ്യൂട്ടുചെയ്യുക</translation>
<translation id="5860033963881614850">ഓഫാക്കുക</translation>
<translation id="588258955323874662">പൂര്‍‌ണ്ണസ്‌ക്രീന്‍</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">വര്‍ഷം</translation>
<translation id="6023896073578205740">ലിസ്റ്റ് ബോക്‌സ്</translation>
<translation id="6101327004457443354">ഓഡിയോ ട്രാക്ക് ശബ്‌ദമുള്ളതാക്കുക</translation>
+<translation id="6150588977291308318">ഗ്രന്ഥസൂചി</translation>
<translation id="6164829606128959761">മീറ്റർ</translation>
+<translation id="6166809985690652833">പിൻ കുറിപ്പ്</translation>
+<translation id="6213469881011901533">പദസഞ്ചയം</translation>
<translation id="6398862346408813489">മാസം തിരഞ്ഞെടുക്കുന്ന പാനൽ കാണിക്കുക</translation>
<translation id="6404546809543547843">ഓഡിയോ സമയ സ്‌ക്രബർ</translation>
+<translation id="6453774872122745852">കടപ്പാട്</translation>
<translation id="648732519525291180">സമയ പിക്കർ</translation>
<translation id="6550675742724504774">ഓപ്ഷനുകൾ</translation>
-<translation id="6564313821541007458">ഇപ്പോൾ ചിത്രത്തിനുള്ളിലെ ചിത്രം മോഡിൽ</translation>
<translation id="658823671542763450">പൂർണ്ണ സ്‌ക്രീനിലേക്ക് പോവുക</translation>
<translation id="663493177488814956">ഫീഡ്</translation>
<translation id="6637586476836377253">ലോഗ്</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">ടൂൾടിപ്പ്</translation>
<translation id="6790428901817661496">പ്ലേചെയ്യുക</translation>
<translation id="6820355525329141109">പ്ലഗിൻ ലോഡുചെയ്യാനായില്ല.</translation>
+<translation id="6820615603175220800">ഗ്രന്ഥസൂചി റെഫറൻസ്</translation>
<translation id="6843725295806269523">നിശബ്‌ദമാക്കുക</translation>
<translation id="6853785296079745596">അടച്ച അടിക്കുറിപ്പുകൾ മറയ്‌ക്കുക</translation>
<translation id="6885760532393684712">ഡയറക്‌ടറി</translation>
+<translation id="689129560213475294">അച്ചടിമുദ്ര</translation>
<translation id="6934078000481955284">ബ്ലോക്ക്‌കോട്ട്</translation>
<translation id="6941933287844615239">മീഡിയ ഡൗൺലോഡുചെയ്യുക</translation>
<translation id="6989848892321993519">ഈ ടെക്‌സ്റ്റിന്റെ ദൈർഘ്യം <ph name="MIN_CHARACTERS" /> പ്രതീകങ്ങളോ അതിൽ കൂടുതലോ ആയി വർദ്ധിപ്പിക്കുക (നിങ്ങൾ നിലവിൽ ഒരു പ്രതീകം മാത്രമേ ഉപയോഗിക്കുന്നുള്ളൂ).</translation>
<translation id="709897737746224366">അഭ്യര്‍ത്ഥി ച്ചഫോര്‍മാറ്റ് ദയവായി പൊരുത്തപ്പെടുത്തുക.</translation>
+<translation id="7139483182332611405">പീഠിക</translation>
<translation id="7223624360433298498">കഴിഞ്ഞ സമയം</translation>
<translation id="7263440858009898357">പട്ടികയിലെ ഒരു ഇനം ദയവായി തിരഞ്ഞെടുക്കുക</translation>
<translation id="727747134524199931">കോളം പേര്</translation>
+<translation id="7353453495576941748">ക്രെഡിറ്റ്</translation>
<translation id="7364796246159120393">ഫയല്‍ തിരഞ്ഞെടുക്കൂ</translation>
<translation id="739024184232394898">മറ്റുള്ളവ...</translation>
+<translation id="7405738980073107433">അന്തിമ കുറിപ്പുകൾ</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">ടാബ്</translation>
<translation id="7514365320538308">ഡൗൺലോഡുചെയ്യുക</translation>
+<translation id="7529102961911894712">ബാക്ക്‌ ലിങ്ക്</translation>
+<translation id="7647456547678091388">നുറുങ്ങ്</translation>
+<translation id="7661956066982048809">ഗ്രാഫിക്‌സ് ഡോക്യുമെന്റ്</translation>
<translation id="7673697353781729403">മണിക്കൂര്‍‌</translation>
+<translation id="7681220483256441252">സൂചിക</translation>
<translation id="7720026100085573005">അവശേഷിക്കുന്ന സമയം</translation>
<translation id="7740016676195725605">അടച്ച അടിക്കുറിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നത് നിർത്തുക</translation>
<translation id="7740050170769002709">HTML ഉള്ളടക്കം</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">സ്‌പ്ലിറ്റർ</translation>
<translation id="795667975304826397">ഒരു ഫയലും തിരഞ്ഞെടുത്തിട്ടില്ല</translation>
<translation id="8053789581856978548">തിരയൽ ടെക്‌സ്റ്റ് ഫീൽഡ്</translation>
+<translation id="8057695513531652401">അറിയിപ്പ്</translation>
+<translation id="8105797009065549151">കുറിപ്പ് റെഫറൻസ്</translation>
<translation id="8115662671911883373">അടച്ച അടിക്കുറിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നത് ആരംഭിക്കുക</translation>
<translation id="8117451130807776954">ഈ ആഴ്‌ച</translation>
<translation id="819205353528511139">പൂർണ്ണ സ്‌ക്രീൻ മോഡിൽ മൂവി പ്ലേ ചെയ്യുക</translation>
<translation id="8199524924445686405">വർഷം</translation>
<translation id="8284326494547611709">അടിക്കുറിപ്പുകൾ</translation>
<translation id="835897206747267392">അസാധുവായ മൂല്യം.</translation>
+<translation id="8415319359811155763">ഭാഗം</translation>
<translation id="8433900881053900389">ടൂൾബാർ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ഫയലുകള്‍</translation>
<translation id="8451268428117625855">ദയവായി ഒരു ഫയല്‍ തരം തിരഞ്ഞെടുക്കുക.</translation>
<translation id="8461852803063341183">റേഡിയോ ബട്ടൺ</translation>
+<translation id="8474886197722836894">സമർപ്പണം</translation>
+<translation id="8531739829932800271">സംശോധന പട്ടിക</translation>
<translation id="8534579021159131403">മിനിറ്റ്</translation>
<translation id="8541249477527128034">മീഡിയ നിയന്ത്രണം</translation>
+<translation id="8550857728288566671">ഗ്രാഫിക്സ് ചിഹ്നം</translation>
<translation id="8583702881314752957">നിർവചന ലിസ്റ്റ്</translation>
<translation id="8597182159515967513">തലക്കെട്ട്</translation>
+<translation id="860475260694818407">ഉള്ളടക്ക പട്ടിക</translation>
<translation id="8613126697340063924">വിദൂര പ്ലേബാക്ക് നിയന്ത്രിക്കുക</translation>
+<translation id="862370744433916922">ഉപശീർഷകം</translation>
<translation id="8741316211671074806">ചിത്രത്തിനുള്ളിലെ ചിത്രം</translation>
<translation id="8750798805984357768">ഈ ഓപ്ഷനുകളിലൊന്ന് ദയവായി തിരഞ്ഞെടുക്കുക.</translation>
<translation id="8785498733064193001">പ്ലേബാക്ക് ആരംഭിക്കുക</translation>
+<translation id="8808573423886751634">അധ്യായം</translation>
<translation id="8845239796550121995">ഇപ്പോൾ നിങ്ങളുടെ ടിവിയിൽ കാസ്‌റ്റുചെയ്യുന്നു</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">വീഡിയോ പ്ലേബാക്ക് പിശക്</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">മറ്റുള്ളവ...</translation>
<translation id="9138385573473225930">അലേർട്ട്</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" />-ന് ആരംഭിക്കുന്നു</translation>
+<translation id="9168329111483466115">അടിക്കുറിപ്പ്</translation>
<translation id="947831847158436616">സെൽ</translation>
<translation id="966787709310836684">മെനു</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_mr.xtb b/chromium/content/app/strings/translations/content_strings_mr.xtb
index a39b0cef88d..1f29d299817 100644
--- a/chromium/content/app/strings/translations/content_strings_mr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_mr.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">पूरक</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">स्लायडर</translation>
+<translation id="1211441953136645838">तळटीप</translation>
<translation id="1281252709823657822">संवाद</translation>
+<translation id="1335095011850992622">श्रेय</translation>
<translation id="1342835525016946179">लेख</translation>
<translation id="1359897965706325498">बॅनर</translation>
<translation id="1589122976691792535">प्रदेश</translation>
<translation id="1591562245178063882">या महिन्यात</translation>
<translation id="1637811476055996098">फायली निवडा</translation>
+<translation id="1650423536718072820">पुलकोट</translation>
<translation id="1729654308190250600">कृपया एक रिक्त-नसलेला ईमेल अॅड्रेस एंटर करा.</translation>
<translation id="1758486001363313524">अन्य...</translation>
<translation id="1806710327868736751">सूचना_संवाद</translation>
<translation id="1821985195704844674">ट्री ग्रीड</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">दूरस्थ डिव्हाइसवर प्ले करा</translation>
+<translation id="1907737156431278478">उदाहरण</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">स्थिती</translation>
<translation id="1938124657309484470">मूल्य <ph name="MAXIMUM_DATE_OR_TIME" /> किंवा आधीचे असणे आवश्यक आहे.</translation>
<translation id="1993104285338243655">मिररिंगवर स्विच केले</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' '<ph name="INVALIDDOMAIN" />' मध्ये चुकीच्या स्थितीवर वापरले आहे.</translation>
<translation id="2148716181193084225">आज</translation>
+<translation id="2158401438286456825">पेज सूची</translation>
<translation id="2226276347425096477">कृपया हा मजकूर <ph name="MAX_CHARACTERS" /> वर्ण लहान किंवा कमी करा (आपण सध्या <ph name="CURRENT_LENGTH" /> वर्ण वापरत आहात).</translation>
<translation id="2247351761944213033">आठवडा <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ट्रॅक <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">चेकबॉक्‍स</translation>
+<translation id="2311842470354187719">पेज ब्रेक</translation>
<translation id="2335594187091864976">तारीख आणि वेळ निवडक</translation>
<translation id="248395913932153421">दिवस</translation>
<translation id="2507943997699731163">कृपया हे फील्ड भरा.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">प्ले करा</translation>
<translation id="2613802280814924224">कृपया एक वैध मूल्य एंटर करा. जवळील वैध मूल्य <ph name="VALID_VALUE" /> आहे.</translation>
<translation id="2653659639078652383">सबमिट करा</translation>
+<translation id="2657045182931379222">ग्राफिक्स ऑब्जेक्ट</translation>
<translation id="2674318244760992338">अधोलेख</translation>
<translation id="2709516037105925701">ऑटोफिल</translation>
<translation id="2723001399770238859">ऑडिओ</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">कृपया हा मजकूर <ph name="MIN_CHARACTERS" /> वर्ण किंवा त्यापेक्षा अधिक मोठा करा (आपण सध्‍या <ph name="CURRENT_LENGTH" /> वर्ण वापरत आहात).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' मागुन येणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
<translation id="3846214748874656680">पूर्णस्क्रीनमधून बाहेर पडा</translation>
+<translation id="3920932319529768807">निष्कर्ष</translation>
<translation id="3924558731517983934">अॅप्लिकेशन</translation>
+<translation id="3944740393230681990">उपोद्घात</translation>
<translation id="3960700977367013758">स्क्रोल बार</translation>
<translation id="4103419683916926126">मिलिसेकंद</translation>
<translation id="4151657705144244502">ग्राफिक</translation>
+<translation id="4193965531860883258">प्रस्तावना</translation>
<translation id="4201051445878709314">मागील महिना दर्शवा</translation>
<translation id="421884353938374759">रंग निवडक</translation>
<translation id="4248100235867064564">मेनू बार</translation>
<translation id="4254339807215791271">सामग्री माहिती</translation>
<translation id="4360991593054037559">कृपया एक वैध मूल्य एंटर करा. दोन जवळील वैध मूल्ये <ph name="VALID_VALUE_LOW" /> आणि <ph name="VALID_VALUE_HIGHER" /> आहेत.</translation>
+<translation id="4384583879834880242">प्रश्नोत्तरे</translation>
<translation id="4413860115965805769">मेनू बटण</translation>
+<translation id="4446524499724042288">शब्दावली संदर्भ</translation>
<translation id="4522570452068850558">तपशील</translation>
<translation id="4597532268155981612">फॉर्म</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' चे फॉलो करणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
+<translation id="4668956016107839909">परिशिष्ट</translation>
+<translation id="4742539557769756338">कव्हर</translation>
<translation id="4757246831282535685">टॅब पॅनेल</translation>
<translation id="4763480195061959176">व्हिडिओ</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">कृपया एक नंबर एंटर करा.</translation>
+<translation id="4912536737030637138">ग्रंथसूची नोंद</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> निवडले</translation>
<translation id="4992066212339426712">सशब्द करा</translation>
<translation id="49969490063480558">कृपया '<ph name="ATSIGN" />' चे फॉलो करणारा भाग एंटर करा. '<ph name="INVALIDADDRESS" />' अपूर्ण आहे.</translation>
<translation id="5034860022980953847">प्रगती सूचक</translation>
+<translation id="5093189678851173835">बोधवाक्य</translation>
<translation id="5117590920725113268">पुढील महिना दर्शवा</translation>
<translation id="512758898067543763">पंक्ती शीर्षलेख</translation>
+<translation id="5143125788380636750">उपसंहार</translation>
+<translation id="5153163864850940242">हा व्हिडिओ पिक्चर-इन-पिक्चर मध्ये सुरू आहे</translation>
<translation id="5164977714490026579">मूल्य <ph name="MINIMUM" /> पेक्षा मोठे किंवा समान असावे.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">कृपया '<ph name="ATSIGN" />' मागुन येणारा भाग एंटर करा. '<ph name="INVALIDADDRESS" />' अपूर्ण आहे.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">सशब्द करा</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">10 सेकंद वगळण्यासाठी डावीकडे किंवा उजवीकडे दोनदा टॅप करा</translation>
+<translation id="5631759159893697722">अमूर्त</translation>
<translation id="5641012560118721995">प्लेबॅकला विराम द्या</translation>
<translation id="5643186887447432888">बटण</translation>
<translation id="5677946354068040947">अधिक पर्याय</translation>
+<translation id="576709008726043716">परिचय</translation>
<translation id="57838592816432529">निःशब्द करा</translation>
<translation id="5860033963881614850">बंद</translation>
<translation id="588258955323874662">पूर्णस्क्रीन</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">वर्ष</translation>
<translation id="6023896073578205740">सूची बॉक्स</translation>
<translation id="6101327004457443354">ऑडिओ ट्रॅक सशब्द करा</translation>
+<translation id="6150588977291308318">ग्रंथसूची</translation>
<translation id="6164829606128959761">मीटर</translation>
+<translation id="6166809985690652833">अंतिम शब्द</translation>
+<translation id="6213469881011901533">शब्दावली</translation>
<translation id="6398862346408813489">महिना निवड पॅनेल दर्शवा</translation>
<translation id="6404546809543547843">ऑडिओ वेळ स्क्रबर</translation>
+<translation id="6453774872122745852">श्रेयनिर्देश</translation>
<translation id="648732519525291180">वेळ निवडक</translation>
<translation id="6550675742724504774">पर्याय</translation>
-<translation id="6564313821541007458">आता चित्रात-चित्र मोडमध्ये</translation>
<translation id="658823671542763450">पूर्ण स्क्रीन एंटर करा</translation>
<translation id="663493177488814956">फीड</translation>
<translation id="6637586476836377253">लॉग</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">टूलटिप</translation>
<translation id="6790428901817661496">प्ले करा</translation>
<translation id="6820355525329141109">प्लगिन लोड करणे शक्य झाले नाही.</translation>
+<translation id="6820615603175220800">ग्रंथसूची संदर्भ</translation>
<translation id="6843725295806269523">नि:शब्द करा</translation>
<translation id="6853785296079745596">बंद मथळा लपवा</translation>
<translation id="6885760532393684712">निर्देशिका</translation>
+<translation id="689129560213475294">बोधचिन्ह</translation>
<translation id="6934078000481955284">ब्लॉककोट</translation>
<translation id="6941933287844615239">मीडिया डाउनलोड करा</translation>
<translation id="6989848892321993519">कृपया हा मजकूर <ph name="MIN_CHARACTERS" /> वर्ण किंवा त्यापेक्षा अधिक मोठा करा (आपण सध्‍या 1 वर्ण वापरत आहात).</translation>
<translation id="709897737746224366">कृपया विनंती केलेले स्वरूपन जुळवा.</translation>
+<translation id="7139483182332611405">प्रस्तावना</translation>
<translation id="7223624360433298498">लोटलेला अवधी</translation>
<translation id="7263440858009898357">कृपया सूचीमधील आयटम निवडा.</translation>
<translation id="727747134524199931">स्तंभ शीर्षलेख</translation>
+<translation id="7353453495576941748">श्रेय</translation>
<translation id="7364796246159120393">फाइल निवडा</translation>
<translation id="739024184232394898">अन्य...</translation>
+<translation id="7405738980073107433">अंतिम नोंदी</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">टॅब</translation>
<translation id="7514365320538308">डाउनलोड करा</translation>
+<translation id="7529102961911894712">मागील लिंक</translation>
+<translation id="7647456547678091388">टीप</translation>
+<translation id="7661956066982048809">ग्राफिक्स दस्तऐवज</translation>
<translation id="7673697353781729403">तास</translation>
+<translation id="7681220483256441252">अनुक्रमणिका</translation>
<translation id="7720026100085573005">शिल्लक वेळ</translation>
<translation id="7740016676195725605">बंद मथळा प्रदर्शित करणे थांबवा</translation>
<translation id="7740050170769002709">HTML सामुग्री</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">विभाजक</translation>
<translation id="795667975304826397">कोणतीही फाइल निवडलेली नाही</translation>
<translation id="8053789581856978548">मजकूर फील्ड दर्शवा</translation>
+<translation id="8057695513531652401">सूचना</translation>
+<translation id="8105797009065549151">टीप संदर्भ</translation>
<translation id="8115662671911883373">बंद मथळा प्रदर्शित करणे प्रारंभ करा</translation>
<translation id="8117451130807776954">या आठवड्यात</translation>
<translation id="819205353528511139">पूर्ण स्क्रीन मोडमध्ये चित्रपट प्ले करा</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">मथळे</translation>
<translation id="835897206747267392">अवैध मूल्य.</translation>
+<translation id="8415319359811155763">भाग</translation>
<translation id="8433900881053900389">टूलबार</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फायली</translation>
<translation id="8451268428117625855">कृपया एखादी फाइल निवडा.</translation>
<translation id="8461852803063341183">रेडिओ बटण</translation>
+<translation id="8474886197722836894">अर्पणपत्रिका</translation>
+<translation id="8531739829932800271">शुद्धिपत्रक</translation>
<translation id="8534579021159131403">मिनिटे</translation>
<translation id="8541249477527128034">माध्यम नियंत्रण</translation>
+<translation id="8550857728288566671">ग्राफिक्स चिन्ह</translation>
<translation id="8583702881314752957">परिभाषा सूची</translation>
<translation id="8597182159515967513">शीर्षलेख</translation>
+<translation id="860475260694818407">अनुक्रमणिका</translation>
<translation id="8613126697340063924">दूरस्थ प्लेबॅक नियंत्रित करा</translation>
+<translation id="862370744433916922">उपशीर्षक</translation>
<translation id="8741316211671074806">चित्रात-चित्र</translation>
<translation id="8750798805984357768">कृपया या पर्यायांपैकी एक निवडा.</translation>
<translation id="8785498733064193001">प्लेबॅक आरंभ करा</translation>
+<translation id="8808573423886751634">प्रकरण</translation>
<translation id="8845239796550121995">आता तुमच्या टिव्हीवर कास्ट करत आहे</translation>
<translation id="8851136666856101339">मुख्य</translation>
<translation id="8875657656876809964">व्हिडिओ प्लेबॅक एरर</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">अन्य...</translation>
<translation id="9138385573473225930">सूचना</translation>
<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> रोजी प्रारंभ होणारा, <ph name="WEEK" /></translation>
+<translation id="9168329111483466115">तळटीप</translation>
<translation id="947831847158436616">सेल</translation>
<translation id="966787709310836684">मेनू</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ms.xtb b/chromium/content/app/strings/translations/content_strings_ms.xtb
index 2ffcf8d1af9..2cad6383b2e 100644
--- a/chromium/content/app/strings/translations/content_strings_ms.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ms.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">pelengkap</translation>
<translation id="1206619573307042055">marki</translation>
<translation id="1206693055195146388">peluncur</translation>
+<translation id="1211441953136645838">nota hujung</translation>
<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">kredit</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">sepanduk</translation>
<translation id="1589122976691792535">wilayah</translation>
<translation id="1591562245178063882">Bulan ini</translation>
<translation id="1637811476055996098">Pilih Fail</translation>
+<translation id="1650423536718072820">petikan tarik keluar</translation>
<translation id="1729654308190250600">Sila masukkan alamat e-mel bukan kosong.</translation>
<translation id="1758486001363313524">Lain-lain...</translation>
<translation id="1806710327868736751">dialog_makluman</translation>
<translation id="1821985195704844674">grid pohon</translation>
<translation id="1822429046913737220">PG / P/M</translation>
<translation id="1832974991323546415">main pada peranti jauh</translation>
+<translation id="1907737156431278478">contoh</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Nilai mestilah <ph name="MAXIMUM_DATE_OR_TIME" /> atau lebih awal.</translation>
<translation id="1993104285338243655">Beralih kepada pencerminan</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' digunakan pada kedudukan yang salah dalam '<ph name="INVALIDDOMAIN" />'.</translation>
<translation id="2148716181193084225">Hari ini</translation>
+<translation id="2158401438286456825">senarai halaman</translation>
<translation id="2226276347425096477">Sila pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> aksara atau kurang (anda kini menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Lagu <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kotak pilihan</translation>
+<translation id="2311842470354187719">pemisah halaman</translation>
<translation id="2335594187091864976">pemilih tarikh dan masa</translation>
<translation id="248395913932153421">Hari</translation>
<translation id="2507943997699731163">Sila isikan medan ini.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">main</translation>
<translation id="2613802280814924224">Sila masukkan nilai yang sah. Nilai sah yang terdekat ialah <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Serah</translation>
+<translation id="2657045182931379222">objek grafik</translation>
<translation id="2674318244760992338">pembawah</translation>
<translation id="2709516037105925701">Autoisi</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Sila panjangkan teks ini kepada <ph name="MIN_CHARACTERS" /> aksara atau lebih (anda sedang menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
<translation id="383465348367842624">Bahagian yang diikuti oleh '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="3846214748874656680">Keluar dari skrin penuh</translation>
+<translation id="3920932319529768807">kesimpulan</translation>
<translation id="3924558731517983934">aplikasi</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">bar tatal</translation>
<translation id="4103419683916926126">Milisaat</translation>
<translation id="4151657705144244502">grafik</translation>
+<translation id="4193965531860883258">kata pengantar</translation>
<translation id="4201051445878709314">Tunjukkan bulan sebelumnya</translation>
<translation id="421884353938374759">pemilih warna</translation>
<translation id="4248100235867064564">bar menu</translation>
<translation id="4254339807215791271">maklumat kandungan</translation>
<translation id="4360991593054037559">Sila masukkan nilai yang sah. Dua nilai sah yang terdekat ialah <ph name="VALID_VALUE_LOW" /> dan <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Soal Jawab</translation>
<translation id="4413860115965805769">butang menu</translation>
+<translation id="4446524499724042288">rujukan glosari</translation>
<translation id="4522570452068850558">Butiran</translation>
<translation id="4597532268155981612">borang</translation>
<translation id="4661075872484491155">pohon</translation>
<translation id="4664250907885839816">Bahagian selepas '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">lampiran</translation>
+<translation id="4742539557769756338">muka depan</translation>
<translation id="4757246831282535685">panel tab</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Sila masukkan nombor.</translation>
+<translation id="4912536737030637138">masukan bibliografi</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> dipilih</translation>
<translation id="4992066212339426712">Nyahredam</translation>
<translation id="49969490063480558">Sila masukkan bahagian selepas '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
<translation id="5034860022980953847">penunjuk kemajuan</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Tunjukkan bulan seterusnya</translation>
<translation id="512758898067543763">pengepala baris</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Video ini dimainkan dalam Gambar dalam Gambar</translation>
<translation id="5164977714490026579">Nilai mesti lebih besar daripada atau sama dengan <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Sila masukkan bahagian diikuti oleh '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">nyahredam</translation>
<translation id="561939826962581046">masa</translation>
<translation id="5630795885300617244">Ketik dua kali ke kiri atau kanan untuk melangkau 10s</translation>
+<translation id="5631759159893697722">abstrak</translation>
<translation id="5641012560118721995">jeda main balik</translation>
<translation id="5643186887447432888">butang</translation>
<translation id="5677946354068040947">lagi pilihan</translation>
+<translation id="576709008726043716">pengenalan</translation>
<translation id="57838592816432529">Redam</translation>
<translation id="5860033963881614850">Dimatikan</translation>
<translation id="588258955323874662">Skrin penuh</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Tahun</translation>
<translation id="6023896073578205740">kotak senarai</translation>
<translation id="6101327004457443354">nyahredam runut audio</translation>
+<translation id="6150588977291308318">bibliografi</translation>
<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">kata hujungan</translation>
+<translation id="6213469881011901533">glosari</translation>
<translation id="6398862346408813489">Tunjukkan panel pilihan bulan</translation>
<translation id="6404546809543547843">pembersih masa audio</translation>
+<translation id="6453774872122745852">perakuan</translation>
<translation id="648732519525291180">pemilih masa</translation>
<translation id="6550675742724504774">Pilihan</translation>
-<translation id="6564313821541007458">Sekarang dalam mod Gambar dalam Gambar</translation>
<translation id="658823671542763450">memasuki skrin penuh</translation>
<translation id="663493177488814956">suapan</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">tip alat</translation>
<translation id="6790428901817661496">Mainkan</translation>
<translation id="6820355525329141109">Tidak dapat memuatkan pemalam.</translation>
+<translation id="6820615603175220800">rujukan bibliografi</translation>
<translation id="6843725295806269523">redam</translation>
<translation id="6853785296079745596">sembunyikan kapsyen tertutup</translation>
<translation id="6885760532393684712">direktori</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">petikan blok</translation>
<translation id="6941933287844615239">muat turun media</translation>
<translation id="6989848892321993519">Sila panjangkan teks ini kepada <ph name="MIN_CHARACTERS" /> aksara atau lebih (anda sedang menggunakan 1 aksara).</translation>
<translation id="709897737746224366">Sila padankan dengan format yang diminta.</translation>
+<translation id="7139483182332611405">kata penghantar</translation>
<translation id="7223624360433298498">masa berlalu</translation>
<translation id="7263440858009898357">Sila pilih item dalam senarai.</translation>
<translation id="727747134524199931">pengepala lajur</translation>
+<translation id="7353453495576941748">kredit</translation>
<translation id="7364796246159120393">Pilih Fail</translation>
<translation id="739024184232394898">Lain-lain...</translation>
+<translation id="7405738980073107433">nota hujung</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Muat Turun</translation>
+<translation id="7529102961911894712">pautan balik</translation>
+<translation id="7647456547678091388">petua</translation>
+<translation id="7661956066982048809">dokumen grafik</translation>
<translation id="7673697353781729403">Jam</translation>
+<translation id="7681220483256441252">indeks</translation>
<translation id="7720026100085573005">masa yang tinggal</translation>
<translation id="7740016676195725605">berhenti memaparkan kapsyen tertutup</translation>
<translation id="7740050170769002709">Kandungan HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">pemisah</translation>
<translation id="795667975304826397">Tiada fail dipilih</translation>
<translation id="8053789581856978548">medan teks carian</translation>
+<translation id="8057695513531652401">notis</translation>
+<translation id="8105797009065549151">rujukan nota</translation>
<translation id="8115662671911883373">mula memaparkan kapsyen tertutup</translation>
<translation id="8117451130807776954">Minggu ini</translation>
<translation id="819205353528511139">mainkan filem dalam mod skrin penuh</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Kapsyen</translation>
<translation id="835897206747267392">Nilai tidak sah.</translation>
+<translation id="8415319359811155763">bahagian</translation>
<translation id="8433900881053900389">bar alat</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fail</translation>
<translation id="8451268428117625855">Sila pilih fail.</translation>
<translation id="8461852803063341183">butang radio</translation>
+<translation id="8474886197722836894">dedikasi</translation>
+<translation id="8531739829932800271">ralat</translation>
<translation id="8534579021159131403">Minit</translation>
<translation id="8541249477527128034">kawalan media</translation>
+<translation id="8550857728288566671">simbol grafik</translation>
<translation id="8583702881314752957">senarai takrif</translation>
<translation id="8597182159515967513">tajuk</translation>
+<translation id="860475260694818407">isi kandungan</translation>
<translation id="8613126697340063924">kawal main balik jauh</translation>
+<translation id="862370744433916922">sari kata</translation>
<translation id="8741316211671074806">Gambar dalam Gambar</translation>
<translation id="8750798805984357768">Sila pilih salah satu pilihan ini.</translation>
<translation id="8785498733064193001">mulakan main balik</translation>
+<translation id="8808573423886751634">bab</translation>
<translation id="8845239796550121995">Menghantar ke TV anda sekarang</translation>
<translation id="8851136666856101339">utama</translation>
<translation id="8875657656876809964">Ralat main balik video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Lain-lain...</translation>
<translation id="9138385573473225930">makluman</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, bermula pada <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">nota kaki</translation>
<translation id="947831847158436616">sel</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_nl.xtb b/chromium/content/app/strings/translations/content_strings_nl.xtb
index 256f9a270a2..96d17a835dc 100644
--- a/chromium/content/app/strings/translations/content_strings_nl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_nl.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">aanvullend</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">schuifregelaar</translation>
+<translation id="1211441953136645838">eindnoot</translation>
<translation id="1281252709823657822">dialoogvenster</translation>
+<translation id="1335095011850992622">bronvermelding</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">regio</translation>
<translation id="1591562245178063882">Deze maand</translation>
<translation id="1637811476055996098">Bestanden kiezen</translation>
+<translation id="1650423536718072820">pullquote</translation>
<translation id="1729654308190250600">Geef een e-mailadres op.</translation>
<translation id="1758486001363313524">Anders...</translation>
<translation id="1806710327868736751">dialoogvenster voor meldingen</translation>
<translation id="1821985195704844674">boomstructuur</translation>
<translation id="1822429046913737220">a.m./p.m.</translation>
<translation id="1832974991323546415">afspelen op extern apparaat</translation>
+<translation id="1907737156431278478">voorbeeld</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Waarde moet <ph name="MAXIMUM_DATE_OR_TIME" /> of eerder zijn.</translation>
<translation id="1993104285338243655">Overgeschakeld naar mirroring</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' wordt op een verkeerde positie gebruikt in '<ph name="INVALIDDOMAIN" />'.</translation>
<translation id="2148716181193084225">Vandaag</translation>
+<translation id="2158401438286456825">paginalijst</translation>
<translation id="2226276347425096477">Kort deze tekst in tot <ph name="MAX_CHARACTERS" /> tekens of minder (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">selectievakje</translation>
+<translation id="2311842470354187719">pagina-einde</translation>
<translation id="2335594187091864976">datum- en tijdkiezer</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Vul dit veld in.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">afspelen</translation>
<translation id="2613802280814924224">Geef een geldige waarde op. De dichtstbijzijnde geldige waarde is <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Verzenden</translation>
+<translation id="2657045182931379222">grafisch object</translation>
<translation id="2674318244760992338">voettekst</translation>
<translation id="2709516037105925701">Automatisch aanvullen</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Breid deze tekst uit tot <ph name="MIN_CHARACTERS" /> tekens of meer (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
<translation id="383465348367842624">Het naamgedeelte vóór '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
<translation id="3846214748874656680">Volledig scherm sluiten</translation>
+<translation id="3920932319529768807">conclusie</translation>
<translation id="3924558731517983934">app</translation>
+<translation id="3944740393230681990">proloog</translation>
<translation id="3960700977367013758">scrollbar</translation>
<translation id="4103419683916926126">Milliseconden</translation>
<translation id="4151657705144244502">afbeelding</translation>
+<translation id="4193965531860883258">voorwoord</translation>
<translation id="4201051445878709314">Vorige maand weergeven</translation>
<translation id="421884353938374759">kleurkiezer</translation>
<translation id="4248100235867064564">menubalk</translation>
<translation id="4254339807215791271">informatie over content</translation>
<translation id="4360991593054037559">Geef een geldige waarde op. De twee dichtstbijzijnde geldige waarden zijn <ph name="VALID_VALUE_LOW" /> en <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
<translation id="4413860115965805769">menuknop</translation>
+<translation id="4446524499724042288">woordenlijstreferentie</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4597532268155981612">formulier</translation>
<translation id="4661075872484491155">structuur</translation>
<translation id="4664250907885839816">Het adresgedeelte na '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
+<translation id="4668956016107839909">bijlage</translation>
+<translation id="4742539557769756338">omslag</translation>
<translation id="4757246831282535685">deelvenster met tabblad</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">zoeken</translation>
<translation id="4812940957355064477">Voer een getal in.</translation>
+<translation id="4912536737030637138">bibliografievermelding</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> geselecteerd</translation>
<translation id="4992066212339426712">Dempen opheffen</translation>
<translation id="49969490063480558">Geef een adresgedeelte op na '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is onvolledig.</translation>
<translation id="5034860022980953847">voortgangsindicator</translation>
+<translation id="5093189678851173835">epigraaf</translation>
<translation id="5117590920725113268">Volgende maand weergeven</translation>
<translation id="512758898067543763">rijkop</translation>
+<translation id="5143125788380636750">epiloog</translation>
+<translation id="5153163864850940242">Deze video wordt in de scherm-in-scherm-modus afgespeeld</translation>
<translation id="5164977714490026579">Waarde moet groter dan of gelijk zijn aan <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Geef een naamgedeelte op, gevolgd door '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is onvolledig.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">dempen opheffen</translation>
<translation id="561939826962581046">tijd</translation>
<translation id="5630795885300617244">Dubbeltik links of rechts om 10 seconden over te slaan</translation>
+<translation id="5631759159893697722">uittreksel</translation>
<translation id="5641012560118721995">afspelen onderbreken</translation>
<translation id="5643186887447432888">knop</translation>
<translation id="5677946354068040947">meer opties</translation>
+<translation id="576709008726043716">inleiding</translation>
<translation id="57838592816432529">Dempen</translation>
<translation id="5860033963881614850">Uit</translation>
<translation id="588258955323874662">Volledig scherm</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Jaar</translation>
<translation id="6023896073578205740">keuzelijst</translation>
<translation id="6101327004457443354">dempen van audiotrack opheffen</translation>
+<translation id="6150588977291308318">bibliografie</translation>
<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">nawoord</translation>
+<translation id="6213469881011901533">woordenlijst</translation>
<translation id="6398862346408813489">Deelvenster voor maandselectie weergeven</translation>
<translation id="6404546809543547843">scrollbar met audiotijd</translation>
+<translation id="6453774872122745852">dankwoord</translation>
<translation id="648732519525291180">tijdkiezer</translation>
<translation id="6550675742724504774">Opties</translation>
-<translation id="6564313821541007458">Nu in scherm-in-scherm-modus</translation>
<translation id="658823671542763450">volledig scherm openen</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">logboek</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">knopinfo</translation>
<translation id="6790428901817661496">Spelen</translation>
<translation id="6820355525329141109">Kan plug-in niet laden.</translation>
+<translation id="6820615603175220800">bibliografiereferentie</translation>
<translation id="6843725295806269523">dempen</translation>
<translation id="6853785296079745596">ondertiteling verbergen</translation>
<translation id="6885760532393684712">directory</translation>
+<translation id="689129560213475294">colofon</translation>
<translation id="6934078000481955284">blok met geciteerde tekst</translation>
<translation id="6941933287844615239">media downloaden</translation>
<translation id="6989848892321993519">Breid deze tekst uit tot <ph name="MIN_CHARACTERS" /> tekens of meer (je gebruikt momenteel één teken).</translation>
<translation id="709897737746224366">Zorg dat de indeling voldoet aan de gevraagde indeling.</translation>
+<translation id="7139483182332611405">voorwoord</translation>
<translation id="7223624360433298498">verstreken tijd</translation>
<translation id="7263440858009898357">Selecteer een item in de lijst.</translation>
<translation id="727747134524199931">kolomkop</translation>
+<translation id="7353453495576941748">bronvermelding</translation>
<translation id="7364796246159120393">Bestand kiezen</translation>
<translation id="739024184232394898">Anders...</translation>
+<translation id="7405738980073107433">eindnoten</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Downloaden</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafisch document</translation>
<translation id="7673697353781729403">Uur</translation>
+<translation id="7681220483256441252">index</translation>
<translation id="7720026100085573005">resterende tijd</translation>
<translation id="7740016676195725605">het weergeven van ondertiteling stoppen</translation>
<translation id="7740050170769002709">HTML-content</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">splitser</translation>
<translation id="795667975304826397">Geen bestand gekozen</translation>
<translation id="8053789581856978548">zoektekstveld</translation>
+<translation id="8057695513531652401">kennisgeving</translation>
+<translation id="8105797009065549151">opmerkingsreferentie</translation>
<translation id="8115662671911883373">het weergeven van ondertiteling starten</translation>
<translation id="8117451130807776954">Deze week</translation>
<translation id="819205353528511139">film afspelen op volledig scherm</translation>
<translation id="8199524924445686405">jjjj</translation>
<translation id="8284326494547611709">Ondertiteling</translation>
<translation id="835897206747267392">Ongeldige waarde.</translation>
+<translation id="8415319359811155763">deel</translation>
<translation id="8433900881053900389">werkbalk</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> bestanden</translation>
<translation id="8451268428117625855">Selecteer een bestand.</translation>
<translation id="8461852803063341183">keuzerondje</translation>
+<translation id="8474886197722836894">opgedragen aan</translation>
+<translation id="8531739829932800271">drukfouten</translation>
<translation id="8534579021159131403">Minuten</translation>
<translation id="8541249477527128034">mediacontrole</translation>
+<translation id="8550857728288566671">grafisch symbool</translation>
<translation id="8583702881314752957">definitielijst</translation>
<translation id="8597182159515967513">kop</translation>
+<translation id="860475260694818407">inhoudsopgave</translation>
<translation id="8613126697340063924">afspelen bedienen op afstand</translation>
+<translation id="862370744433916922">ondertitel</translation>
<translation id="8741316211671074806">Scherm-in-scherm</translation>
<translation id="8750798805984357768">Selecteer een van deze opties.</translation>
<translation id="8785498733064193001">afspelen starten</translation>
+<translation id="8808573423886751634">hoofdstuk</translation>
<translation id="8845239796550121995">Wordt nu gecast naar je tv</translation>
<translation id="8851136666856101339">hoofd</translation>
<translation id="8875657656876809964">Fout bij afspelen video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Anders...</translation>
<translation id="9138385573473225930">melding</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, die begint op <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">voetnoot</translation>
<translation id="947831847158436616">cel</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_no.xtb b/chromium/content/app/strings/translations/content_strings_no.xtb
index 46de87f7862..b845d307239 100644
--- a/chromium/content/app/strings/translations/content_strings_no.xtb
+++ b/chromium/content/app/strings/translations/content_strings_no.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">komplementær</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">glidebryter</translation>
+<translation id="1211441953136645838">sluttnote</translation>
<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">anerkjennelser</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">område</translation>
<translation id="1591562245178063882">Denne måneden</translation>
<translation id="1637811476055996098">Velg filer</translation>
+<translation id="1650423536718072820">sitat</translation>
<translation id="1729654308190250600">Skriv inn en ikke-tom e-postadresse.</translation>
<translation id="1758486001363313524">Andre</translation>
<translation id="1806710327868736751">varseldialog</translation>
<translation id="1821985195704844674">trerutenett</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">spill på ekstern enhet</translation>
+<translation id="1907737156431278478">eksempel</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Verdien må være <ph name="MAXIMUM_DATE_OR_TIME" /> eller før.</translation>
<translation id="1993104285338243655">Byttet til speiling</translation>
<translation id="2060505056492490888">«<ph name="DOT" />» er brukt på feil sted i «<ph name="INVALIDDOMAIN" />».</translation>
<translation id="2148716181193084225">I dag</translation>
+<translation id="2158401438286456825">sideliste</translation>
<translation id="2226276347425096477">Forkort denne teksten til <ph name="MAX_CHARACTERS" /> tegn eller færre (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="2247351761944213033">Uke <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Spor <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">avmerkingsboks</translation>
+<translation id="2311842470354187719">sideskift</translation>
<translation id="2335594187091864976">dato- og klokkeslettvelger</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Vennligst fyll ut dette feltet.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">spill av</translation>
<translation id="2613802280814924224">Skriv inn en gyldig verdi. Den nærmeste, gyldige verdien er <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Send</translation>
+<translation id="2657045182931379222">grafikkobjekt</translation>
<translation id="2674318244760992338">fotnote</translation>
<translation id="2709516037105925701">Autofyll</translation>
<translation id="2723001399770238859">lyd</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Du må forlenge denne teksten til <ph name="MIN_CHARACTERS" /> tegn eller mer (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="383465348367842624">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
<translation id="3846214748874656680">Avslutt fullskjermmodus</translation>
+<translation id="3920932319529768807">konklusjon</translation>
<translation id="3924558731517983934">program</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">rullefelt</translation>
<translation id="4103419683916926126">Millisekunder</translation>
<translation id="4151657705144244502">grafikk</translation>
+<translation id="4193965531860883258">forord</translation>
<translation id="4201051445878709314">Se forrige måned</translation>
<translation id="421884353938374759">fargevelger</translation>
<translation id="4248100235867064564">menyrad</translation>
<translation id="4254339807215791271">innholdsinformasjon</translation>
<translation id="4360991593054037559">Skriv inn en gyldig verdi. De to nærmeste, gyldige verdiene er <ph name="VALID_VALUE_LOW" /> og <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Spørsmål og svar</translation>
<translation id="4413860115965805769">menyknapp</translation>
+<translation id="4446524499724042288">ordlistereferanse</translation>
<translation id="4522570452068850558">Detaljer</translation>
<translation id="4597532268155981612">skjema</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
+<translation id="4668956016107839909">vedlegg</translation>
+<translation id="4742539557769756338">omslag</translation>
<translation id="4757246831282535685">fanepanel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">søk</translation>
<translation id="4812940957355064477">Skriv inn et tall.</translation>
+<translation id="4912536737030637138">bibliografioppføring</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> er valgt</translation>
<translation id="4992066212339426712">Slå på lyden</translation>
<translation id="49969490063480558">Skriv inn en del etterfulgt av «<ph name="ATSIGN" />». «<ph name="INVALIDADDRESS" />» er ufullstendig.</translation>
<translation id="5034860022980953847">fremdriftsindikator</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Se neste måned</translation>
<translation id="512758898067543763">radoverskrift</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Denne videoen spilles av i bilde-i-bilde</translation>
<translation id="5164977714490026579">Verdien må være større enn eller lik <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Skriv inn en del etterfulgt av «<ph name="ATSIGN" />». «<ph name="INVALIDADDRESS" />» er ufullstendig.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">slå på lyden</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Dobbelttrykk på venstre eller høyre side for å hoppe 10 sekunder</translation>
+<translation id="5631759159893697722">abstrakt</translation>
<translation id="5641012560118721995">stopp avspillingen midlertidig</translation>
<translation id="5643186887447432888">knapp</translation>
<translation id="5677946354068040947">flere alternativer</translation>
+<translation id="576709008726043716">innledning</translation>
<translation id="57838592816432529">Kutt lyden</translation>
<translation id="5860033963881614850">Av</translation>
<translation id="588258955323874662">Fullskjerm</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">År</translation>
<translation id="6023896073578205740">listefelt</translation>
<translation id="6101327004457443354">slå på lydsporet</translation>
+<translation id="6150588977291308318">bibliografi</translation>
<translation id="6164829606128959761">måler</translation>
+<translation id="6166809985690652833">etterord</translation>
+<translation id="6213469881011901533">ordliste</translation>
<translation id="6398862346408813489">Se panelet for valg av måned</translation>
<translation id="6404546809543547843">lydtidslinje</translation>
+<translation id="6453774872122745852">omtale</translation>
<translation id="648732519525291180">klokkeslettvelger</translation>
<translation id="6550675742724504774">Alternativer</translation>
-<translation id="6564313821541007458">Nå i bilde-i-bilde-modus</translation>
<translation id="658823671542763450">gå til fullskjermmodus</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">logg</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">verktøytips</translation>
<translation id="6790428901817661496">Spill av</translation>
<translation id="6820355525329141109">Kunne ikke laste inn programtillegget.</translation>
+<translation id="6820615603175220800">bibliografireferanse</translation>
<translation id="6843725295806269523">kutt lyd</translation>
<translation id="6853785296079745596">skjul teksting</translation>
<translation id="6885760532393684712">katalog</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">blokksitat</translation>
<translation id="6941933287844615239">last ned medier</translation>
<translation id="6989848892321993519">Øk lengden på denne teksten med minst <ph name="MIN_CHARACTERS" /> tegn (du bruker for øyeblikket 1 tegn).</translation>
<translation id="709897737746224366">Sørg for samsvar med det forespurte formatet.</translation>
+<translation id="7139483182332611405">forord</translation>
<translation id="7223624360433298498">brukt tid</translation>
<translation id="7263440858009898357">Velg en artikkel i listen.</translation>
<translation id="727747134524199931">kolonneoverskrift</translation>
+<translation id="7353453495576941748">anerkjennelse</translation>
<translation id="7364796246159120393">Velg fil</translation>
<translation id="739024184232394898">Andre</translation>
+<translation id="7405738980073107433">sluttnoter</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Last ned</translation>
+<translation id="7529102961911894712">tilbakelink</translation>
+<translation id="7647456547678091388">tips</translation>
+<translation id="7661956066982048809">grafikkdokument</translation>
<translation id="7673697353781729403">Timer</translation>
+<translation id="7681220483256441252">stikkordregister</translation>
<translation id="7720026100085573005">tid som gjenstår</translation>
<translation id="7740016676195725605">slå av tekstingen</translation>
<translation id="7740050170769002709">HTML-innhold</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">vindusdeler</translation>
<translation id="795667975304826397">Ingen fil valgt</translation>
<translation id="8053789581856978548">søketekstfelt</translation>
+<translation id="8057695513531652401">merknad</translation>
+<translation id="8105797009065549151">kommentarreferanse</translation>
<translation id="8115662671911883373">slå på tekstingen</translation>
<translation id="8117451130807776954">Denne uken</translation>
<translation id="819205353528511139">spill av filmen i fullskjermmodus</translation>
<translation id="8199524924445686405">åååå</translation>
<translation id="8284326494547611709">Teksting</translation>
<translation id="835897206747267392">Ugyldig verdi</translation>
+<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">verktøyrad</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
<translation id="8451268428117625855">Velg en fil.</translation>
<translation id="8461852803063341183">alternativknapp</translation>
+<translation id="8474886197722836894">dedikasjon</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minutter</translation>
<translation id="8541249477527128034">mediekontroll</translation>
+<translation id="8550857728288566671">grafikksymbol</translation>
<translation id="8583702881314752957">definisjonsliste</translation>
<translation id="8597182159515967513">overskrift</translation>
+<translation id="860475260694818407">innholdsfortegnelse</translation>
<translation id="8613126697340063924">kontrollér ekstern avspilling</translation>
+<translation id="862370744433916922">undertittel</translation>
<translation id="8741316211671074806">Bilde-i-bilde</translation>
<translation id="8750798805984357768">Velg ett av følgende alternativer.</translation>
<translation id="8785498733064193001">start avspillingen</translation>
+<translation id="8808573423886751634">kapittel</translation>
<translation id="8845239796550121995">Caster til TV-en nå</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Feil ved videoavspilling</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Andre</translation>
<translation id="9138385573473225930">varsel</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, med start <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">fotnote</translation>
<translation id="947831847158436616">celle</translation>
<translation id="966787709310836684">meny</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pl.xtb b/chromium/content/app/strings/translations/content_strings_pl.xtb
index 20bcb1ef174..acac3373159 100644
--- a/chromium/content/app/strings/translations/content_strings_pl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pl.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">pomocniczy</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">suwak</translation>
+<translation id="1211441953136645838">przypis końcowy</translation>
<translation id="1281252709823657822">okno dialogowe</translation>
+<translation id="1335095011850992622">autorzy</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">baner</translation>
<translation id="1589122976691792535">region</translation>
<translation id="1591562245178063882">W tym miesiącu</translation>
<translation id="1637811476055996098">Wybierz pliki</translation>
+<translation id="1650423536718072820">cytat</translation>
<translation id="1729654308190250600">Podaj adres e-mail.</translation>
<translation id="1758486001363313524">Inny...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">siatka drzewa</translation>
<translation id="1822429046913737220">rano/po południu</translation>
<translation id="1832974991323546415">odtwarzanie na urządzeniu zdalnym</translation>
+<translation id="1907737156431278478">przykład</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stan</translation>
<translation id="1938124657309484470">Musisz podać wartość <ph name="MAXIMUM_DATE_OR_TIME" /> lub wcześniejszą.</translation>
<translation id="1993104285338243655">Przełączono na odbicie lustrzane</translation>
<translation id="2060505056492490888">„<ph name="DOT" />” występuje w niewłaściwym miejscu w „<ph name="INVALIDDOMAIN" />”.</translation>
<translation id="2148716181193084225">Dzisiaj</translation>
+<translation id="2158401438286456825">lista stron</translation>
<translation id="2226276347425096477">Skróć ten tekst do maksymalnie <ph name="MAX_CHARACTERS" /> znaków (w tej chwili korzystasz z <ph name="CURRENT_LENGTH" /> znaków).</translation>
<translation id="2247351761944213033">Tydzień <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Utwór <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">pole wyboru</translation>
+<translation id="2311842470354187719">podział strony</translation>
<translation id="2335594187091864976">selektor daty i godziny</translation>
<translation id="248395913932153421">Dzień</translation>
<translation id="2507943997699731163">Wypełnij to pole.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">odtwórz</translation>
<translation id="2613802280814924224">Podaj prawidłową wartość. Najbliższa prawidłowa wartość to <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Prześlij</translation>
+<translation id="2657045182931379222">obiekt graficzny</translation>
<translation id="2674318244760992338">stopka</translation>
<translation id="2709516037105925701">Autouzupełnianie</translation>
<translation id="2723001399770238859">dźwięk</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Wydłuż ten tekst przynajmniej do <ph name="MIN_CHARACTERS" /> znaków (teraz używasz <ph name="CURRENT_LENGTH" /> znaków).</translation>
<translation id="383465348367842624">Część przed znakiem „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
<translation id="3846214748874656680">Zamknij pełny ekran</translation>
+<translation id="3920932319529768807">podsumowanie</translation>
<translation id="3924558731517983934">aplikacja</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">pasek przewijania</translation>
<translation id="4103419683916926126">Milisekundy</translation>
<translation id="4151657705144244502">grafika</translation>
+<translation id="4193965531860883258">przedmowa</translation>
<translation id="4201051445878709314">Pokaż poprzedni miesiąc</translation>
<translation id="421884353938374759">selektor kolorów</translation>
<translation id="4248100235867064564">pasek menu</translation>
<translation id="4254339807215791271">informacje o zawartości</translation>
<translation id="4360991593054037559">Podaj prawidłową wartość. Dwie najbliższe prawidłowe wartości to <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Pytania i odpowiedzi</translation>
<translation id="4413860115965805769">przycisk menu</translation>
+<translation id="4446524499724042288">odniesienie do słownika</translation>
<translation id="4522570452068850558">Szczegóły</translation>
<translation id="4597532268155981612">formularz</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Część po znaku „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4668956016107839909">dodatek</translation>
+<translation id="4742539557769756338">okładka</translation>
<translation id="4757246831282535685">panel karty</translation>
<translation id="4763480195061959176">film</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Wpisz liczbę.</translation>
+<translation id="4912536737030637138">pozycja bibliograficzna</translation>
<translation id="4975562563186953947">Wybrano: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Wyłącz wyciszenie</translation>
<translation id="49969490063480558">Podaj część po znaku „<ph name="ATSIGN" />”. Adres „<ph name="INVALIDADDRESS" />” jest niepełny.</translation>
<translation id="5034860022980953847">wskaźnik postępu</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Pokaż przyszły miesiąc</translation>
<translation id="512758898067543763">nagłówek wiersza</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Ten film jest odtwarzany w trybie obrazu w obrazie</translation>
<translation id="5164977714490026579">Wartość nie może być mniejsza niż <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Podaj część przed znakiem „<ph name="ATSIGN" />”. Adres „<ph name="INVALIDADDRESS" />” jest niepełny.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">wyłącz wyciszenie</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Kliknij dwukrotnie z lewej lub prawej, by przewinąć o 10 s</translation>
+<translation id="5631759159893697722">streszczenie</translation>
<translation id="5641012560118721995">wstrzymaj odtwarzanie</translation>
<translation id="5643186887447432888">przycisk</translation>
<translation id="5677946354068040947">więcej opcji</translation>
+<translation id="576709008726043716">wprowadzenie</translation>
<translation id="57838592816432529">Wycisz</translation>
<translation id="5860033963881614850">Wyłączone</translation>
<translation id="588258955323874662">Pełny ekran</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Rok</translation>
<translation id="6023896073578205740">pole listy</translation>
<translation id="6101327004457443354">wyłącz wyciszenie ścieżki dźwiękowej</translation>
+<translation id="6150588977291308318">bibliografia</translation>
<translation id="6164829606128959761">miernik</translation>
+<translation id="6166809985690652833">posłowie</translation>
+<translation id="6213469881011901533">słownik</translation>
<translation id="6398862346408813489">Pokaż panel wyboru miesiąca</translation>
<translation id="6404546809543547843">pasek czasu odtwarzania dźwięku</translation>
+<translation id="6453774872122745852">podziękowania</translation>
<translation id="648732519525291180">selektor godziny</translation>
<translation id="6550675742724504774">Opcje</translation>
-<translation id="6564313821541007458">Teraz pracuję w trybie Obraz w obrazie</translation>
<translation id="658823671542763450">przejdź do pełnego ekranu</translation>
<translation id="663493177488814956">kanał</translation>
<translation id="6637586476836377253">dziennik</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">etykietka</translation>
<translation id="6790428901817661496">Odtwórz</translation>
<translation id="6820355525329141109">Nie można załadować wtyczki.</translation>
+<translation id="6820615603175220800">odniesienie bibliograficzne</translation>
<translation id="6843725295806269523">wyciszenie</translation>
<translation id="6853785296079745596">ukryj napisy</translation>
<translation id="6885760532393684712">katalog</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">cytat blokowy</translation>
<translation id="6941933287844615239">pobierz multimedia</translation>
<translation id="6989848892321993519">Wydłuż ten tekst co najmniej do <ph name="MIN_CHARACTERS" /> znaków (teraz używasz jednego znaku).</translation>
<translation id="709897737746224366">Podaj wartość w wymaganym formacie.</translation>
+<translation id="7139483182332611405">wstęp</translation>
<translation id="7223624360433298498">upłynęło czasu</translation>
<translation id="7263440858009898357">Wybierz element z listy.</translation>
<translation id="727747134524199931">nagłówek kolumny</translation>
+<translation id="7353453495576941748">twórcy</translation>
<translation id="7364796246159120393">Wybierz plik</translation>
<translation id="739024184232394898">Inny...</translation>
+<translation id="7405738980073107433">przypisy końcowe</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Pobierz</translation>
+<translation id="7529102961911894712">link zwrotny</translation>
+<translation id="7647456547678091388">Wskazówka</translation>
+<translation id="7661956066982048809">dokument graficzny</translation>
<translation id="7673697353781729403">Godziny</translation>
+<translation id="7681220483256441252">indeks</translation>
<translation id="7720026100085573005">pozostały czas</translation>
<translation id="7740016676195725605">przestań pokazywać napisy</translation>
<translation id="7740050170769002709">Treść HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">podział</translation>
<translation id="795667975304826397">Nie wybrano pliku</translation>
<translation id="8053789581856978548">pole tekstowe wyszukiwania</translation>
+<translation id="8057695513531652401">uwaga</translation>
+<translation id="8105797009065549151">odsyłacz</translation>
<translation id="8115662671911883373">zacznij pokazywać napisy</translation>
<translation id="8117451130807776954">W tym tygodniu</translation>
<translation id="819205353528511139">odtwórz film w trybie pełnoekranowym</translation>
<translation id="8199524924445686405">rrrr</translation>
<translation id="8284326494547611709">Napisy</translation>
<translation id="835897206747267392">Nieprawidłowa wartość.</translation>
+<translation id="8415319359811155763">część</translation>
<translation id="8433900881053900389">pasek narzędzi</translation>
<translation id="8444882422881193423">Liczba plików: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Wybierz plik.</translation>
<translation id="8461852803063341183">przycisk opcji</translation>
+<translation id="8474886197722836894">dedykacja</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minuty</translation>
<translation id="8541249477527128034">sterowanie multimediami</translation>
+<translation id="8550857728288566671">symbol graficzny</translation>
<translation id="8583702881314752957">lista definicji</translation>
<translation id="8597182159515967513">nagłówek</translation>
+<translation id="860475260694818407">spis treści</translation>
<translation id="8613126697340063924">sterowanie zdalnym odtwarzaniem</translation>
+<translation id="862370744433916922">podtytuł</translation>
<translation id="8741316211671074806">Obraz w obrazie</translation>
<translation id="8750798805984357768">Wybierz jedną z opcji.</translation>
<translation id="8785498733064193001">rozpocznij odtwarzanie</translation>
+<translation id="8808573423886751634">rozdział</translation>
<translation id="8845239796550121995">Przesyłam na telewizor</translation>
<translation id="8851136666856101339">główny</translation>
<translation id="8875657656876809964">Błąd odtwarzania filmu</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Inny...</translation>
<translation id="9138385573473225930">alert</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, początek <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">przypis</translation>
<translation id="947831847158436616">komórka</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
index 1da5a5819be..12943615149 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementar</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">controle deslizante</translation>
+<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">caixa de diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">região</translation>
<translation id="1591562245178063882">Este mês</translation>
<translation id="1637811476055996098">Escolher arquivos</translation>
+<translation id="1650423536718072820">citação</translation>
<translation id="1729654308190250600">Insira um endereço de e-mail que não esteja vazio.</translation>
<translation id="1758486001363313524">Outras...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">grade de árvore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">reproduzir em dispositivo remoto</translation>
+<translation id="1907737156431278478">exemplo</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">O valor deve ser <ph name="MAXIMUM_DATE_OR_TIME" /> ou anterior.</translation>
<translation id="1993104285338243655">Alterado para espelhamento</translation>
<translation id="2060505056492490888">"<ph name="DOT" />" está sendo usado em uma posição incorreta em "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Hoje</translation>
+<translation id="2158401438286456825">lista de páginas</translation>
<translation id="2226276347425096477">Reduza este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Faixa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">caixa de seleção</translation>
+<translation id="2311842470354187719">quebra de página</translation>
<translation id="2335594187091864976">seletor de data e hora</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Preencha este campo.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">reproduzir</translation>
<translation id="2613802280814924224">Insira um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Enviar</translation>
+<translation id="2657045182931379222">objeto gráfico</translation>
<translation id="2674318244760992338">rodapé</translation>
<translation id="2709516037105925701">Preenchimento automático</translation>
<translation id="2723001399770238859">áudio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> caracteres ou mais. No momento, você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="383465348367842624">Uma parte seguida por "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Sair da tela cheia</translation>
+<translation id="3920932319529768807">conclusão</translation>
<translation id="3924558731517983934">app</translation>
+<translation id="3944740393230681990">prólogo</translation>
<translation id="3960700977367013758">barra de rolagem</translation>
<translation id="4103419683916926126">Milésimos de segundo</translation>
<translation id="4151657705144244502">gráfico</translation>
+<translation id="4193965531860883258">prefácio</translation>
<translation id="4201051445878709314">Mostrar mês anterior</translation>
<translation id="421884353938374759">Seletor de cores</translation>
<translation id="4248100235867064564">barra de menu</translation>
<translation id="4254339807215791271">informações sobre o conteúdo</translation>
<translation id="4360991593054037559">Insira um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Perguntas e respostas</translation>
<translation id="4413860115965805769">botão de menu</translation>
+<translation id="4446524499724042288">referência de glossário</translation>
<translation id="4522570452068850558">Detalhes</translation>
<translation id="4597532268155981612">formulário</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A parte depois de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apêndice</translation>
+<translation id="4742539557769756338">capa</translation>
<translation id="4757246831282535685">painel da guia</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">pesquisar</translation>
<translation id="4812940957355064477">Insira um número.</translation>
+<translation id="4912536737030637138">entrada bibliográfica</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selecionados</translation>
<translation id="4992066212339426712">Ativar som</translation>
<translation id="49969490063480558">Insira uma parte depois de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
<translation id="5034860022980953847">indicador de progresso</translation>
+<translation id="5093189678851173835">epígrafe</translation>
<translation id="5117590920725113268">Mostrar próximo mês</translation>
<translation id="512758898067543763">cabeçalho de linha</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5153163864850940242">Este vídeo está sendo reproduzido em picture-in-picture</translation>
<translation id="5164977714490026579">O valor deve ser maior ou igual a <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Insira uma parte seguida por "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">ativar som</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Toque duas vezes na esquerda ou direita para pular 10 s</translation>
+<translation id="5631759159893697722">resumo</translation>
<translation id="5641012560118721995">pausar reprodução</translation>
<translation id="5643186887447432888">botão</translation>
<translation id="5677946354068040947">mais opções</translation>
+<translation id="576709008726043716">introdução</translation>
<translation id="57838592816432529">Desativar som</translation>
<translation id="5860033963881614850">Desativado</translation>
<translation id="588258955323874662">Tela inteira</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Ano</translation>
<translation id="6023896073578205740">caixa de listagem</translation>
<translation id="6101327004457443354">ativar som da faixa de áudio</translation>
+<translation id="6150588977291308318">bibliografia</translation>
<translation id="6164829606128959761">medidor</translation>
+<translation id="6166809985690652833">posfácio</translation>
+<translation id="6213469881011901533">glossário</translation>
<translation id="6398862346408813489">Mostrar painel de seleção de mês</translation>
<translation id="6404546809543547843">barra de progressão do áudio</translation>
+<translation id="6453774872122745852">agradecimentos</translation>
<translation id="648732519525291180">seletor de hora</translation>
<translation id="6550675742724504774">Opções</translation>
-<translation id="6564313821541007458">Agora no modo picture-in-picture</translation>
<translation id="658823671542763450">entrar no modo tela cheia</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">dica</translation>
<translation id="6790428901817661496">Reproduzir</translation>
<translation id="6820355525329141109">Não foi possível carregar o plug-in.</translation>
+<translation id="6820615603175220800">referência bibliográfica</translation>
<translation id="6843725295806269523">sem som</translation>
<translation id="6853785296079745596">ocultar legendas ocultas</translation>
<translation id="6885760532393684712">diretório</translation>
+<translation id="689129560213475294">colofão</translation>
<translation id="6934078000481955284">bloco de texto</translation>
<translation id="6941933287844615239">fazer o download da mídia</translation>
<translation id="6989848892321993519">Aumente esse texto para <ph name="MIN_CHARACTERS" /> caracteres ou mais. No momento, você está usando 1 caractere.</translation>
<translation id="709897737746224366">É preciso que o formato corresponda ao exigido.</translation>
+<translation id="7139483182332611405">prefácio</translation>
<translation id="7223624360433298498">tempo decorrido</translation>
<translation id="7263440858009898357">Selecione um item da lista.</translation>
<translation id="727747134524199931">cabeçalho da coluna</translation>
+<translation id="7353453495576941748">crédito</translation>
<translation id="7364796246159120393">Escolher arquivo</translation>
<translation id="739024184232394898">Outras...</translation>
+<translation id="7405738980073107433">notas finais</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Fazer o download</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7647456547678091388">dica</translation>
+<translation id="7661956066982048809">documento gráfico</translation>
<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
<translation id="7720026100085573005">tempo restante</translation>
<translation id="7740016676195725605">parar de exibir legendas ocultas</translation>
<translation id="7740050170769002709">Conteúdo HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">Nenhum arquivo selecionado</translation>
<translation id="8053789581856978548">campo de texto da pesquisa</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">referência de nota</translation>
<translation id="8115662671911883373">começar a exibir legendas ocultas</translation>
<translation id="8117451130807776954">Esta semana</translation>
<translation id="819205353528511139">reproduzir filme em tela cheia</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Legendas</translation>
<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de ferramentas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> arquivos</translation>
<translation id="8451268428117625855">Selecione um arquivo.</translation>
<translation id="8461852803063341183">botão de opção</translation>
+<translation id="8474886197722836894">dedicatória</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">controle de mídia</translation>
+<translation id="8550857728288566671">símbolo gráfico</translation>
<translation id="8583702881314752957">lista de definições</translation>
<translation id="8597182159515967513">cabeçalho</translation>
+<translation id="860475260694818407">sumário</translation>
<translation id="8613126697340063924">controlar reprodução remota</translation>
+<translation id="862370744433916922">subtítulo</translation>
<translation id="8741316211671074806">Picture-in-picture</translation>
<translation id="8750798805984357768">Selecione uma das opções.</translation>
<translation id="8785498733064193001">iniciar reprodução</translation>
+<translation id="8808573423886751634">capítulo</translation>
<translation id="8845239796550121995">Reproduzindo agora na sua TV</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Erro na reprodução do vídeo</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Outras...</translation>
<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, que começa em <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">nota de rodapé</translation>
<translation id="947831847158436616">célula</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
index 9b0712fc428..2c22789449d 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementar</translation>
<translation id="1206619573307042055">painel rolante</translation>
<translation id="1206693055195146388">controlo de deslize</translation>
+<translation id="1211441953136645838">nota final</translation>
<translation id="1281252709823657822">caixa de diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">região</translation>
<translation id="1591562245178063882">Este mês</translation>
<translation id="1637811476055996098">Escolher Ficheiros</translation>
+<translation id="1650423536718072820">trecho em destaque</translation>
<translation id="1729654308190250600">Introduza um endereço de email que não esteja vazio.</translation>
<translation id="1758486001363313524">Outra...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">grelha de árvore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">reproduzir no dispositivo remoto</translation>
+<translation id="1907737156431278478">exemplo</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estado</translation>
<translation id="1938124657309484470">O valor tem de ser <ph name="MAXIMUM_DATE_OR_TIME" /> ou anterior.</translation>
<translation id="1993104285338243655">Alterado para espelhamento.</translation>
<translation id="2060505056492490888">"<ph name="DOT" />" está a ser utilizado numa posição errada em "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Hoje</translation>
+<translation id="2158401438286456825">lista de páginas</translation>
<translation id="2226276347425096477">Encurte este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, de <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Faixa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">caixa de verificação</translation>
+<translation id="2311842470354187719">quebra de página</translation>
<translation id="2335594187091864976">selecionador de data e hora</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Preencha este campo.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">reproduzir</translation>
<translation id="2613802280814924224">Introduza um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Submeter</translation>
+<translation id="2657045182931379222">objeto de gráficos</translation>
<translation id="2674318244760992338">rodapé</translation>
<translation id="2709516037105925701">Preenchimento automático</translation>
<translation id="2723001399770238859">áudio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> carateres ou mais (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> carateres).</translation>
<translation id="383465348367842624">Uma parte seguida de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Sair do modo de ecrã inteiro</translation>
+<translation id="3920932319529768807">conclusão</translation>
<translation id="3924558731517983934">aplicação</translation>
+<translation id="3944740393230681990">prólogo</translation>
<translation id="3960700977367013758">barra de deslocamento</translation>
<translation id="4103419683916926126">Milissegundos</translation>
<translation id="4151657705144244502">gráfico</translation>
+<translation id="4193965531860883258">prefácio</translation>
<translation id="4201051445878709314">Mostrar mês anterior</translation>
<translation id="421884353938374759">seletor de cores</translation>
<translation id="4248100235867064564">barra de menu</translation>
<translation id="4254339807215791271">informações do conteúdo</translation>
<translation id="4360991593054037559">Introduza um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Perg e Resp</translation>
<translation id="4413860115965805769">botão de menu</translation>
+<translation id="4446524499724042288">referência do glossário</translation>
<translation id="4522570452068850558">Detalhes</translation>
<translation id="4597532268155981612">formulário</translation>
<translation id="4661075872484491155">árvore</translation>
<translation id="4664250907885839816">Uma parte a seguir a "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apêndice</translation>
+<translation id="4742539557769756338">capa</translation>
<translation id="4757246831282535685">painel de separadores</translation>
<translation id="4763480195061959176">vídeo</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Introduza um número.</translation>
+<translation id="4912536737030637138">entrada da bibliografia</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selecionados</translation>
<translation id="4992066212339426712">Reativar o som</translation>
<translation id="49969490063480558">Introduza uma parte a seguir a "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
<translation id="5034860022980953847">indicador de progresso</translation>
+<translation id="5093189678851173835">epígrafe</translation>
<translation id="5117590920725113268">Mostrar mês seguinte</translation>
<translation id="512758898067543763">cabeçalho da linha</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5153163864850940242">Este vídeo está a ser reproduzido no modo ecrã no ecrã</translation>
<translation id="5164977714490026579">O valor tem de ser superior ou igual a <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Introduza uma parte seguida de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">reativar som</translation>
<translation id="561939826962581046">hora</translation>
<translation id="5630795885300617244">Toque duas vezes à esquerda ou à direita para avançar 10 seg.</translation>
+<translation id="5631759159893697722">resumo</translation>
<translation id="5641012560118721995">interromper a reprodução</translation>
<translation id="5643186887447432888">botão</translation>
<translation id="5677946354068040947">mais opções</translation>
+<translation id="576709008726043716">introdução</translation>
<translation id="57838592816432529">Desativar som</translation>
<translation id="5860033963881614850">Desativado</translation>
<translation id="588258955323874662">Ecrã inteiro</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Ano</translation>
<translation id="6023896073578205740">caixa de lista</translation>
<translation id="6101327004457443354">reativar a faixa de áudio</translation>
+<translation id="6150588977291308318">bibliografia</translation>
<translation id="6164829606128959761">contador</translation>
+<translation id="6166809985690652833">posfácio</translation>
+<translation id="6213469881011901533">glossário</translation>
<translation id="6398862346408813489">Mostrar painel de seleção do mês</translation>
<translation id="6404546809543547843">controlo de arrasto do tempo do áudio</translation>
+<translation id="6453774872122745852">agradecimentos</translation>
<translation id="648732519525291180">selecionador de hora</translation>
<translation id="6550675742724504774">Opções</translation>
-<translation id="6564313821541007458">Agora no modo ecrã no ecrã</translation>
<translation id="658823671542763450">entrar no modo de ecrã inteiro</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">sugestão</translation>
<translation id="6790428901817661496">Reproduzir</translation>
<translation id="6820355525329141109">Não foi possível carregar o plug-in.</translation>
+<translation id="6820615603175220800">referência bibliográfica</translation>
<translation id="6843725295806269523">desativar som</translation>
<translation id="6853785296079745596">esconder legendas ocultas</translation>
<translation id="6885760532393684712">diretório</translation>
+<translation id="689129560213475294">colofão</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">transferir multimédia</translation>
<translation id="6989848892321993519">Aumente este texto para <ph name="MIN_CHARACTERS" /> ou mais carateres (atualmente, está a utilizar 1 caráter).</translation>
<translation id="709897737746224366">Faça corresponder o formato pedido.</translation>
-<translation id="7223624360433298498">tempo decorrido</translation>
+<translation id="7139483182332611405">prefácio</translation>
+<translation id="7223624360433298498">timelapse</translation>
<translation id="7263440858009898357">Seleccione um item na lista.</translation>
<translation id="727747134524199931">cabeçalho da coluna</translation>
+<translation id="7353453495576941748">crédito</translation>
<translation id="7364796246159120393">Escolher ficheiro</translation>
<translation id="739024184232394898">Outra...</translation>
+<translation id="7405738980073107433">notas finais</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Transferir</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7647456547678091388">sugestão</translation>
+<translation id="7661956066982048809">documento de gráficos</translation>
<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
<translation id="7720026100085573005">tempo restante</translation>
<translation id="7740016676195725605">parar de apresentar legendas ocultas</translation>
<translation id="7740050170769002709">Conteúdo HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">Nenhum ficheiro selecionado</translation>
<translation id="8053789581856978548">campo de texto de pesquisa</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">referência de nota</translation>
<translation id="8115662671911883373">apresentar legendas ocultas</translation>
<translation id="8117451130807776954">Esta semana</translation>
<translation id="819205353528511139">reproduzir o filme no modo de ecrã inteiro</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Legendas</translation>
<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de ferramentas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ficheiros</translation>
<translation id="8451268428117625855">Seleccione um ficheiro.</translation>
<translation id="8461852803063341183">botão de opção</translation>
+<translation id="8474886197722836894">dedicatória</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">controlo multimédia</translation>
+<translation id="8550857728288566671">símbolo de gráficos</translation>
<translation id="8583702881314752957">lista de definições</translation>
<translation id="8597182159515967513">cabeçalho</translation>
+<translation id="860475260694818407">índice</translation>
<translation id="8613126697340063924">controlar a reprodução remota</translation>
+<translation id="862370744433916922">legenda</translation>
<translation id="8741316211671074806">Ecrã no ecrã</translation>
<translation id="8750798805984357768">Seleccione uma destas opções.</translation>
<translation id="8785498733064193001">iniciar reprodução</translation>
+<translation id="8808573423886751634">capítulo</translation>
<translation id="8845239796550121995">A transmitir na sua TV…</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Erro de reprodução de vídeo.</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Outra...</translation>
<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir de <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">nota de rodapé</translation>
<translation id="947831847158436616">célula</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ro.xtb b/chromium/content/app/strings/translations/content_strings_ro.xtb
index 59eedb6271a..4a14856b246 100644
--- a/chromium/content/app/strings/translations/content_strings_ro.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ro.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">complementar</translation>
<translation id="1206619573307042055">text derulant</translation>
<translation id="1206693055195146388">glisor</translation>
+<translation id="1211441953136645838">notă de final</translation>
<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">mulțumiri</translation>
<translation id="1342835525016946179">articol</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">regiune</translation>
<translation id="1591562245178063882">Luna aceasta</translation>
<translation id="1637811476055996098">Alege fișierele</translation>
+<translation id="1650423536718072820">citat</translation>
<translation id="1729654308190250600">Introduceți o adresă de e-mail concretă.</translation>
<translation id="1758486001363313524">Altele...</translation>
<translation id="1806710327868736751">dialog de alertă</translation>
<translation id="1821985195704844674">grilă arbore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">redă pe dispozitiv la distanță</translation>
+<translation id="1907737156431278478">exemplu</translation>
<translation id="1921819250265091946">zz</translation>
<translation id="1930711995431081526">stare</translation>
<translation id="1938124657309484470">Valoarea pentru dată/oră trebuie să fie <ph name="MAXIMUM_DATE_OR_TIME" /> sau una anterioară.</translation>
<translation id="1993104285338243655">S-a comutat la oglindire</translation>
<translation id="2060505056492490888">Semnul „<ph name="DOT" />” apare poziționat greșit în „<ph name="INVALIDDOMAIN" />”.</translation>
<translation id="2148716181193084225">Astăzi</translation>
+<translation id="2158401438286456825">listă de pagini</translation>
<translation id="2226276347425096477">Micșorează acest text la cel mult <ph name="MAX_CHARACTERS" /> caractere (în prezent utilizezi <ph name="CURRENT_LENGTH" /> caractere).</translation>
<translation id="2247351761944213033">Săptămâna <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Melodia <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">casetă de selectare</translation>
+<translation id="2311842470354187719">sfârșit de pagină</translation>
<translation id="2335594187091864976">selector pentru dată și oră</translation>
<translation id="248395913932153421">Zi</translation>
<translation id="2507943997699731163">Completează acest câmp.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">redați</translation>
<translation id="2613802280814924224">Introduceți o valoare validă. Cea mai apropiată valoare validă este <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Trimite</translation>
+<translation id="2657045182931379222">obiect grafic</translation>
<translation id="2674318244760992338">notă de subsol</translation>
<translation id="2709516037105925701">Completare automată</translation>
<translation id="2723001399770238859">audio</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Mărește acest text la cel puțin <ph name="MIN_CHARACTERS" /> caractere (în prezent folosești <ph name="CURRENT_LENGTH" /> caractere).</translation>
<translation id="383465348367842624">Valoarea urmată de semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
<translation id="3846214748874656680">Ieși din ecranul complet</translation>
+<translation id="3920932319529768807">concluzie</translation>
<translation id="3924558731517983934">aplicație</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">bară de derulare</translation>
<translation id="4103419683916926126">Milisecunde</translation>
<translation id="4151657705144244502">element grafic</translation>
+<translation id="4193965531860883258">cuvânt înainte</translation>
<translation id="4201051445878709314">Afișează luna anterioară</translation>
<translation id="421884353938374759">selector de culoare</translation>
<translation id="4248100235867064564">bară de meniu</translation>
<translation id="4254339807215791271">informații privind conținutul</translation>
<translation id="4360991593054037559">Introduceți o valoare validă. Cele mai apropiate valori valide sunt <ph name="VALID_VALUE_LOW" /> și <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Întrebări și răspunsuri</translation>
<translation id="4413860115965805769">buton de meniu</translation>
+<translation id="4446524499724042288">trimitere la glosar</translation>
<translation id="4522570452068850558">Detalii</translation>
<translation id="4597532268155981612">formular</translation>
<translation id="4661075872484491155">arbore</translation>
<translation id="4664250907885839816">Valoarea care urmează după semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4668956016107839909">anexă</translation>
+<translation id="4742539557769756338">copertă</translation>
<translation id="4757246831282535685">panou de file</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">căutați</translation>
<translation id="4812940957355064477">Introduceți un număr.</translation>
+<translation id="4912536737030637138">intrare bibliografică</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selectate</translation>
<translation id="4992066212339426712">Activează sunetul</translation>
<translation id="49969490063480558">Introduceți o valoare după semnul „<ph name="ATSIGN" />”. Adresa „<ph name="INVALIDADDRESS" />” nu este completă.</translation>
<translation id="5034860022980953847">indicator de progres</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Afișează luna următoare</translation>
<translation id="512758898067543763">antet rând</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Videoclipul se redă în modul imagine în imagine</translation>
<translation id="5164977714490026579">Valoarea trebuie să fie mai mare sau egală cu <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Introduceți o valoare urmată de semnul „<ph name="ATSIGN" />”. Adresa „<ph name="INVALIDADDRESS" />” nu este completă.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">activați sunetul</translation>
<translation id="561939826962581046">oră</translation>
<translation id="5630795885300617244">Atinge de două ori spre stânga sau spre dreapta pentru a derula cu 10 secunde</translation>
+<translation id="5631759159893697722">rezumat</translation>
<translation id="5641012560118721995">întrerupeți redarea</translation>
<translation id="5643186887447432888">buton</translation>
<translation id="5677946354068040947">mai multe opțiuni</translation>
+<translation id="576709008726043716">introducere</translation>
<translation id="57838592816432529">Dezactivează sunetul</translation>
<translation id="5860033963881614850">Dezactivat</translation>
<translation id="588258955323874662">Ecran complet</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">An</translation>
<translation id="6023896073578205740">casetă listă</translation>
<translation id="6101327004457443354">activați sunetul înregistrării audio</translation>
+<translation id="6150588977291308318">bibliografie</translation>
<translation id="6164829606128959761">instrument de măsurare</translation>
+<translation id="6166809985690652833">postfață</translation>
+<translation id="6213469881011901533">glosar</translation>
<translation id="6398862346408813489">Afișează panoul de selectare a lunii</translation>
<translation id="6404546809543547843">glisor redare audio</translation>
+<translation id="6453774872122745852">lista colaboratorilor</translation>
<translation id="648732519525291180">selector oră</translation>
<translation id="6550675742724504774">Opțiuni</translation>
-<translation id="6564313821541007458">Ești acum în modul picture-in-picture</translation>
<translation id="658823671542763450">deschideți în ecran complet</translation>
<translation id="663493177488814956">feed</translation>
<translation id="6637586476836377253">jurnal</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">balon explicativ</translation>
<translation id="6790428901817661496">Redă</translation>
<translation id="6820355525329141109">Nu s-a putut încărca pluginul.</translation>
+<translation id="6820615603175220800">referință bibliografică</translation>
<translation id="6843725295806269523">dezactivați sunetul</translation>
<translation id="6853785296079745596">ascundeți subtitrările</translation>
<translation id="6885760532393684712">director</translation>
+<translation id="689129560213475294">colofon</translation>
<translation id="6934078000481955284">blockquote</translation>
<translation id="6941933287844615239">descarcă conținut media</translation>
<translation id="6989848892321993519">Mărește acest text la cel puțin <ph name="MIN_CHARACTERS" /> caractere (în prezent folosești 1 caracter).</translation>
<translation id="709897737746224366">Respectă formatul solicitat.</translation>
+<translation id="7139483182332611405">prefață</translation>
<translation id="7223624360433298498">timp scurs</translation>
<translation id="7263440858009898357">Selectează un articol din listă.</translation>
<translation id="727747134524199931">antet coloană</translation>
+<translation id="7353453495576941748">mulțumire</translation>
<translation id="7364796246159120393">Alege fișierul</translation>
<translation id="739024184232394898">Altele...</translation>
+<translation id="7405738980073107433">note de final</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">filă</translation>
<translation id="7514365320538308">Descarcă</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7647456547678091388">sfat</translation>
+<translation id="7661956066982048809">document grafic</translation>
<translation id="7673697353781729403">Ore</translation>
+<translation id="7681220483256441252">index</translation>
<translation id="7720026100085573005">timp rămas</translation>
<translation id="7740016676195725605">nu mai afișați subtitrările</translation>
<translation id="7740050170769002709">Conținut HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">element de divizare</translation>
<translation id="795667975304826397">Nu ai ales niciun fișier</translation>
<translation id="8053789581856978548">câmp pentru căutarea textului</translation>
+<translation id="8057695513531652401">anunț</translation>
+<translation id="8105797009065549151">trimitere la notă</translation>
<translation id="8115662671911883373">începeți să afișați subtitrările</translation>
<translation id="8117451130807776954">Săptămâna aceasta</translation>
<translation id="819205353528511139">redați filmul în modul ecran complet</translation>
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtitrări</translation>
<translation id="835897206747267392">Valoare nevalidă.</translation>
+<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">bară de instrumente</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fișiere</translation>
<translation id="8451268428117625855">Selectează un fișier.</translation>
<translation id="8461852803063341183">buton radio</translation>
+<translation id="8474886197722836894">dedicație</translation>
+<translation id="8531739829932800271">erată</translation>
<translation id="8534579021159131403">Minute</translation>
<translation id="8541249477527128034">comandă media</translation>
+<translation id="8550857728288566671">simbol grafic</translation>
<translation id="8583702881314752957">listă de definiții</translation>
<translation id="8597182159515967513">antet</translation>
+<translation id="860475260694818407">cuprins</translation>
<translation id="8613126697340063924">controlează redarea la distanță</translation>
+<translation id="862370744433916922">subtitlu</translation>
<translation id="8741316211671074806">Picture-in-Picture</translation>
<translation id="8750798805984357768">Selectează una dintre aceste opțiuni.</translation>
<translation id="8785498733064193001">începeți redarea</translation>
+<translation id="8808573423886751634">capitol</translation>
<translation id="8845239796550121995">Acum se proiectează pe televizor</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8875657656876809964">Eroare de redare video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Altele...</translation>
<translation id="9138385573473225930">alertă</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, începând de pe <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">notă de subsol</translation>
<translation id="947831847158436616">celulă</translation>
<translation id="966787709310836684">meniu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ru.xtb b/chromium/content/app/strings/translations/content_strings_ru.xtb
index 4638df24a13..c1ba6cbaaf8 100644
--- a/chromium/content/app/strings/translations/content_strings_ru.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ru.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">дополнительно</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">ползунок</translation>
+<translation id="1211441953136645838">концевая сноска</translation>
<translation id="1281252709823657822">диалоговое окно</translation>
+<translation id="1335095011850992622">выходные сведения</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">баннер</translation>
<translation id="1589122976691792535">регион</translation>
<translation id="1591562245178063882">В этом месяце</translation>
<translation id="1637811476055996098">Выбрать файлы</translation>
+<translation id="1650423536718072820">цитата в виде врезки</translation>
<translation id="1729654308190250600">Введите адрес электронной почты.</translation>
<translation id="1758486001363313524">Другое…</translation>
<translation id="1806710327868736751">диалоговое окно оповещения</translation>
<translation id="1821985195704844674">сетка в виде дерева</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">воспроизвести на удаленном устройстве</translation>
+<translation id="1907737156431278478">пример</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">статус</translation>
<translation id="1938124657309484470">Максимальное значение должно быть <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
<translation id="1993104285338243655">Включено дублирование экрана</translation>
<translation id="2060505056492490888">Недопустимое положение символа "<ph name="DOT" />" в адресе "<ph name="INVALIDDOMAIN" />".</translation>
<translation id="2148716181193084225">Сегодня</translation>
+<translation id="2158401438286456825">список страниц</translation>
<translation id="2226276347425096477">Длина текста не должна превышать <ph name="MAX_CHARACTERS" /> симв. (сейчас <ph name="CURRENT_LENGTH" /> симв.).</translation>
<translation id="2247351761944213033">Неделя <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Трек <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">флажок</translation>
+<translation id="2311842470354187719">разрыв страницы</translation>
<translation id="2335594187091864976">окно выбора даты и времени</translation>
<translation id="248395913932153421">День</translation>
<translation id="2507943997699731163">Заполните это поле.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">воспроизведение</translation>
<translation id="2613802280814924224">Введите допустимое значение. Ближайшее допустимое значение: <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Отправить</translation>
+<translation id="2657045182931379222">графический объект</translation>
<translation id="2674318244760992338">нижний колонтитул</translation>
<translation id="2709516037105925701">Автозаполнение</translation>
<translation id="2723001399770238859">аудио</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Минимально допустимое количество символов: <ph name="MIN_CHARACTERS" />. Длина текста сейчас: <ph name="CURRENT_LENGTH" />.</translation>
<translation id="383465348367842624">Часть адреса до символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Обычный режим</translation>
+<translation id="3920932319529768807">заключение</translation>
<translation id="3924558731517983934">приложение</translation>
+<translation id="3944740393230681990">пролог</translation>
<translation id="3960700977367013758">полоса прокрутки</translation>
<translation id="4103419683916926126">Миллисекунды</translation>
<translation id="4151657705144244502">изображение</translation>
+<translation id="4193965531860883258">предисловие</translation>
<translation id="4201051445878709314">Показать предыдущий месяц</translation>
<translation id="421884353938374759">color picker</translation>
<translation id="4248100235867064564">панель меню</translation>
<translation id="4254339807215791271">сведения о контенте</translation>
<translation id="4360991593054037559">Введите допустимое значение. Ближайшие допустимые значения: <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Вопросы и ответы</translation>
<translation id="4413860115965805769">кнопка меню</translation>
+<translation id="4446524499724042288">ссылка на словарную статью</translation>
<translation id="4522570452068850558">Подробнее</translation>
<translation id="4597532268155981612">форма</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Часть адреса после символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">приложение</translation>
+<translation id="4742539557769756338">обложка</translation>
<translation id="4757246831282535685">панель вкладок</translation>
<translation id="4763480195061959176">видео</translation>
<translation id="479989351350248267">поиск</translation>
<translation id="4812940957355064477">Введите число.</translation>
+<translation id="4912536737030637138">запись в библиографии</translation>
<translation id="4975562563186953947">Выбрано: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Включить звук</translation>
<translation id="49969490063480558">Введите часть адреса после символа "<ph name="ATSIGN" />". Адрес "<ph name="INVALIDADDRESS" />" неполный.</translation>
<translation id="5034860022980953847">индикатор хода выполнения</translation>
+<translation id="5093189678851173835">эпиграф</translation>
<translation id="5117590920725113268">Показать следующий месяц</translation>
<translation id="512758898067543763">заголовок строки</translation>
+<translation id="5143125788380636750">эпилог</translation>
+<translation id="5153163864850940242">Видео воспроизводится в режиме "Картинка в картинке"</translation>
<translation id="5164977714490026579">Значение должно быть больше или равно <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> ПБ</translation>
<translation id="5307600278924710095">Введите часть адреса до символа "<ph name="ATSIGN" />". Адрес "<ph name="INVALIDADDRESS" />" неполный.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">включение звука</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">Чтобы пропустить 10 секунд, нажмите дважды слева или справа.</translation>
+<translation id="5631759159893697722">аннотация</translation>
<translation id="5641012560118721995">пауза</translation>
<translation id="5643186887447432888">кнопка</translation>
<translation id="5677946354068040947">дополнительные параметры</translation>
+<translation id="576709008726043716">введение</translation>
<translation id="57838592816432529">Отключить звук</translation>
<translation id="5860033963881614850">Выкл.</translation>
<translation id="588258955323874662">Полноэкранный режим</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Год</translation>
<translation id="6023896073578205740">список</translation>
<translation id="6101327004457443354">включение звуковой дорожки</translation>
+<translation id="6150588977291308318">библиография</translation>
<translation id="6164829606128959761">счетчик</translation>
+<translation id="6166809985690652833">послесловие</translation>
+<translation id="6213469881011901533">словарь</translation>
<translation id="6398862346408813489">Показать панель выбора месяца</translation>
<translation id="6404546809543547843">полоса воспроизведения</translation>
+<translation id="6453774872122745852">благодарности</translation>
<translation id="648732519525291180">окно выбора даты</translation>
<translation id="6550675742724504774">Параметры</translation>
-<translation id="6564313821541007458">В режиме "Картинка в картинке"</translation>
<translation id="658823671542763450">полноэкранный режим</translation>
<translation id="663493177488814956">лента</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">подсказка</translation>
<translation id="6790428901817661496">Воспроизвести</translation>
<translation id="6820355525329141109">Не удалось загрузить плагин</translation>
+<translation id="6820615603175220800">ссылка на библиографию</translation>
<translation id="6843725295806269523">отключить звук</translation>
<translation id="6853785296079745596">скрыть субтитры</translation>
<translation id="6885760532393684712">каталог</translation>
+<translation id="689129560213475294">выпускные данные</translation>
<translation id="6934078000481955284">цитата</translation>
<translation id="6941933287844615239">скачать файл</translation>
<translation id="6989848892321993519">Текст должен быть не короче <ph name="MIN_CHARACTERS" /> симв. Длина текста сейчас: 1 символ.</translation>
<translation id="709897737746224366">Введите данные в указанном формате.</translation>
+<translation id="7139483182332611405">вступление</translation>
<translation id="7223624360433298498">прошедшее время</translation>
<translation id="7263440858009898357">Выберите один из пунктов списка.</translation>
<translation id="727747134524199931">заголовок столбца</translation>
+<translation id="7353453495576941748">упоминание</translation>
<translation id="7364796246159120393">Выберите файл</translation>
<translation id="739024184232394898">Другое…</translation>
+<translation id="7405738980073107433">концевые сноски</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> ТБ</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Скачать</translation>
+<translation id="7529102961911894712">обратная ссылка</translation>
+<translation id="7647456547678091388">совет</translation>
+<translation id="7661956066982048809">графический документ</translation>
<translation id="7673697353781729403">Часы</translation>
+<translation id="7681220483256441252">указатель</translation>
<translation id="7720026100085573005">оставшееся время</translation>
<translation id="7740016676195725605">скрыть субтитры</translation>
<translation id="7740050170769002709">HTML-содержание</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">разделитель</translation>
<translation id="795667975304826397">Файл не выбран</translation>
<translation id="8053789581856978548">поле поиска</translation>
+<translation id="8057695513531652401">примечание</translation>
+<translation id="8105797009065549151">ссылка на примечание</translation>
<translation id="8115662671911883373">показать субтитры</translation>
<translation id="8117451130807776954">На этой неделе</translation>
<translation id="819205353528511139">воспроизведение в полноэкранном режиме</translation>
<translation id="8199524924445686405">гггг</translation>
<translation id="8284326494547611709">Титры</translation>
<translation id="835897206747267392">Недопустимые данные.</translation>
+<translation id="8415319359811155763">часть</translation>
<translation id="8433900881053900389">панель инструментов</translation>
<translation id="8444882422881193423">Число файлов: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Выберите файл.</translation>
<translation id="8461852803063341183">переключатель</translation>
+<translation id="8474886197722836894">посвящение</translation>
+<translation id="8531739829932800271">список опечаток</translation>
<translation id="8534579021159131403">Минуты</translation>
<translation id="8541249477527128034">управление мультимедиа</translation>
+<translation id="8550857728288566671">графический символ</translation>
<translation id="8583702881314752957">список описаний</translation>
<translation id="8597182159515967513">заголовок</translation>
+<translation id="860475260694818407">оглавление</translation>
<translation id="8613126697340063924">управлять воспроизведением на удаленных устройствах</translation>
+<translation id="862370744433916922">подзаголовок</translation>
<translation id="8741316211671074806">Картинка в картинке</translation>
<translation id="8750798805984357768">Выберите один из вариантов.</translation>
<translation id="8785498733064193001">начать воспроизведение</translation>
+<translation id="8808573423886751634">глава</translation>
<translation id="8845239796550121995">Транслируется на телевизор</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Ошибка при воспроизведении видео</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Другое…</translation>
<translation id="9138385573473225930">оповещение</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, начинается <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">сноска</translation>
<translation id="947831847158436616">ячейка</translation>
<translation id="966787709310836684">меню</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sk.xtb b/chromium/content/app/strings/translations/content_strings_sk.xtb
index 8d3c842429c..ce521185669 100644
--- a/chromium/content/app/strings/translations/content_strings_sk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sk.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">doplnkové</translation>
<translation id="1206619573307042055">pohyblivý prvok</translation>
<translation id="1206693055195146388">posúvač</translation>
+<translation id="1211441953136645838">vysvetlivka</translation>
<translation id="1281252709823657822">dialóg</translation>
+<translation id="1335095011850992622">titulky</translation>
<translation id="1342835525016946179">článok</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">oblasť</translation>
<translation id="1591562245178063882">Tento mesiac</translation>
<translation id="1637811476055996098">Vybrať súbory</translation>
+<translation id="1650423536718072820">obsiahnutý citát</translation>
<translation id="1729654308190250600">Zadajte e-mailovú adresu, ktorá nie je prázdna hodnota.</translation>
<translation id="1758486001363313524">Iné...</translation>
<translation id="1806710327868736751">dialóg_upozornenia</translation>
<translation id="1821985195704844674">stromová mriežka</translation>
<translation id="1822429046913737220">AM / PM</translation>
<translation id="1832974991323546415">prehrať na vzdialenom zariadení</translation>
+<translation id="1907737156431278478">príklad</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stav</translation>
<translation id="1938124657309484470">Hodnota musí byť <ph name="MAXIMUM_DATE_OR_TIME" /> alebo skôr.</translation>
<translation id="1993104285338243655">Prepnuté na zrkadlenie</translation>
<translation id="2060505056492490888">Znak <ph name="DOT" /> je v doméne <ph name="INVALIDDOMAIN" /> použitý na nesprávnej pozícii.</translation>
<translation id="2148716181193084225">Dnes</translation>
+<translation id="2158401438286456825">zoznam strán</translation>
<translation id="2226276347425096477">Tento text musíte skrátiť na <ph name="MAX_CHARACTERS" /> znakov alebo menej (súčasný počet znakov: <ph name="CURRENT_LENGTH" />).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týždeň, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Skladba <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">začiarkavacie políčko</translation>
+<translation id="2311842470354187719">zlom strany</translation>
<translation id="2335594187091864976">výber dátumu a času</translation>
<translation id="248395913932153421">Deň</translation>
<translation id="2507943997699731163">Vyplňte toto pole.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">prehrať</translation>
<translation id="2613802280814924224">Zadajte platnú hodnotu. Najbližšia platná hodnota je <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Odoslať</translation>
+<translation id="2657045182931379222">grafický objekt</translation>
<translation id="2674318244760992338">päta</translation>
<translation id="2709516037105925701">Automatické dopĺňanie</translation>
<translation id="2723001399770238859">zvuk</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Predĺžte tento text aspoň na <ph name="MIN_CHARACTERS" /> alebo viac znakov (momentálny počet znakov je <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Časť pred znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
<translation id="3846214748874656680">Ukončiť režim celej obrazovky</translation>
+<translation id="3920932319529768807">záver</translation>
<translation id="3924558731517983934">aplikácia</translation>
+<translation id="3944740393230681990">prológ</translation>
<translation id="3960700977367013758">posúvač</translation>
<translation id="4103419683916926126">Milisekundy</translation>
<translation id="4151657705144244502">grafika</translation>
+<translation id="4193965531860883258">predhovor</translation>
<translation id="4201051445878709314">Zobraziť predchádzajúci mesiac</translation>
<translation id="421884353938374759">výber farieb</translation>
<translation id="4248100235867064564">panel s ponukami</translation>
<translation id="4254339807215791271">informácie o obsahu</translation>
<translation id="4360991593054037559">Zadajte platnú hodnotu. Najbližšie platné hodnoty sú <ph name="VALID_VALUE_LOW" /> a <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Otázky a odpovede</translation>
<translation id="4413860115965805769">tlačidlo ponuky</translation>
+<translation id="4446524499724042288">glosárový termín</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4597532268155981612">formulár</translation>
<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Časť za znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">príloha</translation>
+<translation id="4742539557769756338">titulná strana</translation>
<translation id="4757246831282535685">panel karty</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Zadajte číslo.</translation>
+<translation id="4912536737030637138">bibliografický záznam</translation>
<translation id="4975562563186953947">Počet vybraných položiek: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Zapnúť zvuk</translation>
<translation id="49969490063480558">Zadajte časť za znakom <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> je neúplná.</translation>
<translation id="5034860022980953847">indikátor priebehu</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Zobraziť ďalší mesiac</translation>
<translation id="512758898067543763">hlavička riadka</translation>
+<translation id="5143125788380636750">epilóg</translation>
+<translation id="5153163864850940242">Toto video sa prehráva v režime Obraz v obraze</translation>
<translation id="5164977714490026579">Hodnota musí byť väčšia alebo rovná hodnote <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Zadajte časť pred znakom <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> je neúplná.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">obnoviť zvuk</translation>
<translation id="561939826962581046">čas</translation>
<translation id="5630795885300617244">Dvojitým klepnutím doľava alebo doprava preskočíte o 10 s</translation>
+<translation id="5631759159893697722">abstrakt</translation>
<translation id="5641012560118721995">pozastaviť prehrávanie</translation>
<translation id="5643186887447432888">tlačidlo</translation>
<translation id="5677946354068040947">ďalšie možnosti</translation>
+<translation id="576709008726043716">úvod</translation>
<translation id="57838592816432529">Vypnúť zvuk</translation>
<translation id="5860033963881614850">Vypnuté</translation>
<translation id="588258955323874662">Celá obrazovka</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Rok</translation>
<translation id="6023896073578205740">pole s ponukou</translation>
<translation id="6101327004457443354">obnoviť zvukovú stopu</translation>
+<translation id="6150588977291308318">bibliografia</translation>
<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">doslov</translation>
+<translation id="6213469881011901533">glosár</translation>
<translation id="6398862346408813489">Zobraziť panel na výber mesiaca</translation>
<translation id="6404546809543547843">posúvač časovej osi zvuku</translation>
+<translation id="6453774872122745852">poďakovanie</translation>
<translation id="648732519525291180">výber času</translation>
<translation id="6550675742724504774">Možnosti</translation>
-<translation id="6564313821541007458">Je aktívny režim Obraz v obraze</translation>
<translation id="658823671542763450">prejsť do režimu celej obrazovky</translation>
<translation id="663493177488814956">informačný kanál</translation>
<translation id="6637586476836377253">denník</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">popis</translation>
<translation id="6790428901817661496">Prehrať</translation>
<translation id="6820355525329141109">Doplnok sa nepodarilo načítať.</translation>
+<translation id="6820615603175220800">bibliografický odkaz</translation>
<translation id="6843725295806269523">stlmiť</translation>
<translation id="6853785296079745596">skryť skryté titulky</translation>
<translation id="6885760532393684712">adresár</translation>
+<translation id="689129560213475294">kolofón</translation>
<translation id="6934078000481955284">značka blockquote</translation>
<translation id="6941933287844615239">stiahnuť médiá</translation>
<translation id="6989848892321993519">Predĺžte tento text aspoň na <ph name="MIN_CHARACTERS" /> alebo viac znakov (momentálne používate jeden znak).</translation>
<translation id="709897737746224366">Zadajte hodnotu zodpovedajúcu požadovanému formátu.</translation>
+<translation id="7139483182332611405">predslov</translation>
<translation id="7223624360433298498">uplynutý čas</translation>
<translation id="7263440858009898357">Vyberte položku zo zoznamu.</translation>
<translation id="727747134524199931">hlavička stĺpca</translation>
+<translation id="7353453495576941748">poďakovanie</translation>
<translation id="7364796246159120393">Vybrať súbor</translation>
<translation id="739024184232394898">Iné...</translation>
+<translation id="7405738980073107433">vysvetlivky</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">karta</translation>
<translation id="7514365320538308">Stiahnuť</translation>
+<translation id="7529102961911894712">spätný odkaz</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafický dokument</translation>
<translation id="7673697353781729403">Hodiny</translation>
+<translation id="7681220483256441252">index</translation>
<translation id="7720026100085573005">zostávajúci čas</translation>
<translation id="7740016676195725605">ukončiť zobrazovanie skrytých titulkov</translation>
<translation id="7740050170769002709">Obsah HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">rozdeľovač</translation>
<translation id="795667975304826397">Nie je vybratý žiadny súbor</translation>
<translation id="8053789581856978548">textové pole pre vyhľadávanie</translation>
+<translation id="8057695513531652401">upozornenie</translation>
+<translation id="8105797009065549151">odkaz na poznámku</translation>
<translation id="8115662671911883373">zobrazovať skryté titulky</translation>
<translation id="8117451130807776954">Tento týždeň</translation>
<translation id="819205353528511139">prehrať film v režime celej obrazovky</translation>
<translation id="8199524924445686405">rrrr</translation>
<translation id="8284326494547611709">Titulky</translation>
<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="8415319359811155763">časť</translation>
<translation id="8433900881053900389">panel s nástrojmi</translation>
<translation id="8444882422881193423">Počet súborov: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Vyberte súbor.</translation>
<translation id="8461852803063341183">prepínač</translation>
+<translation id="8474886197722836894">venovanie</translation>
+<translation id="8531739829932800271">erráta</translation>
<translation id="8534579021159131403">Minúty</translation>
<translation id="8541249477527128034">ovládanie médií</translation>
+<translation id="8550857728288566671">grafický symbol</translation>
<translation id="8583702881314752957">zoznam definícií</translation>
<translation id="8597182159515967513">nadpis</translation>
+<translation id="860475260694818407">obsah</translation>
<translation id="8613126697340063924">ovládať vzdialené prehrávanie</translation>
+<translation id="862370744433916922">podnadpis</translation>
<translation id="8741316211671074806">Obraz v obraze</translation>
<translation id="8750798805984357768">Vyberte jednu z týchto možností.</translation>
<translation id="8785498733064193001">začať prehrávanie</translation>
+<translation id="8808573423886751634">kapitola</translation>
<translation id="8845239796550121995">Prenáša sa do televízora</translation>
<translation id="8851136666856101339">hlavné</translation>
<translation id="8875657656876809964">Chyba prehrávania videa</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Iné...</translation>
<translation id="9138385573473225930">upozornenie</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> začínajúci <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">poznámka pod čiarou</translation>
<translation id="947831847158436616">bunka</translation>
<translation id="966787709310836684">ponuka</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sl.xtb b/chromium/content/app/strings/translations/content_strings_sl.xtb
index af6716e2b55..e21b1f5e558 100644
--- a/chromium/content/app/strings/translations/content_strings_sl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sl.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">dopolnilno</translation>
<translation id="1206619573307042055">potujoči napis</translation>
<translation id="1206693055195146388">drsnik</translation>
+<translation id="1211441953136645838">končna opomba</translation>
<translation id="1281252709823657822">pogovorno okno</translation>
+<translation id="1335095011850992622">seznam sodelujočih</translation>
<translation id="1342835525016946179">člnk</translation>
<translation id="1359897965706325498">pasica</translation>
<translation id="1589122976691792535">območje</translation>
<translation id="1591562245178063882">Ta mesec</translation>
<translation id="1637811476055996098">Izberi datoteke</translation>
+<translation id="1650423536718072820">pojavni citat</translation>
<translation id="1729654308190250600">Vnesite e-poštni naslov (polje ne sme biti prazno).</translation>
<translation id="1758486001363313524">Drugo ...</translation>
<translation id="1806710327868736751">pogovorno okno z opozorilom</translation>
<translation id="1821985195704844674">drevesna mreža</translation>
<translation id="1822429046913737220">Dopoldne/popoldne</translation>
<translation id="1832974991323546415">predvajanje v oddaljeni napravi</translation>
+<translation id="1907737156431278478">primer</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stanje</translation>
<translation id="1938124657309484470">Vrednost mora biti <ph name="MAXIMUM_DATE_OR_TIME" /> ali prej.</translation>
<translation id="1993104285338243655">Preklopljeno na zrcaljenje</translation>
<translation id="2060505056492490888">»<ph name="DOT" />« je na napačnem mestu v »<ph name="INVALIDDOMAIN" />«.</translation>
<translation id="2148716181193084225">Danes</translation>
+<translation id="2158401438286456825">seznam strani</translation>
<translation id="2226276347425096477">Skrajšajte to besedilo na <ph name="MAX_CHARACTERS" /> znakov ali manj (trenutno uporabljate <ph name="CURRENT_LENGTH" /> znakov).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. teden, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Besedilni posnetek <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">potrditveno polje</translation>
+<translation id="2311842470354187719">prelom strani</translation>
<translation id="2335594187091864976">izbirnik datuma in ure</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Izpolnite to polje</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">predvajanje</translation>
<translation id="2613802280814924224">Vnesite veljavno vrednost. Najbližja veljavna vrednost je <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Pošlji</translation>
+<translation id="2657045182931379222">grafični predmet</translation>
<translation id="2674318244760992338">noga</translation>
<translation id="2709516037105925701">Samodejno izpolnjevanje</translation>
<translation id="2723001399770238859">zvok</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Podaljšajte to besedilo na toliko znakov ali več: <ph name="MIN_CHARACTERS" /> (trenutno uporabljate toliko znakov: <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Del pred »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
<translation id="3846214748874656680">Zapri celozaslonski način</translation>
+<translation id="3920932319529768807">sklep</translation>
<translation id="3924558731517983934">aplikacija</translation>
+<translation id="3944740393230681990">uvod</translation>
<translation id="3960700977367013758">drsni trak</translation>
<translation id="4103419683916926126">Milisekunde</translation>
<translation id="4151657705144244502">grafični element</translation>
+<translation id="4193965531860883258">predgovor</translation>
<translation id="4201051445878709314">Prikaz prejšnjega meseca</translation>
<translation id="421884353938374759">izbirnik barve</translation>
<translation id="4248100235867064564">menijska vrstica</translation>
<translation id="4254339807215791271">podatki o vsebini</translation>
<translation id="4360991593054037559">Vnesite veljavno vrednost. Najbližji veljavni vrednosti sta <ph name="VALID_VALUE_LOW" /> in <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Vprašanja</translation>
<translation id="4413860115965805769">menijski gumb</translation>
+<translation id="4446524499724042288">vnos v glosarju</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4597532268155981612">obrazec</translation>
<translation id="4661075872484491155">drevo</translation>
<translation id="4664250907885839816">Del po »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
+<translation id="4668956016107839909">dodatek</translation>
+<translation id="4742539557769756338">naslovnica</translation>
<translation id="4757246831282535685">podokno z zavihki</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Vnesite številko.</translation>
+<translation id="4912536737030637138">bibliografski vnos</translation>
<translation id="4975562563186953947">Št. izbranih: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Vklopi zvok</translation>
<translation id="49969490063480558">Vnesite nekaj po znaku »<ph name="ATSIGN" />«. Naslov »<ph name="INVALIDADDRESS" />« je nepopoln.</translation>
<translation id="5034860022980953847">kazalnik poteka</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Prikaz naslednjega meseca</translation>
<translation id="512758898067543763">glava vrstice</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Ta videoposnetek se predvaja v načinu slike v sliki</translation>
<translation id="5164977714490026579">Vrednost mora biti večja od <ph name="MINIMUM" /> ali enaka.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Vnesite nekaj in nato <ph name="ATSIGN" />. Naslov »<ph name="INVALIDADDRESS" />« je nepopoln.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">vklop zvoka</translation>
<translation id="561939826962581046">čas</translation>
<translation id="5630795885300617244">Dvakrat se dotaknite levo ali desno, da preskočite 10 s</translation>
+<translation id="5631759159893697722">izvleček</translation>
<translation id="5641012560118721995">začasna ustavitev predvajanja</translation>
<translation id="5643186887447432888">gumb</translation>
<translation id="5677946354068040947">več možnosti</translation>
+<translation id="576709008726043716">uvod</translation>
<translation id="57838592816432529">Izklopi zvok</translation>
<translation id="5860033963881614850">Izklopljeno</translation>
<translation id="588258955323874662">Celozaslonsko</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Leto</translation>
<translation id="6023896073578205740">polje s seznamom</translation>
<translation id="6101327004457443354">vklop zvoka za zvočni posnetek</translation>
+<translation id="6150588977291308318">bibliografija</translation>
<translation id="6164829606128959761">merilnik</translation>
+<translation id="6166809985690652833">spremna beseda</translation>
+<translation id="6213469881011901533">glosar</translation>
<translation id="6398862346408813489">Prikaz podokna za izbiro meseca</translation>
<translation id="6404546809543547843">časovni krmilnik za predvajanje zvoka</translation>
+<translation id="6453774872122745852">zahvala</translation>
<translation id="648732519525291180">izbirnik ure</translation>
<translation id="6550675742724504774">Možnosti</translation>
-<translation id="6564313821541007458">Izbran je način slike v sliki</translation>
<translation id="658823671542763450">prehod v celozaslonski način</translation>
<translation id="663493177488814956">vir</translation>
<translation id="6637586476836377253">dnevn</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">opis orodja</translation>
<translation id="6790428901817661496">Predvajanje</translation>
<translation id="6820355525329141109">Vtičnika ni bilo mogoče naložiti.</translation>
+<translation id="6820615603175220800">bibliografski viri</translation>
<translation id="6843725295806269523">nemo</translation>
<translation id="6853785296079745596">skrivanje podnapisov</translation>
<translation id="6885760532393684712">imenik</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">daljši citat</translation>
<translation id="6941933287844615239">prenos predstavnosti</translation>
<translation id="6989848892321993519">Podaljšajte to besedilo na toliko znakov ali več: <ph name="MIN_CHARACTERS" /> (trenutno uporabljate en znak).</translation>
<translation id="709897737746224366">Poskrbite za ujemanje z zahtevano obliko.</translation>
+<translation id="7139483182332611405">predgovor</translation>
<translation id="7223624360433298498">pretečeni čas</translation>
<translation id="7263440858009898357">Izberite element s seznama.</translation>
<translation id="727747134524199931">glava stolpca</translation>
+<translation id="7353453495576941748">zasluga</translation>
<translation id="7364796246159120393">Izberite datoteko</translation>
<translation id="739024184232394898">Drugo ...</translation>
+<translation id="7405738980073107433">končne opombe</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tabulatorka</translation>
<translation id="7514365320538308">Prenos</translation>
+<translation id="7529102961911894712">povratna povezava</translation>
+<translation id="7647456547678091388">namig</translation>
+<translation id="7661956066982048809">grafični dokument</translation>
<translation id="7673697353781729403">Ure</translation>
+<translation id="7681220483256441252">kazalo</translation>
<translation id="7720026100085573005">preostali čas</translation>
<translation id="7740016676195725605">ustavitev prikazovanja podnapisov</translation>
<translation id="7740050170769002709">Vsebina HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">razdelilnik</translation>
<translation id="795667975304826397">Nobena datoteka ni izbrana</translation>
<translation id="8053789581856978548">besedilno polje za iskanje</translation>
+<translation id="8057695513531652401">kritika</translation>
+<translation id="8105797009065549151">sklicevanje na opombo</translation>
<translation id="8115662671911883373">začetek predvajanja podnapisov</translation>
<translation id="8117451130807776954">Ta teden</translation>
<translation id="819205353528511139">predvajanje filma v celozaslonskem načinu</translation>
<translation id="8199524924445686405">llll</translation>
<translation id="8284326494547611709">Napisi</translation>
<translation id="835897206747267392">Neveljavna vrednost.</translation>
+<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">orodna vrstica</translation>
<translation id="8444882422881193423">Število datotek: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Izberite datoteko.</translation>
<translation id="8461852803063341183">izbirni gumb</translation>
+<translation id="8474886197722836894">posvetilo</translation>
+<translation id="8531739829932800271">popravki</translation>
<translation id="8534579021159131403">Minute</translation>
<translation id="8541249477527128034">nadziranje predstavnosti</translation>
+<translation id="8550857728288566671">grafični simbol</translation>
<translation id="8583702881314752957">seznam opredelitev</translation>
<translation id="8597182159515967513">naslov</translation>
+<translation id="860475260694818407">kazalo</translation>
<translation id="8613126697340063924">upravljanje oddaljenega predvajanja</translation>
+<translation id="862370744433916922">podnaslov</translation>
<translation id="8741316211671074806">Slika v sliki</translation>
<translation id="8750798805984357768">Izberite eno od teh možnosti.</translation>
<translation id="8785498733064193001">začetek predvajanja</translation>
+<translation id="8808573423886751634">poglavje</translation>
<translation id="8845239796550121995">Predvajanje na televizorju</translation>
<translation id="8851136666856101339">glavn</translation>
<translation id="8875657656876809964">Napaka pri predvajanju videoposnetka</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Drugo ...</translation>
<translation id="9138385573473225930">opozorilo</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, začne se <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">sprotna opomba</translation>
<translation id="947831847158436616">celica</translation>
<translation id="966787709310836684">meni</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sr.xtb b/chromium/content/app/strings/translations/content_strings_sr.xtb
index 9893f4f40be..80a786e21be 100644
--- a/chromium/content/app/strings/translations/content_strings_sr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sr.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">комплементарно</translation>
<translation id="1206619573307042055">покретни текст</translation>
<translation id="1206693055195146388">клизач</translation>
+<translation id="1211441953136645838">завршна напомена</translation>
<translation id="1281252709823657822">дијалог</translation>
+<translation id="1335095011850992622">заслуге</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">банер</translation>
<translation id="1589122976691792535">регион</translation>
<translation id="1591562245178063882">Овај месец</translation>
<translation id="1637811476055996098">Избор датотека</translation>
+<translation id="1650423536718072820">кратки цитат</translation>
<translation id="1729654308190250600">Унесите имејл адресу која није празна.</translation>
<translation id="1758486001363313524">Друго...</translation>
<translation id="1806710327868736751">дијалог обавештења</translation>
<translation id="1821985195704844674">мрежа стабла</translation>
<translation id="1822429046913737220">пре подне/по подне</translation>
<translation id="1832974991323546415">пуштајте на удаљеном уређају</translation>
+<translation id="1907737156431278478">пример</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">статус</translation>
<translation id="1938124657309484470">Вредност мора да буде <ph name="MAXIMUM_DATE_OR_TIME" /> или старија.</translation>
<translation id="1993104285338243655">Пребачено је на пресликавање</translation>
<translation id="2060505056492490888">„<ph name="DOT" />“ је стављено на погрешно место у „<ph name="INVALIDDOMAIN" />“.</translation>
<translation id="2148716181193084225">Данас</translation>
+<translation id="2158401438286456825">листа страница</translation>
<translation id="2226276347425096477">Скратите овај текст на <ph name="MAX_CHARACTERS" /> знак(ов)а или мање (тренутно користите <ph name="CURRENT_LENGTH" /> знак(ов)а).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. недеља, <ph name="YEAR" />.</translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. песма</translation>
<translation id="2291999235780842123">поље за потврду</translation>
+<translation id="2311842470354187719">прелом странице</translation>
<translation id="2335594187091864976">бирач датума и времена</translation>
<translation id="248395913932153421">Дан</translation>
<translation id="2507943997699731163">Попуните ово поље.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">пустите</translation>
<translation id="2613802280814924224">Унесите важећу вредност. Најближа важећа вредност је <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Пошаљи</translation>
+<translation id="2657045182931379222">графички објекат</translation>
<translation id="2674318244760992338">подножје</translation>
<translation id="2709516037105925701">Аутоматско попуњавање</translation>
<translation id="2723001399770238859">аудио</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Продужите овај текст на <ph name="MIN_CHARACTERS" /> знак(ов)а или више (тренутно користите <ph name="CURRENT_LENGTH" /> знак(ов)а).</translation>
<translation id="383465348367842624">Део пре „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
<translation id="3846214748874656680">Изађи из целог екрана</translation>
+<translation id="3920932319529768807">закључак</translation>
<translation id="3924558731517983934">апликација</translation>
+<translation id="3944740393230681990">пролог</translation>
<translation id="3960700977367013758">трака за померање</translation>
<translation id="4103419683916926126">Милисекунде</translation>
<translation id="4151657705144244502">графички елемент</translation>
+<translation id="4193965531860883258">предговор</translation>
<translation id="4201051445878709314">Прикажи претходни месец</translation>
<translation id="421884353938374759">бирач боја</translation>
<translation id="4248100235867064564">трака са менијима</translation>
<translation id="4254339807215791271">информације о садржају</translation>
<translation id="4360991593054037559">Унесите важећу вредност. Две најближе важеће вредности су <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Питања и одговори</translation>
<translation id="4413860115965805769">дугме менија</translation>
+<translation id="4446524499724042288">референца речника термина</translation>
<translation id="4522570452068850558">Детаљи</translation>
<translation id="4597532268155981612">образац</translation>
<translation id="4661075872484491155">стабло</translation>
<translation id="4664250907885839816">Део после „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4668956016107839909">додатак</translation>
+<translation id="4742539557769756338">корицe</translation>
<translation id="4757246831282535685">табла са картицама</translation>
<translation id="4763480195061959176">видео</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Унесите број.</translation>
+<translation id="4912536737030637138">библиографска ставка</translation>
<translation id="4975562563186953947">Изабрано: <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Укључи звук</translation>
<translation id="49969490063480558">Унесите неки део после „<ph name="ATSIGN" />“. Адреса „<ph name="INVALIDADDRESS" />“ је непотпуна.</translation>
<translation id="5034860022980953847">индикатор напретка</translation>
+<translation id="5093189678851173835">натпис</translation>
<translation id="5117590920725113268">Прикажи следећи месец</translation>
<translation id="512758898067543763">заглавље реда</translation>
+<translation id="5143125788380636750">епилог</translation>
+<translation id="5153163864850940242">Видео се репродукује у режиму слике у слици</translation>
<translation id="5164977714490026579">Вредност сме да буде најмање <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Унесите неки део пре „<ph name="ATSIGN" />“. Адреса „<ph name="INVALIDADDRESS" />“ је непотпуна.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">укључите звук</translation>
<translation id="561939826962581046">време</translation>
<translation id="5630795885300617244">Двапут додирните лево или десно да бисте прескочили 10 сек</translation>
+<translation id="5631759159893697722">сажетак</translation>
<translation id="5641012560118721995">паузирајте репродукцију</translation>
<translation id="5643186887447432888">дугме</translation>
<translation id="5677946354068040947">још опција</translation>
+<translation id="576709008726043716">увод</translation>
<translation id="57838592816432529">Искључи звук</translation>
<translation id="5860033963881614850">Искључено</translation>
<translation id="588258955323874662">Цеo екран</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Година</translation>
<translation id="6023896073578205740">оквир са листом</translation>
<translation id="6101327004457443354">укључите звук аудио снимка</translation>
+<translation id="6150588977291308318">библиографија</translation>
<translation id="6164829606128959761">мерач</translation>
+<translation id="6166809985690652833">поговор</translation>
+<translation id="6213469881011901533">речник термина</translation>
<translation id="6398862346408813489">Прикажи таблу за избор месеца</translation>
<translation id="6404546809543547843">клизач за трајање аудио-садржаја</translation>
+<translation id="6453774872122745852">признања</translation>
<translation id="648732519525291180">бирач времена</translation>
<translation id="6550675742724504774">Опције</translation>
-<translation id="6564313821541007458">Сада у режиму Слика у слици</translation>
<translation id="658823671542763450">пређите на режим целог екрана</translation>
<translation id="663493177488814956">фид</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">објашњење</translation>
<translation id="6790428901817661496">Пусти</translation>
<translation id="6820355525329141109">Учитавање додатне компоненте није успело.</translation>
+<translation id="6820615603175220800">референца библиографије</translation>
<translation id="6843725295806269523">искључи звук</translation>
<translation id="6853785296079745596">сакријте опционални титл</translation>
<translation id="6885760532393684712">каталог</translation>
+<translation id="689129560213475294">знак издавача</translation>
<translation id="6934078000481955284">издвојени цитат</translation>
<translation id="6941933287844615239">преузми медије</translation>
<translation id="6989848892321993519">Продужите овај текст на бар <ph name="MIN_CHARACTERS" /> знак(ов)а (тренутно користите 1 знак).</translation>
<translation id="709897737746224366">Изаберите захтевани формат.</translation>
+<translation id="7139483182332611405">предговор</translation>
<translation id="7223624360433298498">протекло време</translation>
<translation id="7263440858009898357">Изаберите ставку са листе.</translation>
<translation id="727747134524199931">заглавље колоне</translation>
+<translation id="7353453495576941748">заслуга</translation>
<translation id="7364796246159120393">Одабери датотеку</translation>
<translation id="739024184232394898">Друго...</translation>
+<translation id="7405738980073107433">завршне напомене</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Преузми</translation>
+<translation id="7529102961911894712">повратни линк</translation>
+<translation id="7647456547678091388">савет</translation>
+<translation id="7661956066982048809">графички документ</translation>
<translation id="7673697353781729403">Сати</translation>
+<translation id="7681220483256441252">индекс</translation>
<translation id="7720026100085573005">преостало време</translation>
<translation id="7740016676195725605">зауставите приказивање опционалног титла</translation>
<translation id="7740050170769002709">HTML садржај</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">разделник</translation>
<translation id="795667975304826397">Није одабрано</translation>
<translation id="8053789581856978548">поље за текст претраге</translation>
+<translation id="8057695513531652401">обавештење</translation>
+<translation id="8105797009065549151">референца напомене</translation>
<translation id="8115662671911883373">започните приказивање опционалног титла</translation>
<translation id="8117451130807776954">Ова недеља</translation>
<translation id="819205353528511139">пустите филм у режиму целог екрана</translation>
<translation id="8199524924445686405">гггг</translation>
<translation id="8284326494547611709">Титл</translation>
<translation id="835897206747267392">Неважећа вредност.</translation>
+<translation id="8415319359811155763">део</translation>
<translation id="8433900881053900389">трака с алаткама</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> датотеке(а)</translation>
<translation id="8451268428117625855">Изаберите датотеку.</translation>
<translation id="8461852803063341183">дугме за избор</translation>
+<translation id="8474886197722836894">посвета</translation>
+<translation id="8531739829932800271">исправке и допуне</translation>
<translation id="8534579021159131403">Минути</translation>
<translation id="8541249477527128034">контрола за медије</translation>
+<translation id="8550857728288566671">графички симбол</translation>
<translation id="8583702881314752957">листа дефиниција</translation>
<translation id="8597182159515967513">наслов</translation>
+<translation id="860475260694818407">садржај</translation>
<translation id="8613126697340063924">контролишите репродукцију на удаљеном уређају</translation>
+<translation id="862370744433916922">титл</translation>
<translation id="8741316211671074806">Слика у слици</translation>
<translation id="8750798805984357768">Изаберите неку од ових опција.</translation>
<translation id="8785498733064193001">започните репродукцију</translation>
+<translation id="8808573423886751634">поглавље</translation>
<translation id="8845239796550121995">Тренутно се пребацује на ТВ</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Грешка при пуштању видео снимка</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Друго...</translation>
<translation id="9138385573473225930">обавештење</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, од <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">фуснота</translation>
<translation id="947831847158436616">ћелија</translation>
<translation id="966787709310836684">мени</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sv.xtb b/chromium/content/app/strings/translations/content_strings_sv.xtb
index 9bd0e0679b0..570a7a56037 100644
--- a/chromium/content/app/strings/translations/content_strings_sv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sv.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">kompletterande</translation>
<translation id="1206619573307042055">markör</translation>
<translation id="1206693055195146388">skjutreglage</translation>
+<translation id="1211441953136645838">slutnot</translation>
<translation id="1281252709823657822">dialogruta</translation>
+<translation id="1335095011850992622">medverkande</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">område</translation>
<translation id="1591562245178063882">Den här månaden</translation>
<translation id="1637811476055996098">Välj filer</translation>
+<translation id="1650423536718072820">utvalt citat</translation>
<translation id="1729654308190250600">Ange en e-postadress som inte är tom.</translation>
<translation id="1758486001363313524">Annat ...</translation>
<translation id="1806710327868736751">varningsdialogruta</translation>
<translation id="1821985195704844674">träddiagram</translation>
<translation id="1822429046913737220">FM/EM</translation>
<translation id="1832974991323546415">spela på en fjärrenhet</translation>
+<translation id="1907737156431278478">exempel</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Värdet måste vara <ph name="MAXIMUM_DATE_OR_TIME" /> eller tidigare.</translation>
<translation id="1993104285338243655">Bytte till spegling</translation>
<translation id="2060505056492490888"><ph name="DOT" /> används på fel plats i <ph name="INVALIDDOMAIN" />.</translation>
<translation id="2148716181193084225">Idag</translation>
+<translation id="2158401438286456825">sidlista</translation>
<translation id="2226276347425096477">Förkorta texten till <ph name="MAX_CHARACTERS" /> tecken eller mindre (nu är texten <ph name="CURRENT_LENGTH" /> tecken).</translation>
<translation id="2247351761944213033">Vecka <ph name="WEEKNUMBER" /> <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Spår <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kryssruta</translation>
+<translation id="2311842470354187719">sidbrytning</translation>
<translation id="2335594187091864976">datum- och tidsväljare</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Fyll i det här fältet.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">spela upp</translation>
<translation id="2613802280814924224">Ange ett giltigt värde. Det närmast giltiga värdet är <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Skicka</translation>
+<translation id="2657045182931379222">grafiskt objekt</translation>
<translation id="2674318244760992338">sidfot</translation>
<translation id="2709516037105925701">Autofyll</translation>
<translation id="2723001399770238859">ljud</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Lägg till minst <ph name="MIN_CHARACTERS" /> tecken (för närvarande har du angett <ph name="CURRENT_LENGTH" /> tecken).</translation>
<translation id="383465348367842624">En del följt av <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
<translation id="3846214748874656680">Avsluta helskärmsläge</translation>
+<translation id="3920932319529768807">resultat</translation>
<translation id="3924558731517983934">program</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">rullningslist</translation>
<translation id="4103419683916926126">Millisekunder</translation>
<translation id="4151657705144244502">bild</translation>
+<translation id="4193965531860883258">förord</translation>
<translation id="4201051445878709314">Visa föregående månad</translation>
<translation id="421884353938374759">färgval</translation>
<translation id="4248100235867064564">menyfält</translation>
<translation id="4254339807215791271">innehållsinformation</translation>
<translation id="4360991593054037559">Ange ett giltigt värde. De två närmaste giltiga värdena är <ph name="VALID_VALUE_LOW" /> och <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Frågor och svar</translation>
<translation id="4413860115965805769">menyknapp</translation>
+<translation id="4446524499724042288">hänvisning till ordlista</translation>
<translation id="4522570452068850558">Info</translation>
<translation id="4597532268155981612">formulär</translation>
<translation id="4661075872484491155">träd</translation>
<translation id="4664250907885839816">En del efter <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">bilaga</translation>
+<translation id="4742539557769756338">omslag</translation>
<translation id="4757246831282535685">flikpanel</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">sök</translation>
<translation id="4812940957355064477">Ange ett nummer.</translation>
+<translation id="4912536737030637138">bibliografipost</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> valda</translation>
<translation id="4992066212339426712">Slå på ljudet</translation>
<translation id="49969490063480558">Ange en del följt av <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> är ofullständig.</translation>
<translation id="5034860022980953847">förloppsindikator</translation>
+<translation id="5093189678851173835">epigraf</translation>
<translation id="5117590920725113268">Visa nästa månad</translation>
<translation id="512758898067543763">radrubrik</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5153163864850940242">Videon spelas upp i läget bild-i-bild</translation>
<translation id="5164977714490026579">Värdet måste vara större än eller lika med <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Ange en del följt av <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> är ofullständig.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">visa</translation>
<translation id="561939826962581046">tid</translation>
<translation id="5630795885300617244">Hoppa över 10 s genom att trycka två gånger till vänster/höger</translation>
+<translation id="5631759159893697722">abstract</translation>
<translation id="5641012560118721995">pausa uppspelning</translation>
<translation id="5643186887447432888">knapp</translation>
<translation id="5677946354068040947">fler alternativ</translation>
+<translation id="576709008726043716">inledning</translation>
<translation id="57838592816432529">Stäng av ljudet</translation>
<translation id="5860033963881614850">Av</translation>
<translation id="588258955323874662">Helskärm</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">År</translation>
<translation id="6023896073578205740">listruta</translation>
<translation id="6101327004457443354">spela upp ljudspåret</translation>
+<translation id="6150588977291308318">bibliografi</translation>
<translation id="6164829606128959761">mätare</translation>
+<translation id="6166809985690652833">efterord</translation>
+<translation id="6213469881011901533">ordlista</translation>
<translation id="6398862346408813489">Visa panelen för val av månad</translation>
<translation id="6404546809543547843">tidsreglage för ljud</translation>
+<translation id="6453774872122745852">författarens tack</translation>
<translation id="648732519525291180">tidsväljare</translation>
<translation id="6550675742724504774">Alternativ</translation>
-<translation id="6564313821541007458">Visas i läget bild-i-bild</translation>
<translation id="658823671542763450">visa i helskärm</translation>
<translation id="663493177488814956">flöde</translation>
<translation id="6637586476836377253">logg</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">beskrivning</translation>
<translation id="6790428901817661496">Spela</translation>
<translation id="6820355525329141109">Det gick inte att läsa in plugin-programmet.</translation>
+<translation id="6820615603175220800">bibliografisk referens</translation>
<translation id="6843725295806269523">ljud av</translation>
<translation id="6853785296079745596">dölj textning</translation>
<translation id="6885760532393684712">katalog</translation>
+<translation id="689129560213475294">kolofon</translation>
<translation id="6934078000481955284">citatblock</translation>
<translation id="6941933287844615239">ladda ned media</translation>
<translation id="6989848892321993519">Lägg till minst <ph name="MIN_CHARACTERS" /> tecken (för närvarande har du angett 1 tecken).</translation>
<translation id="709897737746224366">Matcha det format som anges.</translation>
+<translation id="7139483182332611405">företal</translation>
<translation id="7223624360433298498">förfluten tid</translation>
<translation id="7263440858009898357">Välj ett alternativ i listan.</translation>
<translation id="727747134524199931">kolumnrubrik</translation>
+<translation id="7353453495576941748">erkännande</translation>
<translation id="7364796246159120393">Välj fil</translation>
<translation id="739024184232394898">Annat ...</translation>
+<translation id="7405738980073107433">slutnoter</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tabb</translation>
<translation id="7514365320538308">Ladda ned</translation>
+<translation id="7529102961911894712">bakåtlänk</translation>
+<translation id="7647456547678091388">tips</translation>
+<translation id="7661956066982048809">grafiskt dokument</translation>
<translation id="7673697353781729403">Timmar</translation>
+<translation id="7681220483256441252">index</translation>
<translation id="7720026100085573005">återstående tid</translation>
<translation id="7740016676195725605">sluta visa textning</translation>
<translation id="7740050170769002709">HTML-innehåll</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">delare</translation>
<translation id="795667975304826397">Ingen fil har valts</translation>
<translation id="8053789581856978548">fält för söktext</translation>
+<translation id="8057695513531652401">anmärkning</translation>
+<translation id="8105797009065549151">referensnot</translation>
<translation id="8115662671911883373">börja visa textning</translation>
<translation id="8117451130807776954">Den här veckan</translation>
<translation id="819205353528511139">spela upp filmen i helskärmsläge</translation>
<translation id="8199524924445686405">åååå</translation>
<translation id="8284326494547611709">Textning</translation>
<translation id="835897206747267392">Ogiltigt värde.</translation>
+<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">verktygsfält</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
<translation id="8451268428117625855">Välj en fil.</translation>
<translation id="8461852803063341183">alternativknapp</translation>
+<translation id="8474886197722836894">tillägnan</translation>
+<translation id="8531739829932800271">errata</translation>
<translation id="8534579021159131403">Minuter</translation>
<translation id="8541249477527128034">mediekontroll</translation>
+<translation id="8550857728288566671">grafisk symbol</translation>
<translation id="8583702881314752957">definitionslista</translation>
<translation id="8597182159515967513">rubrik</translation>
+<translation id="860475260694818407">innehållsförteckning</translation>
<translation id="8613126697340063924">styra fjärruppspelning</translation>
+<translation id="862370744433916922">undertext</translation>
<translation id="8741316211671074806">Bild i bild</translation>
<translation id="8750798805984357768">Välj ett av följande alternativ.</translation>
<translation id="8785498733064193001">starta uppspelning</translation>
+<translation id="8808573423886751634">kapitel</translation>
<translation id="8845239796550121995">Castar nu till TV:n</translation>
<translation id="8851136666856101339">huvud</translation>
<translation id="8875657656876809964">Videouppspelningsfel</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Annat ...</translation>
<translation id="9138385573473225930">varning</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> som börjar den <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">fotnot</translation>
<translation id="947831847158436616">cell</translation>
<translation id="966787709310836684">meny</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sw.xtb b/chromium/content/app/strings/translations/content_strings_sw.xtb
index f21490de4fd..810a58adb8b 100644
--- a/chromium/content/app/strings/translations/content_strings_sw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sw.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">nyongeza</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">kitelezi</translation>
+<translation id="1211441953136645838">maelezo ya mwisho wa kitabu</translation>
<translation id="1281252709823657822">kidirisha</translation>
+<translation id="1335095011850992622">walioshiriki</translation>
<translation id="1342835525016946179">makala</translation>
<translation id="1359897965706325498">bango</translation>
<translation id="1589122976691792535">eneo</translation>
<translation id="1591562245178063882">Mwezi huu</translation>
<translation id="1637811476055996098">Chagua Faili</translation>
+<translation id="1650423536718072820">nukuu muhimu</translation>
<translation id="1729654308190250600">Tafadhali jaza sehemu ya anwani ya barua pepe.</translation>
<translation id="1758486001363313524">Nyingine...</translation>
<translation id="1806710327868736751">kidirisha cha arifa</translation>
<translation id="1821985195704844674">gridi ya mti</translation>
<translation id="1822429046913737220">AM / PM</translation>
<translation id="1832974991323546415">cheza kwenye kifaa cha mbali</translation>
+<translation id="1907737156431278478">mfano</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">hali</translation>
<translation id="1938124657309484470">Thamani lazima iwe <ph name="MAXIMUM_DATE_OR_TIME" /> au mapema.</translation>
<translation id="1993104285338243655">Inatumia hali ya kuakisi</translation>
<translation id="2060505056492490888">' <ph name="DOT" /> 'imetumika kwenye nafasi isiyostahili katika '<ph name="INVALIDDOMAIN" />'.</translation>
<translation id="2148716181193084225">Leo</translation>
+<translation id="2158401438286456825">orodha ya kurasa</translation>
<translation id="2226276347425096477">Tafadhali fupisha maandishi haya hadi vibambo <ph name="MAX_CHARACTERS" /> au chini (kwa sasa unatumia vibambo <ph name="CURRENT_LENGTH" /> ).</translation>
<translation id="2247351761944213033">Wiki <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Wimbo wa <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">kisanduku cha kuteua</translation>
+<translation id="2311842470354187719">nafasi ya kugawa kurasa</translation>
<translation id="2335594187091864976">mchumaji tarehe na wakati</translation>
<translation id="248395913932153421">Siku</translation>
<translation id="2507943997699731163">Tafadhali jaza sehemu hii.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">cheza</translation>
<translation id="2613802280814924224">Tafadhali ingiza thamani halali.Thamani halali ya karibu ni <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Wasilisha</translation>
+<translation id="2657045182931379222">kipengee cha michoro</translation>
<translation id="2674318244760992338">kijachini</translation>
<translation id="2709516037105925701">Kujaza Kiotomatiki</translation>
<translation id="2723001399770238859">sauti</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Tafadhali refusha maandishi haya hadi herufi <ph name="MIN_CHARACTERS" /> au zaidi (kwa sasa unatumia herufi <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Sehemu inayofuatwa na '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="3846214748874656680">Ondoka kwenye skrini nzima</translation>
+<translation id="3920932319529768807">hitimisho</translation>
<translation id="3924558731517983934">programu</translation>
+<translation id="3944740393230681990">shairi la utangulizi</translation>
<translation id="3960700977367013758">sehemu ya kusogeza</translation>
<translation id="4103419683916926126">nukta</translation>
<translation id="4151657705144244502">mchoro</translation>
+<translation id="4193965531860883258">dibaji</translation>
<translation id="4201051445878709314">Onyesha mwezi uliotangulia</translation>
<translation id="421884353938374759">kiteua rangi</translation>
<translation id="4248100235867064564">upau wa menyu</translation>
<translation id="4254339807215791271">maelezo ya maudhui</translation>
<translation id="4360991593054037559">Tafadhali ingiza thamani halali. Thamani mbili halali za karibu ni <ph name="VALID_VALUE_LOW" /> na <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Maswali na Majibu</translation>
<translation id="4413860115965805769">kitufe cha menyu</translation>
+<translation id="4446524499724042288">marejeleo ya farahasa</translation>
<translation id="4522570452068850558">Maelezo</translation>
<translation id="4597532268155981612">fomu</translation>
<translation id="4661075872484491155">mti</translation>
<translation id="4664250907885839816">Sehemu inayofuata '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">kiambatisho</translation>
+<translation id="4742539557769756338">jalada</translation>
<translation id="4757246831282535685">kisanduku cha kichupo</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">tafuta</translation>
<translation id="4812940957355064477">Tafadhali ingiza nambari.</translation>
+<translation id="4912536737030637138">maelezo ya bibliografia</translation>
<translation id="4975562563186953947">Vipengee <ph name="SELECTED_COUNT" /> vimechaguliwa</translation>
<translation id="4992066212339426712">Rejesha sauti</translation>
<translation id="49969490063480558">Tafadhali ingiza sehemu inayofuatia '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' haijakamilika.</translation>
<translation id="5034860022980953847">kiashiria cha maendeleo</translation>
+<translation id="5093189678851173835">epigrafu</translation>
<translation id="5117590920725113268">Onyesha mwezi unaofuata</translation>
<translation id="512758898067543763">kichwa cha safu mlalo</translation>
+<translation id="5143125788380636750">hitimisho</translation>
+<translation id="5153163864850940242">Video hii inacheza katika hali ya Picha Ndani ya Picha</translation>
<translation id="5164977714490026579">Lazima thamani iwe kubwa kuliko au sawa na <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650">PB <ph name="QUANTITY" /></translation>
<translation id="5307600278924710095">Tafadhali ingiza sehemu ikifuatiwa na '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' haijakamilika.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">washa sauti</translation>
<translation id="561939826962581046">wakati</translation>
<translation id="5630795885300617244">Gusa mara mbili kushoto au kulia ili uruke kwa sekunde 10</translation>
+<translation id="5631759159893697722">ikisiri</translation>
<translation id="5641012560118721995">sitisha kucheza</translation>
<translation id="5643186887447432888">kitufe</translation>
<translation id="5677946354068040947">chaguo zaidi</translation>
+<translation id="576709008726043716">utangulizi</translation>
<translation id="57838592816432529">Zima sauti</translation>
<translation id="5860033963881614850">Kimezimwa</translation>
<translation id="588258955323874662">Skrini nzima</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Mwaka</translation>
<translation id="6023896073578205740">kikasha cha orodha</translation>
<translation id="6101327004457443354">washa sauti ya wimbo</translation>
+<translation id="6150588977291308318">bibliografia</translation>
<translation id="6164829606128959761">mita</translation>
+<translation id="6166809985690652833">maelezo kuhusu kitabu</translation>
+<translation id="6213469881011901533">faharasa</translation>
<translation id="6398862346408813489">Onyesha kisanduku cha uchaguzi wa mwezi</translation>
<translation id="6404546809543547843">kitelezi cha muda cha sauti</translation>
+<translation id="6453774872122745852">shukrani</translation>
<translation id="648732519525291180">Kiteua wakati</translation>
<translation id="6550675742724504774">Chaguo</translation>
-<translation id="6564313821541007458">Sasa iko Katika Hali ya Picha Ndani ya Picha</translation>
<translation id="658823671542763450">ingia skrini kamili</translation>
<translation id="663493177488814956">mipasho</translation>
<translation id="6637586476836377253">kumbukumbu</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">kidirisha cha vidokezo</translation>
<translation id="6790428901817661496">Cheza</translation>
<translation id="6820355525329141109">Haikuweza kupakia programu-jalizi.</translation>
+<translation id="6820615603175220800">marejeleo ya bibliografia</translation>
<translation id="6843725295806269523">nyamazisha</translation>
<translation id="6853785296079745596">ficha manukuu yanayoweza kuonyeshwa</translation>
<translation id="6885760532393684712">saraka</translation>
+<translation id="689129560213475294">kolofoni</translation>
<translation id="6934078000481955284">nukuu la msingi</translation>
<translation id="6941933287844615239">pakua maudhui</translation>
<translation id="6989848892321993519">Tafadhali refusha maandishi haya hadi herufi <ph name="MIN_CHARACTERS" /> au zaidi (kwa sasa unatumia herufi 1).</translation>
<translation id="709897737746224366">Tafadhali linganisha umbizo lililoombwa.</translation>
+<translation id="7139483182332611405">dibaji</translation>
<translation id="7223624360433298498">muda uliokwisha</translation>
<translation id="7263440858009898357">Tafadhali chagua kipengee katika orodha.</translation>
<translation id="727747134524199931">kijajuu cha safu wima</translation>
+<translation id="7353453495576941748">aliyeshiriki</translation>
<translation id="7364796246159120393">Chagua Faili</translation>
<translation id="739024184232394898">Nyingine...</translation>
+<translation id="7405738980073107433">maelezo ya mwisho wa kitabu</translation>
<translation id="7460907917090416791">TB <ph name="QUANTITY" /></translation>
<translation id="7491962110804786152">kichupo</translation>
<translation id="7514365320538308">Pakua</translation>
+<translation id="7529102961911894712">kiungo rejeshi</translation>
+<translation id="7647456547678091388">kidokezo</translation>
+<translation id="7661956066982048809">hati ya picha</translation>
<translation id="7673697353781729403">Saa</translation>
+<translation id="7681220483256441252">faharasa</translation>
<translation id="7720026100085573005">muda unaosalia</translation>
<translation id="7740016676195725605">koma kuonyesha manukuu yanaweza kufichwa</translation>
<translation id="7740050170769002709">Maudhui ya HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">kitenganishi</translation>
<translation id="795667975304826397">Hakuna faili iliyochaguliwa</translation>
<translation id="8053789581856978548">sehemu ya maandishi ya utafutaji</translation>
+<translation id="8057695513531652401">ilani</translation>
+<translation id="8105797009065549151">marejeleo ya dokezo</translation>
<translation id="8115662671911883373">anza kuonyesha manukuu yaliyofungwa</translation>
<translation id="8117451130807776954">Wiki hii</translation>
<translation id="819205353528511139">cheza filamu katika hali ya skrini kamili</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Manukuu</translation>
<translation id="835897206747267392">Thamani batili.</translation>
+<translation id="8415319359811155763">sehemu</translation>
<translation id="8433900881053900389">upau wa vidhibiti</translation>
<translation id="8444882422881193423">faili <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Tafadhali chagua faili.</translation>
<translation id="8461852803063341183">kitufe cha mviringo</translation>
+<translation id="8474886197722836894">tabaruku</translation>
+<translation id="8531739829932800271">hitilafu katika uchapishaji</translation>
<translation id="8534579021159131403">Dakika</translation>
<translation id="8541249477527128034">udhibiti wa vyombo vya habari</translation>
+<translation id="8550857728288566671">ishara ya picha</translation>
<translation id="8583702881314752957">orodha ya ufafanuzi</translation>
<translation id="8597182159515967513">kichwa</translation>
+<translation id="860475260694818407">jedwali la yaliyomo</translation>
<translation id="8613126697340063924">dhibiti kucheza kwa mbali</translation>
+<translation id="862370744433916922">kichwa kidogo</translation>
<translation id="8741316211671074806">Picha ndani ya picha</translation>
<translation id="8750798805984357768">Tafadhali chagua moja wapo ya chaguo hizi.</translation>
<translation id="8785498733064193001">anza kucheza</translation>
+<translation id="8808573423886751634">sura</translation>
<translation id="8845239796550121995">Sasa inatuma kwenye TV yako</translation>
<translation id="8851136666856101339">kuu</translation>
<translation id="8875657656876809964">Hitilafu ya kucheza video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Nyingine...</translation>
<translation id="9138385573473225930">arifa</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, itaanza tarehe <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">tanbihi</translation>
<translation id="947831847158436616">kisanduku</translation>
<translation id="966787709310836684">menyu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ta.xtb b/chromium/content/app/strings/translations/content_strings_ta.xtb
index 5373e1415a4..450fea855b3 100644
--- a/chromium/content/app/strings/translations/content_strings_ta.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ta.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">ஈடுசெய்யக்கூடியது</translation>
<translation id="1206619573307042055">மார்கியூ</translation>
<translation id="1206693055195146388">ஸ்லைடர்</translation>
+<translation id="1211441953136645838">முடிவுக்குறிப்பு</translation>
<translation id="1281252709823657822">உரையாடல்</translation>
+<translation id="1335095011850992622">பங்களித்தவர்கள்</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">பேனர்</translation>
<translation id="1589122976691792535">மண்டலம்</translation>
<translation id="1591562245178063882">இந்த மாதம்</translation>
<translation id="1637811476055996098">கோப்புகளைத் தேர்வுசெய்க</translation>
+<translation id="1650423536718072820">pullquote</translation>
<translation id="1729654308190250600">காலி அல்லாத மின்னஞ்சல் முகவரியை உள்ளிடவும்.</translation>
<translation id="1758486001363313524">மற்றவை…</translation>
<translation id="1806710327868736751">விழிப்பூட்டல்_உரையாடல்</translation>
<translation id="1821985195704844674">ட்ரீ கிரிட்</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">தொலைநிலைச் சாதனத்தில் இயக்கு</translation>
+<translation id="1907737156431278478">உதாரணம்</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">நிலை</translation>
<translation id="1938124657309484470">மதிப்பு <ph name="MAXIMUM_DATE_OR_TIME" /> அல்லது அதற்கு முன்பு இருக்க வேண்டும்.</translation>
<translation id="1993104285338243655">பிரதிபலித்தலுக்கு மாற்றியது</translation>
<translation id="2060505056492490888"><ph name="INVALIDDOMAIN" /> இல் தவறான இடத்தில் '<ph name="DOT" />' பயன்படுத்தபட்டுள்ளது.</translation>
<translation id="2148716181193084225">இன்று</translation>
+<translation id="2158401438286456825">பக்கப் பட்டியல்</translation>
<translation id="2226276347425096477">இந்த உரையை <ph name="MAX_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் குறைவாக சுருக்கிடுங்கள் (நீங்கள் தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்).</translation>
<translation id="2247351761944213033">வாரம் <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ட்ராக் <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">செக்பாக்ஸ்</translation>
+<translation id="2311842470354187719">பக்க முறிப்பு</translation>
<translation id="2335594187091864976">தேதி மற்றும் நேரம் தேர்ந்தெடுப்பான்</translation>
<translation id="248395913932153421">நாள்</translation>
<translation id="2507943997699731163">இந்தப் புலத்தை நிரப்புக.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">இயக்கு</translation>
<translation id="2613802280814924224">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE" /> என்பது நெருக்கமாக உள்ள சரியான மதிப்பாகும்.</translation>
<translation id="2653659639078652383">சமர்ப்பி</translation>
+<translation id="2657045182931379222">கிராஃபிக்ஸ் பொருள்</translation>
<translation id="2674318244760992338">அடிக்குறிப்பு</translation>
<translation id="2709516037105925701">தானாகநிரப்பு</translation>
<translation id="2723001399770238859">ஆடியோ</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">இந்த உரையை <ph name="MIN_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் அதிகமாக (தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்) நீட்டிக்கவும்.</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து வரும் பகுதியில் '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
<translation id="3846214748874656680">முழுத்திரை வேண்டாம்</translation>
+<translation id="3920932319529768807">முடிவு</translation>
<translation id="3924558731517983934">பயன்பாடு</translation>
+<translation id="3944740393230681990">முன்னுரை</translation>
<translation id="3960700977367013758">உருட்டல் பட்டி</translation>
<translation id="4103419683916926126">மில்லிவினாடிகள்</translation>
<translation id="4151657705144244502">கிராஃபிக்</translation>
+<translation id="4193965531860883258">அறிமுகம்</translation>
<translation id="4201051445878709314">முந்தைய மாதத்தைக் காட்டு</translation>
<translation id="421884353938374759">வண்ணத் தேர்வி</translation>
<translation id="4248100235867064564">மெனுப் பட்டி</translation>
<translation id="4254339807215791271">உள்ளடக்கத் தகவல்</translation>
<translation id="4360991593054037559">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE_LOW" /> மற்றும் <ph name="VALID_VALUE_HIGHER" /> ஆகியவை மிக நெருக்கமான சரியான இரண்டு மதிப்புகளாகும்.</translation>
+<translation id="4384583879834880242">கேள்வி-பதில்</translation>
<translation id="4413860115965805769">மெனு பொத்தான்</translation>
+<translation id="4446524499724042288">அருஞ்சொல் திரட்டு மேற்கோள்</translation>
<translation id="4522570452068850558">விவரங்கள்</translation>
<translation id="4597532268155981612">படிவம்</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ஐத் தொடரும் பகுதியில், '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
+<translation id="4668956016107839909">பிற்சேர்க்கை</translation>
+<translation id="4742539557769756338">அட்டை</translation>
<translation id="4757246831282535685">தாவல் பலகம்</translation>
<translation id="4763480195061959176">வீடியோ</translation>
<translation id="479989351350248267">Search</translation>
<translation id="4812940957355064477">எண்ணை உள்ளிடுக.</translation>
+<translation id="4912536737030637138">நூல்விவர அட்டவணை உள்ளீடு</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> தேர்ந்தெடுக்கப்பட்டன</translation>
<translation id="4992066212339426712">ஒலி இயக்கு</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS" />' முழுமைப்பெறாமல் உள்ளது.</translation>
<translation id="5034860022980953847">செயல்நிலை காட்டி</translation>
+<translation id="5093189678851173835">கல்வெட்டு</translation>
<translation id="5117590920725113268">அடுத்த மாதத்தைக் காட்டு</translation>
<translation id="512758898067543763">வரிசை மேற்தலைப்பு</translation>
+<translation id="5143125788380636750">முடிவுரை</translation>
+<translation id="5153163864850940242">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையில் இந்த வீடியோ இயக்கப்படுகிறது</translation>
<translation id="5164977714490026579">மதிப்பானது, கண்டிப்பாக <ph name="MINIMUM" /> ஐ விட அதிகமாக அல்லது அதற்குச் சமமாக இருக்க வேண்டும்.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> பெ.பை</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS" />' முழுமைப் பெறாமல் உள்ளது.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">ஒலி இயக்கு</translation>
<translation id="561939826962581046">நேரம்</translation>
<translation id="5630795885300617244">10வி தவிர்க்க, இடது அல்லது வலதுபுறம் இருமுறை தட்டவும்</translation>
+<translation id="5631759159893697722">சுருக்கம்</translation>
<translation id="5641012560118721995">மறுஇயக்கத்தை இடைநிறுத்து</translation>
<translation id="5643186887447432888">பொத்தான்</translation>
<translation id="5677946354068040947">கூடுதல் விருப்பங்கள் பொத்தான்</translation>
+<translation id="576709008726043716">அறிமுகம்</translation>
<translation id="57838592816432529">ஒலியடக்கு</translation>
<translation id="5860033963881614850">ஆஃப்</translation>
<translation id="588258955323874662">முழுத்திரை</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">ஆண்டு</translation>
<translation id="6023896073578205740">பட்டியல் பெட்டி</translation>
<translation id="6101327004457443354">ஆடியோ டிராக்கை இயக்கு</translation>
+<translation id="6150588977291308318">நூல்விவர அட்டவணை</translation>
<translation id="6164829606128959761">மீட்டர்</translation>
+<translation id="6166809985690652833">பின்னுரை</translation>
+<translation id="6213469881011901533">அருஞ்சொல் திரட்டு</translation>
<translation id="6398862346408813489">மாதம் தேர்ந்தெடுப்புப் பலகத்தைக் காட்டு</translation>
<translation id="6404546809543547843">ஆடியோ நேர ஸ்கிரப்பர்</translation>
+<translation id="6453774872122745852">அங்கீகாரங்கள்</translation>
<translation id="648732519525291180">நேரம் தேர்ந்தெடுப்பான்</translation>
<translation id="6550675742724504774">விருப்பத்தேர்வுகள்</translation>
-<translation id="6564313821541007458">இப்போது பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையில் உள்ளது</translation>
<translation id="658823671542763450">முழுத்திரைக்குச் செல்</translation>
<translation id="663493177488814956">ஊட்டம்</translation>
<translation id="6637586476836377253">பதிவு</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">உதவிக்குறிப்பு</translation>
<translation id="6790428901817661496">இயக்கு</translation>
<translation id="6820355525329141109">செருகுநிரல் ஏற்றப்படவில்லை.</translation>
+<translation id="6820615603175220800">நூல்விவர அட்டவணை மேற்கோள்</translation>
<translation id="6843725295806269523">ஒலியடக்கு</translation>
<translation id="6853785296079745596">மூடப்பட்ட தலைப்புகளை மறை</translation>
<translation id="6885760532393684712">கோப்பகம்</translation>
+<translation id="689129560213475294">முத்திரை</translation>
<translation id="6934078000481955284">பிளாக்கோட்</translation>
<translation id="6941933287844615239">மீடியாவைப் பதிவிறக்கு</translation>
<translation id="6989848892321993519">இந்த உரையில் <ph name="MIN_CHARACTERS" /> அல்லது அதற்கு மேற்பட்ட எழுத்துக்குறிகளைப் பயன்படுத்தவும் (தற்போது 1 எழுத்துக்குறியைப் பயன்படுத்துகிறீர்கள்).</translation>
<translation id="709897737746224366">கோரிய வடிவமைப்பில் தருக.</translation>
+<translation id="7139483182332611405">முன்னுரை</translation>
<translation id="7223624360433298498">முடிவடைந்த நேரம்</translation>
<translation id="7263440858009898357">பட்டியலிலிருந்து ஒரு உருப்படியைத் தேர்ந்தெடுங்கள்.</translation>
<translation id="727747134524199931">நெடுவரிசை மேற்தலைப்பு</translation>
+<translation id="7353453495576941748">பங்களித்தவர்</translation>
<translation id="7364796246159120393">கோப்பைத் தேர்வு செய்க</translation>
<translation id="739024184232394898">மற்றவை…</translation>
+<translation id="7405738980073107433">முடிவுக்குறிப்புகள்</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> டெ.பை</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">பதிவிறக்கு</translation>
+<translation id="7529102961911894712">பின்னிணைப்பு</translation>
+<translation id="7647456547678091388">உதவிக்குறிப்பு</translation>
+<translation id="7661956066982048809">கிராஃபிக்ஸ் ஆவணம்</translation>
<translation id="7673697353781729403">மணிநேரம்</translation>
+<translation id="7681220483256441252">பொருளடக்கம்</translation>
<translation id="7720026100085573005">மீதமுள்ள நேரம்</translation>
<translation id="7740016676195725605">மூடப்பட்ட தலைப்புகளைக் காட்டுவதை நிறுத்து</translation>
<translation id="7740050170769002709">HTML உள்ளடக்கம்</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">பிரிப்பான்</translation>
<translation id="795667975304826397">எந்த கோப்பும் தேர்ந்தெடுக்கப்படவில்லை</translation>
<translation id="8053789581856978548">தேடல் உரைப் புலம்</translation>
+<translation id="8057695513531652401">அறிவிப்பு</translation>
+<translation id="8105797009065549151">குறிப்பு மேற்கோள்</translation>
<translation id="8115662671911883373">மூடப்பட்ட தலைப்புகளைக் காட்டுவதைத் தொடங்கு</translation>
<translation id="8117451130807776954">இந்த வாரம்</translation>
<translation id="819205353528511139">மூவியை முழுத்திரைப் பயன்முறையில் இயக்கு</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">வசனங்கள்</translation>
<translation id="835897206747267392">செல்லாத மதிப்பு.</translation>
+<translation id="8415319359811155763">பகுதி</translation>
<translation id="8433900881053900389">கருவிப்பட்டி</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> கோப்புகள்</translation>
<translation id="8451268428117625855">ஒரு கோப்பை தேர்ந்தெடுக்கவும்.</translation>
<translation id="8461852803063341183">ரேடியோ பொத்தான்</translation>
+<translation id="8474886197722836894">அர்ப்பணம்</translation>
+<translation id="8531739829932800271">பிழைகள்</translation>
<translation id="8534579021159131403">நிமிடங்கள்</translation>
<translation id="8541249477527128034">மீடியா கட்டுப்பாடு</translation>
+<translation id="8550857728288566671">கிராஃபிக்ஸ் சின்னம்</translation>
<translation id="8583702881314752957">விளக்கப் பட்டியல்</translation>
<translation id="8597182159515967513">தலைப்பு</translation>
+<translation id="860475260694818407">உள்ளடக்க அட்டவணை</translation>
<translation id="8613126697340063924">தொலைநிலை இயக்கத்தைக் கட்டுப்படுத்தவும்</translation>
+<translation id="862370744433916922">துணை தலைப்பு</translation>
<translation id="8741316211671074806">பிக்ச்சர்-இன்-பிக்ச்சர்</translation>
<translation id="8750798805984357768">தயவுசெய்து இந்த விருப்பங்களில் ஒன்றைத் தேர்ந்தெடுங்கள்.</translation>
<translation id="8785498733064193001">மறுஇயக்கத்தைத் தொடங்கு</translation>
+<translation id="8808573423886751634">அத்தியாயம்</translation>
<translation id="8845239796550121995">டிவிக்கு அனுப்புகிறது</translation>
<translation id="8851136666856101339">முதன்மை</translation>
<translation id="8875657656876809964">வீடியோ இயக்கப் பிழை</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">மற்றவை…</translation>
<translation id="9138385573473225930">விழிப்பூட்டல்</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> அன்று தொடங்குவது</translation>
+<translation id="9168329111483466115">அடிக்குறிப்பு</translation>
<translation id="947831847158436616">கலம்</translation>
<translation id="966787709310836684">மெனு</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_te.xtb b/chromium/content/app/strings/translations/content_strings_te.xtb
index 1c5d44f8602..ece107bc6e9 100644
--- a/chromium/content/app/strings/translations/content_strings_te.xtb
+++ b/chromium/content/app/strings/translations/content_strings_te.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">బహుమానపూర్వకం</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">స్లయిడర్</translation>
+<translation id="1211441953136645838">ఎండ్‌నోట్</translation>
<translation id="1281252709823657822">డైలాగ్</translation>
+<translation id="1335095011850992622">సహకారులు</translation>
<translation id="1342835525016946179">కథనం</translation>
<translation id="1359897965706325498">బ్యానర్</translation>
<translation id="1589122976691792535">ప్రాంతం</translation>
<translation id="1591562245178063882">ఈ నెల</translation>
<translation id="1637811476055996098">ఫైల్‌లను ఎంచుకోండి</translation>
+<translation id="1650423536718072820">పుల్‌కోట్</translation>
<translation id="1729654308190250600">దయచేసి ఖాళీ-కాని ఇమెయిల్ చిరునామాని నమోదు చేయండి.</translation>
<translation id="1758486001363313524">ఇతర...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">వృక్షాంశ గ్రిడ్</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">రిమోట్ పరికరంలో ప్లే చేస్తుంది</translation>
+<translation id="1907737156431278478">ఉదాహరణ</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">స్థితి</translation>
<translation id="1938124657309484470">విలువ తప్పనిసరిగా <ph name="MAXIMUM_DATE_OR_TIME" /> లేదా అంతకంటే మునుపటిది అయి ఉండాలి.</translation>
<translation id="1993104285338243655">మిర్రరింగ్‌కు మార్చబడింది</translation>
<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN" />'లో '<ph name="DOT" />' తప్పు స్థానంలో ఉపయోగించబడింది.</translation>
<translation id="2148716181193084225">ఈ రోజు</translation>
+<translation id="2158401438286456825">పేజీ జాబితా</translation>
<translation id="2226276347425096477">దయచేసి ఈ వచనాన్ని <ph name="MAX_CHARACTERS" /> అక్షరాలకు లేదా అంతకంటే తక్కువ (మీరు ప్రస్తుతం <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు)కు తగ్గించండి.</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />వ వారం, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">ట్రాక్ <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">తనిఖీపెట్టె</translation>
+<translation id="2311842470354187719">పేజీ విభజన</translation>
<translation id="2335594187091864976">తేదీ మరియు సమయం ఎంపిక</translation>
<translation id="248395913932153421">రోజు</translation>
<translation id="2507943997699731163">దయచేసి ఈ ఫీల్డ్‌ని పూర్తి చెయ్యండి.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">ప్లే చేయి</translation>
<translation id="2613802280814924224">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE" /> అనేది సమీప చెల్లుబాటు విలువ.</translation>
<translation id="2653659639078652383">సమర్పించు</translation>
+<translation id="2657045182931379222">గ్రాఫిక్స్ ఆబ్జెక్ట్</translation>
<translation id="2674318244760992338">ఫుటర్</translation>
<translation id="2709516037105925701">స్వయంపూర్తి</translation>
<translation id="2723001399770238859">ఆడియో</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">దయచేసి ఈ వచనాన్ని <ph name="MIN_CHARACTERS" /> లేదా అంతకంటే ఎక్కువ అక్షరాలకు పొడిగించండి (ప్రస్తుతం మీరు <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />'కి ముందు ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
<translation id="3846214748874656680">పూర్తి స్క్రీన్ నుండి నిష్క్రమించు</translation>
+<translation id="3920932319529768807">ముగింపు</translation>
<translation id="3924558731517983934">అనువర్తనం</translation>
+<translation id="3944740393230681990">ప్రారంభం</translation>
<translation id="3960700977367013758">స్క్రోల్ పట్టీ</translation>
<translation id="4103419683916926126">మిల్లీసెకన్లు</translation>
<translation id="4151657705144244502">గ్రాఫిక్</translation>
+<translation id="4193965531860883258">ముందుమాట</translation>
<translation id="4201051445878709314">మునుపటి నెలను చూపుతుంది</translation>
<translation id="421884353938374759">రంగు ఎంపిక</translation>
<translation id="4248100235867064564">మెను పట్టీ</translation>
<translation id="4254339807215791271">కంటెంట్ సమాచారం</translation>
<translation id="4360991593054037559">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE_LOW" /> మరియు <ph name="VALID_VALUE_HIGHER" /> అనేవి రెండు సమీప చెల్లుబాటు విలువలు.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
<translation id="4413860115965805769">మెను బటన్</translation>
+<translation id="4446524499724042288">పదకోశ సూచన</translation>
<translation id="4522570452068850558">వివరాలు</translation>
<translation id="4597532268155981612">ఫారమ్</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
+<translation id="4668956016107839909">అనుబంధం</translation>
+<translation id="4742539557769756338">ముఖచిత్రం</translation>
<translation id="4757246831282535685">ట్యాబ్ ప్యానెల్</translation>
<translation id="4763480195061959176">వీడియో</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">దయచేసి సంఖ్యను నమోదు చేయండి.</translation>
+<translation id="4912536737030637138">వివరణపట్టి నమోదు</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ఎంచుకోబడ్డాయి</translation>
<translation id="4992066212339426712">అన్‌మ్యూట్ చేయి</translation>
<translation id="49969490063480558">దయచేసి '<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS" />' అసంపూర్ణంగా ఉంది.</translation>
<translation id="5034860022980953847">ప్రోగ్రెస్ సూచిక</translation>
+<translation id="5093189678851173835">పరిచయ వాక్యం</translation>
<translation id="5117590920725113268">తదుపరి నెలను చూపుతుంది</translation>
<translation id="512758898067543763">అడ్డు వరుస శీర్షిక</translation>
+<translation id="5143125788380636750">ఉపసంహారం</translation>
+<translation id="5153163864850940242">ఈ వీడియో చిత్రంలో-చిత్రంలో ప్లే అవుతోంది</translation>
<translation id="5164977714490026579">విలువ ఖచ్చితంగా <ph name="MINIMUM" /> కంటే ఎక్కువగా లేదా సమానంగా ఉండాలి.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">దయచేసి '<ph name="ATSIGN" />'కి ముందు ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS" />' అసంపూర్ణంగా ఉంది.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">అన్‌మ్యూట్ చేయి</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">10సె దాటవేయడానికి రెండుసార్లు ఎడమ లేదా కుడివైపుకి నొక్కండి</translation>
+<translation id="5631759159893697722">సంక్షేపం</translation>
<translation id="5641012560118721995">ప్లేబ్యాక్‌ను పాజ్ చేయి</translation>
<translation id="5643186887447432888">బటన్</translation>
<translation id="5677946354068040947">మరిన్ని ఎంపికలు</translation>
+<translation id="576709008726043716">పరిచయం</translation>
<translation id="57838592816432529">మ్యూట్ చేయి</translation>
<translation id="5860033963881614850">ఆఫ్ అయ్యింది</translation>
<translation id="588258955323874662">పూర్తితెర</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">సంవత్సరం</translation>
<translation id="6023896073578205740">జాబితా పెట్టె</translation>
<translation id="6101327004457443354">ఆడియో ట్రాక్‌ను అన్‌మ్యూట్ చేయి</translation>
+<translation id="6150588977291308318">వివరణపట్టి</translation>
<translation id="6164829606128959761">మీటర్</translation>
+<translation id="6166809985690652833">చివరిమాట</translation>
+<translation id="6213469881011901533">పదకోశం</translation>
<translation id="6398862346408813489">నెల ఎంపిక ప్యానెల్‌ను చూపుతుంది</translation>
<translation id="6404546809543547843">ఆడియో సమయ స్క్రబ్బర్</translation>
+<translation id="6453774872122745852">గుర్తింపులు</translation>
<translation id="648732519525291180">సమయం ఎంపిక</translation>
<translation id="6550675742724504774">ఎంపికలు</translation>
-<translation id="6564313821541007458">ఇప్పుడు చిత్రంలో చిత్రం మోడ్‌లో ఉంది</translation>
<translation id="658823671542763450">పూర్తి స్క్రీన్‌లోకి ప్రవేశించు</translation>
<translation id="663493177488814956">ఫీడ్</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">సాధన చిట్కా</translation>
<translation id="6790428901817661496">ప్లే చేయి</translation>
<translation id="6820355525329141109">ప్లగిన్‌ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
+<translation id="6820615603175220800">వివరణపట్టి సూచన</translation>
<translation id="6843725295806269523">మ్యూట్ చేయి</translation>
<translation id="6853785296079745596">సంవృత శీర్షికలను దాచు</translation>
<translation id="6885760532393684712">డైరెక్టరీ</translation>
+<translation id="689129560213475294">ఆఖరిమాట</translation>
<translation id="6934078000481955284">బ్లాక్‌కోట్</translation>
<translation id="6941933287844615239">మీడియా అంశం డౌన్‌లోడ్ చేయి</translation>
<translation id="6989848892321993519">దయచేసి ఈ వచనాన్ని <ph name="MIN_CHARACTERS" /> లేదా అంతకంటే ఎక్కువ అక్షరాలకు పొడిగించండి (ప్రస్తుతం మీరు 1 అక్షరాన్ని ఉపయోగిస్తున్నారు).</translation>
<translation id="709897737746224366">దయచేసి అభ్యర్థించిన ఆకృతీకరణను సరిపోల్చండి.</translation>
+<translation id="7139483182332611405">ముందుమాట</translation>
<translation id="7223624360433298498">గడిచిన సమయం</translation>
<translation id="7263440858009898357">దయచేసి జాబితాలోని ఒక అంశాన్ని ఎంచుకోండి.</translation>
<translation id="727747134524199931">నిలువు వరుస శీర్షిక</translation>
+<translation id="7353453495576941748">సహకారి</translation>
<translation id="7364796246159120393">ఫైల్‌ను ఎంచుకోండి</translation>
<translation id="739024184232394898">ఇతర...</translation>
+<translation id="7405738980073107433">ఎండ్‌నోట్‌లు</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">డౌన్‌లోడ్ చేయి</translation>
+<translation id="7529102961911894712">వెనుకకు తీసుకువెళ్లే లింక్‌</translation>
+<translation id="7647456547678091388">చిట్కా</translation>
+<translation id="7661956066982048809">గ్రాఫిక్స్ పత్రం</translation>
<translation id="7673697353781729403">గంటలు</translation>
+<translation id="7681220483256441252">సూచిక</translation>
<translation id="7720026100085573005">మిగిలి ఉన్న సమయం</translation>
<translation id="7740016676195725605">సంవృత శీర్షికలను ప్రదర్శించడం ఆపివేయి</translation>
<translation id="7740050170769002709">HTML కంటెంట్</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">విభజన</translation>
<translation id="795667975304826397">ఫైల్ ఏదీ ఎంచుకోలేదు</translation>
<translation id="8053789581856978548">శోధన వచనం ఫీల్డ్</translation>
+<translation id="8057695513531652401">గమనిక</translation>
+<translation id="8105797009065549151">గమనిక సూచన</translation>
<translation id="8115662671911883373">సంవృత శీర్షికలను ప్రదర్శించడం ప్రారంభించు</translation>
<translation id="8117451130807776954">ఈ వారం</translation>
<translation id="819205353528511139">చలనచిత్రాన్ని పూర్తి స్క్రీన్ మోడ్‌లో ప్లే చేయి</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">ఉపశీర్షికలు</translation>
<translation id="835897206747267392">చెల్లని విలువ.</translation>
+<translation id="8415319359811155763">భాగం</translation>
<translation id="8433900881053900389">సాధన పట్టీ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ఫైళ్ళు</translation>
<translation id="8451268428117625855">దయచేసి ఒక ఫైల్‌ని ఎంచుకోండి.</translation>
<translation id="8461852803063341183">రేడియో బటన్</translation>
+<translation id="8474886197722836894">అంకితం</translation>
+<translation id="8531739829932800271">తప్పొప్పుల పట్టిక</translation>
<translation id="8534579021159131403">నిమిషాలు</translation>
<translation id="8541249477527128034">మీడియా నియంత్రణ</translation>
+<translation id="8550857728288566671">గ్రాఫిక్స్ చిహ్నం</translation>
<translation id="8583702881314752957">నిర్వచన జాబితా</translation>
<translation id="8597182159515967513">శీర్షిక</translation>
+<translation id="860475260694818407">విషయ పట్టిక</translation>
<translation id="8613126697340063924">రిమోట్ ప్లేబ్యాక్‌ను నియంత్రిస్తుంది</translation>
+<translation id="862370744433916922">ఉపశీర్షిక</translation>
<translation id="8741316211671074806">చిత్రంలో చిత్రం</translation>
<translation id="8750798805984357768">దయచేసి ఈ ఎంపికలలో ఒకదాన్ని ఎంచుకోండి.</translation>
<translation id="8785498733064193001">ప్లేబ్యాక్‌ను ప్రారంభించు</translation>
+<translation id="8808573423886751634">అధ్యాయం</translation>
<translation id="8845239796550121995">ఇప్పుడు మీ టీవీలో ప్రసారం చేస్తోంది</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">వీడియో ప్లేబ్యాక్ ఎర్రర్</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">ఇతర...</translation>
<translation id="9138385573473225930">హెచ్చరిక</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> నుండి ప్రారంభమవుతుంది</translation>
+<translation id="9168329111483466115">ఫుట్‌నోట్</translation>
<translation id="947831847158436616">గడి</translation>
<translation id="966787709310836684">మెను</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_th.xtb b/chromium/content/app/strings/translations/content_strings_th.xtb
index 3edfe6da9e4..b7ec11b7cc2 100644
--- a/chromium/content/app/strings/translations/content_strings_th.xtb
+++ b/chromium/content/app/strings/translations/content_strings_th.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">ส่วนเสริม</translation>
<translation id="1206619573307042055">ตัวอักษรวิ่ง</translation>
<translation id="1206693055195146388">แถบเลื่อน</translation>
+<translation id="1211441953136645838">อ้างอิงท้ายเรื่อง</translation>
<translation id="1281252709823657822">กล่องโต้ตอบ</translation>
+<translation id="1335095011850992622">เครดิต</translation>
<translation id="1342835525016946179">บทความ</translation>
<translation id="1359897965706325498">แบนเนอร์</translation>
<translation id="1589122976691792535">ภูมิภาค</translation>
<translation id="1591562245178063882">เดือนนี้</translation>
<translation id="1637811476055996098">เลือกไฟล์</translation>
+<translation id="1650423536718072820">การเน้นข้อความ</translation>
<translation id="1729654308190250600">โปรดป้อนที่อยู่อีเมลที่ไม่ว่างเปล่า</translation>
<translation id="1758486001363313524">อื่นๆ...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">แผนผังต้นไม้</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">เล่นในอุปกรณ์ระยะไกล</translation>
+<translation id="1907737156431278478">ตัวอย่าง</translation>
<translation id="1921819250265091946">วว</translation>
<translation id="1930711995431081526">สถานะ</translation>
<translation id="1938124657309484470">ค่าต้องเป็น <ph name="MAXIMUM_DATE_OR_TIME" /> หรือก่อนหน้านั้น</translation>
<translation id="1993104285338243655">เปลี่ยนเป็นการมิเรอร์</translation>
<translation id="2060505056492490888">"<ph name="DOT" />" ถูกใช้งานในตำแหน่งที่ไม่ถูกต้องใน "<ph name="INVALIDDOMAIN" />"</translation>
<translation id="2148716181193084225">วันนี้</translation>
+<translation id="2158401438286456825">รายการหน้า</translation>
<translation id="2226276347425096477">โปรดย่อข้อความนี้ให้เหลือไม่เกิน <ph name="MAX_CHARACTERS" /> อักขระ (ขณะนี้ข้อความของคุณมี <ph name="CURRENT_LENGTH" /> อักขระ)</translation>
<translation id="2247351761944213033">สัปดาห์ที่ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">แทร็ก <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">ช่องทำเครื่องหมาย</translation>
+<translation id="2311842470354187719">ตัวแบ่งหน้า</translation>
<translation id="2335594187091864976">เครื่องมือเลือกวันที่และเวลา</translation>
<translation id="248395913932153421">วัน</translation>
<translation id="2507943997699731163">โปรดกรอกฟิลด์นี้</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">เล่น</translation>
<translation id="2613802280814924224">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องคือ <ph name="VALID_VALUE" /></translation>
<translation id="2653659639078652383">ส่ง</translation>
+<translation id="2657045182931379222">ออบเจ็กต์กราฟิก</translation>
<translation id="2674318244760992338">ส่วนท้าย</translation>
<translation id="2709516037105925701">ป้อนอัตโนมัติ</translation>
<translation id="2723001399770238859">เสียง</translation>
@@ -66,34 +73,45 @@
<translation id="3732799496749320381">ดด</translation>
<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
<translation id="3785482301506746191">ตัวควบคุมเวลาของภาพยนตร์</translation>
-<translation id="3808586225841795776">คำหลัก</translation>
+<translation id="3808586225841795776">คีย์เวิร์ด</translation>
<translation id="3822383571486410024">โปรดกรอกข้อความนี้ให้มีอักขระอย่างน้อย <ph name="MIN_CHARACTERS" /> ตัว (ตอนนี้คุณมี <ph name="CURRENT_LENGTH" /> ตัว)</translation>
<translation id="383465348367842624">ส่วนที่ตามด้วย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
<translation id="3846214748874656680">ออกจากการแสดงเต็มหน้าจอ</translation>
+<translation id="3920932319529768807">บทสรุป</translation>
<translation id="3924558731517983934">แอปพลิเคชัน</translation>
+<translation id="3944740393230681990">อารัมภบท</translation>
<translation id="3960700977367013758">แถบเลื่อน</translation>
<translation id="4103419683916926126">มิลลิวินาที</translation>
<translation id="4151657705144244502">กราฟิก</translation>
+<translation id="4193965531860883258">คำนำ</translation>
<translation id="4201051445878709314">แสดงเดือนที่ผ่านมา</translation>
<translation id="421884353938374759">ตัวเลือกสี</translation>
<translation id="4248100235867064564">แถบเมนู</translation>
<translation id="4254339807215791271">ข้อมูลเนื้อหา</translation>
<translation id="4360991593054037559">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องสองรายการคือ <ph name="VALID_VALUE_LOW" /> และ <ph name="VALID_VALUE_HIGHER" /></translation>
+<translation id="4384583879834880242">ถามและตอบ</translation>
<translation id="4413860115965805769">ปุ่มเมนู</translation>
+<translation id="4446524499724042288">ข้อมูลอ้างอิงอภิธานศัพท์</translation>
<translation id="4522570452068850558">รายละเอียด</translation>
<translation id="4597532268155981612">ฟอร์ม</translation>
<translation id="4661075872484491155">แผนผัง</translation>
<translation id="4664250907885839816">ส่วนที่ต่อท้าย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
+<translation id="4668956016107839909">ภาคผนวก</translation>
+<translation id="4742539557769756338">หน้าปก</translation>
<translation id="4757246831282535685">แผงแท็บ</translation>
<translation id="4763480195061959176">วิดีโอ</translation>
<translation id="479989351350248267">ค้นหา</translation>
<translation id="4812940957355064477">โปรดป้อนตัวเลข</translation>
+<translation id="4912536737030637138">รายการบรรณานุกรม</translation>
<translation id="4975562563186953947">เลือกไว้ <ph name="SELECTED_COUNT" /> รายการ</translation>
<translation id="4992066212339426712">เปิดเสียง</translation>
<translation id="49969490063480558">โปรดป้อนส่วนที่ต่อท้าย "<ph name="ATSIGN" />" "<ph name="INVALIDADDRESS" />" นั้นไม่สมบูรณ์</translation>
<translation id="5034860022980953847">ตัวบอกสถานะความคืบหน้า</translation>
+<translation id="5093189678851173835">คำจารึก</translation>
<translation id="5117590920725113268">แสดงเดือนถัดไป</translation>
<translation id="512758898067543763">ส่วนหัวของแถว</translation>
+<translation id="5143125788380636750">ปัจฉิมบท</translation>
+<translation id="5153163864850940242">กำลังเล่นวิดีโอในโหมดการแสดงภาพซ้อนภาพ</translation>
<translation id="5164977714490026579">ค่าต้องมากกว่าหรือเท่ากับ <ph name="MINIMUM" /></translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">โปรดป้อนส่วนหนึ่งโดยตามด้วย "<ph name="ATSIGN" />" "<ph name="INVALIDADDRESS" />" นั้นไม่สมบูรณ์</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">เปิดเสียง</translation>
<translation id="561939826962581046">เวลา</translation>
<translation id="5630795885300617244">แตะ 2 ครั้งที่ด้านขวาหรือซ้ายเพื่อข้ามทีละ 10 วินาที</translation>
+<translation id="5631759159893697722">บทคัดย่อ</translation>
<translation id="5641012560118721995">หยุดเล่นชั่วคราว</translation>
<translation id="5643186887447432888">ปุ่ม</translation>
<translation id="5677946354068040947">ตัวเลือกเพิ่มเติม</translation>
+<translation id="576709008726043716">บทนำ</translation>
<translation id="57838592816432529">ปิดเสียง</translation>
<translation id="5860033963881614850">ปิด</translation>
<translation id="588258955323874662">เต็มหน้าจอ</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">ปี</translation>
<translation id="6023896073578205740">ช่องรายการ</translation>
<translation id="6101327004457443354">เปิดไฟล์เสียง</translation>
+<translation id="6150588977291308318">บรรณานุกรม</translation>
<translation id="6164829606128959761">เมตร</translation>
+<translation id="6166809985690652833">คำแถลงท้ายเล่ม</translation>
+<translation id="6213469881011901533">อภิธานศัพท์</translation>
<translation id="6398862346408813489">แสดงแผงการเลือกเดือน</translation>
<translation id="6404546809543547843">ตัวควบคุมเวลาของเสียง</translation>
+<translation id="6453774872122745852">กิตติกรรมประกาศ</translation>
<translation id="648732519525291180">เครื่องมือเลือกเวลา</translation>
<translation id="6550675742724504774">ตัวเลือก</translation>
-<translation id="6564313821541007458">ขณะนี้อยู่ในโหมดการแสดงภาพซ้อนภาพ</translation>
<translation id="658823671542763450">เข้าสู่โหมดเต็มหน้าจอ</translation>
<translation id="663493177488814956">ฟีด</translation>
<translation id="6637586476836377253">บันทึก</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">เคล็ดลับเครื่องมือ</translation>
<translation id="6790428901817661496">เล่น</translation>
<translation id="6820355525329141109">ไม่สามารถโหลดปลั๊กอิน</translation>
+<translation id="6820615603175220800">ข้อมูลอ้างอิงทางบรรณานุกรม</translation>
<translation id="6843725295806269523">ปิดเสียง</translation>
<translation id="6853785296079745596">ซ่อนคำอธิบายภาพ</translation>
<translation id="6885760532393684712">ไดเรกทอรี</translation>
+<translation id="689129560213475294">ข้อมูลทางบรรณานุกรม</translation>
<translation id="6934078000481955284">ข้อความที่ยกมา</translation>
<translation id="6941933287844615239">ดาวน์โหลดสื่อ</translation>
<translation id="6989848892321993519">โปรดกรอกข้อความนี้ให้มีอักขระอย่างน้อย <ph name="MIN_CHARACTERS" /> ตัว (ตอนนี้คุณมี 1 ตัว)</translation>
<translation id="709897737746224366">โปรดจับคู่รูปแบบที่ร้องขอ</translation>
+<translation id="7139483182332611405">ส่วนนำ</translation>
<translation id="7223624360433298498">เวลาที่ผ่านไป</translation>
<translation id="7263440858009898357">โปรดเลือกรายการจากหน้ารายการ</translation>
<translation id="727747134524199931">ส่วนหัวคอลัมน์</translation>
+<translation id="7353453495576941748">เครดิต</translation>
<translation id="7364796246159120393">เลือกไฟล์</translation>
<translation id="739024184232394898">อื่นๆ...</translation>
+<translation id="7405738980073107433">อ้างอิงท้ายเรื่อง</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">แท็บ</translation>
<translation id="7514365320538308">ดาวน์โหลด</translation>
+<translation id="7529102961911894712">ลิงก์กลับมาที่หน้า</translation>
+<translation id="7647456547678091388">เคล็ดลับ</translation>
+<translation id="7661956066982048809">เอกสารกราฟิก</translation>
<translation id="7673697353781729403">ชั่วโมง</translation>
+<translation id="7681220483256441252">ดัชนี</translation>
<translation id="7720026100085573005">เวลาที่เหลือ</translation>
<translation id="7740016676195725605">หยุดแสดงคำอธิบายภาพ</translation>
<translation id="7740050170769002709">เนื้อหา HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">ตัวแยก</translation>
<translation id="795667975304826397">ไม่ได้เลือกไฟล์ใด</translation>
<translation id="8053789581856978548">ช่องข้อความค้นหา</translation>
+<translation id="8057695513531652401">ประกาศ</translation>
+<translation id="8105797009065549151">ข้อมูลอ้างอิงหมายเหตุ</translation>
<translation id="8115662671911883373">เริ่มแสดงคำอธิบายภาพ</translation>
<translation id="8117451130807776954">สัปดาห์นี้</translation>
<translation id="819205353528511139">เล่นภาพยนตร์ในโหมดเต็มหน้าจอ</translation>
<translation id="8199524924445686405">ปปปป</translation>
<translation id="8284326494547611709">คำบรรยาย</translation>
<translation id="835897206747267392">ค่าไม่ถูกต้อง</translation>
+<translation id="8415319359811155763">ภาค</translation>
<translation id="8433900881053900389">แถบเครื่องมือ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ไฟล์</translation>
<translation id="8451268428117625855">โปรดเลือกไฟล์</translation>
<translation id="8461852803063341183">ปุ่มตัวเลือก</translation>
+<translation id="8474886197722836894">คำอุทิศ</translation>
+<translation id="8531739829932800271">ข้อผิดพลาด</translation>
<translation id="8534579021159131403">นาที</translation>
<translation id="8541249477527128034">การควบคุมสื่อ</translation>
+<translation id="8550857728288566671">สัญลักษณ์กราฟิก</translation>
<translation id="8583702881314752957">รายการคำจำกัดความ</translation>
<translation id="8597182159515967513">ส่วนหัว</translation>
+<translation id="860475260694818407">สารบัญ</translation>
<translation id="8613126697340063924">ควบคุมการเล่นระยะไกล</translation>
+<translation id="862370744433916922">คำบรรยาย</translation>
<translation id="8741316211671074806">การแสดงภาพซ้อนภาพ</translation>
<translation id="8750798805984357768">โปรดเลือกตัวเลือกอย่างหนึ่งอย่างใดเหล่านี้</translation>
<translation id="8785498733064193001">เริ่มเล่น</translation>
+<translation id="8808573423886751634">บท</translation>
<translation id="8845239796550121995">ตอนนี้กำลังแคสต์ไปยัง TV</translation>
<translation id="8851136666856101339">หลัก</translation>
<translation id="8875657656876809964">ข้อผิดพลาดในการเล่นวิดีโอ</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">อื่นๆ...</translation>
<translation id="9138385573473225930">การแจ้งเตือน</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> เริ่มวันที่ <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">เชิงอรรถ</translation>
<translation id="947831847158436616">เซลล์</translation>
<translation id="966787709310836684">เมนู</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_tr.xtb b/chromium/content/app/strings/translations/content_strings_tr.xtb
index cfe8f034e66..109fca3bd36 100644
--- a/chromium/content/app/strings/translations/content_strings_tr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_tr.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">tamamlayıcı</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">kaydırma çubuğu</translation>
+<translation id="1211441953136645838">son not</translation>
<translation id="1281252709823657822">iletişim kutusu</translation>
+<translation id="1335095011850992622">katkıda bulunanlar</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">bölge</translation>
<translation id="1591562245178063882">Bu ay</translation>
<translation id="1637811476055996098">Dosyaları Seç</translation>
+<translation id="1650423536718072820">alıntı</translation>
<translation id="1729654308190250600">Lütfen e-posta adresini boş bırakmayın.</translation>
<translation id="1758486001363313524">Diğer...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">ağaç tablo</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">uzaktan cihazda oynat</translation>
+<translation id="1907737156431278478">örnek</translation>
<translation id="1921819250265091946">gg</translation>
<translation id="1930711995431081526">durum</translation>
<translation id="1938124657309484470">Değer <ph name="MAXIMUM_DATE_OR_TIME" /> veya daha geri olmalıdır.</translation>
<translation id="1993104285338243655">Yansıtmaya geçildi</translation>
<translation id="2060505056492490888">"<ph name="DOT" />", "<ph name="INVALIDDOMAIN" />" adı içinde yanlış bir konumda kullanılmış.</translation>
<translation id="2148716181193084225">Bugün</translation>
+<translation id="2158401438286456825">sayfa listesi</translation>
<translation id="2226276347425096477">Lütfen bu metni <ph name="MAX_CHARACTERS" /> veya daha az karakter olacak şekilde kısaltın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hafta, <ph name="YEAR" /></translation>
<translation id="2277199496770840904"><ph name="NUMBER" />. parça</translation>
<translation id="2291999235780842123">onay kutusu</translation>
+<translation id="2311842470354187719">sayfa sonu</translation>
<translation id="2335594187091864976">tarih ve saat seçici</translation>
<translation id="248395913932153421">Gün</translation>
<translation id="2507943997699731163">Lütfen bu alanı doldurun.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">oynat</translation>
<translation id="2613802280814924224">Lütfen geçerli bir değer girin. En yakın geçerli değer şudur: <ph name="VALID_VALUE" /></translation>
<translation id="2653659639078652383">Gönder</translation>
+<translation id="2657045182931379222">grafik nesnesi</translation>
<translation id="2674318244760992338">altbilgi</translation>
<translation id="2709516037105925701">Otomatik doldurma</translation>
<translation id="2723001399770238859">ses</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Lütfen bu metni <ph name="MIN_CHARACTERS" /> karakter veya daha fazla olacak şekilde uzatın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
<translation id="383465348367842624">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
<translation id="3846214748874656680">Tam ekran modundan çık</translation>
+<translation id="3920932319529768807">sonuç</translation>
<translation id="3924558731517983934">uygulama</translation>
+<translation id="3944740393230681990">prolog</translation>
<translation id="3960700977367013758">kaydırma çubuğu</translation>
<translation id="4103419683916926126">Milisaniye</translation>
<translation id="4151657705144244502">grafik</translation>
+<translation id="4193965531860883258">önsöz</translation>
<translation id="4201051445878709314">Önceki ayı göster</translation>
<translation id="421884353938374759">renk seçici</translation>
<translation id="4248100235867064564">menü çubuğu</translation>
<translation id="4254339807215791271">içerik bilgileri</translation>
<translation id="4360991593054037559">Lütfen geçerli bir değer girin. En yakın iki geçerli değer şunlardır: <ph name="VALID_VALUE_LOW" /> ve <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Soru-Cevap</translation>
<translation id="4413860115965805769">menü düğmesi</translation>
+<translation id="4446524499724042288">terimler sözlüğü referansı</translation>
<translation id="4522570452068850558">Ayrıntılar</translation>
<translation id="4597532268155981612">form</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
+<translation id="4668956016107839909">ek</translation>
+<translation id="4742539557769756338">kapak</translation>
<translation id="4757246831282535685">sekme paneli</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">ara</translation>
<translation id="4812940957355064477">Lütfen bir sayı girin.</translation>
+<translation id="4912536737030637138">kaynakça girişi</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> tane seçildi</translation>
<translation id="4992066212339426712">Sesi aç</translation>
-<translation id="49969490063480558">Lütfen başına "<ph name="ATSIGN" />" ekleyin. "<ph name="INVALIDADDRESS" />" eksik.</translation>
+<translation id="49969490063480558">Lütfen "<ph name="ATSIGN" />" işaretinden sonra gelen kısmı ekleyin. "<ph name="INVALIDADDRESS" />", tam bir adres değil.</translation>
<translation id="5034860022980953847">ilerleme durumu göstergesi</translation>
+<translation id="5093189678851173835">yazıt</translation>
<translation id="5117590920725113268">Sonraki ayı göster</translation>
<translation id="512758898067543763">satır başlığı</translation>
+<translation id="5143125788380636750">son söz</translation>
+<translation id="5153163864850940242">Bu video Pencere İçinde Pencere modunda oynatılıyor</translation>
<translation id="5164977714490026579">Değer <ph name="MINIMUM" /> veya daha büyük olmalıdır.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Lütfen başına "<ph name="ATSIGN" />" ekleyin. "<ph name="INVALIDADDRESS" />" adresi eksik.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">sesi aç</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">10 sn. atlamak için sola veya sağa iki kez dokunun</translation>
+<translation id="5631759159893697722">özet</translation>
<translation id="5641012560118721995">oynatmayı duraklat</translation>
<translation id="5643186887447432888">düğme</translation>
<translation id="5677946354068040947">diğer seçenekler</translation>
+<translation id="576709008726043716">giriş</translation>
<translation id="57838592816432529">Sesi kapat</translation>
<translation id="5860033963881614850">Kapalı</translation>
<translation id="588258955323874662">Tam ekran</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Yıl</translation>
<translation id="6023896073578205740">liste kutusu</translation>
<translation id="6101327004457443354">ses kanalını aç</translation>
+<translation id="6150588977291308318">kaynakça</translation>
<translation id="6164829606128959761">ölçüm aracı</translation>
+<translation id="6166809985690652833">sonsöz</translation>
+<translation id="6213469881011901533">terimler sözlüğü</translation>
<translation id="6398862346408813489">Ay seçim panelini göster</translation>
<translation id="6404546809543547843">ses zaman çizelgesi temizleyici</translation>
+<translation id="6453774872122745852">teşekkür</translation>
<translation id="648732519525291180">zaman seçici</translation>
<translation id="6550675742724504774">Seçenekler</translation>
-<translation id="6564313821541007458">Şimdi Pencere içinde Pencere modunda</translation>
<translation id="658823671542763450">tam ekrana geç</translation>
<translation id="663493177488814956">kartlar</translation>
<translation id="6637586476836377253">log</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">ipucu</translation>
<translation id="6790428901817661496">Oynat</translation>
<translation id="6820355525329141109">Eklenti yüklenemedi.</translation>
+<translation id="6820615603175220800">kaynakça referansı</translation>
<translation id="6843725295806269523">sesi kapat</translation>
<translation id="6853785296079745596">alt yazıları gizle</translation>
<translation id="6885760532393684712">dizin</translation>
+<translation id="689129560213475294">künye</translation>
<translation id="6934078000481955284">blok alıntı</translation>
<translation id="6941933287844615239">medyayı indir</translation>
<translation id="6989848892321993519">Lütfen bu metni <ph name="MIN_CHARACTERS" /> karakter veya daha fazla olacak şekilde uzatın (şu anda 1 karakter kullanıyorsunuz).</translation>
<translation id="709897737746224366">Lütfen istenen biçimi eşleştirin.</translation>
+<translation id="7139483182332611405">önsöz</translation>
<translation id="7223624360433298498">geçen süre</translation>
<translation id="7263440858009898357">Lütfen listeden bir öğe seçin.</translation>
<translation id="727747134524199931">sütun başlığı</translation>
+<translation id="7353453495576941748">katkıda bulunan</translation>
<translation id="7364796246159120393">Dosya Seç</translation>
<translation id="739024184232394898">Diğer...</translation>
+<translation id="7405738980073107433">son notlar</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">İndir</translation>
+<translation id="7529102961911894712">geri bağlantı</translation>
+<translation id="7647456547678091388">ipucu</translation>
+<translation id="7661956066982048809">grafik dokümanı</translation>
<translation id="7673697353781729403">Saat</translation>
+<translation id="7681220483256441252">dizin</translation>
<translation id="7720026100085573005">kalan süre</translation>
<translation id="7740016676195725605">altyazıların görüntülenmesini durdur</translation>
<translation id="7740050170769002709">HTML içeriği</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">ayırıcı</translation>
<translation id="795667975304826397">Dosya seçilmedi</translation>
<translation id="8053789581856978548">arama metni alanı</translation>
+<translation id="8057695513531652401">bildirim</translation>
+<translation id="8105797009065549151">not referansı</translation>
<translation id="8115662671911883373">altyazıları görüntülemeye başla</translation>
<translation id="8117451130807776954">Bu hafta</translation>
<translation id="819205353528511139">filmi tam ekran modunda oynat</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Altyazılar</translation>
<translation id="835897206747267392">Geçersiz değer.</translation>
+<translation id="8415319359811155763">bölüm</translation>
<translation id="8433900881053900389">araç çubuğu</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> dosya</translation>
<translation id="8451268428117625855">Lütfen bir dosya seçin.</translation>
<translation id="8461852803063341183">radyo düğmesi</translation>
+<translation id="8474886197722836894">ithaf</translation>
+<translation id="8531739829932800271">yazım hataları</translation>
<translation id="8534579021159131403">Dakika</translation>
<translation id="8541249477527128034">medya kontrolü</translation>
+<translation id="8550857728288566671">grafik sembolü</translation>
<translation id="8583702881314752957">tanım listesi</translation>
<translation id="8597182159515967513">başlık</translation>
+<translation id="860475260694818407">içindekiler</translation>
<translation id="8613126697340063924">uzaktan oynatmayı kontrol et</translation>
+<translation id="862370744433916922">alt başlık</translation>
<translation id="8741316211671074806">Pencere İçinde Pencere</translation>
<translation id="8750798805984357768">Lütfen bu seçeneklerden birini belirleyin.</translation>
<translation id="8785498733064193001">oynatmayı başlat</translation>
+<translation id="8808573423886751634">bölüm</translation>
<translation id="8845239796550121995">Şimdi TV'nize yayınlanıyor</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8875657656876809964">Video oynatma hatası</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Diğer...</translation>
<translation id="9138385573473225930">uyarı</translation>
<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> tarihinde başlayan <ph name="WEEK" /></translation>
+<translation id="9168329111483466115">dipnot</translation>
<translation id="947831847158436616">hücre</translation>
<translation id="966787709310836684">menü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_uk.xtb b/chromium/content/app/strings/translations/content_strings_uk.xtb
index 79a10ad7290..1c2f2e07482 100644
--- a/chromium/content/app/strings/translations/content_strings_uk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_uk.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">додатково</translation>
<translation id="1206619573307042055">область виділення</translation>
<translation id="1206693055195146388">повзунок</translation>
+<translation id="1211441953136645838">кінцева виноска</translation>
<translation id="1281252709823657822">діалогове вікно</translation>
+<translation id="1335095011850992622">подяки</translation>
<translation id="1342835525016946179">стаття</translation>
<translation id="1359897965706325498">банер</translation>
<translation id="1589122976691792535">регіон</translation>
<translation id="1591562245178063882">Цей місяць</translation>
<translation id="1637811476055996098">Вибрати файли</translation>
+<translation id="1650423536718072820">цитата</translation>
<translation id="1729654308190250600">Введіть електронну адресу.</translation>
<translation id="1758486001363313524">Інші...</translation>
<translation id="1806710327868736751">вікно сповіщення</translation>
<translation id="1821985195704844674">сітка дерева</translation>
<translation id="1822429046913737220">д.п./п.п.</translation>
<translation id="1832974991323546415">відтворити на віддаленому пристрої</translation>
+<translation id="1907737156431278478">приклад</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">статус</translation>
<translation id="1938124657309484470">Має бути <ph name="MAXIMUM_DATE_OR_TIME" /> або раніша дата.</translation>
<translation id="1993104285338243655">Змінено на дзеркалювання</translation>
<translation id="2060505056492490888">Символ "<ph name="DOT" />" у "<ph name="INVALIDDOMAIN" />" використано неправильно.</translation>
<translation id="2148716181193084225">Сьогодні</translation>
+<translation id="2158401438286456825">список сторінок</translation>
<translation id="2226276347425096477">Скоротіть текст до такої кількості символів або менше: <ph name="MAX_CHARACTERS" /> (наразі використано символів: <ph name="CURRENT_LENGTH" />).</translation>
<translation id="2247351761944213033">Тиждень <ph name="WEEKNUMBER" />, <ph name="YEAR" /> р.</translation>
<translation id="2277199496770840904">Композиція <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">прапорець</translation>
+<translation id="2311842470354187719">розрив сторінки</translation>
<translation id="2335594187091864976">засіб вибору дати й часу</translation>
<translation id="248395913932153421">День</translation>
<translation id="2507943997699731163">Заповніть це поле.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">відтворити</translation>
<translation id="2613802280814924224">Введіть дійсне значення. Найближче дійсне значення: <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Надіслати</translation>
+<translation id="2657045182931379222">графічний об’єкт</translation>
<translation id="2674318244760992338">нижній колонтитул</translation>
<translation id="2709516037105925701">Автозаповнення</translation>
<translation id="2723001399770238859">аудіо</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">У тексті має бути на менше <ph name="MIN_CHARACTERS" /> символів (ви ввели <ph name="CURRENT_LENGTH" /> символів).</translation>
<translation id="383465348367842624">Частина перед знаком "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
<translation id="3846214748874656680">Вийти з повноекранного режиму</translation>
+<translation id="3920932319529768807">висновок</translation>
<translation id="3924558731517983934">додаток</translation>
+<translation id="3944740393230681990">пролог</translation>
<translation id="3960700977367013758">смуга прокрутки</translation>
<translation id="4103419683916926126">Мілісекунди</translation>
<translation id="4151657705144244502">зображення</translation>
+<translation id="4193965531860883258">передмова</translation>
<translation id="4201051445878709314">Показати попередній місяць</translation>
<translation id="421884353938374759">вибір кольору</translation>
<translation id="4248100235867064564">панель меню</translation>
<translation id="4254339807215791271">інформація про вміст</translation>
<translation id="4360991593054037559">Введіть дійсне значення. Два найближчі дійсні значення: <ph name="VALID_VALUE_LOW" /> і <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Запитання</translation>
<translation id="4413860115965805769">кнопка меню</translation>
+<translation id="4446524499724042288">посилання на глосарій</translation>
<translation id="4522570452068850558">Деталі</translation>
<translation id="4597532268155981612">форма</translation>
<translation id="4661075872484491155">дерево</translation>
<translation id="4664250907885839816">Частина після знака "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">додаток</translation>
+<translation id="4742539557769756338">обкладинка</translation>
<translation id="4757246831282535685">панель вкладок</translation>
<translation id="4763480195061959176">відео</translation>
<translation id="479989351350248267">пошук</translation>
<translation id="4812940957355064477">Введіть число.</translation>
+<translation id="4912536737030637138">бібліографічний запис</translation>
<translation id="4975562563186953947">Вибрано <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Увімкнути звук</translation>
<translation id="49969490063480558">Введіть частину електронної адреси після знака "<ph name="ATSIGN" />". Електронна адреса "<ph name="INVALIDADDRESS" />" неповна.</translation>
<translation id="5034860022980953847">індикатор перебігу</translation>
+<translation id="5093189678851173835">епіграф</translation>
<translation id="5117590920725113268">Показати наступний місяць</translation>
<translation id="512758898067543763">заголовок рядка</translation>
+<translation id="5143125788380636750">епілог</translation>
+<translation id="5153163864850940242">Це відео відтворюється в режимі "Картинка в картинці"</translation>
<translation id="5164977714490026579">Значення має бути більшим або дорівнювати <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> Пб</translation>
<translation id="5307600278924710095">Введіть частину електронної адреси до знака "<ph name="ATSIGN" />". Електронна адреса "<ph name="INVALIDADDRESS" />" неповна.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">увімкнути звук</translation>
<translation id="561939826962581046">час</translation>
<translation id="5630795885300617244">Двічі торкніться ліворуч або праворуч, щоб пропустити 10 с</translation>
+<translation id="5631759159893697722">автореферат</translation>
<translation id="5641012560118721995">призупинити відтворення</translation>
<translation id="5643186887447432888">кнопка</translation>
<translation id="5677946354068040947">більше опцій</translation>
+<translation id="576709008726043716">вступ</translation>
<translation id="57838592816432529">Вимкнути звук</translation>
<translation id="5860033963881614850">Вимк.</translation>
<translation id="588258955323874662">Повноекранний режим</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Рік</translation>
<translation id="6023896073578205740">вікно списку</translation>
<translation id="6101327004457443354">увімкнути звукову доріжку</translation>
+<translation id="6150588977291308318">бібліографія</translation>
<translation id="6164829606128959761">вимірювач</translation>
+<translation id="6166809985690652833">післямова</translation>
+<translation id="6213469881011901533">глосарій</translation>
<translation id="6398862346408813489">Показати панель вибору місяців</translation>
<translation id="6404546809543547843">повзунок часу відтворення аудіо</translation>
+<translation id="6453774872122745852">слова подяки</translation>
<translation id="648732519525291180">засіб вибору часу</translation>
<translation id="6550675742724504774">Параметри</translation>
-<translation id="6564313821541007458">Зараз у режимі "Картинка в картинці"</translation>
<translation id="658823671542763450">увійти в повноекранний режим</translation>
<translation id="663493177488814956">стрічка</translation>
<translation id="6637586476836377253">журнал</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">підказка</translation>
<translation id="6790428901817661496">Відтворити</translation>
<translation id="6820355525329141109">Не вдалося завантажити плагін.</translation>
+<translation id="6820615603175220800">посилання на бібліографію</translation>
<translation id="6843725295806269523">вимкнути звук</translation>
<translation id="6853785296079745596">сховати приховані субтирти</translation>
<translation id="6885760532393684712">каталог</translation>
+<translation id="689129560213475294">емблема видавництва</translation>
<translation id="6934078000481955284">цитата</translation>
<translation id="6941933287844615239">завантажити медіафайл</translation>
<translation id="6989848892321993519">У тексті має бути не менше стількох символів: <ph name="MIN_CHARACTERS" />. Наразі ви ввели 1 символ.</translation>
<translation id="709897737746224366">Виберіть потрібний формат.</translation>
+<translation id="7139483182332611405">передмова</translation>
<translation id="7223624360433298498">минуло часу</translation>
<translation id="7263440858009898357">Виберіть елемент зі списку.</translation>
<translation id="727747134524199931">заголовок стовпця</translation>
+<translation id="7353453495576941748">подяка</translation>
<translation id="7364796246159120393">Вибрати файл</translation>
<translation id="739024184232394898">Інші...</translation>
+<translation id="7405738980073107433">кінцеві виноски</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> ТБ</translation>
<translation id="7491962110804786152">вкладка</translation>
<translation id="7514365320538308">Завантажити</translation>
+<translation id="7529102961911894712">зворотне посилання</translation>
+<translation id="7647456547678091388">порада</translation>
+<translation id="7661956066982048809">графічний документ</translation>
<translation id="7673697353781729403">Години</translation>
+<translation id="7681220483256441252">покажчик</translation>
<translation id="7720026100085573005">залишилось часу</translation>
<translation id="7740016676195725605">сховати приховані субтитри</translation>
<translation id="7740050170769002709">Вміст HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">розділювач</translation>
<translation id="795667975304826397">Файл не вибрано</translation>
<translation id="8053789581856978548">текстове поле пошуку</translation>
+<translation id="8057695513531652401">примітка</translation>
+<translation id="8105797009065549151">посилання на примітку</translation>
<translation id="8115662671911883373">показати приховані субтитри</translation>
<translation id="8117451130807776954">Цей тиждень</translation>
<translation id="819205353528511139">відтворити фільм у повноекранному режимі</translation>
<translation id="8199524924445686405">рррр</translation>
<translation id="8284326494547611709">Субтитри</translation>
<translation id="835897206747267392">Недійсне значення</translation>
+<translation id="8415319359811155763">частина</translation>
<translation id="8433900881053900389">панель інструментів</translation>
<translation id="8444882422881193423">файлів: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Виберіть файл.</translation>
<translation id="8461852803063341183">перемикач</translation>
+<translation id="8474886197722836894">присвята</translation>
+<translation id="8531739829932800271">перелік описок</translation>
<translation id="8534579021159131403">Хвилини</translation>
<translation id="8541249477527128034">елемент керування мультимедіа</translation>
+<translation id="8550857728288566671">графічний символ</translation>
<translation id="8583702881314752957">список визначень</translation>
<translation id="8597182159515967513">заголовок</translation>
+<translation id="860475260694818407">зміст</translation>
<translation id="8613126697340063924">керувати віддаленим відтворенням</translation>
+<translation id="862370744433916922">підзаголовок</translation>
<translation id="8741316211671074806">Картинка в картинці</translation>
<translation id="8750798805984357768">Виберіть один із запропонованих варіантів.</translation>
<translation id="8785498733064193001">розпочати відтворення</translation>
+<translation id="8808573423886751634">розділ</translation>
<translation id="8845239796550121995">Транслюється на телевізор</translation>
<translation id="8851136666856101339">головний</translation>
<translation id="8875657656876809964">Помилка відтворення відео</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Інші...</translation>
<translation id="9138385573473225930">сповіщення</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, починається <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">виноска</translation>
<translation id="947831847158436616">клітинка</translation>
<translation id="966787709310836684">меню</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_vi.xtb b/chromium/content/app/strings/translations/content_strings_vi.xtb
index 7f5639ae1ac..92c65db3683 100644
--- a/chromium/content/app/strings/translations/content_strings_vi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_vi.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">bổ sung</translation>
<translation id="1206619573307042055">bảng chữ chạy</translation>
<translation id="1206693055195146388">thanh trượt</translation>
+<translation id="1211441953136645838">chú thích cuối</translation>
<translation id="1281252709823657822">hộp thoại</translation>
+<translation id="1335095011850992622">ghi nhận tác giả</translation>
<translation id="1342835525016946179">bài viết</translation>
<translation id="1359897965706325498">biểu ngữ</translation>
<translation id="1589122976691792535">khu vực</translation>
<translation id="1591562245178063882">Tháng này</translation>
<translation id="1637811476055996098">Chọn tệp</translation>
+<translation id="1650423536718072820">đoạn trích dẫn</translation>
<translation id="1729654308190250600">Vui lòng nhập địa chỉ email không trống.</translation>
<translation id="1758486001363313524">Khác...</translation>
<translation id="1806710327868736751">alert_dialog</translation>
<translation id="1821985195704844674">lưới dạng cây</translation>
<translation id="1822429046913737220">SA/CH</translation>
<translation id="1832974991323546415">phát trên thiết bị từ xa</translation>
+<translation id="1907737156431278478">ví dụ</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">trạng thái</translation>
<translation id="1938124657309484470">Giá trị phải là <ph name="MAXIMUM_DATE_OR_TIME" /> hoặc sớm hơn.</translation>
<translation id="1993104285338243655">Đã chuyển sang chế độ phản chiếu</translation>
<translation id="2060505056492490888">'<ph name="DOT" />' bị sử dụng sai vị trí trong '<ph name="INVALIDDOMAIN" />'.</translation>
<translation id="2148716181193084225">Hôm nay</translation>
+<translation id="2158401438286456825">danh sách trang</translation>
<translation id="2226276347425096477">Hãy cắt ngắn văn bản này thành <ph name="MAX_CHARACTERS" /> ký tự hoặc ít hơn (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
<translation id="2247351761944213033">Tuần <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2277199496770840904">Bản nhạc <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">hộp kiểm</translation>
+<translation id="2311842470354187719">ngắt trang</translation>
<translation id="2335594187091864976">bộ chọn ngày và giờ</translation>
<translation id="248395913932153421">Ngày</translation>
<translation id="2507943997699731163">Vui lòng điền vào trường này.</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">phát</translation>
<translation id="2613802280814924224">Vui lòng nhập giá trị hợp lệ. Giá trị hợp lệ gần nhất là <ph name="VALID_VALUE" />.</translation>
<translation id="2653659639078652383">Gửi</translation>
+<translation id="2657045182931379222">đối tượng đồ họa</translation>
<translation id="2674318244760992338">chân trang</translation>
<translation id="2709516037105925701">Tự động điền</translation>
<translation id="2723001399770238859">âm thanh</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">Hãy kéo dài văn bản này thành <ph name="MIN_CHARACTERS" /> ký tự trở lên (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
<translation id="383465348367842624">Phần đứng trước '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
<translation id="3846214748874656680">Thoát chế độ toàn màn hình</translation>
+<translation id="3920932319529768807">kết luận</translation>
<translation id="3924558731517983934">ứng dụng</translation>
+<translation id="3944740393230681990">phần mở đầu</translation>
<translation id="3960700977367013758">thanh cuộn</translation>
<translation id="4103419683916926126">Mili giây</translation>
<translation id="4151657705144244502">hình ảnh</translation>
+<translation id="4193965531860883258">lời tựa</translation>
<translation id="4201051445878709314">Hiển thị tháng trước</translation>
<translation id="421884353938374759">công cụ chọn màu</translation>
<translation id="4248100235867064564">thanh menu</translation>
<translation id="4254339807215791271">thông tin nội dung</translation>
<translation id="4360991593054037559">Vui lòng nhập giá trị hợp lệ. Hai giá trị hợp lệ gần nhất là <ph name="VALID_VALUE_LOW" /> và <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Giải đáp</translation>
<translation id="4413860115965805769">nút menu</translation>
+<translation id="4446524499724042288">tham chiếu bảng thuật ngữ</translation>
<translation id="4522570452068850558">Chi tiết</translation>
<translation id="4597532268155981612">biểu mẫu</translation>
<translation id="4661075872484491155">cây</translation>
<translation id="4664250907885839816">Phần đứng sau '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">phụ lục</translation>
+<translation id="4742539557769756338">trang bìa</translation>
<translation id="4757246831282535685">bảng điều khiển tab</translation>
<translation id="4763480195061959176">video</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Vui lòng nhập một số.</translation>
+<translation id="4912536737030637138">mục nhập danh mục</translation>
<translation id="4975562563186953947">Đã chọn <ph name="SELECTED_COUNT" /></translation>
<translation id="4992066212339426712">Bật âm thanh</translation>
<translation id="49969490063480558">Vui lòng nhập phần đứng sau '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' không hoàn chỉnh.</translation>
<translation id="5034860022980953847">chỉ báo tiến trình</translation>
+<translation id="5093189678851173835">lời đề từ</translation>
<translation id="5117590920725113268">Hiển thị tháng tiếp theo</translation>
<translation id="512758898067543763">tiêu đề hàng</translation>
+<translation id="5143125788380636750">lời kết</translation>
+<translation id="5153163864850940242">Video này đang phát ở chế độ Hình trong hình</translation>
<translation id="5164977714490026579">Giá trị phải lớn hơn hoặc bằng <ph name="MINIMUM" />.</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">Vui lòng nhập phần đứng trước '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' không hoàn chỉnh.</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">bật tiếng</translation>
<translation id="561939826962581046">thời gian</translation>
<translation id="5630795885300617244">Nhấn đúp vào bên trái hoặc phải để bỏ qua sau 10 giây</translation>
+<translation id="5631759159893697722">bản tóm tắt</translation>
<translation id="5641012560118721995">tạm dừng phát lại</translation>
<translation id="5643186887447432888">nút</translation>
<translation id="5677946354068040947">tùy chọn khác</translation>
+<translation id="576709008726043716">giới thiệu</translation>
<translation id="57838592816432529">Tắt tiếng</translation>
<translation id="5860033963881614850">Tắt</translation>
<translation id="588258955323874662">Toàn màn hình</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">Năm</translation>
<translation id="6023896073578205740">hộp danh sách</translation>
<translation id="6101327004457443354">bật tiếng bản âm thanh</translation>
+<translation id="6150588977291308318">danh mục</translation>
<translation id="6164829606128959761">thước đo</translation>
+<translation id="6166809985690652833">lời bạt</translation>
+<translation id="6213469881011901533">bảng thuật ngữ</translation>
<translation id="6398862346408813489">Hiển thị bảng lựa chọn tháng</translation>
<translation id="6404546809543547843">trình kiểm soát thời gian âm thanh</translation>
+<translation id="6453774872122745852">lời cảm ơn</translation>
<translation id="648732519525291180">bộ chọn giờ</translation>
<translation id="6550675742724504774">Tùy chọn</translation>
-<translation id="6564313821541007458">Hiện đang ở chế độ hình trong hình</translation>
<translation id="658823671542763450">vào chế độ toàn màn hình</translation>
<translation id="663493177488814956">nguồn cấp dữ liệu</translation>
<translation id="6637586476836377253">nhật ký</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">chú giải công cụ</translation>
<translation id="6790428901817661496">Phát</translation>
<translation id="6820355525329141109">Không thể tải plugin.</translation>
+<translation id="6820615603175220800">tham chiếu danh mục</translation>
<translation id="6843725295806269523">tắt tiếng</translation>
<translation id="6853785296079745596">ẩn phụ đề chi tiết</translation>
<translation id="6885760532393684712">thư mục</translation>
+<translation id="689129560213475294">lời ghi cuối sách</translation>
<translation id="6934078000481955284">khung trích dẫn</translation>
<translation id="6941933287844615239">tải xuống phương tiện</translation>
<translation id="6989848892321993519">Vui lòng kéo dài văn bản này thành <ph name="MIN_CHARACTERS" /> ký tự trở lên (bạn hiện đang sử dụng 1 ký tự).</translation>
<translation id="709897737746224366">Vui lòng khớp với định dạng được yêu cầu.</translation>
+<translation id="7139483182332611405">lời nói đầu</translation>
<translation id="7223624360433298498">thời gian trôi qua</translation>
<translation id="7263440858009898357">Vui lòng chọn một mục trong danh sách.</translation>
<translation id="727747134524199931">tiêu đề cột</translation>
+<translation id="7353453495576941748">ghi nhận tác giả</translation>
<translation id="7364796246159120393">Chọn tệp</translation>
<translation id="739024184232394898">Khác...</translation>
+<translation id="7405738980073107433">chú thích cuối</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">tab</translation>
<translation id="7514365320538308">Tải xuống</translation>
+<translation id="7529102961911894712">liên kết ngược</translation>
+<translation id="7647456547678091388">mẹo</translation>
+<translation id="7661956066982048809">tài liệu đồ họa</translation>
<translation id="7673697353781729403">Giờ</translation>
+<translation id="7681220483256441252">chú dẫn</translation>
<translation id="7720026100085573005">thời gian còn lại</translation>
<translation id="7740016676195725605">ngừng hiển thị phụ đề chi tiết</translation>
<translation id="7740050170769002709">Nội dung HTML</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">bộ chia</translation>
<translation id="795667975304826397">Không có tệp nào được chọn</translation>
<translation id="8053789581856978548">trường văn bản tìm kiếm</translation>
+<translation id="8057695513531652401">lưu ý</translation>
+<translation id="8105797009065549151">tham chiếu chú thích</translation>
<translation id="8115662671911883373">bắt đầu hiển thị phụ đề chi tiết</translation>
<translation id="8117451130807776954">Tuần này</translation>
<translation id="819205353528511139">phát phim ở chế độ toàn màn hình</translation>
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Phụ đề</translation>
<translation id="835897206747267392">Giá trị không hợp lệ.</translation>
+<translation id="8415319359811155763">phần</translation>
<translation id="8433900881053900389">thanh công cụ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tệp</translation>
<translation id="8451268428117625855">Vui lòng chọn một tệp.</translation>
<translation id="8461852803063341183">nút radio</translation>
+<translation id="8474886197722836894">lời đề tặng</translation>
+<translation id="8531739829932800271">bản đính chính</translation>
<translation id="8534579021159131403">Phút</translation>
<translation id="8541249477527128034">kiểm soát phương tiện</translation>
+<translation id="8550857728288566671">biểu tượng đồ họa</translation>
<translation id="8583702881314752957">danh sách định nghĩa</translation>
<translation id="8597182159515967513">đầu đề</translation>
+<translation id="860475260694818407">mục lục</translation>
<translation id="8613126697340063924">điều khiển phát lại từ xa</translation>
+<translation id="862370744433916922">phụ đề</translation>
<translation id="8741316211671074806">Chế độ hình trong hình</translation>
<translation id="8750798805984357768">Vui lòng chọn một trong các tùy chọn sau.</translation>
<translation id="8785498733064193001">bắt đầu phát lại</translation>
+<translation id="8808573423886751634">chương</translation>
<translation id="8845239796550121995">Hiện đang truyền tới TV của bạn</translation>
<translation id="8851136666856101339">chính</translation>
<translation id="8875657656876809964">Lỗi phát lại video</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">Khác...</translation>
<translation id="9138385573473225930">thông báo</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, bắt đầu vào <ph name="WEEK_START_DATE" /></translation>
+<translation id="9168329111483466115">chú thích cuối trang</translation>
<translation id="947831847158436616">ô</translation>
<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
index b582ad3abda..d6d7b75efc6 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">补充内容</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">滑块</translation>
+<translation id="1211441953136645838">尾注</translation>
<translation id="1281252709823657822">对话框</translation>
+<translation id="1335095011850992622">参与者名单</translation>
<translation id="1342835525016946179">文章标记</translation>
<translation id="1359897965706325498">横幅</translation>
<translation id="1589122976691792535">区域</translation>
<translation id="1591562245178063882">本月</translation>
<translation id="1637811476055996098">选择文件</translation>
+<translation id="1650423536718072820">重要引述</translation>
<translation id="1729654308190250600">请输入有效的电子邮件地址。</translation>
<translation id="1758486001363313524">其他...</translation>
<translation id="1806710327868736751">提醒对话框</translation>
<translation id="1821985195704844674">树状网格</translation>
<translation id="1822429046913737220">上午/下午</translation>
<translation id="1832974991323546415">在远程设备上播放</translation>
+<translation id="1907737156431278478">示例</translation>
<translation id="1921819250265091946">日</translation>
<translation id="1930711995431081526">状态</translation>
<translation id="1938124657309484470">指定的值不得晚于<ph name="MAXIMUM_DATE_OR_TIME" />。</translation>
<translation id="1993104285338243655">已切换到镜像</translation>
<translation id="2060505056492490888">“<ph name="INVALIDDOMAIN" />”中“<ph name="DOT" />”的位置不正确。</translation>
<translation id="2148716181193084225">今天</translation>
+<translation id="2158401438286456825">页面列表</translation>
<translation id="2226276347425096477">请将该文本减少为 <ph name="MAX_CHARACTERS" /> 个字符或更少(您当前使用了 <ph name="CURRENT_LENGTH" /> 个字符)。</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> 年第 <ph name="WEEKNUMBER" /> 周</translation>
<translation id="2277199496770840904">字幕轨 <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">复选框</translation>
+<translation id="2311842470354187719">分页符</translation>
<translation id="2335594187091864976">日期和时间选择器</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">请填写此字段。</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">播放</translation>
<translation id="2613802280814924224">请输入有效值。最接近的有效值为<ph name="VALID_VALUE" />。</translation>
<translation id="2653659639078652383">提交</translation>
+<translation id="2657045182931379222">图形对象</translation>
<translation id="2674318244760992338">页脚</translation>
<translation id="2709516037105925701">自动填充</translation>
<translation id="2723001399770238859">音频</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">请将该文本增加为 <ph name="MIN_CHARACTERS" /> 个字符或更多(您当前使用的是 <ph name="CURRENT_LENGTH" /> 个字符)。</translation>
<translation id="383465348367842624">“<ph name="ATSIGN" />”前面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
<translation id="3846214748874656680">退出全屏模式</translation>
+<translation id="3920932319529768807">总结</translation>
<translation id="3924558731517983934">应用</translation>
+<translation id="3944740393230681990">序言</translation>
<translation id="3960700977367013758">滚动条</translation>
<translation id="4103419683916926126">毫秒</translation>
<translation id="4151657705144244502">图形</translation>
+<translation id="4193965531860883258">前言</translation>
<translation id="4201051445878709314">显示上一个月</translation>
<translation id="421884353938374759">颜色选择器</translation>
<translation id="4248100235867064564">菜单栏</translation>
<translation id="4254339807215791271">内容信息</translation>
<translation id="4360991593054037559">请输入有效值。两个最接近的有效值分别为<ph name="VALID_VALUE_LOW" />和<ph name="VALID_VALUE_HIGHER" />。</translation>
+<translation id="4384583879834880242">问答</translation>
<translation id="4413860115965805769">菜单按钮</translation>
+<translation id="4446524499724042288">词汇表参考资料</translation>
<translation id="4522570452068850558">详细信息</translation>
<translation id="4597532268155981612">表单</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">“<ph name="ATSIGN" />”后面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
+<translation id="4668956016107839909">附录</translation>
+<translation id="4742539557769756338">封面</translation>
<translation id="4757246831282535685">标签面板</translation>
<translation id="4763480195061959176">视频</translation>
<translation id="479989351350248267">搜索</translation>
<translation id="4812940957355064477">请输入一个数字。</translation>
+<translation id="4912536737030637138">参考书目</translation>
<translation id="4975562563186953947">选择了<ph name="SELECTED_COUNT" />项</translation>
<translation id="4992066212339426712">取消静音</translation>
<translation id="49969490063480558">请在“<ph name="ATSIGN" />”后面输入内容。“<ph name="INVALIDADDRESS" />”不完整。</translation>
<translation id="5034860022980953847">进度指示器</translation>
+<translation id="5093189678851173835">题词</translation>
<translation id="5117590920725113268">显示下一个月</translation>
<translation id="512758898067543763">行标题</translation>
+<translation id="5143125788380636750">结语</translation>
+<translation id="5153163864850940242">此视频正在“画中画”模式中播放</translation>
<translation id="5164977714490026579">值必须大于或等于 <ph name="MINIMUM" />。</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">请在“<ph name="ATSIGN" />”前面输入内容。“<ph name="INVALIDADDRESS" />”不完整。</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">取消静音</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">在左侧或右侧点按两次即可跳过 10 秒</translation>
+<translation id="5631759159893697722">摘要</translation>
<translation id="5641012560118721995">暂停播放</translation>
<translation id="5643186887447432888">按钮</translation>
<translation id="5677946354068040947">更多选项</translation>
+<translation id="576709008726043716">简介</translation>
<translation id="57838592816432529">静音</translation>
<translation id="5860033963881614850">关闭</translation>
<translation id="588258955323874662">全屏</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">年</translation>
<translation id="6023896073578205740">列表框</translation>
<translation id="6101327004457443354">取消对音轨静音</translation>
+<translation id="6150588977291308318">参考书目</translation>
<translation id="6164829606128959761">计量条</translation>
+<translation id="6166809985690652833">后记</translation>
+<translation id="6213469881011901533">词汇表</translation>
<translation id="6398862346408813489">显示月份选择面板</translation>
<translation id="6404546809543547843">音频时间进度条</translation>
+<translation id="6453774872122745852">致谢</translation>
<translation id="648732519525291180">时间选择器</translation>
<translation id="6550675742724504774">选项</translation>
-<translation id="6564313821541007458">现为画中画模式</translation>
<translation id="658823671542763450">进入全屏模式</translation>
<translation id="663493177488814956">Feed</translation>
<translation id="6637586476836377253">日志</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">提示</translation>
<translation id="6790428901817661496">播放</translation>
<translation id="6820355525329141109">无法加载插件。</translation>
+<translation id="6820615603175220800">参考书目</translation>
<translation id="6843725295806269523">静音</translation>
<translation id="6853785296079745596">隐藏可选字幕</translation>
<translation id="6885760532393684712">目录</translation>
+<translation id="689129560213475294">版权页</translation>
<translation id="6934078000481955284">引用标记</translation>
<translation id="6941933287844615239">下载媒体</translation>
<translation id="6989848892321993519">请将该内容增加到 <ph name="MIN_CHARACTERS" /> 个或更多字符(目前您使用了 1 个字符)。</translation>
<translation id="709897737746224366">请与所请求的格式保持一致。</translation>
+<translation id="7139483182332611405">序言</translation>
<translation id="7223624360433298498">已播放时间</translation>
<translation id="7263440858009898357">请在列表中选择一项。</translation>
<translation id="727747134524199931">列标题</translation>
+<translation id="7353453495576941748">感谢</translation>
<translation id="7364796246159120393">选择文件</translation>
<translation id="739024184232394898">其他...</translation>
+<translation id="7405738980073107433">尾注</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">标签</translation>
<translation id="7514365320538308">下载</translation>
+<translation id="7529102961911894712">返回链接</translation>
+<translation id="7647456547678091388">提示</translation>
+<translation id="7661956066982048809">图形文档</translation>
<translation id="7673697353781729403">小时</translation>
+<translation id="7681220483256441252">索引</translation>
<translation id="7720026100085573005">剩余时间</translation>
<translation id="7740016676195725605">停止显示可选字幕</translation>
<translation id="7740050170769002709">HTML 内容</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">分离器</translation>
<translation id="795667975304826397">未选择任何文件</translation>
<translation id="8053789581856978548">搜索文本字段</translation>
+<translation id="8057695513531652401">通知</translation>
+<translation id="8105797009065549151">备注参考资料</translation>
<translation id="8115662671911883373">开始显示可选字幕</translation>
<translation id="8117451130807776954">本周</translation>
<translation id="819205353528511139">在全屏模式下播放电影</translation>
<translation id="8199524924445686405"> 年 </translation>
<translation id="8284326494547611709">字幕</translation>
<translation id="835897206747267392">值无效。</translation>
+<translation id="8415319359811155763">部分</translation>
<translation id="8433900881053900389">工具栏</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 个文件</translation>
<translation id="8451268428117625855">请选择一个文件。</translation>
<translation id="8461852803063341183">单选按钮</translation>
+<translation id="8474886197722836894">献辞</translation>
+<translation id="8531739829932800271">勘误表</translation>
<translation id="8534579021159131403">分钟</translation>
<translation id="8541249477527128034">媒体控件</translation>
+<translation id="8550857728288566671">图形符号</translation>
<translation id="8583702881314752957">定义列表</translation>
<translation id="8597182159515967513">标题</translation>
+<translation id="860475260694818407">目录</translation>
<translation id="8613126697340063924">控制远程播放</translation>
+<translation id="862370744433916922">副标题</translation>
<translation id="8741316211671074806">画中画</translation>
<translation id="8750798805984357768">请从这些选项中选择一个。</translation>
<translation id="8785498733064193001">开始播放</translation>
+<translation id="8808573423886751634">章节</translation>
<translation id="8845239796550121995">现在正投射到您的电视上</translation>
<translation id="8851136666856101339">主体内容</translation>
<translation id="8875657656876809964">视频播放出错</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">其他...</translation>
<translation id="9138385573473225930">提醒</translation>
<translation id="9155987714137265666"><ph name="WEEK" />,从 <ph name="WEEK_START_DATE" />开始</translation>
+<translation id="9168329111483466115">脚注</translation>
<translation id="947831847158436616">单元格</translation>
<translation id="966787709310836684">菜单</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
index 6b890983fe9..06fcccba466 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
@@ -10,28 +10,34 @@
<translation id="1188858454923323853">補充</translation>
<translation id="1206619573307042055">marquee</translation>
<translation id="1206693055195146388">滑桿</translation>
+<translation id="1211441953136645838">章節附註</translation>
<translation id="1281252709823657822">對話方塊</translation>
+<translation id="1335095011850992622">參與名單</translation>
<translation id="1342835525016946179">文章</translation>
<translation id="1359897965706325498">橫幅</translation>
<translation id="1589122976691792535">區域</translation>
<translation id="1591562245178063882">本月</translation>
<translation id="1637811476055996098">選擇檔案</translation>
+<translation id="1650423536718072820">重要引述</translation>
<translation id="1729654308190250600">請輸入電子郵件地址。</translation>
<translation id="1758486001363313524">其他...</translation>
<translation id="1806710327868736751">警示對話方塊</translation>
<translation id="1821985195704844674">樹狀目錄網格</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">在遠端裝置上播放</translation>
+<translation id="1907737156431278478">範例</translation>
<translation id="1921819250265091946">日</translation>
<translation id="1930711995431081526">狀態</translation>
<translation id="1938124657309484470">必須輸入 <ph name="MAXIMUM_DATE_OR_TIME" /> 或之前的值。</translation>
<translation id="1993104285338243655">已切換至鏡像模式</translation>
<translation id="2060505056492490888">「<ph name="DOT" />」未放在「<ph name="INVALIDDOMAIN" />」的正確位置。</translation>
<translation id="2148716181193084225">今天</translation>
+<translation id="2158401438286456825">頁面清單</translation>
<translation id="2226276347425096477">請將這段文字刪減至 <ph name="MAX_CHARACTERS" /> 個字元以下 (目前的字元數為 <ph name="CURRENT_LENGTH" /> 個)。</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> 年,第 <ph name="WEEKNUMBER" /> 週</translation>
<translation id="2277199496770840904">曲目 <ph name="NUMBER" /></translation>
<translation id="2291999235780842123">核取方塊</translation>
+<translation id="2311842470354187719">分頁符號</translation>
<translation id="2335594187091864976">日期和時間選擇器</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">請填寫這個欄位。</translation>
@@ -40,6 +46,7 @@
<translation id="2572483411312390101">播放</translation>
<translation id="2613802280814924224">請輸入有效值。最接近的有效值是 <ph name="VALID_VALUE" />。</translation>
<translation id="2653659639078652383">提交</translation>
+<translation id="2657045182931379222">圖形物件</translation>
<translation id="2674318244760992338">頁尾</translation>
<translation id="2709516037105925701">自動填入</translation>
<translation id="2723001399770238859">音訊</translation>
@@ -70,30 +77,41 @@
<translation id="3822383571486410024">請將這段文字加長到 <ph name="MIN_CHARACTERS" /> 個字元以上 (目前使用字元數:<ph name="CURRENT_LENGTH" />)。</translation>
<translation id="383465348367842624">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
<translation id="3846214748874656680">結束全螢幕</translation>
+<translation id="3920932319529768807">結論</translation>
<translation id="3924558731517983934">應用程式</translation>
+<translation id="3944740393230681990">序言</translation>
<translation id="3960700977367013758">捲軸</translation>
<translation id="4103419683916926126">毫秒</translation>
<translation id="4151657705144244502">圖形</translation>
+<translation id="4193965531860883258">前言</translation>
<translation id="4201051445878709314">顯示上一個月</translation>
<translation id="421884353938374759">顏色選擇器</translation>
<translation id="4248100235867064564">選單列</translation>
<translation id="4254339807215791271">內容資訊</translation>
<translation id="4360991593054037559">請輸入有效值。最接近的兩個有效值分別是 <ph name="VALID_VALUE_LOW" /> 和 <ph name="VALID_VALUE_HIGHER" />。</translation>
+<translation id="4384583879834880242">問與答</translation>
<translation id="4413860115965805769">選單按鈕</translation>
+<translation id="4446524499724042288">詞彙解釋參考資料</translation>
<translation id="4522570452068850558">詳細資訊</translation>
<translation id="4597532268155981612">表單</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
+<translation id="4668956016107839909">附錄</translation>
+<translation id="4742539557769756338">封面</translation>
<translation id="4757246831282535685">分頁面板</translation>
<translation id="4763480195061959176">影片</translation>
<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">請輸入一個數字。</translation>
+<translation id="4912536737030637138">參考書目</translation>
<translation id="4975562563186953947">已選取 <ph name="SELECTED_COUNT" /> 個項目</translation>
<translation id="4992066212339426712">取消靜音</translation>
<translation id="49969490063480558">請輸入「<ph name="ATSIGN" />」後面的部分。「<ph name="INVALIDADDRESS" />」不是完整值。</translation>
<translation id="5034860022980953847">進度指標</translation>
+<translation id="5093189678851173835">題詞</translation>
<translation id="5117590920725113268">顯示下一個月</translation>
<translation id="512758898067543763">列標題</translation>
+<translation id="5143125788380636750">結尾</translation>
+<translation id="5153163864850940242">目前在子母畫面模式中播放這部影片</translation>
<translation id="5164977714490026579">值必須大於或等於 <ph name="MINIMUM" />。</translation>
<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
<translation id="5307600278924710095">請輸入「<ph name="ATSIGN" />」後面的部分。「<ph name="INVALIDADDRESS" />」不是完整值。</translation>
@@ -106,9 +124,11 @@
<translation id="5546461542133609677">取消靜音</translation>
<translation id="561939826962581046">time</translation>
<translation id="5630795885300617244">輕觸兩下左側或右側可跳過 10 秒</translation>
+<translation id="5631759159893697722">摘要</translation>
<translation id="5641012560118721995">暫停播放</translation>
<translation id="5643186887447432888">按鈕</translation>
<translation id="5677946354068040947">更多選項</translation>
+<translation id="576709008726043716">簡介</translation>
<translation id="57838592816432529">靜音</translation>
<translation id="5860033963881614850">關閉</translation>
<translation id="588258955323874662">全螢幕</translation>
@@ -119,12 +139,15 @@
<translation id="6015796118275082299">年</translation>
<translation id="6023896073578205740">清單方塊</translation>
<translation id="6101327004457443354">取消音軌靜音</translation>
+<translation id="6150588977291308318">參考書目</translation>
<translation id="6164829606128959761">計量器</translation>
+<translation id="6166809985690652833">後記</translation>
+<translation id="6213469881011901533">詞彙解釋</translation>
<translation id="6398862346408813489">顯示月份選取面板</translation>
<translation id="6404546809543547843">音訊時間點拖曳工具</translation>
+<translation id="6453774872122745852">鳴謝</translation>
<translation id="648732519525291180">時間選擇器</translation>
<translation id="6550675742724504774">選項</translation>
-<translation id="6564313821541007458">目前在子母畫面模式中</translation>
<translation id="658823671542763450">進入全螢幕</translation>
<translation id="663493177488814956">資訊提供</translation>
<translation id="6637586476836377253">記錄</translation>
@@ -135,22 +158,31 @@
<translation id="6755330956360078551">工具提示</translation>
<translation id="6790428901817661496">播放</translation>
<translation id="6820355525329141109">無法載入外掛程式。</translation>
+<translation id="6820615603175220800">參考書目資料</translation>
<translation id="6843725295806269523">靜音</translation>
<translation id="6853785296079745596">不顯示字幕</translation>
<translation id="6885760532393684712">目錄</translation>
+<translation id="689129560213475294">版權頁標記</translation>
<translation id="6934078000481955284">引用標記</translation>
<translation id="6941933287844615239">下載媒體</translation>
<translation id="6989848892321993519">請將這段文字加長到 <ph name="MIN_CHARACTERS" /> 個字元以上 (目前已有 1 個字元)。</translation>
<translation id="709897737746224366">請符合要求的格式。</translation>
+<translation id="7139483182332611405">前言</translation>
<translation id="7223624360433298498">已播放時間</translation>
<translation id="7263440858009898357">請選取一個清單中的項目。</translation>
<translation id="727747134524199931">欄標題</translation>
+<translation id="7353453495576941748">參與名單</translation>
<translation id="7364796246159120393">選擇檔案</translation>
<translation id="739024184232394898">其他...</translation>
+<translation id="7405738980073107433">章節附註</translation>
<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
<translation id="7491962110804786152">分頁</translation>
<translation id="7514365320538308">下載</translation>
+<translation id="7529102961911894712">反向連結</translation>
+<translation id="7647456547678091388">提示</translation>
+<translation id="7661956066982048809">圖形文件</translation>
<translation id="7673697353781729403">小時</translation>
+<translation id="7681220483256441252">索引</translation>
<translation id="7720026100085573005">剩餘時間</translation>
<translation id="7740016676195725605">停止顯示字幕</translation>
<translation id="7740050170769002709">HTML 內容</translation>
@@ -160,24 +192,33 @@
<translation id="7891486169920085145">分割器</translation>
<translation id="795667975304826397">未選擇任何檔案</translation>
<translation id="8053789581856978548">搜尋文字欄位</translation>
+<translation id="8057695513531652401">聲明</translation>
+<translation id="8105797009065549151">附註參考資料</translation>
<translation id="8115662671911883373">開始顯示字幕</translation>
<translation id="8117451130807776954">本週</translation>
<translation id="819205353528511139">使用全螢幕模式播放電影</translation>
<translation id="8199524924445686405"> 年 </translation>
<translation id="8284326494547611709">字幕</translation>
<translation id="835897206747267392">無效的值。</translation>
+<translation id="8415319359811155763">分輯</translation>
<translation id="8433900881053900389">工具列</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 個檔案</translation>
<translation id="8451268428117625855">請選取檔案。</translation>
<translation id="8461852803063341183">圓形按鈕</translation>
+<translation id="8474886197722836894">獻辭</translation>
+<translation id="8531739829932800271">勘誤表</translation>
<translation id="8534579021159131403">分鐘</translation>
<translation id="8541249477527128034">媒體控制</translation>
+<translation id="8550857728288566671">圖形符號</translation>
<translation id="8583702881314752957">定義清單</translation>
<translation id="8597182159515967513">標題</translation>
+<translation id="860475260694818407">目錄</translation>
<translation id="8613126697340063924">控制遠端播放</translation>
+<translation id="862370744433916922">副標題</translation>
<translation id="8741316211671074806">子母畫面</translation>
<translation id="8750798805984357768">請選取其中一個選項。</translation>
<translation id="8785498733064193001">開始播放</translation>
+<translation id="8808573423886751634">章節</translation>
<translation id="8845239796550121995">正在投放到電視上</translation>
<translation id="8851136666856101339">主要元素</translation>
<translation id="8875657656876809964">影片播放錯誤</translation>
@@ -191,6 +232,7 @@
<translation id="9132465097189459683">其他...</translation>
<translation id="9138385573473225930">警示</translation>
<translation id="9155987714137265666"><ph name="WEEK" />,從 <ph name="WEEK_START_DATE" />開始</translation>
+<translation id="9168329111483466115">註腳</translation>
<translation id="947831847158436616">儲存格</translation>
<translation id="966787709310836684">選單</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index a967e1b15f3..5747496dc5f 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -7,7 +7,6 @@ import("//build/config/features.gni")
import("//build/config/jumbo.gni")
import("//build/config/linux/pangocairo/pangocairo.gni")
import("//build/config/ui.gni")
-import("//content/public/common/zygote_features.gni")
import("//gpu/vulkan/features.gni")
import("//media/media_options.gni")
import("//net/features.gni")
@@ -71,18 +70,19 @@ jumbo_source_set("browser") {
"//content/browser/background_fetch:background_fetch_proto",
"//content/browser/background_sync:background_sync_proto",
"//content/browser/cache_storage:cache_storage_proto",
+ "//content/browser/cookie_store:cookie_store_proto",
"//content/browser/devtools:devtools_resources",
"//content/browser/devtools:protocol_sources",
"//content/browser/dom_storage:local_storage_proto",
"//content/browser/notifications:notification_proto",
"//content/browser/payments:payment_app_proto",
+ "//content/browser/process_internals:mojo_bindings",
"//content/browser/service_worker:service_worker_proto",
"//content/browser/speech/proto",
"//content/common",
"//content/common:buildflags",
"//content/common:mojo_bindings",
"//content/public/common:common_sources",
- "//content/public/common:zygote_buildflags",
"//crypto",
"//device/bluetooth",
"//device/fido",
@@ -97,6 +97,7 @@ jumbo_source_set("browser") {
"//gpu/ipc/common:gpu_preferences_util",
"//gpu/ipc/host",
"//gpu/vulkan:buildflags",
+ "//jingle:jingle_glue",
"//media",
"//media:media_buildflags",
"//media/capture",
@@ -107,8 +108,6 @@ jumbo_source_set("browser") {
"//media/mojo/interfaces",
"//media/mojo/interfaces:constants",
"//media/mojo/services",
- "//mojo/common",
- "//mojo/common:values_struct_traits",
"//mojo/edk",
"//mojo/public/cpp/bindings",
"//mojo/public/js:resources",
@@ -119,7 +118,7 @@ jumbo_source_set("browser") {
"//printing/buildflags",
"//services/audio:lib",
"//services/audio/public/cpp",
- "//services/audio/public/mojom:constants",
+ "//services/audio/public/mojom",
"//services/catalog:constants",
"//services/catalog/public/cpp",
"//services/catalog/public/mojom:constants",
@@ -139,11 +138,12 @@ jumbo_source_set("browser") {
"//services/resource_coordinator:lib",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/service_manager",
- "//services/service_manager/embedder",
+ "//services/service_manager/embedder:embedder_result_codes",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
"//services/service_manager/runner/common",
"//services/service_manager/runner/host:lib",
+ "//services/service_manager/zygote:zygote_buildflags",
"//services/shape_detection:lib",
"//services/shape_detection/public/mojom",
"//services/tracing:lib",
@@ -172,6 +172,9 @@ jumbo_source_set("browser") {
"//third_party/icu",
"//third_party/libyuv",
"//third_party/re2",
+ "//third_party/webrtc/media:rtc_media_base",
+ "//third_party/webrtc/modules/desktop_capture:primitives",
+ "//third_party/webrtc/rtc_base:rtc_base",
"//third_party/zlib",
"//third_party/zlib/google:compression_utils",
"//third_party/zlib/google:zip",
@@ -206,8 +209,8 @@ jumbo_source_set("browser") {
":accessibility_buildflags",
"//ipc",
"//media/mojo/interfaces:remoting",
+ "//third_party/blink/public:embedded_frame_sink_mojo_bindings",
"//third_party/blink/public:media_devices_mojo_bindings",
- "//third_party/blink/public:offscreen_canvas_mojo_bindings",
"//third_party/leveldatabase",
]
@@ -253,10 +256,6 @@ jumbo_source_set("browser") {
"$target_gen_dir/devtools/protocol/tracing.h",
"../common/service_manager/child_connection.cc",
"../common/service_manager/child_connection.h",
- "../zygote/zygote_linux.cc",
- "../zygote/zygote_linux.h",
- "../zygote/zygote_main.h",
- "../zygote/zygote_main_linux.cc",
"accessibility/accessibility_tree_formatter.cc",
"accessibility/accessibility_tree_formatter.h",
"accessibility/accessibility_tree_formatter_blink.cc",
@@ -323,8 +322,6 @@ jumbo_source_set("browser") {
"android/launcher_thread.h",
"android/scoped_surface_request_manager.cc",
"android/scoped_surface_request_manager.h",
- "android/string_message_codec.cc",
- "android/string_message_codec.h",
"android/text_suggestion_host_android.cc",
"android/text_suggestion_host_android.h",
"android/text_suggestion_host_mojo_impl_android.cc",
@@ -413,6 +410,8 @@ jumbo_source_set("browser") {
"background_fetch/background_fetch_event_dispatcher.h",
"background_fetch/background_fetch_job_controller.cc",
"background_fetch/background_fetch_job_controller.h",
+ "background_fetch/background_fetch_metrics.cc",
+ "background_fetch/background_fetch_metrics.h",
"background_fetch/background_fetch_registration_id.cc",
"background_fetch/background_fetch_registration_id.h",
"background_fetch/background_fetch_registration_notifier.cc",
@@ -438,8 +437,16 @@ jumbo_source_set("browser") {
"background_fetch/storage/get_developer_ids_task.h",
"background_fetch/storage/get_metadata_task.cc",
"background_fetch/storage/get_metadata_task.h",
+ "background_fetch/storage/get_num_requests_task.cc",
+ "background_fetch/storage/get_num_requests_task.h",
+ "background_fetch/storage/get_settled_fetches_task.cc",
+ "background_fetch/storage/get_settled_fetches_task.h",
"background_fetch/storage/mark_registration_for_deletion_task.cc",
"background_fetch/storage/mark_registration_for_deletion_task.h",
+ "background_fetch/storage/mark_request_complete_task.cc",
+ "background_fetch/storage/mark_request_complete_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",
@@ -493,7 +500,8 @@ jumbo_source_set("browser") {
"browser_main.h",
"browser_main_loop.cc",
"browser_main_loop.h",
- "browser_main_runner.cc",
+ "browser_main_runner_impl.cc",
+ "browser_main_runner_impl.h",
"browser_plugin/browser_plugin_embedder.cc",
"browser_plugin/browser_plugin_embedder.h",
"browser_plugin/browser_plugin_guest.cc",
@@ -569,6 +577,14 @@ jumbo_source_set("browser") {
# needed on all platforms.
"compositor/surface_utils.cc",
"compositor/surface_utils.h",
+ "cookie_store/cookie_change_subscription.cc",
+ "cookie_store/cookie_change_subscription.h",
+ "cookie_store/cookie_store_context.cc",
+ "cookie_store/cookie_store_context.h",
+ "cookie_store/cookie_store_host.cc",
+ "cookie_store/cookie_store_host.h",
+ "cookie_store/cookie_store_manager.cc",
+ "cookie_store/cookie_store_manager.h",
"dedicated_worker/dedicated_worker_host.cc",
"dedicated_worker/dedicated_worker_host.h",
"devtools/browser_devtools_agent_host.cc",
@@ -592,6 +608,12 @@ jumbo_source_set("browser") {
"devtools/devtools_pipe_handler.h",
"devtools/devtools_session.cc",
"devtools/devtools_session.h",
+ "devtools/devtools_stream_blob.cc",
+ "devtools/devtools_stream_blob.h",
+ "devtools/devtools_stream_file.cc",
+ "devtools/devtools_stream_file.h",
+ "devtools/devtools_stream_pipe.cc",
+ "devtools/devtools_stream_pipe.h",
"devtools/devtools_target_registry.cc",
"devtools/devtools_target_registry.h",
"devtools/devtools_traceable_screenshot.cc",
@@ -684,12 +706,20 @@ jumbo_source_set("browser") {
"dom_storage/local_storage_context_mojo.h",
"dom_storage/session_storage_context_mojo.cc",
"dom_storage/session_storage_context_mojo.h",
+ "dom_storage/session_storage_data_map.cc",
+ "dom_storage/session_storage_data_map.h",
"dom_storage/session_storage_database.cc",
"dom_storage/session_storage_database.h",
"dom_storage/session_storage_database_adapter.cc",
"dom_storage/session_storage_database_adapter.h",
+ "dom_storage/session_storage_leveldb_wrapper.cc",
+ "dom_storage/session_storage_leveldb_wrapper.h",
+ "dom_storage/session_storage_metadata.cc",
+ "dom_storage/session_storage_metadata.h",
"dom_storage/session_storage_namespace_impl.cc",
"dom_storage/session_storage_namespace_impl.h",
+ "dom_storage/session_storage_namespace_impl_mojo.cc",
+ "dom_storage/session_storage_namespace_impl_mojo.h",
"download/blob_download_url_loader_factory_getter.cc",
"download/blob_download_url_loader_factory_getter.h",
"download/byte_stream_input_stream.cc",
@@ -704,6 +734,8 @@ jumbo_source_set("browser") {
"download/download_request_utils.cc",
"download/download_resource_handler.cc",
"download/download_resource_handler.h",
+ "download/download_url_loader_factory_getter_impl.cc",
+ "download/download_url_loader_factory_getter_impl.h",
"download/download_utils.cc",
"download/download_utils.h",
"download/drag_download_file.cc",
@@ -736,6 +768,8 @@ jumbo_source_set("browser") {
"file_url_loader_factory.h",
"fileapi/browser_file_system_helper.cc",
"fileapi/browser_file_system_helper.h",
+ "fileapi/file_system_url_loader_factory.cc",
+ "fileapi/file_system_url_loader_factory.h",
"fileapi/fileapi_message_filter.cc",
"fileapi/fileapi_message_filter.h",
"find_request_manager.cc",
@@ -743,10 +777,10 @@ jumbo_source_set("browser") {
"font_list_async.cc",
"frame_host/ancestor_throttle.cc",
"frame_host/ancestor_throttle.h",
+ "frame_host/blocked_scheme_navigation_throttle.cc",
+ "frame_host/blocked_scheme_navigation_throttle.h",
"frame_host/cross_process_frame_connector.cc",
"frame_host/cross_process_frame_connector.h",
- "frame_host/data_url_navigation_throttle.cc",
- "frame_host/data_url_navigation_throttle.h",
"frame_host/debug_urls.cc",
"frame_host/debug_urls.h",
"frame_host/form_submission_throttle.cc",
@@ -761,8 +795,6 @@ jumbo_source_set("browser") {
"frame_host/frame_tree_node_blame_context.h",
"frame_host/input/input_injector_impl.cc",
"frame_host/input/input_injector_impl.h",
- "frame_host/input/legacy_ipc_frame_input_handler.cc",
- "frame_host/input/legacy_ipc_frame_input_handler.h",
"frame_host/interstitial_page_impl.cc",
"frame_host/interstitial_page_impl.h",
"frame_host/interstitial_page_navigator_impl.cc",
@@ -808,6 +840,8 @@ jumbo_source_set("browser") {
"frame_host/render_frame_proxy_host.h",
"frame_host/render_widget_host_view_guest.cc",
"frame_host/render_widget_host_view_guest.h",
+ "frame_host/webui_navigation_throttle.cc",
+ "frame_host/webui_navigation_throttle.h",
"generic_sensor/sensor_provider_proxy_impl.cc",
"generic_sensor/sensor_provider_proxy_impl.h",
"geolocation/geolocation_service_impl.cc",
@@ -818,8 +852,8 @@ jumbo_source_set("browser") {
"gpu/browser_gpu_memory_buffer_manager.h",
"gpu/compositor_util.cc",
"gpu/compositor_util.h",
- "gpu/gpu_client.cc",
- "gpu/gpu_client.h",
+ "gpu/gpu_client_impl.cc",
+ "gpu/gpu_client_impl.h",
"gpu/gpu_data_manager_impl.cc",
"gpu/gpu_data_manager_impl.h",
"gpu/gpu_data_manager_impl_private.cc",
@@ -836,13 +870,11 @@ jumbo_source_set("browser") {
"gpu/shader_cache_factory.h",
"histogram_controller.cc",
"histogram_controller.h",
- "histogram_internals_request_job.cc",
- "histogram_internals_request_job.h",
- "histogram_internals_url_loader.cc",
- "histogram_internals_url_loader.h",
"histogram_subscriber.h",
"histogram_synchronizer.cc",
"histogram_synchronizer.h",
+ "histograms_internals_ui.cc",
+ "histograms_internals_ui.h",
"image_capture/image_capture_impl.cc",
"image_capture/image_capture_impl.h",
"indexed_db/cursor_impl.cc",
@@ -925,12 +957,15 @@ jumbo_source_set("browser") {
"indexed_db/leveldb/leveldb_write_batch.cc",
"indexed_db/leveldb/leveldb_write_batch.h",
"indexed_db/list_set.h",
+ "initiator_csp_context.cc",
+ "initiator_csp_context.h",
"installedapp/installed_app_provider_impl_default.cc",
"installedapp/installed_app_provider_impl_default.h",
"interface_provider_filtering.cc",
"interface_provider_filtering.h",
"isolated_origin_util.cc",
"isolated_origin_util.h",
+ "keyboard_lock/keyboard_lock_metrics.h",
"keyboard_lock/keyboard_lock_service_impl.cc",
"keyboard_lock/keyboard_lock_service_impl.h",
"leveldb_wrapper_impl.cc",
@@ -959,20 +994,14 @@ jumbo_source_set("browser") {
"loader/mojo_async_resource_handler.h",
"loader/navigation_loader_interceptor.cc",
"loader/navigation_loader_interceptor.h",
- "loader/navigation_metrics.cc",
- "loader/navigation_metrics.h",
- "loader/navigation_resource_handler.cc",
- "loader/navigation_resource_handler.h",
+ "loader/navigation_loader_util.cc",
+ "loader/navigation_loader_util.h",
"loader/navigation_url_loader.cc",
"loader/navigation_url_loader.h",
"loader/navigation_url_loader_delegate.h",
"loader/navigation_url_loader_factory.h",
"loader/navigation_url_loader_impl.cc",
"loader/navigation_url_loader_impl.h",
- "loader/navigation_url_loader_impl_core.cc",
- "loader/navigation_url_loader_impl_core.h",
- "loader/navigation_url_loader_network_service.cc",
- "loader/navigation_url_loader_network_service.h",
"loader/null_resource_controller.cc",
"loader/null_resource_controller.h",
"loader/prefetch_url_loader.cc",
@@ -1040,6 +1069,16 @@ jumbo_source_set("browser") {
"media/android/media_web_contents_observer_android.h",
"media/audible_metrics.cc",
"media/audible_metrics.h",
+ "media/audio_input_stream_broker.cc",
+ "media/audio_input_stream_broker.h",
+ "media/audio_loopback_stream_broker.cc",
+ "media/audio_loopback_stream_broker.h",
+ "media/audio_muting_session.cc",
+ "media/audio_muting_session.h",
+ "media/audio_output_stream_broker.cc",
+ "media/audio_output_stream_broker.h",
+ "media/audio_stream_broker.cc",
+ "media/audio_stream_broker.h",
"media/audio_stream_monitor.cc",
"media/audio_stream_monitor.h",
"media/capture/audio_mirroring_manager.cc",
@@ -1054,6 +1093,10 @@ jumbo_source_set("browser") {
"media/capture/web_contents_tracker.h",
"media/cdm_registry_impl.cc",
"media/cdm_registry_impl.h",
+ "media/flinging_renderer.cc",
+ "media/flinging_renderer.h",
+ "media/forwarding_audio_stream_factory.cc",
+ "media/forwarding_audio_stream_factory.h",
"media/media_devices_permission_checker.cc",
"media/media_devices_permission_checker.h",
"media/media_devices_util.cc",
@@ -1146,8 +1189,6 @@ jumbo_source_set("browser") {
"notifications/notification_event_dispatcher_impl.h",
"notifications/notification_id_generator.cc",
"notifications/notification_id_generator.h",
- "notifications/notification_message_filter.cc",
- "notifications/notification_message_filter.h",
"notifications/platform_notification_context_impl.cc",
"notifications/platform_notification_context_impl.h",
"origin_manifest/origin_manifest_parser.cc",
@@ -1176,6 +1217,10 @@ jumbo_source_set("browser") {
"picture_in_picture/picture_in_picture_window_controller_impl.h",
"presentation/presentation_service_impl.cc",
"presentation/presentation_service_impl.h",
+ "process_internals/process_internals_handler_impl.cc",
+ "process_internals/process_internals_handler_impl.h",
+ "process_internals/process_internals_ui.cc",
+ "process_internals/process_internals_ui.h",
"push_messaging/push_messaging_context.cc",
"push_messaging/push_messaging_context.h",
"push_messaging/push_messaging_manager.cc",
@@ -1195,6 +1240,10 @@ jumbo_source_set("browser") {
"renderer_host/display_util.h",
"renderer_host/dwrite_font_proxy_message_filter_win.cc",
"renderer_host/dwrite_font_proxy_message_filter_win.h",
+ "renderer_host/embedded_frame_sink_impl.cc",
+ "renderer_host/embedded_frame_sink_impl.h",
+ "renderer_host/embedded_frame_sink_provider_impl.cc",
+ "renderer_host/embedded_frame_sink_provider_impl.h",
"renderer_host/event_with_latency_info.h",
"renderer_host/file_utilities_host_impl.cc",
"renderer_host/file_utilities_host_impl.h",
@@ -1210,6 +1259,10 @@ jumbo_source_set("browser") {
"renderer_host/frame_token_message_queue.h",
"renderer_host/input/fling_controller.cc",
"renderer_host/input/fling_controller.h",
+ "renderer_host/input/fling_scheduler.cc",
+ "renderer_host/input/fling_scheduler.h",
+ "renderer_host/input/fling_scheduler_mac.h",
+ "renderer_host/input/fling_scheduler_mac.mm",
"renderer_host/input/gesture_event_queue.cc",
"renderer_host/input/gesture_event_queue.h",
"renderer_host/input/input_device_change_observer.cc",
@@ -1221,10 +1274,6 @@ jumbo_source_set("browser") {
"renderer_host/input/input_router_config_helper.h",
"renderer_host/input/input_router_impl.cc",
"renderer_host/input/input_router_impl.h",
- "renderer_host/input/legacy_input_router_impl.cc",
- "renderer_host/input/legacy_input_router_impl.h",
- "renderer_host/input/legacy_ipc_widget_input_handler.cc",
- "renderer_host/input/legacy_ipc_widget_input_handler.h",
"renderer_host/input/motion_event_web.cc",
"renderer_host/input/motion_event_web.h",
"renderer_host/input/mouse_wheel_event_queue.cc",
@@ -1278,7 +1327,6 @@ jumbo_source_set("browser") {
"renderer_host/input/synthetic_touchscreen_pinch_gesture.h",
"renderer_host/input/tap_suppression_controller.cc",
"renderer_host/input/tap_suppression_controller.h",
- "renderer_host/input/tap_suppression_controller_client.h",
"renderer_host/input/timeout_monitor.cc",
"renderer_host/input/timeout_monitor.h",
"renderer_host/input/touch_action_filter.cc",
@@ -1306,8 +1354,6 @@ jumbo_source_set("browser") {
"renderer_host/media/audio_input_delegate_impl.h",
"renderer_host/media/audio_input_device_manager.cc",
"renderer_host/media/audio_input_device_manager.h",
- "renderer_host/media/audio_input_renderer_host.cc",
- "renderer_host/media/audio_input_renderer_host.h",
"renderer_host/media/audio_input_stream_handle.cc",
"renderer_host/media/audio_input_stream_handle.h",
"renderer_host/media/audio_output_authorization_handler.cc",
@@ -1316,8 +1362,8 @@ jumbo_source_set("browser") {
"renderer_host/media/audio_output_delegate_impl.h",
"renderer_host/media/audio_output_stream_observer_impl.cc",
"renderer_host/media/audio_output_stream_observer_impl.h",
- "renderer_host/media/audio_renderer_host.cc",
- "renderer_host/media/audio_renderer_host.h",
+ "renderer_host/media/audio_service_listener.cc",
+ "renderer_host/media/audio_service_listener.h",
"renderer_host/media/in_process_launched_video_capture_device.cc",
"renderer_host/media/in_process_launched_video_capture_device.h",
"renderer_host/media/in_process_video_capture_device_launcher.cc",
@@ -1339,6 +1385,12 @@ jumbo_source_set("browser") {
"renderer_host/media/media_stream_track_metrics_host.h",
"renderer_host/media/media_stream_ui_proxy.cc",
"renderer_host/media/media_stream_ui_proxy.h",
+ "renderer_host/media/old_render_frame_audio_input_stream_factory.cc",
+ "renderer_host/media/old_render_frame_audio_input_stream_factory.h",
+ "renderer_host/media/old_render_frame_audio_output_stream_factory.cc",
+ "renderer_host/media/old_render_frame_audio_output_stream_factory.h",
+ "renderer_host/media/peer_connection_tracker_host.cc",
+ "renderer_host/media/peer_connection_tracker_host.h",
"renderer_host/media/render_frame_audio_input_stream_factory.cc",
"renderer_host/media/render_frame_audio_input_stream_factory.h",
"renderer_host/media/render_frame_audio_output_stream_factory.cc",
@@ -1369,14 +1421,22 @@ jumbo_source_set("browser") {
"renderer_host/media/video_capture_provider_switcher.h",
"renderer_host/native_web_keyboard_event_aura.cc",
"renderer_host/native_web_keyboard_event_mac.mm",
- "renderer_host/offscreen_canvas_provider_impl.cc",
- "renderer_host/offscreen_canvas_provider_impl.h",
- "renderer_host/offscreen_canvas_surface_impl.cc",
- "renderer_host/offscreen_canvas_surface_impl.h",
"renderer_host/overscroll_configuration.cc",
"renderer_host/overscroll_controller.cc",
"renderer_host/overscroll_controller.h",
"renderer_host/overscroll_controller_delegate.h",
+ "renderer_host/p2p/socket_dispatcher_host.cc",
+ "renderer_host/p2p/socket_dispatcher_host.h",
+ "renderer_host/p2p/socket_host.cc",
+ "renderer_host/p2p/socket_host.h",
+ "renderer_host/p2p/socket_host_tcp.cc",
+ "renderer_host/p2p/socket_host_tcp.h",
+ "renderer_host/p2p/socket_host_tcp_server.cc",
+ "renderer_host/p2p/socket_host_tcp_server.h",
+ "renderer_host/p2p/socket_host_throttler.cc",
+ "renderer_host/p2p/socket_host_throttler.h",
+ "renderer_host/p2p/socket_host_udp.cc",
+ "renderer_host/p2p/socket_host_udp.h",
"renderer_host/render_frame_metadata_provider_impl.cc",
"renderer_host/render_frame_metadata_provider_impl.h",
"renderer_host/render_message_filter.cc",
@@ -1459,6 +1519,8 @@ jumbo_source_set("browser") {
"service_worker/service_worker_blob_reader.h",
"service_worker/service_worker_cache_writer.cc",
"service_worker/service_worker_cache_writer.h",
+ "service_worker/service_worker_client_info.cc",
+ "service_worker/service_worker_client_info.h",
"service_worker/service_worker_client_utils.cc",
"service_worker/service_worker_client_utils.h",
"service_worker/service_worker_consts.cc",
@@ -1664,6 +1726,8 @@ jumbo_source_set("browser") {
"web_package/signed_exchange_certificate_chain.cc",
"web_package/signed_exchange_certificate_chain.h",
"web_package/signed_exchange_consts.h",
+ "web_package/signed_exchange_devtools_proxy.cc",
+ "web_package/signed_exchange_devtools_proxy.h",
"web_package/signed_exchange_handler.cc",
"web_package/signed_exchange_handler.h",
"web_package/signed_exchange_header.cc",
@@ -1684,6 +1748,13 @@ jumbo_source_set("browser") {
"web_package/web_package_prefetch_handler.h",
"web_package/web_package_request_handler.cc",
"web_package/web_package_request_handler.h",
+ "webrtc/webrtc_internals.cc",
+ "webrtc/webrtc_internals.h",
+ "webrtc/webrtc_internals_message_handler.cc",
+ "webrtc/webrtc_internals_message_handler.h",
+ "webrtc/webrtc_internals_ui.cc",
+ "webrtc/webrtc_internals_ui.h",
+ "webrtc/webrtc_internals_ui_observer.h",
"websockets/websocket_handshake_request_info_impl.cc",
"websockets/websocket_handshake_request_info_impl.h",
"websockets/websocket_manager.cc",
@@ -1711,19 +1782,21 @@ jumbo_source_set("browser") {
"webui/web_ui_message_handler.cc",
"webui/web_ui_url_loader_factory.cc",
"webui/web_ui_url_loader_factory_internal.h",
- "zygote_host/zygote_communication_linux.cc",
- "zygote_host/zygote_communication_linux.h",
- "zygote_host/zygote_host_impl_linux.cc",
- "zygote_host/zygote_host_impl_linux.h",
]
if (toolkit_views) {
deps += [ "//ui/events" ]
}
+ if (is_linux) {
+ deps += [ "//services/service_manager/zygote" ]
+ }
+
# ChromeOS also defines linux but their memory-monitors conflict.
if (is_chromeos) {
sources += [
+ "media/keyboard_mic_registration.cc",
+ "media/keyboard_mic_registration.h",
"memory/memory_monitor_chromeos.cc",
"memory/memory_monitor_chromeos.h",
"tracing/cros_tracing_agent.cc",
@@ -1736,6 +1809,10 @@ jumbo_source_set("browser") {
]
}
+ if (is_chromeos || is_android || is_chromecast) {
+ defines += [ "ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION" ]
+ }
+
if (is_chromecast && is_linux) {
sources += [
"tracing/cast_tracing_agent.cc",
@@ -1761,7 +1838,7 @@ jumbo_source_set("browser") {
]
}
- if (enable_basic_printing || enable_print_preview) {
+ if (enable_basic_printing) {
deps += [ "//printing" ]
}
@@ -1782,39 +1859,6 @@ jumbo_source_set("browser") {
]
}
- if (enable_webrtc) {
- sources += [
- "renderer_host/media/peer_connection_tracker_host.cc",
- "renderer_host/media/peer_connection_tracker_host.h",
- "renderer_host/p2p/socket_dispatcher_host.cc",
- "renderer_host/p2p/socket_dispatcher_host.h",
- "renderer_host/p2p/socket_host.cc",
- "renderer_host/p2p/socket_host.h",
- "renderer_host/p2p/socket_host_tcp.cc",
- "renderer_host/p2p/socket_host_tcp.h",
- "renderer_host/p2p/socket_host_tcp_server.cc",
- "renderer_host/p2p/socket_host_tcp_server.h",
- "renderer_host/p2p/socket_host_throttler.cc",
- "renderer_host/p2p/socket_host_throttler.h",
- "renderer_host/p2p/socket_host_udp.cc",
- "renderer_host/p2p/socket_host_udp.h",
- "webrtc/webrtc_internals.cc",
- "webrtc/webrtc_internals.h",
- "webrtc/webrtc_internals_message_handler.cc",
- "webrtc/webrtc_internals_message_handler.h",
- "webrtc/webrtc_internals_ui.cc",
- "webrtc/webrtc_internals_ui.h",
- "webrtc/webrtc_internals_ui_observer.h",
- ]
-
- deps += [
- "//jingle:jingle_glue",
- "//third_party/webrtc/media:rtc_media_base",
- "//third_party/webrtc/modules/desktop_capture:primitives",
- "//third_party/webrtc/rtc_base:rtc_base",
- ]
- }
-
# Desktop/Window/WebContents screen capture implementations, conditionally
# built depending on the available implementations for each platform.
if (is_linux || is_mac || is_win) {
@@ -1822,6 +1866,8 @@ jumbo_source_set("browser") {
sources += [
"media/capture/cursor_renderer.cc",
"media/capture/cursor_renderer.h",
+ "media/capture/desktop_capture_device.cc",
+ "media/capture/desktop_capture_device.h",
"media/capture/fake_webcontent_capture_machine.cc",
"media/capture/fake_webcontent_capture_machine.h",
"media/capture/frame_sink_video_capture_device.cc",
@@ -1829,16 +1875,26 @@ jumbo_source_set("browser") {
"media/capture/web_contents_video_capture_device.cc",
"media/capture/web_contents_video_capture_device.h",
]
+ public_deps += [ "//third_party/webrtc_overrides:init_webrtc" ]
+ deps += [ "//third_party/webrtc/modules/desktop_capture" ]
if (use_aura) {
sources += [
"media/capture/aura_window_capture_machine.cc",
"media/capture/aura_window_capture_machine.h",
+ "media/capture/aura_window_video_capture_device.cc",
+ "media/capture/aura_window_video_capture_device.h",
"media/capture/cursor_renderer_aura.cc",
"media/capture/cursor_renderer_aura.h",
"media/capture/desktop_capture_device_aura.cc",
"media/capture/desktop_capture_device_aura.h",
]
}
+ if (is_chromeos) {
+ sources += [
+ "media/capture/lame_window_capturer_chromeos.cc",
+ "media/capture/lame_window_capturer_chromeos.h",
+ ]
+ }
if (is_mac) {
sources += [
"media/capture/cursor_renderer_mac.h",
@@ -1849,14 +1905,6 @@ jumbo_source_set("browser") {
"//sandbox/mac:seatbelt_extension",
]
}
- if (enable_webrtc) {
- sources += [
- "media/capture/desktop_capture_device.cc",
- "media/capture/desktop_capture_device.h",
- ]
- deps += [ "//third_party/webrtc/modules/desktop_capture" ]
- public_deps += [ "//third_party/webrtc_overrides:init_webrtc" ]
- }
}
if (is_win) {
@@ -2036,6 +2084,8 @@ jumbo_source_set("browser") {
"accessibility/captioning_controller.h",
"accessibility/web_contents_accessibility_android.cc",
"accessibility/web_contents_accessibility_android.h",
+ "android/content_ui_event_handler.cc",
+ "android/content_ui_event_handler.h",
"android/content_view_core.cc",
"android/content_view_core.h",
"android/content_view_render_view.cc",
@@ -2047,8 +2097,6 @@ jumbo_source_set("browser") {
"android/gesture_listener_manager.h",
"android/ime_adapter_android.cc",
"android/ime_adapter_android.h",
- "android/interstitial_page_delegate_android.cc",
- "android/interstitial_page_delegate_android.h",
"android/java/gin_java_bound_object.cc",
"android/java/gin_java_bound_object.h",
"android/java/gin_java_bound_object_delegate.cc",
@@ -2086,8 +2134,6 @@ jumbo_source_set("browser") {
"android/selection/selection_popup_controller.h",
"android/selection/smart_selection_client.cc",
"android/selection/smart_selection_client.h",
- "android/synchronous_compositor_browser_filter.cc",
- "android/synchronous_compositor_browser_filter.h",
"android/synchronous_compositor_host.cc",
"android/synchronous_compositor_host.h",
"android/synchronous_compositor_sync_call_bridge.cc",
@@ -2098,6 +2144,8 @@ jumbo_source_set("browser") {
"android/tracing_controller_android.h",
"android/web_contents_observer_proxy.cc",
"android/web_contents_observer_proxy.h",
+ "compositor/in_process_display_client.cc",
+ "compositor/in_process_display_client.h",
"frame_host/render_frame_host_android.cc",
"frame_host/render_frame_host_android.h",
"media/capture/screen_capture_device_android.cc",
@@ -2143,9 +2191,12 @@ jumbo_source_set("browser") {
deps += [
":reflection_jni_headers",
"//content/public/android:jni",
+ "//device/gamepad/public/mojom",
"//media",
"//media/capture/content/android",
"//media/capture/video/android",
+ "//ui/accessibility:ax_assistant",
+ "//ui/accessibility/mojom",
"//ui/android",
"//ui/compositor",
]
@@ -2305,8 +2356,6 @@ jumbo_source_set("browser") {
"context_factory.cc",
"renderer_host/browser_compositor_view_mac.h",
"renderer_host/browser_compositor_view_mac.mm",
- "renderer_host/compositor_resize_lock.cc",
- "renderer_host/compositor_resize_lock.h",
"renderer_host/delegated_frame_host.cc",
"renderer_host/delegated_frame_host.h",
]
@@ -2325,6 +2374,7 @@ jumbo_source_set("browser") {
"compositor/vulkan_browser_compositor_output_surface.cc",
"compositor/vulkan_browser_compositor_output_surface.h",
]
+ deps += [ "//gpu/vulkan/init" ]
}
deps += [
"//components/viz/service",
@@ -2351,10 +2401,6 @@ jumbo_source_set("browser") {
]
}
- if (use_zygote_handle) {
- sources += [ "zygote_host/zygote_handle_linux.cc" ]
- }
-
if (enable_reporting) {
sources += [
"net/reporting_service_proxy.cc",
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index df2d78160a9..59cc7c497cd 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -53,7 +53,7 @@ include_rules = [
"+third_party/iaccessible2",
"+third_party/isimpledom",
"+third_party/khronos", # For enum definitions only
- "+third_party/libaom/av1_features.h",
+ "+third_party/libaom/av1_buildflags.h",
"+third_party/re2",
"+third_party/zlib",
@@ -67,10 +67,10 @@ include_rules = [
"-third_party/blink",
"+third_party/blink/public/common",
"+third_party/blink/public/mojom",
+ "+third_party/blink/public/platform/resource_request_blocked_reason.h",
"+third_party/blink/public/platform/WebAddressSpace.h",
"+third_party/blink/public/platform/web_content_security_policy.h",
"+third_party/blink/public/platform/web_cursor_info.h",
- "+third_party/blink/public/platform/web_display_mode.h",
"+third_party/blink/public/platform/web_drag_operation.h",
"+third_party/blink/public/platform/web_focus_type.h",
"+third_party/blink/public/platform/web_fullscreen_video_status.h",
@@ -87,6 +87,7 @@ include_rules = [
"+third_party/blink/public/platform/WebRemoteFrameProperties.h",
"+third_party/blink/public/platform/web_screen_info.h",
"+third_party/blink/public/platform/web_scroll_into_view_params.h",
+ "+third_party/blink/public/platform/web_scroll_types.h",
"+third_party/blink/public/platform/web_security_style.h",
"+third_party/blink/public/platform/web_sudden_termination_disabler_type.h",
"+third_party/blink/public/platform/web_touch_event.h",
@@ -96,19 +97,15 @@ include_rules = [
"+third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h",
"+third_party/blink/public/platform/modules/indexeddb/web_idb_types.h",
"+third_party/blink/public/platform/modules/notifications/web_notification_constants.h",
- "+third_party/blink/public/platform/modules/screen_orientation/web_lock_orientation_error.h",
- "+third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h",
- "+third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_type.h",
"+third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h",
"+third_party/blink/public/public_buildflags.h",
- "+third_party/blink/public/web/devtools_agent.mojom.h",
- "+third_party/blink/public/web/devtools_frontend.mojom.h",
"+third_party/blink/public/web/web_ax_enums.h",
"+third_party/blink/public/web/web_console_message.h",
"+third_party/blink/public/web/web_context_menu_data.h",
"+third_party/blink/public/web/web_device_emulation_params.h",
"+third_party/blink/public/web/web_drag_status.h",
"+third_party/blink/public/web/web_find_options.h",
+ "+third_party/blink/public/web/web_fullscreen_options.h",
"+third_party/blink/public/web/web_frame_serializer_cache_control_policy.h",
"+third_party/blink/public/web/web_ime_text_span.h",
"+third_party/blink/public/web/web_media_player_action.h",
@@ -131,15 +128,15 @@ include_rules = [
"+third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h",
"+third_party/blink/public/platform/modules/broadcastchannel/broadcast_channel.mojom.h",
"+third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h",
+ "+third_party/blink/public/platform/modules/cookie_store/cookie_store.mojom.h",
"+third_party/blink/public/platform/modules/geolocation/geolocation_service.mojom.h",
"+third_party/blink/public/platform/modules/installedapp/installed_app_provider.mojom.h",
"+third_party/blink/public/platform/modules/installedapp/related_application.mojom.h",
"+third_party/blink/public/platform/modules/keyboard_lock/keyboard_lock.mojom.h",
- "+third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h",
"+third_party/blink/public/platform/modules/mediasession/media_session.mojom.h",
"+third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h",
"+third_party/blink/public/platform/modules/notifications/notification_service.mojom.h",
- "+third_party/blink/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h",
+ "+third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom.h",
"+third_party/blink/public/platform/modules/payments/payment_app.mojom.h",
"+third_party/blink/public/platform/modules/permissions/permission.mojom.h",
"+third_party/blink/public/platform/modules/permissions/permission_status.mojom.h",
@@ -152,6 +149,8 @@ include_rules = [
"+third_party/blink/public/platform/reporting.mojom.h",
"+third_party/blink/public/platform/web_feature.mojom.h",
"+third_party/blink/public/web/commit_result.mojom.h",
+ "+third_party/blink/public/web/devtools_agent.mojom.h",
+ "+third_party/blink/public/web/devtools_frontend.mojom.h",
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
# See https://sites.google.com/a/chromium.org/dev/developers/content-module
diff --git a/chromium/content/browser/OWNERS b/chromium/content/browser/OWNERS
index c78c8cee12b..76478df0021 100644
--- a/chromium/content/browser/OWNERS
+++ b/chromium/content/browser/OWNERS
@@ -31,5 +31,5 @@ per-file sandbox_ipc_linux.*=jorgelo@chromium.org
# LevelDBWrapperImpl used in LocalStorage
per-file leveldb_wrapper_impl*=mek@chromium.org
-per-file leveldb_wrapper_impl*=michaeln@chromium.org
+per-file leveldb_wrapper_impl*=dmurph@chromium.org
per-file leveldb_wrapper_impl*=pwnall@chromium.org
diff --git a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
index 96a46abd1e5..cad16f8da69 100644
--- a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
@@ -164,12 +164,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImage) {
" c.beginPath();\n"
" c.moveTo(0, 0.5);\n"
" c.lineTo(4, 0.5);\n"
- " c.strokeStyle = '#ff0000';\n"
+ " c.strokeStyle = '%23ff0000';\n"
" c.stroke();\n"
" c.beginPath();\n"
" c.moveTo(0, 1.5);\n"
" c.lineTo(4, 1.5);\n"
- " c.strokeStyle = '#0000ff';\n"
+ " c.strokeStyle = '%230000ff';\n"
" c.stroke();\n"
"</script>"
"</body>");
@@ -211,9 +211,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, CanvasGetImageScale) {
"<canvas aria-label='canvas' id='c' width='40' height='20'></canvas>"
"<script>\n"
" var c = document.getElementById('c').getContext('2d');\n"
- " c.fillStyle = '#00ff00';\n"
+ " c.fillStyle = '%2300ff00';\n"
" c.fillRect(0, 0, 40, 10);\n"
- " c.fillStyle = '#ff00ff';\n"
+ " c.fillStyle = '%23ff00ff';\n"
" c.fillRect(0, 10, 40, 10);\n"
"</script>"
"</body>");
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index 569515a57cb..50f1d01015b 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -71,6 +71,8 @@ std::string AccessibilityTreeFormatterBlink::IntAttrToString(
return ui::ToString(static_cast<ax::mojom::DefaultActionVerb>(value));
case ax::mojom::IntAttribute::kDescriptionFrom:
return ui::ToString(static_cast<ax::mojom::DescriptionFrom>(value));
+ case ax::mojom::IntAttribute::kHasPopup:
+ return ui::ToString(static_cast<ax::mojom::HasPopup>(value));
case ax::mojom::IntAttribute::kInvalidState:
return ui::ToString(static_cast<ax::mojom::InvalidState>(value));
case ax::mojom::IntAttribute::kNameFrom:
@@ -81,6 +83,8 @@ std::string AccessibilityTreeFormatterBlink::IntAttrToString(
return ui::ToString(static_cast<ax::mojom::SortDirection>(value));
case ax::mojom::IntAttribute::kTextDirection:
return ui::ToString(static_cast<ax::mojom::TextDirection>(value));
+ case ax::mojom::IntAttribute::kTextPosition:
+ return ui::ToString(static_cast<ax::mojom::TextPosition>(value));
// No pretty printing necessary for these:
case ax::mojom::IntAttribute::kActivedescendantId:
case ax::mojom::IntAttribute::kAriaCellColumnIndex:
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
index 9d32091c650..f5281e28968 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
@@ -129,7 +129,9 @@ CONTENT_EXPORT base::string16 IAccessible2RoleToString(int32_t ia2_role) {
QUOTE(IA2_ROLE_TOGGLE_BUTTON),
QUOTE(IA2_ROLE_UNKNOWN),
QUOTE(IA2_ROLE_VIEW_PORT),
- };
+ QUOTE(IA2_ROLE_COMPLEMENTARY_CONTENT),
+ QUOTE(IA2_ROLE_LANDMARK),
+ QUOTE(IA2_ROLE_LEVEL_BAR)};
return GetNameForPlatformConstant(ia2_table, arraysize(ia2_table), ia2_role);
}
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 5d928bb9524..089946e6c50 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -14,6 +14,7 @@
#include "base/process/process_handle.h"
#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_variant.h"
@@ -48,14 +49,14 @@ namespace content {
namespace {
-
-const char INPUT_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33) "
+constexpr char kInputContents[] =
+ "Moz/5.0 (ST 6.x; WWW33) "
"WebKit \"KHTML, like\".";
-const char TEXTAREA_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33)\n"
+constexpr char kTextareaContents[] =
+ "Moz/5.0 (ST 6.x; WWW33)\n"
"WebKit \n\"KHTML, like\".";
-const LONG CONTENTS_LENGTH = static_cast<LONG>(
- (sizeof(INPUT_CONTENTS) - 1) / sizeof(char));
-
+constexpr LONG kContentsLength =
+ static_cast<LONG>((sizeof(kInputContents) - 1) / sizeof(char));
// AccessibilityWinBrowserTest ------------------------------------------------
@@ -70,18 +71,22 @@ class AccessibilityWinBrowserTest : public ContentBrowserTest {
const std::string& html,
ui::AXMode accessibility_mode = ui::kAXModeComplete);
IAccessible* GetRendererAccessible();
+ base::string16 PrintAXTree() const;
void ExecuteScript(const std::wstring& script);
void SetUpInputField(Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
+ void SetUpScrollableInputField(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpTextareaField(
Microsoft::WRL::ComPtr<IAccessibleText>* textarea_text);
void SetUpSampleParagraph(
Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text,
ui::AXMode accessibility_mode = ui::kAXModeComplete);
- void SetUpSampleParagraphWithScroll(
+ void SetUpSampleParagraphInScrollableDocument(
+ Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text,
+ ui::AXMode accessibility_mode = ui::kAXModeComplete);
+ void SetUpSampleParagraphInScrollableEditable(
Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text,
ui::AXMode accessibility_mode = ui::kAXModeComplete);
- void SetUpSampleParagraphHelper(
- Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text);
static Microsoft::WRL::ComPtr<IAccessible> GetAccessibleFromVariant(
IAccessible* parent,
@@ -103,6 +108,11 @@ class AccessibilityWinBrowserTest : public ContentBrowserTest {
IAccessible* element);
private:
+ void SetUpInputFieldHelper(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
+ void SetUpSampleParagraphHelper(
+ Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text);
+
DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest);
};
@@ -118,11 +128,29 @@ void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
accessibility_mode,
ax::mojom::Event::kLoadComplete);
- GURL html_data_url("data:text/html," + html);
+ GURL html_data_url("data:text/html," +
+ net::EscapeQueryParamValue(html, false));
NavigateToURL(shell(), html_data_url);
waiter.WaitForNotification();
}
+base::string16 AccessibilityWinBrowserTest::PrintAXTree() const {
+ std::unique_ptr<AccessibilityTreeFormatter> formatter(
+ AccessibilityTreeFormatter::Create());
+ DCHECK(formatter);
+ formatter->set_show_ids(true);
+ formatter->SetFilters({AccessibilityTreeFormatter::Filter(
+ L"*", AccessibilityTreeFormatter::Filter::ALLOW)});
+
+ base::string16 str;
+ formatter->FormatAccessibilityTree(
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetRootBrowserAccessibilityManager()
+ ->GetRoot(),
+ &str);
+ return str;
+}
+
// Retrieve the MSAA client accessibility object for the Render Widget Host View
// of the selected tab.
IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() {
@@ -135,35 +163,66 @@ void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) {
}
// Loads a page with an input text field and places sample text in it. Also,
-// places the caret on the last character.
+// places the caret before the last character.
void AccessibilityWinBrowserTest::SetUpInputField(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
ASSERT_NE(nullptr, input_text);
- LoadInitialAccessibilityTreeFromHtml(std::string("<!DOCTYPE html><html><body>"
- "<form><label for='textField'>Browser name:</label>"
- "<input type='text' id='textField' name='name' value='") +
- net::EscapeQueryParamValue(INPUT_CONTENTS, false) + std::string(
- "'></form></body></html>"));
+ LoadInitialAccessibilityTreeFromHtml(std::string(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <form>
+ <label for="textField">Browser name:</label>
+ <input type="text" id="textField" name="name" value=")HTML") +
+ net::EscapeForHTML(kInputContents) +
+ std::string(R"HTML(">
+ </form>
+ </body>
+ </html>)HTML"));
+
+ SetUpInputFieldHelper(input_text);
+}
+
+// Loads a page with an input text field and places sample text in it that
+// overflows its width. Also, places the caret before the last character.
+void AccessibilityWinBrowserTest::SetUpScrollableInputField(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
+ ASSERT_NE(nullptr, input_text);
+ LoadInitialAccessibilityTreeFromHtml(std::string(
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <input type="text" style="width: 30px;" value=")HTML") +
+ net::EscapeForHTML(kInputContents) +
+ std::string(R"HTML(">
+ </body>
+ </html>)HTML"));
- // Retrieve the IAccessible interface for the web page.
+ SetUpInputFieldHelper(input_text);
+}
+
+void AccessibilityWinBrowserTest::SetUpInputFieldHelper(
+ Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
std::vector<base::win::ScopedVariant> document_children =
GetAllAccessibleChildren(document.Get());
ASSERT_EQ(1u, document_children.size());
- Microsoft::WRL::ComPtr<IAccessible2> form;
+ Microsoft::WRL::ComPtr<IAccessible2> div;
ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2(
GetAccessibleFromVariant(document.Get(), document_children[0].AsInput())
.Get(),
- form.GetAddressOf()));
- std::vector<base::win::ScopedVariant> form_children =
- GetAllAccessibleChildren(form.Get());
- ASSERT_EQ(2u, form_children.size());
+ div.GetAddressOf()));
+ std::vector<base::win::ScopedVariant> div_children =
+ GetAllAccessibleChildren(div.Get());
+ ASSERT_LT(0u, div_children.size());
- // Find the input text field.
+ // The input field is always the last child.
Microsoft::WRL::ComPtr<IAccessible2> input;
ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2(
- GetAccessibleFromVariant(form.Get(), form_children[1].AsInput()).Get(),
+ GetAccessibleFromVariant(div.Get(),
+ div_children[div_children.size() - 1].AsInput())
+ .Get(),
input.GetAddressOf()));
LONG input_role = 0;
ASSERT_HRESULT_SUCCEEDED(input->role(&input_role));
@@ -172,29 +231,32 @@ void AccessibilityWinBrowserTest::SetUpInputField(
// Retrieve the IAccessibleText interface for the field.
ASSERT_HRESULT_SUCCEEDED(input.CopyTo(input_text->GetAddressOf()));
- // Set the caret on the last character.
+ // Set the caret before the last character.
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kTextSelectionChanged);
- std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
- static_cast<int>(CONTENTS_LENGTH - 1)));
- ExecuteScript(std::wstring(
- L"var textField = document.getElementById('textField');"
- L"textField.focus();"
- L"textField.setSelectionRange(") +
- caret_offset + L"," + caret_offset + L");");
+ std::wstring caret_offset = base::UTF16ToWide(
+ base::IntToString16(static_cast<int>(kContentsLength - 1)));
+ ExecuteScript(std::wstring(L"let textField = document.querySelector('input');"
+ L"textField.focus();"
+ L"textField.setSelectionRange(") +
+ caret_offset + L"," + caret_offset + L");");
waiter.WaitForNotification();
}
// Loads a page with a textarea text field and places sample text in it. Also,
-// places the caret on the last character.
+// places the caret before the last character.
void AccessibilityWinBrowserTest::SetUpTextareaField(
Microsoft::WRL::ComPtr<IAccessibleText>* textarea_text) {
ASSERT_NE(nullptr, textarea_text);
- LoadInitialAccessibilityTreeFromHtml(std::string("<!DOCTYPE html><html><body>"
- "<textarea id='textField' rows='3' cols='60'>") +
- net::EscapeQueryParamValue(TEXTAREA_CONTENTS, false) + std::string(
- "</textarea></body></html>"));
+ LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <textarea rows="3" cols="60">)HTML") +
+ net::EscapeForHTML(kTextareaContents) +
+ std::string(R"HTML(</textarea>
+ </body>
+ </html>)HTML"));
// Retrieve the IAccessible interface for the web page.
Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
@@ -224,16 +286,16 @@ void AccessibilityWinBrowserTest::SetUpTextareaField(
// Retrieve the IAccessibleText interface for the field.
ASSERT_HRESULT_SUCCEEDED(textarea.CopyTo(textarea_text->GetAddressOf()));
- // Set the caret on the last character.
+ // Set the caret before the last character.
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kTextSelectionChanged);
- std::wstring caret_offset = base::UTF16ToWide(base::IntToString16(
- static_cast<int>(CONTENTS_LENGTH - 1)));
- ExecuteScript(std::wstring(
- L"var textField = document.getElementById('textField');"
- L"textField.focus();"
- L"textField.setSelectionRange(") +
+ std::wstring caret_offset = base::UTF16ToWide(
+ base::IntToString16(static_cast<int>(kContentsLength - 1)));
+ ExecuteScript(
+ std::wstring(L"var textField = document.querySelector('textarea');"
+ L"textField.focus();"
+ L"textField.setSelectionRange(") +
caret_offset + L"," + caret_offset + L");");
waiter.WaitForNotification();
}
@@ -243,12 +305,16 @@ void AccessibilityWinBrowserTest::SetUpSampleParagraph(
Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text,
ui::AXMode accessibility_mode) {
LoadInitialAccessibilityTreeFromHtml(
- "<!DOCTYPE html><html>"
- "<body>"
- "<p><b>Game theory</b> is \"the study of "
- "<a href=\"#\" title=\"Mathematical model\">mathematical models</a> "
- "of conflict and<br>cooperation between intelligent rational "
- "decision-makers.\"</p></body></html>",
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <p><b>Game theory</b> is "the study of
+ <a href="" title="Mathematical model">mathematical models</a>
+ of conflict and<br>cooperation between intelligent rational
+ decision-makers."
+ </p>
+ </body>
+ </html>)HTML",
accessibility_mode);
SetUpSampleParagraphHelper(accessible_text);
@@ -256,21 +322,55 @@ void AccessibilityWinBrowserTest::SetUpSampleParagraph(
// Loads a page with a paragraph of sample text which is below the
// bottom of the screen.
-void AccessibilityWinBrowserTest::SetUpSampleParagraphWithScroll(
+void AccessibilityWinBrowserTest::SetUpSampleParagraphInScrollableDocument(
Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text,
ui::AXMode accessibility_mode) {
LoadInitialAccessibilityTreeFromHtml(
- "<!DOCTYPE html><html>"
- "<body style=\"overflow: scroll; margin-top: 100vh\">"
- "<p><b>Game theory</b> is \"the study of "
- "<a href=\"#\" title=\"Mathematical model\">mathematical models</a> "
- "of conflict and<br>cooperation between intelligent rational "
- "decision-makers.\"</p></body></html>",
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body style="overflow: scroll; margin-top: 100vh">
+ <p><b>Game theory</b> is "the study of
+ <a href="" title="Mathematical model">mathematical models</a>
+ of conflict and<br>cooperation between intelligent rational
+ decision-makers."
+ </p>
+ </body>
+ </html>)HTML",
accessibility_mode);
SetUpSampleParagraphHelper(accessible_text);
}
+// Loads a page with a content editable whose text overflows its height.
+// Places the caret at the beginning of the editable's last line but doesn't
+// scroll the editable.
+void AccessibilityWinBrowserTest::SetUpSampleParagraphInScrollableEditable(
+ Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text,
+ ui::AXMode accessibility_mode) {
+ LoadInitialAccessibilityTreeFromHtml(
+ R"HTML(<p contenteditable="true"
+ style="height: 30px; overflow: scroll;">
+ hello<br><br><br>hello
+ </p>)HTML",
+ accessibility_mode);
+
+ AccessibilityNotificationWaiter selection_waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kTextSelectionChanged);
+ ExecuteScript(
+ L"let selection=document.getSelection();"
+ L"let range=document.createRange();"
+ L"let editable=document.querySelector('p[contenteditable=\"true\"]');"
+ L"editable.focus();"
+ L"range.setStart(editable.lastChild, 0);"
+ L"range.setEnd(editable.lastChild, 0);"
+ L"selection.removeAllRanges();"
+ L"selection.addRange(range);");
+ selection_waiter.WaitForNotification();
+
+ SetUpSampleParagraphHelper(accessible_text);
+}
+
void AccessibilityWinBrowserTest::SetUpSampleParagraphHelper(
Microsoft::WRL::ComPtr<IAccessibleText>* accessible_text) {
ASSERT_NE(nullptr, accessible_text);
@@ -286,9 +386,11 @@ void AccessibilityWinBrowserTest::SetUpSampleParagraphHelper(
GetAccessibleFromVariant(document.Get(), document_children[0].AsInput())
.Get(),
paragraph.GetAddressOf()));
+
LONG paragraph_role = 0;
ASSERT_HRESULT_SUCCEEDED(paragraph->role(&paragraph_role));
ASSERT_EQ(IA2_ROLE_PARAGRAPH, paragraph_role);
+
ASSERT_HRESULT_SUCCEEDED(paragraph.CopyTo(accessible_text->GetAddressOf()));
}
@@ -417,9 +519,9 @@ AccessibilityWinBrowserTest::GetAllAccessibleChildren(
std::vector<base::win::ScopedVariant> children(
static_cast<size_t>(child_count));
- for (size_t i = 0; i < children.size(); i++) {
+ for (size_t i = 0; i < children.size(); i++)
children[i].Reset(children_array[i]);
- }
+
return children;
}
@@ -1085,17 +1187,18 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(-1, height);
}
-IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestCharacterExtents) {
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestCharacterExtentsInEditable) {
Microsoft::WRL::ComPtr<IAccessibleText> paragraph_text;
SetUpSampleParagraph(&paragraph_text);
- const LONG newline_offset = 46;
+ constexpr LONG newline_offset = 46;
LONG n_characters;
ASSERT_HRESULT_SUCCEEDED(paragraph_text->get_nCharacters(&n_characters));
- ASSERT_LT(0, n_characters);
+ ASSERT_EQ(105, n_characters);
LONG x, y, width, height;
- LONG previous_x, previous_y;
+ LONG previous_x, previous_y, previous_height;
for (int coordinate = IA2_COORDTYPE_SCREEN_RELATIVE;
coordinate <= IA2_COORDTYPE_PARENT_RELATIVE; ++coordinate) {
auto coordinate_type = static_cast<IA2CoordinateType>(coordinate);
@@ -1103,19 +1206,20 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestCharacterExtents) {
0, coordinate_type, &x, &y, &width, &height));
EXPECT_LT(0, x) << "at offset 0";
EXPECT_LT(0, y) << "at offset 0";
- EXPECT_LT(0, width) << "at offset 0";
- EXPECT_LT(0, height) << "at offset 0";
+ EXPECT_LT(1, width) << "at offset 0";
+ EXPECT_LT(1, height) << "at offset 0";
for (LONG offset = 1; offset < newline_offset; ++offset) {
previous_x = x;
previous_y = y;
+ previous_height = height;
EXPECT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
offset, coordinate_type, &x, &y, &width, &height));
EXPECT_LT(previous_x, x) << "at offset " << offset;
EXPECT_EQ(previous_y, y) << "at offset " << offset;
- EXPECT_LT(0, width) << "at offset " << offset;
- EXPECT_LT(0, height) << "at offset " << offset;
+ EXPECT_LT(1, width) << "at offset " << offset;
+ EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
EXPECT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
@@ -1123,19 +1227,160 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestCharacterExtents) {
EXPECT_LE(0, x) << "at offset " << newline_offset + 1;
EXPECT_GT(previous_x, x) << "at offset " << newline_offset + 1;
EXPECT_LT(previous_y, y) << "at offset " << newline_offset + 1;
- EXPECT_LT(0, width) << "at offset " << newline_offset + 1;
- EXPECT_LT(0, height) << "at offset " << newline_offset + 1;
+ EXPECT_LT(1, width) << "at offset " << newline_offset + 1;
+ EXPECT_EQ(previous_height, height) << "at offset " << newline_offset + 1;
for (LONG offset = newline_offset + 2; offset < n_characters; ++offset) {
previous_x = x;
previous_y = y;
+ previous_height = height;
EXPECT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
offset, coordinate_type, &x, &y, &width, &height));
EXPECT_LT(previous_x, x) << "at offset " << offset;
EXPECT_EQ(previous_y, y) << "at offset " << offset;
- EXPECT_LT(0, width) << "at offset " << offset;
- EXPECT_LT(0, height) << "at offset " << offset;
+ EXPECT_LT(1, width) << "at offset " << offset;
+ EXPECT_EQ(previous_height, height) << "at offset " << offset;
+ }
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestCharacterExtentsInScrollableEditable) {
+ Microsoft::WRL::ComPtr<IAccessibleText> editable_container;
+ // By construction, only the first line of the content editable is visible.
+ SetUpSampleParagraphInScrollableEditable(&editable_container);
+
+ constexpr LONG first_line_end = 5;
+ constexpr LONG last_line_start = 8;
+ LONG n_characters;
+ ASSERT_HRESULT_SUCCEEDED(editable_container->get_nCharacters(&n_characters));
+ ASSERT_EQ(13, n_characters);
+ LONG caret_offset;
+ ASSERT_HRESULT_SUCCEEDED(editable_container->get_caretOffset(&caret_offset));
+ ASSERT_EQ(last_line_start, caret_offset);
+
+ LONG x, y, width, height;
+ LONG previous_x, previous_y, previous_height;
+ for (int coordinate = IA2_COORDTYPE_SCREEN_RELATIVE;
+ coordinate <= IA2_COORDTYPE_PARENT_RELATIVE; ++coordinate) {
+ auto coordinate_type = static_cast<IA2CoordinateType>(coordinate);
+
+ // Test that non offscreen characters have increasing x coordinates and a
+ // height that is greater than 1px.
+ EXPECT_HRESULT_SUCCEEDED(editable_container->get_characterExtents(
+ 0, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(0, x) << "at offset 0";
+ EXPECT_LT(0, y) << "at offset 0";
+ EXPECT_LT(1, width) << "at offset 0";
+ EXPECT_LT(1, height) << "at offset 0";
+
+ for (LONG offset = 1; offset < first_line_end; ++offset) {
+ previous_x = x;
+ previous_y = y;
+ previous_height = height;
+
+ EXPECT_HRESULT_SUCCEEDED(editable_container->get_characterExtents(
+ offset, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(previous_x, x) << "at offset " << offset;
+ EXPECT_EQ(previous_y, y) << "at offset " << offset;
+ EXPECT_LT(1, width) << "at offset " << offset;
+ EXPECT_EQ(previous_height, height) << "at offset " << offset;
+ }
+
+ // Vertically offscreen objects should have a height of 1px so that if an
+ // assistive aid ignores the offscreen state, they will still be too small
+ // to be visible and thus not appear outside the window. Note that a height
+ // of 0 is not used because it signifies an invalid size.
+ EXPECT_HRESULT_SUCCEEDED(editable_container->get_characterExtents(
+ last_line_start, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(0, x) << "at offset " << last_line_start;
+ EXPECT_LT(previous_y, y) << "at offset " << last_line_start;
+ EXPECT_LT(1, width) << "at offset " << last_line_start;
+ EXPECT_EQ(1, height) << "at offset " << last_line_start;
+
+ for (LONG offset = last_line_start + 1; offset < n_characters; ++offset) {
+ previous_x = x;
+ previous_y = y;
+
+ EXPECT_HRESULT_SUCCEEDED(editable_container->get_characterExtents(
+ offset, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(previous_x, x) << "at offset " << offset;
+ EXPECT_EQ(previous_y, y) << "at offset " << offset;
+ EXPECT_LT(1, width) << "at offset " << offset;
+ EXPECT_EQ(1, height) << "at offset " << offset;
+ }
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ DISABLED_TestCharacterExtentsInScrollableInputField) {
+ Microsoft::WRL::ComPtr<IAccessibleText> input_text;
+ SetUpScrollableInputField(&input_text);
+
+ constexpr LONG visible_characters_start = 20;
+ LONG n_characters;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
+ ASSERT_EQ(kContentsLength, n_characters);
+ LONG caret_offset;
+ ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
+ ASSERT_EQ(kContentsLength - 1, caret_offset);
+
+ LONG x, y, width, height;
+ LONG previous_x, previous_y, previous_height;
+ for (int coordinate = IA2_COORDTYPE_SCREEN_RELATIVE;
+ coordinate <= IA2_COORDTYPE_PARENT_RELATIVE; ++coordinate) {
+ auto coordinate_type = static_cast<IA2CoordinateType>(coordinate);
+
+ // Horizontally offscreen objects should have a width of 1px so that if an
+ // assistive aid ignores the offscreen state, they will still be too small
+ // to be visible and thus not appear outside the window. Note that a width
+ // of 0 is not used because it signifies an invalid size.
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ 0, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(0, x) << "at offset 0";
+ EXPECT_LT(0, y) << "at offset 0";
+ EXPECT_EQ(1, width) << "at offset 0";
+ EXPECT_LT(1, height) << "at offset 0";
+
+ // Test that characters at the start of the input field are offscreen by
+ // checking that their x coordinate is at the start of the field and their
+ // width is 1.
+ for (LONG offset = 1; offset < visible_characters_start; ++offset) {
+ previous_x = x;
+ previous_y = y;
+ previous_height = height;
+
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ offset, coordinate_type, &x, &y, &width, &height));
+ EXPECT_EQ(previous_x, x) << "at offset " << offset;
+ EXPECT_EQ(previous_y, y) << "at offset " << offset;
+ EXPECT_EQ(1, width) << "at offset " << offset;
+ EXPECT_LT(previous_height, height) << "at offset " << offset;
+ }
+
+ // Test that non offscreen characters have increasing x coordinates and a
+ // width that is greater than 1px.
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ visible_characters_start, coordinate_type, &x, &y, &width, &height));
+ EXPECT_EQ(previous_x, x) << "at offset " << visible_characters_start;
+ EXPECT_EQ(previous_y, y) << "at offset " << visible_characters_start;
+ EXPECT_LT(1, width) << "at offset " << visible_characters_start;
+ EXPECT_EQ(previous_height, height)
+ << "at offset " << visible_characters_start;
+
+ for (LONG offset = visible_characters_start + 1; offset < n_characters;
+ ++offset) {
+ previous_x = x;
+ previous_y = y;
+ previous_height = height;
+
+ EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
+ offset, coordinate_type, &x, &y, &width, &height));
+ EXPECT_LT(previous_x, x) << "at offset " << offset;
+ EXPECT_EQ(previous_y, y) << "at offset " << offset;
+ EXPECT_LT(1, width) << "at offset " << offset;
+ EXPECT_EQ(previous_height, height) << "at offset " << offset;
}
}
}
@@ -1148,11 +1393,11 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
ui::AXMode::kScreenReader);
LONG x, y, width, height;
- AccessibilityNotificationWaiter waiter(shell()->web_contents(),
- ui::AXMode::kNativeAPIs |
- ui::AXMode::kWebContents |
- ui::AXMode::kScreenReader,
- ax::mojom::Event::kLoadComplete);
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(),
+ ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents |
+ ui::AXMode::kScreenReader | ui::AXMode::kInlineTextBoxes,
+ ax::mojom::Event::kLoadComplete);
EXPECT_HRESULT_SUCCEEDED(paragraph_text->get_characterExtents(
0, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
// X and y coordinates should be available without
@@ -1168,13 +1413,13 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
0, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
EXPECT_LT(0, x);
EXPECT_LT(0, y);
- EXPECT_LT(0, width);
- EXPECT_LT(0, height);
+ EXPECT_LT(1, width);
+ EXPECT_LT(1, height);
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestScrollToPoint) {
Microsoft::WRL::ComPtr<IAccessibleText> accessible_text;
- SetUpSampleParagraphWithScroll(&accessible_text);
+ SetUpSampleParagraphInScrollableDocument(&accessible_text);
Microsoft::WRL::ComPtr<IAccessible2> paragraph;
ASSERT_HRESULT_SUCCEEDED(
accessible_text.CopyTo(IID_PPV_ARGS(&paragraph)));
@@ -1213,7 +1458,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetCaretOffset) {
LONG caret_offset = 0;
HRESULT hr = input_text->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
+ EXPECT_EQ(kContentsLength - 1, caret_offset);
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), ui::kAXModeComplete,
@@ -1236,7 +1481,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
LONG caret_offset = 0;
HRESULT hr = textarea_text->get_caretOffset(&caret_offset);
EXPECT_EQ(S_OK, hr);
- EXPECT_EQ(CONTENTS_LENGTH - 1, caret_offset);
+ EXPECT_EQ(kContentsLength - 1, caret_offset);
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), ui::kAXModeComplete,
@@ -1266,7 +1511,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetSelection) {
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kTextSelectionChanged);
start_offset = 0;
- end_offset = CONTENTS_LENGTH;
+ end_offset = kContentsLength;
EXPECT_HRESULT_FAILED(input_text->setSelection(1, start_offset, end_offset));
EXPECT_HRESULT_SUCCEEDED(
input_text->setSelection(0, start_offset, end_offset));
@@ -1275,9 +1520,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetSelection) {
hr = input_text->get_selection(0, &start_offset, &end_offset);
EXPECT_EQ(S_OK, hr);
EXPECT_EQ(0, start_offset);
- EXPECT_EQ(CONTENTS_LENGTH, end_offset);
+ EXPECT_EQ(kContentsLength, end_offset);
- start_offset = CONTENTS_LENGTH;
+ start_offset = kContentsLength;
end_offset = 1;
EXPECT_HRESULT_SUCCEEDED(
input_text->setSelection(0, start_offset, end_offset));
@@ -1287,7 +1532,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetSelection) {
EXPECT_EQ(S_OK, hr);
// Start and end offsets are always swapped to be in ascending order.
EXPECT_EQ(1, start_offset);
- EXPECT_EQ(CONTENTS_LENGTH, end_offset);
+ EXPECT_EQ(kContentsLength, end_offset);
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestMultiLineSetSelection) {
@@ -1305,7 +1550,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestMultiLineSetSelection) {
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kTextSelectionChanged);
start_offset = 0;
- end_offset = CONTENTS_LENGTH;
+ end_offset = kContentsLength;
EXPECT_HRESULT_FAILED(
textarea_text->setSelection(1, start_offset, end_offset));
EXPECT_HRESULT_SUCCEEDED(
@@ -1315,9 +1560,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestMultiLineSetSelection) {
hr = textarea_text->get_selection(0, &start_offset, &end_offset);
EXPECT_EQ(S_OK, hr);
EXPECT_EQ(0, start_offset);
- EXPECT_EQ(CONTENTS_LENGTH, end_offset);
+ EXPECT_EQ(kContentsLength, end_offset);
- start_offset = CONTENTS_LENGTH - 1;
+ start_offset = kContentsLength - 1;
end_offset = 0;
EXPECT_HRESULT_SUCCEEDED(
textarea_text->setSelection(0, start_offset, end_offset));
@@ -1327,7 +1572,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestMultiLineSetSelection) {
EXPECT_EQ(S_OK, hr);
// Start and end offsets are always swapped to be in ascending order.
EXPECT_EQ(0, start_offset);
- EXPECT_EQ(CONTENTS_LENGTH - 1, end_offset);
+ EXPECT_EQ(kContentsLength - 1, end_offset);
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -1388,7 +1633,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(0, start_offset);
EXPECT_EQ(0, end_offset);
EXPECT_EQ(nullptr, static_cast<BSTR>(text));
- invalid_offset = CONTENTS_LENGTH + 1;
+ invalid_offset = kContentsLength + 1;
hr = input_text->get_textAtOffset(
invalid_offset, IA2_TEXT_BOUNDARY_WORD,
&start_offset, &end_offset, text.Receive());
@@ -1399,7 +1644,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// According to the IA2 Spec, only line boundaries should succeed when
// the offset is one past the end of the text.
- invalid_offset = CONTENTS_LENGTH;
+ invalid_offset = kContentsLength;
hr = input_text->get_textAtOffset(
invalid_offset, IA2_TEXT_BOUNDARY_CHAR,
&start_offset, &end_offset, text.Receive());
@@ -1481,7 +1726,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_EQ(0, start_offset);
EXPECT_EQ(0, end_offset);
EXPECT_EQ(nullptr, static_cast<BSTR>(text));
- invalid_offset = CONTENTS_LENGTH + 1;
+ invalid_offset = kContentsLength + 1;
hr = textarea_text->get_textAtOffset(
invalid_offset, IA2_TEXT_BOUNDARY_WORD,
&start_offset, &end_offset, text.Receive());
@@ -1492,7 +1737,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// According to the IA2 Spec, only line boundaries should succeed when
// the offset is one past the end of the text.
- invalid_offset = CONTENTS_LENGTH;
+ invalid_offset = kContentsLength;
hr = textarea_text->get_textAtOffset(
invalid_offset, IA2_TEXT_BOUNDARY_CHAR,
&start_offset, &end_offset, text.Receive());
@@ -1558,40 +1803,40 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestTextAtOffsetWithBoundaryCharacter) {
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpInputField(&input_text);
- for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) {
- std::wstring expected_text(1, INPUT_CONTENTS[offset]);
+ for (LONG offset = 0; offset < kContentsLength; ++offset) {
+ std::wstring expected_text(1, kInputContents[offset]);
LONG expected_start_offset = offset;
LONG expected_end_offset = offset + 1;
CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR,
expected_start_offset, expected_end_offset, expected_text);
}
- for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) {
- std::wstring expected_text(1, INPUT_CONTENTS[offset]);
+ for (LONG offset = kContentsLength - 1; offset >= 0; --offset) {
+ std::wstring expected_text(1, kInputContents[offset]);
LONG expected_start_offset = offset;
LONG expected_end_offset = offset + 1;
CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR,
expected_start_offset, expected_end_offset, expected_text);
}
- CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET,
- IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L".");
+ CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, IA2_TEXT_BOUNDARY_CHAR,
+ kContentsLength - 1, kContentsLength, L".");
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestMultiLineTextAtOffsetWithBoundaryCharacter) {
Microsoft::WRL::ComPtr<IAccessibleText> textarea_text;
SetUpTextareaField(&textarea_text);
- for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) {
- std::wstring expected_text(1, TEXTAREA_CONTENTS[offset]);
+ for (LONG offset = 0; offset < kContentsLength; ++offset) {
+ std::wstring expected_text(1, kTextareaContents[offset]);
LONG expected_start_offset = offset;
LONG expected_end_offset = offset + 1;
CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR,
expected_start_offset, expected_end_offset, expected_text);
}
- for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) {
- std::wstring expected_text(1, TEXTAREA_CONTENTS[offset]);
+ for (LONG offset = kContentsLength - 1; offset >= 0; --offset) {
+ std::wstring expected_text(1, kTextareaContents[offset]);
LONG expected_start_offset = offset;
LONG expected_end_offset = offset + 1;
CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR,
@@ -1599,7 +1844,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
}
CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
- IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L".");
+ IA2_TEXT_BOUNDARY_CHAR, kContentsLength - 1,
+ kContentsLength, L".");
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -1664,14 +1910,14 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
33, 40, L"KHTML, ");
// Trailing final punctuation should be part of the last word.
- CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD,
- 40, CONTENTS_LENGTH, L"like\".");
- CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD,
- 40, CONTENTS_LENGTH, L"like\".");
+ CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD, 40, kContentsLength,
+ L"like\".");
+ CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD, 40, kContentsLength,
+ L"like\".");
// Test special offsets.
- CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET,
- IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\".");
+ CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, IA2_TEXT_BOUNDARY_WORD,
+ 40, kContentsLength, L"like\".");
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -1736,14 +1982,14 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
33, 40, L"KHTML, ");
// Trailing final punctuation should be part of the last word.
- CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD,
- 40, CONTENTS_LENGTH, L"like\".");
- CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD,
- 40, CONTENTS_LENGTH, L"like\".");
+ CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD, 40,
+ kContentsLength, L"like\".");
+ CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD, 40,
+ kContentsLength, L"like\".");
// Test special offsets.
CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
- IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\".");
+ IA2_TEXT_BOUNDARY_WORD, 40, kContentsLength, L"like\".");
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -1822,14 +2068,14 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
SetUpInputField(&input_text);
// Single line text fields should return the whole text.
- CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_LINE,
- 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
+ CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_LINE, 0, kContentsLength,
+ base::SysUTF8ToWide(kInputContents));
// Test special offsets.
CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_LINE,
- 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
+ 0, kContentsLength, base::SysUTF8ToWide(kInputContents));
CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, IA2_TEXT_BOUNDARY_LINE,
- 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
+ 0, kContentsLength, base::SysUTF8ToWide(kInputContents));
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -1845,18 +2091,20 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
24, 32, L"WebKit \n");
// Last line does not have a trailing newline.
- CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_LINE,
- 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
+ CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_LINE, 32,
+ kContentsLength, L"\"KHTML, like\".");
// An offset one past the last character should return the last line.
- CheckTextAtOffset(textarea_text, CONTENTS_LENGTH, IA2_TEXT_BOUNDARY_LINE,
- 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
+ CheckTextAtOffset(textarea_text, kContentsLength, IA2_TEXT_BOUNDARY_LINE, 32,
+ kContentsLength, L"\"KHTML, like\".");
// Test special offsets.
CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_LENGTH,
- IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
+ IA2_TEXT_BOUNDARY_LINE, 32, kContentsLength,
+ L"\"KHTML, like\".");
CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
- IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\".");
+ IA2_TEXT_BOUNDARY_LINE, 32, kContentsLength,
+ L"\"KHTML, like\".");
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -1892,8 +2140,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpInputField(&input_text);
- CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL,
- 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS));
+ CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL, 0, kContentsLength,
+ base::SysUTF8ToWide(kInputContents));
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -1901,16 +2149,19 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
Microsoft::WRL::ComPtr<IAccessibleText> textarea_text;
SetUpTextareaField(&textarea_text);
- CheckTextAtOffset(textarea_text, CONTENTS_LENGTH - 1, IA2_TEXT_BOUNDARY_ALL,
- 0, CONTENTS_LENGTH, base::SysUTF8ToWide(TEXTAREA_CONTENTS));
+ CheckTextAtOffset(textarea_text, kContentsLength - 1, IA2_TEXT_BOUNDARY_ALL,
+ 0, kContentsLength, base::SysUTF8ToWide(kTextareaContents));
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestIAccessibleAction) {
LoadInitialAccessibilityTreeFromHtml(
- "<!DOCTYPE html><html><body>"
- "<img src=\"\" alt=\"image\" "
- "onclick=\"document.querySelector('img').alt = 'image2';\">"
- "</body></html>");
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <img src="" alt="image"
+ onclick="document.querySelector('img').alt = 'image2';">
+ </body>
+ </html>)HTML");
// Retrieve the IAccessible interface for the web page.
Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
@@ -2104,13 +2355,16 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestAccNavigateInTables) {
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestScrollTo) {
LoadInitialAccessibilityTreeFromHtml(
- "<!DOCTYPE html><html><body>"
- "<div style='height: 5000px;'></div>"
- "<img src='#' alt='Target1'>"
- "<div style='height: 5000px;'></div>"
- "<img src='#' alt='Target2'>"
- "<div style='height: 5000px;'></div>"
- "</body></html>");
+ R"HTML(<!DOCTYPE html>
+ <html>
+ <body>
+ <div style="height: 5000px;"></div>
+ <img src="" alt="Target1">
+ <div style="height: 5000px;"></div>
+ <img src="" alt="Target2">
+ <div style="height: 5000px;"></div>
+ </body>
+ </html>)HTML");
// Retrieve the IAccessible interface for the document node.
Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index bfd96ed1eb6..64868046c9a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -16,6 +16,7 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/common/accessibility_messages.h"
#include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_table_info.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/accessibility/platform/ax_unique_id.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -58,6 +59,8 @@ bool BrowserAccessibility::PlatformIsLeaf() const {
// (Note that whilst ARIA buttons can have only presentational children, HTML5
// buttons are allowed to have content.)
switch (GetRole()) {
+ case ax::mojom::Role::kDocCover:
+ case ax::mojom::Role::kGraphicsSymbol:
case ax::mojom::Role::kImage:
case ax::mojom::Role::kMeter:
case ax::mojom::Role::kScrollBar:
@@ -955,6 +958,83 @@ BrowserAccessibility::GetTargetForNativeAccessibilityEvent() {
return root_delegate->AccessibilityGetAcceleratedWidget();
}
+int BrowserAccessibility::GetTableRowCount() const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return 0;
+
+ return table_info->row_count;
+}
+
+int BrowserAccessibility::GetTableColCount() const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return 0;
+
+ return table_info->col_count;
+}
+
+std::vector<int32_t> BrowserAccessibility::GetColHeaderNodeIds(
+ int32_t col_index) const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return std::vector<int32_t>();
+
+ if (col_index < 0 || col_index >= table_info->col_count)
+ return std::vector<int32_t>();
+
+ return table_info->col_headers[col_index];
+}
+
+std::vector<int32_t> BrowserAccessibility::GetRowHeaderNodeIds(
+ int32_t row_index) const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return std::vector<int32_t>();
+
+ if (row_index < 0 || row_index >= table_info->row_count)
+ return std::vector<int32_t>();
+
+ return table_info->row_headers[row_index];
+}
+
+int32_t BrowserAccessibility::GetCellId(int32_t row_index,
+ int32_t col_index) const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return -1;
+
+ if (row_index < 0 || row_index >= table_info->row_count || col_index < 0 ||
+ col_index >= table_info->col_count)
+ return -1;
+
+ return table_info->cell_ids[row_index][col_index];
+}
+
+int32_t BrowserAccessibility::CellIdToIndex(int32_t cell_id) const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return -1;
+
+ const auto& iter = table_info->cell_id_to_index.find(cell_id);
+ if (iter != table_info->cell_id_to_index.end())
+ return iter->second;
+
+ return -1;
+}
+
+int32_t BrowserAccessibility::CellIndexToId(int32_t cell_index) const {
+ ui::AXTableInfo* table_info = manager()->ax_tree()->GetTableInfo(node());
+ if (!table_info)
+ return -1;
+
+ if (cell_index < 0 ||
+ cell_index >= static_cast<int32_t>(table_info->unique_cell_ids.size()))
+ return -1;
+
+ return table_info->unique_cell_ids[cell_index];
+}
+
bool BrowserAccessibility::AccessibilityPerformAction(
const ui::AXActionData& data) {
switch (data.action) {
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index 2f74f6021c5..83f78a21604 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -341,6 +341,13 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
ui::AXPlatformNode* GetFromNodeID(int32_t id) override;
int GetIndexInParent() const override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
+ int GetTableRowCount() const override;
+ int GetTableColCount() const override;
+ std::vector<int32_t> GetColHeaderNodeIds(int32_t col_index) const override;
+ std::vector<int32_t> GetRowHeaderNodeIds(int32_t row_index) const override;
+ int32_t GetCellId(int32_t row_index, int32_t col_index) const override;
+ int32_t CellIdToIndex(int32_t cell_id) const override;
+ int32_t CellIndexToId(int32_t cell_index) const override;
bool AccessibilityPerformAction(const ui::AXActionData& data) override;
bool ShouldIgnoreHoveredStateForTesting() override;
bool IsOffscreen() const override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 01a094c10bc..0bce59cad23 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -16,9 +16,9 @@
#include "content/common/accessibility_messages.h"
#include "content/public/common/content_client.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/accessibility/ax_assistant_structure.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/platform/ax_android_constants.h"
-#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h"
#include "ui/accessibility/platform/ax_unique_id.h"
namespace {
@@ -253,9 +253,7 @@ bool BrowserAccessibilityAndroid::IsHeading() const {
if (parent && parent->IsHeading())
return true;
- return (GetRole() == ax::mojom::Role::kColumnHeader ||
- GetRole() == ax::mojom::Role::kHeading ||
- GetRole() == ax::mojom::Role::kRowHeader);
+ return ui::IsHeadingOrTableHeader(GetRole());
}
bool BrowserAccessibilityAndroid::IsHierarchical() const {
@@ -265,7 +263,7 @@ bool BrowserAccessibilityAndroid::IsHierarchical() const {
}
bool BrowserAccessibilityAndroid::IsLink() const {
- return ui::AXSnapshotNodeAndroid::AXRoleIsLink(GetRole());
+ return ui::IsLink(GetRole());
}
bool BrowserAccessibilityAndroid::IsMultiLine() const {
@@ -301,8 +299,10 @@ bool BrowserAccessibilityAndroid::IsVisibleToUser() const {
}
bool BrowserAccessibilityAndroid::IsInterestingOnAndroid() const {
+ // The root is not interesting if it doesn't have a title, even
+ // though it's focusable.
if (GetRole() == ax::mojom::Role::kRootWebArea && GetText().empty())
- return true;
+ return false;
// Focusable nodes are always interesting. Note that IsFocusable()
// already skips over things like iframes and child frames that are
@@ -366,12 +366,12 @@ bool BrowserAccessibilityAndroid::AreInlineTextBoxesLoaded() const {
}
bool BrowserAccessibilityAndroid::CanOpenPopup() const {
- return HasState(ax::mojom::State::kHaspopup);
+ return HasIntAttribute(ax::mojom::IntAttribute::kHasPopup);
}
const char* BrowserAccessibilityAndroid::GetClassName() const {
- return ui::AXSnapshotNodeAndroid::AXRoleToAndroidClassName(
- GetRole(), PlatformGetParent() != nullptr);
+ return ui::AXRoleToAndroidClassName(GetRole(),
+ PlatformGetParent() != nullptr);
}
base::string16 BrowserAccessibilityAndroid::GetText() const {
@@ -418,10 +418,10 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
}
}
- if (text.empty() && (IsLink() || GetRole() == ax::mojom::Role::kImage) &&
+ if (text.empty() && (ui::IsLink(GetRole()) || ui::IsImage(GetRole())) &&
!HasExplicitlyEmptyName()) {
base::string16 url = GetString16Attribute(ax::mojom::StringAttribute::kUrl);
- text = ui::AXSnapshotNodeAndroid::AXUrlBaseText(url);
+ text = ui::AXUrlBaseText(url);
}
return text;
@@ -572,6 +572,123 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ax::mojom::Role::kDisclosureTriangle:
message_id = IDS_AX_ROLE_DISCLOSURE_TRIANGLE;
break;
+ case ax::mojom::Role::kDocAbstract:
+ message_id = IDS_AX_ROLE_DOC_ABSTRACT;
+ break;
+ case ax::mojom::Role::kDocAcknowledgments:
+ message_id = IDS_AX_ROLE_DOC_ACKNOWLEDGMENTS;
+ break;
+ case ax::mojom::Role::kDocAfterword:
+ message_id = IDS_AX_ROLE_DOC_AFTERWORD;
+ break;
+ case ax::mojom::Role::kDocAppendix:
+ message_id = IDS_AX_ROLE_DOC_APPENDIX;
+ break;
+ case ax::mojom::Role::kDocBackLink:
+ message_id = IDS_AX_ROLE_DOC_BACKLINK;
+ break;
+ case ax::mojom::Role::kDocBiblioEntry:
+ message_id = IDS_AX_ROLE_DOC_BIBLIO_ENTRY;
+ break;
+ case ax::mojom::Role::kDocBibliography:
+ message_id = IDS_AX_ROLE_DOC_BIBLIOGRAPHY;
+ break;
+ case ax::mojom::Role::kDocBiblioRef:
+ message_id = IDS_AX_ROLE_DOC_BIBLIO_REF;
+ break;
+ case ax::mojom::Role::kDocChapter:
+ message_id = IDS_AX_ROLE_DOC_CHAPTER;
+ break;
+ case ax::mojom::Role::kDocColophon:
+ message_id = IDS_AX_ROLE_DOC_COLOPHON;
+ break;
+ case ax::mojom::Role::kDocConclusion:
+ message_id = IDS_AX_ROLE_DOC_CONCLUSION;
+ break;
+ case ax::mojom::Role::kDocCover:
+ message_id = IDS_AX_ROLE_DOC_COVER;
+ break;
+ case ax::mojom::Role::kDocCredit:
+ message_id = IDS_AX_ROLE_DOC_CREDIT;
+ break;
+ case ax::mojom::Role::kDocCredits:
+ message_id = IDS_AX_ROLE_DOC_CREDITS;
+ break;
+ case ax::mojom::Role::kDocDedication:
+ message_id = IDS_AX_ROLE_DOC_DEDICATION;
+ break;
+ case ax::mojom::Role::kDocEndnote:
+ message_id = IDS_AX_ROLE_DOC_ENDNOTE;
+ break;
+ case ax::mojom::Role::kDocEndnotes:
+ message_id = IDS_AX_ROLE_DOC_ENDNOTES;
+ break;
+ case ax::mojom::Role::kDocEpigraph:
+ message_id = IDS_AX_ROLE_DOC_EPIGRAPH;
+ break;
+ case ax::mojom::Role::kDocEpilogue:
+ message_id = IDS_AX_ROLE_DOC_EPILOGUE;
+ break;
+ case ax::mojom::Role::kDocErrata:
+ message_id = IDS_AX_ROLE_DOC_ERRATA;
+ break;
+ case ax::mojom::Role::kDocExample:
+ message_id = IDS_AX_ROLE_DOC_EXAMPLE;
+ break;
+ case ax::mojom::Role::kDocFootnote:
+ message_id = IDS_AX_ROLE_DOC_FOOTNOTE;
+ break;
+ case ax::mojom::Role::kDocForeword:
+ message_id = IDS_AX_ROLE_DOC_FOREWORD;
+ break;
+ case ax::mojom::Role::kDocGlossary:
+ message_id = IDS_AX_ROLE_DOC_GLOSSARY;
+ break;
+ case ax::mojom::Role::kDocGlossRef:
+ message_id = IDS_AX_ROLE_DOC_GLOSS_REF;
+ break;
+ case ax::mojom::Role::kDocIndex:
+ message_id = IDS_AX_ROLE_DOC_INDEX;
+ break;
+ case ax::mojom::Role::kDocIntroduction:
+ message_id = IDS_AX_ROLE_DOC_INTRODUCTION;
+ break;
+ case ax::mojom::Role::kDocNoteRef:
+ message_id = IDS_AX_ROLE_DOC_NOTE_REF;
+ break;
+ case ax::mojom::Role::kDocNotice:
+ message_id = IDS_AX_ROLE_DOC_NOTICE;
+ break;
+ case ax::mojom::Role::kDocPageBreak:
+ message_id = IDS_AX_ROLE_DOC_PAGE_BREAK;
+ break;
+ case ax::mojom::Role::kDocPageList:
+ message_id = IDS_AX_ROLE_DOC_PAGE_LIST;
+ break;
+ case ax::mojom::Role::kDocPart:
+ message_id = IDS_AX_ROLE_DOC_PART;
+ break;
+ case ax::mojom::Role::kDocPreface:
+ message_id = IDS_AX_ROLE_DOC_PREFACE;
+ break;
+ case ax::mojom::Role::kDocPrologue:
+ message_id = IDS_AX_ROLE_DOC_PROLOGUE;
+ break;
+ case ax::mojom::Role::kDocPullquote:
+ message_id = IDS_AX_ROLE_DOC_PULLQUOTE;
+ break;
+ case ax::mojom::Role::kDocQna:
+ message_id = IDS_AX_ROLE_DOC_QNA;
+ break;
+ case ax::mojom::Role::kDocSubtitle:
+ message_id = IDS_AX_ROLE_DOC_SUBTITLE;
+ break;
+ case ax::mojom::Role::kDocTip:
+ message_id = IDS_AX_ROLE_DOC_TIP;
+ break;
+ case ax::mojom::Role::kDocToc:
+ message_id = IDS_AX_ROLE_DOC_TOC;
+ break;
case ax::mojom::Role::kDocument:
message_id = IDS_AX_ROLE_DOCUMENT;
break;
@@ -596,6 +713,15 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ax::mojom::Role::kGenericContainer:
// No role description.
break;
+ case ax::mojom::Role::kGraphicsDocument:
+ message_id = IDS_AX_ROLE_GRAPHICS_DOCUMENT;
+ break;
+ case ax::mojom::Role::kGraphicsObject:
+ message_id = IDS_AX_ROLE_GRAPHICS_OBJECT;
+ break;
+ case ax::mojom::Role::kGraphicsSymbol:
+ message_id = IDS_AX_ROLE_GRAPHICS_SYMBOL;
+ break;
case ax::mojom::Role::kGrid:
message_id = IDS_AX_ROLE_TABLE;
break;
@@ -757,6 +883,9 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ax::mojom::Role::kScrollBar:
message_id = IDS_AX_ROLE_SCROLL_BAR;
break;
+ case ax::mojom::Role::kScrollView:
+ // No role description.
+ break;
case ax::mojom::Role::kSearch:
message_id = IDS_AX_ROLE_SEARCH;
break;
@@ -769,9 +898,6 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
case ax::mojom::Role::kSliderThumb:
// No role description.
break;
- case ax::mojom::Role::kSpinButtonPart:
- // No role description.
- break;
case ax::mojom::Role::kSpinButton:
message_id = IDS_AX_ROLE_SPIN_BUTTON;
break;
@@ -1419,7 +1545,7 @@ bool BrowserAccessibilityAndroid::HasOnlyTextAndImageChildren() const {
for (uint32_t i = 0; i < InternalChildCount(); i++) {
BrowserAccessibility* child = InternalGetChild(i);
if (child->GetRole() != ax::mojom::Role::kStaticText &&
- child->GetRole() != ax::mojom::Role::kImage) {
+ !ui::IsImage(child->GetRole())) {
return false;
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 2fba090c047..bc4b972f9c7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -29,6 +29,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_range.h"
#include "ui/accessibility/ax_role_properties.h"
+#include "ui/accessibility/ax_table_info.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
@@ -866,19 +867,36 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- const std::vector<int32_t>& uniqueCellIds =
- table->GetIntListAttribute(ax::mojom::IntListAttribute::kUniqueCellIds);
- for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
- int id = uniqueCellIds[i];
- BrowserAccessibility* cell =
- browserAccessibility_->manager()->GetFromID(id);
- if (cell && cell->GetRole() == ax::mojom::Role::kColumnHeader) {
- // Expose all column headers on table object.
- // Expose only relevant column headers on cell object.
- if (is_table_like || [self isColumnHeaderForCurrentCell:cell])
+
+ if (is_table_like) {
+ // If this is a table, return all column headers.
+ std::set<int32_t> headerIds;
+ for (int i = 0; i < table->GetTableColCount(); i++) {
+ std::vector<int32_t> colHeaderIds = table->GetColHeaderNodeIds(i);
+ std::copy(colHeaderIds.begin(), colHeaderIds.end(),
+ std::inserter(headerIds, headerIds.end()));
+ }
+ for (int32_t id : headerIds) {
+ BrowserAccessibility* cell =
+ browserAccessibility_->manager()->GetFromID(id);
+ if (cell)
+ [ret addObject:ToBrowserAccessibilityCocoa(cell)];
+ }
+ } else {
+ // Otherwise this is a cell, return the column headers for this cell.
+ int column = -1;
+ browserAccessibility_->GetIntAttribute(
+ ax::mojom::IntAttribute::kTableCellColumnIndex, &column);
+
+ std::vector<int32_t> colHeaderIds = table->GetColHeaderNodeIds(column);
+ for (int32_t id : colHeaderIds) {
+ BrowserAccessibility* cell =
+ browserAccessibility_->manager()->GetFromID(id);
+ if (cell)
[ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
}
+
return [ret count] ? ret : nil;
}
@@ -1115,7 +1133,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSNumber*)hasPopup {
if (![self instanceActive])
return nil;
- return browserAccessibility_->HasState(ax::mojom::State::kHaspopup) ? @YES
+ return browserAccessibility_->HasState(ax::mojom::State::kHasPopup) ? @YES
: @NO;
}
@@ -1768,6 +1786,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSArray*)rowHeaders {
if (![self instanceActive])
return nil;
+
bool is_cell_or_table_header =
ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole());
bool is_table_like = ui::IsTableLikeRole(browserAccessibility_->GetRole());
@@ -1778,17 +1797,36 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- const std::vector<int32_t>& uniqueCellIds =
- table->GetIntListAttribute(ax::mojom::IntListAttribute::kUniqueCellIds);
- for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
- int id = uniqueCellIds[i];
- BrowserAccessibility* cell =
- browserAccessibility_->manager()->GetFromID(id);
- if (cell && cell->GetRole() == ax::mojom::Role::kRowHeader) {
- if (is_table_like || [self isRowHeaderForCurrentCell:cell])
+
+ if (is_table_like) {
+ // If this is a table, return all row headers.
+ std::set<int32_t> headerIds;
+ for (int i = 0; i < table->GetTableRowCount(); i++) {
+ std::vector<int32_t> rowHeaderIds = table->GetRowHeaderNodeIds(i);
+ for (int32_t id : rowHeaderIds)
+ headerIds.insert(id);
+ }
+ for (int32_t id : headerIds) {
+ BrowserAccessibility* cell =
+ browserAccessibility_->manager()->GetFromID(id);
+ if (cell)
+ [ret addObject:ToBrowserAccessibilityCocoa(cell)];
+ }
+ } else {
+ // Otherwise this is a cell, return the row headers for this cell.
+ int row = -1;
+ browserAccessibility_->GetIntAttribute(
+ ax::mojom::IntAttribute::kTableCellRowIndex, &row);
+
+ std::vector<int32_t> rowHeaderIds = table->GetRowHeaderNodeIds(row);
+ for (int32_t id : rowHeaderIds) {
+ BrowserAccessibility* cell =
+ browserAccessibility_->manager()->GetFromID(id);
+ if (cell)
[ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
}
+
return [ret count] ? ret : nil;
}
@@ -2208,12 +2246,16 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
- (NSArray*)visibleCells {
if (![self instanceActive])
return nil;
+
+ ui::AXTableInfo* table_info =
+ browserAccessibility_->manager()->ax_tree()->GetTableInfo(
+ browserAccessibility_->node());
+ if (!table_info)
+ return nil;
+
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
- const std::vector<int32_t>& uniqueCellIds =
- browserAccessibility_->GetIntListAttribute(
- ax::mojom::IntListAttribute::kUniqueCellIds);
- for (size_t i = 0; i < uniqueCellIds.size(); ++i) {
- int id = uniqueCellIds[i];
+ for (size_t i = 0; i < table_info->unique_cell_ids.size(); ++i) {
+ int id = table_info->unique_cell_ids[i];
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromID(id);
if (cell)
@@ -3029,7 +3071,7 @@ NSString* const NSAccessibilityRequiredAttributeChrome = @"AXRequired";
[ret addObjectsFromArray:@[ NSAccessibilityGrabbedAttribute ]];
}
- if (browserAccessibility_->HasState(ax::mojom::State::kHaspopup)) {
+ if (browserAccessibility_->HasState(ax::mojom::State::kHasPopup)) {
[ret addObjectsFromArray:@[ NSAccessibilityHasPopupAttribute ]];
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
index a0738c7e24b..0cd7fd5a2d0 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -1724,7 +1724,10 @@ void BrowserAccessibilityComWin::ComputeStylesIfNeeded() {
// style span.
std::vector<base::string16> previous_attributes =
attributes_map.rbegin()->second;
- if (!std::equal(attributes.begin(), attributes.end(),
+ // Must check the size, otherwise if attributes is a subset of
+ // prev_attributes, they would appear to be equal.
+ if (attributes.size() != previous_attributes.size() ||
+ !std::equal(attributes.begin(), attributes.end(),
previous_attributes.begin())) {
attributes_map[start_offset] = attributes;
}
@@ -1913,6 +1916,52 @@ void BrowserAccessibilityComWin::Init(ui::AXPlatformNodeDelegate* delegate) {
AXPlatformNodeWin::Init(delegate);
}
+base::string16 BrowserAccessibilityComWin::GetInvalidValue() const {
+ const BrowserAccessibilityWin* target = owner();
+ // The aria-invalid=spelling/grammar need to be exposed as text attributes for
+ // a range matching the visual underline representing the error.
+ if (static_cast<ax::mojom::InvalidState>(
+ target->GetIntAttribute(ax::mojom::IntAttribute::kInvalidState)) ==
+ ax::mojom::InvalidState::kNone &&
+ target->IsTextOnlyObject() && target->PlatformGetParent()) {
+ // Text nodes need to reflect the invalid state of their parent object,
+ // otherwise spelling and grammar errors communicated through aria-invalid
+ // won't be reflected in text attributes.
+ target = static_cast<BrowserAccessibilityWin*>(target->PlatformGetParent());
+ }
+
+ base::string16 invalid_value;
+ // Note: spelling+grammar errors case is disallowed and not supported. It
+ // could possibly arise with aria-invalid on the ancestor of a spelling error,
+ // but this is not currently described in any spec and no real-world use cases
+ // have been found.
+ switch (static_cast<ax::mojom::InvalidState>(
+ target->GetIntAttribute(ax::mojom::IntAttribute::kInvalidState))) {
+ case ax::mojom::InvalidState::kNone:
+ case ax::mojom::InvalidState::kFalse:
+ break;
+ case ax::mojom::InvalidState::kTrue:
+ return invalid_value = L"true";
+ case ax::mojom::InvalidState::kSpelling:
+ return invalid_value = L"spelling";
+ case ax::mojom::InvalidState::kGrammar:
+ return base::ASCIIToUTF16("grammar");
+ case ax::mojom::InvalidState::kOther: {
+ base::string16 aria_invalid_value;
+ if (target->GetString16Attribute(
+ ax::mojom::StringAttribute::kAriaInvalidValue,
+ &aria_invalid_value)) {
+ SanitizeStringAttributeForIA2(aria_invalid_value, &aria_invalid_value);
+ invalid_value = aria_invalid_value;
+ } else {
+ // Set the attribute to L"true", since we cannot be more specific.
+ invalid_value = L"true";
+ }
+ }
+ }
+ return invalid_value;
+}
+
std::vector<base::string16> BrowserAccessibilityComWin::ComputeTextAttributes()
const {
std::vector<base::string16> attributes;
@@ -1922,38 +1971,37 @@ std::vector<base::string16> BrowserAccessibilityComWin::ComputeTextAttributes()
// TODO(nektar): Compute what objects are auto-generated in Blink.
if (owner()->GetRole() == ax::mojom::Role::kListMarker)
attributes.push_back(L"auto-generated:true");
- else
- attributes.push_back(L"auto-generated:false");
int color;
- base::string16 color_value(L"transparent");
if (owner()->GetIntAttribute(ax::mojom::IntAttribute::kBackgroundColor,
&color)) {
unsigned int alpha = SkColorGetA(color);
unsigned int red = SkColorGetR(color);
unsigned int green = SkColorGetG(color);
unsigned int blue = SkColorGetB(color);
- if (alpha) {
- color_value = L"rgb(" + base::UintToString16(red) + L',' +
- base::UintToString16(green) + L',' +
- base::UintToString16(blue) + L')';
+ // Don't expose default value of pure white.
+ if (alpha && (red != 255 || green != 255 || blue != 255)) {
+ base::string16 color_value = L"rgb(" + base::UintToString16(red) + L',' +
+ base::UintToString16(green) + L',' +
+ base::UintToString16(blue) + L')';
+ SanitizeStringAttributeForIA2(color_value, &color_value);
+ attributes.push_back(L"background-color:" + color_value);
}
}
- SanitizeStringAttributeForIA2(color_value, &color_value);
- attributes.push_back(L"background-color:" + color_value);
if (owner()->GetIntAttribute(ax::mojom::IntAttribute::kColor, &color)) {
unsigned int red = SkColorGetR(color);
unsigned int green = SkColorGetG(color);
unsigned int blue = SkColorGetB(color);
- color_value = L"rgb(" + base::UintToString16(red) + L',' +
- base::UintToString16(green) + L',' +
- base::UintToString16(blue) + L')';
- } else {
- color_value = L"rgb(0,0,0)";
+ // Don't expose default value of black.
+ if (red || green || blue) {
+ base::string16 color_value = L"rgb(" + base::UintToString16(red) + L',' +
+ base::UintToString16(green) + L',' +
+ base::UintToString16(blue) + L')';
+ SanitizeStringAttributeForIA2(color_value, &color_value);
+ attributes.push_back(L"color:" + color_value);
+ }
}
- SanitizeStringAttributeForIA2(color_value, &color_value);
- attributes.push_back(L"color:" + color_value);
base::string16 font_family(owner()->GetInheritedString16Attribute(
ax::mojom::StringAttribute::kFontFamily));
@@ -1975,117 +2023,56 @@ std::vector<base::string16> BrowserAccessibilityComWin::ComputeTextAttributes()
L"pt");
}
+ // TODO(nektar): Add Blink support for the following attributes:
+ // text-line-through-mode, text-line-through-width, text-outline:false,
+ // text-position:baseline, text-shadow:none, text-underline-mode:continuous.
+
int32_t text_style =
owner()->GetIntAttribute(ax::mojom::IntAttribute::kTextStyle);
- if (text_style == static_cast<int32_t>(ax::mojom::TextStyle::kNone)) {
- attributes.push_back(L"font-style:normal");
- attributes.push_back(L"font-weight:normal");
- } else {
+ if (text_style != static_cast<int32_t>(ax::mojom::TextStyle::kNone)) {
if (text_style &
static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleItalic)) {
attributes.push_back(L"font-style:italic");
- } else {
- attributes.push_back(L"font-style:normal");
}
if (text_style &
static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleBold)) {
attributes.push_back(L"font-weight:bold");
- } else {
- attributes.push_back(L"font-weight:normal");
}
- }
- int32_t invalid_state =
- owner()->GetIntAttribute(ax::mojom::IntAttribute::kInvalidState);
- switch (static_cast<ax::mojom::InvalidState>(invalid_state)) {
- case ax::mojom::InvalidState::kNone:
- case ax::mojom::InvalidState::kFalse:
- attributes.push_back(L"invalid:false");
- break;
- case ax::mojom::InvalidState::kTrue:
- attributes.push_back(L"invalid:true");
- break;
- case ax::mojom::InvalidState::kSpelling:
- case ax::mojom::InvalidState::kGrammar: {
- base::string16 spelling_grammar_value;
- if (invalid_state &
- static_cast<int32_t>(ax::mojom::InvalidState::kSpelling))
- spelling_grammar_value = L"spelling";
- else if (invalid_state &
- static_cast<int32_t>(ax::mojom::InvalidState::kGrammar))
- spelling_grammar_value = L"grammar";
- else
- spelling_grammar_value = L"spelling,grammar";
- attributes.push_back(L"invalid:" + spelling_grammar_value);
- break;
+ if (text_style &
+ static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleLineThrough)) {
+ // TODO(nektar): Figure out a more specific value.
+ attributes.push_back(L"text-line-through-style:solid");
}
- case ax::mojom::InvalidState::kOther: {
- base::string16 aria_invalid_value;
- if (owner()->GetString16Attribute(
- ax::mojom::StringAttribute::kAriaInvalidValue,
- &aria_invalid_value)) {
- SanitizeStringAttributeForIA2(aria_invalid_value, &aria_invalid_value);
- attributes.push_back(L"invalid:" + aria_invalid_value);
- } else {
- // Set the attribute to L"true", since we cannot be more specific.
- attributes.push_back(L"invalid:true");
- }
- break;
+
+ if (text_style &
+ static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleUnderline)) {
+ // TODO(nektar): Figure out a more specific value.
+ attributes.push_back(L"text-underline-style:solid");
}
}
+ // Screen readers look at the text attributes to determine if something is
+ // misspelled, so we need to propagate any spelling attributes from immediate
+ // parents of text-only objects.
+ base::string16 invalid_value = GetInvalidValue();
+ if (!invalid_value.empty())
+ attributes.push_back(L"invalid:" + invalid_value);
+
base::string16 language(owner()->GetInheritedString16Attribute(
ax::mojom::StringAttribute::kLanguage));
- // Default value should be L"en-US".
- if (language.empty()) {
- attributes.push_back(L"language:en-US");
- } else {
+ // Don't expose default value should of L"en-US".
+ if (!language.empty() && language != L"en-US") {
SanitizeStringAttributeForIA2(language, &language);
attributes.push_back(L"language:" + language);
}
- // TODO(nektar): Add Blink support for the following attributes.
- // Currently set to their default values as dictated by the IA2 Spec.
- attributes.push_back(L"text-line-through-mode:continuous");
- if (text_style &
- static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleLineThrough)) {
- // TODO(nektar): Figure out a more specific value.
- attributes.push_back(L"text-line-through-style:solid");
- } else {
- attributes.push_back(L"text-line-through-style:none");
- }
- // Default value must be the empty string.
- attributes.push_back(L"text-line-through-text:");
- if (text_style &
- static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleLineThrough)) {
- // TODO(nektar): Figure out a more specific value.
- attributes.push_back(L"text-line-through-type:single");
- } else {
- attributes.push_back(L"text-line-through-type:none");
- }
- attributes.push_back(L"text-line-through-width:auto");
- attributes.push_back(L"text-outline:false");
- attributes.push_back(L"text-position:baseline");
- attributes.push_back(L"text-shadow:none");
- attributes.push_back(L"text-underline-mode:continuous");
- if (text_style &
- static_cast<int32_t>(ax::mojom::TextStyle::kTextStyleUnderline)) {
- // TODO(nektar): Figure out a more specific value.
- attributes.push_back(L"text-underline-style:solid");
- attributes.push_back(L"text-underline-type:single");
- } else {
- attributes.push_back(L"text-underline-style:none");
- attributes.push_back(L"text-underline-type:none");
- }
- attributes.push_back(L"text-underline-width:auto");
-
auto text_direction = static_cast<ax::mojom::TextDirection>(
owner()->GetIntAttribute(ax::mojom::IntAttribute::kTextDirection));
switch (text_direction) {
case ax::mojom::TextDirection::kNone:
case ax::mojom::TextDirection::kLtr:
- attributes.push_back(L"writing-mode:lr");
break;
case ax::mojom::TextDirection::kRtl:
attributes.push_back(L"writing-mode:rl");
@@ -2099,6 +2086,19 @@ std::vector<base::string16> BrowserAccessibilityComWin::ComputeTextAttributes()
break;
}
+ auto text_position = static_cast<ax::mojom::TextPosition>(
+ owner()->GetIntAttribute(ax::mojom::IntAttribute::kTextPosition));
+ switch (text_position) {
+ case ax::mojom::TextPosition::kNone:
+ break;
+ case ax::mojom::TextPosition::kSubscript:
+ attributes.push_back(L"text-position:sub");
+ break;
+ case ax::mojom::TextPosition::kSuperscript:
+ attributes.push_back(L"text-position:super");
+ break;
+ }
+
return attributes;
}
@@ -2125,10 +2125,8 @@ BrowserAccessibilityComWin::GetSpellingAttributes() {
int end_offset = marker_ends[i];
std::vector<base::string16> start_attributes;
start_attributes.push_back(L"invalid:spelling");
- std::vector<base::string16> end_attributes;
- end_attributes.push_back(L"invalid:false");
spelling_attributes[start_offset] = start_attributes;
- spelling_attributes[end_offset] = end_attributes;
+ spelling_attributes[end_offset] = std::vector<base::string16>();
}
}
if (owner()->IsPlainTextField()) {
@@ -2193,6 +2191,16 @@ HRESULT BrowserAccessibilityComWin::GetStringAttributeAsBstr(
return S_OK;
}
+// Pass in prefix with ":" included at the end, e.g. "invalid:".
+bool HasAttribute(std::vector<base::string16>& existing_attributes,
+ base::string16 prefix) {
+ for (base::string16& attr : existing_attributes) {
+ if (base::StartsWith(attr, prefix, base::CompareCase::SENSITIVE))
+ return true;
+ }
+ return false;
+}
+
// static
void BrowserAccessibilityComWin::MergeSpellingIntoTextAttributes(
const std::map<int, std::vector<base::string16>>& spelling_attributes,
@@ -2212,16 +2220,14 @@ void BrowserAccessibilityComWin::MergeSpellingIntoTextAttributes(
std::vector<base::string16>& existing_attributes = iterator->second;
// There might be a spelling attribute already in the list of text
// attributes, originating from "aria-invalid", that is being overwritten
- // by a spelling marker.
- auto existing_spelling_attribute =
- std::find(existing_attributes.begin(), existing_attributes.end(),
- L"invalid:false");
- if (existing_spelling_attribute != existing_attributes.end())
- existing_attributes.erase(existing_spelling_attribute);
-
- existing_attributes.insert(existing_attributes.end(),
- spelling_attribute.second.begin(),
- spelling_attribute.second.end());
+ // by a spelling marker. If it already exists, prefer it over this
+ // automatically computed attribute.
+ if (!HasAttribute(existing_attributes, L"invalid:")) {
+ // Does not exist -- insert our own.
+ existing_attributes.insert(existing_attributes.end(),
+ spelling_attribute.second.begin(),
+ spelling_attribute.second.end());
+ }
}
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.h b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
index 4d6ce30ac99..debd107f060 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.h
@@ -483,6 +483,8 @@ class __declspec(uuid("562072fe-3390-43b1-9e2c-dd4118f5ac79"))
HRESULT GetStringAttributeAsBstr(ax::mojom::StringAttribute attribute,
BSTR* value_bstr);
+ base::string16 GetInvalidValue() const;
+
// Merges the given spelling attributes, i.e. document marker information,
// into the given text attributes starting at the given character offset. This
// is required for two reasons: 1. Document markers that are present on text
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index bf2680cbbf0..f15f0305256 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -711,6 +711,28 @@ void BrowserAccessibilityManager::LoadInlineTextBoxes(
delegate_->AccessibilityPerformAction(action_data);
}
+void BrowserAccessibilityManager::SetAccessibilityFocus(
+ const BrowserAccessibility& node) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ax::mojom::Action::kSetAccessibilityFocus;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
+void BrowserAccessibilityManager::ClearAccessibilityFocus(
+ const BrowserAccessibility& node) {
+ if (!delegate_)
+ return;
+
+ ui::AXActionData action_data;
+ action_data.action = ax::mojom::Action::kClearAccessibilityFocus;
+ action_data.target_node_id = node.GetId();
+ delegate_->AccessibilityPerformAction(action_data);
+}
+
void BrowserAccessibilityManager::HitTest(const gfx::Point& point) {
if (!delegate_)
return;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 276eb429ba0..b1b47d25878 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -203,6 +203,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
// by sending a message to the renderer to perform the respective action
// on the given node. See the definition of |ui::AXActionData| for more
// information about each of these actions.
+ void ClearAccessibilityFocus(const BrowserAccessibility& node);
void Decrement(const BrowserAccessibility& node);
void DoDefaultAction(const BrowserAccessibility& node);
void GetImageData(const BrowserAccessibility& node,
@@ -214,6 +215,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
const BrowserAccessibility& node, gfx::Rect subfocus);
void ScrollToPoint(
const BrowserAccessibility& node, gfx::Point point);
+ void SetAccessibilityFocus(const BrowserAccessibility& node);
void SetFocus(const BrowserAccessibility& node);
void SetScrollOffset(const BrowserAccessibility& node, gfx::Point offset);
void SetValue(
@@ -341,7 +343,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
// Accessors.
ui::AXTreeIDRegistry::AXTreeID ax_tree_id() const { return ax_tree_id_; }
float device_scale_factor() const { return device_scale_factor_; }
- const ui::AXTree* ax_tree() const { return tree_.get(); }
+ ui::AXTree* ax_tree() const { return tree_.get(); }
// AXTreeDelegate implementation.
void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index 2a7a4c49a34..f81b59ee00a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -1788,16 +1788,15 @@ TEST_F(BrowserAccessibilityTest, TestTextAttributesInContentEditables) {
EXPECT_EQ(3, end_offset);
EXPECT_NE(base::string16::npos,
base::string16(text_attributes).find(L"font-family:Helvetica"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"font-weight:normal"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"font-style:normal"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"font-weight:"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"font-style:"));
EXPECT_NE(
base::string16::npos,
base::string16(text_attributes).find(L"text-underline-style:solid"));
- EXPECT_NE(
- base::string16::npos,
- base::string16(text_attributes).find(L"text-underline-type:single"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"text-underline-type:"));
// For compatibility with Firefox, spelling attributes should also be
// propagated to the parent of static text leaves.
EXPECT_NE(base::string16::npos,
@@ -1811,16 +1810,15 @@ TEST_F(BrowserAccessibilityTest, TestTextAttributesInContentEditables) {
EXPECT_EQ(3, end_offset);
EXPECT_NE(base::string16::npos,
base::string16(text_attributes).find(L"font-family:Helvetica"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"font-weight:normal"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"font-style:normal"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"font-weight:"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"font-style:"));
EXPECT_NE(
base::string16::npos,
base::string16(text_attributes).find(L"text-underline-style:solid"));
- EXPECT_NE(
- base::string16::npos,
- base::string16(text_attributes).find(L"text-underline-type:single"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"text-underline-type:"));
EXPECT_NE(base::string16::npos,
base::string16(text_attributes).find(L"invalid:spelling"));
text_attributes.Reset();
@@ -1834,14 +1832,13 @@ TEST_F(BrowserAccessibilityTest, TestTextAttributesInContentEditables) {
EXPECT_EQ(15, end_offset);
base::string16 attributes(text_attributes);
EXPECT_NE(base::string16::npos, attributes.find(L"font-family:Helvetica"));
- EXPECT_NE(base::string16::npos, attributes.find(L"font-weight:normal"));
- EXPECT_NE(base::string16::npos, attributes.find(L"font-style:normal"));
- EXPECT_NE(
- base::string16::npos,
- base::string16(text_attributes).find(L"text-underline-style:none"));
- EXPECT_NE(
+ EXPECT_EQ(base::string16::npos, attributes.find(L"font-weight:"));
+ EXPECT_EQ(base::string16::npos, attributes.find(L"font-style:"));
+ EXPECT_EQ(
base::string16::npos,
- base::string16(text_attributes).find(L"text-underline-type:none"));
+ base::string16(text_attributes).find(L"text-underline-style:solid"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"text-underline-type:"));
EXPECT_EQ(base::string16::npos, attributes.find(L"invalid:spelling"));
text_attributes.Reset();
}
@@ -1869,14 +1866,14 @@ TEST_F(BrowserAccessibilityTest, TestTextAttributesInContentEditables) {
EXPECT_EQ(7, end_offset);
EXPECT_NE(base::string16::npos,
base::string16(text_attributes).find(L"font-family:Helvetica"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"font-weight:normal"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"font-style:normal"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"text-underline-style:none"));
- EXPECT_NE(base::string16::npos,
- base::string16(text_attributes).find(L"text-underline-type:none"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"font-weight:"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"font-style:"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"text-underline-style:"));
+ EXPECT_EQ(base::string16::npos,
+ base::string16(text_attributes).find(L"text-underline-type:"));
EXPECT_EQ(base::string16::npos,
base::string16(text_attributes).find(L"invalid:spelling"));
text_attributes.Reset();
@@ -1965,11 +1962,9 @@ TEST_F(BrowserAccessibilityTest, TestExistingMisspellingsInSimpleTextFields) {
for (LONG offset = 0; offset < value1_length; ++offset) {
hr = ax_combo_box->GetCOM()->get_attributes(
offset, &start_offset, &end_offset, text_attributes.Receive());
- EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(S_FALSE, hr);
EXPECT_EQ(0, start_offset);
EXPECT_EQ(value1_length, end_offset);
- EXPECT_EQ(base::string16::npos,
- base::string16(text_attributes).find(L"invalid:spelling"));
text_attributes.Reset();
}
@@ -1990,11 +1985,9 @@ TEST_F(BrowserAccessibilityTest, TestExistingMisspellingsInSimpleTextFields) {
++offset) {
hr = ax_combo_box->GetCOM()->get_attributes(
offset, &start_offset, &end_offset, text_attributes.Receive());
- EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(S_FALSE, hr);
EXPECT_EQ(value1_length + 4, start_offset);
EXPECT_EQ(combo_box_value_length, end_offset);
- EXPECT_EQ(base::string16::npos,
- base::string16(text_attributes).find(L"invalid:spelling"));
text_attributes.Reset();
}
@@ -2068,11 +2061,9 @@ TEST_F(BrowserAccessibilityTest, TestNewMisspellingsInSimpleTextFields) {
for (LONG offset = 0; offset < combo_box_value_length; ++offset) {
hr = ax_combo_box->GetCOM()->get_attributes(
offset, &start_offset, &end_offset, text_attributes.Receive());
- EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(S_FALSE, hr);
EXPECT_EQ(0, start_offset);
EXPECT_EQ(combo_box_value_length, end_offset);
- EXPECT_EQ(base::string16::npos,
- base::string16(text_attributes).find(L"invalid:spelling"));
text_attributes.Reset();
}
@@ -2095,11 +2086,9 @@ TEST_F(BrowserAccessibilityTest, TestNewMisspellingsInSimpleTextFields) {
for (LONG offset = 0; offset < value1_length; ++offset) {
hr = ax_combo_box->GetCOM()->get_attributes(
offset, &start_offset, &end_offset, text_attributes.Receive());
- EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(S_FALSE, hr);
EXPECT_EQ(0, start_offset);
EXPECT_EQ(value1_length, end_offset);
- EXPECT_EQ(base::string16::npos,
- base::string16(text_attributes).find(L"invalid:spelling"));
text_attributes.Reset();
}
@@ -2120,11 +2109,9 @@ TEST_F(BrowserAccessibilityTest, TestNewMisspellingsInSimpleTextFields) {
++offset) {
hr = ax_combo_box->GetCOM()->get_attributes(
offset, &start_offset, &end_offset, text_attributes.Receive());
- EXPECT_EQ(S_OK, hr);
+ EXPECT_EQ(S_FALSE, hr);
EXPECT_EQ(value1_length + 4, start_offset);
EXPECT_EQ(combo_box_value_length, end_offset);
- EXPECT_EQ(base::string16::npos,
- base::string16(text_attributes).find(L"invalid:spelling"));
text_attributes.Reset();
}
diff --git a/chromium/content/browser/accessibility/captioning_controller.cc b/chromium/content/browser/accessibility/captioning_controller.cc
index 3e1967f9565..f0511fc03ae 100644
--- a/chromium/content/browser/accessibility/captioning_controller.cc
+++ b/chromium/content/browser/accessibility/captioning_controller.cc
@@ -24,7 +24,7 @@ int GetRenderProcessIdFromRenderViewHost(RenderViewHost* host) {
RenderProcessHost* render_process = host->GetProcess();
DCHECK(render_process);
if (render_process->HasConnection())
- return render_process->GetHandle();
+ return render_process->GetProcess().Handle();
return 0;
}
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 14d88ae68bd..6a812bdaa34 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -430,18 +430,6 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const ui::AXNode* cell3 = table->ChildAtIndex(1)->ChildAtIndex(0);
const ui::AXNode* cell4 = table->ChildAtIndex(1)->ChildAtIndex(1);
- ASSERT_EQ(ax::mojom::IntListAttribute::kCellIds,
- table->data().intlist_attributes[0].first);
- const std::vector<int32_t>& table_cell_ids =
- table->data().intlist_attributes[0].second;
- ASSERT_EQ(6U, table_cell_ids.size());
- EXPECT_EQ(cell1->id(), table_cell_ids[0]);
- EXPECT_EQ(cell1->id(), table_cell_ids[1]);
- EXPECT_EQ(cell2->id(), table_cell_ids[2]);
- EXPECT_EQ(cell3->id(), table_cell_ids[3]);
- EXPECT_EQ(cell4->id(), table_cell_ids[4]);
- EXPECT_EQ(cell4->id(), table_cell_ids[5]);
-
EXPECT_EQ(0,
GetIntAttr(cell1, ax::mojom::IntAttribute::kTableCellColumnIndex));
EXPECT_EQ(0, GetIntAttr(cell1, ax::mojom::IntAttribute::kTableCellRowIndex));
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 09c6ba4cdf1..4d30edf5a69 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -189,9 +189,8 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("aria-treeitem-focus.html"));
}
-// http:/crbug.com/791268
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
- DISABLED_AccessibilityEventsAriaComboBoxFocus) {
+ AccessibilityEventsAriaComboBoxFocus) {
RunEventTest(FILE_PATH_LITERAL("aria-combo-box-focus.html"));
}
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 41d6b68e6ff..263cc2387f5 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -282,6 +282,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSLanguage) {
RunCSSTest(FILE_PATH_LITERAL("language.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityCSSTableIncomplete) {
+ RunCSSTest(FILE_PATH_LITERAL("table-incomplete.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
RunHtmlTest(FILE_PATH_LITERAL("a.html"));
}
@@ -371,6 +376,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
#endif
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaAnyUnignored) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-any-unignored.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityAriaApplication) {
RunAriaTest(FILE_PATH_LITERAL("aria-application.html"));
}
@@ -1060,6 +1070,14 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDt) {
RunHtmlTest(FILE_PATH_LITERAL("dt.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDpubRoles) {
+ RunAriaTest(FILE_PATH_LITERAL("dpub-roles.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityGraphicsRoles) {
+ RunAriaTest(FILE_PATH_LITERAL("graphics-roles.html"));
+}
+
#if defined(OS_ANDROID) || defined(OS_MACOSX)
// Flaky failures: http://crbug.com/445929.
// Mac failures: http://crbug.com/571712.
diff --git a/chromium/content/browser/accessibility/fullscreen_browsertest.cc b/chromium/content/browser/accessibility/fullscreen_browsertest.cc
index dbc3358655b..aff774b3a62 100644
--- a/chromium/content/browser/accessibility/fullscreen_browsertest.cc
+++ b/chromium/content/browser/accessibility/fullscreen_browsertest.cc
@@ -51,7 +51,9 @@ class FakeFullscreenDelegate : public WebContentsDelegate {
FakeFullscreenDelegate() = default;
~FakeFullscreenDelegate() override = default;
- void EnterFullscreenModeForTab(WebContents*, const GURL&) override {
+ void EnterFullscreenModeForTab(WebContents*,
+ const GURL&,
+ const blink::WebFullscreenOptions&) override {
is_fullscreen_ = true;
}
diff --git a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
index 88c6d110407..a088ec91be7 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -270,7 +270,7 @@ bool AccessibilityControlPredicate(
if (node->HasState(ax::mojom::State::kFocusable) &&
node->GetRole() != ax::mojom::Role::kIframe &&
node->GetRole() != ax::mojom::Role::kIframePresentational &&
- node->GetRole() != ax::mojom::Role::kLink &&
+ !ui::IsLink(node->GetRole()) &&
node->GetRole() != ax::mojom::Role::kWebArea &&
node->GetRole() != ax::mojom::Role::kRootWebArea) {
return true;
@@ -292,52 +292,52 @@ bool AccessibilityFocusablePredicate(
bool AccessibilityGraphicPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return node->GetRole() == ax::mojom::Role::kImage;
+ return ui::IsImage(node->GetRole());
}
bool AccessibilityHeadingPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kHeading);
+ return ui::IsHeading(node->GetRole());
}
bool AccessibilityH1Predicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kHeading &&
+ return (ui::IsHeading(node->GetRole()) &&
node->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel) ==
1);
}
bool AccessibilityH2Predicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kHeading &&
+ return (ui::IsHeading(node->GetRole()) &&
node->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel) ==
2);
}
bool AccessibilityH3Predicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kHeading &&
+ return (ui::IsHeading(node->GetRole()) &&
node->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel) ==
3);
}
bool AccessibilityH4Predicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kHeading &&
+ return (ui::IsHeading(node->GetRole()) &&
node->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel) ==
4);
}
bool AccessibilityH5Predicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kHeading &&
+ return (ui::IsHeading(node->GetRole()) &&
node->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel) ==
5);
}
bool AccessibilityH6Predicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kHeading &&
+ return (ui::IsHeading(node->GetRole()) &&
node->GetIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel) ==
6);
}
@@ -381,21 +381,17 @@ bool AccessibilityLandmarkPredicate(
bool AccessibilityLinkPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return node->GetRole() == ax::mojom::Role::kLink;
+ return ui::IsLink(node->GetRole());
}
bool AccessibilityListPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kListBox ||
- node->GetRole() == ax::mojom::Role::kList ||
- node->GetRole() == ax::mojom::Role::kDescriptionList);
+ return ui::IsList(node->GetRole());
}
bool AccessibilityListItemPredicate(
BrowserAccessibility* start, BrowserAccessibility* node) {
- return (node->GetRole() == ax::mojom::Role::kListItem ||
- node->GetRole() == ax::mojom::Role::kDescriptionListTerm ||
- node->GetRole() == ax::mojom::Role::kListBoxOption);
+ return ui::IsListItem(node->GetRole());
}
bool AccessibilityLiveRegionPredicate(
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
index 5e7ccb79c98..c1be0a5d63f 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -551,6 +551,7 @@ bool WebContentsAccessibilityAndroid::OnHoverEvent(
root_manager_) {
gfx::PointF point =
IsUseZoomForDSFEnabled() ? event.GetPointPix() : event.GetPoint();
+ point.Scale(1 / page_scale_);
root_manager_->HitTest(gfx::ToFlooredPoint(point));
}
return true;
@@ -1042,15 +1043,25 @@ jboolean WebContentsAccessibilityAndroid::PreviousAtGranularity(
return false;
}
-void WebContentsAccessibilityAndroid::SetAccessibilityFocus(
+void WebContentsAccessibilityAndroid::MoveAccessibilityFocus(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
- jint unique_id) {
+ jint old_unique_id,
+ jint new_unique_id) {
+ BrowserAccessibilityAndroid* old_node = GetAXFromUniqueID(old_unique_id);
+ if (old_node)
+ old_node->manager()->ClearAccessibilityFocus(*old_node);
+
+ BrowserAccessibilityAndroid* node = GetAXFromUniqueID(new_unique_id);
+ if (!node)
+ return;
+ node->manager()->SetAccessibilityFocus(*node);
+
// When Android sets accessibility focus to a node, we load inline text
// boxes for that node so that subsequent requests for character bounding
- // boxes will succeed.
- BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
- if (node)
+ // boxes will succeed. However, don't do that for the root of the tree,
+ // as that will result in loading inline text boxes for the whole tree.
+ if (node != node->manager()->GetRoot())
node->manager()->LoadInlineTextBoxes(*node);
}
@@ -1196,7 +1207,8 @@ BrowserAccessibilityAndroid* WebContentsAccessibilityAndroid::GetAXFromUniqueID(
BrowserAccessibilityAndroid::GetFromUniqueId(unique_id));
}
-void WebContentsAccessibilityAndroid::UpdateFrameInfo() {
+void WebContentsAccessibilityAndroid::UpdateFrameInfo(float page_scale) {
+ page_scale_ = page_scale;
if (frame_info_initialized_)
return;
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.h b/chromium/content/browser/accessibility/web_contents_accessibility_android.h
index 68fd068abbf..51343b13f97 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.h
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.h
@@ -151,12 +151,18 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
jint id,
jint cursor_index);
- // Set accessibility focus. This sends a message to the renderer to
- // asynchronously load inline text boxes for this node only, enabling more
- // accurate movement by granularities on this node.
- void SetAccessibilityFocus(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jint id);
+ // Move accessibility focus. This sends a message to the renderer to
+ // clear accessibility focus on the previous node and set accessibility
+ // focus on the current node. This isn't exposed to the open web, but used
+ // internally.
+ //
+ // In addition, when a node gets accessibility focus we asynchronously
+ // load inline text boxes for this node only, enabling more accurate
+ // movement by granularities on this node.
+ void MoveAccessibilityFocus(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint old_unique_id,
+ jint new_unique_id);
// Returns true if the object is a slider.
bool IsSlider(JNIEnv* env,
@@ -213,7 +219,7 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
jint start,
jint len);
- void UpdateFrameInfo();
+ void UpdateFrameInfo(float page_scale);
void set_root_manager(BrowserAccessibilityManagerAndroid* manager) {
root_manager_ = manager;
@@ -253,6 +259,8 @@ class CONTENT_EXPORT WebContentsAccessibilityAndroid
bool frame_info_initialized_;
+ float page_scale_ = 1.f;
+
BrowserAccessibilityManagerAndroid* root_manager_;
// Manages the connection between web contents and the RenderFrameHost that
diff --git a/chromium/content/browser/android/OWNERS b/chromium/content/browser/android/OWNERS
index 6006c70ff37..13cc5f86a23 100644
--- a/chromium/content/browser/android/OWNERS
+++ b/chromium/content/browser/android/OWNERS
@@ -1,8 +1,6 @@
+jinsukkim@chromium.org
skyostil@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
-# ContentViewCore related
-per-file content_view_*=jinsukkim@chromium.org
-
# COMPONENT: Content>WebApps
diff --git a/chromium/content/browser/android/app_web_message_port.cc b/chromium/content/browser/android/app_web_message_port.cc
index 97e66fd5146..ec7b9ba9fdf 100644
--- a/chromium/content/browser/android/app_web_message_port.cc
+++ b/chromium/content/browser/android/app_web_message_port.cc
@@ -9,8 +9,8 @@
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/android/string_message_codec.h"
#include "jni/AppWebMessagePort_jni.h"
+#include "third_party/blink/public/common/message_port/string_message_codec.h"
using blink::MessagePortChannel;
@@ -44,7 +44,7 @@ JNI_AppWebMessagePort_DecodeStringMessage(
&encoded_message);
base::string16 message;
- if (!DecodeStringMessage(encoded_message, &message))
+ if (!blink::DecodeStringMessage(encoded_message, &message))
return nullptr;
base::android::ScopedJavaLocalRef<jstring> jmessage =
@@ -57,8 +57,8 @@ JNI_AppWebMessagePort_EncodeStringMessage(
JNIEnv* env,
const base::android::JavaParamRef<jclass>& jcaller,
const base::android::JavaParamRef<jstring>& jmessage) {
- std::vector<uint8_t> encoded_message =
- EncodeStringMessage(base::android::ConvertJavaStringToUTF16(jmessage));
+ std::vector<uint8_t> encoded_message = blink::EncodeStringMessage(
+ base::android::ConvertJavaStringToUTF16(jmessage));
return base::android::ToJavaByteArray(env, encoded_message);
}
diff --git a/chromium/content/browser/android/content_protocol_handler_impl.cc b/chromium/content/browser/android/content_protocol_handler_impl.cc
index 143dc304e6e..172487374f0 100644
--- a/chromium/content/browser/android/content_protocol_handler_impl.cc
+++ b/chromium/content/browser/android/content_protocol_handler_impl.cc
@@ -4,7 +4,8 @@
#include "content/browser/android/content_protocol_handler_impl.h"
-#include "base/memory/ptr_util.h"
+#include <memory>
+
#include "base/task_runner.h"
#include "content/browser/android/url_request_content_job.h"
#include "net/base/net_errors.h"
@@ -16,7 +17,7 @@ namespace content {
// static
std::unique_ptr<ContentProtocolHandler> ContentProtocolHandler::Create(
const scoped_refptr<base::TaskRunner>& content_task_runner) {
- return base::WrapUnique(new ContentProtocolHandlerImpl(content_task_runner));
+ return std::make_unique<ContentProtocolHandlerImpl>(content_task_runner);
}
ContentProtocolHandlerImpl::ContentProtocolHandlerImpl(
diff --git a/chromium/content/browser/android/content_ui_event_handler.cc b/chromium/content/browser/android/content_ui_event_handler.cc
new file mode 100644
index 00000000000..c043c6a73c8
--- /dev/null
+++ b/chromium/content/browser/android/content_ui_event_handler.cc
@@ -0,0 +1,220 @@
+// 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/android/content_ui_event_handler.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/web_contents/web_contents_view_android.h"
+#include "jni/ContentUiEventHandler_jni.h"
+#include "ui/android/window_android.h"
+#include "ui/events/android/event_handler_android.h"
+#include "ui/events/android/gesture_event_android.h"
+#include "ui/events/android/gesture_event_type.h"
+#include "ui/events/android/key_event_android.h"
+#include "ui/events/android/motion_event_android.h"
+#include "ui/events/base_event_utils.h"
+
+using base::android::AttachCurrentThread;
+using base::android::JavaParamRef;
+using base::android::JavaRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+
+ContentUiEventHandler::ContentUiEventHandler(JNIEnv* env,
+ const JavaRef<jobject>& obj,
+ WebContentsImpl* web_contents)
+ : java_ref_(env, obj), web_contents_(web_contents) {}
+
+RenderWidgetHostViewAndroid* ContentUiEventHandler::GetRenderWidgetHostView() {
+ RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
+ if (web_contents_->ShowingInterstitialPage()) {
+ rwhv = web_contents_->GetInterstitialPage()
+ ->GetMainFrame()
+ ->GetRenderViewHost()
+ ->GetWidget()
+ ->GetView();
+ }
+ return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
+}
+
+bool ContentUiEventHandler::OnGenericMotionEvent(
+ const ui::MotionEventAndroid& event) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (!j_obj.is_null()) {
+ return Java_ContentUiEventHandler_onGenericMotionEvent(
+ env, j_obj, event.GetJavaObject());
+ }
+ return false;
+}
+
+bool ContentUiEventHandler::OnKeyUp(const ui::KeyEventAndroid& event) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (!j_obj.is_null()) {
+ return Java_ContentUiEventHandler_onKeyUp(env, j_obj, event.key_code(),
+ event.GetJavaObject());
+ }
+ return false;
+}
+
+bool ContentUiEventHandler::DispatchKeyEvent(const ui::KeyEventAndroid& event) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (!j_obj.is_null()) {
+ return Java_ContentUiEventHandler_dispatchKeyEvent(env, j_obj,
+ event.GetJavaObject());
+ }
+ return false;
+}
+
+bool ContentUiEventHandler::ScrollBy(float delta_x, float delta_y) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (!j_obj.is_null()) {
+ Java_ContentUiEventHandler_scrollBy(env, j_obj, delta_x, delta_y);
+ }
+ return false;
+}
+
+bool ContentUiEventHandler::ScrollTo(float x, float y) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (!j_obj.is_null()) {
+ Java_ContentUiEventHandler_scrollTo(env, j_obj, x, y);
+ }
+ return false;
+}
+
+void ContentUiEventHandler::SendMouseWheelEvent(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jlong time_ms,
+ jfloat x,
+ jfloat y,
+ jfloat ticks_x,
+ jfloat ticks_y) {
+ auto* event_handler = GetRenderWidgetHostView();
+ if (!event_handler)
+ return;
+
+ // Compute Event.Latency.OS.MOUSE_WHEEL histogram.
+ base::TimeTicks current_time = ui::EventTimeForNow();
+ base::TimeTicks event_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
+ base::TimeDelta delta = current_time - event_time;
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.MOUSE_WHEEL",
+ delta.InMicroseconds(), 1, 1000000, 50);
+ ui::MotionEventAndroid::Pointer pointer(
+ 0, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */, 0.0f, 0.0f, 0);
+
+ auto* view = web_contents_->GetNativeView();
+ auto* window = view->GetWindowAndroid();
+ float pixels_per_tick =
+ window ? window->mouse_wheel_scroll_factor()
+ : ui::kDefaultMouseWheelTickMultiplier * view->GetDipScale();
+ ui::MotionEventAndroid event(
+ env, nullptr, 1.f / view->GetDipScale(), ticks_x, ticks_y,
+ pixels_per_tick, time_ms, 0 /* action */, 1 /* pointer_count */,
+ 0 /* history_size */, 0 /* action_index */, 0, 0, 0,
+ 0 /* raw_offset_x_pixels */, 0 /* raw_offset_y_pixels */,
+ false /* for_touch_handle */, &pointer, nullptr);
+ event_handler->OnMouseWheelEvent(event);
+}
+
+void ContentUiEventHandler::SendMouseEvent(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jlong time_ms,
+ jint android_action,
+ jfloat x,
+ jfloat y,
+ jint pointer_id,
+ jfloat orientation,
+ jfloat pressure,
+ jfloat tilt,
+ jint android_action_button,
+ jint android_button_state,
+ jint android_meta_state,
+ jint android_tool_type) {
+ auto* event_handler = GetRenderWidgetHostView();
+ if (!event_handler)
+ return;
+
+ // Construct a motion_event object minimally, only to convert the raw
+ // parameters to ui::MotionEvent values. Since we used only the cached values
+ // at index=0, it is okay to even pass a null event to the constructor.
+ ui::MotionEventAndroid::Pointer pointer(
+ pointer_id, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */,
+ orientation, tilt, android_tool_type);
+ ui::MotionEventAndroid event(
+ env, nullptr /* event */,
+ 1.f / web_contents_->GetNativeView()->GetDipScale(), 0.f, 0.f, 0.f,
+ time_ms, android_action, 1 /* pointer_count */, 0 /* history_size */,
+ 0 /* action_index */, android_action_button, android_button_state,
+ android_meta_state, 0 /* raw_offset_x_pixels */,
+ 0 /* raw_offset_y_pixels */, false /* for_touch_handle */, &pointer,
+ nullptr);
+ event_handler->OnMouseEvent(event);
+}
+
+void ContentUiEventHandler::SendScrollEvent(JNIEnv* env,
+ const JavaParamRef<jobject>& jobj,
+ jlong time_ms,
+ jfloat delta_x,
+ jfloat delta_y) {
+ auto* event_handler = GetRenderWidgetHostView();
+ if (!event_handler)
+ return;
+ float dip_scale = web_contents_->GetNativeView()->GetDipScale();
+ float delta_xdip = delta_x / dip_scale;
+ float delta_ydip = delta_y / dip_scale;
+ constexpr bool target_viewport = true;
+ constexpr bool synthetic_scroll = false;
+ constexpr bool prevent_boosting = false;
+ event_handler->OnGestureEvent(ui::GestureEventAndroid(
+ ui::GESTURE_EVENT_TYPE_SCROLL_START, gfx::PointF(), gfx::PointF(),
+ time_ms, 0, -delta_xdip, -delta_ydip, 0, 0, target_viewport,
+ synthetic_scroll, prevent_boosting));
+ event_handler->OnGestureEvent(ui::GestureEventAndroid(
+ ui::GESTURE_EVENT_TYPE_SCROLL_BY, gfx::PointF(), gfx::PointF(), time_ms,
+ 0, -delta_xdip, -delta_ydip, 0, 0, target_viewport, synthetic_scroll,
+ prevent_boosting));
+ event_handler->OnGestureEvent(ui::GestureEventAndroid(
+ ui::GESTURE_EVENT_TYPE_SCROLL_END, gfx::PointF(), gfx::PointF(), time_ms,
+ 0, -delta_xdip, -delta_ydip, 0, 0, target_viewport, synthetic_scroll,
+ prevent_boosting));
+}
+
+void ContentUiEventHandler::CancelFling(JNIEnv* env,
+ const JavaParamRef<jobject>& jobj,
+ jlong time_ms) {
+ auto* event_handler = GetRenderWidgetHostView();
+ if (!event_handler)
+ return;
+ event_handler->OnGestureEvent(ui::GestureEventAndroid(
+ ui::GESTURE_EVENT_TYPE_FLING_CANCEL, gfx::PointF(), gfx::PointF(),
+ time_ms, 0, 0, 0, 0, 0, /*target_viewport*/ false,
+ /*synthetic_scroll*/ false, true));
+}
+
+jlong JNI_ContentUiEventHandler_Init(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobject>& jweb_contents) {
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromJavaWebContents(jweb_contents));
+ CHECK(web_contents)
+ << "A ContentUiEventHandler should be created with a valid WebContents.";
+ auto handler =
+ std::make_unique<ContentUiEventHandler>(env, obj, web_contents);
+ auto* handler_ptr = handler.get();
+ static_cast<WebContentsViewAndroid*>(web_contents->GetView())
+ ->SetContentUiEventHandler(std::move(handler));
+ return reinterpret_cast<intptr_t>(handler_ptr);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/content_ui_event_handler.h b/chromium/content/browser/android/content_ui_event_handler.h
new file mode 100644
index 00000000000..0ff884dc16f
--- /dev/null
+++ b/chromium/content/browser/android/content_ui_event_handler.h
@@ -0,0 +1,82 @@
+// 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_ANDROID_CONTENT_UI_EVENT_HANDLER_H_
+#define CONTENT_BROWSER_ANDROID_CONTENT_UI_EVENT_HANDLER_H_
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+
+namespace ui {
+class KeyEventAndroid;
+class MotionEventAndroid;
+} // namespace ui
+
+namespace content {
+
+class RenderWidgetHostViewAndroid;
+class WebContentsImpl;
+
+// Handles UI events that need Java layer access.
+// Owned by |WebContentsViewAndroid|.
+class ContentUiEventHandler {
+ public:
+ ContentUiEventHandler(JNIEnv* env,
+ const base::android::JavaRef<jobject>& obj,
+ WebContentsImpl* web_contents);
+
+ base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
+ bool OnGenericMotionEvent(const ui::MotionEventAndroid& event);
+ bool OnKeyUp(const ui::KeyEventAndroid& event);
+ bool DispatchKeyEvent(const ui::KeyEventAndroid& event);
+ bool ScrollBy(float delta_x, float delta_y);
+ bool ScrollTo(float x, float y);
+
+ void SendMouseWheelEvent(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jlong time_ms,
+ jfloat x,
+ jfloat y,
+ jfloat ticks_x,
+ jfloat ticks_y);
+ void SendMouseEvent(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jlong time_ms,
+ jint android_action,
+ jfloat x,
+ jfloat y,
+ jint pointer_id,
+ jfloat orientation,
+ jfloat pressure,
+ jfloat tilt,
+ jint android_action_button,
+ jint android_button_state,
+ jint android_meta_state,
+ jint android_tool_type);
+ void SendScrollEvent(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& jobj,
+ jlong time_ms,
+ jfloat delta_x,
+ jfloat delta_y);
+ void CancelFling(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& jobj,
+ jlong time_ms);
+
+ private:
+ RenderWidgetHostViewAndroid* GetRenderWidgetHostView();
+
+ // A weak reference to the Java ContentUiEventHandler object.
+ JavaObjectWeakGlobalRef java_ref_;
+
+ WebContentsImpl* const web_contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentUiEventHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_CONTENT_UI_EVENT_HANDLER_H_
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
index f057fe9e734..15011da9bd3 100644
--- a/chromium/content/browser/android/content_video_view.cc
+++ b/chromium/content/browser/android/content_video_view.cc
@@ -6,7 +6,7 @@
#include "base/metrics/histogram_macros.h"
#include "content/public/browser/web_contents.h"
-#include "jni/ContentVideoView_jni.h"
+#include "jni/ContentVideoViewImpl_jni.h"
using base::android::AttachCurrentThread;
using base::android::JavaParamRef;
@@ -24,7 +24,7 @@ ContentVideoView* g_content_video_view = NULL;
} // namespace
static ScopedJavaLocalRef<jobject>
-JNI_ContentVideoView_GetSingletonJavaContentVideoView(
+JNI_ContentVideoViewImpl_GetSingletonJavaContentVideoView(
JNIEnv* env,
const JavaParamRef<jclass>&) {
if (g_content_video_view)
@@ -53,8 +53,8 @@ ContentVideoView::~ContentVideoView() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
- Java_ContentVideoView_destroyContentVideoView(env, content_video_view,
- true);
+ Java_ContentVideoViewImpl_destroyContentVideoView(env, content_video_view,
+ true);
j_content_video_view_.reset();
}
g_content_video_view = NULL;
@@ -64,7 +64,7 @@ void ContentVideoView::OpenVideo() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
- Java_ContentVideoView_openVideo(env, content_video_view);
+ Java_ContentVideoViewImpl_openVideo(env, content_video_view);
}
}
@@ -72,8 +72,8 @@ void ContentVideoView::OnMediaPlayerError(int error_type) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
- Java_ContentVideoView_onMediaPlayerError(env, content_video_view,
- error_type);
+ Java_ContentVideoViewImpl_onMediaPlayerError(env, content_video_view,
+ error_type);
}
}
@@ -81,8 +81,8 @@ void ContentVideoView::OnVideoSizeChanged(int width, int height) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
- Java_ContentVideoView_onVideoSizeChanged(env, content_video_view, width,
- height);
+ Java_ContentVideoViewImpl_onVideoSizeChanged(env, content_video_view, width,
+ height);
}
}
@@ -91,8 +91,8 @@ void ContentVideoView::ExitFullscreen() {
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
bool release_media_player = false;
if (!content_video_view.is_null())
- Java_ContentVideoView_exitFullscreen(env, content_video_view,
- release_media_player);
+ Java_ContentVideoViewImpl_exitFullscreen(env, content_video_view,
+ release_media_player);
}
ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
@@ -163,7 +163,7 @@ JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject(
return JavaObjectWeakGlobalRef(env, nullptr);
return JavaObjectWeakGlobalRef(
- env, Java_ContentVideoView_createContentVideoView(
+ env, Java_ContentVideoViewImpl_createContentVideoView(
env, j_web_contents, j_content_video_view_embedder,
reinterpret_cast<intptr_t>(this), video_natural_size.width(),
video_natural_size.height())
diff --git a/chromium/content/browser/android/content_view_core.cc b/chromium/content/browser/android/content_view_core.cc
index 37e331fec3a..abcb9272529 100644
--- a/chromium/content/browser/android/content_view_core.cc
+++ b/chromium/content/browser/android/content_view_core.cc
@@ -4,10 +4,6 @@
#include "content/browser/android/content_view_core.h"
-#include "base/android/jni_android.h"
-#include "base/macros.h"
-#include "base/metrics/user_metrics.h"
-#include "cc/layers/layer.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -37,14 +33,10 @@ RenderWidgetHostViewAndroid* GetRenderWidgetHostViewFromHost(
ContentViewCore::ContentViewCore(JNIEnv* env,
const JavaRef<jobject>& obj,
- WebContents* web_contents,
- float dpi_scale)
+ WebContents* web_contents)
: WebContentsObserver(web_contents),
java_ref_(env, obj),
- web_contents_(static_cast<WebContentsImpl*>(web_contents)),
- dpi_scale_(dpi_scale),
- device_orientation_(0) {
-
+ web_contents_(static_cast<WebContentsImpl*>(web_contents)) {
// Currently, the only use case we have for overriding a user agent involves
// spoofing a desktop Linux user agent for "Request desktop site".
// Automatically set it for all WebContents so that it is available when a
@@ -66,23 +58,6 @@ ContentViewCore::~ContentViewCore() {
}
}
-void ContentViewCore::UpdateWindowAndroid(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jwindow_android) {
- ui::WindowAndroid* window =
- ui::WindowAndroid::FromJavaWindowAndroid(jwindow_android);
- auto* old_window = GetWindowAndroid();
- if (window == old_window)
- return;
-
- auto* view = GetViewAndroid();
- if (old_window)
- view->RemoveFromParent();
- if (window)
- window->AddChild(view);
-}
-
void ContentViewCore::OnJavaContentViewCoreDestroyed(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
@@ -94,8 +69,15 @@ void ContentViewCore::OnJavaContentViewCoreDestroyed(
}
void ContentViewCore::RenderViewReady() {
- if (device_orientation_ != 0)
- SendOrientationChangeEventInternal();
+ WebContentsViewAndroid* view =
+ static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
+ if (view->device_orientation() == 0)
+ return;
+ RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
+ if (rwhva)
+ rwhva->UpdateScreenInfo(GetViewAndroid());
+
+ web_contents_->OnScreenOrientationChange();
}
void ContentViewCore::WebContentsDestroyed() {
@@ -132,19 +114,6 @@ RenderWidgetHostViewAndroid* ContentViewCore::GetRenderWidgetHostViewAndroid()
return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
}
-void ContentViewCore::SendScreenRectsAndResizeWidget() {
- RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
- if (view) {
- // |SendScreenRects()| indirectly calls GetViewSize() that asks Java layer.
- web_contents_->SendScreenRects();
- view->WasResized();
- }
-}
-
-ui::WindowAndroid* ContentViewCore::GetWindowAndroid() const {
- return GetViewAndroid()->GetWindowAndroid();
-}
-
ui::ViewAndroid* ContentViewCore::GetViewAndroid() const {
return web_contents_->GetView()->GetNativeView();
}
@@ -159,16 +128,6 @@ void ContentViewCore::SetFocus(JNIEnv* env,
SetFocusInternal(focused);
}
-void ContentViewCore::SetDIPScale(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jfloat dpi_scale) {
- if (dpi_scale_ == dpi_scale)
- return;
-
- dpi_scale_ = dpi_scale;
- SendScreenRectsAndResizeWidget();
-}
-
void ContentViewCore::SetFocusInternal(bool focused) {
if (!GetRenderWidgetHostViewAndroid())
return;
@@ -179,82 +138,16 @@ void ContentViewCore::SetFocusInternal(bool focused) {
GetRenderWidgetHostViewAndroid()->LostFocus();
}
-int ContentViewCore::GetTopControlsShrinkBlinkHeightPixForTesting(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- return !rwhv || !rwhv->DoBrowserControlsShrinkBlinkSize()
- ? 0
- : rwhv->GetTopControlsHeight() * dpi_scale_;
-}
-
-void ContentViewCore::SendOrientationChangeEvent(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jint orientation) {
- if (device_orientation_ != orientation) {
- base::RecordAction(base::UserMetricsAction("ScreenOrientationChange"));
- device_orientation_ = orientation;
- SendOrientationChangeEventInternal();
- }
-}
-
-void ContentViewCore::ResetGestureDetection(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->ResetGestureDetection();
-}
-
-void ContentViewCore::SetDoubleTapSupportEnabled(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jboolean enabled) {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->SetDoubleTapSupportEnabled(enabled);
-}
-
-void ContentViewCore::SetMultiTouchZoomSupportEnabled(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jboolean enabled) {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->SetMultiTouchZoomSupportEnabled(enabled);
-}
-
-void ContentViewCore::SendOrientationChangeEventInternal() {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->UpdateScreenInfo(GetViewAndroid());
-
- static_cast<WebContentsImpl*>(web_contents())->OnScreenOrientationChange();
-}
-
// This is called for each ContentView.
-jlong JNI_ContentViewCoreImpl_Init(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& jweb_contents,
- const JavaParamRef<jobject>& jview_android_delegate,
- const JavaParamRef<jobject>& jwindow_android,
- jfloat dip_scale) {
+jlong JNI_ContentViewCoreImpl_Init(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobject>& jweb_contents) {
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
WebContents::FromJavaWebContents(jweb_contents));
CHECK(web_contents)
<< "A ContentViewCore should be created with a valid WebContents.";
- ui::ViewAndroid* view_android = web_contents->GetView()->GetNativeView();
- view_android->SetDelegate(jview_android_delegate);
-
- ui::WindowAndroid* window_android =
- ui::WindowAndroid::FromJavaWindowAndroid(jwindow_android);
- DCHECK(window_android);
- window_android->AddChild(view_android);
-
- ContentViewCore* view =
- new ContentViewCore(env, obj, web_contents, dip_scale);
- return reinterpret_cast<intptr_t>(view);
+ return reinterpret_cast<intptr_t>(
+ new ContentViewCore(env, obj, web_contents));
}
} // namespace content
diff --git a/chromium/content/browser/android/content_view_core.h b/chromium/content/browser/android/content_view_core.h
index 36373ad9fa9..f41a9a56497 100644
--- a/chromium/content/browser/android/content_view_core.h
+++ b/chromium/content/browser/android/content_view_core.h
@@ -13,7 +13,6 @@
namespace ui {
class ViewAndroid;
-class WindowAndroid;
}
namespace content {
@@ -25,8 +24,7 @@ class ContentViewCore : public WebContentsObserver {
public:
ContentViewCore(JNIEnv* env,
const base::android::JavaRef<jobject>& obj,
- WebContents* web_contents,
- float dpi_scale);
+ WebContents* web_contents);
~ContentViewCore() override;
@@ -34,44 +32,14 @@ class ContentViewCore : public WebContentsObserver {
// Methods called from Java via JNI
// --------------------------------------------------------------------------
- void UpdateWindowAndroid(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- const base::android::JavaParamRef<jobject>& jwindow_android);
void OnJavaContentViewCoreDestroyed(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
- // Returns the amount of the top controls height if controls are in the state
- // of shrinking Blink's view size, otherwise 0.
- int GetTopControlsShrinkBlinkHeightPixForTesting(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
-
- void SendOrientationChangeEvent(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jint orientation);
-
- void ResetGestureDetection(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
- void SetDoubleTapSupportEnabled(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jboolean enabled);
- void SetMultiTouchZoomSupportEnabled(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jboolean enabled);
-
void SetFocus(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean focused);
- void SetDIPScale(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jfloat dipScale);
-
private:
// WebContentsObserver implementation.
@@ -84,19 +52,13 @@ class ContentViewCore : public WebContentsObserver {
// Other private methods and data
// --------------------------------------------------------------------------
- void SendScreenRectsAndResizeWidget();
-
ui::ViewAndroid* GetViewAndroid() const;
- ui::WindowAndroid* GetWindowAndroid() const;
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid() const;
// Update focus state of the RenderWidgetHostView.
void SetFocusInternal(bool focused);
- // Send device_orientation_ to renderer.
- void SendOrientationChangeEventInternal();
-
// A weak reference to the Java ContentViewCore object.
JavaObjectWeakGlobalRef java_ref_;
@@ -104,13 +66,6 @@ class ContentViewCore : public WebContentsObserver {
// display in the ContentViewCore.
WebContentsImpl* web_contents_;
- // Device scale factor.
- float dpi_scale_;
-
- // The cache of device's current orientation set from Java side, this value
- // will be sent to Renderer once it is ready.
- int device_orientation_;
-
DISALLOW_COPY_AND_ASSIGN(ContentViewCore);
};
diff --git a/chromium/content/browser/android/content_view_render_view.cc b/chromium/content/browser/android/content_view_render_view.cc
index be2b36162b9..afaefd7c88b 100644
--- a/chromium/content/browser/android/content_view_render_view.cc
+++ b/chromium/content/browser/android/content_view_render_view.cc
@@ -14,7 +14,6 @@
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
#include "base/lazy_instance.h"
-#include "base/message_loop/message_loop.h"
#include "cc/layers/layer.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/android/content_view_layer_renderer.h"
@@ -115,6 +114,12 @@ void ContentViewRenderView::SetOverlayVideoMode(
compositor_->SetNeedsComposite();
}
+void ContentViewRenderView::SetNeedsComposite(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj) {
+ compositor_->SetNeedsComposite();
+}
+
void ContentViewRenderView::UpdateLayerTreeHost() {
// TODO(wkorman): Rename Layout to UpdateLayerTreeHost in all Android
// Compositor related classes.
diff --git a/chromium/content/browser/android/content_view_render_view.h b/chromium/content/browser/android/content_view_render_view.h
index 3c1194d048c..97916d3a300 100644
--- a/chromium/content/browser/android/content_view_render_view.h
+++ b/chromium/content/browser/android/content_view_render_view.h
@@ -48,6 +48,8 @@ class ContentViewRenderView : public CompositorClient {
void SetOverlayVideoMode(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
bool enabled);
+ void SetNeedsComposite(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
// CompositorClient implementation
void UpdateLayerTreeHost() override;
diff --git a/chromium/content/browser/android/content_view_statics.cc b/chromium/content/browser/android/content_view_statics.cc
index abeb57cd933..6275395ace8 100644
--- a/chromium/content/browser/android/content_view_statics.cc
+++ b/chromium/content/browser/android/content_view_statics.cc
@@ -14,7 +14,7 @@
#include "content/common/view_messages.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
-#include "jni/ContentViewStatics_jni.h"
+#include "jni/ContentViewStaticsImpl_jni.h"
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF16ToJavaString;
@@ -40,9 +40,9 @@ class SuspendedProcessWatcher : public content::RenderProcessHostObserver {
// If the process crashes, stop watching the corresponding RenderProcessHost
// and ensure it doesn't get over-resumed.
- void RenderProcessExited(content::RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override {
+ void RenderProcessExited(
+ content::RenderProcessHost* host,
+ const content::ChildProcessTerminationInfo& info) override {
StopWatching(host);
}
@@ -90,7 +90,7 @@ base::LazyInstance<SuspendedProcessWatcher>::DestructorAtExit
} // namespace
-static void JNI_ContentViewStatics_SetWebKitSharedTimersSuspended(
+static void JNI_ContentViewStaticsImpl_SetWebKitSharedTimersSuspended(
JNIEnv* env,
const JavaParamRef<jclass>& obj,
jboolean suspend) {
diff --git a/chromium/content/browser/android/gesture_listener_manager.cc b/chromium/content/browser/android/gesture_listener_manager.cc
index 1eeb5d41b40..2cee9bf9e34 100644
--- a/chromium/content/browser/android/gesture_listener_manager.cc
+++ b/chromium/content/browser/android/gesture_listener_manager.cc
@@ -119,6 +119,29 @@ void GestureListenerManager::Reset(JNIEnv* env,
java_ref_.reset();
}
+void GestureListenerManager::ResetGestureDetection(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ if (rwhva_)
+ rwhva_->ResetGestureDetection();
+}
+
+void GestureListenerManager::SetDoubleTapSupportEnabled(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jboolean enabled) {
+ if (rwhva_)
+ rwhva_->SetDoubleTapSupportEnabled(enabled);
+}
+
+void GestureListenerManager::SetMultiTouchZoomSupportEnabled(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jboolean enabled) {
+ if (rwhva_)
+ rwhva_->SetMultiTouchZoomSupportEnabled(enabled);
+}
+
void GestureListenerManager::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
@@ -244,6 +267,7 @@ void GestureListenerManager::UpdateRenderProcessConnection(
if (new_rwhva) {
new_rwhva->set_gesture_listener_manager(this);
}
+ rwhva_ = new_rwhva;
}
void GestureListenerManager::OnNavigationFinished(
diff --git a/chromium/content/browser/android/gesture_listener_manager.h b/chromium/content/browser/android/gesture_listener_manager.h
index 693a9b7beed..59121618e4c 100644
--- a/chromium/content/browser/android/gesture_listener_manager.h
+++ b/chromium/content/browser/android/gesture_listener_manager.h
@@ -34,6 +34,16 @@ class GestureListenerManager : public RenderWidgetHostConnector {
~GestureListenerManager() override;
void Reset(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+ void ResetGestureDetection(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
+ void SetDoubleTapSupportEnabled(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jboolean enabled);
+ void SetMultiTouchZoomSupportEnabled(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jboolean enabled);
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result);
void DidStopFlinging();
@@ -67,6 +77,7 @@ class GestureListenerManager : public RenderWidgetHostConnector {
std::unique_ptr<ResetScrollObserver> reset_scroll_observer_;
WebContentsImpl* web_contents_;
+ RenderWidgetHostViewAndroid* rwhva_ = nullptr;
// A weak reference to the Java GestureListenerManager object.
JavaObjectWeakGlobalRef java_ref_;
diff --git a/chromium/content/browser/android/ime_adapter_android.cc b/chromium/content/browser/android/ime_adapter_android.cc
index ed271d17508..6bb9735fc5b 100644
--- a/chromium/content/browser/android/ime_adapter_android.cc
+++ b/chromium/content/browser/android/ime_adapter_android.cc
@@ -19,7 +19,6 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/common/frame_messages.h"
-#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/native_web_keyboard_event.h"
@@ -54,10 +53,10 @@ NativeWebKeyboardEvent NativeWebKeyboardEventFromKeyEvent(
int scan_code,
bool is_system_key,
int unicode_char) {
- return NativeWebKeyboardEvent(env, java_key_event,
- static_cast<blink::WebInputEvent::Type>(type),
- modifiers, time_ms / 1000.0, key_code,
- scan_code, unicode_char, is_system_key);
+ return NativeWebKeyboardEvent(
+ env, java_key_event, static_cast<blink::WebInputEvent::Type>(type),
+ modifiers, base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms),
+ key_code, scan_code, unicode_char, is_system_key);
}
} // anonymous namespace
diff --git a/chromium/content/browser/android/interstitial_page_delegate_android.cc b/chromium/content/browser/android/interstitial_page_delegate_android.cc
deleted file mode 100644
index 81b57c0f1ce..00000000000
--- a/chromium/content/browser/android/interstitial_page_delegate_android.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/android/interstitial_page_delegate_android.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "content/public/browser/interstitial_page.h"
-#include "jni/InterstitialPageDelegateAndroid_jni.h"
-
-using base::android::AttachCurrentThread;
-using base::android::JavaParamRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-
-InterstitialPageDelegateAndroid::InterstitialPageDelegateAndroid(
- JNIEnv* env,
- jobject obj,
- const std::string& html_content)
- : weak_java_obj_(env, obj),
- html_content_(html_content),
- page_(NULL) {
-}
-
-InterstitialPageDelegateAndroid::~InterstitialPageDelegateAndroid() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = weak_java_obj_.get(env);
- if (obj.obj())
- Java_InterstitialPageDelegateAndroid_onNativeDestroyed(env, obj);
-}
-
-void InterstitialPageDelegateAndroid::Proceed(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- if (page_)
- page_->Proceed();
-}
-
-void InterstitialPageDelegateAndroid::DontProceed(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- if (page_)
- page_->DontProceed();
-}
-
-std::string InterstitialPageDelegateAndroid::GetHTMLContents() {
- return html_content_;
-}
-
-void InterstitialPageDelegateAndroid::OnProceed() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = weak_java_obj_.get(env);
- if (obj.obj())
- Java_InterstitialPageDelegateAndroid_onProceed(env, obj);
-}
-
-void InterstitialPageDelegateAndroid::OnDontProceed() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = weak_java_obj_.get(env);
- if (obj.obj())
- Java_InterstitialPageDelegateAndroid_onDontProceed(env, obj);
-}
-
-void InterstitialPageDelegateAndroid::CommandReceived(
- const std::string& command) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = weak_java_obj_.get(env);
- if (obj.obj()) {
- std::string sanitized_command(command);
- // The JSONified response has quotes, remove them.
- if (sanitized_command.length() > 1 && sanitized_command[0] == '"') {
- sanitized_command = sanitized_command.substr(
- 1, sanitized_command.length() - 2);
- }
-
- Java_InterstitialPageDelegateAndroid_commandReceived(
- env, obj,
- base::android::ConvertUTF8ToJavaString(env, sanitized_command));
- }
-}
-
-static jlong JNI_InterstitialPageDelegateAndroid_Init(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jstring>& html_content) {
- InterstitialPageDelegateAndroid* delegate =
- new InterstitialPageDelegateAndroid(
- env, obj, base::android::ConvertJavaStringToUTF8(env, html_content));
- return reinterpret_cast<intptr_t>(delegate);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/interstitial_page_delegate_android.h b/chromium/content/browser/android/interstitial_page_delegate_android.h
deleted file mode 100644
index b4900e2c461..00000000000
--- a/chromium/content/browser/android/interstitial_page_delegate_android.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_
-#define CONTENT_BROWSER_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_
-
-#include <jni.h>
-#include <string>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/interstitial_page_delegate.h"
-
-namespace content {
-
-class InterstitialPage;
-
-// Native counterpart that allows interstitial pages to be constructed and
-// managed from Java.
-class InterstitialPageDelegateAndroid : public InterstitialPageDelegate {
- public:
- InterstitialPageDelegateAndroid(JNIEnv* env,
- jobject obj,
- const std::string& html_content);
- ~InterstitialPageDelegateAndroid() override;
-
- void set_interstitial_page(InterstitialPage* page) { page_ = page; }
-
- // Methods called from Java.
- void Proceed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
- void DontProceed(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
-
- // Implementation of InterstitialPageDelegate
- std::string GetHTMLContents() override;
- void OnProceed() override;
- void OnDontProceed() override;
- void CommandReceived(const std::string& command) override;
-
- private:
- JavaObjectWeakGlobalRef weak_java_obj_;
-
- std::string html_content_;
- InterstitialPage* page_; // Owns this.
-
- DISALLOW_COPY_AND_ASSIGN(InterstitialPageDelegateAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_INTERSTITIAL_PAGE_DELEGATE_ANDROID_H_
diff --git a/chromium/content/browser/android/java/java_bridge_thread.cc b/chromium/content/browser/android/java/java_bridge_thread.cc
index b0b39d31204..d0d03812cbb 100644
--- a/chromium/content/browser/android/java/java_bridge_thread.cc
+++ b/chromium/content/browser/android/java/java_bridge_thread.cc
@@ -5,7 +5,6 @@
#include "content/browser/android/java/java_bridge_thread.h"
#include "base/lazy_instance.h"
-#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "build/build_config.h"
diff --git a/chromium/content/browser/android/overscroll_controller_android_unittest.cc b/chromium/content/browser/android/overscroll_controller_android_unittest.cc
index 2745dd1243e..29fb140cdb0 100644
--- a/chromium/content/browser/android/overscroll_controller_android_unittest.cc
+++ b/chromium/content/browser/android/overscroll_controller_android_unittest.cc
@@ -217,10 +217,9 @@ TEST_F(OverscrollControllerAndroidUnitTest,
controller_->OnOverscrolled(params);
// Generate a consumed scroll update.
- blink::WebGestureEvent event(
- blink::WebInputEvent::kGestureScrollUpdate,
- blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebGestureEvent event(blink::WebInputEvent::kGestureScrollUpdate,
+ blink::WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
controller_->OnGestureEventAck(event, INPUT_EVENT_ACK_STATE_CONSUMED);
testing::Mock::VerifyAndClearExpectations(&refresh_);
diff --git a/chromium/content/browser/android/string_message_codec.cc b/chromium/content/browser/android/string_message_codec.cc
deleted file mode 100644
index 5303ac43b73..00000000000
--- a/chromium/content/browser/android/string_message_codec.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2017 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/android/string_message_codec.h"
-
-#include <vector>
-
-#include "base/logging.h"
-
-namespace content {
-namespace {
-
-const uint32_t kVarIntShift = 7;
-const uint32_t kVarIntMask = (1 << kVarIntShift) - 1;
-
-const uint8_t kVersionTag = 0xFF;
-const uint8_t kPaddingTag = '\0';
-const uint8_t kOneByteStringTag = '"';
-const uint8_t kTwoByteStringTag = 'c';
-
-const uint32_t kVersion = 10;
-
-static size_t BytesNeededForUint32(uint32_t value) {
- size_t result = 0;
- do {
- result++;
- value >>= kVarIntShift;
- } while (value);
- return result;
-}
-
-void WriteUint8(uint8_t value, std::vector<uint8_t>* buffer) {
- buffer->push_back(value);
-}
-
-void WriteUint32(uint32_t value, std::vector<uint8_t>* buffer) {
- for (;;) {
- uint8_t b = (value & kVarIntMask);
- value >>= kVarIntShift;
- if (!value) {
- WriteUint8(b, buffer);
- break;
- }
- WriteUint8(b | (1 << kVarIntShift), buffer);
- }
-}
-
-void WriteBytes(const char* bytes, size_t num_bytes,
- std::vector<uint8_t>* buffer) {
- buffer->insert(buffer->end(), bytes, bytes + num_bytes);
-}
-
-bool ReadUint8(const uint8_t** ptr, const uint8_t* end, uint8_t* value) {
- if (*ptr >= end)
- return false;
- *value = *(*ptr)++;
- return true;
-}
-
-bool ReadUint32(const uint8_t** ptr, const uint8_t* end, uint32_t* value) {
- *value = 0;
- uint8_t current_byte;
- int shift = 0;
- do {
- if (*ptr >= end)
- return false;
- current_byte = *(*ptr)++;
- *value |= (static_cast<uint32_t>(current_byte & kVarIntMask) << shift);
- shift += kVarIntShift;
- } while (current_byte & (1 << kVarIntShift));
- return true;
-}
-
-bool ContainsOnlyLatin1(const base::string16& data) {
- base::char16 x = 0;
- for (base::char16 c : data)
- x |= c;
- return !(x & 0xFF00);
-}
-
-} // namespace
-
-std::vector<uint8_t> EncodeStringMessage(const base::string16& data) {
- std::vector<uint8_t> buffer;
- WriteUint8(kVersionTag, &buffer);
- WriteUint32(kVersion, &buffer);
-
- if (ContainsOnlyLatin1(data)) {
- std::string data_latin1(data.begin(), data.end());
- WriteUint8(kOneByteStringTag, &buffer);
- WriteUint32(data_latin1.size(), &buffer);
- WriteBytes(data_latin1.c_str(), data_latin1.size(), &buffer);
- } else {
- size_t num_bytes = data.size() * sizeof(base::char16);
- if ((buffer.size() + 1 + BytesNeededForUint32(num_bytes)) & 1)
- WriteUint8(kPaddingTag, &buffer);
- WriteUint8(kTwoByteStringTag, &buffer);
- WriteUint32(num_bytes, &buffer);
- WriteBytes(reinterpret_cast<const char*>(data.data()), num_bytes, &buffer);
- }
-
- return buffer;
-}
-
-bool DecodeStringMessage(const std::vector<uint8_t>& encoded_data,
- base::string16* result) {
- const uint8_t* ptr = encoded_data.data();
- const uint8_t* end = ptr + encoded_data.size();
- uint8_t tag;
-
- // Discard any leading version and padding tags.
- // There may be more than one version, due to Blink and V8 having separate
- // version tags.
- do {
- if (!ReadUint8(&ptr, end, &tag))
- return false;
- uint32_t version;
- if (tag == kVersionTag && !ReadUint32(&ptr, end, &version))
- return false;
- } while (tag == kVersionTag || tag == kPaddingTag);
-
- switch (tag) {
- case kOneByteStringTag: {
- uint32_t num_bytes;
- if (!ReadUint32(&ptr, end, &num_bytes))
- return false;
- result->assign(reinterpret_cast<const char*>(ptr),
- reinterpret_cast<const char*>(ptr) + num_bytes);
- return true;
- }
- case kTwoByteStringTag: {
- uint32_t num_bytes;
- if (!ReadUint32(&ptr, end, &num_bytes))
- return false;
- result->assign(reinterpret_cast<const base::char16*>(ptr), num_bytes / 2);
- return true;
- }
- }
-
- DLOG(WARNING) << "Unexpected tag: " << tag;
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/string_message_codec.h b/chromium/content/browser/android/string_message_codec.h
deleted file mode 100644
index a613f057609..00000000000
--- a/chromium/content/browser/android/string_message_codec.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 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_ANDROID_STRING_MESSAGE_CODEC_H_
-#define CONTENT_BROWSER_ANDROID_STRING_MESSAGE_CODEC_H_
-
-#include <vector>
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// To support exposing HTML message ports to Java, it is necessary to be able
-// to encode and decode message data using the same serialization format as V8.
-// That format is an implementation detail of V8, but we cannot invoke V8 in
-// the browser process. Rather than IPC over to the renderer process to execute
-// the V8 serialization code, we duplicate some of the serialization logic
-// (just for simple string messages) here. This is a trade-off between overall
-// complexity / performance and code duplication. Fortunately, we only need to
-// handle string messages and this serialization format is static, as it is a
-// format we currently persist to disk via IndexedDB.
-
-CONTENT_EXPORT std::vector<uint8_t> EncodeStringMessage(
- const base::string16& data);
-
-CONTENT_EXPORT bool DecodeStringMessage(
- const std::vector<uint8_t>& encoded_data,
- base::string16* result);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_STRING_MESSAGE_CODEC_H_
diff --git a/chromium/content/browser/android/string_message_codec_unittest.cc b/chromium/content/browser/android/string_message_codec_unittest.cc
deleted file mode 100644
index d32233e30ab..00000000000
--- a/chromium/content/browser/android/string_message_codec_unittest.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2017 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/android/string_message_codec.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "v8/include/v8.h"
-
-namespace content {
-namespace {
-
-base::string16 DecodeWithV8(const std::vector<uint8_t>& encoded) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
- base::string16 result;
-
- v8::Isolate::CreateParams params;
- params.array_buffer_allocator =
- v8::ArrayBuffer::Allocator::NewDefaultAllocator();
- v8::Isolate* isolate = v8::Isolate::New(params);
- {
- v8::HandleScope scope(isolate);
- v8::TryCatch try_catch(isolate);
-
- v8::Local<v8::Context> context = v8::Context::New(isolate);
-
- v8::ValueDeserializer deserializer(isolate, encoded.data(), encoded.size());
- deserializer.SetSupportsLegacyWireFormat(true);
-
- EXPECT_TRUE(deserializer.ReadHeader(context).ToChecked());
-
- v8::Local<v8::Value> value =
- deserializer.ReadValue(context).ToLocalChecked();
- v8::Local<v8::String> str = value->ToString(context).ToLocalChecked();
-
- result.resize(str->Length());
- str->Write(&result[0], 0, result.size());
- }
- isolate->Dispose();
- delete params.array_buffer_allocator;
-
- return result;
-}
-
-std::vector<uint8_t> EncodeWithV8(const base::string16& message) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
- std::vector<uint8_t> result;
-
- v8::Isolate::CreateParams params;
- params.array_buffer_allocator =
- v8::ArrayBuffer::Allocator::NewDefaultAllocator();
- v8::Isolate* isolate = v8::Isolate::New(params);
- {
- v8::HandleScope scope(isolate);
- v8::TryCatch try_catch(isolate);
-
- v8::Local<v8::Context> context = v8::Context::New(isolate);
-
- v8::Local<v8::String> message_as_value =
- v8::String::NewFromTwoByte(isolate,
- message.data(),
- v8::NewStringType::kNormal,
- message.size()).ToLocalChecked();
-
- v8::ValueSerializer serializer(isolate);
- serializer.WriteHeader();
- EXPECT_TRUE(serializer.WriteValue(context, message_as_value).ToChecked());
-
- std::pair<uint8_t*, size_t> buffer = serializer.Release();
- result = std::vector<uint8_t>(buffer.first, buffer.first + buffer.second);
- free(buffer.first);
- }
- isolate->Dispose();
- delete params.array_buffer_allocator;
-
- return result;
-}
-
-TEST(StringMessageCodecTest, SelfTest_ASCII) {
- base::string16 message = base::ASCIIToUTF16("hello");
- base::string16 decoded;
- EXPECT_TRUE(DecodeStringMessage(EncodeStringMessage(message), &decoded));
- EXPECT_EQ(message, decoded);
-}
-
-TEST(StringMessageCodecTest, SelfTest_NonASCII) {
- base::string16 message = base::WideToUTF16(L"hello \u263A");
- base::string16 decoded;
- EXPECT_TRUE(DecodeStringMessage(EncodeStringMessage(message), &decoded));
- EXPECT_EQ(message, decoded);
-}
-
-TEST(StringMessageCodecTest, SelfTest_NonASCIILongEnoughToForcePadding) {
- base::string16 message(200, 0x263A);
- base::string16 decoded;
- EXPECT_TRUE(DecodeStringMessage(EncodeStringMessage(message), &decoded));
- EXPECT_EQ(message, decoded);
-}
-
-TEST(StringMessageCodecTest, SelfToV8Test_ASCII) {
- base::string16 message = base::ASCIIToUTF16("hello");
- EXPECT_EQ(message, DecodeWithV8(EncodeStringMessage(message)));
-}
-
-TEST(StringMessageCodecTest, SelfToV8Test_NonASCII) {
- base::string16 message = base::WideToUTF16(L"hello \u263A");
- EXPECT_EQ(message, DecodeWithV8(EncodeStringMessage(message)));
-}
-
-TEST(StringMessageCodecTest, SelfToV8Test_NonASCIILongEnoughToForcePadding) {
- base::string16 message(200, 0x263A);
- EXPECT_EQ(message, DecodeWithV8(EncodeStringMessage(message)));
-}
-
-TEST(StringMessageCodecTest, V8ToSelfTest_ASCII) {
- base::string16 message = base::ASCIIToUTF16("hello");
- base::string16 decoded;
- EXPECT_TRUE(DecodeStringMessage(EncodeWithV8(message), &decoded));
- EXPECT_EQ(message, decoded);
-}
-
-TEST(StringMessageCodecTest, V8ToSelfTest_NonASCII) {
- base::string16 message = base::WideToUTF16(L"hello \u263A");
- base::string16 decoded;
- EXPECT_TRUE(DecodeStringMessage(EncodeWithV8(message), &decoded));
- EXPECT_EQ(message, decoded);
-}
-
-TEST(StringMessageCodecTest, V8ToSelfTest_NonASCIILongEnoughToForcePadding) {
- base::string16 message(200, 0x263A);
- base::string16 decoded;
- EXPECT_TRUE(DecodeStringMessage(EncodeWithV8(message), &decoded));
- EXPECT_EQ(message, decoded);
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/browser/android/synchronous_compositor_browser_filter.cc b/chromium/content/browser/android/synchronous_compositor_browser_filter.cc
deleted file mode 100644
index af6f7774137..00000000000
--- a/chromium/content/browser/android/synchronous_compositor_browser_filter.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2016 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/android/synchronous_compositor_browser_filter.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/lazy_instance.h"
-#include "base/optional.h"
-#include "base/stl_util.h"
-#include "content/browser/android/synchronous_compositor_sync_call_bridge.h"
-#include "content/browser/bad_message.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-
-namespace content {
-
-SynchronousCompositorBrowserFilter::SynchronousCompositorBrowserFilter(
- int process_id)
- : BrowserMessageFilter(SyncCompositorMsgStart),
- render_process_host_(RenderProcessHost::FromID(process_id)) {
- DCHECK(render_process_host_);
-}
-
-SynchronousCompositorBrowserFilter::~SynchronousCompositorBrowserFilter() {
-}
-
-bool SynchronousCompositorBrowserFilter::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorBrowserFilter, message)
- IPC_MESSAGE_HANDLER_GENERIC(SyncCompositorHostMsg_ReturnFrame,
- ReceiveFrame(message))
- IPC_MESSAGE_HANDLER_GENERIC(SyncCompositorHostMsg_BeginFrameResponse,
- BeginFrameResponse(message))
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-bool SynchronousCompositorBrowserFilter::ReceiveFrame(
- const IPC::Message& message) {
- SyncCompositorHostMsg_ReturnFrame::Param param;
- if (!SyncCompositorHostMsg_ReturnFrame::Read(&message, &param))
- return false;
-
- int routing_id = message.routing_id();
- auto itr = bridges_.find(routing_id);
- if (itr == bridges_.end()) {
- bad_message::ReceivedBadMessage(this, bad_message::SCO_INVALID_ARGUMENT);
- return true;
- }
-
- int frame_sink_id = std::get<0>(param);
- uint32_t metadata_version = std::get<1>(param);
- base::Optional<viz::CompositorFrame>& compositor_frame = std::get<2>(param);
-
- if (!itr->second->ReceiveFrameOnIOThread(frame_sink_id, metadata_version,
- std::move(compositor_frame))) {
- bad_message::ReceivedBadMessage(this, bad_message::SCO_INVALID_ARGUMENT);
- }
- return true;
-}
-
-bool SynchronousCompositorBrowserFilter::BeginFrameResponse(
- const IPC::Message& message) {
- SyncCompositorHostMsg_BeginFrameResponse::Param param;
- if (!SyncCompositorHostMsg_BeginFrameResponse::Read(&message, &param))
- return false;
-
- int routing_id = message.routing_id();
- auto itr = bridges_.find(routing_id);
- if (itr == bridges_.end()) {
- bad_message::ReceivedBadMessage(this, bad_message::SCO_INVALID_ARGUMENT);
- return true;
- }
- const SyncCompositorCommonRendererParams& render_params = std::get<0>(param);
- if (!itr->second->BeginFrameResponseOnIOThread(render_params))
- bad_message::ReceivedBadMessage(this, bad_message::SCO_INVALID_ARGUMENT);
- return true;
-}
-
-void SynchronousCompositorBrowserFilter::OnFilterAdded(IPC::Channel* channel) {
- filter_ready_ = true;
- for (auto& bridge : bridges_)
- bridge.second->RemoteReady();
-}
-
-void SynchronousCompositorBrowserFilter::OnFilterRemoved() {
- SignalFilterClosed();
-}
-
-void SynchronousCompositorBrowserFilter::OnChannelClosing() {
- SignalFilterClosed();
-}
-
-void SynchronousCompositorBrowserFilter::OnChannelError() {
- SignalFilterClosed();
-}
-
-void SynchronousCompositorBrowserFilter::SignalFilterClosed() {
- for (auto& bridge : bridges_)
- bridge.second->RemoteClosedOnIOThread();
-}
-
-void SynchronousCompositorBrowserFilter::RegisterSyncCallBridge(
- int routing_id,
- scoped_refptr<SynchronousCompositorSyncCallBridge> host_bridge) {
- DCHECK(bridges_.find(routing_id) == bridges_.end());
- bridges_[routing_id] = host_bridge;
- if (filter_ready_)
- host_bridge->RemoteReady();
-}
-
-void SynchronousCompositorBrowserFilter::UnregisterSyncCallBridge(
- int routing_id) {
- DCHECK(bridges_.find(routing_id) != bridges_.end());
- bridges_.erase(routing_id);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/synchronous_compositor_browser_filter.h b/chromium/content/browser/android/synchronous_compositor_browser_filter.h
deleted file mode 100644
index 111e26a77fc..00000000000
--- a/chromium/content/browser/android/synchronous_compositor_browser_filter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 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_ANDROID_SYNCHRONOUS_COMPOSITOR_BROWSER_FILTER_H_
-#define CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_BROWSER_FILTER_H_
-
-#include <map>
-#include <vector>
-
-#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
-
-namespace content {
-
-class RenderProcessHost;
-class SynchronousCompositorSyncCallBridge;
-
-class SynchronousCompositorBrowserFilter : public BrowserMessageFilter {
- public:
- explicit SynchronousCompositorBrowserFilter(int process_id);
-
- // BrowserMessageFilter overrides.
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnFilterAdded(IPC::Channel* channel) override;
- void OnFilterRemoved() override;
- void OnChannelClosing() override;
- void OnChannelError() override;
-
- void RegisterSyncCallBridge(
- int routing_id,
- scoped_refptr<SynchronousCompositorSyncCallBridge> host_bridge);
- void UnregisterSyncCallBridge(int routing_id);
-
- private:
- ~SynchronousCompositorBrowserFilter() override;
-
- bool ReceiveFrame(const IPC::Message& message);
- bool BeginFrameResponse(const IPC::Message& message);
- void SignalFilterClosed();
-
- RenderProcessHost* const render_process_host_;
-
- std::map<int, scoped_refptr<SynchronousCompositorSyncCallBridge>> bridges_;
-
- bool filter_ready_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorBrowserFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_SYNCHRONOUS_COMPOSITOR_BROWSER_FILTER_H_
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index 7a2ce5797c4..39672258292 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -13,7 +13,6 @@
#include "base/memory/shared_memory.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event_argument.h"
-#include "content/browser/android/synchronous_compositor_browser_filter.h"
#include "content/browser/android/synchronous_compositor_sync_call_bridge.h"
#include "content/browser/bad_message.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
@@ -36,116 +35,6 @@
namespace content {
-class SynchronousCompositorLegacyChromeIPC
- : public mojom::SynchronousCompositor {
- public:
- SynchronousCompositorLegacyChromeIPC(IPC::Sender* sender, int routing_id)
- : sender_(sender), routing_id_(routing_id) {}
-
- void ComputeScroll(base::TimeTicks animation_time) override {
- sender_->Send(
- new SyncCompositorMsg_ComputeScroll(routing_id_, animation_time));
- }
-
- void DemandDrawHwAsync(
- const SyncCompositorDemandDrawHwParams& draw_params) override {
- sender_->Send(
- new SyncCompositorMsg_DemandDrawHwAsync(routing_id_, draw_params));
- }
-
- bool DemandDrawHw(
- const content::SyncCompositorDemandDrawHwParams& draw_params,
- content::SyncCompositorCommonRendererParams* out_result,
- uint32_t* out_layer_tree_frame_sink_id,
- uint32_t* out_metadata_version,
- base::Optional<viz::CompositorFrame>* out_frame) override {
- return sender_->Send(new SyncCompositorMsg_DemandDrawHw(
- routing_id_, draw_params, out_result, out_layer_tree_frame_sink_id,
- out_metadata_version, out_frame));
- }
-
- void DemandDrawHw(const SyncCompositorDemandDrawHwParams& params,
- DemandDrawHwCallback callback) override {
- NOTREACHED();
- }
-
- bool SetSharedMemory(
- const content::SyncCompositorSetSharedMemoryParams& params,
- bool* out_success,
- content::SyncCompositorCommonRendererParams* out_result) override {
- return sender_->Send(new SyncCompositorMsg_SetSharedMemory(
- routing_id_, params, out_success, out_result));
- }
-
- void SetSharedMemory(const SyncCompositorSetSharedMemoryParams& params,
- SetSharedMemoryCallback callback) override {
- NOTREACHED();
- }
-
- bool DemandDrawSw(
- const content::SyncCompositorDemandDrawSwParams& draw_params,
- content::SyncCompositorCommonRendererParams* out_result,
- uint32_t* out_metadata_version,
- base::Optional<viz::CompositorFrameMetadata>* out_meta_data) override {
- return sender_->Send(new SyncCompositorMsg_DemandDrawSw(
- routing_id_, draw_params, out_result, out_metadata_version,
- out_meta_data));
- }
-
- void DemandDrawSw(const SyncCompositorDemandDrawSwParams& params,
- DemandDrawSwCallback callback) override {
- NOTREACHED();
- }
-
- void ZeroSharedMemory() override {
- sender_->Send(new SyncCompositorMsg_ZeroSharedMemory(routing_id_));
- }
-
- bool ZoomBy(
- float delta,
- const gfx::Point& anchor,
- content::SyncCompositorCommonRendererParams* out_result) override {
- return sender_->Send(
- new SyncCompositorMsg_ZoomBy(routing_id_, delta, anchor, out_result));
- }
-
- void ZoomBy(float zoom_delta,
- const gfx::Point& anchor,
- ZoomByCallback) override {
- NOTREACHED();
- }
-
- void SetMemoryPolicy(uint32_t bytes_limit) override {
- sender_->Send(
- new SyncCompositorMsg_SetMemoryPolicy(routing_id_, bytes_limit));
- }
-
- void ReclaimResources(
- uint32_t layer_tree_frame_sink_id,
- const std::vector<viz::ReturnedResource>& resources) override {
- sender_->Send(new SyncCompositorMsg_ReclaimResources(
- routing_id_, layer_tree_frame_sink_id, resources));
- }
-
- void SetScroll(const gfx::ScrollOffset& total_scroll_offset) override {
- sender_->Send(
- new SyncCompositorMsg_SetScroll(routing_id_, total_scroll_offset));
- }
-
- void BeginFrame(const viz::BeginFrameArgs& args) override {
- sender_->Send(new SyncCompositorMsg_BeginFrame(routing_id_, args));
- }
-
- void SetBeginFrameSourcePaused(bool paused) override {
- sender_->Send(
- new SyncCompositorMsg_SetBeginFramePaused(routing_id_, paused));
- }
-
- private:
- IPC::Sender* const sender_;
- int routing_id_;
-};
-
// This class runs on the IO thread and is destroyed when the renderer
// side closes the mojo channel.
class SynchronousCompositorControlHost
@@ -224,7 +113,6 @@ SynchronousCompositorHost::SynchronousCompositorHost(
client_(rwhva->synchronous_compositor_client()),
process_id_(rwhva_->GetRenderWidgetHost()->GetProcess()->GetID()),
routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
- use_mojo_(base::FeatureList::IsEnabled(features::kMojoInputMessages)),
use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
host_binding_(this),
bytes_limit_(0u),
@@ -234,12 +122,6 @@ SynchronousCompositorHost::SynchronousCompositorHost(
did_activate_pending_tree_count_(0u) {
client_->DidInitializeCompositor(this, process_id_, routing_id_);
bridge_ = new SynchronousCompositorSyncCallBridge(this);
-
- if (!use_mojo_) {
- bridge_->BindFilterOnUIThread();
- legacy_compositor_ = std::make_unique<SynchronousCompositorLegacyChromeIPC>(
- rwhva_->GetRenderWidgetHost(), routing_id_);
- }
}
SynchronousCompositorHost::~SynchronousCompositorHost() {
@@ -248,9 +130,6 @@ SynchronousCompositorHost::~SynchronousCompositorHost() {
}
void SynchronousCompositorHost::InitMojo() {
- if (!use_mojo_)
- return;
-
mojom::SynchronousCompositorControlHostPtr host_control;
mojom::SynchronousCompositorControlHostRequest host_request =
mojo::MakeRequest(&host_control);
@@ -274,19 +153,6 @@ bool SynchronousCompositorHost::IsReadyForSynchronousCall() {
return res;
}
-bool SynchronousCompositorHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorHost, message)
- IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_LayerTreeFrameSinkCreated,
- LayerTreeFrameSinkCreated)
- IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_SetNeedsBeginFrames,
- SetNeedsBeginFrames)
- IPC_MESSAGE_HANDLER(SyncCompositorHostMsg_UpdateState, UpdateState)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
scoped_refptr<SynchronousCompositor::FrameFuture>
SynchronousCompositorHost::DemandDrawHwAsync(
const gfx::Size& viewport_size,
@@ -613,8 +479,7 @@ void SynchronousCompositorHost::SetNeedsBeginFrames(bool needs_begin_frames) {
}
void SynchronousCompositorHost::LayerTreeFrameSinkCreated() {
- if (use_mojo_)
- bridge_->RemoteReady();
+ bridge_->RemoteReady();
// New LayerTreeFrameSink is not aware of state from Browser side. So need to
// re-send all browser side state here.
@@ -660,20 +525,12 @@ void SynchronousCompositorHost::UpdateState(
}
}
-SynchronousCompositorBrowserFilter* SynchronousCompositorHost::GetFilter() {
- return static_cast<RenderProcessHostImpl*>(
- rwhva_->GetRenderWidgetHost()->GetProcess())
- ->synchronous_compositor_filter();
-}
-
RenderProcessHost* SynchronousCompositorHost::GetRenderProcessHost() {
return rwhva_->GetRenderWidgetHost()->GetProcess();
}
mojom::SynchronousCompositor*
SynchronousCompositorHost::GetSynchronousCompositor() {
- if (legacy_compositor_)
- return legacy_compositor_.get();
return sync_compositor_.get();
}
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index 74e01ac917d..7333ee6a263 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -23,10 +23,6 @@
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/size_f.h"
-namespace IPC {
-class Message;
-}
-
namespace ui {
class WindowAndroid;
struct DidOverscrollParams;
@@ -37,8 +33,6 @@ namespace content {
class RenderProcessHost;
class RenderWidgetHostViewAndroid;
class SynchronousCompositorClient;
-class SynchronousCompositorBrowserFilter;
-class SynchronousCompositorLegacyChromeIPC;
class SynchronousCompositorSyncCallBridge;
struct SyncCompositorCommonRendererParams;
@@ -69,7 +63,6 @@ class SynchronousCompositorHost : public SynchronousCompositor,
void BeginFrame(ui::WindowAndroid* window_android,
const viz::BeginFrameArgs& args);
void SetBeginFramePaused(bool paused);
- bool OnMessageReceived(const IPC::Message& message);
// Called by SynchronousCompositorSyncCallBridge.
int routing_id() const { return routing_id_; }
@@ -81,7 +74,6 @@ class SynchronousCompositorHost : public SynchronousCompositor,
SynchronousCompositorClient* client() { return client_; }
- SynchronousCompositorBrowserFilter* GetFilter();
RenderProcessHost* GetRenderProcessHost();
// mojom::SynchronousCompositorHost overrides.
@@ -115,9 +107,7 @@ class SynchronousCompositorHost : public SynchronousCompositor,
SynchronousCompositorClient* const client_;
const int process_id_;
const int routing_id_;
- const bool use_mojo_;
const bool use_in_process_zero_copy_software_draw_;
- std::unique_ptr<SynchronousCompositorLegacyChromeIPC> legacy_compositor_;
mojom::SynchronousCompositorAssociatedPtr sync_compositor_;
mojo::AssociatedBinding<mojom::SynchronousCompositorHost> host_binding_;
diff --git a/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc b/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc
index bbd19c4f3da..1f560661134 100644
--- a/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc
+++ b/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.cc
@@ -4,7 +4,6 @@
#include "content/browser/android/synchronous_compositor_sync_call_bridge.h"
-#include "content/browser/android/synchronous_compositor_browser_filter.h"
#include "content/browser/android/synchronous_compositor_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -17,7 +16,6 @@ SynchronousCompositorSyncCallBridge::SynchronousCompositorSyncCallBridge(
SynchronousCompositorHost* host)
: routing_id_(host->routing_id()),
host_(host),
- mojo_enabled_(base::FeatureList::IsEnabled(features::kMojoInputMessages)),
begin_frame_condition_(&lock_) {
DCHECK(host);
}
@@ -27,23 +25,6 @@ SynchronousCompositorSyncCallBridge::~SynchronousCompositorSyncCallBridge() {
DCHECK(!window_android_in_vsync_);
}
-void SynchronousCompositorSyncCallBridge::BindFilterOnUIThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(host_);
- if (mojo_enabled_ || bound_to_filter_)
- return;
- scoped_refptr<SynchronousCompositorBrowserFilter> filter = host_->GetFilter();
- if (!filter)
- return;
- bound_to_filter_ = true;
- scoped_refptr<SynchronousCompositorSyncCallBridge> thiz = this;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &SynchronousCompositorBrowserFilter::RegisterSyncCallBridge,
- std::move(filter), routing_id_, thiz));
-}
-
void SynchronousCompositorSyncCallBridge::RemoteReady() {
base::AutoLock lock(lock_);
if (remote_state_ != RemoteState::INIT)
@@ -55,7 +36,6 @@ void SynchronousCompositorSyncCallBridge::RemoteClosedOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::AutoLock lock(lock_);
SignalRemoteClosedToAllWaitersOnIOThread();
- UnregisterSyncCallBridgeIfNecessary();
}
bool SynchronousCompositorSyncCallBridge::ReceiveFrameOnIOThread(
@@ -84,8 +64,6 @@ bool SynchronousCompositorSyncCallBridge::ReceiveFrameOnIOThread(
*frame_ptr->frame = std::move(*compositor_frame);
}
future->SetFrame(std::move(frame_ptr));
-
- UnregisterSyncCallBridgeIfNecessary();
return true;
}
@@ -105,12 +83,9 @@ bool SynchronousCompositorSyncCallBridge::WaitAfterVSyncOnUIThread(
ui::WindowAndroid* window_android) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::AutoLock lock(lock_);
- if (!mojo_enabled_ && !bound_to_filter_)
- BindFilterOnUIThread();
if (remote_state_ != RemoteState::READY)
return false;
DCHECK(!begin_frame_response_valid_);
- DCHECK(mojo_enabled_ || bound_to_filter_);
if (window_android_in_vsync_) {
DCHECK_EQ(window_android_in_vsync_, window_android);
return true;
@@ -129,8 +104,6 @@ bool SynchronousCompositorSyncCallBridge::SetFrameFutureOnUIThread(
if (remote_state_ != RemoteState::READY)
return false;
- BindFilterOnUIThread();
- DCHECK(mojo_enabled_ || bound_to_filter_);
// Allowing arbitrary number of pending futures can lead to increase in frame
// latency. Due to this, Android platform already ensures that here that there
// can be at most 2 pending frames. Here, we rely on Android to do the
@@ -144,20 +117,7 @@ bool SynchronousCompositorSyncCallBridge::SetFrameFutureOnUIThread(
void SynchronousCompositorSyncCallBridge::HostDestroyedOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(host_);
- scoped_refptr<SynchronousCompositorBrowserFilter> filter = host_->GetFilter();
-
- base::AutoLock lock(lock_);
- bound_to_filter_ = false;
host_ = nullptr;
-
- if (filter) {
- unregister_callback_ =
- base::BindOnce(&SynchronousCompositorSyncCallBridge::
- UnregisterSyncCallBridgeOnIOThread,
- this, filter);
-
- UnregisterSyncCallBridgeIfNecessary();
- }
}
bool SynchronousCompositorSyncCallBridge::IsRemoteReadyOnUIThread() {
@@ -203,19 +163,6 @@ void SynchronousCompositorSyncCallBridge::ProcessFrameMetadataOnUIThread(
host_->UpdateFrameMetaData(metadata_version, std::move(metadata));
}
-void SynchronousCompositorSyncCallBridge::UnregisterSyncCallBridgeOnIOThread(
- scoped_refptr<SynchronousCompositorBrowserFilter> filter) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- {
- base::AutoLock lock(lock_);
- if (remote_state_ == RemoteState::READY)
- SignalRemoteClosedToAllWaitersOnIOThread();
- }
- if (filter)
- filter->UnregisterSyncCallBridge(routing_id_);
-}
-
void SynchronousCompositorSyncCallBridge::
SignalRemoteClosedToAllWaitersOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -228,17 +175,4 @@ void SynchronousCompositorSyncCallBridge::
begin_frame_condition_.Signal();
}
-void SynchronousCompositorSyncCallBridge::
- UnregisterSyncCallBridgeIfNecessary() {
- // Can be called from either thread.
- lock_.AssertAcquired();
-
- // If no more frames left deregister if necessary. Post a task as
- // unregistering will destroy this object.
- if (frame_futures_.empty() && unregister_callback_) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- std::move(unregister_callback_));
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h b/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h
index 4a40e8bcfaa..36dc19df4ad 100644
--- a/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h
+++ b/chromium/content/browser/android/synchronous_compositor_sync_call_bridge.h
@@ -14,7 +14,6 @@
namespace content {
-class SynchronousCompositorBrowserFilter;
class SynchronousCompositorHost;
// For the synchronous compositor feature of webview it is necessary
@@ -71,9 +70,6 @@ class SynchronousCompositorSyncCallBridge
public:
explicit SynchronousCompositorSyncCallBridge(SynchronousCompositorHost* host);
- // Attach a filter.
- void BindFilterOnUIThread();
-
// Indicatation that the remote is now ready to process requests. Called
// on either UI or IO thread.
void RemoteReady();
@@ -117,16 +113,9 @@ class SynchronousCompositorSyncCallBridge
void ProcessFrameMetadataOnUIThread(uint32_t metadata_version,
viz::CompositorFrameMetadata metadata);
- void UnregisterSyncCallBridgeOnIOThread(
- scoped_refptr<SynchronousCompositorBrowserFilter> filter);
-
// Signal all waiters for closure. Callee must host a lock to |lock_|.
void SignalRemoteClosedToAllWaitersOnIOThread();
- // Post a task to unregister the bridge with the filter if necessary. Can
- // be called on either thread but must hold a lock to |lock_|.
- void UnregisterSyncCallBridgeIfNecessary();
-
using FrameFutureQueue =
base::circular_deque<scoped_refptr<SynchronousCompositor::FrameFuture>>;
@@ -137,8 +126,6 @@ class SynchronousCompositorSyncCallBridge
// UI thread only.
ui::WindowAndroid* window_android_in_vsync_ = nullptr;
SynchronousCompositorHost* host_;
- bool bound_to_filter_ = false;
- bool mojo_enabled_;
// Shared variables between the IO thread and UI thread.
base::Lock lock_;
@@ -148,11 +135,6 @@ class SynchronousCompositorSyncCallBridge
base::ConditionVariable begin_frame_condition_;
RemoteState remote_state_ = RemoteState::INIT;
- // IO thread based callback that will unbind this object from
- // the SynchronousCompositorBrowserFilter. Only called once
- // all pending frames are acknowledged.
- base::OnceClosure unregister_callback_;
-
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorSyncCallBridge);
};
diff --git a/chromium/content/browser/android/url_request_content_job.cc b/chromium/content/browser/android/url_request_content_job.cc
index fb7f3c479a8..7ea404b10e2 100644
--- a/chromium/content/browser/android/url_request_content_job.cc
+++ b/chromium/content/browser/android/url_request_content_job.cc
@@ -7,7 +7,6 @@
#include "base/android/content_uri_utils.h"
#include "base/bind.h"
#include "base/files/file_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/task_runner.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_type.h"
diff --git a/chromium/content/browser/android/url_request_content_job_unittest.cc b/chromium/content/browser/android/url_request_content_job_unittest.cc
index 8815dc8f323..f15fb087e1b 100644
--- a/chromium/content/browser/android/url_request_content_job_unittest.cc
+++ b/chromium/content/browser/android/url_request_content_job_unittest.cc
@@ -129,7 +129,7 @@ URLRequestContentJobTest::URLRequestContentJobTest() {}
void URLRequestContentJobTest::RunRequest(const Range* range,
const char* intent_type) {
base::FilePath test_dir;
- PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
+ base::PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
test_dir = test_dir.AppendASCII("content");
test_dir = test_dir.AppendASCII("test");
test_dir = test_dir.AppendASCII("data");
diff --git a/chromium/content/browser/appcache/OWNERS b/chromium/content/browser/appcache/OWNERS
index 21ddbb8551d..db1043cbffe 100644
--- a/chromium/content/browser/appcache/OWNERS
+++ b/chromium/content/browser/appcache/OWNERS
@@ -1,8 +1,5 @@
pwnall@chromium.org
jsbell@chromium.org
-# OOO until this comment is removed.
-michaeln@chromium.org
-
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>AppCache
diff --git a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
index e6e94b70099..321ad52d4f1 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_task_environment.h"
diff --git a/chromium/content/browser/appcache/appcache_interceptor.cc b/chromium/content/browser/appcache/appcache_interceptor.cc
index 249851898ec..6ff24bf35ac 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.cc
+++ b/chromium/content/browser/appcache/appcache_interceptor.cc
@@ -81,45 +81,6 @@ void AppCacheInterceptor::GetExtraResponseInfo(net::URLRequest* request,
handler->GetExtraResponseInfo(cache_id, manifest_url);
}
-void AppCacheInterceptor::PrepareForCrossSiteTransfer(
- net::URLRequest* request,
- int old_process_id) {
- AppCacheRequestHandler* handler = GetHandler(request);
- if (!handler)
- return;
- handler->PrepareForCrossSiteTransfer(old_process_id);
-}
-
-void AppCacheInterceptor::CompleteCrossSiteTransfer(
- net::URLRequest* request,
- int new_process_id,
- int new_host_id,
- ResourceRequesterInfo* requester_info) {
- // AppCache is supported only for renderer initiated requests.
- DCHECK(requester_info->IsRenderer());
- AppCacheRequestHandler* handler = GetHandler(request);
- if (!handler)
- return;
- if (!handler->SanityCheckIsSameService(requester_info->appcache_service())) {
- // This can happen when V2 apps and web pages end up in the same storage
- // partition.
- bad_message::ReceivedBadMessage(requester_info->filter(),
- bad_message::ACI_WRONG_STORAGE_PARTITION);
- return;
- }
- DCHECK_NE(kAppCacheNoHostId, new_host_id);
- handler->CompleteCrossSiteTransfer(new_process_id, new_host_id);
-}
-
-void AppCacheInterceptor::MaybeCompleteCrossSiteTransferInOldProcess(
- net::URLRequest* request,
- int process_id) {
- AppCacheRequestHandler* handler = GetHandler(request);
- if (!handler)
- return;
- handler->MaybeCompleteCrossSiteTransferInOldProcess(process_id);
-}
-
AppCacheInterceptor::AppCacheInterceptor() {
}
diff --git a/chromium/content/browser/appcache/appcache_interceptor.h b/chromium/content/browser/appcache/appcache_interceptor.h
index 7f802d175ac..6658220ddd4 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.h
+++ b/chromium/content/browser/appcache/appcache_interceptor.h
@@ -24,7 +24,6 @@ namespace content {
class AppCacheHost;
class AppCacheRequestHandler;
class AppCacheServiceImpl;
-class ResourceRequesterInfo;
// An interceptor to hijack requests and potentially service them out of
// the appcache.
@@ -51,17 +50,6 @@ class CONTENT_EXPORT AppCacheInterceptor : public net::URLRequestInterceptor {
int64_t* cache_id,
GURL* manifest_url);
- // Methods to support cross site navigations.
- static void PrepareForCrossSiteTransfer(net::URLRequest* request,
- int old_process_id);
- static void CompleteCrossSiteTransfer(net::URLRequest* request,
- int new_process_id,
- int new_host_id,
- ResourceRequesterInfo* requester_info);
- static void MaybeCompleteCrossSiteTransferInOldProcess(
- net::URLRequest* request,
- int old_process_id);
-
AppCacheInterceptor();
~AppCacheInterceptor() override;
diff --git a/chromium/content/browser/appcache/appcache_request_handler.cc b/chromium/content/browser/appcache/appcache_request_handler.cc
index f7d16136ca7..07d2b0573e4 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -47,8 +47,6 @@ AppCacheRequestHandler::AppCacheRequestHandler(
cache_entry_not_found_(false),
is_delivering_network_response_(false),
maybe_load_resource_executed_(false),
- old_process_id_(0),
- old_host_id_(kAppCacheNoHostId),
cache_id_(kAppCacheNoCacheId),
service_(host_->service()),
request_(std::move(request)),
@@ -222,37 +220,6 @@ void AppCacheRequestHandler::GetExtraResponseInfo(int64_t* cache_id,
*manifest_url = manifest_url_;
}
-void AppCacheRequestHandler::PrepareForCrossSiteTransfer(int old_process_id) {
- if (!host_)
- return;
- AppCacheBackendImpl* backend = host_->service()->GetBackend(old_process_id);
- DCHECK(backend) << "appcache detected likely storage partition mismatch";
- old_process_id_ = old_process_id;
- old_host_id_ = host_->host_id();
- host_for_cross_site_transfer_ = backend->TransferHostOut(host_->host_id());
- DCHECK_EQ(host_, host_for_cross_site_transfer_.get());
-}
-
-void AppCacheRequestHandler::CompleteCrossSiteTransfer(
- int new_process_id, int new_host_id) {
- if (!host_for_cross_site_transfer_.get())
- return;
- DCHECK_EQ(host_, host_for_cross_site_transfer_.get());
- AppCacheBackendImpl* backend = host_->service()->GetBackend(new_process_id);
- DCHECK(backend) << "appcache detected likely storage partition mismatch";
- backend->TransferHostIn(new_host_id,
- std::move(host_for_cross_site_transfer_));
-}
-
-void AppCacheRequestHandler::MaybeCompleteCrossSiteTransferInOldProcess(
- int old_process_id) {
- if (!host_ || !host_for_cross_site_transfer_.get() ||
- old_process_id != old_process_id_) {
- return;
- }
- CompleteCrossSiteTransfer(old_process_id_, old_host_id_);
-}
-
// static
std::unique_ptr<AppCacheRequestHandler>
AppCacheRequestHandler::InitializeForNavigationNetworkService(
@@ -286,13 +253,11 @@ void AppCacheRequestHandler::OnServiceDestructionImminent(
AppCacheServiceImpl* service) {
service_ = nullptr;
if (!host_) {
- DCHECK(!host_for_cross_site_transfer_);
DCHECK(!job_);
return;
}
host_->RemoveObserver(this);
OnDestructionImminent(host_);
- host_for_cross_site_transfer_.reset();
}
void AppCacheRequestHandler::DeliverAppCachedResponse(
diff --git a/chromium/content/browser/appcache/appcache_request_handler.h b/chromium/content/browser/appcache/appcache_request_handler.h
index 9f79c30586b..cea61697ba8 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.h
+++ b/chromium/content/browser/appcache/appcache_request_handler.h
@@ -67,21 +67,10 @@ class CONTENT_EXPORT AppCacheRequestHandler
void GetExtraResponseInfo(int64_t* cache_id, GURL* manifest_url);
- // Methods to support cross site navigations.
- void PrepareForCrossSiteTransfer(int old_process_id);
- void CompleteCrossSiteTransfer(int new_process_id, int new_host_id);
- void MaybeCompleteCrossSiteTransferInOldProcess(int old_process_id);
-
- // Useful for detecting storage partition mismatches in the context
- // of cross site transfer navigations.
- bool SanityCheckIsSameService(AppCacheService* service) {
- return !host_ || (host_->service() == service);
- }
-
// NetworkService loading
// NavigationLoaderInterceptor overrides - main resource loading.
- // These methods are used by the NavigationURLLoaderNetworkService.
+ // These methods are used by the NavigationURLLoaderImpl.
// Internally they use same methods used by the network library based impl,
// MaybeLoadResource and MaybeLoadFallbackForResponse.
// Eventually one of the Deliver*Response() methods is called and the
@@ -249,12 +238,6 @@ class CONTENT_EXPORT AppCacheRequestHandler
// 3) Request has been cancelled, and the job killed.
base::WeakPtr<AppCacheJob> job_;
- // During a cross site navigation, we transfer ownership the AppcacheHost
- // from the old processes structures over to the new structures.
- std::unique_ptr<AppCacheHost> host_for_cross_site_transfer_;
- int old_process_id_;
- int old_host_id_;
-
// Cached information about the response being currently served by the
// AppCache, if there is one.
int cache_id_;
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index f2391591aaa..3e742cdca67 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -818,28 +818,6 @@ class AppCacheRequestHandlerTest
TestFinished();
}
- void DestroyedServiceWithCrossSiteNav() {
- EXPECT_TRUE(CreateRequestAndHandler(GURL("http://blah/"), host_,
- RESOURCE_TYPE_MAIN_FRAME));
- EXPECT_TRUE(handler_.get());
- handler_->PrepareForCrossSiteTransfer(backend_impl_->process_id());
- EXPECT_TRUE(handler_->host_for_cross_site_transfer_.get());
-
- backend_impl_.reset();
- mock_frontend_.reset();
- mock_service_.reset();
- mock_policy_.reset();
- host_ = nullptr;
-
- EXPECT_FALSE(handler_->host_for_cross_site_transfer_.get());
- EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
- EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
- nullptr, GURL("http://blah/redirect")));
- EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
-
- TestFinished();
- }
-
// UnsupportedScheme -----------------------------
void UnsupportedScheme() {
@@ -1065,11 +1043,6 @@ TEST_P(AppCacheRequestHandlerTest, DestroyedService) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedService);
}
-TEST_P(AppCacheRequestHandlerTest, DestroyedServiceWithCrossSiteNav) {
- RunTestOnIOThread(
- &AppCacheRequestHandlerTest::DestroyedServiceWithCrossSiteNav);
-}
-
TEST_P(AppCacheRequestHandlerTest, UnsupportedScheme) {
RunTestOnIOThread(&AppCacheRequestHandlerTest::UnsupportedScheme);
}
diff --git a/chromium/content/browser/appcache/appcache_service_impl.h b/chromium/content/browser/appcache/appcache_service_impl.h
index a2a41ed9e4f..ff3bcd5153d 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.h
+++ b/chromium/content/browser/appcache/appcache_service_impl.h
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
+#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/url_loader_factory_getter.h"
diff --git a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
index d8988c284b7..43400a1f726 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -18,6 +18,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_task_environment.h"
diff --git a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
index a59273f1659..72bb381ee93 100644
--- a/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/chromium/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -127,9 +127,13 @@ class SubresourceLoader : public network::mojom::URLLoader,
// network::mojom::URLLoader implementation
// Called by the remote client in the renderer.
- void FollowRedirect() override {
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
if (!handler_) {
- network_loader_->FollowRedirect();
+ network_loader_->FollowRedirect(base::nullopt);
return;
}
DCHECK(network_loader_);
@@ -148,7 +152,7 @@ class SubresourceLoader : public network::mojom::URLLoader,
if (handler)
CreateAndStartAppCacheLoader(std::move(handler));
else
- network_loader_->FollowRedirect();
+ network_loader_->FollowRedirect(base::nullopt);
}
void SetPriority(net::RequestPriority priority,
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.cc b/chromium/content/browser/appcache/appcache_url_loader_job.cc
index 520195a6ca8..b3969898ae2 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.cc
@@ -105,7 +105,8 @@ base::WeakPtr<AppCacheURLLoaderJob> AppCacheURLLoaderJob::GetDerivedWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-void AppCacheURLLoaderJob::FollowRedirect() {
+void AppCacheURLLoaderJob::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
NOTREACHED() << "appcache never produces redirects";
}
diff --git a/chromium/content/browser/appcache/appcache_url_loader_job.h b/chromium/content/browser/appcache/appcache_url_loader_job.h
index f64748dc4a4..d116c91d890 100644
--- a/chromium/content/browser/appcache/appcache_url_loader_job.h
+++ b/chromium/content/browser/appcache/appcache_url_loader_job.h
@@ -55,7 +55,8 @@ class CONTENT_EXPORT AppCacheURLLoaderJob : public AppCacheJob,
base::WeakPtr<AppCacheURLLoaderJob> GetDerivedWeakPtr();
// network::mojom::URLLoader implementation:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
diff --git a/chromium/content/browser/background_fetch/background_fetch.proto b/chromium/content/browser/background_fetch/background_fetch.proto
index b33f8003e4b..ec387edd7b8 100644
--- a/chromium/content/browser/background_fetch/background_fetch.proto
+++ b/chromium/content/browser/background_fetch/background_fetch.proto
@@ -61,7 +61,7 @@ message BackgroundFetchOptions {
// in memory. This information should be everything needed to reconstruct
// the state of an interrupted background fetch.
//
-// Next Tag: 6
+// Next Tag: 7
message BackgroundFetchMetadata {
optional int64 creation_microseconds_since_unix_epoch = 1;
optional string origin = 2;
@@ -69,8 +69,38 @@ message BackgroundFetchMetadata {
optional BackgroundFetchRegistration registration = 3;
optional BackgroundFetchOptions options = 4;
- // Defaults to BackgroundFetchOptions.title.
- // Can be updated by calling `BackgroundFetchUpdateEvent.updateUI`.
- // https://wicg.github.io/background-fetch/#backgroundfetchupdateevent.
- optional string ui_title = 5;
+ // Number of fetches initiated by the developer.
+ optional int32 num_fetches = 5;
+}
+
+// A background fetch request that is still in a pending state.
+//
+// Next Tag: 4
+message BackgroundFetchPendingRequest {
+ optional string unique_id = 1;
+ optional int32 request_index = 2;
+ optional string serialized_request = 3;
}
+
+// A background fetch request in the active state. This means that
+// the DownloadManager started downloading the file.
+//
+// Next Tag: 5
+message BackgroundFetchActiveRequest {
+ optional string unique_id = 1;
+ optional int32 request_index = 2;
+ optional string serialized_request = 3;
+ optional string download_guid = 4;
+}
+
+// A background fetch request in the completed state. This means that
+// the DownloadManager returned the download.
+//
+// Next Tag: 6
+message BackgroundFetchCompletedRequest {
+ optional string unique_id = 1;
+ optional int32 request_index = 2;
+ optional string serialized_request = 3;
+ optional string download_guid = 4;
+ optional bool succeeded = 5;
+} \ No newline at end of file
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.cc b/chromium/content/browser/background_fetch/background_fetch_context.cc
index 572933b7540..0ddea261409 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_context.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.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_id.h"
#include "content/browser/background_fetch/background_fetch_registration_notifier.h"
#include "content/browser/background_fetch/background_fetch_scheduler.h"
@@ -19,26 +20,6 @@
namespace content {
-namespace {
-
-void IgnoreError(blink::mojom::BackgroundFetchError) {
- // TODO(johnme): Log errors to UMA.
-}
-
-// 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) {
- // TODO(peter): Add UMA.
-}
-
-// 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) {
- // TODO(peter): Add UMA.
-}
-
-} // namespace
-
BackgroundFetchContext::BackgroundFetchContext(
BrowserContext* browser_context,
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
@@ -111,7 +92,7 @@ void BackgroundFetchContext::StartFetch(
registration_id, requests, options, icon,
base::BindOnce(&BackgroundFetchContext::DidCreateRegistration,
weak_factory_.GetWeakPtr(), registration_id, options, icon,
- std::move(callback)));
+ requests.size(), std::move(callback)));
}
void BackgroundFetchContext::GetIconDisplaySize(
@@ -125,21 +106,34 @@ void BackgroundFetchContext::DidCreateRegistration(
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ size_t num_requests,
blink::mojom::BackgroundFetchService::FetchCallback callback,
blink::mojom::BackgroundFetchError error,
std::unique_ptr<BackgroundFetchRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- RecordRegistrationCreatedError(error);
+ background_fetch::RecordRegistrationCreatedError(error);
if (error != blink::mojom::BackgroundFetchError::NONE) {
std::move(callback).Run(error, base::nullopt);
return;
}
DCHECK(registration);
+
+ BackgroundFetchRegistration* registration_ptr = registration.get();
+ // The closure takes ownership of |registration|, and it's guaranteed to
+ // outlive CreateController, which uses the underlying pointer.
+ base::OnceClosure done_closure = base::BindOnce(
+ [](blink::mojom::BackgroundFetchService::FetchCallback callback,
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<BackgroundFetchRegistration> registration) {
+ std::move(callback).Run(error, *registration);
+ },
+ std::move(callback), error, std::move(registration));
+
// Create the BackgroundFetchJobController to do the actual fetching.
- CreateController(registration_id, options, icon, *registration.get());
- std::move(callback).Run(error, *registration.get());
+ CreateController(registration_id, options, icon, num_requests,
+ *registration_ptr, std::move(done_closure));
}
void BackgroundFetchContext::AddRegistrationObserver(
@@ -190,7 +184,9 @@ void BackgroundFetchContext::CreateController(
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- const BackgroundFetchRegistration& registration) {
+ size_t num_requests,
+ const BackgroundFetchRegistration& registration,
+ base::OnceClosure done_closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto controller = std::make_unique<BackgroundFetchJobController>(
@@ -199,21 +195,31 @@ void BackgroundFetchContext::CreateController(
// 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(&IgnoreError)));
+ base::BindOnce(
+ &BackgroundFetchContext::DidFinishJob, weak_factory_.GetWeakPtr(),
+ base::Bind(&background_fetch::RecordSchedulerFinishedError)));
+
+ data_manager_.GetNumCompletedRequests(
+ registration_id,
+ base::BindOnce(&BackgroundFetchContext::InitializeController,
+ weak_factory_.GetWeakPtr(), registration_id.unique_id(),
+ std::move(controller), std::move(done_closure),
+ num_requests));
+}
- // TODO(delphick): This assumes that fetches are always started afresh in
- // each browser session. We need to initialize the number of downloads using
- // information loaded from the database.
- controller->InitializeRequestStatus(
- 0, /* completed_downloads*/
- data_manager_.GetTotalNumberOfRequests(registration_id),
- std::vector<std::string>() /* outstanding download GUIDs */);
+void BackgroundFetchContext::InitializeController(
+ const std::string& unique_id,
+ std::unique_ptr<BackgroundFetchJobController> controller,
+ base::OnceClosure done_closure,
+ size_t total_downloads,
+ size_t completed_downloads) {
+ controller->InitializeRequestStatus(completed_downloads, total_downloads,
+ {} /* outstanding download GUIDs */);
scheduler_->AddJobController(controller.get());
- job_controllers_.insert(
- std::make_pair(registration_id.unique_id(), std::move(controller)));
+ job_controllers_.insert({unique_id, std::move(controller)});
+ std::move(done_closure).Run();
}
void BackgroundFetchContext::Abort(
@@ -221,13 +227,14 @@ void BackgroundFetchContext::Abort(
blink::mojom::BackgroundFetchService::AbortCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DidFinishJob(std::move(callback), registration_id, true /* aborted */);
+ DidFinishJob(std::move(callback), registration_id,
+ BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER);
}
void BackgroundFetchContext::DidFinishJob(
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
const BackgroundFetchRegistrationId& registration_id,
- bool aborted) {
+ BackgroundFetchReasonToAbort reason_to_abort) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// If |aborted| is true, this will also propagate the event to any active
@@ -235,13 +242,13 @@ void BackgroundFetchContext::DidFinishJob(
data_manager_.MarkRegistrationForDeletion(
registration_id,
base::BindOnce(&BackgroundFetchContext::DidMarkForDeletion,
- weak_factory_.GetWeakPtr(), registration_id, aborted,
- std::move(callback)));
+ weak_factory_.GetWeakPtr(), registration_id,
+ reason_to_abort, std::move(callback)));
}
void BackgroundFetchContext::DidMarkForDeletion(
const BackgroundFetchRegistrationId& registration_id,
- bool aborted,
+ BackgroundFetchReasonToAbort reason_to_abort,
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
blink::mojom::BackgroundFetchError error) {
std::move(callback).Run(error);
@@ -253,19 +260,27 @@ void BackgroundFetchContext::DidMarkForDeletion(
if (error != blink::mojom::BackgroundFetchError::NONE)
return;
- if (aborted) {
+ if (reason_to_abort == BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER) {
DCHECK(job_controllers_.count(registration_id.unique_id()));
- job_controllers_[registration_id.unique_id()]->Abort();
-
- CleanupRegistration(registration_id, {});
+ job_controllers_[registration_id.unique_id()]->Abort(reason_to_abort);
+ }
- event_dispatcher_.DispatchBackgroundFetchAbortEvent(registration_id,
- base::DoNothing());
- } else {
- data_manager_.GetSettledFetchesForRegistration(
- registration_id,
- base::BindOnce(&BackgroundFetchContext::DidGetSettledFetches,
- weak_factory_.GetWeakPtr(), registration_id));
+ switch (reason_to_abort) {
+ case BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER:
+ case BackgroundFetchReasonToAbort::CANCELLED_FROM_UI:
+ CleanupRegistration(registration_id, {});
+ // TODO(rayankans): Send fetches to the event dispatcher.
+ event_dispatcher_.DispatchBackgroundFetchAbortEvent(
+ registration_id, {} /* settled_fetches */, base::DoNothing());
+ return;
+ case BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED:
+ case BackgroundFetchReasonToAbort::NONE:
+ // This will send a BackgroundFetchFetched or BackgroundFetchFail event.
+ data_manager_.GetSettledFetchesForRegistration(
+ registration_id,
+ base::BindOnce(&BackgroundFetchContext::DidGetSettledFetches,
+ weak_factory_.GetWeakPtr(), registration_id));
+ return;
}
}
@@ -278,7 +293,7 @@ void BackgroundFetchContext::DidGetSettledFetches(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (error != blink::mojom::BackgroundFetchError::NONE) {
- CleanupRegistration(registration_id, {});
+ CleanupRegistration(registration_id, {} /* fetches */);
return;
}
@@ -338,7 +353,8 @@ void BackgroundFetchContext::LastObserverGarbageCollected(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
data_manager_.DeleteRegistration(
- registration_id, base::BindOnce(&RecordRegistrationDeletedError));
+ registration_id,
+ base::BindOnce(&background_fetch::RecordRegistrationDeletedError));
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_context.h b/chromium/content/browser/background_fetch/background_fetch_context.h
index d2a8b980fb0..fe0892dd021 100644
--- a/chromium/content/browser/background_fetch/background_fetch_context.h
+++ b/chromium/content/browser/background_fetch/background_fetch_context.h
@@ -113,7 +113,17 @@ class CONTENT_EXPORT BackgroundFetchContext
void CreateController(const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
- const BackgroundFetchRegistration& registration);
+ size_t num_requests,
+ const BackgroundFetchRegistration& registration,
+ base::OnceClosure done_closure);
+
+ // Initializes the new Job Controller.
+ void InitializeController(
+ const std::string& unique_id,
+ std::unique_ptr<BackgroundFetchJobController> controller,
+ base::OnceClosure done_closure,
+ size_t total_downloads,
+ size_t completed_downloads);
// Called when an existing registration has been retrieved from the data
// manager. If the registration does not exist then |registration| is nullptr.
@@ -127,6 +137,7 @@ class CONTENT_EXPORT BackgroundFetchContext
const BackgroundFetchRegistrationId& registration_id,
const BackgroundFetchOptions& options,
const SkBitmap& icon,
+ size_t num_requests,
blink::mojom::BackgroundFetchService::FetchCallback callback,
blink::mojom::BackgroundFetchError error,
std::unique_ptr<BackgroundFetchRegistration> registration);
@@ -143,12 +154,12 @@ class CONTENT_EXPORT BackgroundFetchContext
void DidFinishJob(
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
const BackgroundFetchRegistrationId& registration_id,
- bool aborted);
+ BackgroundFetchReasonToAbort reason_to_abort);
// Called when the data manager finishes marking a registration as deleted.
void DidMarkForDeletion(
const BackgroundFetchRegistrationId& registration_id,
- bool aborted,
+ BackgroundFetchReasonToAbort reason_to_abort,
base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
blink::mojom::BackgroundFetchError error);
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
index 500993d7b94..a8cb4f6d5fc 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -19,7 +19,11 @@
#include "content/browser/background_fetch/storage/delete_registration_task.h"
#include "content/browser/background_fetch/storage/get_developer_ids_task.h"
#include "content/browser/background_fetch/storage/get_metadata_task.h"
+#include "content/browser/background_fetch/storage/get_num_requests_task.h"
+#include "content/browser/background_fetch/storage/get_settled_fetches_task.h"
#include "content/browser/background_fetch/storage/mark_registration_for_deletion_task.h"
+#include "content/browser/background_fetch/storage/mark_request_complete_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/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -142,10 +146,7 @@ class BackgroundFetchDataManager::RegistrationData {
uint64_t GetDownloaded() const { return complete_requests_downloaded_bytes_; }
- int GetTotalNumberOfRequests() const {
- return pending_requests_.size() + active_requests_.size() +
- completed_requests_.size();
- }
+ size_t GetNumCompletedRequests() const { return completed_requests_.size(); }
private:
BackgroundFetchRegistrationId registration_id_;
@@ -343,8 +344,24 @@ void BackgroundFetchDataManager::PopNextRequest(
NextRequestCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBackgroundFetchPersistence)) {
+ auto start_next_request = base::BindOnce(
+ &BackgroundFetchDataManager::AddStartNextPendingRequestTask,
+ weak_ptr_factory_.GetWeakPtr(),
+ registration_id.service_worker_registration_id(), std::move(callback));
+
+ // Get the associated metadata, and add a StartNextPendingRequestTask.
+ GetMetadata(registration_id.service_worker_registration_id(),
+ registration_id.origin(), registration_id.developer_id(),
+ std::move(start_next_request));
+
+ return;
+ }
+
if (!IsActive(registration_id)) {
- // Stop giving out requests as registration aborted (or otherwise finished).
+ // Stop giving out requests as registration was aborted (or otherwise
+ // finished).
std::move(callback).Run(nullptr /* request */);
return;
}
@@ -361,12 +378,37 @@ void BackgroundFetchDataManager::PopNextRequest(
std::move(callback).Run(std::move(next_request));
}
+void BackgroundFetchDataManager::AddStartNextPendingRequestTask(
+ int64_t service_worker_registration_id,
+ NextRequestCallback callback,
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata) {
+ if (!metadata) {
+ // Stop giving out requests as registration aborted (or otherwise finished).
+ std::move(callback).Run(nullptr /* request */);
+ return;
+ }
+ DCHECK_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+
+ AddDatabaseTask(
+ std::make_unique<background_fetch::StartNextPendingRequestTask>(
+ this, service_worker_registration_id, std::move(metadata),
+ std::move(callback)));
+}
+
void BackgroundFetchDataManager::MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
BackgroundFetchRequestInfo* request,
BackgroundFetchScheduler::MarkedCompleteCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBackgroundFetchPersistence)) {
+ AddDatabaseTask(std::make_unique<background_fetch::MarkRequestCompleteTask>(
+ this, registration_id, request, std::move(callback)));
+ return;
+ }
+
auto iter = registrations_.find(registration_id.unique_id());
DCHECK(iter != registrations_.end());
@@ -381,6 +423,13 @@ void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
SettledFetchesCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBackgroundFetchPersistence)) {
+ AddDatabaseTask(std::make_unique<background_fetch::GetSettledFetchesTask>(
+ this, registration_id, std::move(callback)));
+ return;
+ }
+
auto iter = registrations_.find(registration_id.unique_id());
DCHECK(iter != registrations_.end());
@@ -404,58 +453,10 @@ void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
// The |filter| decides which values can be passed on to the Service Worker.
BackgroundFetchCrossOriginFilter filter(registration_id.origin(), *request);
- settled_fetch.response.url_list = request->GetURLChain();
- settled_fetch.response.response_type =
- network::mojom::FetchResponseType::kDefault;
-
- // Include the status code, status text and the response's body as a blob
- // when this is allowed by the CORS protocol.
- if (filter.CanPopulateBody()) {
- settled_fetch.response.status_code = request->GetResponseCode();
- settled_fetch.response.status_text = request->GetResponseText();
- settled_fetch.response.headers.insert(
- request->GetResponseHeaders().begin(),
- request->GetResponseHeaders().end());
-
- if (request->GetFileSize() > 0) {
- DCHECK(!request->GetFilePath().empty());
- DCHECK(blob_storage_context_);
-
- auto blob_builder =
- std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID());
- blob_builder->AppendFile(request->GetFilePath(), 0 /* offset */,
- request->GetFileSize(),
- base::Time() /* expected_modification_time */);
-
- auto blob_data_handle =
- GetBlobStorageContext(blob_storage_context_.get())
- ->AddFinishedBlob(std::move(blob_builder));
-
- // TODO(peter): Appropriately handle !blob_data_handle
- if (blob_data_handle) {
- settled_fetch.response.blob_uuid = blob_data_handle->uuid();
- settled_fetch.response.blob_size = blob_data_handle->size();
- blink::mojom::BlobPtr blob_ptr;
- storage::BlobImpl::Create(
- std::make_unique<storage::BlobDataHandle>(*blob_data_handle),
- MakeRequest(&blob_ptr));
-
- settled_fetch.response.blob =
- base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
- blob_data_handles.push_back(std::move(blob_data_handle));
- }
- }
- } else {
- // TODO(crbug.com/711354): Consider Background Fetches as failed when the
- // response cannot be relayed to the developer.
- background_fetch_succeeded = false;
- }
-
- // TODO(delphick): settled_fetch.response.error
- settled_fetch.response.response_time = request->GetResponseTime();
- // TODO(delphick): settled_fetch.response.cors_exposed_header_names
-
- background_fetch_succeeded = background_fetch_succeeded && IsOK(*request);
+ background_fetch_succeeded =
+ FillServiceWorkerResponse(*request, registration_id.origin(),
+ &settled_fetch.response) &&
+ background_fetch_succeeded;
settled_fetches.push_back(settled_fetch);
}
@@ -465,6 +466,62 @@ void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
std::move(settled_fetches), std::move(blob_data_handles));
}
+bool BackgroundFetchDataManager::FillServiceWorkerResponse(
+ const BackgroundFetchRequestInfo& request,
+ const url::Origin& origin,
+ ServiceWorkerResponse* response) {
+ DCHECK(response);
+
+ response->url_list = request.GetURLChain();
+ response->response_type = network::mojom::FetchResponseType::kDefault;
+ // TODO(crbug.com/838837): settled_fetch.response.error
+ response->response_time = request.GetResponseTime();
+ // TODO(crbug.com/838837): settled_fetch.response.cors_exposed_header_names
+
+ BackgroundFetchCrossOriginFilter filter(origin, request);
+ if (!filter.CanPopulateBody()) {
+ // TODO(crbug.com/711354): Consider Background Fetches as failed when the
+ // response cannot be relayed to the developer.
+ return false;
+ }
+
+ // Include the status code, status text and the response's body as a blob
+ // when this is allowed by the CORS protocol.
+ response->status_code = request.GetResponseCode();
+ response->status_text = request.GetResponseText();
+ response->headers.insert(request.GetResponseHeaders().begin(),
+ request.GetResponseHeaders().end());
+
+ if (request.GetFileSize() > 0) {
+ DCHECK(!request.GetFilePath().empty());
+ DCHECK(blob_storage_context_);
+
+ auto blob_builder =
+ std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID());
+ blob_builder->AppendFile(request.GetFilePath(), 0 /* offset */,
+ request.GetFileSize(),
+ base::Time() /* expected_modification_time */);
+
+ auto blob_data_handle = GetBlobStorageContext(blob_storage_context_.get())
+ ->AddFinishedBlob(std::move(blob_builder));
+
+ // TODO(peter): Appropriately handle !blob_data_handle
+ if (blob_data_handle) {
+ response->blob_uuid = blob_data_handle->uuid();
+ response->blob_size = blob_data_handle->size();
+ blink::mojom::BlobPtr blob_ptr;
+ storage::BlobImpl::Create(
+ std::make_unique<storage::BlobDataHandle>(*blob_data_handle),
+ MakeRequest(&blob_ptr));
+
+ response->blob =
+ base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ }
+ }
+
+ return IsOK(request);
+}
+
void BackgroundFetchDataManager::MarkRegistrationForDeletion(
const BackgroundFetchRegistrationId& registration_id,
HandleBackgroundFetchErrorCallback callback) {
@@ -545,10 +602,21 @@ void BackgroundFetchDataManager::GetDeveloperIdsForServiceWorker(
developer_ids);
}
-int BackgroundFetchDataManager::GetTotalNumberOfRequests(
- const BackgroundFetchRegistrationId& registration_id) const {
- return registrations_.find(registration_id.unique_id())
- ->second->GetTotalNumberOfRequests();
+void BackgroundFetchDataManager::GetNumCompletedRequests(
+ const BackgroundFetchRegistrationId& registration_id,
+ NumRequestsCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBackgroundFetchPersistence)) {
+ AddDatabaseTask(std::make_unique<background_fetch::GetNumRequestsTask>(
+ this, registration_id, background_fetch::RequestType::kCompleted,
+ std::move(callback)));
+ return;
+ }
+
+ std::move(callback).Run(registrations_.find(registration_id.unique_id())
+ ->second->GetNumCompletedRequests());
}
bool BackgroundFetchDataManager::IsActive(
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager.h b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
index 3d61469caad..6b70bbf5715 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager.h
@@ -63,6 +63,7 @@ class CONTENT_EXPORT BackgroundFetchDataManager
std::unique_ptr<BackgroundFetchRegistration>)>;
using NextRequestCallback =
base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
+ using NumRequestsCallback = base::OnceCallback<void(size_t)>;
BackgroundFetchDataManager(
BrowserContext* browser_context,
@@ -133,17 +134,27 @@ class CONTENT_EXPORT BackgroundFetchDataManager
const url::Origin& origin,
blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback);
- int GetTotalNumberOfRequests(
- const BackgroundFetchRegistrationId& registration_id) const;
+ // Gets the number of fetch requests that have been completed for a given
+ // registration.
+ void GetNumCompletedRequests(
+ const BackgroundFetchRegistrationId& registration_id,
+ NumRequestsCallback callback);
// BackgroundFetchScheduler::RequestProvider implementation:
void PopNextRequest(const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback) override;
+
void MarkRequestAsComplete(
const BackgroundFetchRegistrationId& registration_id,
BackgroundFetchRequestInfo* request,
BackgroundFetchScheduler::MarkedCompleteCallback callback) override;
+ // TODO(rayankans): Move this function to MarkRequestCompleteTask after
+ // non-persistent background fetch support is removed.
+ bool FillServiceWorkerResponse(const BackgroundFetchRequestInfo& request,
+ const url::Origin& origin,
+ ServiceWorkerResponse* response);
+
private:
FRIEND_TEST_ALL_PREFIXES(BackgroundFetchDataManagerTest, Cleanup);
friend class BackgroundFetchDataManagerTest;
@@ -151,6 +162,12 @@ class CONTENT_EXPORT BackgroundFetchDataManager
class RegistrationData;
+ void AddStartNextPendingRequestTask(
+ int64_t service_worker_registration_id,
+ NextRequestCallback callback,
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata);
+
void AddDatabaseTask(std::unique_ptr<background_fetch::DatabaseTask> task);
void OnDatabaseTaskFinished(background_fetch::DatabaseTask* task);
diff --git a/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
index 509c5bb5de3..8a1cd9a985e 100644
--- a/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -18,9 +18,12 @@
#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/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/get_num_requests_task.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
+#include "storage/browser/blob/blob_data_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace content {
@@ -41,13 +44,6 @@ const char kAlternativeUniqueId[] = "bb48a9fb-c21f-4c2d-a9ae-58bd48a9fb53";
const char kInitialTitle[] = "Initial Title";
const char kUpdatedTitle[] = "Updated Title";
-// See schema documentation in background_fetch_data_manager.cc.
-// A "bgfetch_registration_" per registration (not including keys for requests).
-constexpr size_t kUserDataKeysPerInactiveRegistration = 1u;
-
-// A "bgfetch_request_" per request.
-constexpr size_t kUserDataKeysPerInactiveRequest = 1u;
-
void DidCreateRegistration(
base::Closure quit_closure,
blink::mojom::BackgroundFetchError* out_error,
@@ -74,6 +70,37 @@ void DidGetRegistrationUserDataByKeyPrefix(base::Closure quit_closure,
std::move(quit_closure).Run();
}
+void AnnotateRequestInfoWithFakeDownloadManagerData(
+ BackgroundFetchRequestInfo* request_info) {
+ // Fill |request_info| with a failed result.
+ request_info->SetResult(std::make_unique<BackgroundFetchResult>(
+ base::Time::Now(), BackgroundFetchResult::FailureReason::UNKNOWN));
+ request_info->PopulateWithResponse(
+ std::make_unique<BackgroundFetchResponse>(std::vector<GURL>(1), nullptr));
+}
+
+void GetNumUserData(base::Closure quit_closure,
+ int* out_size,
+ const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status) {
+ DCHECK(out_size);
+ DCHECK_EQ(SERVICE_WORKER_OK, status);
+ *out_size = data.size();
+ std::move(quit_closure).Run();
+}
+
+struct ResponseStateStats {
+ int pending_requests = 0;
+ int active_requests = 0;
+ int completed_requests = 0;
+};
+
+bool operator==(const ResponseStateStats& s1, const ResponseStateStats& s2) {
+ return s1.pending_requests == s2.pending_requests &&
+ s1.active_requests == s2.active_requests &&
+ s1.completed_requests == s2.completed_requests;
+}
+
} // namespace
class BackgroundFetchDataManagerTest
@@ -196,6 +223,22 @@ class BackgroundFetchDataManagerTest
}
// Synchronous version of
+ // BackgroundFetchDataManager::PopNextRequest().
+ void PopNextRequest(
+ const BackgroundFetchRegistrationId& registration_id,
+ scoped_refptr<BackgroundFetchRequestInfo>* out_request_info) {
+ DCHECK(out_request_info);
+
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->PopNextRequest(
+ registration_id,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidPopNextRequest,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_request_info));
+ run_loop.Run();
+ }
+
+ // Synchronous version of
// BackgroundFetchDataManager::MarkRegistrationForDeletion().
void MarkRegistrationForDeletion(
const BackgroundFetchRegistrationId& registration_id,
@@ -221,6 +264,72 @@ class BackgroundFetchDataManagerTest
run_loop.Run();
}
+ // Synchronous version of BackgroundFetchDataManager::MarkRequestAsComplete().
+ void MarkRequestAsComplete(
+ const BackgroundFetchRegistrationId& registration_id,
+ BackgroundFetchRequestInfo* request_info) {
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->MarkRequestAsComplete(
+ registration_id, request_info,
+ base::BindOnce(
+ &BackgroundFetchDataManagerTest::DidMarkRequestAsComplete,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
+ // Synchronous version of
+ // BackgroundFetchDataManager::GetSettledFetchesForRegistration().
+ void GetSettledFetchesForRegistration(
+ const BackgroundFetchRegistrationId& registration_id,
+ blink::mojom::BackgroundFetchError* out_error,
+ bool* out_succeeded,
+ std::vector<BackgroundFetchSettledFetch>* out_settled_fetches) {
+ DCHECK(out_error);
+ DCHECK(out_succeeded);
+ DCHECK(out_settled_fetches);
+
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->GetSettledFetchesForRegistration(
+ registration_id,
+ base::BindOnce(&BackgroundFetchDataManagerTest::
+ DidGetSettledFetchesForRegistration,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_error, out_succeeded, out_settled_fetches));
+ run_loop.Run();
+ }
+
+ // Synchronous version of
+ // BackgroundFetchDataManager::GetNumCompletedRequests().
+ void GetNumCompletedRequests(
+ const BackgroundFetchRegistrationId& registration_id,
+ size_t* out_size) {
+ DCHECK(out_size);
+
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->GetNumCompletedRequests(
+ registration_id,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidGetNumRequests,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_size));
+ run_loop.Run();
+ }
+
+ // Synchronous version of GetNumRequestsTask::Start().
+ void GetNumRequestsTask(const BackgroundFetchRegistrationId& registration_id,
+ background_fetch::RequestType type,
+ size_t* out_size) {
+ DCHECK(out_size);
+
+ base::RunLoop run_loop;
+ background_fetch_data_manager_->AddDatabaseTask(
+ std::make_unique<background_fetch::GetNumRequestsTask>(
+ background_fetch_data_manager_.get(), registration_id, type,
+ base::BindOnce(&BackgroundFetchDataManagerTest::DidGetNumRequests,
+ base::Unretained(this), run_loop.QuitClosure(),
+ out_size)));
+ run_loop.Run();
+ }
+
// Synchronous version of
// ServiceWorkerContextWrapper::GetRegistrationUserDataByKeyPrefix.
std::vector<std::string> GetRegistrationUserDataByKeyPrefix(
@@ -240,6 +349,45 @@ class BackgroundFetchDataManagerTest
return data;
}
+ // Gets information about the number of background fetch requests by state.
+ ResponseStateStats GetRequestStats(int64_t service_worker_registration_id) {
+ ResponseStateStats stats;
+ {
+ base::RunLoop run_loop;
+ embedded_worker_test_helper()
+ ->context_wrapper()
+ ->GetRegistrationUserDataByKeyPrefix(
+ service_worker_registration_id,
+ background_fetch::kPendingRequestKeyPrefix,
+ base::BindOnce(&GetNumUserData, run_loop.QuitClosure(),
+ &stats.pending_requests));
+ run_loop.Run();
+ }
+ {
+ base::RunLoop run_loop;
+ embedded_worker_test_helper()
+ ->context_wrapper()
+ ->GetRegistrationUserDataByKeyPrefix(
+ service_worker_registration_id,
+ background_fetch::kActiveRequestKeyPrefix,
+ base::BindOnce(&GetNumUserData, run_loop.QuitClosure(),
+ &stats.active_requests));
+ run_loop.Run();
+ }
+ {
+ base::RunLoop run_loop;
+ embedded_worker_test_helper()
+ ->context_wrapper()
+ ->GetRegistrationUserDataByKeyPrefix(
+ service_worker_registration_id,
+ background_fetch::kCompletedRequestKeyPrefix,
+ base::BindOnce(&GetNumUserData, run_loop.QuitClosure(),
+ &stats.completed_requests));
+ run_loop.Run();
+ }
+ return stats;
+ }
+
protected:
void DidGetRegistration(
base::Closure quit_closure,
@@ -289,6 +437,41 @@ class BackgroundFetchDataManagerTest
std::move(quit_closure).Run();
}
+ void DidPopNextRequest(
+ base::OnceClosure quit_closure,
+ scoped_refptr<BackgroundFetchRequestInfo>* out_request_info,
+ scoped_refptr<BackgroundFetchRequestInfo> request_info) {
+ *out_request_info = request_info;
+ std::move(quit_closure).Run();
+ }
+
+ void DidMarkRequestAsComplete(base::OnceClosure quit_closure) {
+ std::move(quit_closure).Run();
+ }
+
+ void DidGetSettledFetchesForRegistration(
+ base::OnceClosure quit_closure,
+ blink::mojom::BackgroundFetchError* out_error,
+ bool* out_succeeded,
+ std::vector<BackgroundFetchSettledFetch>* out_settled_fetches,
+ blink::mojom::BackgroundFetchError error,
+ bool succeeded,
+ std::vector<BackgroundFetchSettledFetch> settled_fetches,
+ std::vector<std::unique_ptr<storage::BlobDataHandle>>) {
+ *out_error = error;
+ *out_succeeded = succeeded;
+ *out_settled_fetches = std::move(settled_fetches);
+
+ std::move(quit_closure).Run();
+ }
+
+ void DidGetNumRequests(base::OnceClosure quit_closure,
+ size_t* out_size,
+ size_t size) {
+ *out_size = size;
+ std::move(quit_closure).Run();
+ }
+
BackgroundFetchRegistrationStorage registration_storage_;
std::unique_ptr<BackgroundFetchDataManager> background_fetch_data_manager_;
};
@@ -471,6 +654,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetMetadata) {
ASSERT_TRUE(metadata);
EXPECT_EQ(metadata->origin(), origin().Serialize());
EXPECT_NE(metadata->creation_microseconds_since_unix_epoch(), 0);
+ EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
// Verify that retrieving using the wrong developer id doesn't work.
metadata = GetMetadata(sw_id, origin(), kAlternativeDeveloperId, &error);
@@ -485,6 +669,7 @@ TEST_P(BackgroundFetchDataManagerTest, GetMetadata) {
ASSERT_TRUE(metadata);
EXPECT_EQ(metadata->origin(), origin().Serialize());
EXPECT_NE(metadata->creation_microseconds_since_unix_epoch(), 0);
+ EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
}
TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
@@ -504,15 +689,20 @@ TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
options.title = kInitialTitle;
blink::mojom::BackgroundFetchError error;
+ // There should be no title before the registration.
+ std::vector<std::string> title = GetRegistrationUserDataByKeyPrefix(
+ sw_id, background_fetch::kTitleKeyPrefix);
+ EXPECT_TRUE(title.empty());
+
// Create a single registration.
CreateRegistration(registration_id, requests, options, &error);
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
// Verify that the title can be retrieved.
- auto metadata = GetMetadata(sw_id, origin(), kExampleDeveloperId, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_TRUE(metadata);
- EXPECT_EQ(metadata->ui_title(), kInitialTitle);
+ title = GetRegistrationUserDataByKeyPrefix(sw_id,
+ background_fetch::kTitleKeyPrefix);
+ EXPECT_EQ(title.size(), 1u);
+ ASSERT_EQ(title.front(), kInitialTitle);
// Update the title.
UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
@@ -520,10 +710,10 @@ TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
RestartDataManagerFromPersistentStorage();
// After a restart, GetMetadata should find the new title.
- metadata = GetMetadata(sw_id, origin(), kExampleDeveloperId, &error);
- ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
- ASSERT_TRUE(metadata);
- EXPECT_EQ(metadata->ui_title(), kUpdatedTitle);
+ title = GetRegistrationUserDataByKeyPrefix(sw_id,
+ background_fetch::kTitleKeyPrefix);
+ EXPECT_EQ(title.size(), 1u);
+ ASSERT_EQ(title.front(), kUpdatedTitle);
}
TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
@@ -592,6 +782,254 @@ TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
}
+TEST_P(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
+ // This test only applies to persistent storage.
+ if (registration_storage_ ==
+ BackgroundFetchRegistrationStorage::kNonPersistent)
+ return;
+
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ // There registration hasn't been created yet, so there are no pending
+ // requests.
+ PopNextRequest(registration_id, &request_info);
+ EXPECT_FALSE(request_info);
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
+ 0 /* completed_requests */}));
+
+ std::vector<ServiceWorkerFetchRequest> requests(2u);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+
+ CreateRegistration(registration_id, requests, options, &error);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{2 /* pending_requests */, 0 /* active_requests */,
+ 0 /* completed_requests */}));
+
+ // Popping should work now.
+ PopNextRequest(registration_id, &request_info);
+ EXPECT_TRUE(request_info);
+ EXPECT_EQ(request_info->request_index(), 0);
+ EXPECT_FALSE(request_info->download_guid().empty());
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{1 /* pending_requests */, 1 /* active_requests */,
+ 0 /* completed_requests */}));
+
+ // Mark as complete.
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+ ASSERT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{1 /* pending_requests */, 0 /* active_requests */,
+ 1 /* completed_requests */}));
+
+ RestartDataManagerFromPersistentStorage();
+
+ PopNextRequest(registration_id, &request_info);
+ EXPECT_TRUE(request_info);
+ EXPECT_EQ(request_info->request_index(), 1);
+ EXPECT_FALSE(request_info->download_guid().empty());
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{0 /* pending_requests */, 1 /* active_requests */,
+ 1 /* completed_requests */}));
+
+ // Mark as complete.
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+ ASSERT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
+ 2 /* completed_requests */}));
+
+ // We are out of pending requests.
+ PopNextRequest(registration_id, &request_info);
+ EXPECT_FALSE(request_info);
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
+ 2 /* completed_requests */}));
+}
+
+TEST_P(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
+ // This test only applies to persistent storage.
+ if (registration_storage_ ==
+ BackgroundFetchRegistrationStorage::kNonPersistent)
+ return;
+
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ std::vector<ServiceWorkerFetchRequest> requests(2u);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ CreateRegistration(registration_id, requests, options, &error);
+ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{2 /* pending_requests */, 0 /* active_requests */,
+ 0 /* completed_requests */}));
+
+ // Nothing is downloaded yet.
+ bool succeeded = false;
+ std::vector<BackgroundFetchSettledFetch> settled_fetches;
+ GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
+ &settled_fetches);
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ EXPECT_TRUE(succeeded);
+ EXPECT_EQ(settled_fetches.size(), 0u);
+
+ for (size_t i = 0; i < requests.size(); i++) {
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+ }
+
+ RestartDataManagerFromPersistentStorage();
+
+ EXPECT_EQ(
+ GetRequestStats(sw_id),
+ (ResponseStateStats{0 /* pending_requests */, 0 /* active_requests */,
+ requests.size() /* completed_requests */}));
+
+ GetSettledFetchesForRegistration(registration_id, &error, &succeeded,
+ &settled_fetches);
+
+ EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ // We are marking the responses as failed in Download Manager.
+ EXPECT_FALSE(succeeded);
+ EXPECT_EQ(settled_fetches.size(), requests.size());
+}
+
+TEST_P(BackgroundFetchDataManagerTest, GetNumCompletedRequests) {
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+
+ // The requests are default-initialized, but valid.
+ std::vector<ServiceWorkerFetchRequest> requests(2u);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+
+ CreateRegistration(registration_id, requests, options, &error);
+
+ size_t num_completed = 0u;
+
+ GetNumCompletedRequests(registration_id, &num_completed);
+ EXPECT_EQ(num_completed, 0u);
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ // Download and store first request.
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ GetNumCompletedRequests(registration_id, &num_completed);
+ EXPECT_EQ(num_completed, 1u);
+
+ RestartDataManagerFromPersistentStorage();
+
+ GetNumCompletedRequests(registration_id, &num_completed);
+ EXPECT_EQ(num_completed, 1u);
+
+ // Download and store second request.
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ GetNumCompletedRequests(registration_id, &num_completed);
+ EXPECT_EQ(num_completed, 2u);
+}
+
+TEST_P(BackgroundFetchDataManagerTest, GetNumRequestsTask) {
+ // This test only applies to persistent storage.
+ if (registration_storage_ ==
+ BackgroundFetchRegistrationStorage::kNonPersistent)
+ return;
+
+ int64_t sw_id = RegisterServiceWorker();
+ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
+
+ BackgroundFetchRegistrationId registration_id(
+ sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+ BackgroundFetchOptions options;
+ blink::mojom::BackgroundFetchError error;
+
+ CreateRegistration(registration_id, {ServiceWorkerFetchRequest()}, options,
+ &error);
+
+ size_t size = 0u;
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kAny,
+ &size);
+ EXPECT_EQ(size, 1u); // Total requests is 1.
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kPending,
+ &size);
+ EXPECT_EQ(size, 1u); // Total pending requests is 1.
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kActive,
+ &size);
+ EXPECT_EQ(size, 0u); // No active requests.
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
+ &size);
+ EXPECT_EQ(size, 0u); // No complete requests.
+
+ scoped_refptr<BackgroundFetchRequestInfo> request_info;
+ // Download and store first request.
+ PopNextRequest(registration_id, &request_info);
+ ASSERT_TRUE(request_info);
+
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kAny,
+ &size);
+ EXPECT_EQ(size, 1u); // Total requests is 1.
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kPending,
+ &size);
+ EXPECT_EQ(size, 0u); // Pending requests moved to active.
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kActive,
+ &size);
+ EXPECT_EQ(size, 1u); // Request is active.
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
+ &size);
+ EXPECT_EQ(size, 0u); // No complete requests.
+
+ AnnotateRequestInfoWithFakeDownloadManagerData(request_info.get());
+ MarkRequestAsComplete(registration_id, request_info.get());
+
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kActive,
+ &size);
+ EXPECT_EQ(size, 0u); // No active requests.
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
+ &size);
+ EXPECT_EQ(size, 1u); // Request is complete.
+
+ RestartDataManagerFromPersistentStorage();
+
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kCompleted,
+ &size);
+ EXPECT_EQ(size, 1u);
+ GetNumRequestsTask(registration_id, background_fetch::RequestType::kAny,
+ &size);
+ EXPECT_EQ(size, 1u); // Total requests is still 1.
+}
+
TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
// Tests that the BackgroundFetchDataManager cleans up registrations
// marked for deletion.
@@ -605,14 +1043,11 @@ TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
BackgroundFetchRegistrationId registration_id(
sw_id, origin(), kExampleDeveloperId, kExampleUniqueId);
+ // The requests are default-initialized, but valid.
std::vector<ServiceWorkerFetchRequest> requests(2u);
BackgroundFetchOptions options;
blink::mojom::BackgroundFetchError error;
- size_t expected_inactive_data_count =
- kUserDataKeysPerInactiveRegistration +
- requests.size() * kUserDataKeysPerInactiveRequest;
-
if (registration_storage_ ==
BackgroundFetchRegistrationStorage::kPersistent) {
EXPECT_EQ(
@@ -623,6 +1058,15 @@ TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
CreateRegistration(registration_id, requests, options, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+ if (registration_storage_ ==
+ BackgroundFetchRegistrationStorage::kPersistent) {
+ // We expect as many pending entries as there are requests.
+ EXPECT_EQ(requests.size(),
+ GetRegistrationUserDataByKeyPrefix(
+ sw_id, background_fetch::kPendingRequestKeyPrefix)
+ .size());
+ }
+
// And deactivate it.
MarkRegistrationForDeletion(registration_id, &error);
ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
@@ -631,8 +1075,13 @@ TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
if (registration_storage_ ==
BackgroundFetchRegistrationStorage::kPersistent) {
+ // Pending Requests should be deleted after marking a registration for
+ // deletion.
+ EXPECT_EQ(0u, GetRegistrationUserDataByKeyPrefix(
+ sw_id, background_fetch::kPendingRequestKeyPrefix)
+ .size());
EXPECT_EQ(
- expected_inactive_data_count,
+ 2u, // Metadata proto + title.
GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
index cec58a9ba29..99679a6d0f1 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -9,6 +9,7 @@
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_url_parameters.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
+#include "content/public/browser/background_fetch_description.h"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/download_manager.h"
#include "ui/gfx/geometry/size.h"
@@ -63,19 +64,12 @@ class BackgroundFetchDelegateProxy::Core
}
}
- void CreateDownloadJob(const std::string& job_unique_id,
- const std::string& title,
- const url::Origin& origin,
- const SkBitmap& icon,
- int completed_parts,
- int total_parts,
- const std::vector<std::string>& current_guids) {
+ void CreateDownloadJob(
+ std::unique_ptr<BackgroundFetchDescription> fetch_description) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (delegate_) {
- delegate_->CreateDownloadJob(job_unique_id, title, origin, icon,
- completed_parts, total_parts, current_guids);
- }
+ if (delegate_)
+ delegate_->CreateDownloadJob(std::move(fetch_description));
}
void StartRequest(const std::string& job_unique_id,
@@ -150,7 +144,8 @@ class BackgroundFetchDelegateProxy::Core
}
// BackgroundFetchDelegate::Client implementation:
- void OnJobCancelled(const std::string& job_unique_id) override;
+ void OnJobCancelled(const std::string& job_unique_id,
+ BackgroundFetchReasonToAbort reason_to_abort) override;
void OnDownloadUpdated(const std::string& job_unique_id,
const std::string& guid,
uint64_t bytes_downloaded) override;
@@ -178,12 +173,13 @@ class BackgroundFetchDelegateProxy::Core
};
void BackgroundFetchDelegateProxy::Core::OnJobCancelled(
- const std::string& job_unique_id) {
+ const std::string& job_unique_id,
+ BackgroundFetchReasonToAbort reason_to_abort) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&BackgroundFetchDelegateProxy::OnJobCancelled, io_parent_,
- job_unique_id));
+ job_unique_id, reason_to_abort));
}
void BackgroundFetchDelegateProxy::Core::OnDownloadUpdated(
@@ -261,24 +257,17 @@ void BackgroundFetchDelegateProxy::GetIconDisplaySize(
}
void BackgroundFetchDelegateProxy::CreateDownloadJob(
- const std::string& job_unique_id,
- const std::string& title,
- const url::Origin& origin,
- const SkBitmap& icon,
base::WeakPtr<Controller> controller,
- int completed_parts,
- int total_parts,
- const std::vector<std::string>& current_guids) {
+ std::unique_ptr<BackgroundFetchDescription> fetch_description) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!job_details_map_.count(job_unique_id));
- job_details_map_.emplace(job_unique_id, JobDetails(controller));
+ DCHECK(!job_details_map_.count(fetch_description->job_unique_id));
+ job_details_map_.emplace(fetch_description->job_unique_id,
+ JobDetails(controller));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Core::CreateDownloadJob, ui_core_ptr_, job_unique_id,
- title, origin, icon, completed_parts, total_parts,
- current_guids));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&Core::CreateDownloadJob, ui_core_ptr_,
+ std::move(fetch_description)));
}
void BackgroundFetchDelegateProxy::StartRequest(
@@ -319,8 +308,12 @@ void BackgroundFetchDelegateProxy::Abort(const std::string& job_unique_id) {
}
void BackgroundFetchDelegateProxy::OnJobCancelled(
- const std::string& job_unique_id) {
+ const std::string& job_unique_id,
+ BackgroundFetchReasonToAbort reason_to_abort) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(reason_to_abort == BackgroundFetchReasonToAbort::CANCELLED_FROM_UI ||
+ reason_to_abort ==
+ BackgroundFetchReasonToAbort::TOTAL_DOWNLOAD_SIZE_EXCEEDED);
// TODO(delphick): The controller may not exist as persistence is not yet
// implemented.
@@ -330,7 +323,7 @@ void BackgroundFetchDelegateProxy::OnJobCancelled(
JobDetails& job_details = job_details_iter->second;
if (job_details.controller)
- job_details.controller->AbortFromUser();
+ job_details.controller->Abort(reason_to_abort);
}
void BackgroundFetchDelegateProxy::DidStartRequest(
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
index 3b905d3631d..744278a5d18 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -16,11 +16,10 @@
#include "base/memory/weak_ptr.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/public/browser/background_fetch_delegate.h"
+#include "content/public/browser/background_fetch_description.h"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
-class SkBitmap;
-
namespace content {
// Proxy class for passing messages between BackgroundFetchJobControllers on the
@@ -45,8 +44,8 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
virtual void DidCompleteRequest(
const scoped_refptr<BackgroundFetchRequestInfo>& request) = 0;
- // Called when the user aborts a Background Fetch registration.
- virtual void AbortFromUser() = 0;
+ // Called when the delegate aborts a Background Fetch registration.
+ virtual void Abort(BackgroundFetchReasonToAbort) = 0;
virtual ~Controller() {}
};
@@ -59,22 +58,19 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
void GetIconDisplaySize(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback);
- // Creates a new download grouping identified by |job_unique_id|. Further
- // downloads started by StartRequest will also use this |job_unique_id| so
- // that a notification can be updated with the current status. If the download
- // was already started in a previous browser session, then |current_guids|
- // should contain the GUIDs of in progress downloads, while completed
- // downloads are recorded in |completed_parts|.
- // Should only be called from the Controller (on the IO
- // thread).
- void CreateDownloadJob(const std::string& job_unique_id,
- const std::string& title,
- const url::Origin& origin,
- const SkBitmap& icon,
- base::WeakPtr<Controller> controller,
- int completed_parts,
- int total_parts,
- const std::vector<std::string>& current_guids);
+ // Creates a new download grouping described by |fetch_description|. Further
+ // downloads started by StartRequest will also use
+ // |fetch_description.job_unique_id| so that a notification can be updated
+ // with the current status. If the download was already started in a previous
+ // browser session, then |fetch_description.current_guids| should contain the
+ // GUIDs of in progress downloads, while completed downloads are recorded in
+ // |fetch_description.completed_parts|. The size of the completed parts is
+ // recorded in |fetch_description.completed_parts_size| and total download
+ // size is stored in |fetch_description.total_parts_size|. Should only be
+ // called from the Controller (on the IO thread).
+ void CreateDownloadJob(
+ base::WeakPtr<Controller> controller,
+ std::unique_ptr<BackgroundFetchDescription> fetch_description);
// Requests that the download manager start fetching |request|.
// Should only be called from the Controller (on the IO
@@ -88,8 +84,8 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
void UpdateUI(const std::string& job_unique_id, const std::string& title);
// Aborts in progress downloads for the given registration. Called from the
- // Controller (on the IO thread) after it is aborted, either by the user or
- // website. May occur even if all requests already called OnDownloadComplete.
+ // Controller (on the IO thread) after it is aborted. May occur even if all
+ // requests already called OnDownloadComplete.
void Abort(const std::string& job_unique_id);
private:
@@ -97,7 +93,8 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
// Called when the job identified by |job_unique|id| was cancelled by the
// delegate. Should only be called on the IO thread.
- void OnJobCancelled(const std::string& job_unique_id);
+ void OnJobCancelled(const std::string& job_unique_id,
+ BackgroundFetchReasonToAbort reason_to_abort);
// Called when the download identified by |guid| has succeeded/failed/aborted.
// Should only be called on the IO thread.
diff --git a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
index 9091e65d5c5..788e87a46a8 100644
--- a/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -11,6 +11,7 @@
#include "base/run_loop.h"
#include "content/browser/background_fetch/background_fetch_test_base.h"
#include "content/public/browser/background_fetch_delegate.h"
+#include "content/public/browser/background_fetch_description.h"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,13 +34,7 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
std::move(callback).Run(gfx::Size(kIconDisplaySize, kIconDisplaySize));
}
void CreateDownloadJob(
- const std::string& job_unique_id,
- const std::string& title,
- const url::Origin& origin,
- const SkBitmap& icon,
- int completed_parts,
- int total_parts,
- const std::vector<std::string>& current_guids) override {}
+ std::unique_ptr<BackgroundFetchDescription> fetch_description) override {}
void DownloadUrl(const std::string& job_unique_id,
const std::string& guid,
const std::string& method,
@@ -108,7 +103,7 @@ class FakeController : public BackgroundFetchDelegateProxy::Controller {
request_completed_ = true;
}
- void AbortFromUser() override {}
+ void Abort(BackgroundFetchReasonToAbort reason_to_abort) override {}
bool request_started_ = false;
bool request_completed_ = false;
@@ -154,9 +149,13 @@ TEST_F(BackgroundFetchDelegateProxyTest, StartRequest) {
EXPECT_FALSE(controller.request_started_);
EXPECT_FALSE(controller.request_completed_);
- delegate_proxy_.CreateDownloadJob(
+ auto fetch_description = std::make_unique<BackgroundFetchDescription>(
kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(),
- controller.weak_ptr_factory_.GetWeakPtr(), 0, 1, {});
+ 0 /* completed_parts */, 1 /* total_parts */,
+ 0 /* completed_parts_size */, 0 /* total_parts_size */,
+ std::vector<std::string>());
+ delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
+ std::move(fetch_description));
delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
base::RunLoop().RunUntilIdle();
@@ -174,9 +173,13 @@ TEST_F(BackgroundFetchDelegateProxyTest, StartRequest_NotCompleted) {
EXPECT_FALSE(controller.request_completed_);
delegate_.set_complete_downloads(false);
- delegate_proxy_.CreateDownloadJob(
+ auto fetch_description = std::make_unique<BackgroundFetchDescription>(
kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(),
- controller.weak_ptr_factory_.GetWeakPtr(), 0, 1, {});
+ 0 /* completed_parts */, 1 /* total_parts */,
+ 0 /* completed_parts_size */, 0 /* total_parts_size */,
+ std::vector<std::string>());
+ delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
+ std::move(fetch_description));
delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
base::RunLoop().RunUntilIdle();
@@ -198,13 +201,21 @@ TEST_F(BackgroundFetchDelegateProxyTest, Abort) {
EXPECT_FALSE(controller2.request_started_);
EXPECT_FALSE(controller2.request_completed_);
- delegate_proxy_.CreateDownloadJob(
+ auto fetch_description1 = std::make_unique<BackgroundFetchDescription>(
kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(),
- controller.weak_ptr_factory_.GetWeakPtr(), 0, 1, {});
+ 0 /* completed_parts */, 1 /* total_parts */,
+ 0 /* completed_parts_size */, 0 /* total_parts_size */,
+ std::vector<std::string>());
+ delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
+ std::move(fetch_description1));
- delegate_proxy_.CreateDownloadJob(
+ auto fetch_description2 = std::make_unique<BackgroundFetchDescription>(
kExampleUniqueId2, "Job 2", url::Origin(), SkBitmap(),
- controller2.weak_ptr_factory_.GetWeakPtr(), 0, 1, {});
+ 0 /* completed_parts */, 1 /* total_parts */,
+ 0 /* completed_parts_size */, 0 /* total_parts_size */,
+ std::vector<std::string>());
+ delegate_proxy_.CreateDownloadJob(controller2.weak_ptr_factory_.GetWeakPtr(),
+ std::move(fetch_description2));
delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
delegate_proxy_.StartRequest(kExampleUniqueId2, url::Origin(), request2);
diff --git a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
index dc606892ca4..4f7182d5511 100644
--- a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.cc
@@ -21,9 +21,13 @@ BackgroundFetchEmbeddedWorkerTestHelper::
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback) {
last_developer_id_ = developer_id;
+ last_unique_id_ = unique_id;
+ last_fetches_ = fetches;
if (fail_abort_event_) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
@@ -59,10 +63,12 @@ void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
void BackgroundFetchEmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback) {
last_developer_id_ = developer_id;
+ last_unique_id_ = unique_id;
last_fetches_ = fetches;
if (fail_fetch_fail_event_) {
diff --git a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
index 7e12d00538f..248b9113586 100644
--- a/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
+++ b/chromium/content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h
@@ -68,6 +68,8 @@ class BackgroundFetchEmbeddedWorkerTestHelper
// EmbeddedWorkerTestHelper overrides:
void OnBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback) override;
void OnBackgroundFetchClickEvent(
@@ -77,6 +79,7 @@ class BackgroundFetchEmbeddedWorkerTestHelper
DispatchBackgroundFetchClickEventCallback callback) override;
void OnBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback) override;
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
index 7a52ccc795b..452c9524c84 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -76,6 +76,7 @@ BackgroundFetchEventDispatcher::~BackgroundFetchEventDispatcher() {
void BackgroundFetchEventDispatcher::DispatchBackgroundFetchAbortEvent(
const BackgroundFetchRegistrationId& registration_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
base::OnceClosure finished_closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
LoadServiceWorkerRegistrationForDispatch(
@@ -83,16 +84,19 @@ void BackgroundFetchEventDispatcher::DispatchBackgroundFetchAbortEvent(
std::move(finished_closure),
base::Bind(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent,
- registration_id.developer_id()));
+ registration_id.developer_id(), registration_id.unique_id(),
+ fetches));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
service_worker_version->event_dispatcher()->DispatchBackgroundFetchAbortEvent(
- developer_id,
+ developer_id, unique_id, fetches,
service_worker_version->CreateSimpleEventCallback(request_id));
}
@@ -130,17 +134,19 @@ void BackgroundFetchEventDispatcher::DispatchBackgroundFetchFailEvent(
std::move(finished_closure),
base::Bind(
&BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent,
- registration_id.developer_id(), fetches));
+ registration_id.developer_id(), registration_id.unique_id(),
+ fetches));
}
void BackgroundFetchEventDispatcher::DoDispatchBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id) {
DCHECK(service_worker_version);
service_worker_version->event_dispatcher()->DispatchBackgroundFetchFailEvent(
- developer_id, fetches,
+ developer_id, unique_id, fetches,
service_worker_version->CreateSimpleEventCallback(request_id));
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
index 73bbd100818..7194e67e967 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher.h
@@ -45,6 +45,7 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
// background fetch was aborted by the user or another external event.
void DispatchBackgroundFetchAbortEvent(
const BackgroundFetchRegistrationId& registration_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
base::OnceClosure finished_closure);
// Dispatches the `backgroundfetchclick` event, which indicates that the user
@@ -113,6 +114,8 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
// Methods that actually invoke the event on an activated Service Worker.
static void DoDispatchBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id);
static void DoDispatchBackgroundFetchClickEvent(
@@ -122,6 +125,7 @@ class CONTENT_EXPORT BackgroundFetchEventDispatcher {
int request_id);
static void DoDispatchBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
int request_id);
diff --git a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
index da84755ce0c..aac9e2f1f68 100644
--- a/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
@@ -44,8 +44,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchInvalidRegistration) {
kExampleUniqueId);
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchAbortEvent(invalid_registration_id,
- run_loop.QuitClosure());
+ event_dispatcher_.DispatchBackgroundFetchAbortEvent(
+ invalid_registration_id, {}, run_loop.QuitClosure());
run_loop.Run();
@@ -62,14 +62,17 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
service_worker_registration_id);
+ std::vector<BackgroundFetchSettledFetch> fetches;
+ fetches.push_back(BackgroundFetchSettledFetch());
+
BackgroundFetchRegistrationId registration_id(service_worker_registration_id,
origin(), kExampleDeveloperId,
kExampleUniqueId);
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchAbortEvent(registration_id,
- run_loop.QuitClosure());
+ event_dispatcher_.DispatchBackgroundFetchAbortEvent(
+ registration_id, fetches, run_loop.QuitClosure());
run_loop.Run();
}
@@ -77,6 +80,10 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
EXPECT_EQ(kExampleDeveloperId,
embedded_worker_test_helper()->last_developer_id().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_unique_id().has_value());
+ EXPECT_EQ(kExampleUniqueId,
+ embedded_worker_test_helper()->last_unique_id().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
histogram_tester_.ExpectUniqueSample(
"BackgroundFetch.EventDispatchResult.AbortEvent",
@@ -90,8 +97,8 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
{
base::RunLoop run_loop;
- event_dispatcher_.DispatchBackgroundFetchAbortEvent(second_registration_id,
- run_loop.QuitClosure());
+ event_dispatcher_.DispatchBackgroundFetchAbortEvent(
+ second_registration_id, fetches, run_loop.QuitClosure());
run_loop.Run();
}
@@ -99,6 +106,10 @@ TEST_F(BackgroundFetchEventDispatcherTest, DispatchAbortEvent) {
ASSERT_TRUE(embedded_worker_test_helper()->last_developer_id().has_value());
EXPECT_EQ(kExampleDeveloperId2,
embedded_worker_test_helper()->last_developer_id().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_unique_id().has_value());
+ EXPECT_EQ(kExampleUniqueId2,
+ embedded_worker_test_helper()->last_unique_id().value());
+ ASSERT_TRUE(embedded_worker_test_helper()->last_fetches().has_value());
histogram_tester_.ExpectBucketCount(
"BackgroundFetch.EventDispatchResult.AbortEvent",
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
index 83f1fa69711..aac1856ce92 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -45,10 +45,17 @@ void BackgroundFetchJobController::InitializeRequestStatus(
completed_downloads_ = completed_downloads;
total_downloads_ = total_downloads;
- delegate_proxy_->CreateDownloadJob(registration_id().unique_id(),
- options_.title, registration_id().origin(),
- icon_, GetWeakPtr(), completed_downloads,
- total_downloads, outstanding_guids);
+ // TODO(nator): Update this when we support uploads.
+ int total_downloads_size = options_.download_total;
+
+ auto fetch_description = std::make_unique<BackgroundFetchDescription>(
+ registration_id().unique_id(), options_.title, registration_id().origin(),
+ icon_, completed_downloads, total_downloads,
+ complete_requests_downloaded_bytes_cache_, total_downloads_size,
+ outstanding_guids);
+
+ delegate_proxy_->CreateDownloadJob(GetWeakPtr(),
+ std::move(fetch_description));
}
BackgroundFetchJobController::~BackgroundFetchJobController() {
@@ -107,12 +114,6 @@ void BackgroundFetchJobController::DidCompleteRequest(
request_manager_->MarkRequestAsComplete(registration_id(), request.get());
}
-void BackgroundFetchJobController::AbortFromUser() {
- // Aborts from user come via the BackgroundFetchDelegate, which will have
- // already cancelled the download.
- Abort(false /* cancel_download */);
-}
-
void BackgroundFetchJobController::UpdateUI(const std::string& title) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -126,21 +127,23 @@ uint64_t BackgroundFetchJobController::GetInProgressDownloadedBytes() {
return sum;
}
-void BackgroundFetchJobController::Abort() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- Abort(true /* cancel_download */);
-}
-
-void BackgroundFetchJobController::Abort(bool cancel_download) {
- if (cancel_download)
- delegate_proxy_->Abort(registration_id().unique_id());
+void BackgroundFetchJobController::Abort(
+ BackgroundFetchReasonToAbort reason_to_abort) {
+ delegate_proxy_->Abort(registration_id().unique_id());
std::vector<std::string> aborted_guids;
for (const auto& pair : active_request_download_bytes_)
aborted_guids.push_back(pair.first);
request_manager_->OnJobAborted(registration_id(), std::move(aborted_guids));
- Finish(true /* aborted */);
+ if (reason_to_abort != BackgroundFetchReasonToAbort::ABORTED_BY_DEVELOPER) {
+ // Don't call Finish() here, so that we don't mark data for deletion while
+ // there are active fetches.
+ // Once the controller finishes processing, this function will be called
+ // again. (BackgroundFetchScheduler's finished_callback_ will call
+ // BackgroundFetchJobController::Abort() with |cancel_download| set to
+ // true.)
+ Finish(reason_to_abort);
+ }
}
} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller.h b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
index 02d5378318a..bc7eb93c844 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller.h
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller.h
@@ -41,7 +41,7 @@ class CONTENT_EXPORT BackgroundFetchJobController final
public:
using FinishedCallback =
base::OnceCallback<void(const BackgroundFetchRegistrationId&,
- bool /* aborted */)>;
+ BackgroundFetchReasonToAbort)>;
using ProgressCallback =
base::RepeatingCallback<void(const std::string& /* unique_id */,
uint64_t /* download_total */,
@@ -71,9 +71,6 @@ class CONTENT_EXPORT BackgroundFetchJobController final
// of a notification for instance.
void UpdateUI(const std::string& title);
- // Aborts the job including cancelling any ongoing downloads.
- void Abort();
-
// Returns the options with which this job is fetching data.
const BackgroundFetchOptions& options() const { return options_; }
@@ -89,17 +86,13 @@ class CONTENT_EXPORT BackgroundFetchJobController final
uint64_t bytes_downloaded) override;
void DidCompleteRequest(
const scoped_refptr<BackgroundFetchRequestInfo>& request) override;
- void AbortFromUser() override;
// BackgroundFetchScheduler::Controller implementation:
bool HasMoreRequests() override;
void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request) override;
+ void Abort(BackgroundFetchReasonToAbort reason_to_abort) override;
private:
- // Aborts a job updating the registration with the new state. If
- // |cancel_download| is true, the ongoing download is also cancelled
- // (otherwise it assumes that has already happened).
- void Abort(bool cancel_download);
// Options for the represented background fetch registration.
BackgroundFetchOptions options_;
diff --git a/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
index f628088aebe..f504d14b912 100644
--- a/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -190,7 +190,7 @@ class BackgroundFetchJobControllerTest : public BackgroundFetchTestBase {
}
static void OnJobFinished(const BackgroundFetchRegistrationId&,
- bool aborted) {}
+ BackgroundFetchReasonToAbort reason_to_abort) {}
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchJobControllerTest);
};
@@ -268,7 +268,7 @@ TEST_F(BackgroundFetchJobControllerTest, Abort) {
CreateJobController(registration_id, requests.size());
controller->StartRequest(requests[0]);
- controller->AbortFromUser();
+ controller->Abort(BackgroundFetchReasonToAbort::CANCELLED_FROM_UI);
// Tell the delegate to abort the job as well so it doesn't send completed
// messages to the JobController.
delegate_->Abort(registration_id.unique_id());
diff --git a/chromium/content/browser/background_fetch/background_fetch_metrics.cc b/chromium/content/browser/background_fetch/background_fetch_metrics.cc
new file mode 100644
index 00000000000..ec5979b21d1
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_metrics.cc
@@ -0,0 +1,27 @@
+// 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/background_fetch_metrics.h"
+
+#include "base/metrics/histogram_macros.h"
+
+namespace content {
+
+namespace background_fetch {
+
+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);
+}
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/background_fetch_metrics.h b/chromium/content/browser/background_fetch/background_fetch_metrics.h
new file mode 100644
index 00000000000..977b33bc687
--- /dev/null
+++ b/chromium/content/browser/background_fetch/background_fetch_metrics.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 CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_METRICS_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_METRICS_H_
+
+#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
+
+namespace content {
+
+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);
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_METRICS_H_
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
index 1b96430ec00..62309d66bba 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -19,9 +19,12 @@ BackgroundFetchScheduler::Controller::Controller(
BackgroundFetchScheduler::Controller::~Controller() = default;
-void BackgroundFetchScheduler::Controller::Finish(bool abort) {
- DCHECK(abort || !HasMoreRequests());
- std::move(finished_callback_).Run(registration_id_, abort);
+void BackgroundFetchScheduler::Controller::Finish(
+ BackgroundFetchReasonToAbort reason_to_abort) {
+ DCHECK(reason_to_abort != BackgroundFetchReasonToAbort::NONE ||
+ !HasMoreRequests());
+
+ std::move(finished_callback_).Run(registration_id_, reason_to_abort);
}
BackgroundFetchScheduler::BackgroundFetchScheduler(
@@ -80,7 +83,7 @@ void BackgroundFetchScheduler::DidMarkRequestAsComplete(
if (controller->HasMoreRequests())
controller_queue_.push_back(controller);
else
- controller->Finish(false);
+ controller->Finish(BackgroundFetchReasonToAbort::NONE);
ScheduleDownload();
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler.h b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
index fb72f3144f9..8527582c520 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler.h
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler.h
@@ -21,6 +21,7 @@ namespace content {
class BackgroundFetchRegistrationId;
class BackgroundFetchRequestInfo;
+enum class BackgroundFetchReasonToAbort;
// Maintains a list of Controllers and chooses which ones should launch new
// downloads.
@@ -29,7 +30,7 @@ class CONTENT_EXPORT BackgroundFetchScheduler
public:
using FinishedCallback =
base::OnceCallback<void(const BackgroundFetchRegistrationId&,
- bool /* aborted */)>;
+ BackgroundFetchReasonToAbort)>;
using MarkedCompleteCallback = base::OnceCallback<void()>;
// Interface for download job controllers.
@@ -44,7 +45,7 @@ class CONTENT_EXPORT BackgroundFetchScheduler
virtual void StartRequest(
scoped_refptr<BackgroundFetchRequestInfo> request) = 0;
- void Finish(bool abort);
+ void Finish(BackgroundFetchReasonToAbort reason_to_abort);
const BackgroundFetchRegistrationId& registration_id() const {
return registration_id_;
diff --git a/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
index 8e917b0345e..fdee316f59d 100644
--- a/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
@@ -61,7 +61,7 @@ class FakeController : public BackgroundFetchScheduler::Controller {
}
static void OnJobFinished(const BackgroundFetchRegistrationId&,
- bool aborted) {}
+ BackgroundFetchReasonToAbort reason_to_abort) {}
int jobs_started_ = 0;
BackgroundFetchScheduler* scheduler_;
diff --git a/chromium/content/browser/background_fetch/background_fetch_service_impl.cc b/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
index c481fb6c041..596cfaa0109 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -8,6 +8,7 @@
#include "base/guid.h"
#include "content/browser/background_fetch/background_fetch_context.h"
+#include "content/browser/background_fetch/background_fetch_metrics.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/bad_message.h"
#include "content/browser/storage_partition_impl.h"
@@ -76,17 +77,12 @@ void BackgroundFetchServiceImpl::Fetch(
const SkBitmap& icon,
FetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ValidateDeveloperId(developer_id)) {
- std::move(callback).Run(
- blink::mojom::BackgroundFetchError::INVALID_ARGUMENT,
- base::nullopt /* registration */);
- return;
- }
-
- if (!ValidateRequests(requests)) {
+ if (!ValidateDeveloperId(developer_id) || !ValidateRequests(requests)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT,
base::nullopt /* registration */);
+ background_fetch::RecordRegistrationCreatedError(
+ blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
return;
}
diff --git a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
index 6e703f027a3..839e8eee9a7 100644
--- a/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/chromium/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -9,6 +9,7 @@
#include "base/auto_reset.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/test/histogram_tester.h"
#include "base/time/time.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h"
@@ -98,6 +99,7 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
DCHECK(out_error);
DCHECK(out_registration);
+ base::HistogramTester histogram_tester;
base::RunLoop run_loop;
service_->Fetch(
service_worker_registration_id, developer_id, requests, options, icon,
@@ -107,6 +109,10 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
run_loop.Run();
+ histogram_tester.ExpectBucketCount(
+ "BackgroundFetch.RegistrationCreatedError",
+ static_cast<int32_t>(*out_error), 1);
+
if (*out_error != blink::mojom::BackgroundFetchError::NONE)
return BackgroundFetchRegistrationId();
@@ -139,6 +145,7 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
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,
@@ -146,6 +153,17 @@ class BackgroundFetchServiceTest : public BackgroundFetchTestBase {
run_loop.QuitClosure(), out_error));
run_loop.Run();
+
+ // 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().
diff --git a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
index ffe514bd9c5..753d955a839 100644
--- a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
+++ b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -8,6 +8,7 @@
#include "base/files/file_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/background_fetch/mock_background_fetch_delegate.h"
+#include "content/public/browser/background_fetch_description.h"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_thread.h"
#include "net/http/http_response_headers.h"
@@ -59,13 +60,7 @@ void MockBackgroundFetchDelegate::GetIconDisplaySize(
GetIconDisplaySizeCallback callback) {}
void MockBackgroundFetchDelegate::CreateDownloadJob(
- const std::string& job_unique_id,
- const std::string& title,
- const url::Origin& origin,
- const SkBitmap& icon,
- int completed_parts,
- int total_parts,
- const std::vector<std::string>& current_guids) {}
+ std::unique_ptr<BackgroundFetchDescription> fetch_description) {}
void MockBackgroundFetchDelegate::DownloadUrl(
const std::string& job_unique_id,
diff --git a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
index fe63a87b786..bc685f96a56 100644
--- a/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
+++ b/chromium/content/browser/background_fetch/mock_background_fetch_delegate.h
@@ -66,13 +66,7 @@ class MockBackgroundFetchDelegate : public BackgroundFetchDelegate {
void GetIconDisplaySize(
BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) override;
void CreateDownloadJob(
- const std::string& job_unique_id,
- const std::string& title,
- const url::Origin& origin,
- const SkBitmap& icon,
- int completed_parts,
- int total_parts,
- const std::vector<std::string>& current_guids) override;
+ std::unique_ptr<BackgroundFetchDescription> fetch_description) override;
void DownloadUrl(const std::string& job_unique_id,
const std::string& guid,
const std::string& method,
diff --git a/chromium/content/browser/background_fetch/storage/README.md b/chromium/content/browser/background_fetch/storage/README.md
index 8292ab494e2..e21e9c327e9 100644
--- a/chromium/content/browser/background_fetch/storage/README.md
+++ b/chromium/content/browser/background_fetch/storage/README.md
@@ -19,17 +19,30 @@ running background fetches.
key: "bgfetch_active_registration_unique_id_<developer_id>"
value: "<unique_id>"
```
+
```
key: "bgfetch_registration_<unique_id>"
value: "<serialized content::proto::BackgroundFetchMetadata>"
```
+
+```
+key: "bgfetch_title_<unique_id>"
+value: "<ui_title>"
+```
+
```
-key: "bgfetch_request_<unique_id>_<request_index>"
-value: "<TODO: FetchAPIRequest serialized as a string>"
+key: "bgfetch_pending_request_<unique_id>_<request_index>"
+value: "<serialized content::proto::BackgroundFetchPendingRequest>"
```
+
+```
+key: "bgfetch_active_request_<unique_id>_<request_index>"
+value: "<serialized content::proto::BackgroundFetchActiveRequest>"
+```
+
```
-key: "bgfetch_pending_request_<creation_time>_<unique_id>_<request_index>"
-value: ""
+key: "bgfetch_completed_request_<unique_id>_<request_index>"
+value: "<serialized content::proto::BackgroundFetchCompletedRequest>"
```
### Expansions
@@ -42,9 +55,6 @@ introduce ambiguity.
* `<request_index>` is an `int` containing the index of a request within a
multi-part fetch. These must be padded with zeros to ensure that the ordering
is maintain when reading back from the database, e.g. `0000000000`.
-* `<creation_time>` is the registration creation time expressed as the number
-of microseconds since the unix epoch (internally stored as an `int64_t`).
-Without padding with zeros, this may introduce an ordering inversion in
-November 2286 and again in the year 5138, but the impact would only be on the
-relative ordering with which two different fetches were scheduled.
+* `<ui_title>` is the notification title provided by the developer. It can also
+be updated by calling `BackgroundFetchUpdateEvent.updateUI`.
diff --git a/chromium/content/browser/background_fetch/storage/create_metadata_task.cc b/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
index 18d45c6ec2a..c070e9f817b 100644
--- a/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/chromium/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -15,11 +15,6 @@ namespace content {
namespace background_fetch {
-std::string RequestKey(const std::string& unique_id, int request_index) {
- // Allows looking up a request by registration id and index within that.
- return RequestKeyPrefix(unique_id) + base::IntToString(request_index);
-}
-
CreateMetadataTask::CreateMetadataTask(
BackgroundFetchDataManager* data_manager,
const BackgroundFetchRegistrationId& registration_id,
@@ -90,7 +85,7 @@ void CreateMetadataTask::InitializeMetadataProto() {
metadata_proto_->set_origin(registration_id_.origin().Serialize());
metadata_proto_->set_creation_microseconds_since_unix_epoch(
(base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds());
- metadata_proto_->set_ui_title(options_.title);
+ metadata_proto_->set_num_fetches(requests_.size());
}
void CreateMetadataTask::StoreMetadata() {
@@ -113,17 +108,16 @@ void CreateMetadataTask::StoreMetadata() {
registration_id_.unique_id());
entries.emplace_back(RegistrationKey(registration_id_.unique_id()),
std::move(serialized_metadata_proto));
+ entries.emplace_back(TitleKey(registration_id_.unique_id()), options_.title);
// Signed integers are used for request indexes to avoid unsigned gotchas.
for (int i = 0; i < base::checked_cast<int>(requests_.size()); i++) {
- // TODO(crbug.com/757760): Serialize actual values for these entries.
- entries.emplace_back(RequestKey(registration_id_.unique_id(), i),
- "TODO: Serialize FetchAPIRequest as value");
- entries.emplace_back(
- PendingRequestKey(
- metadata_proto_->creation_microseconds_since_unix_epoch(),
- registration_id_.unique_id(), i),
- std::string());
+ proto::BackgroundFetchPendingRequest pending_request_proto;
+ pending_request_proto.set_unique_id(registration_id_.unique_id());
+ pending_request_proto.set_request_index(i);
+ pending_request_proto.set_serialized_request(requests_[i].Serialize());
+ entries.emplace_back(PendingRequestKey(registration_id_.unique_id(), i),
+ pending_request_proto.SerializeAsString());
}
service_worker_context()->StoreRegistrationUserData(
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.cc b/chromium/content/browser/background_fetch/storage/database_helpers.cc
index be25d6d5837..cb8348e731c 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.cc
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.cc
@@ -23,41 +23,33 @@ std::string RegistrationKey(const std::string& unique_id) {
return kRegistrationKeyPrefix + unique_id;
}
-std::string RequestKeyPrefix(const std::string& unique_id) {
- // Allows looking up all requests within a registration.
- return kRequestKeyPrefix + unique_id + kSeparator;
+std::string TitleKey(const std::string& unique_id) {
+ return kTitleKeyPrefix + unique_id;
}
-std::string PendingRequestKeyPrefix(
- int64_t registration_creation_microseconds_since_unix_epoch,
- const std::string& unique_id) {
- // These keys are ordered by the registration's creation time rather than by
- // its |unique_id|, so that the highest priority pending requests in FIFO
- // order can be looked up by fetching the lexicographically smallest keys.
- // https://crbug.com/741609 may introduce more advanced prioritisation.
- //
- // Since the ordering must survive restarts, wall clock time is used, but that
- // is not monotonically increasing, so the ordering is not exact, and the
- // |unique_id| is appended to break ties in case the wall clock returns the
- // same values more than once.
- //
- // On Nov 20 2286 17:46:39 the microseconds will transition from 9999999999999
- // to 10000000000000 and pending requests will briefly sort incorrectly.
- return kPendingRequestKeyPrefix +
- base::Int64ToString(
- registration_creation_microseconds_since_unix_epoch) +
- kSeparator + unique_id + kSeparator;
+std::string PendingRequestKeyPrefix(const std::string& unique_id) {
+ return kPendingRequestKeyPrefix + unique_id + kSeparator;
}
-std::string PendingRequestKey(
- int64_t registration_creation_microseconds_since_unix_epoch,
- const std::string& unique_id,
- int request_index) {
- // In addition to the ordering from PendingRequestKeyPrefix, the requests
- // within each registration should be prioritized according to their index.
- return PendingRequestKeyPrefix(
- registration_creation_microseconds_since_unix_epoch, unique_id) +
- base::IntToString(request_index);
+std::string PendingRequestKey(const std::string& unique_id, int request_index) {
+ return PendingRequestKeyPrefix(unique_id) + std::to_string(request_index);
+}
+
+std::string ActiveRequestKeyPrefix(const std::string& unique_id) {
+ return kActiveRequestKeyPrefix + unique_id + kSeparator;
+}
+
+std::string ActiveRequestKey(const std::string& unique_id, int request_index) {
+ return ActiveRequestKeyPrefix(unique_id) + std::to_string(request_index);
+}
+
+std::string CompletedRequestKeyPrefix(const std::string& unique_id) {
+ return kCompletedRequestKeyPrefix + unique_id + kSeparator;
+}
+
+std::string CompletedRequestKey(const std::string& unique_id,
+ int request_index) {
+ return CompletedRequestKeyPrefix(unique_id) + std::to_string(request_index);
}
DatabaseStatus ToDatabaseStatus(ServiceWorkerStatusCode status) {
diff --git a/chromium/content/browser/background_fetch/storage/database_helpers.h b/chromium/content/browser/background_fetch/storage/database_helpers.h
index 188937b5af6..c81874378ce 100644
--- a/chromium/content/browser/background_fetch/storage/database_helpers.h
+++ b/chromium/content/browser/background_fetch/storage/database_helpers.h
@@ -8,6 +8,7 @@
#include <string>
#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker_types.h"
namespace content {
@@ -20,26 +21,32 @@ namespace background_fetch {
// Warning: registration |developer_id|s may contain kSeparator characters.
const char kSeparator[] = "_";
-const char kRequestKeyPrefix[] = "bgfetch_request_";
-const char kRegistrationKeyPrefix[] = "bgfetch_registration_";
-const char kPendingRequestKeyPrefix[] = "bgfetch_pending_request_";
const char kActiveRegistrationUniqueIdKeyPrefix[] =
"bgfetch_active_registration_unique_id_";
+const char kRegistrationKeyPrefix[] = "bgfetch_registration_";
+const char kTitleKeyPrefix[] = "bgfetch_title_";
+const char kPendingRequestKeyPrefix[] = "bgfetch_pending_request_";
+const char kActiveRequestKeyPrefix[] = "bgfetch_active_request_";
+const char kCompletedRequestKeyPrefix[] = "bgfetch_completed_request_";
std::string ActiveRegistrationUniqueIdKey(const std::string& developer_id);
std::string RegistrationKey(const std::string& unique_id);
-std::string RequestKeyPrefix(const std::string& unique_id);
+std::string TitleKey(const std::string& unique_id);
+
+std::string PendingRequestKeyPrefix(const std::string& unique_id);
+
+std::string PendingRequestKey(const std::string& unique_id, int request_index);
+
+std::string ActiveRequestKeyPrefix(const std::string& unique_id);
+
+std::string ActiveRequestKey(const std::string& unique_id, int request_index);
-std::string PendingRequestKeyPrefix(
- int64_t registration_creation_microseconds_since_unix_epoch,
- const std::string& unique_id);
+std::string CompletedRequestKeyPrefix(const std::string& unique_id);
-std::string PendingRequestKey(
- int64_t registration_creation_microseconds_since_unix_epoch,
- const std::string& unique_id,
- int request_index);
+std::string CompletedRequestKey(const std::string& unique_id,
+ int request_index);
enum class DatabaseStatus { kOk, kFailed, kNotFound };
diff --git a/chromium/content/browser/background_fetch/storage/delete_registration_task.cc b/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
index 92cb468eac8..e5c2d759758 100644
--- a/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
+++ b/chromium/content/browser/background_fetch/storage/delete_registration_task.cc
@@ -87,7 +87,7 @@ void DeleteRegistrationTask::DidGetRegistration(
service_worker_context()->ClearRegistrationUserDataByKeyPrefixes(
service_worker_registration_id_,
- {RegistrationKey(unique_id_), RequestKeyPrefix(unique_id_)},
+ {RegistrationKey(unique_id_), TitleKey(unique_id_)},
base::BindOnce(&DeleteRegistrationTask::DidDeleteRegistration,
weak_factory_.GetWeakPtr()));
}
diff --git a/chromium/content/browser/background_fetch/storage/get_num_requests_task.cc b/chromium/content/browser/background_fetch/storage/get_num_requests_task.cc
new file mode 100644
index 00000000000..6e4fbf2f566
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_num_requests_task.cc
@@ -0,0 +1,88 @@
+// 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/get_num_requests_task.h"
+
+#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/background_fetch/storage/get_metadata_task.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+
+namespace content {
+
+namespace background_fetch {
+
+namespace {
+
+void HandleGetMetadataCallback(
+ GetNumRequestsTask::NumRequestsCallback callback,
+ blink::mojom::BackgroundFetchError error,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata) {
+ if (error != blink::mojom::BackgroundFetchError::NONE) {
+ std::move(callback).Run(0u);
+ return;
+ }
+
+ DCHECK(metadata);
+ std::move(callback).Run(metadata->num_fetches());
+}
+
+} // namespace
+
+GetNumRequestsTask::GetNumRequestsTask(
+ BackgroundFetchDataManager* data_manager,
+ const BackgroundFetchRegistrationId& registration_id,
+ RequestType type,
+ NumRequestsCallback callback)
+ : DatabaseTask(data_manager),
+ registration_id_(registration_id),
+ type_(type),
+ callback_(std::move(callback)),
+ weak_factory_(this) {}
+
+GetNumRequestsTask::~GetNumRequestsTask() = default;
+
+void GetNumRequestsTask::Start() {
+ switch (type_) {
+ case RequestType::kAny:
+ GetMetadata();
+ return;
+ case RequestType::kPending:
+ GetRequests(PendingRequestKeyPrefix(registration_id_.unique_id()));
+ return;
+ case RequestType::kActive:
+ GetRequests(ActiveRequestKeyPrefix(registration_id_.unique_id()));
+ return;
+ case RequestType::kCompleted:
+ GetRequests(CompletedRequestKeyPrefix(registration_id_.unique_id()));
+ return;
+ }
+ NOTREACHED();
+}
+
+void GetNumRequestsTask::GetMetadata() {
+ AddDatabaseTask(std::make_unique<GetMetadataTask>(
+ data_manager(), registration_id_.service_worker_registration_id(),
+ registration_id_.origin(), registration_id_.developer_id(),
+ base::BindOnce(&HandleGetMetadataCallback, std::move(callback_))));
+ Finished(); // Destroys |this|.
+}
+
+void GetNumRequestsTask::GetRequests(const std::string& key_prefix) {
+ service_worker_context()->GetRegistrationUserDataByKeyPrefix(
+ registration_id_.service_worker_registration_id(), key_prefix,
+ base::BindOnce(&GetNumRequestsTask::DidGetRequests,
+ weak_factory_.GetWeakPtr()));
+}
+
+void GetNumRequestsTask::DidGetRequests(const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status) {
+ DCHECK_EQ(ToDatabaseStatus(status), DatabaseStatus::kOk);
+ std::move(callback_).Run(data.size());
+ Finished(); // Destroys |this|.
+}
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_num_requests_task.h b/chromium/content/browser/background_fetch/storage/get_num_requests_task.h
new file mode 100644
index 00000000000..fe4857b4b91
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_num_requests_task.h
@@ -0,0 +1,53 @@
+// 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_GET_NUM_REQUESTS_TASK_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_NUM_REQUESTS_TASK_H_
+
+#include "base/callback_forward.h"
+#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/common/content_export.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+
+namespace content {
+
+namespace background_fetch {
+
+enum class RequestType { kAny, kPending, kActive, kCompleted };
+
+// Gets the number of requests per registration of the given type.
+class CONTENT_EXPORT GetNumRequestsTask : public DatabaseTask {
+ public:
+ using NumRequestsCallback = base::OnceCallback<void(size_t)>;
+
+ GetNumRequestsTask(BackgroundFetchDataManager* data_manager,
+ const BackgroundFetchRegistrationId& registration_id,
+ RequestType type,
+ NumRequestsCallback callback);
+
+ ~GetNumRequestsTask() override;
+
+ // DatabaseTask implementation:
+ void Start() override;
+
+ private:
+ void GetMetadata();
+ void GetRequests(const std::string& key_prefix);
+ void DidGetRequests(const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status);
+
+ BackgroundFetchRegistrationId registration_id_;
+ RequestType type_;
+ NumRequestsCallback callback_;
+
+ base::WeakPtrFactory<GetNumRequestsTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(GetNumRequestsTask);
+};
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_NUM_REQUESTS_TASK_H_
diff --git a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
new file mode 100644
index 00000000000..9ea3c390098
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.cc
@@ -0,0 +1,111 @@
+// 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/get_settled_fetches_task.h"
+
+#include "base/barrier_closure.h"
+#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+
+namespace content {
+
+namespace background_fetch {
+
+GetSettledFetchesTask::GetSettledFetchesTask(
+ BackgroundFetchDataManager* data_manager,
+ BackgroundFetchRegistrationId registration_id,
+ SettledFetchesCallback callback)
+ : DatabaseTask(data_manager),
+ registration_id_(registration_id),
+ settled_fetches_callback_(std::move(callback)),
+ weak_factory_(this) {}
+
+GetSettledFetchesTask::~GetSettledFetchesTask() = default;
+
+void GetSettledFetchesTask::Start() {
+ service_worker_context()->GetRegistrationUserDataByKeyPrefix(
+ registration_id_.service_worker_registration_id(),
+ {CompletedRequestKeyPrefix(registration_id_.unique_id())},
+ base::BindOnce(&GetSettledFetchesTask::DidGetCompletedRequests,
+ weak_factory_.GetWeakPtr()));
+}
+
+void GetSettledFetchesTask::DidGetCompletedRequests(
+ const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kOk:
+ break;
+ // TODO(crbug.com/780025): Log failures to UMA.
+ case DatabaseStatus::kFailed:
+ FinishTaskWithErrorCode(
+ blink::mojom::BackgroundFetchError::STORAGE_ERROR);
+ return;
+ case DatabaseStatus::kNotFound:
+ background_fetch_succeeded_ = false;
+ FinishTaskWithErrorCode(blink::mojom::BackgroundFetchError::INVALID_ID);
+ return;
+ }
+
+ // Nothing failed yet so the default state is success.
+ if (data.empty()) {
+ FinishTaskWithErrorCode(blink::mojom::BackgroundFetchError::NONE);
+ return;
+ }
+
+ base::RepeatingClosure barrier_closure = base::BarrierClosure(
+ data.size(),
+ base::BindOnce(&GetSettledFetchesTask::FinishTaskWithErrorCode,
+ weak_factory_.GetWeakPtr(),
+ blink::mojom::BackgroundFetchError::NONE));
+
+ settled_fetches_.reserve(data.size());
+ for (const std::string& serialized_completed_request : data) {
+ proto::BackgroundFetchCompletedRequest completed_request;
+ if (!completed_request.ParseFromString(serialized_completed_request)) {
+ NOTREACHED()
+ << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
+ }
+
+ settled_fetches_.emplace_back(BackgroundFetchSettledFetch());
+ settled_fetches_.back().request =
+ std::move(ServiceWorkerFetchRequest::ParseFromString(
+ completed_request.serialized_request()));
+ if (!completed_request.succeeded()) {
+ FillFailedResponse(&settled_fetches_.back().response, barrier_closure);
+ continue;
+ }
+ FillSuccessfulResponse(&settled_fetches_.back().response, barrier_closure);
+ }
+}
+
+void GetSettledFetchesTask::FillFailedResponse(
+ ServiceWorkerResponse* response,
+ const base::RepeatingClosure& callback) {
+ DCHECK(response);
+ background_fetch_succeeded_ = false;
+ // TODO(rayankans): Fill failed response with error reports.
+ std::move(callback).Run();
+}
+
+void GetSettledFetchesTask::FillSuccessfulResponse(
+ ServiceWorkerResponse* response,
+ const base::RepeatingClosure& callback) {
+ DCHECK(response);
+ // TODO(rayankans): Get the response stored in Cache Storage.
+ std::move(callback).Run();
+}
+
+void GetSettledFetchesTask::FinishTaskWithErrorCode(
+ blink::mojom::BackgroundFetchError error) {
+ std::move(settled_fetches_callback_)
+ .Run(error, background_fetch_succeeded_, std::move(settled_fetches_),
+ {} /* blob_data_handles */);
+ Finished(); // Destroys |this|.
+}
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
new file mode 100644
index 00000000000..7fba53179fc
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/get_settled_fetches_task.h
@@ -0,0 +1,61 @@
+// 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_GET_SETTLED_FETCHES_TASK_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_SETTLED_FETCHES_TASK_H_
+
+#include "base/callback_forward.h"
+#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+#include "storage/browser/blob/blob_data_handle.h"
+
+namespace content {
+
+namespace background_fetch {
+
+class GetSettledFetchesTask : public DatabaseTask {
+ public:
+ using SettledFetchesCallback = base::OnceCallback<void(
+ blink::mojom::BackgroundFetchError,
+ bool,
+ std::vector<BackgroundFetchSettledFetch>,
+ std::vector<std::unique_ptr<storage::BlobDataHandle>>)>;
+
+ GetSettledFetchesTask(BackgroundFetchDataManager* data_manager,
+ BackgroundFetchRegistrationId registration_id,
+ SettledFetchesCallback callback);
+
+ ~GetSettledFetchesTask() override;
+
+ // DatabaseTask implementation:
+ void Start() override;
+
+ private:
+ void DidGetCompletedRequests(const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status);
+
+ void FillFailedResponse(ServiceWorkerResponse* response,
+ const base::RepeatingClosure& callback);
+
+ void FillSuccessfulResponse(ServiceWorkerResponse* response,
+ const base::RepeatingClosure& callback);
+
+ void FinishTaskWithErrorCode(blink::mojom::BackgroundFetchError error);
+
+ BackgroundFetchRegistrationId registration_id_;
+ SettledFetchesCallback settled_fetches_callback_;
+
+ std::vector<BackgroundFetchSettledFetch> settled_fetches_;
+ bool background_fetch_succeeded_ = true;
+
+ base::WeakPtrFactory<GetSettledFetchesTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(GetSettledFetchesTask);
+};
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_GET_SETTLED_FETCHES_TASK_H_
diff --git a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
index 365e6bf7115..576d8fb64ab 100644
--- a/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
+++ b/chromium/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
@@ -65,8 +65,7 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
}
proto::BackgroundFetchMetadata metadata_proto;
- if (metadata_proto.ParseFromString(data[1]) &&
- metadata_proto.has_creation_microseconds_since_unix_epoch()) {
+ if (metadata_proto.ParseFromString(data[1])) {
// Mark registration as no longer active. Also deletes pending request
// keys, since those are globally sorted and requests within deactivated
// registrations are no longer eligible to be started. Pending request
@@ -74,9 +73,7 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
service_worker_context()->ClearRegistrationUserDataByKeyPrefixes(
registration_id_.service_worker_registration_id(),
{ActiveRegistrationUniqueIdKey(registration_id_.developer_id()),
- PendingRequestKeyPrefix(
- metadata_proto.creation_microseconds_since_unix_epoch(),
- registration_id_.unique_id())},
+ PendingRequestKeyPrefix(registration_id_.unique_id())},
base::BindOnce(&MarkRegistrationForDeletionTask::DidDeactivate,
weak_factory_.GetWeakPtr()));
} else {
diff --git a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
new file mode 100644
index 00000000000..63884ce938d
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.cc
@@ -0,0 +1,106 @@
+// 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/mark_request_complete_task.h"
+
+#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+
+namespace content {
+
+namespace background_fetch {
+
+MarkRequestCompleteTask::MarkRequestCompleteTask(
+ BackgroundFetchDataManager* data_manager,
+ BackgroundFetchRegistrationId registration_id,
+ scoped_refptr<BackgroundFetchRequestInfo> request_info,
+ MarkedCompleteCallback callback)
+ : DatabaseTask(data_manager),
+ registration_id_(registration_id),
+ request_info_(std::move(request_info)),
+ callback_(std::move(callback)),
+ weak_factory_(this) {}
+
+MarkRequestCompleteTask::~MarkRequestCompleteTask() = default;
+
+void MarkRequestCompleteTask::Start() {
+ StoreResponse();
+}
+
+void MarkRequestCompleteTask::StoreResponse() {
+ ServiceWorkerResponse response;
+ bool is_response_valid = data_manager()->FillServiceWorkerResponse(
+ *request_info_, registration_id_.origin(), &response);
+
+ if (!is_response_valid) {
+ // No point in caching the response, just do the request state transition.
+ CreateAndStoreCompletedRequest(false);
+ return;
+ }
+ // TODO(rayankans): Store the request/response pair in cache storage, and call
+ // `CreateAndStoreActiveRequest` via a callback.
+ CreateAndStoreCompletedRequest(true);
+}
+
+void MarkRequestCompleteTask::CreateAndStoreCompletedRequest(bool succeeded) {
+ completed_request_.set_unique_id(registration_id_.unique_id());
+ completed_request_.set_request_index(request_info_->request_index());
+ completed_request_.set_serialized_request(
+ request_info_->fetch_request().Serialize());
+ completed_request_.set_download_guid(request_info_->download_guid());
+ completed_request_.set_succeeded(succeeded);
+
+ service_worker_context()->StoreRegistrationUserData(
+ registration_id_.service_worker_registration_id(),
+ registration_id_.origin().GetURL(),
+ {{CompletedRequestKey(completed_request_.unique_id(),
+ completed_request_.request_index()),
+ completed_request_.SerializeAsString()}},
+ base::BindRepeating(&MarkRequestCompleteTask::DidStoreCompletedRequest,
+ weak_factory_.GetWeakPtr()));
+}
+
+void MarkRequestCompleteTask::DidStoreCompletedRequest(
+ ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kOk:
+ break;
+ case DatabaseStatus::kFailed:
+ case DatabaseStatus::kNotFound:
+ // TODO(crbug.com/780025): Log failures to UMA.
+ Finished(); // Destroys |this|.
+ return;
+ }
+
+ // Delete the active request.
+ service_worker_context()->ClearRegistrationUserData(
+ registration_id_.service_worker_registration_id(),
+ {ActiveRequestKey(completed_request_.unique_id(),
+ completed_request_.request_index())},
+ base::BindOnce(&MarkRequestCompleteTask::DidDeleteActiveRequest,
+ weak_factory_.GetWeakPtr()));
+}
+
+void MarkRequestCompleteTask::DidDeleteActiveRequest(
+ ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kFailed:
+ // TODO(crbug.com/780025): Log failures to UMA.
+ break;
+ case DatabaseStatus::kOk:
+ std::move(callback_).Run();
+ break;
+ }
+
+ Finished(); // Destroys |this|.
+
+ // TODO(rayankans): Update download stats.
+}
+
+} // namespace background_fetch
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
new file mode 100644
index 00000000000..b36c836ba04
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/mark_request_complete_task.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_MARK_REQUEST_COMPLETE_TASK_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_MARK_REQUEST_COMPLETE_TASK_H_
+
+#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/background_fetch_request_info.h"
+#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+
+namespace content {
+
+namespace background_fetch {
+
+// Moves the request from an active state to a complete state. Stores the
+// download response in cache storage.
+class MarkRequestCompleteTask : public DatabaseTask {
+ public:
+ using MarkedCompleteCallback = base::OnceCallback<void()>;
+
+ MarkRequestCompleteTask(
+ BackgroundFetchDataManager* data_manager,
+ BackgroundFetchRegistrationId registration_id,
+ scoped_refptr<BackgroundFetchRequestInfo> request_info,
+ MarkedCompleteCallback callback);
+
+ ~MarkRequestCompleteTask() override;
+
+ // DatabaseTask implementation:
+ void Start() override;
+
+ private:
+ void StoreResponse();
+
+ void CreateAndStoreCompletedRequest(bool succeeded);
+
+ void DidStoreCompletedRequest(ServiceWorkerStatusCode status);
+
+ void DidDeleteActiveRequest(ServiceWorkerStatusCode status);
+
+ BackgroundFetchRegistrationId registration_id_;
+ scoped_refptr<BackgroundFetchRequestInfo> request_info_;
+ MarkedCompleteCallback callback_;
+
+ proto::BackgroundFetchCompletedRequest completed_request_;
+
+ base::WeakPtrFactory<MarkRequestCompleteTask> weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(MarkRequestCompleteTask);
+};
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_MARK_REQUEST_COMPLETE_TASK_H_ \ No newline at end of file
diff --git a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
new file mode 100644
index 00000000000..107bb160409
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.cc
@@ -0,0 +1,161 @@
+// 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/start_next_pending_request_task.h"
+
+#include "base/guid.h"
+#include "content/browser/background_fetch/storage/database_helpers.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+
+namespace content {
+
+namespace background_fetch {
+
+StartNextPendingRequestTask::StartNextPendingRequestTask(
+ BackgroundFetchDataManager* data_manager,
+ int64_t service_worker_registration_id,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata,
+ NextRequestCallback callback)
+ : DatabaseTask(data_manager),
+ service_worker_registration_id_(service_worker_registration_id),
+ metadata_(std::move(metadata)),
+ callback_(std::move(callback)),
+ weak_factory_(this) {
+ DCHECK(metadata_);
+}
+
+StartNextPendingRequestTask::~StartNextPendingRequestTask() = default;
+
+void StartNextPendingRequestTask::Start() {
+ GetPendingRequests();
+}
+
+void StartNextPendingRequestTask::GetPendingRequests() {
+ service_worker_context()->GetRegistrationUserDataByKeyPrefix(
+ service_worker_registration_id_,
+ PendingRequestKeyPrefix(metadata_->registration().unique_id()),
+ base::BindOnce(&StartNextPendingRequestTask::DidGetPendingRequests,
+ weak_factory_.GetWeakPtr()));
+}
+
+void StartNextPendingRequestTask::DidGetPendingRequests(
+ const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kNotFound:
+ case DatabaseStatus::kFailed:
+ // TODO(crbug.com/780025): Log failures to UMA.
+ std::move(callback_).Run(nullptr /* request */);
+ Finished(); // Destroys |this|.
+ return;
+ case DatabaseStatus::kOk:
+ if (data.empty()) {
+ // There are no pending requests.
+ std::move(callback_).Run(nullptr /* request */);
+ Finished(); // Destroys |this|.
+ return;
+ }
+ }
+
+ if (!pending_request_.ParseFromString(data.front())) {
+ NOTREACHED() << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
+ }
+
+ // Make sure there isn't already an Active Request.
+ // This might happen if the browser is killed in-between writes.
+ service_worker_context()->GetRegistrationUserData(
+ service_worker_registration_id_,
+ {ActiveRequestKey(pending_request_.unique_id(),
+ pending_request_.request_index())},
+ base::BindOnce(&StartNextPendingRequestTask::DidFindActiveRequest,
+ weak_factory_.GetWeakPtr()));
+}
+
+void StartNextPendingRequestTask::DidFindActiveRequest(
+ const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kFailed:
+ // TODO(crbug.com/780025): Log failures to UMA.
+ std::move(callback_).Run(nullptr /* request */);
+ Finished(); // Destroys |this|.
+ return;
+ case DatabaseStatus::kNotFound:
+ CreateAndStoreActiveRequest();
+ return;
+ case DatabaseStatus::kOk:
+ // We already stored the active request.
+ if (!active_request_.ParseFromString(data.front())) {
+ NOTREACHED()
+ << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it.
+ }
+ StartDownload();
+ return;
+ }
+ NOTREACHED();
+}
+
+void StartNextPendingRequestTask::CreateAndStoreActiveRequest() {
+ proto::BackgroundFetchActiveRequest active_request;
+
+ active_request_.set_download_guid(base::GenerateGUID());
+ active_request_.set_unique_id(pending_request_.unique_id());
+ active_request_.set_request_index(pending_request_.request_index());
+ // Transfer ownership of the request to avoid a potentially expensive copy.
+ active_request_.set_allocated_serialized_request(
+ pending_request_.release_serialized_request());
+
+ service_worker_context()->StoreRegistrationUserData(
+ service_worker_registration_id_, GURL(metadata_->origin()),
+ {{ActiveRequestKey(active_request_.unique_id(),
+ active_request_.request_index()),
+ active_request_.SerializeAsString()}},
+ base::BindRepeating(&StartNextPendingRequestTask::DidStoreActiveRequest,
+ weak_factory_.GetWeakPtr()));
+}
+
+void StartNextPendingRequestTask::DidStoreActiveRequest(
+ ServiceWorkerStatusCode status) {
+ switch (ToDatabaseStatus(status)) {
+ case DatabaseStatus::kOk:
+ break;
+ case DatabaseStatus::kFailed:
+ case DatabaseStatus::kNotFound:
+ // TODO(crbug.com/780025): Log failures to UMA.
+ std::move(callback_).Run(nullptr /* request */);
+ Finished(); // Destroys |this|.
+ return;
+ }
+ StartDownload();
+}
+
+void StartNextPendingRequestTask::StartDownload() {
+ DCHECK(!active_request_.download_guid().empty());
+
+ auto next_request = base::MakeRefCounted<BackgroundFetchRequestInfo>(
+ active_request_.request_index(),
+ ServiceWorkerFetchRequest::ParseFromString(
+ active_request_.serialized_request()));
+ next_request->SetDownloadGuid(active_request_.download_guid());
+
+ std::move(callback_).Run(next_request);
+
+ // Delete the pending request.
+ service_worker_context()->ClearRegistrationUserData(
+ service_worker_registration_id_,
+ {PendingRequestKey(pending_request_.unique_id(),
+ pending_request_.request_index())},
+ base::BindOnce(&StartNextPendingRequestTask::DidDeletePendingRequest,
+ weak_factory_.GetWeakPtr()));
+}
+
+void StartNextPendingRequestTask::DidDeletePendingRequest(
+ ServiceWorkerStatusCode status) {
+ // TODO(crbug.com/780025): Log failures to UMA.
+ Finished(); // Destroys |this|.
+}
+
+} // namespace background_fetch
+
+} // namespace content
diff --git a/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
new file mode 100644
index 00000000000..476db6aa670
--- /dev/null
+++ b/chromium/content/browser/background_fetch/storage/start_next_pending_request_task.h
@@ -0,0 +1,72 @@
+// 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_START_NEXT_PENDING_REQUEST_TASK_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_START_NEXT_PENDING_REQUEST_TASK_H_
+
+#include "base/callback_forward.h"
+#include "content/browser/background_fetch/background_fetch.pb.h"
+#include "content/browser/background_fetch/background_fetch_request_info.h"
+#include "content/browser/background_fetch/storage/database_task.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+
+namespace content {
+
+namespace background_fetch {
+
+// Gets a pending request for a given registration, and moves it
+// to an active state.
+class StartNextPendingRequestTask : public DatabaseTask {
+ public:
+ using NextRequestCallback =
+ base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>;
+
+ StartNextPendingRequestTask(
+ BackgroundFetchDataManager* data_manager,
+ int64_t service_worker_registration_id,
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata,
+ NextRequestCallback callback);
+
+ ~StartNextPendingRequestTask() override;
+
+ // DatabaseTask implementation:
+ void Start() override;
+
+ private:
+ void GetPendingRequests();
+
+ void DidGetPendingRequests(const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status);
+
+ void DidFindActiveRequest(const std::vector<std::string>& data,
+ ServiceWorkerStatusCode status);
+
+ void CreateAndStoreActiveRequest();
+
+ void DidStoreActiveRequest(ServiceWorkerStatusCode status);
+
+ void StartDownload();
+
+ void DidDeletePendingRequest(ServiceWorkerStatusCode status);
+
+ int64_t service_worker_registration_id_;
+ std::unique_ptr<proto::BackgroundFetchMetadata> metadata_;
+ NextRequestCallback callback_;
+
+ // protos don't support move semantics, so these class members will be used
+ // to avoid unnecessary copying within callbacks.
+ proto::BackgroundFetchPendingRequest pending_request_;
+ proto::BackgroundFetchActiveRequest active_request_;
+
+ base::WeakPtrFactory<StartNextPendingRequestTask>
+ weak_factory_; // Keep as last.
+
+ DISALLOW_COPY_AND_ASSIGN(StartNextPendingRequestTask);
+};
+
+} // namespace background_fetch
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_START_NEXT_PENDING_REQUEST_TASK_H_
diff --git a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
index 0c2bafb7825..5927855db09 100644
--- a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
+++ b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.cc
@@ -26,61 +26,21 @@ UpdateRegistrationUITask::UpdateRegistrationUITask(
UpdateRegistrationUITask::~UpdateRegistrationUITask() = default;
void UpdateRegistrationUITask::Start() {
- service_worker_context()->GetRegistrationUserData(
- registration_id_.service_worker_registration_id(),
- {RegistrationKey(registration_id_.unique_id())},
- base::BindOnce(&UpdateRegistrationUITask::DidGetMetadata,
- weak_factory_.GetWeakPtr()));
-}
-
-void UpdateRegistrationUITask::DidGetMetadata(
- const std::vector<std::string>& data,
- ServiceWorkerStatusCode status) {
- switch (ToDatabaseStatus(status)) {
- case DatabaseStatus::kNotFound:
- case DatabaseStatus::kFailed:
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- Finished(); // Destroys |this|.
- return;
- case DatabaseStatus::kOk:
- if (data.size() != 1u) {
- std::move(callback_).Run(
- blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- Finished(); // Destroys |this|.
- return;
- }
- UpdateUI(data[0]);
- return;
- }
-}
-
-void UpdateRegistrationUITask::UpdateUI(
- const std::string& serialized_metadata_proto) {
- proto::BackgroundFetchMetadata metadata_proto;
- if (!metadata_proto.ParseFromString(serialized_metadata_proto)) {
- std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
- Finished(); // Destroys |this|.
- return;
- }
-
- metadata_proto.set_ui_title(updated_title_);
-
service_worker_context()->StoreRegistrationUserData(
registration_id_.service_worker_registration_id(),
registration_id_.origin().GetURL(),
- {{RegistrationKey(registration_id_.unique_id()),
- metadata_proto.SerializeAsString()}},
- base::BindOnce(&UpdateRegistrationUITask::DidUpdateUI,
+ {{TitleKey(registration_id_.unique_id()), updated_title_}},
+ base::BindOnce(&UpdateRegistrationUITask::DidUpdateTitle,
weak_factory_.GetWeakPtr()));
}
-void UpdateRegistrationUITask::DidUpdateUI(ServiceWorkerStatusCode status) {
+void UpdateRegistrationUITask::DidUpdateTitle(ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kOk:
break;
case DatabaseStatus::kFailed:
case DatabaseStatus::kNotFound:
+ // TODO(crbug.com/780025): Log failures to UMA.
std::move(callback_).Run(
blink::mojom::BackgroundFetchError::STORAGE_ERROR);
Finished(); // Destroys |this|.
diff --git a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
index 54aebf6ed8d..08167977bd2 100644
--- a/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
+++ b/chromium/content/browser/background_fetch/storage/update_registration_ui_task.h
@@ -33,12 +33,7 @@ class UpdateRegistrationUITask : public DatabaseTask {
void Start() override;
private:
- void DidGetMetadata(const std::vector<std::string>& data,
- ServiceWorkerStatusCode status);
-
- void UpdateUI(const std::string& serialized_metadata_proto);
-
- void DidUpdateUI(ServiceWorkerStatusCode status);
+ void DidUpdateTitle(ServiceWorkerStatusCode status);
BackgroundFetchRegistrationId registration_id_;
std::string updated_title_;
diff --git a/chromium/content/browser/background_sync/background_sync_context.cc b/chromium/content/browser/background_sync/background_sync_context.cc
index 625ae345c6a..d460b065966 100644
--- a/chromium/content/browser/background_sync/background_sync_context.cc
+++ b/chromium/content/browser/background_sync/background_sync_context.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/background_sync/background_sync_service_impl.h"
@@ -16,11 +15,15 @@
namespace content {
-BackgroundSyncContext::BackgroundSyncContext() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
+BackgroundSyncContext::BackgroundSyncContext()
+ : base::RefCountedDeleteOnSequence<BackgroundSyncContext>(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)) {}
BackgroundSyncContext::~BackgroundSyncContext() {
+ // The destructor must run on the IO thread because it implicitly accesses
+ // background_sync_manager_ and services_, when it runs their destructors.
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
DCHECK(!background_sync_manager_);
DCHECK(services_.empty());
}
@@ -37,7 +40,6 @@ void BackgroundSyncContext::Init(
void BackgroundSyncContext::Shutdown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&BackgroundSyncContext::ShutdownOnIO, this));
@@ -46,7 +48,6 @@ void BackgroundSyncContext::Shutdown() {
void BackgroundSyncContext::CreateService(
blink::mojom::BackgroundSyncServiceRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&BackgroundSyncContext::CreateServiceOnIOThread, this,
@@ -86,9 +87,9 @@ void BackgroundSyncContext::CreateServiceOnIOThread(
mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(background_sync_manager_);
- BackgroundSyncServiceImpl* service =
- new BackgroundSyncServiceImpl(this, std::move(request));
- services_[service] = base::WrapUnique(service);
+ auto service =
+ std::make_unique<BackgroundSyncServiceImpl>(this, std::move(request));
+ services_[service.get()] = std::move(service);
}
void BackgroundSyncContext::ShutdownOnIO() {
diff --git a/chromium/content/browser/background_sync/background_sync_context.h b/chromium/content/browser/background_sync/background_sync_context.h
index 38d317146c7..f0e1f89260a 100644
--- a/chromium/content/browser/background_sync/background_sync_context.h
+++ b/chromium/content/browser/background_sync/background_sync_context.h
@@ -9,7 +9,7 @@
#include <memory>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_delete_on_sequence.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/modules/background_sync/background_sync.mojom.h"
@@ -23,8 +23,10 @@ class ServiceWorkerContextWrapper;
// processes/origins. Most logic is delegated to the owned BackgroundSyncManager
// instance, which is only accessed on the IO thread.
class CONTENT_EXPORT BackgroundSyncContext
- : public base::RefCountedThreadSafe<BackgroundSyncContext> {
+ : public base::RefCountedDeleteOnSequence<BackgroundSyncContext> {
public:
+ REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+
BackgroundSyncContext();
// Init and Shutdown are for use on the UI thread when the
@@ -46,7 +48,8 @@ class CONTENT_EXPORT BackgroundSyncContext
BackgroundSyncManager* background_sync_manager() const;
protected:
- friend class base::RefCountedThreadSafe<BackgroundSyncContext>;
+ friend class base::RefCountedDeleteOnSequence<BackgroundSyncContext>;
+ friend class base::DeleteHelper<BackgroundSyncContext>;
virtual ~BackgroundSyncContext();
void set_background_sync_manager_for_testing(
diff --git a/chromium/content/browser/background_sync/background_sync_manager.cc b/chromium/content/browser/background_sync/background_sync_manager.cc
index 0c6fe683b64..62d6f5a2d7d 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager.cc
@@ -279,10 +279,30 @@ void BackgroundSyncManager::EmulateDispatchSyncEvent(
bool last_chance,
ServiceWorkerVersion::StatusCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ServiceWorkerStatusCode code = CanEmulateSyncEvent(active_version);
+ if (code != SERVICE_WORKER_OK) {
+ std::move(callback).Run(code);
+ return;
+ }
DispatchSyncEvent(tag, std::move(active_version), last_chance,
std::move(callback));
}
+void BackgroundSyncManager::EmulateServiceWorkerOffline(
+ int64_t service_worker_id,
+ bool is_offline) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Multiple DevTools sessions may want to set the same SW offline, which
+ // is supposed to disable the background sync. For consistency with the
+ // network stack, SW remains offline until all DevTools sessions disable
+ // the offline mode.
+ emulated_offline_sw_[service_worker_id] += is_offline ? 1 : -1;
+ if (emulated_offline_sw_[service_worker_id] > 0)
+ return;
+ emulated_offline_sw_.erase(service_worker_id);
+ FireReadyEvents();
+}
+
BackgroundSyncManager::BackgroundSyncManager(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
: op_scheduler_(CacheStorageSchedulerClient::CLIENT_BACKGROUND_SYNC),
@@ -845,7 +865,8 @@ bool BackgroundSyncManager::AreOptionConditionsMet(
}
bool BackgroundSyncManager::IsRegistrationReadyToFire(
- const BackgroundSyncRegistration& registration) {
+ const BackgroundSyncRegistration& registration,
+ int64_t service_worker_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (registration.sync_state() != blink::mojom::BackgroundSyncState::PENDING)
@@ -854,6 +875,9 @@ bool BackgroundSyncManager::IsRegistrationReadyToFire(
if (clock_->Now() < registration.delay_until())
return false;
+ if (base::ContainsKey(emulated_offline_sw_, service_worker_id))
+ return false;
+
return AreOptionConditionsMet(*registration.options());
}
@@ -933,7 +957,8 @@ void BackgroundSyncManager::FireReadyEventsImpl(base::OnceClosure callback) {
for (auto& key_and_registration :
sw_id_and_registrations.second.registration_map) {
BackgroundSyncRegistration* registration = &key_and_registration.second;
- if (IsRegistrationReadyToFire(*registration)) {
+
+ if (IsRegistrationReadyToFire(*registration, service_worker_id)) {
sw_id_and_tags_to_fire.push_back(
std::make_pair(service_worker_id, key_and_registration.first));
// The state change is not saved to persistent storage because
@@ -1202,4 +1227,16 @@ base::OnceClosure BackgroundSyncManager::MakeEmptyCompletion() {
return op_scheduler_.WrapCallbackToRunNext(base::DoNothing::Once());
}
+ServiceWorkerStatusCode BackgroundSyncManager::CanEmulateSyncEvent(
+ scoped_refptr<ServiceWorkerVersion> active_version) {
+ if (!active_version)
+ return SERVICE_WORKER_ERROR_FAILED;
+ if (!network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE))
+ return SERVICE_WORKER_ERROR_NETWORK;
+ int64_t registration_id = active_version->registration_id();
+ if (base::ContainsKey(emulated_offline_sw_, registration_id))
+ return SERVICE_WORKER_ERROR_NETWORK;
+ return SERVICE_WORKER_OK;
+}
+
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_manager.h b/chromium/content/browser/background_sync/background_sync_manager.h
index 797e632efd5..38091eaa269 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.h
+++ b/chromium/content/browser/background_sync/background_sync_manager.h
@@ -107,6 +107,9 @@ class CONTENT_EXPORT BackgroundSyncManager
bool last_chance,
ServiceWorkerVersion::StatusCallback callback);
+ // Called from DevTools to toggle service worker "offline" status
+ void EmulateServiceWorkerOffline(int64_t service_worker_id, bool is_offline);
+
protected:
explicit BackgroundSyncManager(
scoped_refptr<ServiceWorkerContextWrapper> context);
@@ -223,8 +226,8 @@ class CONTENT_EXPORT BackgroundSyncManager
StatusAndRegistrationsCallback callback);
bool AreOptionConditionsMet(const BackgroundSyncRegistrationOptions& options);
- bool IsRegistrationReadyToFire(
- const BackgroundSyncRegistration& registration);
+ bool IsRegistrationReadyToFire(const BackgroundSyncRegistration& registration,
+ int64_t service_worker_id);
// Determines if the browser needs to be able to run in the background (e.g.,
// to run a pending registration or verify that a firing registration
@@ -282,6 +285,9 @@ class CONTENT_EXPORT BackgroundSyncManager
base::OnceClosure MakeEmptyCompletion();
+ ServiceWorkerStatusCode CanEmulateSyncEvent(
+ scoped_refptr<ServiceWorkerVersion> active_version);
+
SWIdToRegistrationsMap active_registrations_;
CacheStorageScheduler op_scheduler_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
@@ -300,6 +306,8 @@ class CONTENT_EXPORT BackgroundSyncManager
base::Clock* clock_;
+ std::map<int64_t, int> emulated_offline_sw_;
+
base::WeakPtrFactory<BackgroundSyncManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncManager);
diff --git a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
index 554c5ee9798..5fc543bee78 100644
--- a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -392,7 +392,7 @@ class BackgroundSyncManagerTest : public testing::Test {
EXPECT_TRUE(Register(sync_options));
EXPECT_EQ(sync_events_called + 1, sync_events_called_);
- EXPECT_TRUE(GetRegistration(sync_options_1_));
+ EXPECT_TRUE(GetRegistration(sync_options));
EXPECT_TRUE(sync_fired_callback_);
}
@@ -1348,4 +1348,114 @@ TEST_F(BackgroundSyncManagerTest, LastChance) {
EXPECT_TRUE(test_background_sync_manager_->last_chance());
}
+TEST_F(BackgroundSyncManagerTest, EmulateOfflineSingleClient) {
+ InitSyncEventTest();
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ true);
+ EXPECT_TRUE(Register(sync_options_1_));
+ EXPECT_EQ(0, sync_events_called_);
+ EXPECT_TRUE(GetRegistration(sync_options_1_));
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ false);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, sync_events_called_);
+ EXPECT_FALSE(GetRegistration(sync_options_1_));
+
+ EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_EQ(2, sync_events_called_);
+ EXPECT_FALSE(GetRegistration(sync_options_2_));
+}
+
+TEST_F(BackgroundSyncManagerTest, EmulateOfflineMultipleClients) {
+ InitSyncEventTest();
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ true);
+ EXPECT_TRUE(Register(sync_options_1_));
+ EXPECT_EQ(0, sync_events_called_);
+ EXPECT_TRUE(GetRegistration(sync_options_1_));
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ true);
+
+ EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_EQ(0, sync_events_called_);
+ EXPECT_TRUE(GetRegistration(sync_options_2_));
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ false);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, sync_events_called_);
+ EXPECT_TRUE(GetRegistration(sync_options_1_));
+ EXPECT_TRUE(GetRegistration(sync_options_2_));
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ false);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(2, sync_events_called_);
+ EXPECT_FALSE(GetRegistration(sync_options_1_));
+ EXPECT_FALSE(GetRegistration(sync_options_2_));
+}
+
+static void EmulateDispatchSyncEventCallback(
+ bool* was_called,
+ ServiceWorkerStatusCode* code,
+ ServiceWorkerStatusCode status_code) {
+ *was_called = true;
+ *code = status_code;
+}
+
+TEST_F(BackgroundSyncManagerTest, EmulateDispatchSyncEvent) {
+ InitSyncEventTest();
+ bool was_called = false;
+ ServiceWorkerStatusCode code = SERVICE_WORKER_ERROR_MAX_VALUE;
+ background_sync_manager_->EmulateDispatchSyncEvent(
+ "emulated_tag", sw_registration_1_->active_version(), false,
+ base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_OK, code);
+
+ EXPECT_EQ(1, sync_events_called_);
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ true);
+
+ was_called = false;
+ code = SERVICE_WORKER_ERROR_MAX_VALUE;
+ background_sync_manager_->EmulateDispatchSyncEvent(
+ "emulated_tag", sw_registration_1_->active_version(), false,
+ base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, code);
+
+ background_sync_manager_->EmulateServiceWorkerOffline(sw_registration_id_1_,
+ false);
+
+ SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
+ was_called = false;
+ code = SERVICE_WORKER_ERROR_MAX_VALUE;
+ background_sync_manager_->EmulateDispatchSyncEvent(
+ "emulated_tag", sw_registration_1_->active_version(), false,
+ base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, code);
+
+ SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ was_called = false;
+ code = SERVICE_WORKER_ERROR_MAX_VALUE;
+ background_sync_manager_->EmulateDispatchSyncEvent(
+ "emulated_tag", sw_registration_1_->active_version(), false,
+ base::BindOnce(EmulateDispatchSyncEventCallback, &was_called, &code));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_OK, code);
+
+ EXPECT_EQ(2, sync_events_called_);
+}
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc b/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
index 6cbdfccaf3b..aecf773c011 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
@@ -142,7 +142,8 @@ class BackgroundSyncServiceImplTest : public testing::Test {
void CreateBackgroundSyncContext() {
// Registering for background sync includes a check for having a same-origin
// main frame. Use a test context that allows control over that check.
- background_sync_context_ = new TestBackgroundSyncContext();
+ background_sync_context_ =
+ base::MakeRefCounted<TestBackgroundSyncContext>();
background_sync_context_->Init(embedded_worker_helper_->context_wrapper());
// Tests do not expect the sync event to fire immediately after
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index 80ab47d8248..20115161d55 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -52,7 +52,7 @@ enum BadMessageReason {
OBSOLETE_DBMF_DB_NOT_OPEN_ON_CLOSE = 25,
OBSOLETE_DBMF_INVALID_ORIGIN_ON_SQLITE_ERROR = 26,
RDH_INVALID_PRIORITY = 27,
- RDH_REQUEST_NOT_TRANSFERRING = 28,
+ OBSOLETE_RDH_REQUEST_NOT_TRANSFERRING = 28,
RDH_BAD_DOWNLOAD = 29,
OBSOLETE_NMF_NO_PERMISSION_SHOW = 30,
OBSOLETE_NMF_NO_PERMISSION_CLOSE = 31,
@@ -130,8 +130,8 @@ enum BadMessageReason {
DWNLD_INVALID_SAVABLE_RESOURCE_LINKS_RESPONSE = 103,
DWNLD_INVALID_SERIALIZE_AS_MHTML_RESPONSE = 104,
BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN = 105,
- ACI_WRONG_STORAGE_PARTITION = 106,
- RDHI_WRONG_STORAGE_PARTITION = 107,
+ OBSOLETE_ACI_WRONG_STORAGE_PARTITION = 106,
+ OBSOLETE_RDHI_WRONG_STORAGE_PARTITION = 107,
RDH_INVALID_REQUEST_ID = 108,
BDH_SERVICE_NOT_ALLOWED_FOR_ORIGIN = 109,
WSI_UNEXPECTED_ADD_CHANNEL_REQUEST = 110,
@@ -151,7 +151,7 @@ enum BadMessageReason {
OBSOLETE_DBMF_INVALID_ORIGIN_ON_GET_SPACE = 124,
OBSOLETE_DBMF_INVALID_ORIGIN_ON_MODIFIED = 125,
OBSOLETE_DBMF_INVALID_ORIGIN_ON_CLOSED = 126,
- WSI_INVALID_HEADER_VALUE = 127,
+ OBSOLETE_WSI_INVALID_HEADER_VALUE = 127,
OBSOLETE_SWDH_SET_HOSTED_VERSION_INVALID_HOST = 128,
OBSOLETE_SWDH_SET_HOSTED_VERSION_PROCESS_MISMATCH = 129,
OBSOLETE_MSDH_INVALID_FRAME_ID = 130,
@@ -170,8 +170,9 @@ enum BadMessageReason {
OBSOLETE_SWDH_ENABLE_NAVIGATION_PRELOAD_NO_HOST = 143,
OBSOLETE_SWDH_ENABLE_NAVIGATION_PRELOAD_INVALID_ORIGIN = 144,
OBSOLETE_SWDH_ENABLE_NAVIGATION_PRELOAD_BAD_REGISTRATION_ID = 145,
- RDH_TRANSFERRING_REQUEST_NOT_FOUND = 146, // Disabled - crbug.com/659613.
- RDH_TRANSFERRING_NONNAVIGATIONAL_REQUEST = 147,
+ OBSOLETE_RDH_TRANSFERRING_REQUEST_NOT_FOUND =
+ 146, // Disabled - crbug.com/659613.
+ OBSOLETE_RDH_TRANSFERRING_NONNAVIGATIONAL_REQUEST = 147,
OBSOLETE_SWDH_GET_NAVIGATION_PRELOAD_STATE_NO_HOST = 148,
OBSOLETE_SWDH_GET_NAVIGATION_PRELOAD_STATE_INVALID_ORIGIN = 149,
OBSOLETE_SWDH_GET_NAVIGATION_PRELOAD_STATE_BAD_REGISTRATION_ID = 150,
@@ -225,6 +226,10 @@ enum BadMessageReason {
SYNC_COMPOSITOR_NO_FUTURE_FRAME = 198,
SYNC_COMPOSITOR_NO_BEGIN_FRAME = 199,
WEBUI_BAD_HOST_ACCESS = 200,
+ RFMF_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 201,
+ PERMISSION_SERVICE_BAD_PERMISSION_DESCRIPTOR = 202,
+ RFH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 203,
+ RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 204,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/chromium/content/browser/blob_storage/blob_url_unittest.cc b/chromium/content/browser/blob_storage/blob_url_unittest.cc
index 82e79a3125b..e7d27de9650 100644
--- a/chromium/content/browser/blob_storage/blob_url_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_url_unittest.cc
@@ -13,7 +13,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
index 0b5780dfe11..17347dbfd10 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -19,12 +19,12 @@
#include "base/task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "content/browser/resource_context_impl.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_impl.h"
#include "storage/browser/blob/blob_memory_controller.h"
@@ -174,27 +174,6 @@ std::unique_ptr<BlobHandle> ChromeBlobStorageContext::CreateMemoryBackedBlob(
return blob_handle;
}
-std::unique_ptr<BlobHandle> ChromeBlobStorageContext::CreateFileBackedBlob(
- const FilePath& path,
- int64_t offset,
- int64_t size,
- const base::Time& expected_modification_time) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- std::string uuid(base::GenerateGUID());
- auto blob_data_builder = std::make_unique<storage::BlobDataBuilder>(uuid);
- blob_data_builder->AppendFile(path, offset, size, expected_modification_time);
-
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle =
- context_->AddFinishedBlob(std::move(blob_data_builder));
- if (!blob_data_handle)
- return std::unique_ptr<BlobHandle>();
-
- std::unique_ptr<BlobHandle> blob_handle(
- new BlobHandleImpl(std::move(blob_data_handle)));
- return blob_handle;
-}
-
// static
scoped_refptr<network::SharedURLLoaderFactory>
ChromeBlobStorageContext::URLLoaderFactoryForToken(
@@ -214,7 +193,7 @@ ChromeBlobStorageContext::URLLoaderFactoryForToken(
},
base::WrapRefCounted(GetFor(browser_context)),
MakeRequest(&blob_url_loader_factory_ptr), token.PassInterface()));
- return base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
+ return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(blob_url_loader_factory_ptr));
}
diff --git a/chromium/content/browser/blob_storage/chrome_blob_storage_context.h b/chromium/content/browser/blob_storage/chrome_blob_storage_context.h
index 043d968ca6a..812a6a5cebe 100644
--- a/chromium/content/browser/blob_storage/chrome_blob_storage_context.h
+++ b/chromium/content/browser/blob_storage/chrome_blob_storage_context.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 CONTENT_BROWSER_FILEAPI_CHROME_BLOB_STORAGE_CONTEXT_H_
-#define CONTENT_BROWSER_FILEAPI_CHROME_BLOB_STORAGE_CONTEXT_H_
+#ifndef CONTENT_BROWSER_BLOB_STORAGE_CHROME_BLOB_STORAGE_CONTEXT_H_
+#define CONTENT_BROWSER_BLOB_STORAGE_CHROME_BLOB_STORAGE_CONTEXT_H_
#include <stddef.h>
#include <stdint.h>
@@ -20,9 +20,7 @@
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
namespace base {
-class FilePath;
class TaskRunner;
-class Time;
}
namespace network {
@@ -67,13 +65,6 @@ class CONTENT_EXPORT ChromeBlobStorageContext
size_t length,
const std::string& content_type);
- // Returns a NULL scoped_ptr on failure.
- std::unique_ptr<BlobHandle> CreateFileBackedBlob(
- const base::FilePath& path,
- int64_t offset,
- int64_t size,
- const base::Time& expected_modification_time);
-
// Must be called on the UI thread.
static scoped_refptr<network::SharedURLLoaderFactory>
URLLoaderFactoryForToken(BrowserContext* browser_context,
@@ -117,4 +108,4 @@ extern const char kBlobStorageContextKeyName[];
} // namespace content
-#endif // CONTENT_BROWSER_FILEAPI_CHROME_BLOB_STORAGE_CONTEXT_H_
+#endif // CONTENT_BROWSER_BLOB_STORAGE_CHROME_BLOB_STORAGE_CONTEXT_H_
diff --git a/chromium/content/browser/browser_associated_interface_unittest.cc b/chromium/content/browser/browser_associated_interface_unittest.cc
index 0de9b41eb07..8e3a8041c0c 100644
--- a/chromium/content/browser/browser_associated_interface_unittest.cc
+++ b/chromium/content/browser/browser_associated_interface_unittest.cc
@@ -149,7 +149,7 @@ class TestClientRunner {
proxy.channel()->Send(message.release());
}
- driver->RequestQuit(base::MessageLoop::QuitWhenIdleClosure());
+ driver->RequestQuit(base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).Run();
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index dcf54720afd..1686c7a9f2b 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -25,7 +25,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "components/tracing/common/trace_config_file.h"
+#include "components/tracing/common/trace_startup_config.h"
#include "components/tracing/common/tracing_switches.h"
#include "content/browser/bad_message.h"
#include "content/browser/browser_main_loop.h"
@@ -43,7 +43,6 @@
#include "content/public/common/connection_filter.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_channel_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
@@ -82,14 +81,18 @@ void NotifyProcessHostDisconnected(const ChildProcessData& data) {
observer.BrowserChildProcessHostDisconnected(data);
}
-void NotifyProcessCrashed(const ChildProcessData& data, int exit_code) {
+#if !defined(OS_ANDROID)
+void NotifyProcessCrashed(const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) {
for (auto& observer : g_browser_child_process_observers.Get())
- observer.BrowserChildProcessCrashed(data, exit_code);
+ observer.BrowserChildProcessCrashed(data, info);
}
+#endif
-void NotifyProcessKilled(const ChildProcessData& data, int exit_code) {
+void NotifyProcessKilled(const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) {
for (auto& observer : g_browser_child_process_observers.Get())
- observer.BrowserChildProcessKilled(data, exit_code);
+ observer.BrowserChildProcessKilled(data, info);
}
} // namespace
@@ -213,24 +216,9 @@ void BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(
// static
void BrowserChildProcessHostImpl::CopyTraceStartupFlags(
base::CommandLine* cmd_line) {
- const base::CommandLine& browser_cmd_line =
- *base::CommandLine::ForCurrentProcess();
-
- if (browser_cmd_line.HasSwitch(switches::kTraceStartup) &&
- BrowserMainLoop::GetInstance()->is_tracing_startup_for_duration()) {
- // Pass kTraceStartup switch to renderer only if startup tracing has not
- // finished.
- cmd_line->AppendSwitchASCII(
- switches::kTraceStartup,
- browser_cmd_line.GetSwitchValueASCII(switches::kTraceStartup));
- if (browser_cmd_line.HasSwitch(switches::kTraceStartupRecordMode)) {
- cmd_line->AppendSwitchASCII(switches::kTraceStartupRecordMode,
- browser_cmd_line.GetSwitchValueASCII(
- switches::kTraceStartupRecordMode));
- }
- } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) {
+ if (tracing::TraceStartupConfig::GetInstance()->IsEnabled()) {
const auto trace_config =
- tracing::TraceConfigFile::GetInstance()->GetTraceConfig();
+ tracing::TraceStartupConfig::GetInstance()->GetTraceConfig();
if (!trace_config.IsArgumentFilterEnabled()) {
// The only trace option that we can pass through switches is the record
// mode. Other trace options should have the default value.
@@ -274,8 +262,9 @@ void BrowserChildProcessHostImpl::Launch(
arraysize(kForwardSwitches));
if (child_connection_) {
- cmd_line->AppendSwitchASCII(switches::kServiceRequestChannelToken,
- child_connection_->service_token());
+ cmd_line->AppendSwitchASCII(
+ service_manager::switches::kServiceRequestChannelToken,
+ child_connection_->service_token());
}
DCHECK(broker_client_invitation_);
@@ -358,13 +347,16 @@ void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
PROCESS_TYPE_MAX);
}
-base::TerminationStatus BrowserChildProcessHostImpl::GetTerminationStatus(
- bool known_dead, int* exit_code) {
+ChildProcessTerminationInfo BrowserChildProcessHostImpl::GetTerminationInfo(
+ bool known_dead) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!child_process_) // If the delegate doesn't use Launch() helper.
- return base::GetTerminationStatus(data_.handle, exit_code);
- return child_process_->GetChildTerminationStatus(known_dead,
- exit_code);
+ if (!child_process_) {
+ // If the delegate doesn't use Launch() helper.
+ ChildProcessTerminationInfo info;
+ info.status = base::GetTerminationStatus(data_.handle, &info.exit_code);
+ return info;
+ }
+ return child_process_->GetChildTerminationInfo(known_dead);
}
bool BrowserChildProcessHostImpl::OnMessageReceived(
@@ -424,7 +416,7 @@ void BrowserChildProcessHostImpl::TerminateOnBadMessageReceived(
// what the bad message was.
base::debug::DumpWithoutCrashing();
- child_process_->GetProcess().Terminate(RESULT_CODE_KILLED_BAD_MESSAGE, false);
+ child_process_->Terminate(RESULT_CODE_KILLED_BAD_MESSAGE);
}
void BrowserChildProcessHostImpl::OnChannelInitialized(IPC::Channel* channel) {
@@ -439,32 +431,33 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
early_exit_watcher_.StopWatching();
#endif
if (child_process_.get() || data_.handle) {
- int exit_code;
- base::TerminationStatus status = GetTerminationStatus(
- true /* known_dead */, &exit_code);
- switch (status) {
+ ChildProcessTerminationInfo info =
+ GetTerminationInfo(true /* known_dead */);
+#if defined(OS_ANDROID)
+ delegate_->OnProcessCrashed(info.exit_code);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NotifyProcessKilled, data_, info));
+#else // OS_ANDROID
+ switch (info.status) {
case base::TERMINATION_STATUS_PROCESS_CRASHED:
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
- delegate_->OnProcessCrashed(exit_code);
+ delegate_->OnProcessCrashed(info.exit_code);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessCrashed, data_, exit_code));
+ base::BindOnce(&NotifyProcessCrashed, data_, info));
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed2",
static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
break;
}
-#if defined(OS_ANDROID)
- case base::TERMINATION_STATUS_OOM_PROTECTED:
-#endif
#if defined(OS_CHROMEOS)
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
- delegate_->OnProcessCrashed(exit_code);
+ delegate_->OnProcessCrashed(info.exit_code);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NotifyProcessKilled, data_, exit_code));
+ base::BindOnce(&NotifyProcessKilled, data_, info));
// Report that this child process was killed.
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2",
static_cast<ProcessType>(data_.process_type),
@@ -480,11 +473,12 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
default:
break;
}
+#endif // OS_ANDROID
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected2",
static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
#if defined(OS_CHROMEOS)
- if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) {
+ if (info.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) {
UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed2.OOM",
static_cast<ProcessType>(data_.process_type),
PROCESS_TYPE_MAX);
@@ -646,8 +640,7 @@ void BrowserChildProcessHostImpl::OnMojoError(
base::debug::ScopedCrashKeyString scoped_error_key(
bad_message::GetMojoErrorCrashKey(), error);
base::debug::DumpWithoutCrashing();
- process->child_process_->GetProcess().Terminate(
- RESULT_CODE_KILLED_BAD_MESSAGE, false);
+ process->child_process_->Terminate(RESULT_CODE_KILLED_BAD_MESSAGE);
}
#if defined(OS_WIN)
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index 5dc64aa2224..ee21de31936 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -75,8 +75,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
bool terminate_on_shutdown) override;
const ChildProcessData& GetData() const override;
ChildProcessHost* GetHost() const override;
- base::TerminationStatus GetTerminationStatus(bool known_dead,
- int* exit_code) override;
+ ChildProcessTerminationInfo GetTerminationInfo(bool known_dead) override;
std::unique_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator()
override;
void SetName(const base::string16& name) override;
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index 15cb62d76bb..69271e39f27 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -24,6 +24,7 @@
#include "base/rand_util.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browsing_data/browsing_data_remover_impl.h"
@@ -338,26 +339,6 @@ void BrowserContext::CreateMemoryBackedBlob(BrowserContext* browser_context,
}
// static
-void BrowserContext::CreateFileBackedBlob(
- BrowserContext* browser_context,
- const base::FilePath& path,
- int64_t offset,
- int64_t size,
- const base::Time& expected_modification_time,
- BlobCallback callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- ChromeBlobStorageContext* blob_context =
- ChromeBlobStorageContext::GetFor(browser_context);
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ChromeBlobStorageContext::CreateFileBackedBlob,
- base::WrapRefCounted(blob_context), path, offset, size,
- expected_modification_time),
- std::move(callback));
-}
-
-// static
BrowserContext::BlobContextGetter BrowserContext::GetBlobStorageContext(
BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -535,14 +516,12 @@ void BrowserContext::Initialize(
connection->Start();
}
-#if BUILDFLAG(ENABLE_WEBRTC)
if (!browser_context->IsOffTheRecord()) {
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
logger->EnableForBrowserContext(browser_context);
}
}
-#endif
}
// static
@@ -583,7 +562,7 @@ ServiceManagerConnection* BrowserContext::GetServiceManagerConnectionFor(
}
BrowserContext::BrowserContext()
- : media_device_id_salt_(CreateRandomMediaDeviceIDSalt()) {}
+ : unique_id_(base::UnguessableToken::Create().ToString()) {}
BrowserContext::~BrowserContext() {
CHECK(GetUserData(kMojoWasInitialized))
@@ -595,12 +574,10 @@ BrowserContext::~BrowserContext() {
DCHECK(was_notify_will_be_destroyed_called_);
-#if BUILDFLAG(ENABLE_WEBRTC)
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
logger->DisableForBrowserContext(this);
}
-#endif
RemoveBrowserContextFromUserIdMap(this);
@@ -614,15 +591,16 @@ void BrowserContext::ShutdownStoragePartitions() {
}
std::string BrowserContext::GetMediaDeviceIDSalt() {
- return media_device_id_salt_;
+ return unique_id_;
}
// static
std::string BrowserContext::CreateRandomMediaDeviceIDSalt() {
- std::string salt;
- base::Base64Encode(base::RandBytesAsString(16), &salt);
- DCHECK(!salt.empty());
- return salt;
+ return base::UnguessableToken::Create().ToString();
+}
+
+const std::string& BrowserContext::UniqueId() const {
+ return unique_id_;
}
media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
diff --git a/chromium/content/browser/browser_main.cc b/chromium/content/browser/browser_main.cc
index d706269f9db..f06e59b43ff 100644
--- a/chromium/content/browser/browser_main.cc
+++ b/chromium/content/browser/browser_main.cc
@@ -7,8 +7,9 @@
#include <memory>
#include "base/trace_event/trace_event.h"
+#include "content/browser/browser_main_runner_impl.h"
+#include "content/browser/browser_process_sub_thread.h"
#include "content/common/content_constants_internal.h"
-#include "content/public/browser/browser_main_runner.h"
namespace content {
@@ -30,16 +31,20 @@ class ScopedBrowserMainEvent {
} // namespace
// Main routine for running as the Browser process.
-int BrowserMain(const MainFunctionParams& parameters) {
+int BrowserMain(
+ const MainFunctionParams& parameters,
+ std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
ScopedBrowserMainEvent scoped_browser_main_event;
base::trace_event::TraceLog::GetInstance()->set_process_name("Browser");
base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
kTraceEventBrowserProcessSortIndex);
- std::unique_ptr<BrowserMainRunner> main_runner(BrowserMainRunner::Create());
+ std::unique_ptr<BrowserMainRunnerImpl> main_runner(
+ BrowserMainRunnerImpl::Create());
- int exit_code = main_runner->Initialize(parameters);
+ int exit_code =
+ main_runner->Initialize(parameters, std::move(service_manager_thread));
if (exit_code >= 0)
return exit_code;
diff --git a/chromium/content/browser/browser_main.h b/chromium/content/browser/browser_main.h
index 8fab146352a..02f3af601fe 100644
--- a/chromium/content/browser/browser_main.h
+++ b/chromium/content/browser/browser_main.h
@@ -5,13 +5,18 @@
#ifndef CONTENT_BROWSER_BROWSER_MAIN_H_
#define CONTENT_BROWSER_BROWSER_MAIN_H_
+#include <memory>
+
#include "content/common/content_export.h"
namespace content {
+class BrowserProcessSubThread;
struct MainFunctionParams;
-CONTENT_EXPORT int BrowserMain(const content::MainFunctionParams& parameters);
+CONTENT_EXPORT int BrowserMain(
+ const content::MainFunctionParams& parameters,
+ std::unique_ptr<BrowserProcessSubThread> service_manager_thread);
} // namespace content
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 81c93e51b65..10de251accf 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
+#include "base/debug/stack_trace.h"
#include "base/deferred_sequenced_task_runner.h"
#include "base/feature_list.h"
#include "base/location.h"
@@ -23,6 +24,7 @@
#include "base/memory/memory_coordinator_proxy.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
@@ -46,7 +48,7 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
-#include "components/tracing/common/trace_config_file.h"
+#include "components/tracing/common/trace_startup_config.h"
#include "components/tracing/common/trace_to_console.h"
#include "components/tracing/common/tracing_switches.h"
#include "components/viz/common/features.h"
@@ -55,7 +57,6 @@
#include "components/viz/service/display_embedder/compositing_mode_reporter_impl.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
-#include "content/browser/browser_process_sub_thread.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/compositor/gpu_process_transport_factory.h"
@@ -87,6 +88,7 @@
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/tracing/tracing_controller_impl.h"
#include "content/browser/utility_process_host.h"
+#include "content/browser/webrtc/webrtc_internals.h"
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "content/browser/webui/url_data_manager.h"
#include "content/common/content_switches_internal.h"
@@ -105,9 +107,7 @@
#include "content/public/common/main_function_params.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/service_names.mojom.h"
-#include "content/public/common/zygote_buildflags.h"
#include "device/gamepad/gamepad_service.h"
-#include "gpu/vulkan/buildflags.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_system.h"
#include "media/audio/audio_thread_impl.h"
@@ -118,15 +118,18 @@
#include "media/mojo/buildflags.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/scoped_ipc_support.h"
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
#include "net/ssl/ssl_config_service.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/audio/public/cpp/audio_system_factory.h"
+#include "services/audio/public/mojom/constants.mojom.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
#include "services/service_manager/runner/common/client_util.h"
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
#include "skia/ext/event_tracer_impl.h"
#include "skia/ext/skia_memory_dump_provider.h"
#include "sql/sql_memory_dump_provider.h"
@@ -160,7 +163,6 @@
#endif
#if defined(OS_MACOSX)
-#include "base/allocator/allocator_interception_mac.h"
#include "base/memory/memory_pressure_monitor_mac.h"
#include "content/browser/cocoa/system_hotkey_helper_mac.h"
#include "content/browser/mach_broker_mac.h"
@@ -217,10 +219,6 @@
#include "content/browser/media/cdm_registry_impl.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "content/browser/webrtc/webrtc_internals.h"
-#endif
-
#if defined(USE_X11)
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "ui/base/x/x11_util_internal.h" // nogncheck
@@ -232,10 +230,6 @@
#include "crypto/nss_util.h"
#endif
-#if BUILDFLAG(ENABLE_VULKAN)
-#include "gpu/vulkan/vulkan_implementation.h"
-#endif
-
#if BUILDFLAG(ENABLE_MUS)
#include "services/ui/common/image_cursors_set.h"
#endif
@@ -267,6 +261,12 @@ static void GLibLogHandler(const gchar* log_domain,
LOG(DFATAL) << log_domain << ": " << message;
} else if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL)) {
LOG(ERROR) << log_domain << ": " << message;
+#if defined(THREAD_SANITIZER)
+ // TODO(thomasanderson): This is temporary debugging for
+ // https://crbug.com/821704. Revert this CL once we have the stack trace:
+ // https://chromium-review.googlesource.com/#/c/chromium/src/+/1069247
+ base::debug::StackTrace().Print();
+#endif
} else if (log_level & (G_LOG_LEVEL_WARNING)) {
LOG(WARNING) << log_domain << ": " << message;
} else if (log_level &
@@ -456,13 +456,13 @@ class HDRProxy {
public:
static void Initialize() {
display::win::ScreenWin::SetRequestHDRStatusCallback(
- base::Bind(&HDRProxy::RequestHDRStatus));
+ base::BindRepeating(&HDRProxy::RequestHDRStatus));
}
static void RequestHDRStatus() {
// The request must be sent to the GPU process from the IO thread.
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&HDRProxy::RequestOnIOThread));
+ base::BindOnce(&HDRProxy::RequestOnIOThread));
}
private:
@@ -471,7 +471,7 @@ class HDRProxy {
GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, false);
if (gpu_process_host) {
gpu_process_host->RequestHDRStatus(
- base::Bind(&HDRProxy::GotResultOnIOThread));
+ base::BindRepeating(&HDRProxy::GotResultOnIOThread));
} else {
bool hdr_enabled = false;
GotResultOnIOThread(hdr_enabled);
@@ -479,7 +479,7 @@ class HDRProxy {
}
static void GotResultOnIOThread(bool hdr_enabled) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&HDRProxy::GotResult, hdr_enabled));
+ base::BindOnce(&HDRProxy::GotResult, hdr_enabled));
}
static void GotResult(bool hdr_enabled) {
display::win::ScreenWin::SetHDREnabled(hdr_enabled);
@@ -506,14 +506,8 @@ BrowserMainLoop* BrowserMainLoop::GetInstance() {
BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
: parameters_(parameters),
parsed_command_line_(parameters.command_line),
- result_code_(RESULT_CODE_NORMAL_EXIT),
- created_threads_(false),
- // ContentMainRunner should have enabled tracing of the browser process
- // when kTraceStartup or kTraceConfigFile is in the command line.
- is_tracing_startup_for_duration_(
- parameters.command_line.HasSwitch(switches::kTraceStartup) ||
- (tracing::TraceConfigFile::GetInstance()->IsEnabled() &&
- tracing::TraceConfigFile::GetInstance()->GetStartupDuration() > 0)) {
+ result_code_(service_manager::RESULT_CODE_NORMAL_EXIT),
+ created_threads_(false) {
DCHECK(!g_current_browser_main_loop);
g_current_browser_main_loop = this;
@@ -530,9 +524,13 @@ BrowserMainLoop::~BrowserMainLoop() {
g_current_browser_main_loop = nullptr;
}
-void BrowserMainLoop::Init() {
+void BrowserMainLoop::Init(
+ std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
TRACE_EVENT0("startup", "BrowserMainLoop::Init");
+ // This is always invoked before |io_thread_| is initialized (i.e. never
+ // resets it).
+ io_thread_ = std::move(service_manager_thread);
parts_.reset(
GetContentClient()->browser()->CreateBrowserMainParts(parameters_));
}
@@ -585,7 +583,7 @@ int BrowserMainLoop::EarlyInitialization() {
}
#endif
const int pre_early_init_error_code = parts_->PreEarlyInitialization();
- if (pre_early_init_error_code != content::RESULT_CODE_NORMAL_EXIT)
+ if (pre_early_init_error_code != service_manager::RESULT_CODE_NORMAL_EXIT)
return pre_early_init_error_code;
}
@@ -599,7 +597,8 @@ int BrowserMainLoop::EarlyInitialization() {
command_line->GetSwitchValueASCII(switches::kDisableFeatures));
}
-#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
+ defined(OS_ANDROID)
// We use quite a few file descriptors for our IPC as well as disk the disk
// cache,and the default limit on the Mac is low (256), so bump it up.
@@ -607,8 +606,9 @@ int BrowserMainLoop::EarlyInitialization() {
// Low soft limits combined with liberal use of file descriptors means power
// users can easily hit this limit with many open tabs. Bump up the limit to
// an arbitrarily high number. See https://crbug.com/539567
- base::SetFdLimit(8192);
-#endif // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_CHROMEOS)
+ base::IncreaseFdLimitTo(8192);
+#endif // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_CHROMEOS) ||
+ // defined(OS_ANDROID)
#if defined(OS_WIN)
net::EnsureWinsockInit();
@@ -635,7 +635,7 @@ int BrowserMainLoop::EarlyInitialization() {
if (parts_)
parts_->PostEarlyInitialization();
- return content::RESULT_CODE_NORMAL_EXIT;
+ return service_manager::RESULT_CODE_NORMAL_EXIT;
}
void BrowserMainLoop::PreMainMessageLoopStart() {
@@ -653,7 +653,7 @@ void BrowserMainLoop::MainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart");
// Create a MessageLoop if one does not already exist for the current thread.
- if (!base::MessageLoop::current())
+ if (!base::MessageLoopCurrent::Get())
main_message_loop_.reset(new base::MessageLoopForUI);
InitializeMainThread();
@@ -661,11 +661,6 @@ void BrowserMainLoop::MainMessageLoopStart() {
void BrowserMainLoop::PostMainMessageLoopStart() {
{
- TRACE_EVENT0("startup",
- "BrowserMainLoop::Subsystem:CreateBrowserThread::IO");
- InitializeIOThread();
- }
- {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:SystemMonitor");
system_monitor_.reset(new base::SystemMonitor);
}
@@ -773,14 +768,6 @@ int BrowserMainLoop::PreCreateThreads() {
InitializeMemoryManagementComponent();
-#if defined(OS_MACOSX)
- if (base::CommandLine::InitializedForCurrentProcess() &&
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableHeapProfiling)) {
- base::allocator::PeriodicallyShimNewMallocZones();
- }
-#endif
-
#if BUILDFLAG(ENABLE_PLUGINS)
// Prior to any processing happening on the IO thread, we create the
// plugin service as it is predominantly used from the IO thread,
@@ -938,12 +925,14 @@ int BrowserMainLoop::CreateThreads() {
*task_scheduler_init_params.get());
}
- // The thread used for BrowserThread::IO is created in
- // |PostMainMessageLoopStart()|, but it's only tagged as BrowserThread::IO
- // here in order to prevent any code from statically posting to it before
+ // The |io_thread| can have optionally been injected into Init(), but if not,
+ // create it here. Thre thread is only tagged as BrowserThread::IO here in
+ // order to prevent any code from statically posting to it before
// CreateThreads() (as such maintaining the invariant that PreCreateThreads()
// et al. "happen-before" BrowserThread::IO is "brought up").
- DCHECK(io_thread_);
+ if (!io_thread_) {
+ io_thread_ = BrowserProcessSubThread::CreateIOThread();
+ }
io_thread_->RegisterAsBrowserThread();
created_threads_ = true;
@@ -1143,12 +1132,17 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
}
}
-base::SequencedTaskRunner* BrowserMainLoop::audio_service_runner() {
- return audio_service_runner_.get();
+media::AudioManager* BrowserMainLoop::audio_manager() const {
+ DCHECK(audio_manager_) << "AudioManager is not instantiated - running the "
+ "audio service out of process?";
+ return audio_manager_.get();
}
-void BrowserMainLoop::InitializeIOThreadForTesting() {
- InitializeIOThread();
+base::SequencedTaskRunner* BrowserMainLoop::audio_service_runner() {
+ DCHECK(audio_service_runner_) << "The audio service task runner is not "
+ "instantiated - running the audio service "
+ "out of process?";
+ return audio_service_runner_.get();
}
#if !defined(OS_ANDROID)
@@ -1164,8 +1158,8 @@ void BrowserMainLoop::GetCompositingModeReporter(
// CompositingModeReporter.
return;
#else
- if (features::IsMusEnabled()) {
- // Mus == ChromeOS, which doesn't support software compositing, so no need
+ if (features::IsMashEnabled()) {
+ // Mash == ChromeOS, which doesn't support software compositing, so no need
// to report compositing mode.
return;
}
@@ -1184,7 +1178,7 @@ void BrowserMainLoop::InitializeMainThread() {
// Register the main thread. The main thread's task runner should already have
// been initialized in MainMessageLoopStart() (or before if
- // MessageLoop::current() was externally provided).
+ // MessageLoopCurrent::Get() was externally provided).
DCHECK(base::ThreadTaskRunnerHandle::IsSet());
main_thread_.reset(new BrowserThreadImpl(
BrowserThread::UI, base::ThreadTaskRunnerHandle::Get()));
@@ -1202,7 +1196,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
InitializeMojo();
#if BUILDFLAG(ENABLE_MUS)
- if (features::IsMusEnabled()) {
+ if (features::IsMashEnabled()) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSurfaceSynchronization);
}
@@ -1214,11 +1208,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
#endif
-#if BUILDFLAG(ENABLE_VULKAN)
- if (parsed_command_line_.HasSwitch(switches::kEnableVulkan))
- gpu::InitializeVulkan();
-#endif
-
// Initialize the GPU shader cache. This needs to be initialized before
// BrowserGpuChannelHostFactory below, since that depends on an initialized
// ShaderCacheFactory.
@@ -1287,7 +1276,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
{
TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:AudioMan");
- CreateAudioManager();
+ InitializeAudio();
}
{
@@ -1303,18 +1292,20 @@ int BrowserMainLoop::BrowserThreadsStarted() {
device_monitor_linux_.reset(
new media::DeviceMonitorLinux(io_thread_->task_runner()));
#elif defined(OS_MACOSX)
+ // On Mac, the audio task runner must belong to the main thread.
+ // See audio_thread_impl.cc and https://crbug.com/158170.
+ DCHECK(!audio_manager_ ||
+ audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
device_monitor_mac_.reset(
- new media::DeviceMonitorMac(audio_manager_->GetTaskRunner()));
+ new media::DeviceMonitorMac(base::ThreadTaskRunnerHandle::Get()));
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
// Instantiated once using CreateSingletonInstance(), and accessed only using
// GetInstance(), which is not allowed to create the object. This allows us
// to ensure that it cannot be used before objects it relies on have been
// created; namely, WebRtcEventLogManager.
// Allowed to leak when the browser exits.
WebRTCInternals::CreateSingletonInstance();
-#endif
// RDH needs the IO thread to be created
{
@@ -1342,16 +1333,29 @@ int BrowserMainLoop::BrowserThreadsStarted() {
{
TRACE_EVENT0("startup",
"BrowserMainLoop::BrowserThreadsStarted:InitMediaStreamManager");
- media_stream_manager_.reset(new MediaStreamManager(
- audio_system_.get(), audio_manager_->GetTaskRunner()));
+
+ scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner =
+ audio_manager_ ? audio_manager_->GetTaskRunner() : nullptr;
+
+#if defined(OS_MACOSX)
+ // On Mac, the audio task runner must belong to the main thread.
+ // See audio_thread_impl.cc and https://crbug.com/158170.
+ if (audio_task_runner) {
+ DCHECK(audio_task_runner->BelongsToCurrentThread());
+ } else {
+ audio_task_runner = base::ThreadTaskRunnerHandle::Get();
+ }
+#endif
+
+ media_stream_manager_ = std::make_unique<MediaStreamManager>(
+ audio_system_.get(), std::move(audio_task_runner));
}
{
TRACE_EVENT0("startup",
"BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition");
speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl(
- audio_system_.get(), audio_manager_.get(),
- media_stream_manager_.get()));
+ audio_system_.get(), media_stream_manager_.get()));
}
{
@@ -1473,12 +1477,13 @@ bool BrowserMainLoop::InitializeToolkit() {
// Env creates the compositor. Aura widgets need the compositor to be created
// before they can be initialized by the browser.
- env_ = aura::Env::CreateInstance(
- features::IsMusEnabled() ? aura::Env::Mode::MUS : aura::Env::Mode::LOCAL);
+ env_ = aura::Env::CreateInstance(features::IsMashEnabled()
+ ? aura::Env::Mode::MUS
+ : aura::Env::Mode::LOCAL);
#endif // defined(USE_AURA)
#if BUILDFLAG(ENABLE_MUS)
- if (features::IsMusEnabled())
+ if (features::IsMashEnabled())
image_cursors_set_ = std::make_unique<ui::ImageCursorsSet>();
#endif
@@ -1504,30 +1509,12 @@ void BrowserMainLoop::MainMessageLoopRun() {
#endif
}
-void BrowserMainLoop::InitializeIOThread() {
- base::Thread::Options options;
- options.message_loop_type = base::MessageLoop::TYPE_IO;
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
- // Up the priority of the |io_thread_| as some of its IPCs relate to
- // display tasks.
- options.priority = base::ThreadPriority::DISPLAY;
-#endif
-
- io_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::IO);
-
- if (!io_thread_->StartWithOptions(options))
- LOG(FATAL) << "Failed to start BrowserThread::IO";
-}
-
void BrowserMainLoop::InitializeMojo() {
if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
// Disallow mojo sync calls in the browser process. Note that we allow sync
// calls in single-process mode since renderer IPCs are made from a browser
// thread.
- bool sync_call_allowed = false;
- MojoResult result = mojo::edk::SetProperty(
- MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, &sync_call_allowed);
- DCHECK_EQ(MOJO_RESULT_OK, result);
+ mojo::SyncCallRestrictions::DisallowSyncCall();
}
mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(
@@ -1557,30 +1544,24 @@ void BrowserMainLoop::InitializeMojo() {
// Start startup tracing through TracingController's interface. TraceLog has
// been enabled in content_main_runner where threads are not available. Now We
// need to start tracing for all other tracing agents, which require threads.
- if (parsed_command_line_.HasSwitch(switches::kTraceStartup)) {
- base::trace_event::TraceConfig trace_config(
- parsed_command_line_.GetSwitchValueASCII(switches::kTraceStartup),
- parsed_command_line_.GetSwitchValueASCII(
- switches::kTraceStartupRecordMode));
+ auto* trace_startup_config = tracing::TraceStartupConfig::GetInstance();
+ if (trace_startup_config->IsEnabled()) {
+ // This checks kTraceConfigFile switch.
TracingController::GetInstance()->StartTracing(
- trace_config, TracingController::StartTracingDoneCallback());
+ trace_startup_config->GetTraceConfig(),
+ TracingController::StartTracingDoneCallback());
} else if (parsed_command_line_.HasSwitch(switches::kTraceToConsole)) {
TracingController::GetInstance()->StartTracing(
tracing::GetConfigForTraceToConsole(),
TracingController::StartTracingDoneCallback());
- } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) {
- // This checks kTraceConfigFile switch.
- TracingController::GetInstance()->StartTracing(
- tracing::TraceConfigFile::GetInstance()->GetTraceConfig(),
- TracingController::StartTracingDoneCallback());
}
// Start tracing to a file for certain duration if needed. Only do this after
// starting the main message loop to avoid calling
// MessagePumpForUI::ScheduleWork() before MessagePumpForUI::Start() as it
// will crash the browser.
- if (is_tracing_startup_for_duration_) {
+ if (trace_startup_config->IsTracingStartupForDuration()) {
TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracingForDuration");
- InitStartupTracingForDuration(parsed_command_line_);
+ InitStartupTracingForDuration();
}
if (parts_) {
@@ -1589,93 +1570,82 @@ void BrowserMainLoop::InitializeMojo() {
}
}
-base::FilePath BrowserMainLoop::GetStartupTraceFileName(
- const base::CommandLine& command_line) const {
+base::FilePath BrowserMainLoop::GetStartupTraceFileName() const {
base::FilePath trace_file;
- if (command_line.HasSwitch(switches::kTraceStartup)) {
- trace_file = command_line.GetSwitchValuePath(
- switches::kTraceStartupFile);
- // trace_file = "none" means that startup events will show up for the next
- // begin/end tracing (via about:tracing or AutomationProxy::BeginTracing/
- // EndTracing, for example).
- if (trace_file == base::FilePath().AppendASCII("none"))
- return trace_file;
-
- if (trace_file.empty()) {
-#if defined(OS_ANDROID)
- TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
-#else
- // Default to saving the startup trace into the current dir.
- trace_file = base::FilePath().AppendASCII("chrometrace.log");
-#endif
- }
- } else {
+
#if defined(OS_ANDROID)
- TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
+ TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
#else
- trace_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
-#endif
+ trace_file = tracing::TraceStartupConfig::GetInstance()->GetResultFile();
+ if (trace_file.empty()) {
+ // Default to saving the startup trace into the current dir.
+ trace_file = base::FilePath().AppendASCII("chrometrace.log");
}
+#endif
return trace_file;
}
-void BrowserMainLoop::InitStartupTracingForDuration(
- const base::CommandLine& command_line) {
- DCHECK(is_tracing_startup_for_duration_);
-
- startup_trace_file_ = GetStartupTraceFileName(parsed_command_line_);
+void BrowserMainLoop::InitStartupTracingForDuration() {
+ DCHECK(tracing::TraceStartupConfig::GetInstance()
+ ->IsTracingStartupForDuration());
- int delay_secs = 5;
- if (command_line.HasSwitch(switches::kTraceStartup)) {
- std::string delay_str = command_line.GetSwitchValueASCII(
- switches::kTraceStartupDuration);
- if (!delay_str.empty() && !base::StringToInt(delay_str, &delay_secs)) {
- DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration
- << "=" << delay_str << " defaulting to 5 (secs)";
- delay_secs = 5;
- }
- } else {
- delay_secs = tracing::TraceConfigFile::GetInstance()->GetStartupDuration();
- }
+ startup_trace_file_ = GetStartupTraceFileName();
- startup_trace_timer_.Start(FROM_HERE,
- base::TimeDelta::FromSeconds(delay_secs),
- this,
- &BrowserMainLoop::EndStartupTracing);
+ startup_trace_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromSeconds(
+ tracing::TraceStartupConfig::GetInstance()->GetStartupDuration()),
+ this, &BrowserMainLoop::EndStartupTracing);
}
void BrowserMainLoop::EndStartupTracing() {
- DCHECK(is_tracing_startup_for_duration_);
+ // Do nothing if startup tracing is already stopped.
+ if (!tracing::TraceStartupConfig::GetInstance()->IsEnabled())
+ return;
- is_tracing_startup_for_duration_ = false;
TracingController::GetInstance()->StopTracing(
TracingController::CreateFileEndpoint(
startup_trace_file_,
base::Bind(OnStoppedStartupTracing, startup_trace_file_)));
}
-void BrowserMainLoop::CreateAudioManager() {
+void BrowserMainLoop::InitializeAudio() {
DCHECK(!audio_manager_);
audio_manager_ = GetContentClient()->browser()->CreateAudioManager(
MediaInternals::GetInstance());
- if (!audio_manager_) {
+ DCHECK_EQ(!!audio_manager_,
+ GetContentClient()->browser()->OverridesAudioManager());
+
+ // Do not initialize |audio_manager_| if running out of process.
+ if (!audio_manager_ &&
+ !base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess)) {
audio_manager_ =
media::AudioManager::Create(std::make_unique<media::AudioThreadImpl>(),
MediaInternals::GetInstance());
+ CHECK(audio_manager_);
}
- CHECK(audio_manager_);
- AudioMirroringManager* const mirroring_manager =
- AudioMirroringManager::GetInstance();
- audio_manager_->SetDiverterCallbacks(
- mirroring_manager->GetAddDiverterCallback(),
- mirroring_manager->GetRemoveDiverterCallback());
+ // Iff |audio_manager_| is instantiated, the audio service will run
+ // in-process. Complete the setup for that:
+ if (audio_manager_) {
+ AudioMirroringManager* const mirroring_manager =
+ AudioMirroringManager::GetInstance();
+ audio_manager_->SetDiverterCallbacks(
+ mirroring_manager->GetAddDiverterCallback(),
+ mirroring_manager->GetRemoveDiverterCallback());
- TRACE_EVENT_INSTANT0("startup", "Starting Audio service task runner",
- TRACE_EVENT_SCOPE_THREAD);
- audio_service_runner_->StartWithTaskRunner(audio_manager_->GetTaskRunner());
+ TRACE_EVENT_INSTANT0("startup", "Starting Audio service task runner",
+ TRACE_EVENT_SCOPE_THREAD);
+ audio_service_runner_->StartWithTaskRunner(audio_manager_->GetTaskRunner());
+ }
+
+ if (base::FeatureList::IsEnabled(features::kAudioServiceLaunchOnStartup)) {
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->StartService(audio::mojom::kServiceName);
+ }
audio_system_ = audio::CreateAudioSystem(
content::ServiceManagerConnection::GetForProcess()
@@ -1684,4 +1654,11 @@ void BrowserMainLoop::CreateAudioManager() {
CHECK(audio_system_);
}
+bool BrowserMainLoop::AudioServiceOutOfProcess() const {
+ // Returns true iff kAudioServiceOutOfProcess feature is enabled and if the
+ // embedder does not provide its own in-process AudioManager.
+ return base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess) &&
+ !GetContentClient()->browser()->OverridesAudioManager();
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index 20b2ac7b95a..c8618c586f5 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -13,12 +13,17 @@
#include "base/memory/ref_counted.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "content/browser/browser_process_sub_thread.h"
#include "content/public/browser/browser_main_runner.h"
#include "media/media_buildflags.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
#include "ui/base/ui_features.h"
+#if defined(OS_CHROMEOS)
+#include "content/browser/media/keyboard_mic_registration.h"
+#endif
+
#if defined(USE_AURA)
namespace aura {
class Env;
@@ -91,7 +96,6 @@ class HostFrameSinkManager;
namespace content {
class BrowserMainParts;
class BrowserOnlineStateObserver;
-class BrowserProcessSubThread;
class BrowserThreadImpl;
class LoaderDelegateImpl;
class MediaStreamManager;
@@ -125,7 +129,10 @@ class CONTENT_EXPORT BrowserMainLoop {
explicit BrowserMainLoop(const MainFunctionParams& parameters);
virtual ~BrowserMainLoop();
- void Init();
+ // |service_manager_thread| is optional. If set, it will be registered as
+ // BrowserThread::IO in CreateThreads() instead of creating a brand new
+ // thread.
+ void Init(std::unique_ptr<BrowserProcessSubThread> service_manager_thread);
// Return value is exit status. Anything other than RESULT_CODE_NORMAL_EXIT
// is considered an error.
@@ -153,12 +160,11 @@ class CONTENT_EXPORT BrowserMainLoop {
// through stopping threads to PostDestroyThreads.
void ShutdownThreadsAndCleanUp();
- void InitializeIOThreadForTesting();
-
int GetResultCode() const { return result_code_; }
- media::AudioManager* audio_manager() const { return audio_manager_.get(); }
+ media::AudioManager* audio_manager() const;
base::SequencedTaskRunner* audio_service_runner();
+ bool AudioServiceOutOfProcess() const;
media::AudioSystem* audio_system() const { return audio_system_.get(); }
MediaStreamManager* media_stream_manager() const {
return media_stream_manager_.get();
@@ -166,15 +172,20 @@ class CONTENT_EXPORT BrowserMainLoop {
media::UserInputMonitor* user_input_monitor() const {
return user_input_monitor_.get();
}
+
+#if defined(OS_CHROMEOS)
+ KeyboardMicRegistration* keyboard_mic_registration() {
+ return &keyboard_mic_registration_;
+ }
+#endif
+
discardable_memory::DiscardableSharedMemoryManager*
discardable_shared_memory_manager() const {
return discardable_shared_memory_manager_.get();
}
midi::MidiService* midi_service() const { return midi_service_.get(); }
- bool is_tracing_startup_for_duration() const {
- return is_tracing_startup_for_duration_;
- }
+ base::FilePath GetStartupTraceFileName() const;
const base::FilePath& startup_trace_file() const {
return startup_trace_file_;
@@ -243,17 +254,11 @@ class CONTENT_EXPORT BrowserMainLoop {
void MainMessageLoopRun();
- // Initializes |io_thread_|. It will not be promoted to BrowserThread::IO
- // until CreateThreads().
- void InitializeIOThread();
-
void InitializeMojo();
- base::FilePath GetStartupTraceFileName(
- const base::CommandLine& command_line) const;
- void InitStartupTracingForDuration(const base::CommandLine& command_line);
+ void InitStartupTracingForDuration();
void EndStartupTracing();
- void CreateAudioManager();
+ void InitializeAudio();
bool UsingInProcessGpu() const;
@@ -282,7 +287,6 @@ class CONTENT_EXPORT BrowserMainLoop {
const base::CommandLine& parsed_command_line_;
int result_code_;
bool created_threads_; // True if the non-UI threads were created.
- bool is_tracing_startup_for_duration_;
// Members initialized in |MainMessageLoopStart()| ---------------------------
std::unique_ptr<base::MessageLoop> main_message_loop_;
@@ -345,10 +349,20 @@ class CONTENT_EXPORT BrowserMainLoop {
// |user_input_monitor_| has to outlive |audio_manager_|, so declared first.
std::unique_ptr<media::UserInputMonitor> user_input_monitor_;
+
+ // |audio_manager_| is not instantiated when the audio service runs out of
+ // process.
std::unique_ptr<media::AudioManager> audio_manager_;
+
+ // Task runner for the audio service when it runs in the browser process.
scoped_refptr<base::DeferredSequencedTaskRunner> audio_service_runner_;
+
std::unique_ptr<media::AudioSystem> audio_system_;
+#if defined(OS_CHROMEOS)
+ KeyboardMicRegistration keyboard_mic_registration_;
+#endif
+
std::unique_ptr<midi::MidiService> midi_service_;
// Must be deleted on the IO thread.
diff --git a/chromium/content/browser/browser_main_loop_unittest.cc b/chromium/content/browser/browser_main_loop_unittest.cc
index 728331bda09..24e38ba8a61 100644
--- a/chromium/content/browser/browser_main_loop_unittest.cc
+++ b/chromium/content/browser/browser_main_loop_unittest.cc
@@ -29,7 +29,7 @@ TEST(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
*scoped_command_line.GetProcessCommandLine());
BrowserMainLoop browser_main_loop(main_function_params);
browser_main_loop.MainMessageLoopStart();
- browser_main_loop.InitializeIOThreadForTesting();
+ browser_main_loop.Init(nullptr);
browser_main_loop.CreateThreads();
EXPECT_GE(base::TaskScheduler::GetInstance()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
deleted file mode 100644
index 20d32d31d87..00000000000
--- a/chromium/content/browser/browser_main_runner.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/browser/browser_main_runner.h"
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/debug/debugger.h"
-#include "base/debug/leak_annotations.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/run_loop.h"
-#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/time/time.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "components/tracing/common/trace_config_file.h"
-#include "components/tracing/common/tracing_switches.h"
-#include "content/browser/browser_main_loop.h"
-#include "content/browser/browser_shutdown_profile_dumper.h"
-#include "content/browser/notification_service_impl.h"
-#include "content/common/content_switches_internal.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/main_function_params.h"
-#include "third_party/skia/include/core/SkGraphics.h"
-#include "ui/base/ime/input_method_initializer.h"
-
-#if defined(OS_ANDROID)
-#include "content/browser/android/tracing_controller_android.h"
-#endif
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#include "ui/base/win/scoped_ole_initializer.h"
-#include "ui/gfx/win/direct_write.h"
-#endif
-
-namespace content {
-
-namespace {
-
-base::LazyInstance<base::AtomicFlag>::Leaky g_exited_main_message_loop;
-
-} // namespace
-
-class BrowserMainRunnerImpl : public BrowserMainRunner {
- public:
- BrowserMainRunnerImpl()
- : initialization_started_(false), is_shutdown_(false) {}
-
- ~BrowserMainRunnerImpl() override {
- if (initialization_started_ && !is_shutdown_)
- Shutdown();
- }
-
- int Initialize(const MainFunctionParams& parameters) override {
- SCOPED_UMA_HISTOGRAM_LONG_TIMER(
- "Startup.BrowserMainRunnerImplInitializeLongTime");
- TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
-
- // On Android we normally initialize the browser in a series of UI thread
- // tasks. While this is happening a second request can come from the OS or
- // another application to start the browser. If this happens then we must
- // not run these parts of initialization twice.
- if (!initialization_started_) {
- initialization_started_ = true;
-
- const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
-
- base::SamplingHeapProfiler::InitTLSSlot();
- if (parameters.command_line.HasSwitch(switches::kSamplingHeapProfiler)) {
- base::SamplingHeapProfiler* profiler =
- base::SamplingHeapProfiler::GetInstance();
- unsigned sampling_interval = 0;
- bool parsed =
- base::StringToUint(parameters.command_line.GetSwitchValueASCII(
- switches::kSamplingHeapProfiler),
- &sampling_interval);
- if (parsed && sampling_interval > 0)
- profiler->SetSamplingInterval(sampling_interval * 1024);
- profiler->Start();
- }
-
- SkGraphics::Init();
-
- if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
- base::debug::WaitForDebugger(60, true);
-
- if (parameters.command_line.HasSwitch(switches::kBrowserStartupDialog))
- WaitForDebugger("Browser");
-
- notification_service_.reset(new NotificationServiceImpl);
-
-#if defined(OS_WIN)
- // Ole must be initialized before starting message pump, so that TSF
- // (Text Services Framework) module can interact with the message pump
- // on Windows 8 Metro mode.
- ole_initializer_.reset(new ui::ScopedOleInitializer);
- // Enable DirectWrite font rendering if needed.
- gfx::win::MaybeInitializeDirectWrite();
-#endif // OS_WIN
-
- main_loop_.reset(new BrowserMainLoop(parameters));
-
- main_loop_->Init();
-
- if (parameters.created_main_parts_closure) {
- parameters.created_main_parts_closure->Run(main_loop_->parts());
- delete parameters.created_main_parts_closure;
- }
-
- const int early_init_error_code = main_loop_->EarlyInitialization();
- if (early_init_error_code > 0)
- return early_init_error_code;
-
- // Must happen before we try to use a message loop or display any UI.
- if (!main_loop_->InitializeToolkit())
- return 1;
-
- main_loop_->PreMainMessageLoopStart();
- main_loop_->MainMessageLoopStart();
- main_loop_->PostMainMessageLoopStart();
-
-// WARNING: If we get a WM_ENDSESSION, objects created on the stack here
-// are NOT deleted. If you need something to run during WM_ENDSESSION add it
-// to browser_shutdown::Shutdown or BrowserProcess::EndSession.
-
- ui::InitializeInputMethod();
- UMA_HISTOGRAM_TIMES("Startup.BrowserMainRunnerImplInitializeStep1Time",
- base::TimeTicks::Now() - start_time_step1);
- }
- const base::TimeTicks start_time_step2 = base::TimeTicks::Now();
- main_loop_->CreateStartupTasks();
- int result_code = main_loop_->GetResultCode();
- if (result_code > 0)
- return result_code;
-
- UMA_HISTOGRAM_TIMES("Startup.BrowserMainRunnerImplInitializeStep2Time",
- base::TimeTicks::Now() - start_time_step2);
-
- // Return -1 to indicate no early termination.
- return -1;
- }
-
-#if defined(OS_ANDROID)
- void SynchronouslyFlushStartupTasks() override {
- main_loop_->SynchronouslyFlushStartupTasks();
- }
-#endif
-
- int Run() override {
- DCHECK(initialization_started_);
- DCHECK(!is_shutdown_);
- main_loop_->RunMainMessageLoopParts();
- return main_loop_->GetResultCode();
- }
-
- void Shutdown() override {
- DCHECK(initialization_started_);
- DCHECK(!is_shutdown_);
-
-#ifdef LEAK_SANITIZER
- // Invoke leak detection now, to avoid dealing with shutdown-only leaks.
- // Normally this will have already happened in
- // BroserProcessImpl::ReleaseModule(), so this call has no effect. This is
- // only for processes which do not instantiate a BrowserProcess.
- // If leaks are found, the process will exit here.
- __lsan_do_leak_check();
-#endif
-
- main_loop_->PreShutdown();
-
- // If startup tracing has not been finished yet, replace it's dumper
- // with special version, which would save trace file on exit (i.e.
- // startup tracing becomes a version of shutdown tracing).
- // There are two cases:
- // 1. Startup duration is not reached.
- // 2. Or startup duration is not specified for --trace-config-file flag.
- std::unique_ptr<BrowserShutdownProfileDumper> startup_profiler;
- if (main_loop_->is_tracing_startup_for_duration()) {
- main_loop_->StopStartupTracingTimer();
- if (main_loop_->startup_trace_file() !=
- base::FilePath().AppendASCII("none")) {
- startup_profiler.reset(
- new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
- }
- } else if (tracing::TraceConfigFile::GetInstance()->IsEnabled()) {
- base::FilePath result_file;
-#if defined(OS_ANDROID)
- TracingControllerAndroid::GenerateTracingFilePath(&result_file);
-#else
- result_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
-#endif
- startup_profiler.reset(new BrowserShutdownProfileDumper(result_file));
- }
-
- // The shutdown tracing got enabled in AttemptUserExit earlier, but someone
- // needs to write the result to disc. For that a dumper needs to get created
- // which will dump the traces to disc when it gets destroyed.
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- std::unique_ptr<BrowserShutdownProfileDumper> shutdown_profiler;
- if (command_line.HasSwitch(switches::kTraceShutdown)) {
- shutdown_profiler.reset(new BrowserShutdownProfileDumper(
- BrowserShutdownProfileDumper::GetShutdownProfileFileName()));
- }
-
- {
- // The trace event has to stay between profiler creation and destruction.
- TRACE_EVENT0("shutdown", "BrowserMainRunner");
- g_exited_main_message_loop.Get().Set();
-
- main_loop_->ShutdownThreadsAndCleanUp();
-
- ui::ShutdownInputMethod();
- #if defined(OS_WIN)
- ole_initializer_.reset(NULL);
- #endif
- #if defined(OS_ANDROID)
- // Forcefully terminates the RunLoop inside MessagePumpForUI, ensuring
- // proper shutdown for content_browsertests. Shutdown() is not used by
- // the actual browser.
- if (base::RunLoop::IsRunningOnCurrentThread())
- base::RunLoop::QuitCurrentDeprecated();
- #endif
- main_loop_.reset(nullptr);
-
- notification_service_.reset(nullptr);
-
- is_shutdown_ = true;
- }
- }
-
- protected:
- // True if we have started to initialize the runner.
- bool initialization_started_;
-
- // True if the runner has been shut down.
- bool is_shutdown_;
-
- std::unique_ptr<NotificationServiceImpl> notification_service_;
- std::unique_ptr<BrowserMainLoop> main_loop_;
-#if defined(OS_WIN)
- std::unique_ptr<ui::ScopedOleInitializer> ole_initializer_;
-#endif
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl);
-};
-
-// static
-BrowserMainRunner* BrowserMainRunner::Create() {
- return new BrowserMainRunnerImpl();
-}
-
-// static
-bool BrowserMainRunner::ExitedMainMessageLoop() {
- return g_exited_main_message_loop.IsCreated() &&
- g_exited_main_message_loop.Get().IsSet();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/browser_main_runner_impl.cc b/chromium/content/browser/browser_main_runner_impl.cc
new file mode 100644
index 00000000000..6381234ca78
--- /dev/null
+++ b/chromium/content/browser/browser_main_runner_impl.cc
@@ -0,0 +1,256 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/browser_main_runner_impl.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/debug/debugger.h"
+#include "base/debug/leak_annotations.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/run_loop.h"
+#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/atomic_flag.h"
+#include "base/time/time.h"
+#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
+#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "components/tracing/common/trace_startup_config.h"
+#include "components/tracing/common/tracing_switches.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/browser_process_sub_thread.h"
+#include "content/browser/browser_shutdown_profile_dumper.h"
+#include "content/browser/notification_service_impl.h"
+#include "content/common/content_switches_internal.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/main_function_params.h"
+#include "third_party/skia/include/core/SkGraphics.h"
+#include "ui/base/ime/input_method_initializer.h"
+
+#if defined(OS_ANDROID)
+#include "content/browser/android/tracing_controller_android.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#include "ui/base/win/scoped_ole_initializer.h"
+#include "ui/gfx/win/direct_write.h"
+#endif
+
+namespace content {
+namespace {
+
+base::LazyInstance<base::AtomicFlag>::Leaky g_exited_main_message_loop;
+
+} // namespace
+
+// static
+BrowserMainRunnerImpl* BrowserMainRunnerImpl::Create() {
+ return new BrowserMainRunnerImpl();
+}
+
+BrowserMainRunnerImpl::BrowserMainRunnerImpl()
+ : initialization_started_(false), is_shutdown_(false) {}
+
+BrowserMainRunnerImpl::~BrowserMainRunnerImpl() {
+ if (initialization_started_ && !is_shutdown_)
+ Shutdown();
+}
+
+int BrowserMainRunnerImpl::Initialize(const MainFunctionParams& parameters) {
+ return Initialize(parameters, nullptr);
+}
+
+int BrowserMainRunnerImpl::Initialize(
+ const MainFunctionParams& parameters,
+ std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
+ SCOPED_UMA_HISTOGRAM_LONG_TIMER(
+ "Startup.BrowserMainRunnerImplInitializeLongTime");
+ TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
+
+ // On Android we normally initialize the browser in a series of UI thread
+ // tasks. While this is happening a second request can come from the OS or
+ // another application to start the browser. If this happens then we must
+ // not run these parts of initialization twice.
+ if (!initialization_started_) {
+ initialization_started_ = true;
+
+ const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
+
+ base::SamplingHeapProfiler::InitTLSSlot();
+ if (parameters.command_line.HasSwitch(switches::kSamplingHeapProfiler)) {
+ base::SamplingHeapProfiler* profiler =
+ base::SamplingHeapProfiler::GetInstance();
+ unsigned sampling_interval = 0;
+ bool parsed =
+ base::StringToUint(parameters.command_line.GetSwitchValueASCII(
+ switches::kSamplingHeapProfiler),
+ &sampling_interval);
+ if (parsed && sampling_interval > 0)
+ profiler->SetSamplingInterval(sampling_interval * 1024);
+ profiler->Start();
+ }
+
+ SkGraphics::Init();
+
+ if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
+ base::debug::WaitForDebugger(60, true);
+
+ if (parameters.command_line.HasSwitch(switches::kBrowserStartupDialog))
+ WaitForDebugger("Browser");
+
+ notification_service_.reset(new NotificationServiceImpl);
+
+#if defined(OS_WIN)
+ // Ole must be initialized before starting message pump, so that TSF
+ // (Text Services Framework) module can interact with the message pump
+ // on Windows 8 Metro mode.
+ ole_initializer_.reset(new ui::ScopedOleInitializer);
+ // Enable DirectWrite font rendering if needed.
+ gfx::win::MaybeInitializeDirectWrite();
+#endif // OS_WIN
+
+ main_loop_.reset(new BrowserMainLoop(parameters));
+
+ main_loop_->Init(std::move(service_manager_thread));
+
+ if (parameters.created_main_parts_closure) {
+ parameters.created_main_parts_closure->Run(main_loop_->parts());
+ delete parameters.created_main_parts_closure;
+ }
+
+ const int early_init_error_code = main_loop_->EarlyInitialization();
+ if (early_init_error_code > 0)
+ return early_init_error_code;
+
+ // Must happen before we try to use a message loop or display any UI.
+ if (!main_loop_->InitializeToolkit())
+ return 1;
+
+ main_loop_->PreMainMessageLoopStart();
+ main_loop_->MainMessageLoopStart();
+ main_loop_->PostMainMessageLoopStart();
+
+ // WARNING: If we get a WM_ENDSESSION, objects created on the stack here
+ // are NOT deleted. If you need something to run during WM_ENDSESSION add it
+ // to browser_shutdown::Shutdown or BrowserProcess::EndSession.
+
+ ui::InitializeInputMethod();
+ UMA_HISTOGRAM_TIMES("Startup.BrowserMainRunnerImplInitializeStep1Time",
+ base::TimeTicks::Now() - start_time_step1);
+ }
+ const base::TimeTicks start_time_step2 = base::TimeTicks::Now();
+ main_loop_->CreateStartupTasks();
+ int result_code = main_loop_->GetResultCode();
+ if (result_code > 0)
+ return result_code;
+
+ UMA_HISTOGRAM_TIMES("Startup.BrowserMainRunnerImplInitializeStep2Time",
+ base::TimeTicks::Now() - start_time_step2);
+
+ // Return -1 to indicate no early termination.
+ return -1;
+}
+
+#if defined(OS_ANDROID)
+void BrowserMainRunnerImpl::SynchronouslyFlushStartupTasks() {
+ main_loop_->SynchronouslyFlushStartupTasks();
+}
+#endif
+
+int BrowserMainRunnerImpl::Run() {
+ DCHECK(initialization_started_);
+ DCHECK(!is_shutdown_);
+ main_loop_->RunMainMessageLoopParts();
+ return main_loop_->GetResultCode();
+}
+
+void BrowserMainRunnerImpl::Shutdown() {
+ DCHECK(initialization_started_);
+ DCHECK(!is_shutdown_);
+
+#ifdef LEAK_SANITIZER
+ // Invoke leak detection now, to avoid dealing with shutdown-only leaks.
+ // Normally this will have already happened in
+ // BroserProcessImpl::ReleaseModule(), so this call has no effect. This is
+ // only for processes which do not instantiate a BrowserProcess.
+ // If leaks are found, the process will exit here.
+ __lsan_do_leak_check();
+#endif
+
+ main_loop_->PreShutdown();
+
+ // If startup tracing has not been finished yet, replace it's dumper
+ // with special version, which would save trace file on exit (i.e.
+ // startup tracing becomes a version of shutdown tracing).
+ // There are two cases:
+ // 1. Startup duration is not reached.
+ // 2. Or startup duration is not specified for --trace-config-file flag.
+ std::unique_ptr<BrowserShutdownProfileDumper> startup_profiler;
+ if (tracing::TraceStartupConfig::GetInstance()
+ ->IsTracingStartupForDuration()) {
+ main_loop_->StopStartupTracingTimer();
+ if (main_loop_->startup_trace_file() !=
+ base::FilePath().AppendASCII("none")) {
+ startup_profiler.reset(
+ new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
+ }
+ } else if (tracing::TraceStartupConfig::GetInstance()->IsEnabled()) {
+ base::FilePath result_file = main_loop_->GetStartupTraceFileName();
+ startup_profiler.reset(new BrowserShutdownProfileDumper(result_file));
+ }
+
+ // The shutdown tracing got enabled in AttemptUserExit earlier, but someone
+ // needs to write the result to disc. For that a dumper needs to get created
+ // which will dump the traces to disc when it gets destroyed.
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ std::unique_ptr<BrowserShutdownProfileDumper> shutdown_profiler;
+ if (command_line.HasSwitch(switches::kTraceShutdown)) {
+ shutdown_profiler.reset(new BrowserShutdownProfileDumper(
+ BrowserShutdownProfileDumper::GetShutdownProfileFileName()));
+ }
+
+ {
+ // The trace event has to stay between profiler creation and destruction.
+ TRACE_EVENT0("shutdown", "BrowserMainRunner");
+ g_exited_main_message_loop.Get().Set();
+
+ main_loop_->ShutdownThreadsAndCleanUp();
+
+ ui::ShutdownInputMethod();
+#if defined(OS_WIN)
+ ole_initializer_.reset(NULL);
+#endif
+#if defined(OS_ANDROID)
+ // Forcefully terminates the RunLoop inside MessagePumpForUI, ensuring
+ // proper shutdown for content_browsertests. Shutdown() is not used by
+ // the actual browser.
+ if (base::RunLoop::IsRunningOnCurrentThread())
+ base::RunLoop::QuitCurrentDeprecated();
+#endif
+ main_loop_.reset(nullptr);
+
+ notification_service_.reset(nullptr);
+
+ is_shutdown_ = true;
+ }
+}
+
+// static
+BrowserMainRunner* BrowserMainRunner::Create() {
+ return BrowserMainRunnerImpl::Create();
+}
+
+// static
+bool BrowserMainRunner::ExitedMainMessageLoop() {
+ return g_exited_main_message_loop.IsCreated() &&
+ g_exited_main_message_loop.Get().IsSet();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/browser_main_runner_impl.h b/chromium/content/browser/browser_main_runner_impl.h
new file mode 100644
index 00000000000..adb084fe27c
--- /dev/null
+++ b/chromium/content/browser/browser_main_runner_impl.h
@@ -0,0 +1,65 @@
+// 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_BROWSER_MAIN_RUNNER_IMPL_H_
+#define CONTENT_BROWSER_BROWSER_MAIN_RUNNER_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "content/public/browser/browser_main_runner.h"
+
+#if defined(OS_WIN)
+namespace ui {
+class ScopedOleInitializer;
+}
+#endif
+
+namespace content {
+
+class BrowserProcessSubThread;
+class BrowserMainLoop;
+class NotificationServiceImpl;
+
+class BrowserMainRunnerImpl : public BrowserMainRunner {
+ public:
+ static BrowserMainRunnerImpl* Create();
+
+ BrowserMainRunnerImpl();
+ ~BrowserMainRunnerImpl() override;
+
+ // BrowserMainRunner:
+ int Initialize(const MainFunctionParams& parameters) override;
+#if defined(OS_ANDROID)
+ void SynchronouslyFlushStartupTasks() override;
+#endif
+ int Run() override;
+ void Shutdown() override;
+
+ // Initialize all necessary browser state with a |service_manager_thread|
+ // on which ServiceManager is currently running.
+ int Initialize(
+ const MainFunctionParams& parameters,
+ std::unique_ptr<BrowserProcessSubThread> service_manager_thread);
+
+ private:
+ // True if we have started to initialize the runner.
+ bool initialization_started_;
+
+ // True if the runner has been shut down.
+ bool is_shutdown_;
+
+ std::unique_ptr<NotificationServiceImpl> notification_service_;
+ std::unique_ptr<BrowserMainLoop> main_loop_;
+#if defined(OS_WIN)
+ std::unique_ptr<ui::ScopedOleInitializer> ole_initializer_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BROWSER_MAIN_RUNNER_IMPL_H_
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 15994d5dada..a0bc9305e62 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -12,7 +12,6 @@
#include <utility>
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/user_metrics.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
@@ -36,9 +35,8 @@
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_constants_internal.h"
#include "content/common/drag_messages.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
#include "content/common/input/ime_text_span_conversions.h"
-#include "content/common/input_messages.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
@@ -176,11 +174,11 @@ void BrowserPluginGuest::DisableAutoResize() {
browser_plugin_instance_id_));
}
-void BrowserPluginGuest::ResizeDueToAutoResize(const gfx::Size& new_size,
- uint64_t sequence_number) {
+void BrowserPluginGuest::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
SendMessageToEmbedder(
- std::make_unique<BrowserPluginMsg_ResizeDueToAutoResize>(
- browser_plugin_instance_id_, sequence_number));
+ std::make_unique<BrowserPluginMsg_DidUpdateVisualProperties>(
+ browser_plugin_instance_id_, metadata));
}
void BrowserPluginGuest::SizeContents(const gfx::Size& new_size) {
@@ -288,8 +286,8 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateResizeParams,
- OnUpdateResizeParams)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SynchronizeVisualProperties,
+ OnSynchronizeVisualProperties)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -715,8 +713,6 @@ bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
// In --site-per-process, we do not need most of BrowserPluginGuest to drive
// inner WebContents.
- // Right now InputHostMsg_ImeCompositionRangeChanged hits NOTREACHED() in
- // RWHVChildFrame, so we're disabling message handling entirely here.
// TODO(lazyboy): Fix this as part of http://crbug.com/330264. The required
// parts of code from this class should be extracted to a separate class for
// --site-per-process.
@@ -724,12 +720,6 @@ bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
return false;
IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
- IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
- OnImeCancelComposition)
-#if defined(OS_MACOSX) || defined(USE_AURA)
- IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
- OnImeCompositionRangeChanged)
-#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
OnHasTouchEventHandlers)
IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
@@ -1041,13 +1031,15 @@ void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
mouse_locked_ = false;
}
-void BrowserPluginGuest::OnUpdateResizeParams(
+void BrowserPluginGuest::OnSynchronizeVisualProperties(
int browser_plugin_instance_id,
const viz::LocalSurfaceId& local_surface_id,
- const FrameResizeParams& resize_params) {
+ const FrameVisualProperties& visual_properties) {
if (local_surface_id_ > local_surface_id ||
- ((frame_rect_.size() != resize_params.screen_space_rect.size() ||
- screen_info_ != resize_params.screen_info) &&
+ ((frame_rect_.size() != visual_properties.screen_space_rect.size() ||
+ screen_info_ != visual_properties.screen_info ||
+ capture_sequence_number_ !=
+ visual_properties.capture_sequence_number) &&
local_surface_id_ == local_surface_id)) {
SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance();
bad_message::ReceivedBadMessage(
@@ -1056,30 +1048,35 @@ void BrowserPluginGuest::OnUpdateResizeParams(
return;
}
- screen_info_ = resize_params.screen_info;
- frame_rect_ = resize_params.screen_space_rect;
+ screen_info_ = visual_properties.screen_info;
+ frame_rect_ = visual_properties.screen_space_rect;
GetWebContents()->SendScreenRects();
local_surface_id_ = local_surface_id;
+ bool capture_sequence_number_changed =
+ capture_sequence_number_ != visual_properties.capture_sequence_number;
+ capture_sequence_number_ = visual_properties.capture_sequence_number;
RenderWidgetHostView* view = web_contents()->GetRenderWidgetHostView();
if (!view)
return;
+ // We could add functionality to set a specific capture sequence number on the
+ // |view|, but knowing that it's changed is sufficient for us simply request
+ // that our RenderWidgetHostView synchronizes its surfaces. Note that this
+ // should only happen during layout tests, since that is the only call that
+ // should trigger the capture sequence number to change.
+ if (capture_sequence_number_changed)
+ view->EnsureSurfaceSynchronizedForLayoutTest();
+
RenderWidgetHostImpl* render_widget_host =
RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
DCHECK(render_widget_host);
- render_widget_host->SetAutoResize(resize_params.auto_resize_enabled,
- resize_params.min_size_for_auto_resize,
- resize_params.max_size_for_auto_resize);
-
- if (render_widget_host->auto_resize_enabled()) {
- render_widget_host->DidAllocateLocalSurfaceIdForAutoResize(
- resize_params.auto_resize_sequence_number);
- return;
- }
+ render_widget_host->SetAutoResize(visual_properties.auto_resize_enabled,
+ visual_properties.min_size_for_auto_resize,
+ visual_properties.max_size_for_auto_resize);
- render_widget_host->WasResized();
+ render_widget_host->SynchronizeVisualProperties();
}
void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
@@ -1133,19 +1130,4 @@ void BrowserPluginGuest::OnTextInputStateChanged(const TextInputState& params) {
web_contents()->GetRenderWidgetHostView()));
}
-void BrowserPluginGuest::OnImeCancelComposition() {
- static_cast<RenderWidgetHostViewBase*>(
- web_contents()->GetRenderWidgetHostView())->ImeCancelComposition();
-}
-
-#if defined(OS_MACOSX) || defined(USE_AURA)
-void BrowserPluginGuest::OnImeCompositionRangeChanged(
- const gfx::Range& range,
- const std::vector<gfx::Rect>& character_bounds) {
- static_cast<RenderWidgetHostViewBase*>(
- web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged(
- range, character_bounds);
-}
-#endif
-
} // namespace content
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index 5c2d39745cc..964137dafc0 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -30,6 +30,7 @@
#include "base/values.h"
#include "build/build_config.h"
#include "components/viz/common/surfaces/local_surface_id.h"
+#include "components/viz/common/surfaces/scoped_surface_id_allocator.h"
#include "content/common/edit_command.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/browser/guest_host.h"
@@ -56,6 +57,10 @@ namespace gfx {
class Range;
} // namespace gfx
+namespace cc {
+class RenderFrameMetadata;
+} // namespace cc
+
namespace viz {
class LocalSurfaceId;
class SurfaceInfo;
@@ -71,7 +76,7 @@ class RenderWidgetHostView;
class RenderWidgetHostViewBase;
class SiteInstance;
struct DropData;
-struct FrameResizeParams;
+struct FrameVisualProperties;
struct ScreenInfo;
struct TextInputState;
@@ -181,8 +186,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void EnableAutoResize(const gfx::Size& min_size, const gfx::Size& max_size);
void DisableAutoResize();
- void ResizeDueToAutoResize(const gfx::Size& new_size,
- uint64_t sequence_number);
+ void DidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
// WebContentsObserver implementation.
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
@@ -334,9 +338,10 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void OnSetVisibility(int instance_id, bool visible);
void OnUnlockMouse();
void OnUnlockMouseAck(int instance_id);
- void OnUpdateResizeParams(int instance_id,
- const viz::LocalSurfaceId& local_surface_id,
- const FrameResizeParams& resize_params);
+ void OnSynchronizeVisualProperties(
+ int instance_id,
+ const viz::LocalSurfaceId& local_surface_id,
+ const FrameVisualProperties& visual_properties);
void OnTextInputStateChanged(const TextInputState& params);
void OnImeSetComposition(
@@ -349,12 +354,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
int relative_cursor_pos);
void OnImeFinishComposingText(int instance_id, bool keep_selection);
void OnExtendSelectionAndDelete(int instance_id, int before, int after);
- void OnImeCancelComposition();
-#if defined(OS_MACOSX) || defined(USE_AURA)
- void OnImeCompositionRangeChanged(
- const gfx::Range& range,
- const std::vector<gfx::Rect>& character_bounds);
-#endif
// Message handlers for messages from guest.
void OnHandleInputEventAck(
@@ -456,6 +455,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
viz::LocalSurfaceId local_surface_id_;
ScreenInfo screen_info_;
+ uint32_t capture_sequence_number_ = 0u;
// Weak pointer used to ask GeolocationPermissionContext about geolocation
// permission.
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc
index fec9859d9b3..93bf2a10367 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc
@@ -28,6 +28,11 @@ BrowserPluginMessageFilter::~BrowserPluginMessageFilter() {
bool BrowserPluginMessageFilter::OnMessageReceived(
const IPC::Message& message) {
+ if (sub_filter_for_testing_ &&
+ sub_filter_for_testing_->OnMessageReceived(message)) {
+ return true;
+ }
+
// Any message requested by a BrowserPluginGuest should be routed through
// a BrowserPluginGuestManager.
if (BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(message)) {
@@ -82,4 +87,9 @@ void BrowserPluginMessageFilter::ForwardMessageToGuest(
->OnMessageReceivedFromEmbedder(message);
}
+void BrowserPluginMessageFilter::SetSubFilterForTesting(
+ scoped_refptr<BrowserMessageFilter> sub_filter) {
+ sub_filter_for_testing_ = sub_filter;
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h
index 646f424825e..7c03bd30a64 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h
@@ -23,6 +23,9 @@ class BrowserPluginMessageFilter : public BrowserMessageFilter {
bool OnMessageReceived(const IPC::Message& message) override;
void OnDestruct() const override;
+ // Test-only functions:
+ void SetSubFilterForTesting(scoped_refptr<BrowserMessageFilter> sub_filter);
+
private:
friend class BrowserThread;
friend class base::DeleteHelper<BrowserPluginMessageFilter>;
@@ -33,6 +36,8 @@ class BrowserPluginMessageFilter : public BrowserMessageFilter {
const int render_process_id_;
+ scoped_refptr<BrowserMessageFilter> sub_filter_for_testing_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserPluginMessageFilter);
};
diff --git a/chromium/content/browser/browser_process_sub_thread.cc b/chromium/content/browser/browser_process_sub_thread.cc
index 0902fb6bfd0..6f33cee4d65 100644
--- a/chromium/content/browser/browser_process_sub_thread.cc
+++ b/chromium/content/browser/browser_process_sub_thread.cc
@@ -6,13 +6,18 @@
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
+#include "base/metrics/histogram_macros.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/memory_dump_manager.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/notification_service_impl.h"
+#include "content/browser/utility_process_host.h"
+#include "content/common/child_process_host_impl.h"
+#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread_delegate.h"
+#include "content/public/common/process_type.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request.h"
@@ -70,6 +75,24 @@ void BrowserProcessSubThread::AllowBlockingForTesting() {
is_blocking_allowed_for_testing_ = true;
}
+// static
+std::unique_ptr<BrowserProcessSubThread>
+BrowserProcessSubThread::CreateIOThread() {
+ TRACE_EVENT0("startup", "BrowserProcessSubThread::CreateIOThread");
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_IO;
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ // Up the priority of the |io_thread_| as some of its IPCs relate to
+ // display tasks.
+ options.priority = base::ThreadPriority::DISPLAY;
+#endif
+ std::unique_ptr<BrowserProcessSubThread> io_thread(
+ new BrowserProcessSubThread(BrowserThread::IO));
+ if (!io_thread->StartWithOptions(options))
+ LOG(FATAL) << "Failed to start BrowserThread:IO";
+ return io_thread;
+}
+
void BrowserProcessSubThread::Init() {
DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
@@ -168,6 +191,40 @@ void BrowserProcessSubThread::IOThreadCleanUp() {
// Destroy all URLRequests started by URLFetchers.
net::URLFetcher::CancelAll();
+ for (BrowserChildProcessHostIterator it(PROCESS_TYPE_UTILITY); !it.Done();
+ ++it) {
+ UtilityProcessHost* utility_process =
+ static_cast<UtilityProcessHost*>(it.GetDelegate());
+ if (utility_process->sandbox_type() ==
+ service_manager::SANDBOX_TYPE_NETWORK) {
+ // Even though the TerminateAll call above tries to kill all child
+ // processes, that will fail sometimes (e.g. on Windows if there's pending
+ // I/O). Once the network service is sandboxed this will be taken care of,
+ // since the sandbox ensures child processes are terminated. Until then,
+ // wait on the network process for a bit. This is done so that:
+ // 1) when Chrome quits, we ensure that cookies & cache are flushed
+ // 2) tests aren't killed by swarming because of child processes that
+ // outlive the parent process.
+ // https://crbug.com/841001
+ const int kMaxSecondsToWaitForNetworkProcess = 10;
+ ChildProcessHostImpl* child_process =
+ static_cast<ChildProcessHostImpl*>(it.GetHost());
+ auto& process = child_process->peer_process();
+ if (!process.IsValid())
+ continue;
+ base::ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives;
+ const base::TimeTicks start_time = base::TimeTicks::Now();
+ process.WaitForExitWithTimeout(
+ base::TimeDelta::FromSeconds(kMaxSecondsToWaitForNetworkProcess),
+ nullptr);
+ // Record time spent for the method call.
+ base::TimeDelta network_wait_time = base::TimeTicks::Now() - start_time;
+ UMA_HISTOGRAM_TIMES("NetworkService.ShutdownTime", network_wait_time);
+ LOG(ERROR) << "Waited " << network_wait_time.InMilliseconds()
+ << " ms for network service";
+ }
+ }
+
// If any child processes are still running, terminate them and
// and delete the BrowserChildProcessHost instances to release whatever
// IO thread only resources they are referencing.
diff --git a/chromium/content/browser/browser_process_sub_thread.h b/chromium/content/browser/browser_process_sub_thread.h
index f4b87997e3f..edc223865ba 100644
--- a/chromium/content/browser/browser_process_sub_thread.h
+++ b/chromium/content/browser/browser_process_sub_thread.h
@@ -53,6 +53,10 @@ class CONTENT_EXPORT BrowserProcessSubThread : public base::Thread {
// starting this BrowserProcessSubThread.
void AllowBlockingForTesting();
+ // Creates and starts the IO thread. It should not be promoted to
+ // BrowserThread::IO until BrowserMainLoop::CreateThreads().
+ static std::unique_ptr<BrowserProcessSubThread> CreateIOThread();
+
protected:
void Init() override;
void Run(base::RunLoop* run_loop) override;
diff --git a/chromium/content/browser/browser_side_navigation_browsertest.cc b/chromium/content/browser/browser_side_navigation_browsertest.cc
index a2a4b80f88e..bbc595fb84f 100644
--- a/chromium/content/browser/browser_side_navigation_browsertest.cc
+++ b/chromium/content/browser/browser_side_navigation_browsertest.cc
@@ -18,7 +18,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_types.h"
-#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
@@ -44,22 +43,6 @@
namespace content {
-namespace {
-
-class RequestBlockingResourceDispatcherHostDelegate
- : public ResourceDispatcherHostDelegate {
- public:
- // ResourceDispatcherHostDelegate implementation:
- bool ShouldBeginRequest(const std::string& method,
- const GURL& url,
- ResourceType resource_type,
- ResourceContext* resource_context) override {
- return false;
- }
-};
-
-} // namespace
-
// Test with BrowserSideNavigation enabled (aka PlzNavigate).
// If you don't need a custom embedded test server, please use the next class
// below (BrowserSideNavigationBrowserTest), it will automatically start the
@@ -482,7 +465,9 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserDisableWebSecurityTest,
base::TimeTicks::Now() /* navigation_start */, "GET",
nullptr /* post_data */, base::Optional<SourceLocation>(),
CSPDisposition::CHECK, false /* started_from_context_menu */,
- false /* has_user_gesture */, base::nullopt /* suggested_filename */);
+ false /* has_user_gesture */,
+ std::vector<ContentSecurityPolicy>() /* initiator_csp */,
+ CSPSource() /* initiator_self_source */);
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New(
std::string() /* headers */, net::LOAD_NORMAL,
@@ -647,206 +632,6 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBaseBrowserTest,
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
}
-// TODO(arthursonzogni): Remove these tests once NavigationMojoResponse has
-// launched.
-class NavigationMojoResponseBrowserTest : public ContentBrowserTest {
- public:
- NavigationMojoResponseBrowserTest() {}
-
- protected:
- void SetUp() override {
- base::test::ScopedFeatureList().InitAndEnableFeature(
- features::kNavigationMojoResponse);
- ContentBrowserTest::SetUp();
- }
-
- void SetUpOnMainThread() override {
- host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
- }
-};
-
-// Ensure that browser initiated basic navigations work with browser side
-// navigation.
-// TODO(arthursonzogni): Remove this test once NavigationMojoResponse has
-// launched.
-IN_PROC_BROWSER_TEST_F(NavigationMojoResponseBrowserTest,
- BrowserInitiatedNavigations) {
- // Perform a navigation with no live renderer.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL url(embedded_test_server()->GetURL("/title1.html"));
- NavigateToURL(shell(), url);
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- RenderFrameHost* initial_rfh =
- static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host();
-
- // Perform a same site navigation.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL url(embedded_test_server()->GetURL("/title2.html"));
- NavigateToURL(shell(), url);
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- // The RenderFrameHost should not have changed.
- EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host());
-
- // Perform a cross-site navigation.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL url = embedded_test_server()->GetURL("foo.com", "/title3.html");
- NavigateToURL(shell(), url);
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- // The RenderFrameHost should have changed.
- EXPECT_NE(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host());
-}
-
-// Ensure that renderer initiated same-site navigations work with browser side
-// navigation.
-// TODO(arthursonzogni): Remove this test once NavigationMojoResponse has
-// launched.
-IN_PROC_BROWSER_TEST_F(NavigationMojoResponseBrowserTest,
- RendererInitiatedSameSiteNavigation) {
- // Perform a navigation with no live renderer.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL url(embedded_test_server()->GetURL("/simple_links.html"));
- NavigateToURL(shell(), url);
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- RenderFrameHost* initial_rfh =
- static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host();
-
- // Simulate clicking on a same-site link.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL url(embedded_test_server()->GetURL("/title2.html"));
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell(), "window.domAutomationController.send(clickSameSiteLink());",
- &success));
- EXPECT_TRUE(success);
- EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- // The RenderFrameHost should not have changed.
- EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host());
-}
-
-// Ensure that renderer initiated cross-site navigations work with browser side
-// navigation.
-// TODO(arthursonzogni): Remove this test once NavigationMojoResponse has
-// launched.
-IN_PROC_BROWSER_TEST_F(NavigationMojoResponseBrowserTest,
- RendererInitiatedCrossSiteNavigation) {
- // Perform a navigation with no live renderer.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL url(embedded_test_server()->GetURL("/simple_links.html"));
- NavigateToURL(shell(), url);
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- RenderFrameHost* initial_rfh =
- static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host();
-
- // Simulate clicking on a cross-site link.
- {
- TestNavigationObserver observer(shell()->web_contents());
- const char kReplacePortNumber[] =
- "window.domAutomationController.send(setPortNumber(%d));";
- uint16_t port_number = embedded_test_server()->port();
- GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell(), base::StringPrintf(kReplacePortNumber, port_number),
- &success));
- success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell(), "window.domAutomationController.send(clickCrossSiteLink());",
- &success));
- EXPECT_TRUE(success);
- EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- // The RenderFrameHost should not have changed unless site-per-process is
- // enabled.
- if (AreAllSitesIsolatedForTesting()) {
- EXPECT_NE(initial_rfh,
- static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host());
- } else {
- EXPECT_EQ(initial_rfh,
- static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()
- ->root()
- ->current_frame_host());
- }
-}
-
-// Ensure that browser side navigation handles navigation failures.
-// TODO(arthursonzogni): Remove this test once NavigationMojoResponse has
-// launched.
-IN_PROC_BROWSER_TEST_F(NavigationMojoResponseBrowserTest, FailedNavigation) {
- // Perform a navigation with no live renderer.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL url(embedded_test_server()->GetURL("/title1.html"));
- NavigateToURL(shell(), url);
- EXPECT_EQ(url, observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- }
-
- // Now navigate to an unreachable url.
- {
- TestNavigationObserver observer(shell()->web_contents());
- GURL error_url(embedded_test_server()->GetURL("/close-socket"));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
- NavigateToURL(shell(), error_url);
- EXPECT_EQ(error_url, observer.last_navigation_url());
- NavigationEntry* entry =
- shell()->web_contents()->GetController().GetLastCommittedEntry();
- EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
- }
-}
-
// Data URLs can have a reference fragment like any other URLs. This test makes
// sure it is taken into account.
IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
@@ -919,41 +704,4 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
}
}
-// Requests not allowed by a ResourceDispatcherHostDelegate must be aborted.
-IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
- RequestBlockedByResourceDispatcherHostDelegate) {
- // The Network Service doesn't use a ResourceDispatcherHost. A request can't
- // be canceled by a ResourceDispatcherHostDelegate.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService))
- return;
-
- // Add a ResourceDispatcherHost blocking every requests.
- RequestBlockingResourceDispatcherHostDelegate delegate;
- base::RunLoop loop;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- [](base::OnceClosure resume,
- ResourceDispatcherHostDelegate* delegate) {
- ResourceDispatcherHost::Get()->SetDelegate(delegate);
- std::move(resume).Run();
- },
- loop.QuitClosure(), &delegate));
- loop.Run();
-
- // Navigate somewhere. The navigation will be aborted.
- GURL simple_url(embedded_test_server()->GetURL("/simple_page.html"));
- TestNavigationManager manager(shell()->web_contents(), simple_url);
- NavigationHandleObserver handle_observer(shell()->web_contents(), simple_url);
- shell()->LoadURL(simple_url);
-
- EXPECT_TRUE(manager.WaitForRequestStart());
- EXPECT_FALSE(manager.WaitForResponse());
- manager.WaitForNavigationFinished();
-
- EXPECT_FALSE(handle_observer.has_committed());
- EXPECT_TRUE(handle_observer.is_error());
- EXPECT_EQ(net::ERR_ABORTED, handle_observer.net_error_code());
-}
-
} // namespace content
diff --git a/chromium/content/browser/browser_thread_unittest.cc b/chromium/content/browser/browser_thread_unittest.cc
index 703fe3448d4..cf5b1635992 100644
--- a/chromium/content/browser/browser_thread_unittest.cc
+++ b/chromium/content/browser/browser_thread_unittest.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/callback.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -23,9 +24,9 @@ namespace content {
class BrowserThreadTest : public testing::Test {
public:
void Release() const {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- loop_.task_runner()->PostTask(FROM_HERE,
- base::MessageLoop::QuitWhenIdleClosure());
+ EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ EXPECT_TRUE(on_release_);
+ std::move(on_release_).Run();
}
void StopUIThread() { ui_thread_->Stop(); }
@@ -52,42 +53,49 @@ class BrowserThreadTest : public testing::Test {
BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::IO);
}
- static void BasicFunction(base::MessageLoop* message_loop) {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- message_loop->task_runner()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ // Prepares this BrowserThreadTest for Release() to be invoked. |on_release|
+ // will be invoked when this occurs.
+ void ExpectRelease(base::OnceClosure on_release) {
+ on_release_ = std::move(on_release);
+ }
+
+ static void BasicFunction(base::OnceClosure continuation) {
+ EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ std::move(continuation).Run();
}
class DeletedOnIO
: public base::RefCountedThreadSafe<DeletedOnIO,
BrowserThread::DeleteOnIOThread> {
public:
- explicit DeletedOnIO(base::MessageLoop* message_loop)
- : message_loop_(message_loop) {}
+ explicit DeletedOnIO(base::OnceClosure on_deletion)
+ : on_deletion_(std::move(on_deletion)) {}
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
friend class base::DeleteHelper<DeletedOnIO>;
~DeletedOnIO() {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- message_loop_->task_runner()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ std::move(on_deletion_).Run();
}
- base::MessageLoop* message_loop_;
+ base::OnceClosure on_deletion_;
};
private:
std::unique_ptr<BrowserProcessSubThread> ui_thread_;
std::unique_ptr<BrowserProcessSubThread> io_thread_;
- // It's kind of ugly to make this mutable - solely so we can post the Quit
- // Task from Release(). This should be fixed.
- mutable base::MessageLoop loop_;
+
+ base::MessageLoop loop_;
+ // Must be set before Release() to verify the deletion is intentional. Will be
+ // run from the next call to Release(). mutable so it can be consumed from
+ // Release().
+ mutable base::OnceClosure on_release_;
};
class UIThreadDestructionObserver
- : public base::MessageLoop::DestructionObserver {
+ : public base::MessageLoopCurrent::DestructionObserver {
public:
explicit UIThreadDestructionObserver(bool* did_shutdown,
const base::Closure& callback)
@@ -102,10 +110,10 @@ class UIThreadDestructionObserver
private:
static void Watch(UIThreadDestructionObserver* observer) {
- base::MessageLoop::current()->AddDestructionObserver(observer);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(observer);
}
- // base::MessageLoop::DestructionObserver:
+ // base::MessageLoopCurrent::DestructionObserver:
void WillDestroyCurrentMessageLoop() override {
// Ensure that even during MessageLoop teardown the BrowserThread ID is
// correctly associated with this thread and the BrowserThreadTaskRunner
@@ -113,7 +121,7 @@ class UIThreadDestructionObserver
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
EXPECT_TRUE(ui_task_runner_->BelongsToCurrentThread());
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
*did_shutdown_ = true;
callback_task_runner_->PostTask(FROM_HERE, callback_);
}
@@ -125,47 +133,57 @@ class UIThreadDestructionObserver
};
TEST_F(BrowserThreadTest, PostTask) {
+ base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BasicFunction, base::MessageLoop::current()));
- base::RunLoop().Run();
+ base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure()));
+ run_loop.Run();
}
TEST_F(BrowserThreadTest, Release) {
+ base::RunLoop run_loop;
+ ExpectRelease(run_loop.QuitWhenIdleClosure());
BrowserThread::ReleaseSoon(BrowserThread::UI, FROM_HERE, this);
- base::RunLoop().Run();
+ run_loop.Run();
}
TEST_F(BrowserThreadTest, ReleasedOnCorrectThread) {
+ base::RunLoop run_loop;
{
scoped_refptr<DeletedOnIO> test(
- new DeletedOnIO(base::MessageLoop::current()));
+ new DeletedOnIO(run_loop.QuitWhenIdleClosure()));
}
- base::RunLoop().Run();
+ run_loop.Run();
}
TEST_F(BrowserThreadTest, PostTaskViaTaskRunner) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
+ base::RunLoop run_loop;
task_runner->PostTask(
- FROM_HERE, base::BindOnce(&BasicFunction, base::MessageLoop::current()));
- base::RunLoop().Run();
+ FROM_HERE,
+ base::BindOnce(&BasicFunction, run_loop.QuitWhenIdleClosure()));
+ run_loop.Run();
}
TEST_F(BrowserThreadTest, ReleaseViaTaskRunner) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
+
+ base::RunLoop run_loop;
+ ExpectRelease(run_loop.QuitWhenIdleClosure());
task_runner->ReleaseSoon(FROM_HERE, this);
- base::RunLoop().Run();
+ run_loop.Run();
}
TEST_F(BrowserThreadTest, PostTaskAndReply) {
// Most of the heavy testing for PostTaskAndReply() is done inside the
// task runner test. This just makes sure we get piped through at all.
- ASSERT_TRUE(BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE, base::DoNothing(),
- base::BindOnce(&base::RunLoop::QuitCurrentWhenIdleDeprecated)));
- base::RunLoop().Run();
+ base::RunLoop run_loop;
+ ASSERT_TRUE(BrowserThread::PostTaskAndReply(BrowserThread::IO, FROM_HERE,
+ base::DoNothing(),
+ run_loop.QuitWhenIdleClosure()));
+ run_loop.Run();
}
TEST_F(BrowserThreadTest, RunsTasksInCurrentSequencedDuringShutdown) {
diff --git a/chromium/content/browser/browsing_data/OWNERS b/chromium/content/browser/browsing_data/OWNERS
index 8d413bc741f..4b224ec6732 100644
--- a/chromium/content/browser/browsing_data/OWNERS
+++ b/chromium/content/browser/browsing_data/OWNERS
@@ -1,7 +1,7 @@
bauerb@chromium.org
dullweber@chromium.org
markusheintz@chromium.org
-michaeln@chromium.org
+jsbell@chromium.org
msramek@chromium.org
# COMPONENT: Privacy
diff --git a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
index 174800f2958..cba9445e35b 100644
--- a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "net/cookies/canonical_cookie.h"
#include "url/origin.h"
using net::registry_controlled_domains::GetDomainAndRegistry;
@@ -56,38 +55,6 @@ bool MatchesURL(
(mode == BrowsingDataFilterBuilder::WHITELIST));
}
-// True if no domains can see the given cookie and we're a blacklist, or any
-// domains can see the cookie and we're a whitelist.
-// The whitelist or blacklist is represented as |domains_and_ips| and |mode|.
-bool MatchesCookieForRegisterableDomainsAndIPs(
- const std::set<std::string>& domains_and_ips,
- BrowsingDataFilterBuilder::Mode mode,
- const net::CanonicalCookie& cookie) {
- if (domains_and_ips.empty())
- return mode == BrowsingDataFilterBuilder::BLACKLIST;
- std::string cookie_domain = cookie.Domain();
- if (cookie.IsDomainCookie())
- cookie_domain = cookie_domain.substr(1);
- std::string parsed_cookie_domain =
- GetDomainAndRegistry(cookie_domain, INCLUDE_PRIVATE_REGISTRIES);
- // This means we're an IP address or an internal hostname.
- if (parsed_cookie_domain.empty())
- parsed_cookie_domain = cookie_domain;
- return (mode == BrowsingDataFilterBuilder::WHITELIST) ==
- (domains_and_ips.find(parsed_cookie_domain) != domains_and_ips.end());
-}
-
-// True if none of the supplied domains matches this Channel ID's server ID
-// and we're a blacklist, or one of them does and we're a whitelist.
-// The whitelist or blacklist is represented as |domains_and_ips| and |mode|.
-bool MatchesChannelIDForRegisterableDomainsAndIPs(
- const std::set<std::string>& domains_and_ips,
- BrowsingDataFilterBuilder::Mode mode,
- const std::string& channel_id_server_id) {
- return ((mode == BrowsingDataFilterBuilder::WHITELIST) ==
- (domains_and_ips.find(channel_id_server_id) != domains_and_ips.end()));
-}
-
// True if none of the supplied domains matches this plugin's |site| and we're
// a blacklist, or one of them does and we're a whitelist. The whitelist or
// blacklist is represented by |domains_and_ips| and |mode|.
@@ -159,13 +126,13 @@ BrowsingDataFilterBuilderImpl::BuildGeneralFilter() const {
return base::BindRepeating(&MatchesURL, origins_, domains_, mode_);
}
-network::mojom::ClearCacheUrlFilterPtr
-BrowsingDataFilterBuilderImpl::BuildClearCacheUrlFilter() const {
- network::mojom::ClearCacheUrlFilterPtr filter =
- network::mojom::ClearCacheUrlFilter::New();
+network::mojom::ClearDataFilterPtr
+BrowsingDataFilterBuilderImpl::BuildNetworkServiceFilter() const {
+ network::mojom::ClearDataFilterPtr filter =
+ network::mojom::ClearDataFilter::New();
filter->type = (mode_ == Mode::WHITELIST)
- ? network::mojom::ClearCacheUrlFilter::Type::DELETE_MATCHES
- : network::mojom::ClearCacheUrlFilter::Type::KEEP_MATCHES;
+ ? network::mojom::ClearDataFilter::Type::DELETE_MATCHES
+ : network::mojom::ClearDataFilter::Type::KEEP_MATCHES;
filter->origins.insert(filter->origins.begin(), origins_.begin(),
origins_.end());
filter->domains.insert(filter->domains.begin(), domains_.begin(),
@@ -173,22 +140,24 @@ BrowsingDataFilterBuilderImpl::BuildClearCacheUrlFilter() const {
return filter;
}
-base::RepeatingCallback<bool(const net::CanonicalCookie& cookie)>
-BrowsingDataFilterBuilderImpl::BuildCookieFilter() const {
- DCHECK(origins_.empty()) <<
- "Origin-based deletion is not suitable for cookies. Please use "
- "different scoping, such as RegistrableDomainFilterBuilder.";
- return base::BindRepeating(&MatchesCookieForRegisterableDomainsAndIPs,
- domains_, mode_);
-}
-
-base::RepeatingCallback<bool(const std::string& channel_id_server_id)>
-BrowsingDataFilterBuilderImpl::BuildChannelIDFilter() const {
- DCHECK(origins_.empty()) <<
- "Origin-based deletion is not suitable for channel IDs. Please use "
- "different scoping, such as RegistrableDomainFilterBuilder.";
- return base::BindRepeating(&MatchesChannelIDForRegisterableDomainsAndIPs,
- domains_, mode_);
+network::mojom::CookieDeletionFilterPtr
+BrowsingDataFilterBuilderImpl::BuildCookieDeletionFilter() const {
+ DCHECK(origins_.empty())
+ << "Origin-based deletion is not suitable for cookies. Please use "
+ "different scoping, such as RegistrableDomainFilterBuilder.";
+ auto deletion_filter = network::mojom::CookieDeletionFilter::New();
+
+ switch (mode_) {
+ case WHITELIST:
+ deletion_filter->including_domains.emplace(domains_.begin(),
+ domains_.end());
+ break;
+ case BLACKLIST:
+ deletion_filter->excluding_domains.emplace(domains_.begin(),
+ domains_.end());
+ break;
+ }
+ return deletion_filter;
}
base::RepeatingCallback<bool(const std::string& site)>
diff --git a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h
index ed3fe8fcd1c..a310963340d 100644
--- a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h
+++ b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl.h
@@ -24,12 +24,9 @@ class CONTENT_EXPORT BrowsingDataFilterBuilderImpl
bool IsEmptyBlacklist() const override;
base::RepeatingCallback<bool(const GURL&)>
BuildGeneralFilter() const override;
- network::mojom::ClearCacheUrlFilterPtr BuildClearCacheUrlFilter()
+ network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter() const override;
+ network::mojom::CookieDeletionFilterPtr BuildCookieDeletionFilter()
const override;
- base::RepeatingCallback<bool(const net::CanonicalCookie& pattern)>
- BuildCookieFilter() const override;
- base::RepeatingCallback<bool(const std::string& server_id)>
- BuildChannelIDFilter() const override;
base::RepeatingCallback<bool(const std::string& site)>
BuildPluginFilter() const override;
Mode GetMode() const override;
diff --git a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc
index 81fc09dc81e..61e3563d867 100644
--- a/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc
@@ -11,10 +11,15 @@
#include "base/callback.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_deletion_info.h"
+#include "services/network/cookie_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
+using CookieDeletionInfo = net::CookieDeletionInfo;
+
namespace content {
namespace {
@@ -47,10 +52,11 @@ void RunTestCase(TestCase test_case,
<< test_case.url;
}
-void RunTestCase(
- TestCase test_case,
- const base::Callback<bool(const net::CanonicalCookie&)>& filter) {
+void RunTestCase(TestCase test_case,
+ network::mojom::CookieDeletionFilterPtr deletion_filter) {
// Test with regular cookie, http only, domain, and secure.
+ CookieDeletionInfo delete_info =
+ network::DeletionFilterToInfo(std::move(deletion_filter));
std::string cookie_line = "A=2";
GURL test_url(test_case.url);
EXPECT_TRUE(test_url.is_valid()) << test_case.url;
@@ -59,28 +65,28 @@ void RunTestCase(
EXPECT_TRUE(cookie) << cookie_line << " from " << test_case.url
<< " is not a valid cookie";
if (cookie)
- EXPECT_EQ(test_case.should_match, filter.Run(*cookie))
+ EXPECT_EQ(test_case.should_match, delete_info.Matches(*cookie))
<< cookie->DebugString();
cookie_line = std::string("A=2;domain=") + test_url.host();
cookie = net::CanonicalCookie::Create(
test_url, cookie_line, base::Time::Now(), net::CookieOptions());
if (cookie)
- EXPECT_EQ(test_case.should_match, filter.Run(*cookie))
+ EXPECT_EQ(test_case.should_match, delete_info.Matches(*cookie))
<< cookie->DebugString();
cookie_line = std::string("A=2; HttpOnly;") + test_url.host();
cookie = net::CanonicalCookie::Create(
test_url, cookie_line, base::Time::Now(), net::CookieOptions());
if (cookie)
- EXPECT_EQ(test_case.should_match, filter.Run(*cookie))
+ EXPECT_EQ(test_case.should_match, delete_info.Matches(*cookie))
<< cookie->DebugString();
cookie_line = std::string("A=2; HttpOnly; Secure;") + test_url.host();
cookie = net::CanonicalCookie::Create(
test_url, cookie_line, base::Time::Now(), net::CookieOptions());
if (cookie)
- EXPECT_EQ(test_case.should_match, filter.Run(*cookie))
+ EXPECT_EQ(test_case.should_match, delete_info.Matches(*cookie))
<< cookie->DebugString();
}
@@ -210,8 +216,6 @@ TEST(BrowsingDataFilterBuilderImplTest,
builder.AddRegisterableDomain(std::string(kIPAddress));
builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain));
builder.AddRegisterableDomain(std::string(kInternalHostname));
- base::Callback<bool(const net::CanonicalCookie&)> filter =
- builder.BuildCookieFilter();
TestCase test_cases[] = {
// Any cookie with the same registerable domain as the origins is matched.
@@ -250,7 +254,7 @@ TEST(BrowsingDataFilterBuilderImplTest,
};
for (TestCase test_case : test_cases)
- RunTestCase(test_case, filter);
+ RunTestCase(test_case, builder.BuildCookieDeletionFilter());
}
TEST(BrowsingDataFilterBuilderImplTest,
@@ -262,8 +266,6 @@ TEST(BrowsingDataFilterBuilderImplTest,
builder.AddRegisterableDomain(std::string(kIPAddress));
builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain));
builder.AddRegisterableDomain(std::string(kInternalHostname));
- base::Callback<bool(const net::CanonicalCookie&)> filter =
- builder.BuildCookieFilter();
TestCase test_cases[] = {
// Any cookie that doesn't have the same registerable domain is matched.
@@ -302,71 +304,45 @@ TEST(BrowsingDataFilterBuilderImplTest,
};
for (TestCase test_case : test_cases)
- RunTestCase(test_case, filter);
+ RunTestCase(test_case, builder.BuildCookieDeletionFilter());
}
-TEST(BrowsingDataFilterBuilderImplTest,
- RegistrableDomainMatchesChannelIDsWhitelist) {
+TEST(BrowsingDataFilterBuilderImplTest, NetworkServiceFilterWhitelist) {
BrowsingDataFilterBuilderImpl builder(
BrowsingDataFilterBuilderImpl::WHITELIST);
+ ASSERT_EQ(BrowsingDataFilterBuilderImpl::WHITELIST, builder.GetMode());
builder.AddRegisterableDomain(std::string(kGoogleDomain));
builder.AddRegisterableDomain(std::string(kLongETLDDomain));
builder.AddRegisterableDomain(std::string(kIPAddress));
builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain));
builder.AddRegisterableDomain(std::string(kInternalHostname));
- base::Callback<bool(const std::string&)> filter =
- builder.BuildChannelIDFilter();
-
- TestCase test_cases[] = {
- // Channel ID server identifiers can be second level domains, ...
- {"google.com", true},
- {"website.sp.nom.br", true},
- {"second-level-domain.fileserver", true},
-
- // ... IP addresses, or internal hostnames.
- {"192.168.1.1", true},
- {"fileserver", true},
-
- // Channel IDs not in the whitelist are not matched.
- {"example.com", false},
- {"192.168.1.2", false},
- {"website.fileserver", false},
- };
-
- for (TestCase test_case : test_cases)
- RunTestCase(test_case, filter);
+ network::mojom::ClearDataFilterPtr filter =
+ builder.BuildNetworkServiceFilter();
+
+ EXPECT_EQ(network::mojom::ClearDataFilter_Type::DELETE_MATCHES, filter->type);
+ EXPECT_THAT(filter->domains, testing::UnorderedElementsAre(
+ kGoogleDomain, kLongETLDDomain, kIPAddress,
+ kUnknownRegistryDomain, kInternalHostname));
+ EXPECT_TRUE(filter->origins.empty());
}
-TEST(BrowsingDataFilterBuilderImplTest,
- RegistrableDomainMatchesChannelIDsBlacklist) {
+TEST(BrowsingDataFilterBuilderImplTest, NetworkServiceFilterBlacklist) {
BrowsingDataFilterBuilderImpl builder(
BrowsingDataFilterBuilderImpl::BLACKLIST);
+ ASSERT_EQ(BrowsingDataFilterBuilderImpl::BLACKLIST, builder.GetMode());
builder.AddRegisterableDomain(std::string(kGoogleDomain));
builder.AddRegisterableDomain(std::string(kLongETLDDomain));
builder.AddRegisterableDomain(std::string(kIPAddress));
builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain));
builder.AddRegisterableDomain(std::string(kInternalHostname));
- base::Callback<bool(const std::string&)> filter =
- builder.BuildChannelIDFilter();
-
- TestCase test_cases[] = {
- // Channel ID server identifiers can be second level domains, ...
- {"google.com", false},
- {"website.sp.nom.br", false},
- {"second-level-domain.fileserver", false},
-
- // ...IP addresses, or internal hostnames.
- {"192.168.1.1", false},
- {"fileserver", false},
-
- // Channel IDs that are not blacklisted are matched.
- {"example.com", true},
- {"192.168.1.2", true},
- {"website.fileserver", true},
- };
-
- for (TestCase test_case : test_cases)
- RunTestCase(test_case, filter);
+ network::mojom::ClearDataFilterPtr filter =
+ builder.BuildNetworkServiceFilter();
+
+ EXPECT_EQ(network::mojom::ClearDataFilter_Type::KEEP_MATCHES, filter->type);
+ EXPECT_THAT(filter->domains, testing::UnorderedElementsAre(
+ kGoogleDomain, kLongETLDDomain, kIPAddress,
+ kUnknownRegistryDomain, kInternalHostname));
+ EXPECT_TRUE(filter->origins.empty());
}
TEST(BrowsingDataFilterBuilderImplTest,
diff --git a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
index bb4e8bd443c..4c478ad0079 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl.cc
@@ -26,15 +26,6 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
-#include "net/base/net_errors.h"
-#include "net/cookies/cookie_store.h"
-#include "net/http/http_network_session.h"
-#include "net/http/http_transaction_factory.h"
-#include "net/http/transport_security_state.h"
-#include "net/ssl/channel_id_service.h"
-#include "net/ssl/channel_id_store.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/network/public/cpp/features.h"
#include "storage/browser/quota/special_storage_policy.h"
@@ -105,50 +96,6 @@ bool DoesOriginMatchMaskAndURLs(
return false;
}
-void ClearHttpAuthCacheOnIOThread(
- scoped_refptr<net::URLRequestContextGetter> context_getter,
- base::Time delete_begin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- net::HttpNetworkSession* http_session = context_getter->GetURLRequestContext()
- ->http_transaction_factory()
- ->GetSession();
- DCHECK(http_session);
- http_session->http_auth_cache()->ClearEntriesAddedWithin(base::Time::Now() -
- delete_begin);
- http_session->CloseAllConnections();
-}
-
-void OnClearedChannelIDsOnIOThread(net::URLRequestContextGetter* rq_context,
- base::OnceClosure callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Need to close open SSL connections which may be using the channel ids we
- // are deleting.
- // TODO(mattm): http://crbug.com/166069 Make the server bound cert
- // service/store have observers that can notify relevant things directly.
- rq_context->GetURLRequestContext()
- ->ssl_config_service()
- ->NotifySSLConfigChange();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback));
-}
-
-void ClearChannelIDsOnIOThread(
- const base::Callback<bool(const std::string&)>& domain_predicate,
- base::Time delete_begin,
- base::Time delete_end,
- scoped_refptr<net::URLRequestContextGetter> request_context,
- base::OnceClosure callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::ChannelIDService* channel_id_service =
- request_context->GetURLRequestContext()->channel_id_service();
- channel_id_service->GetChannelIDStore()->DeleteForDomainsCreatedBetween(
- domain_predicate, delete_begin, delete_end,
- base::Bind(&OnClearedChannelIDsOnIOThread,
- base::RetainedRef(std::move(request_context)),
- base::Passed(std::move(callback))));
-}
-
} // namespace
BrowsingDataRemoverImpl::BrowsingDataRemoverImpl(
@@ -353,16 +300,16 @@ void BrowsingDataRemoverImpl::RemoveImpl(
!(remove_mask & DATA_TYPE_AVOID_CLOSING_CONNECTIONS) &&
origin_type_mask_ & ORIGIN_TYPE_UNPROTECTED_WEB) {
base::RecordAction(UserMetricsAction("ClearBrowsingData_ChannelIDs"));
- // Since we are running on the UI thread don't call GetURLRequestContext().
- scoped_refptr<net::URLRequestContextGetter> request_context =
- BrowserContext::GetDefaultStoragePartition(browser_context_)
- ->GetURLRequestContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ClearChannelIDsOnIOThread,
- filter_builder.BuildChannelIDFilter(), delete_begin_,
- delete_end_, std::move(request_context),
- CreatePendingTaskCompletionClosure()));
+
+ network::mojom::ClearDataFilterPtr service_filter =
+ filter_builder.BuildNetworkServiceFilter();
+ DCHECK(service_filter->origins.empty())
+ << "Origin-based deletion is not suitable for channel IDs.";
+
+ BrowserContext::GetDefaultStoragePartition(browser_context_)
+ ->GetNetworkContext()
+ ->ClearChannelIds(delete_begin, delete_end, std::move(service_filter),
+ CreatePendingTaskCompletionClosureForMojo());
}
//////////////////////////////////////////////////////////////////////////////
@@ -405,6 +352,10 @@ void BrowsingDataRemoverImpl::RemoveImpl(
storage_partition_remove_mask |=
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
}
+ if (remove_mask & DATA_TYPE_BACKGROUND_FETCH) {
+ storage_partition_remove_mask |=
+ StoragePartition::REMOVE_DATA_MASK_BACKGROUND_FETCH;
+ }
// Content Decryption Modules used by Encrypted Media store licenses in a
// private filesystem. These are different than content licenses used by
@@ -435,12 +386,14 @@ void BrowsingDataRemoverImpl::RemoveImpl(
}
// If cookies are supposed to be conditionally deleted from the storage
- // partition, create a cookie matcher function.
- StoragePartition::CookieMatcherFunction cookie_matcher;
+ // partition, create the deletion info object.
+ network::mojom::CookieDeletionFilterPtr deletion_filter;
if (!filter_builder.IsEmptyBlacklist() &&
(storage_partition_remove_mask &
StoragePartition::REMOVE_DATA_MASK_COOKIES)) {
- cookie_matcher = filter_builder.BuildCookieFilter();
+ deletion_filter = filter_builder.BuildCookieDeletionFilter();
+ } else {
+ deletion_filter = network::mojom::CookieDeletionFilter::New();
}
BrowsingDataRemoverDelegate::EmbedderOriginTypeMatcher embedder_matcher;
@@ -451,7 +404,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(
storage_partition_remove_mask, quota_storage_remove_mask,
base::BindRepeating(&DoesOriginMatchMaskAndURLs, origin_type_mask_,
filter, std::move(embedder_matcher)),
- std::move(cookie_matcher), delete_begin_, delete_end_,
+ std::move(deletion_filter), delete_begin_, delete_end_,
CreatePendingTaskCompletionClosure());
}
@@ -469,7 +422,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(
// The clearing of the HTTP cache happens in the network service process
// when enabled.
network_context->ClearHttpCache(
- delete_begin, delete_end, filter_builder.BuildClearCacheUrlFilter(),
+ delete_begin, delete_end, filter_builder.BuildNetworkServiceFilter(),
CreatePendingTaskCompletionClosureForMojo());
}
@@ -493,18 +446,30 @@ void BrowsingDataRemoverImpl::RemoveImpl(
StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
}
+#if BUILDFLAG(ENABLE_REPORTING)
+ //////////////////////////////////////////////////////////////////////////////
+ // Reporting cache.
+ if (remove_mask & DATA_TYPE_COOKIES) {
+ network::mojom::NetworkContext* network_context =
+ BrowserContext::GetDefaultStoragePartition(browser_context_)
+ ->GetNetworkContext();
+ network_context->ClearReportingCacheClients(
+ filter_builder.BuildNetworkServiceFilter(),
+ CreatePendingTaskCompletionClosureForMojo());
+ network_context->ClearNetworkErrorLogging(
+ filter_builder.BuildNetworkServiceFilter(),
+ CreatePendingTaskCompletionClosureForMojo());
+ }
+#endif // BUILDFLAG(ENABLE_REPORTING)
+
//////////////////////////////////////////////////////////////////////////////
// Auth cache.
if ((remove_mask & DATA_TYPE_COOKIES) &&
!(remove_mask & DATA_TYPE_AVOID_CLOSING_CONNECTIONS)) {
- scoped_refptr<net::URLRequestContextGetter> request_context =
- BrowserContext::GetDefaultStoragePartition(browser_context_)
- ->GetURLRequestContext();
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ClearHttpAuthCacheOnIOThread,
- std::move(request_context), delete_begin_),
- CreatePendingTaskCompletionClosure());
+ BrowserContext::GetDefaultStoragePartition(browser_context_)
+ ->GetNetworkContext()
+ ->ClearHttpAuthCache(delete_begin,
+ CreatePendingTaskCompletionClosureForMojo());
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/content/browser/browsing_data/browsing_data_remover_impl_browsertest.cc b/chromium/content/browser/browsing_data/browsing_data_remover_impl_browsertest.cc
index 2fcc7faa4fa..aab8824e253 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl_browsertest.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl_browsertest.cc
@@ -8,14 +8,20 @@
#include "base/bind.h"
#include "base/files/file_path.h"
+#include "base/test/bind_test_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browsing_data_remover.h"
+#include "content/public/browser/notification_service.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
#include "content/public/test/browsing_data_remover_test_util.h"
#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/simple_url_loader_test_helper.h"
+#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_content_browser_client.h"
#include "net/base/net_errors.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -30,6 +36,7 @@
namespace {
const char kHstsPath[] = "/hsts";
+const char kHttpAuthPath[] = "/http_auth";
const char kHstsResponseBody[] = "HSTS set";
std::unique_ptr<net::test_server::HttpResponse> HandleHstsRequest(
@@ -45,6 +52,26 @@ std::unique_ptr<net::test_server::HttpResponse> HandleHstsRequest(
return nullptr;
}
+// Handles |request| to "/http_auth". If "Authorization" header is present,
+// responds with a non-empty HTTP 200 page (regardless of auth credentials).
+// Otherwise serves a Basic Auth challenge.
+std::unique_ptr<net::test_server::HttpResponse> HandleHttpAuthRequest(
+ const net::test_server::HttpRequest& request) {
+ if (request.relative_url != kHttpAuthPath)
+ return nullptr;
+
+ auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
+ if (base::ContainsKey(request.headers, "Authorization")) {
+ http_response->set_code(net::HTTP_OK);
+ http_response->set_content("Success!");
+ } else {
+ http_response->set_code(net::HTTP_UNAUTHORIZED);
+ http_response->AddCustomHeader("WWW-Authenticate",
+ "Basic realm=\"test realm\"");
+ }
+ return http_response;
+}
+
} // namespace
namespace content {
@@ -58,7 +85,9 @@ class BrowsingDataRemoverImplBrowserTest : public ContentBrowserTest {
net::test_server::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
ssl_server_.AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("content/test/data")));
- ssl_server_.RegisterRequestHandler(base::Bind(&HandleHstsRequest));
+ ssl_server_.RegisterRequestHandler(base::BindRepeating(&HandleHstsRequest));
+ ssl_server_.RegisterRequestHandler(
+ base::BindRepeating(&HandleHttpAuthRequest));
EXPECT_TRUE(ssl_server_.Start());
}
@@ -130,6 +159,40 @@ class BrowsingDataRemoverImplBrowserTest : public ContentBrowserTest {
return false;
}
+ // Sets HTTP auth cache by making a request with credentials specified in the
+ // URL to a page with an auth challenge.
+ void IssueRequestThatSetsHttpAuthCache() {
+ GURL url = ssl_server_.GetURL(kHttpAuthPath);
+ GURL::Replacements replacements;
+ replacements.SetUsernameStr("user");
+ replacements.SetPasswordStr("password");
+ GURL url_with_creds = url.ReplaceComponents(replacements);
+ ASSERT_TRUE(NavigateToURL(shell(), url_with_creds));
+
+ ASSERT_TRUE(IsHttpAuthCacheSet());
+ }
+
+ // Determines if auth cache is populated by seeing if a request to a page with
+ // an auth challenge succeeds.
+ bool IsHttpAuthCacheSet() {
+ // Set a login request callback to be used instead of a login dialog since
+ // such a dialog is difficult to control programmatically and doesn't work
+ // on all platforms.
+ bool login_requested = false;
+ ShellContentBrowserClient::Get()->set_login_request_callback(
+ base::BindLambdaForTesting([&]() { login_requested = true; }));
+
+ GURL url = ssl_server_.GetURL(kHttpAuthPath);
+ bool navigation_suceeded = NavigateToURL(shell(), url);
+
+ // Because our login request callback does nothing, navigation should
+ // succeed iff login is not needed unless some other unexpected error
+ // occurs.
+ EXPECT_NE(navigation_suceeded, login_requested);
+
+ return !login_requested && navigation_suceeded;
+ }
+
network::mojom::URLLoaderFactory* url_loader_factory() {
return BrowserContext::GetDefaultStoragePartition(
shell()->web_contents()->GetBrowserContext())
@@ -160,4 +223,29 @@ IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverImplBrowserTest,
EXPECT_TRUE(IsHstsSet());
}
+IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverImplBrowserTest, ClearHttpAuthCache) {
+ ASSERT_FALSE(IsHttpAuthCacheSet());
+ IssueRequestThatSetsHttpAuthCache();
+
+ RemoveAndWait(BrowsingDataRemover::DATA_TYPE_COOKIES);
+ EXPECT_FALSE(IsHttpAuthCacheSet());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverImplBrowserTest,
+ PreserveHttpAuthCache) {
+ ASSERT_FALSE(IsHttpAuthCacheSet());
+ IssueRequestThatSetsHttpAuthCache();
+
+ RemoveAndWait(BrowsingDataRemover::DATA_TYPE_DOWNLOADS);
+ EXPECT_TRUE(IsHttpAuthCacheSet());
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverImplBrowserTest,
+ ClearHttpAuthCacheWhenEmpty) {
+ ASSERT_FALSE(IsHttpAuthCacheSet());
+
+ RemoveAndWait(BrowsingDataRemover::DATA_TYPE_COOKIES);
+ EXPECT_FALSE(IsHttpAuthCacheSet());
+}
+
} // namespace content
diff --git a/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc b/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
index cf4705ac2e8..c7322c1f278 100644
--- a/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
+++ b/chromium/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
@@ -20,7 +20,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
@@ -43,6 +42,7 @@
#include "content/public/test/test_storage_partition.h"
#include "content/public/test/test_utils.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_deletion_info.h"
#include "net/cookies/cookie_store.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
@@ -52,24 +52,36 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/buildflags/buildflags.h"
+#include "services/network/cookie_manager.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
-using testing::_;
+#if BUILDFLAG(ENABLE_REPORTING)
+#include "net/network_error_logging/network_error_logging_delegate.h"
+#include "net/network_error_logging/network_error_logging_service.h"
+#include "net/reporting/reporting_cache.h"
+#include "net/reporting/reporting_report.h"
+#include "net/reporting/reporting_service.h"
+#include "net/reporting/reporting_test_util.h"
+#endif // BUILDFLAG(ENABLE_REPORTING)
+
using testing::ByRef;
using testing::Eq;
using testing::Invoke;
using testing::IsEmpty;
-using testing::Matcher;
using testing::MakeMatcher;
-using testing::MatcherInterface;
using testing::MatchResultListener;
+using testing::Matcher;
+using testing::MatcherInterface;
using testing::Not;
using testing::Return;
using testing::SizeIs;
+using testing::UnorderedElementsAre;
using testing::WithArgs;
+using testing::_;
+using CookieDeletionFilterPtr = network::mojom::CookieDeletionFilterPtr;
namespace content {
@@ -94,27 +106,37 @@ const GURL kOrigin4(kTestOrigin4);
const GURL kOriginExt(kTestOriginExt);
const GURL kOriginDevTools(kTestOriginDevTools);
-const base::FilePath::CharType kDomStorageOrigin1[] =
- FILE_PATH_LITERAL("http_host1_1.localstorage");
-
-const base::FilePath::CharType kDomStorageOrigin2[] =
- FILE_PATH_LITERAL("http_host2_1.localstorage");
-
-const base::FilePath::CharType kDomStorageOrigin3[] =
- FILE_PATH_LITERAL("http_host3_1.localstorage");
-
-const base::FilePath::CharType kDomStorageExt[] = FILE_PATH_LITERAL(
- "chrome-extension_abcdefghijklmnopqrstuvwxyz_0.localstorage");
-
struct StoragePartitionRemovalData {
- uint32_t remove_mask = 0;
- uint32_t quota_storage_remove_mask = 0;
+ StoragePartitionRemovalData()
+ : remove_mask(0),
+ quota_storage_remove_mask(0),
+ cookie_deletion_filter(network::mojom::CookieDeletionFilter::New()) {}
+
+ StoragePartitionRemovalData(const StoragePartitionRemovalData& other)
+ : remove_mask(other.remove_mask),
+ quota_storage_remove_mask(other.quota_storage_remove_mask),
+ remove_begin(other.remove_begin),
+ remove_end(other.remove_end),
+ origin_matcher(other.origin_matcher),
+ cookie_deletion_filter(other.cookie_deletion_filter.Clone()) {}
+
+ StoragePartitionRemovalData& operator=(
+ const StoragePartitionRemovalData& rhs) {
+ remove_mask = rhs.remove_mask;
+ quota_storage_remove_mask = rhs.quota_storage_remove_mask;
+ remove_begin = rhs.remove_begin;
+ remove_end = rhs.remove_end;
+ origin_matcher = rhs.origin_matcher;
+ cookie_deletion_filter = rhs.cookie_deletion_filter.Clone();
+ return *this;
+ }
+
+ uint32_t remove_mask;
+ uint32_t quota_storage_remove_mask;
base::Time remove_begin;
base::Time remove_end;
StoragePartition::OriginMatcherFunction origin_matcher;
- StoragePartition::CookieMatcherFunction cookie_matcher;
-
- StoragePartitionRemovalData() {}
+ CookieDeletionFilterPtr cookie_deletion_filter;
};
net::CanonicalCookie CreateCookieWithHost(const GURL& source) {
@@ -162,7 +184,7 @@ class StoragePartitionRemovalTestStoragePartition
void ClearData(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
+ CookieDeletionFilterPtr cookie_deletion_filter,
const base::Time begin,
const base::Time end,
base::OnceClosure callback) override {
@@ -173,7 +195,8 @@ class StoragePartitionRemovalTestStoragePartition
storage_partition_removal_data_.remove_begin = begin;
storage_partition_removal_data_.remove_end = end;
storage_partition_removal_data_.origin_matcher = origin_matcher;
- storage_partition_removal_data_.cookie_matcher = cookie_matcher;
+ storage_partition_removal_data_.cookie_deletion_filter =
+ std::move(cookie_deletion_filter);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -182,7 +205,7 @@ class StoragePartitionRemovalTestStoragePartition
base::Unretained(this), std::move(callback)));
}
- StoragePartitionRemovalData GetStoragePartitionRemovalData() {
+ const StoragePartitionRemovalData& GetStoragePartitionRemovalData() const {
return storage_partition_removal_data_;
}
@@ -254,71 +277,15 @@ base::Time AnHourAgo() {
return base::Time::Now() - base::TimeDelta::FromHours(1);
}
+bool FilterMatchesCookie(const CookieDeletionFilterPtr& filter,
+ const net::CanonicalCookie& cookie) {
+ return network::DeletionFilterToInfo(filter.Clone()).Matches(cookie);
+}
+
} // namespace
// Testers -------------------------------------------------------------------
-class RemoveCookieTester {
- public:
- RemoveCookieTester() {}
-
- // Returns true, if the given cookie exists in the cookie store.
- bool ContainsCookie() {
- scoped_refptr<MessageLoopRunner> message_loop_runner =
- new MessageLoopRunner();
- quit_closure_ = message_loop_runner->QuitClosure();
- get_cookie_success_ = false;
- cookie_store_->GetCookieListWithOptionsAsync(
- kOrigin1, net::CookieOptions(),
- base::BindOnce(&RemoveCookieTester::GetCookieListCallback,
- base::Unretained(this)));
- message_loop_runner->Run();
- return get_cookie_success_;
- }
-
- void AddCookie() {
- scoped_refptr<MessageLoopRunner> message_loop_runner =
- new MessageLoopRunner();
- quit_closure_ = message_loop_runner->QuitClosure();
- cookie_store_->SetCookieWithOptionsAsync(
- kOrigin1, "A=1", net::CookieOptions(),
- base::BindOnce(&RemoveCookieTester::SetCookieCallback,
- base::Unretained(this)));
- message_loop_runner->Run();
- }
-
- protected:
- void SetCookieStore(net::CookieStore* cookie_store) {
- cookie_store_ = cookie_store;
- }
-
- private:
- void GetCookieListCallback(const net::CookieList& cookie_list) {
- std::string cookie_line =
- net::CanonicalCookie::BuildCookieLine(cookie_list);
- if (cookie_line == std::string("A=1")) {
- get_cookie_success_ = true;
- } else {
- EXPECT_EQ("", cookie_line);
- get_cookie_success_ = false;
- }
- quit_closure_.Run();
- }
-
- void SetCookieCallback(bool result) {
- ASSERT_TRUE(result);
- quit_closure_.Run();
- }
-
- bool get_cookie_success_ = false;
- base::Closure quit_closure_;
-
- // CookieStore must out live |this|.
- net::CookieStore* cookie_store_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(RemoveCookieTester);
-};
-
class RemoveChannelIDTester : public net::SSLConfigService::Observer {
public:
explicit RemoveChannelIDTester(BrowserContext* browser_context) {
@@ -381,78 +348,6 @@ class RemoveChannelIDTester : public net::SSLConfigService::Observer {
DISALLOW_COPY_AND_ASSIGN(RemoveChannelIDTester);
};
-class RemoveLocalStorageTester {
- public:
- explicit RemoveLocalStorageTester(BrowserContext* browser_context)
- : browser_context_(browser_context) {
- dom_storage_context_ =
- BrowserContext::GetDefaultStoragePartition(browser_context_)
- ->GetDOMStorageContext();
- }
-
- // Returns true, if the given origin URL exists.
- bool DOMStorageExistsForOrigin(const GURL& origin) {
- scoped_refptr<MessageLoopRunner> message_loop_runner =
- new MessageLoopRunner();
- quit_closure_ = message_loop_runner->QuitClosure();
- GetLocalStorageUsage();
- message_loop_runner->Run();
- for (size_t i = 0; i < infos_.size(); ++i) {
- if (origin == infos_[i].origin)
- return true;
- }
- return false;
- }
-
- void AddDOMStorageTestData() {
- // Note: This test depends on details of how the dom_storage library
- // stores data in the host file system.
- base::FilePath storage_path =
- browser_context_->GetPath().AppendASCII("Local Storage");
- base::CreateDirectory(storage_path);
-
- // Write some files.
- base::WriteFile(storage_path.Append(kDomStorageOrigin1), nullptr, 0);
- base::WriteFile(storage_path.Append(kDomStorageOrigin2), nullptr, 0);
- base::WriteFile(storage_path.Append(kDomStorageOrigin3), nullptr, 0);
- base::WriteFile(storage_path.Append(kDomStorageExt), nullptr, 0);
-
- // Tweak their dates.
- base::Time now = base::Time::Now();
- base::TouchFile(storage_path.Append(kDomStorageOrigin1), now, now);
-
- base::Time one_day_ago = now - base::TimeDelta::FromDays(1);
- base::TouchFile(storage_path.Append(kDomStorageOrigin2), one_day_ago,
- one_day_ago);
-
- base::Time sixty_days_ago = now - base::TimeDelta::FromDays(60);
- base::TouchFile(storage_path.Append(kDomStorageOrigin3), sixty_days_ago,
- sixty_days_ago);
-
- base::TouchFile(storage_path.Append(kDomStorageExt), now, now);
- }
-
- private:
- void GetLocalStorageUsage() {
- dom_storage_context_->GetLocalStorageUsage(
- base::Bind(&RemoveLocalStorageTester::OnGotLocalStorageUsage,
- base::Unretained(this)));
- }
- void OnGotLocalStorageUsage(const std::vector<LocalStorageUsageInfo>& infos) {
- infos_ = infos;
- quit_closure_.Run();
- }
-
- // We don't own these pointers.
- BrowserContext* browser_context_;
- DOMStorageContext* dom_storage_context_ = nullptr;
-
- std::vector<LocalStorageUsageInfo> infos_;
- base::Closure quit_closure_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoveLocalStorageTester);
-};
-
class RemoveDownloadsTester {
public:
explicit RemoveDownloadsTester(BrowserContext* browser_context)
@@ -548,7 +443,7 @@ class BrowsingDataRemoverImplTest : public testing::Test {
int GetOriginTypeMask() { return remover_->GetLastUsedOriginTypeMask(); }
- StoragePartitionRemovalData GetStoragePartitionRemovalData() {
+ const StoragePartitionRemovalData& GetStoragePartitionRemovalData() const {
return storage_partition_removal_data_;
}
@@ -645,12 +540,16 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveCookiesDomainBlacklist) {
// Even though it's a different origin, it's the same domain.
EXPECT_FALSE(removal_data.origin_matcher.Run(kOrigin4, mock_policy()));
- EXPECT_FALSE(removal_data.cookie_matcher.Run(CreateCookieWithHost(kOrigin1)));
- EXPECT_TRUE(removal_data.cookie_matcher.Run(CreateCookieWithHost(kOrigin2)));
- EXPECT_FALSE(removal_data.cookie_matcher.Run(CreateCookieWithHost(kOrigin3)));
+ EXPECT_FALSE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
+ CreateCookieWithHost(kOrigin1)));
+ EXPECT_TRUE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
+ CreateCookieWithHost(kOrigin2)));
+ EXPECT_FALSE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
+ CreateCookieWithHost(kOrigin3)));
// This is false, because this is the same domain as 3, just with a different
// scheme.
- EXPECT_FALSE(removal_data.cookie_matcher.Run(CreateCookieWithHost(kOrigin4)));
+ EXPECT_FALSE(FilterMatchesCookie(removal_data.cookie_deletion_filter,
+ CreateCookieWithHost(kOrigin4)));
}
// Test that removing cookies clears HTTP auth data.
@@ -1491,6 +1390,169 @@ TEST_F(BrowsingDataRemoverImplTest, RemoveDownloadsByOrigin) {
std::move(builder));
}
+#if BUILDFLAG(ENABLE_REPORTING)
+TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache) {
+ auto reporting_context = std::make_unique<net::TestReportingContext>(
+ base::DefaultClock::GetInstance(), base::DefaultTickClock::GetInstance(),
+ net::ReportingPolicy());
+ net::ReportingCache* reporting_cache = reporting_context->cache();
+ std::unique_ptr<net::ReportingService> reporting_service =
+ net::ReportingService::CreateForTesting(std::move(reporting_context));
+
+ BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
+ ->GetURLRequestContext()
+ ->GetURLRequestContext()
+ ->set_reporting_service(reporting_service.get());
+
+ GURL domain("https://google.com");
+ reporting_cache->SetClient(url::Origin::Create(domain), domain,
+ net::ReportingClient::Subdomains::EXCLUDE, "group",
+ base::TimeTicks::Max(), 0, 1);
+
+ std::vector<const net::ReportingClient*> clients;
+ reporting_cache->GetClients(&clients);
+ ASSERT_EQ(1u, clients.size());
+
+ BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES, false);
+
+ reporting_cache->GetClients(&clients);
+ EXPECT_TRUE(clients.empty());
+}
+
+TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache_SpecificOrigins) {
+ auto reporting_context = std::make_unique<net::TestReportingContext>(
+ base::DefaultClock::GetInstance(), base::DefaultTickClock::GetInstance(),
+ net::ReportingPolicy());
+ net::ReportingCache* reporting_cache = reporting_context->cache();
+ std::unique_ptr<net::ReportingService> reporting_service =
+ net::ReportingService::CreateForTesting(std::move(reporting_context));
+
+ BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
+ ->GetURLRequestContext()
+ ->GetURLRequestContext()
+ ->set_reporting_service(reporting_service.get());
+
+ GURL domain1("https://google.com");
+ reporting_cache->SetClient(url::Origin::Create(domain1), domain1,
+ net::ReportingClient::Subdomains::EXCLUDE, "group",
+ base::TimeTicks::Max(), 0, 1);
+ GURL domain2("https://host2.com");
+ reporting_cache->SetClient(url::Origin::Create(domain2), domain2,
+ net::ReportingClient::Subdomains::EXCLUDE, "group",
+ base::TimeTicks::Max(), 0, 1);
+ GURL domain3("https://host3.com");
+ reporting_cache->SetClient(url::Origin::Create(domain3), domain3,
+ net::ReportingClient::Subdomains::EXCLUDE, "group",
+ base::TimeTicks::Max(), 0, 1);
+ GURL domain4("https://host4.com");
+ reporting_cache->SetClient(url::Origin::Create(domain4), domain4,
+ net::ReportingClient::Subdomains::EXCLUDE, "group",
+ base::TimeTicks::Max(), 0, 1);
+
+ std::vector<const net::ReportingClient*> clients;
+ reporting_cache->GetClients(&clients);
+ ASSERT_EQ(4u, clients.size());
+
+ std::unique_ptr<BrowsingDataFilterBuilder> filter_builder(
+ BrowsingDataFilterBuilder::Create(BrowsingDataFilterBuilder::WHITELIST));
+ filter_builder->AddRegisterableDomain("google.com");
+ filter_builder->AddRegisterableDomain("host3.com");
+ BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES,
+ std::move(filter_builder));
+
+ reporting_cache->GetClients(&clients);
+ EXPECT_EQ(2u, clients.size());
+ std::vector<GURL> origins;
+ for (const net::ReportingClient* client : clients) {
+ origins.push_back(client->endpoint);
+ }
+ EXPECT_THAT(origins, UnorderedElementsAre(domain2, domain4));
+}
+
+TEST_F(BrowsingDataRemoverImplTest, RemoveReportingCache_NoService) {
+ ASSERT_FALSE(BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
+ ->GetURLRequestContext()
+ ->GetURLRequestContext()
+ ->reporting_service());
+
+ BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES, false);
+}
+
+TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging) {
+ std::unique_ptr<net::NetworkErrorLoggingService> logging_service =
+ net::NetworkErrorLoggingService::Create(
+ net::NetworkErrorLoggingDelegate::Create());
+ BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
+ ->GetURLRequestContext()
+ ->GetURLRequestContext()
+ ->set_network_error_logging_service(logging_service.get());
+
+ GURL domain("https://google.com");
+ logging_service->OnHeader(url::Origin::Create(domain),
+ "{\"report-to\":\"group\",\"max-age\":86400}");
+
+ ASSERT_EQ(1u, logging_service->GetPolicyOriginsForTesting().size());
+
+ BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES, false);
+
+ EXPECT_TRUE(logging_service->GetPolicyOriginsForTesting().empty());
+}
+
+TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging_SpecificOrigins) {
+ std::unique_ptr<net::NetworkErrorLoggingService> logging_service =
+ net::NetworkErrorLoggingService::Create(
+ net::NetworkErrorLoggingDelegate::Create());
+ BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
+ ->GetURLRequestContext()
+ ->GetURLRequestContext()
+ ->set_network_error_logging_service(logging_service.get());
+
+ GURL domain1("https://google.com");
+ logging_service->OnHeader(url::Origin::Create(domain1),
+ "{\"report-to\":\"group\",\"max-age\":86400}");
+ GURL domain2("https://host2.com");
+ logging_service->OnHeader(url::Origin::Create(domain2),
+ "{\"report-to\":\"group\",\"max-age\":86400}");
+ GURL domain3("https://host3.com");
+ logging_service->OnHeader(url::Origin::Create(domain3),
+ "{\"report-to\":\"group\",\"max-age\":86400}");
+ GURL domain4("https://host4.com");
+ logging_service->OnHeader(url::Origin::Create(domain4),
+ "{\"report-to\":\"group\",\"max-age\":86400}");
+
+ ASSERT_EQ(4u, logging_service->GetPolicyOriginsForTesting().size());
+
+ std::unique_ptr<BrowsingDataFilterBuilder> filter_builder(
+ BrowsingDataFilterBuilder::Create(BrowsingDataFilterBuilder::WHITELIST));
+ filter_builder->AddRegisterableDomain("google.com");
+ filter_builder->AddRegisterableDomain("host3.com");
+ BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES,
+ std::move(filter_builder));
+
+ std::set<url::Origin> policy_origins =
+ logging_service->GetPolicyOriginsForTesting();
+ EXPECT_EQ(2u, policy_origins.size());
+ EXPECT_THAT(policy_origins,
+ UnorderedElementsAre(url::Origin::Create(domain2),
+ url::Origin::Create(domain4)));
+}
+
+TEST_F(BrowsingDataRemoverImplTest, RemoveNetworkErrorLogging_NoService) {
+ ASSERT_FALSE(BrowserContext::GetDefaultStoragePartition(GetBrowserContext())
+ ->GetURLRequestContext()
+ ->GetURLRequestContext()
+ ->network_error_logging_service());
+
+ BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(),
+ BrowsingDataRemover::DATA_TYPE_COOKIES, false);
+}
+#endif // BUILDFLAG(ENABLE_REPORTING)
+
class MultipleTasksObserver {
public:
// A simple implementation of BrowsingDataRemover::Observer.
diff --git a/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc b/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
index bd37230b055..8fba2e45093 100644
--- a/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
+++ b/chromium/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
@@ -666,7 +666,7 @@ IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, MAYBE_Credentials) {
std::string credentials;
bool should_run;
} kTestCases[] = {
- {true, "", false},
+ {true, "", true},
{true, "omit", false},
{true, "same-origin", true},
{true, "include", true},
diff --git a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.h b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.h
index da7b590e8f9..ba0eb7369ac 100644
--- a/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.h
+++ b/chromium/content/browser/browsing_data/conditional_cache_deletion_helper.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/callback_forward.h"
-#include "base/message_loop/message_loop.h"
+#include "base/sequenced_task_runner_helpers.h"
#include "content/common/content_export.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
diff --git a/chromium/content/browser/byte_stream.cc b/chromium/content/browser/byte_stream.cc
index 010e8d85295..91b59676545 100644
--- a/chromium/content/browser/byte_stream.cc
+++ b/chromium/content/browser/byte_stream.cc
@@ -60,7 +60,7 @@ class ByteStreamWriterImpl : public ByteStreamWriter {
bool Write(scoped_refptr<net::IOBuffer> buffer, size_t byte_count) override;
void Flush() override;
void Close(int status) override;
- void RegisterCallback(const base::Closure& source_callback) override;
+ void RegisterCallback(const base::RepeatingClosure& source_callback) override;
size_t GetTotalBufferedBytes() const override;
// PostTask target from |ByteStreamReaderImpl::MaybeUpdateInput|.
@@ -83,7 +83,7 @@ class ByteStreamWriterImpl : public ByteStreamWriter {
// True while this object is alive.
scoped_refptr<LifetimeFlag> my_lifetime_flag_;
- base::Closure space_available_callback_;
+ base::RepeatingClosure space_available_callback_;
ContentVector input_contents_;
size_t input_contents_size_;
@@ -118,7 +118,7 @@ class ByteStreamReaderImpl : public ByteStreamReader {
// Overridden from ByteStreamReader.
StreamState Read(scoped_refptr<net::IOBuffer>* data, size_t* length) override;
int GetStatus() const override;
- void RegisterCallback(const base::Closure& sink_callback) override;
+ void RegisterCallback(const base::RepeatingClosure& sink_callback) override;
// PostTask target from |ByteStreamWriterImpl::Write| and
// |ByteStreamWriterImpl::Close|.
@@ -154,7 +154,7 @@ class ByteStreamReaderImpl : public ByteStreamReader {
bool received_status_;
int status_;
- base::Closure data_available_callback_;
+ base::RepeatingClosure data_available_callback_;
// Time of last point at which data in stream transitioned from full
// to non-full. Nulled when a callback is sent.
diff --git a/chromium/content/browser/byte_stream.h b/chromium/content/browser/byte_stream.h
index 375eeb5c16b..784bc67cc13 100644
--- a/chromium/content/browser/byte_stream.h
+++ b/chromium/content/browser/byte_stream.h
@@ -155,7 +155,8 @@ class CONTENT_EXPORT ByteStreamWriter {
// available (i.e. in the case of that race either of the before
// or after callbacks may be called).
// The callback will not be called after ByteStreamWriter destruction.
- virtual void RegisterCallback(const base::Closure& source_callback) = 0;
+ virtual void RegisterCallback(
+ const base::RepeatingClosure& source_callback) = 0;
// Returns the number of bytes sent to the reader but not yet reported by
// the reader as read.
@@ -191,7 +192,8 @@ class CONTENT_EXPORT ByteStreamReader {
// with data becoming available (i.e. in the case of that race
// either of the before or after callbacks may be called).
// The callback will not be called after ByteStreamReader destruction.
- virtual void RegisterCallback(const base::Closure& sink_callback) = 0;
+ virtual void RegisterCallback(
+ const base::RepeatingClosure& sink_callback) = 0;
};
CONTENT_EXPORT void CreateByteStream(
diff --git a/chromium/content/browser/byte_stream_unittest.cc b/chromium/content/browser/byte_stream_unittest.cc
index e774da17afb..7335cf2f717 100644
--- a/chromium/content/browser/byte_stream_unittest.cc
+++ b/chromium/content/browser/byte_stream_unittest.cc
@@ -331,7 +331,7 @@ TEST_F(ByteStreamTest, ByteStream_SinkCallback) {
// Setup callback
int num_callbacks = 0;
byte_stream_output->RegisterCallback(
- base::Bind(CountCallbacks, &num_callbacks));
+ base::BindRepeating(CountCallbacks, &num_callbacks));
EXPECT_TRUE(Write(byte_stream_input.get(), 4000));
base::RunLoop().RunUntilIdle();
@@ -383,7 +383,7 @@ TEST_F(ByteStreamTest, ByteStream_SourceCallback) {
// Add data.
int num_callbacks = 0;
byte_stream_input->RegisterCallback(
- base::Bind(CountCallbacks, &num_callbacks));
+ base::BindRepeating(CountCallbacks, &num_callbacks));
EXPECT_TRUE(Write(byte_stream_input.get(), 2000));
EXPECT_TRUE(Write(byte_stream_input.get(), 2001));
EXPECT_FALSE(Write(byte_stream_input.get(), 6000));
@@ -437,7 +437,7 @@ TEST_F(ByteStreamTest, ByteStream_SinkInterrupt) {
// Record initial state.
int num_callbacks = 0;
byte_stream_output->RegisterCallback(
- base::Bind(CountCallbacks, &num_callbacks));
+ base::BindRepeating(CountCallbacks, &num_callbacks));
// Add data, and pass it across.
EXPECT_TRUE(Write(byte_stream_input.get(), 4000));
@@ -451,7 +451,7 @@ TEST_F(ByteStreamTest, ByteStream_SinkInterrupt) {
// (simulates race with post task).
int num_alt_callbacks = 0;
byte_stream_output->RegisterCallback(
- base::Bind(CountCallbacks, &num_alt_callbacks));
+ base::BindRepeating(CountCallbacks, &num_alt_callbacks));
task_runner->RunUntilIdle();
EXPECT_EQ(0, num_callbacks);
EXPECT_EQ(1, num_alt_callbacks);
@@ -483,7 +483,7 @@ TEST_F(ByteStreamTest, ByteStream_SourceInterrupt) {
// Setup state for test.
int num_callbacks = 0;
byte_stream_input->RegisterCallback(
- base::Bind(CountCallbacks, &num_callbacks));
+ base::BindRepeating(CountCallbacks, &num_callbacks));
EXPECT_TRUE(Write(byte_stream_input.get(), 2000));
EXPECT_TRUE(Write(byte_stream_input.get(), 2001));
EXPECT_FALSE(Write(byte_stream_input.get(), 6000));
@@ -503,7 +503,7 @@ TEST_F(ByteStreamTest, ByteStream_SourceInterrupt) {
// Which should do the right thing when it's run.
int num_alt_callbacks = 0;
byte_stream_input->RegisterCallback(
- base::Bind(CountCallbacks, &num_alt_callbacks));
+ base::BindRepeating(CountCallbacks, &num_alt_callbacks));
task_runner->RunUntilIdle();
EXPECT_EQ(0, num_callbacks);
EXPECT_EQ(1, num_alt_callbacks);
@@ -532,7 +532,7 @@ TEST_F(ByteStreamTest, ByteStream_ZeroCallback) {
// Record initial state.
int num_callbacks = 0;
byte_stream_output->RegisterCallback(
- base::Bind(CountCallbacks, &num_callbacks));
+ base::BindRepeating(CountCallbacks, &num_callbacks));
// Immediately close the stream.
byte_stream_input->Close(0);
diff --git a/chromium/content/browser/cache_storage/OWNERS b/chromium/content/browser/cache_storage/OWNERS
index b78333e3092..f802dd14208 100644
--- a/chromium/content/browser/cache_storage/OWNERS
+++ b/chromium/content/browser/cache_storage/OWNERS
@@ -1,4 +1,3 @@
-michaeln@chromium.org
nhiroki@chromium.org
jkarlin@chromium.org
jsbell@chromium.org
diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc
index 241d017ab4c..d91b54a4d2a 100644
--- a/chromium/content/browser/cache_storage/cache_storage.cc
+++ b/chromium/content/browser/cache_storage/cache_storage.cc
@@ -32,6 +32,7 @@
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_index.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
+#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/symmetric_key.h"
@@ -122,13 +123,15 @@ class CacheStorage::CacheLoader {
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
CacheStorage* cache_storage,
- const url::Origin& origin)
+ const url::Origin& origin,
+ CacheStorageOwner owner)
: cache_task_runner_(cache_task_runner),
request_context_getter_(request_context_getter),
quota_manager_proxy_(quota_manager_proxy),
blob_context_(blob_context),
cache_storage_(cache_storage),
- origin_(origin) {
+ origin_(origin),
+ owner_(owner) {
DCHECK(!origin_.unique());
}
@@ -179,6 +182,7 @@ class CacheStorage::CacheLoader {
CacheStorage* cache_storage_;
url::Origin origin_;
+ CacheStorageOwner owner_;
};
// Creates memory-only ServiceWorkerCaches. Because these caches have no
@@ -192,13 +196,15 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
CacheStorage* cache_storage,
- const url::Origin& origin)
+ const url::Origin& origin,
+ CacheStorageOwner owner)
: CacheLoader(cache_task_runner,
request_context,
quota_manager_proxy,
blob_context,
cache_storage,
- origin) {}
+ origin,
+ owner) {}
std::unique_ptr<CacheStorageCache> CreateCache(
const std::string& cache_name,
@@ -206,7 +212,7 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
int64_t cache_padding,
std::unique_ptr<SymmetricKey> cache_padding_key) override {
return CacheStorageCache::CreateMemoryCache(
- origin_, cache_name, cache_storage_, request_context_getter_,
+ origin_, owner_, cache_name, cache_storage_, request_context_getter_,
quota_manager_proxy_, blob_context_,
s_padding_key.Get().CreateDuplicate());
}
@@ -260,13 +266,15 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
CacheStorage* cache_storage,
- const url::Origin& origin)
+ const url::Origin& origin,
+ CacheStorageOwner owner)
: CacheLoader(cache_task_runner,
request_context,
quota_manager_proxy,
blob_context,
cache_storage,
- origin),
+ origin,
+ owner),
origin_path_(origin_path),
weak_ptr_factory_(this) {}
@@ -281,7 +289,7 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
std::string cache_dir = cache_name_to_cache_dir_[cache_name];
base::FilePath cache_path = origin_path_.AppendASCII(cache_dir);
return CacheStorageCache::CreatePersistentCache(
- origin_, cache_name, cache_storage_, cache_path,
+ origin_, owner_, cache_name, cache_storage_, cache_path,
request_context_getter_, quota_manager_proxy_, blob_context_,
cache_size, cache_padding, std::move(cache_padding_key));
}
@@ -577,7 +585,8 @@ CacheStorage::CacheStorage(
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
CacheStorageManager* cache_storage_manager,
- const url::Origin& origin)
+ const url::Origin& origin,
+ CacheStorageOwner owner)
: initialized_(false),
initializing_(false),
memory_only_(memory_only),
@@ -587,16 +596,17 @@ CacheStorage::CacheStorage(
cache_task_runner_(cache_task_runner),
quota_manager_proxy_(quota_manager_proxy),
origin_(origin),
+ owner_(owner),
cache_storage_manager_(cache_storage_manager),
weak_factory_(this) {
if (memory_only)
cache_loader_.reset(new MemoryLoader(
cache_task_runner_.get(), std::move(request_context),
- quota_manager_proxy.get(), blob_context, this, origin));
+ quota_manager_proxy.get(), blob_context, this, origin, owner));
else
cache_loader_.reset(new SimpleCacheLoader(
origin_path_, cache_task_runner_.get(), std::move(request_context),
- quota_manager_proxy.get(), blob_context, this, origin));
+ quota_manager_proxy.get(), blob_context, this, origin, owner));
}
CacheStorage::~CacheStorage() {
@@ -610,7 +620,7 @@ void CacheStorage::OpenCache(const std::string& cache_name,
LazyInit();
quota_manager_proxy_->NotifyStorageAccessed(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
StorageType::kTemporary);
scheduler_->ScheduleOperation(base::BindOnce(
@@ -626,7 +636,7 @@ void CacheStorage::HasCache(const std::string& cache_name,
LazyInit();
quota_manager_proxy_->NotifyStorageAccessed(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
StorageType::kTemporary);
scheduler_->ScheduleOperation(base::BindOnce(
@@ -642,7 +652,7 @@ void CacheStorage::DoomCache(const std::string& cache_name,
LazyInit();
quota_manager_proxy_->NotifyStorageAccessed(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
StorageType::kTemporary);
scheduler_->ScheduleOperation(base::BindOnce(
@@ -657,7 +667,7 @@ void CacheStorage::EnumerateCaches(IndexCallback callback) {
LazyInit();
quota_manager_proxy_->NotifyStorageAccessed(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
StorageType::kTemporary);
scheduler_->ScheduleOperation(base::BindOnce(
@@ -668,7 +678,7 @@ void CacheStorage::EnumerateCaches(IndexCallback callback) {
void CacheStorage::MatchCache(
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -676,18 +686,18 @@ void CacheStorage::MatchCache(
LazyInit();
quota_manager_proxy_->NotifyStorageAccessed(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
StorageType::kTemporary);
scheduler_->ScheduleOperation(
base::BindOnce(&CacheStorage::MatchCacheImpl, weak_factory_.GetWeakPtr(),
- cache_name, std::move(request), match_params,
+ cache_name, std::move(request), std::move(match_params),
scheduler_->WrapCallbackToRunNext(std::move(callback))));
}
void CacheStorage::MatchAllCaches(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -695,12 +705,32 @@ void CacheStorage::MatchAllCaches(
LazyInit();
quota_manager_proxy_->NotifyStorageAccessed(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
StorageType::kTemporary);
scheduler_->ScheduleOperation(base::BindOnce(
&CacheStorage::MatchAllCachesImpl, weak_factory_.GetWeakPtr(),
- std::move(request), match_params,
+ std::move(request), std::move(match_params),
+ scheduler_->WrapCallbackToRunNext(std::move(callback))));
+}
+
+void CacheStorage::WriteToCache(
+ const std::string& cache_name,
+ std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ CacheStorage::ErrorCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!initialized_)
+ LazyInit();
+
+ quota_manager_proxy_->NotifyStorageAccessed(
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
+ StorageType::kTemporary);
+
+ scheduler_->ScheduleOperation(base::BindOnce(
+ &CacheStorage::WriteToCacheImpl, weak_factory_.GetWeakPtr(), cache_name,
+ std::move(request), std::move(response),
scheduler_->WrapCallbackToRunNext(std::move(callback))));
}
@@ -877,13 +907,14 @@ void CacheStorage::CreateCacheDidCreateCache(
cache_name, cache_ptr->cache_size(), cache_ptr->cache_padding(),
cache_ptr->cache_padding_key()->key()));
+ CacheStorageCacheHandle handle = CreateCacheHandle(cache_ptr);
cache_loader_->WriteIndex(
*cache_index_,
base::BindOnce(&CacheStorage::CreateCacheDidWriteIndex,
weak_factory_.GetWeakPtr(), std::move(callback),
CreateCacheHandle(cache_ptr)));
- cache_loader_->NotifyCacheCreated(cache_name, CreateCacheHandle(cache_ptr));
+ cache_loader_->NotifyCacheCreated(cache_name, std::move(handle));
if (cache_storage_manager_)
cache_storage_manager_->NotifyCacheListChanged(origin_);
}
@@ -967,7 +998,7 @@ void CacheStorage::DeleteCacheFinalize(CacheStorageCache* doomed_cache) {
void CacheStorage::DeleteCacheDidGetSize(CacheStorageCache* doomed_cache,
int64_t cache_size) {
quota_manager_proxy_->NotifyStorageModified(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
StorageType::kTemporary, -1 * cache_size);
cache_loader_->CleanUpDeletedCache(doomed_cache);
@@ -983,7 +1014,7 @@ void CacheStorage::EnumerateCachesImpl(IndexCallback callback) {
void CacheStorage::MatchCacheImpl(
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback) {
CacheStorageCacheHandle cache_handle = GetLoadedCache(cache_name);
@@ -997,7 +1028,7 @@ void CacheStorage::MatchCacheImpl(
// match is done.
CacheStorageCache* cache_ptr = cache_handle.value();
cache_ptr->Match(
- std::move(request), match_params,
+ std::move(request), std::move(match_params),
base::BindOnce(&CacheStorage::MatchCacheDidMatch,
weak_factory_.GetWeakPtr(), std::move(cache_handle),
std::move(callback)));
@@ -1013,7 +1044,7 @@ void CacheStorage::MatchCacheDidMatch(
void CacheStorage::MatchAllCachesImpl(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback) {
std::vector<CacheMatchResponse>* match_responses =
new std::vector<CacheMatchResponse>(cache_index_->num_entries());
@@ -1031,7 +1062,8 @@ void CacheStorage::MatchAllCachesImpl(
CacheStorageCache* cache_ptr = cache_handle.value();
cache_ptr->Match(
- std::make_unique<ServiceWorkerFetchRequest>(*request), match_params,
+ std::make_unique<ServiceWorkerFetchRequest>(*request),
+ match_params ? match_params->Clone() : nullptr,
base::BindOnce(&CacheStorage::MatchAllCachesDidMatch,
weak_factory_.GetWeakPtr(), std::move(cache_handle),
&match_responses->at(idx), barrier_closure));
@@ -1064,6 +1096,24 @@ void CacheStorage::MatchAllCachesDidMatchAll(
std::move(callback).Run(CacheStorageError::kErrorNotFound, nullptr);
}
+void CacheStorage::WriteToCacheImpl(
+ const std::string& cache_name,
+ std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ CacheStorage::ErrorCallback callback) {
+ CacheStorageCacheHandle cache_handle = GetLoadedCache(cache_name);
+
+ if (!cache_handle.value()) {
+ std::move(callback).Run(CacheStorageError::kErrorCacheNameNotFound);
+ return;
+ }
+
+ CacheStorageCache* cache_ptr = cache_handle.value();
+ DCHECK(cache_ptr);
+
+ cache_ptr->Put(std::move(request), std::move(response), std::move(callback));
+}
+
void CacheStorage::AddCacheHandleRef(CacheStorageCache* cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto iter = cache_handle_counts_.find(cache);
diff --git a/chromium/content/browser/cache_storage/cache_storage.h b/chromium/content/browser/cache_storage/cache_storage.h
index acfbcd77ec0..af34ef18253 100644
--- a/chromium/content/browser/cache_storage/cache_storage.h
+++ b/chromium/content/browser/cache_storage/cache_storage.h
@@ -40,6 +40,7 @@ class CacheStorageCacheHandle;
class CacheStorageIndex;
class CacheStorageManager;
class CacheStorageScheduler;
+enum class CacheStorageOwner;
namespace cache_storage_manager_unittest {
class CacheStorageManagerTest;
@@ -76,7 +77,8 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
CacheStorageManager* cache_storage_manager,
- const url::Origin& origin);
+ const url::Origin& origin,
+ CacheStorageOwner owner);
// Any unfinished asynchronous operations may not complete or call their
// callbacks.
@@ -105,7 +107,7 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// Calls match on the cache with the given |cache_name|.
void MatchCache(const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback);
// Calls match on all of the caches in parallel, calling |callback| with the
@@ -113,9 +115,15 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// entry. If no response is found then |callback| is called with
// blink::mojom::CacheStorageError::kErrorNotFound.
void MatchAllCaches(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback);
+ // Puts the request/response pair in the cache.
+ void WriteToCache(const std::string& cache_name,
+ std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ CacheStorage::ErrorCallback callback);
+
// Sums the sizes of each cache and closes them. Runs |callback| with the
// size. The sizes include any doomed caches and will also force close all
// caches even if there are existing handles to them.
@@ -201,7 +209,7 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// The MatchCache callbacks are below.
void MatchCacheImpl(const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback);
void MatchCacheDidMatch(CacheStorageCacheHandle cache_handle,
CacheStorageCache::ResponseCallback callback,
@@ -210,7 +218,7 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// The MatchAllCaches callbacks are below.
void MatchAllCachesImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback);
void MatchAllCachesDidMatch(
CacheStorageCacheHandle cache_handle,
@@ -222,6 +230,12 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
std::unique_ptr<std::vector<CacheMatchResponse>> match_responses,
CacheStorageCache::ResponseCallback callback);
+ // WriteToCache callbacks.
+ void WriteToCacheImpl(const std::string& cache_name,
+ std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ CacheStorage::ErrorCallback callback);
+
void GetSizeThenCloseAllCachesImpl(SizeCallback callback);
void SizeImpl(SizeCallback callback);
@@ -280,6 +294,9 @@ class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
// The origin that this CacheStorage is associated with.
url::Origin origin_;
+ // The owner that this CacheStorage is associated with.
+ CacheStorageOwner owner_;
+
// The manager that owns this cache storage. Only set to null by
// RemoveManager() when this cache storage is being deleted.
CacheStorageManager* cache_storage_manager_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index 90956c40767..d5459e40398 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -27,6 +27,7 @@
#include "content/browser/cache_storage/cache_storage_blob_to_disk_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
#include "content/browser/cache_storage/cache_storage_cache_observer.h"
+#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
@@ -379,11 +380,11 @@ struct CacheStorageCache::QueryCacheResult {
struct CacheStorageCache::QueryCacheContext {
QueryCacheContext(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
QueryCacheCallback callback,
QueryTypes query_types)
: request(std::move(request)),
- options(options),
+ options(std::move(options)),
callback(std::move(callback)),
query_types(query_types),
matches(std::make_unique<QueryCacheResults>()) {}
@@ -400,7 +401,7 @@ struct CacheStorageCache::QueryCacheContext {
// Input to QueryCache
std::unique_ptr<ServiceWorkerFetchRequest> request;
- CacheStorageCacheQueryParams options;
+ blink::mojom::QueryParamsPtr options;
QueryCacheCallback callback;
QueryTypes query_types = 0;
size_t estimated_out_bytes = 0;
@@ -419,6 +420,7 @@ struct CacheStorageCache::QueryCacheContext {
// static
std::unique_ptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage* cache_storage,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
@@ -426,7 +428,7 @@ std::unique_ptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
base::WeakPtr<storage::BlobStorageContext> blob_context,
std::unique_ptr<crypto::SymmetricKey> cache_padding_key) {
CacheStorageCache* cache = new CacheStorageCache(
- origin, cache_name, base::FilePath(), cache_storage,
+ origin, owner, cache_name, base::FilePath(), cache_storage,
std::move(request_context_getter), std::move(quota_manager_proxy),
blob_context, 0 /* cache_size */, 0 /* cache_padding */,
std::move(cache_padding_key));
@@ -438,6 +440,7 @@ std::unique_ptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
// static
std::unique_ptr<CacheStorageCache> CacheStorageCache::CreatePersistentCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage* cache_storage,
const base::FilePath& path,
@@ -448,7 +451,7 @@ std::unique_ptr<CacheStorageCache> CacheStorageCache::CreatePersistentCache(
int64_t cache_padding,
std::unique_ptr<crypto::SymmetricKey> cache_padding_key) {
CacheStorageCache* cache = new CacheStorageCache(
- origin, cache_name, path, cache_storage,
+ origin, owner, cache_name, path, cache_storage,
std::move(request_context_getter), std::move(quota_manager_proxy),
blob_context, cache_size, cache_padding, std::move(cache_padding_key));
cache->SetObserver(cache_storage);
@@ -462,7 +465,7 @@ base::WeakPtr<CacheStorageCache> CacheStorageCache::AsWeakPtr() {
void CacheStorageCache::Match(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ResponseCallback callback) {
if (backend_state_ == BACKEND_CLOSED) {
std::move(callback).Run(CacheStorageError::kErrorStorage, nullptr);
@@ -471,13 +474,13 @@ void CacheStorageCache::Match(
scheduler_->ScheduleOperation(base::BindOnce(
&CacheStorageCache::MatchImpl, weak_ptr_factory_.GetWeakPtr(),
- std::move(request), match_params,
+ std::move(request), std::move(match_params),
scheduler_->WrapCallbackToRunNext(std::move(callback))));
}
void CacheStorageCache::MatchAll(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ResponsesCallback callback) {
if (backend_state_ == BACKEND_CLOSED) {
std::move(callback).Run(CacheStorageError::kErrorStorage,
@@ -487,7 +490,7 @@ void CacheStorageCache::MatchAll(
scheduler_->ScheduleOperation(base::BindOnce(
&CacheStorageCache::MatchAllImpl, weak_ptr_factory_.GetWeakPtr(),
- std::move(request), match_params,
+ std::move(request), std::move(match_params),
scheduler_->WrapCallbackToRunNext(std::move(callback))));
}
@@ -515,7 +518,7 @@ void CacheStorageCache::WriteSideData(ErrorCallback callback,
}
void CacheStorageCache::BatchOperation(
- const std::vector<CacheStorageBatchOperation>& operations,
+ std::vector<blink::mojom::BatchOperationPtr> operations,
ErrorCallback callback,
BadMessageCallback bad_message_callback) {
if (backend_state_ == BACKEND_CLOSED) {
@@ -530,9 +533,9 @@ void CacheStorageCache::BatchOperation(
base::CheckedNumeric<uint64_t> safe_space_required = 0;
base::CheckedNumeric<uint64_t> safe_side_data_size = 0;
for (const auto& operation : operations) {
- if (operation.operation_type == CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT) {
- safe_space_required += operation.response.blob_size;
- safe_side_data_size += operation.response.side_data_blob_size;
+ if (operation->operation_type == blink::mojom::OperationType::kPut) {
+ safe_space_required += operation->response->blob_size;
+ safe_side_data_size += operation->response->side_data_blob_size;
}
}
if (!safe_space_required.IsValid() || !safe_side_data_size.IsValid()) {
@@ -556,19 +559,21 @@ void CacheStorageCache::BatchOperation(
blink::mojom::StorageType::kTemporary,
base::AdaptCallbackForRepeating(base::BindOnce(
&CacheStorageCache::BatchDidGetUsageAndQuota,
- weak_ptr_factory_.GetWeakPtr(), operations, std::move(callback),
- std::move(bad_message_callback), space_required, side_data_size)));
+ weak_ptr_factory_.GetWeakPtr(), std::move(operations),
+ std::move(callback), std::move(bad_message_callback),
+ space_required, side_data_size)));
return;
}
- BatchDidGetUsageAndQuota(
- operations, std::move(callback), std::move(bad_message_callback),
- 0 /* space_required */, 0 /* side_data_size */,
- blink::mojom::QuotaStatusCode::kOk, 0 /* usage */, 0 /* quota */);
+ BatchDidGetUsageAndQuota(std::move(operations), std::move(callback),
+ std::move(bad_message_callback),
+ 0 /* space_required */, 0 /* side_data_size */,
+ blink::mojom::QuotaStatusCode::kOk, 0 /* usage */,
+ 0 /* quota */);
}
void CacheStorageCache::BatchDidGetUsageAndQuota(
- const std::vector<CacheStorageBatchOperation>& operations,
+ std::vector<blink::mojom::BatchOperationPtr> operations,
ErrorCallback callback,
BadMessageCallback bad_message_callback,
uint64_t space_required,
@@ -617,24 +622,23 @@ void CacheStorageCache::BatchDidGetUsageAndQuota(
// will no-op automatically.)
CacheStorageCacheHandle handle = CreateCacheHandle();
- for (const auto& operation : operations) {
- switch (operation.operation_type) {
- case CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT:
+ for (auto& operation : operations) {
+ switch (operation->operation_type) {
+ case blink::mojom::OperationType::kPut:
if (skip_side_data) {
- CacheStorageBatchOperation new_operation = operation;
- new_operation.response.side_data_blob_uuid = std::string();
- new_operation.response.side_data_blob_size = 0;
- new_operation.response.side_data_blob = nullptr;
- Put(new_operation, completion_callback);
+ operation->response->side_data_blob_uuid = std::string();
+ operation->response->side_data_blob_size = 0;
+ operation->response->side_data_blob = nullptr;
+ Put(std::move(operation), completion_callback);
} else {
- Put(operation, completion_callback);
+ Put(std::move(operation), completion_callback);
}
break;
- case CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE:
+ case blink::mojom::OperationType::kDelete:
DCHECK_EQ(1u, operations.size());
- Delete(operation, completion_callback);
+ Delete(std::move(operation), completion_callback);
break;
- case CACHE_STORAGE_CACHE_OPERATION_TYPE_UNDEFINED:
+ case blink::mojom::OperationType::kUndefined:
NOTREACHED();
// TODO(nhiroki): This should return "TypeError".
// http://crbug.com/425505
@@ -664,7 +668,7 @@ void CacheStorageCache::BatchDidAllOperations(ErrorCallback callback) {
}
void CacheStorageCache::Keys(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
RequestsCallback callback) {
if (backend_state_ == BACKEND_CLOSED) {
std::move(callback).Run(CacheStorageError::kErrorStorage, nullptr);
@@ -673,7 +677,7 @@ void CacheStorageCache::Keys(std::unique_ptr<ServiceWorkerFetchRequest> request,
scheduler_->ScheduleOperation(base::BindOnce(
&CacheStorageCache::KeysImpl, weak_ptr_factory_.GetWeakPtr(),
- std::move(request), options,
+ std::move(request), std::move(options),
scheduler_->WrapCallbackToRunNext(std::move(callback))));
}
@@ -724,6 +728,7 @@ CacheStorageCache::~CacheStorageCache() {
CacheStorageCache::CacheStorageCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
const base::FilePath& path,
CacheStorage* cache_storage,
@@ -734,6 +739,7 @@ CacheStorageCache::CacheStorageCache(
int64_t cache_padding,
std::unique_ptr<crypto::SymmetricKey> cache_padding_key)
: origin_(origin),
+ owner_(owner),
cache_name_(cache_name),
path_(path),
cache_storage_(cache_storage),
@@ -764,7 +770,7 @@ CacheStorageCache::CacheStorageCache(
void CacheStorageCache::QueryCache(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
QueryTypes query_types,
QueryCacheCallback callback) {
DCHECK_NE(
@@ -775,19 +781,22 @@ void CacheStorageCache::QueryCache(
return;
}
- if (!options.ignore_method && request && !request->method.empty() &&
- request->method != "GET") {
+ if ((!options || !options->ignore_method) && request &&
+ !request->method.empty() && request->method != "GET") {
std::move(callback).Run(CacheStorageError::kSuccess,
std::make_unique<QueryCacheResults>());
return;
}
ServiceWorkerFetchRequest* request_ptr = request.get();
- std::unique_ptr<QueryCacheContext> query_cache_context(new QueryCacheContext(
- std::move(request), options, std::move(callback), query_types));
+ std::unique_ptr<QueryCacheContext> query_cache_context(
+ new QueryCacheContext(std::move(request), std::move(options),
+ std::move(callback), query_types));
if (query_cache_context->request &&
- !query_cache_context->request->url.is_empty() && !options.ignore_search) {
+ !query_cache_context->request->url.is_empty() &&
+ (!query_cache_context->options ||
+ !query_cache_context->options->ignore_search)) {
// There is no need to scan the entire backend, just open the exact
// URL.
disk_cache::Entry** entry_ptr = &query_cache_context->enumerated_entry;
@@ -880,7 +889,8 @@ void CacheStorageCache::QueryCacheFilterEntry(
GURL requestURL = query_cache_context->request->url;
GURL cachedURL = GURL(entry->GetKey());
- if (query_cache_context->options.ignore_search) {
+ if (query_cache_context->options &&
+ query_cache_context->options->ignore_search) {
requestURL = RemoveQueryParam(requestURL);
cachedURL = RemoveQueryParam(cachedURL);
}
@@ -922,7 +932,8 @@ void CacheStorageCache::QueryCacheDidReadMetadata(
match->response = CreateResponse(*metadata, cache_name_);
if (query_cache_context->request &&
- !query_cache_context->options.ignore_vary &&
+ (!query_cache_context->options ||
+ !query_cache_context->options->ignore_vary) &&
!VaryMatches(query_cache_context->request->headers,
match->request->headers, match->response->headers)) {
query_cache_context->matches->pop_back();
@@ -997,10 +1008,10 @@ int32_t CacheStorageCache::GetResponsePaddingVersion() {
void CacheStorageCache::MatchImpl(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ResponseCallback callback) {
MatchAllImpl(
- std::move(request), match_params,
+ std::move(request), std::move(match_params),
base::BindOnce(&CacheStorageCache::MatchDidMatchAll,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
@@ -1027,7 +1038,7 @@ void CacheStorageCache::MatchDidMatchAll(
void CacheStorageCache::MatchAllImpl(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
ResponsesCallback callback) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
@@ -1037,7 +1048,7 @@ void CacheStorageCache::MatchAllImpl(
}
QueryCache(
- std::move(request), options,
+ std::move(request), std::move(options),
QUERY_CACHE_REQUESTS | QUERY_CACHE_RESPONSES_WITH_BODIES,
base::BindOnce(&CacheStorageCache::MatchAllDidQueryCache,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
@@ -1197,19 +1208,28 @@ void CacheStorageCache::WriteSideDataDidWrite(
base::BindOnce(std::move(callback), CacheStorageError::kSuccess));
}
-void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
+void CacheStorageCache::Put(blink::mojom::BatchOperationPtr operation,
ErrorCallback callback) {
DCHECK(BACKEND_OPEN == backend_state_ || initializing_);
- DCHECK_EQ(CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT, operation.operation_type);
+ DCHECK_EQ(blink::mojom::OperationType::kPut, operation->operation_type);
std::unique_ptr<ServiceWorkerFetchRequest> request(
new ServiceWorkerFetchRequest(
- operation.request.url, operation.request.method,
- operation.request.headers, operation.request.referrer,
- operation.request.is_reload));
+ operation->request.url, operation->request.method,
+ operation->request.headers, operation->request.referrer,
+ operation->request.is_reload));
std::unique_ptr<ServiceWorkerResponse> response =
- std::make_unique<ServiceWorkerResponse>(operation.response);
+ std::make_unique<ServiceWorkerResponse>(*operation->response);
+
+ Put(std::move(request), std::move(response), std::move(callback));
+}
+
+void CacheStorageCache::Put(std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ ErrorCallback callback) {
+ DCHECK(BACKEND_OPEN == backend_state_ || initializing_);
+
blink::mojom::BlobPtr blob;
blink::mojom::BlobPtr side_data_blob;
@@ -1219,7 +1239,7 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
side_data_blob = response->side_data_blob->Clone();
UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.Cache.AllWritesResponseType",
- operation.response.response_type);
+ response->response_type);
auto put_context = std::make_unique<PutContext>(
std::move(request), std::move(response), std::move(blob),
@@ -1247,11 +1267,11 @@ void CacheStorageCache::PutImpl(std::unique_ptr<PutContext> put_context) {
put_context->request->url, "", ServiceWorkerHeaderMap(), Referrer(),
false);
- CacheStorageCacheQueryParams query_options;
- query_options.ignore_method = true;
- query_options.ignore_vary = true;
+ blink::mojom::QueryParamsPtr query_options = blink::mojom::QueryParams::New();
+ query_options->ignore_method = true;
+ query_options->ignore_vary = true;
DeleteImpl(
- std::move(delete_request), query_options,
+ std::move(delete_request), std::move(query_options),
base::BindOnce(&CacheStorageCache::PutDidDeleteEntry,
weak_ptr_factory_.GetWeakPtr(), std::move(put_context)));
}
@@ -1458,9 +1478,10 @@ void CacheStorageCache::CalculateCacheSizePaddingGotSize(
// necessary.
DCHECK_EQ(backend_state_, BACKEND_UNINITIALIZED);
std::unique_ptr<ServiceWorkerFetchRequest> request;
- CacheStorageCacheQueryParams options;
- options.ignore_search = true;
- QueryCache(std::move(request), options, QUERY_CACHE_RESPONSES_NO_BODIES,
+ blink::mojom::QueryParamsPtr options = blink::mojom::QueryParams::New();
+ options->ignore_search = true;
+ QueryCache(std::move(request), std::move(options),
+ QUERY_CACHE_RESPONSES_NO_BODIES,
base::BindOnce(&CacheStorageCache::PaddingDidQueryCache,
weak_ptr_factory_.GetWeakPtr(), std::move(callback),
cache_size));
@@ -1516,7 +1537,7 @@ void CacheStorageCache::UpdateCacheSizeGotSize(
last_reported_size_ = PaddedCacheSize();
quota_manager_proxy_->NotifyStorageModified(
- storage::QuotaClient::kServiceWorkerCache, origin_,
+ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_,
blink::mojom::StorageType::kTemporary, size_delta);
if (cache_storage_)
@@ -1528,27 +1549,26 @@ void CacheStorageCache::UpdateCacheSizeGotSize(
std::move(callback).Run();
}
-void CacheStorageCache::Delete(const CacheStorageBatchOperation& operation,
+void CacheStorageCache::Delete(blink::mojom::BatchOperationPtr operation,
ErrorCallback callback) {
DCHECK(BACKEND_OPEN == backend_state_ || initializing_);
- DCHECK_EQ(CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE,
- operation.operation_type);
+ DCHECK_EQ(blink::mojom::OperationType::kDelete, operation->operation_type);
std::unique_ptr<ServiceWorkerFetchRequest> request(
new ServiceWorkerFetchRequest(
- operation.request.url, operation.request.method,
- operation.request.headers, operation.request.referrer,
- operation.request.is_reload));
+ operation->request.url, operation->request.method,
+ operation->request.headers, operation->request.referrer,
+ operation->request.is_reload));
scheduler_->ScheduleOperation(base::BindOnce(
&CacheStorageCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(),
- std::move(request), operation.match_params,
+ std::move(request), std::move(operation->match_params),
scheduler_->WrapCallbackToRunNext(std::move(callback))));
}
void CacheStorageCache::DeleteImpl(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ErrorCallback callback) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
@@ -1557,7 +1577,7 @@ void CacheStorageCache::DeleteImpl(
}
QueryCache(
- std::move(request), match_params,
+ std::move(request), std::move(match_params),
QUERY_CACHE_ENTRIES | QUERY_CACHE_RESPONSES_NO_BODIES,
base::BindOnce(&CacheStorageCache::DeleteDidQueryCache,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
@@ -1593,7 +1613,7 @@ void CacheStorageCache::DeleteDidQueryCache(
void CacheStorageCache::KeysImpl(
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
RequestsCallback callback) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
@@ -1602,7 +1622,7 @@ void CacheStorageCache::KeysImpl(
}
QueryCache(
- std::move(request), options, QUERY_CACHE_REQUESTS,
+ std::move(request), std::move(options), QUERY_CACHE_REQUESTS,
base::BindOnce(&CacheStorageCache::KeysDidQueryCache,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index 75d0bc95ac9..f343ccbf97d 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -16,7 +16,6 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/cache_storage/cache_storage_types.h"
#include "content/common/service_worker/service_worker_types.h"
#include "net/base/io_buffer.h"
#include "net/disk_cache/disk_cache.h"
@@ -44,6 +43,7 @@ class CacheStorageCacheHandle;
class CacheStorageCacheObserver;
class CacheStorageScheduler;
class TestCacheStorageCache;
+enum class CacheStorageOwner;
namespace proto {
class CacheMetadata;
@@ -81,6 +81,7 @@ class CONTENT_EXPORT CacheStorageCache {
static std::unique_ptr<CacheStorageCache> CreateMemoryCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage* cache_storage,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
@@ -89,6 +90,7 @@ class CONTENT_EXPORT CacheStorageCache {
std::unique_ptr<crypto::SymmetricKey> cache_padding_key);
static std::unique_ptr<CacheStorageCache> CreatePersistentCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage* cache_storage,
const base::FilePath& path,
@@ -106,14 +108,14 @@ class CONTENT_EXPORT CacheStorageCache {
// Returns ERROR_TYPE_NOT_FOUND if not found.
void Match(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ResponseCallback callback);
// Returns blink::mojom::CacheStorageError::kSuccess and matched
// responses in this cache. If there are no responses, returns
// blink::mojom::CacheStorageError::kSuccess and an empty vector.
void MatchAll(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ResponsesCallback callback);
// Writes the side data (ex: V8 code cache) for the specified cache entry.
@@ -141,11 +143,11 @@ class CONTENT_EXPORT CacheStorageCache {
//
// TODO(nhiroki): This function should run all operations atomically.
// http://crbug.com/486637
- void BatchOperation(const std::vector<CacheStorageBatchOperation>& operations,
+ void BatchOperation(std::vector<blink::mojom::BatchOperationPtr> operations,
ErrorCallback callback,
BadMessageCallback bad_message_callback);
void BatchDidGetUsageAndQuota(
- const std::vector<CacheStorageBatchOperation>& operations,
+ std::vector<blink::mojom::BatchOperationPtr> operations,
ErrorCallback callback,
BadMessageCallback bad_message_callback,
uint64_t space_required,
@@ -166,7 +168,7 @@ class CONTENT_EXPORT CacheStorageCache {
// Returns blink::mojom::CacheStorageError::kSuccess and a vector of
// requests if there are no errors.
void Keys(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
RequestsCallback callback);
// Closes the backend. Future operations that require the backend
@@ -180,6 +182,14 @@ class CONTENT_EXPORT CacheStorageCache {
// the cache's size.
void GetSizeThenClose(SizeCallback callback);
+ // Puts the request/response pair in the cache. This is a public member to
+ // directly bypass the batch operations and write into the cache. This is used
+ // by non-CacheAPI owners. The Cache Storage API uses batch operations defined
+ // in the dispatcher.
+ void Put(std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ ErrorCallback callback);
+
// Async operations in progress will cancel and not run their callbacks.
virtual ~CacheStorageCache();
@@ -243,6 +253,7 @@ class CONTENT_EXPORT CacheStorageCache {
CacheStorageCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
const base::FilePath& path,
CacheStorage* cache_storage,
@@ -260,7 +271,7 @@ class CONTENT_EXPORT CacheStorageCache {
// REQUESTS_AND_RESPONSES then only out_requests, out_responses, and
// out_blob_data_handles are valid.
void QueryCache(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
QueryTypes query_types,
QueryCacheCallback callback);
void QueryCacheDidOpenFastPath(
@@ -280,7 +291,7 @@ class CONTENT_EXPORT CacheStorageCache {
// Match callbacks
void MatchImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ResponseCallback callback);
void MatchDidMatchAll(ResponseCallback callback,
blink::mojom::CacheStorageError match_all_error,
@@ -288,7 +299,7 @@ class CONTENT_EXPORT CacheStorageCache {
// MatchAll callbacks
void MatchAllImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
ResponsesCallback callback);
void MatchAllDidQueryCache(
ResponsesCallback callback,
@@ -343,7 +354,7 @@ class CONTENT_EXPORT CacheStorageCache {
// Puts the request and response object in the cache. The response body (if
// present) is stored in the cache, but not the request body. Returns OK on
// success.
- void Put(const CacheStorageBatchOperation& operation, ErrorCallback callback);
+ void Put(blink::mojom::BatchOperationPtr operation, ErrorCallback callback);
void PutImpl(std::unique_ptr<PutContext> put_context);
void PutDidDeleteEntry(std::unique_ptr<PutContext> put_context,
blink::mojom::CacheStorageError error);
@@ -373,10 +384,10 @@ class CONTENT_EXPORT CacheStorageCache {
int current_cache_size);
// Returns ERROR_NOT_FOUND if not found. Otherwise deletes and returns OK.
- void Delete(const CacheStorageBatchOperation& operation,
+ void Delete(blink::mojom::BatchOperationPtr operation,
ErrorCallback callback);
void DeleteImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
ErrorCallback callback);
void DeleteDidQueryCache(
ErrorCallback callback,
@@ -385,7 +396,7 @@ class CONTENT_EXPORT CacheStorageCache {
// Keys callbacks.
void KeysImpl(std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& options,
+ blink::mojom::QueryParamsPtr options,
RequestsCallback callback);
void KeysDidQueryCache(
RequestsCallback callback,
@@ -441,6 +452,7 @@ class CONTENT_EXPORT CacheStorageCache {
std::unique_ptr<disk_cache::Backend> backend_;
url::Origin origin_;
+ CacheStorageOwner owner_;
const std::string cache_name_;
base::FilePath path_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
index 3243379ec93..92d66a32d43 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -23,7 +23,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/cache_storage/cache_storage_cache_handle.h"
-#include "content/common/cache_storage/cache_storage_types.h"
+#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
@@ -283,6 +283,7 @@ class TestCacheStorageCache : public CacheStorageCache {
const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context)
: CacheStorageCache(origin,
+ CacheStorageOwner::kCacheAPI,
cache_name,
path,
cache_storage,
@@ -490,11 +491,11 @@ class CacheStorageCacheTest : public testing::Test {
}
CacheStorageError BatchOperation(
- const std::vector<CacheStorageBatchOperation>& operations) {
+ std::vector<blink::mojom::BatchOperationPtr> operations) {
std::unique_ptr<base::RunLoop> loop(new base::RunLoop());
cache_->BatchOperation(
- operations,
+ std::move(operations),
base::BindOnce(&CacheStorageCacheTest::ErrorTypeCallback,
base::Unretained(this), base::Unretained(loop.get())),
base::BindOnce(&OnBadMessage, base::Unretained(&bad_message_reason_)));
@@ -507,23 +508,24 @@ class CacheStorageCacheTest : public testing::Test {
bool Put(const ServiceWorkerFetchRequest& request,
const ServiceWorkerResponse& response) {
- CacheStorageBatchOperation operation;
- operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation.request = request;
- operation.response = response;
-
- CacheStorageError error =
- BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation));
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kPut;
+ operation->request = request;
+ operation->response = response;
+
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.emplace_back(std::move(operation));
+ CacheStorageError error = BatchOperation(std::move(operations));
return error == CacheStorageError::kSuccess;
}
bool Match(const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params =
- CacheStorageCacheQueryParams()) {
+ blink::mojom::QueryParamsPtr match_params = nullptr) {
std::unique_ptr<base::RunLoop> loop(new base::RunLoop());
cache_->Match(
- CopyFetchRequest(request), match_params,
+ CopyFetchRequest(request), std::move(match_params),
base::BindOnce(&CacheStorageCacheTest::ResponseAndErrorCallback,
base::Unretained(this), base::Unretained(loop.get())));
loop->Run();
@@ -532,11 +534,11 @@ class CacheStorageCacheTest : public testing::Test {
}
bool MatchAll(const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
std::vector<ServiceWorkerResponse>* responses) {
base::RunLoop loop;
cache_->MatchAll(
- CopyFetchRequest(request), match_params,
+ CopyFetchRequest(request), std::move(match_params),
base::BindOnce(&CacheStorageCacheTest::ResponsesAndErrorCallback,
base::Unretained(this), loop.QuitClosure(), responses));
loop.Run();
@@ -544,31 +546,30 @@ class CacheStorageCacheTest : public testing::Test {
}
bool MatchAll(std::vector<ServiceWorkerResponse>* responses) {
- return MatchAll(ServiceWorkerFetchRequest(), CacheStorageCacheQueryParams(),
- responses);
+ return MatchAll(ServiceWorkerFetchRequest(), nullptr, responses);
}
bool Delete(const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params =
- CacheStorageCacheQueryParams()) {
- CacheStorageBatchOperation operation;
- operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
- operation.request = request;
- operation.match_params = match_params;
-
- CacheStorageError error =
- BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation));
+ blink::mojom::QueryParamsPtr match_params = nullptr) {
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kDelete;
+ operation->request = request;
+ operation->match_params = std::move(match_params);
+
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.emplace_back(std::move(operation));
+ CacheStorageError error = BatchOperation(std::move(operations));
return error == CacheStorageError::kSuccess;
}
bool Keys(
const ServiceWorkerFetchRequest& request = ServiceWorkerFetchRequest(),
- const CacheStorageCacheQueryParams& match_params =
- CacheStorageCacheQueryParams()) {
+ blink::mojom::QueryParamsPtr match_params = nullptr) {
std::unique_ptr<base::RunLoop> loop(new base::RunLoop());
cache_->Keys(
- CopyFetchRequest(request), match_params,
+ CopyFetchRequest(request), std::move(match_params),
base::BindOnce(&CacheStorageCacheTest::RequestsCallback,
base::Unretained(this), base::Unretained(loop.get())));
loop->Run();
@@ -757,36 +758,39 @@ TEST_P(CacheStorageCacheTestP, PutBody) {
}
TEST_P(CacheStorageCacheTestP, PutBody_Multiple) {
- CacheStorageBatchOperation operation1;
- operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation1.request = body_request_;
- operation1.request.url = GURL("http://example.com/1");
- operation1.response = body_response_;
- operation1.response.url_list.push_back(GURL("http://example.com/1"));
-
- CacheStorageBatchOperation operation2;
- operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation2.request = body_request_;
- operation2.request.url = GURL("http://example.com/2");
- operation2.response = body_response_;
- operation2.response.url_list.push_back(GURL("http://example.com/2"));
-
- CacheStorageBatchOperation operation3;
- operation3.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation3.request = body_request_;
- operation3.request.url = GURL("http://example.com/3");
- operation3.response = body_response_;
- operation3.response.url_list.push_back(GURL("http://example.com/3"));
-
- std::vector<CacheStorageBatchOperation> operations;
- operations.push_back(operation1);
- operations.push_back(operation2);
- operations.push_back(operation3);
-
- EXPECT_EQ(CacheStorageError::kSuccess, BatchOperation(operations));
- EXPECT_TRUE(Match(operation1.request));
- EXPECT_TRUE(Match(operation2.request));
- EXPECT_TRUE(Match(operation3.request));
+ blink::mojom::BatchOperationPtr operation1 =
+ blink::mojom::BatchOperation::New();
+ operation1->operation_type = blink::mojom::OperationType::kPut;
+ operation1->request = body_request_;
+ operation1->request.url = GURL("http://example.com/1");
+ operation1->response = body_response_;
+ operation1->response->url_list.push_back(GURL("http://example.com/1"));
+
+ blink::mojom::BatchOperationPtr operation2 =
+ blink::mojom::BatchOperation::New();
+ operation2->operation_type = blink::mojom::OperationType::kPut;
+ operation2->request = body_request_;
+ operation2->request.url = GURL("http://example.com/2");
+ operation2->response = body_response_;
+ operation2->response->url_list.push_back(GURL("http://example.com/2"));
+
+ blink::mojom::BatchOperationPtr operation3 =
+ blink::mojom::BatchOperation::New();
+ operation3->operation_type = blink::mojom::OperationType::kPut;
+ operation3->request = body_request_;
+ operation3->request.url = GURL("http://example.com/3");
+ operation3->response = body_response_;
+ operation3->response->url_list.push_back(GURL("http://example.com/3"));
+
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.push_back(operation1->Clone());
+ operations.push_back(operation2->Clone());
+ operations.push_back(operation3->Clone());
+
+ EXPECT_EQ(CacheStorageError::kSuccess, BatchOperation(std::move(operations)));
+ EXPECT_TRUE(Match(operation1->request));
+ EXPECT_TRUE(Match(operation2->request));
+ EXPECT_TRUE(Match(operation3->request));
}
TEST_P(CacheStorageCacheTestP, MatchLimit) {
@@ -814,25 +818,25 @@ TEST_P(CacheStorageCacheTestP, MatchAllLimit) {
callback_response_->EstimatedStructSize();
std::vector<ServiceWorkerResponse> responses;
- CacheStorageCacheQueryParams match_params;
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
// There is enough room for both requests and responses
SetMaxQuerySizeBytes(body_request_size + query_request_size);
- EXPECT_TRUE(MatchAll(body_request_, match_params, &responses));
+ EXPECT_TRUE(MatchAll(body_request_, match_params->Clone(), &responses));
EXPECT_EQ(1u, responses.size());
- match_params.ignore_search = true;
- EXPECT_TRUE(MatchAll(body_request_, match_params, &responses));
+ match_params->ignore_search = true;
+ EXPECT_TRUE(MatchAll(body_request_, match_params->Clone(), &responses));
EXPECT_EQ(2u, responses.size());
// There is not enough room for both requests and responses
SetMaxQuerySizeBytes(body_request_size);
- match_params.ignore_search = false;
- EXPECT_TRUE(MatchAll(body_request_, match_params, &responses));
+ match_params->ignore_search = false;
+ EXPECT_TRUE(MatchAll(body_request_, match_params->Clone(), &responses));
EXPECT_EQ(1u, responses.size());
- match_params.ignore_search = true;
- EXPECT_FALSE(MatchAll(body_request_, match_params, &responses));
+ match_params->ignore_search = true;
+ EXPECT_FALSE(MatchAll(body_request_, match_params->Clone(), &responses));
EXPECT_EQ(CacheStorageError::kErrorQueryTooLarge, callback_error_);
}
@@ -876,14 +880,17 @@ TEST_P(CacheStorageCacheTestP, ResponseURLEmpty) {
}
TEST_P(CacheStorageCacheTestP, PutBodyDropBlobRef) {
- CacheStorageBatchOperation operation;
- operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation.request = body_request_;
- operation.response = body_response_;
-
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kPut;
+ operation->request = body_request_;
+ operation->response = body_response_;
+
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.emplace_back(std::move(operation));
std::unique_ptr<base::RunLoop> loop(new base::RunLoop());
cache_->BatchOperation(
- std::vector<CacheStorageBatchOperation>(1, operation),
+ std::move(operations),
base::BindOnce(&CacheStorageCacheTestP::ErrorTypeCallback,
base::Unretained(this), base::Unretained(loop.get())),
CacheStorageCache::BadMessageCallback());
@@ -896,15 +903,18 @@ TEST_P(CacheStorageCacheTestP, PutBodyDropBlobRef) {
}
TEST_P(CacheStorageCacheTestP, PutBadMessage) {
- CacheStorageBatchOperation operation;
- operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation.request = body_request_;
- operation.response = body_response_;
- operation.response.blob_size = UINT64_MAX;
-
- std::vector<CacheStorageBatchOperation> operations =
- std::vector<CacheStorageBatchOperation>(2, operation);
- EXPECT_EQ(CacheStorageError::kErrorStorage, BatchOperation(operations));
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kPut;
+ operation->request = body_request_;
+ operation->response = body_response_;
+ operation->response->blob_size = UINT64_MAX;
+
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.push_back(operation->Clone());
+ operations.push_back(operation->Clone());
+ EXPECT_EQ(CacheStorageError::kErrorStorage,
+ BatchOperation(std::move(operations)));
EXPECT_EQ("CSDH_UNEXPECTED_OPERATION", bad_message_reason_);
EXPECT_FALSE(Match(body_request_));
@@ -925,24 +935,26 @@ TEST_P(CacheStorageCacheTestP, PutReplace) {
}
TEST_P(CacheStorageCacheTestP, PutReplaceInBatch) {
- CacheStorageBatchOperation operation1;
- operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation1.request = body_request_;
- operation1.response = no_body_response_;
+ blink::mojom::BatchOperationPtr operation1 =
+ blink::mojom::BatchOperation::New();
+ operation1->operation_type = blink::mojom::OperationType::kPut;
+ operation1->request = body_request_;
+ operation1->response = no_body_response_;
- CacheStorageBatchOperation operation2;
- operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation2.request = body_request_;
- operation2.response = body_response_;
+ blink::mojom::BatchOperationPtr operation2 =
+ blink::mojom::BatchOperation::New();
+ operation2->operation_type = blink::mojom::OperationType::kPut;
+ operation2->request = body_request_;
+ operation2->response = body_response_;
- std::vector<CacheStorageBatchOperation> operations;
- operations.push_back(operation1);
- operations.push_back(operation2);
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.push_back(operation1->Clone());
+ operations.push_back(operation2->Clone());
- EXPECT_EQ(CacheStorageError::kSuccess, BatchOperation(operations));
+ EXPECT_EQ(CacheStorageError::kSuccess, BatchOperation(std::move(operations)));
// |operation2| should win.
- EXPECT_TRUE(Match(operation2.request));
+ EXPECT_TRUE(Match(operation2->request));
EXPECT_TRUE(callback_response_->blob);
}
@@ -1031,9 +1043,9 @@ TEST_P(CacheStorageCacheTestP, Match_IgnoreSearch) {
EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
EXPECT_FALSE(Match(body_request_));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
- EXPECT_TRUE(Match(body_request_, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
+ EXPECT_TRUE(Match(body_request_, std::move(match_params)));
}
TEST_P(CacheStorageCacheTestP, Match_IgnoreMethod) {
@@ -1043,9 +1055,9 @@ TEST_P(CacheStorageCacheTestP, Match_IgnoreMethod) {
post_request.method = "POST";
EXPECT_FALSE(Match(post_request));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_method = true;
- EXPECT_TRUE(Match(post_request, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_method = true;
+ EXPECT_TRUE(Match(post_request, std::move(match_params)));
}
TEST_P(CacheStorageCacheTestP, Match_IgnoreVary) {
@@ -1057,9 +1069,9 @@ TEST_P(CacheStorageCacheTestP, Match_IgnoreVary) {
body_request_.headers["vary_foo"] = "bar";
EXPECT_FALSE(Match(body_request_));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_vary = true;
- EXPECT_TRUE(Match(body_request_, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_vary = true;
+ EXPECT_TRUE(Match(body_request_, std::move(match_params)));
}
TEST_P(CacheStorageCacheTestP, Keys_IgnoreSearch) {
@@ -1068,9 +1080,9 @@ TEST_P(CacheStorageCacheTestP, Keys_IgnoreSearch) {
EXPECT_TRUE(Keys(body_request_));
EXPECT_EQ(0u, callback_strings_.size());
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
- EXPECT_TRUE(Keys(body_request_, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
+ EXPECT_TRUE(Keys(body_request_, std::move(match_params)));
EXPECT_EQ(1u, callback_strings_.size());
}
@@ -1082,9 +1094,9 @@ TEST_P(CacheStorageCacheTestP, Keys_IgnoreMethod) {
EXPECT_TRUE(Keys(post_request));
EXPECT_EQ(0u, callback_strings_.size());
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_method = true;
- EXPECT_TRUE(Keys(post_request, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_method = true;
+ EXPECT_TRUE(Keys(post_request, std::move(match_params)));
EXPECT_EQ(1u, callback_strings_.size());
}
@@ -1099,9 +1111,9 @@ TEST_P(CacheStorageCacheTestP, Keys_IgnoreVary) {
EXPECT_TRUE(Keys(body_request_));
EXPECT_EQ(0u, callback_strings_.size());
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_vary = true;
- EXPECT_TRUE(Keys(body_request_, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_vary = true;
+ EXPECT_TRUE(Keys(body_request_, std::move(match_params)));
EXPECT_EQ(1u, callback_strings_.size());
}
@@ -1109,9 +1121,9 @@ TEST_P(CacheStorageCacheTestP, Delete_IgnoreSearch) {
EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
EXPECT_FALSE(Delete(body_request_));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
- EXPECT_TRUE(Delete(body_request_, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
+ EXPECT_TRUE(Delete(body_request_, std::move(match_params)));
}
TEST_P(CacheStorageCacheTestP, Delete_IgnoreMethod) {
@@ -1121,9 +1133,9 @@ TEST_P(CacheStorageCacheTestP, Delete_IgnoreMethod) {
post_request.method = "POST";
EXPECT_FALSE(Delete(post_request));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_method = true;
- EXPECT_TRUE(Delete(post_request, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_method = true;
+ EXPECT_TRUE(Delete(post_request, std::move(match_params)));
}
TEST_P(CacheStorageCacheTestP, Delete_IgnoreVary) {
@@ -1134,9 +1146,9 @@ TEST_P(CacheStorageCacheTestP, Delete_IgnoreVary) {
body_request_.headers["vary_foo"] = "bar";
EXPECT_FALSE(Delete(body_request_));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_vary = true;
- EXPECT_TRUE(Delete(body_request_, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_vary = true;
+ EXPECT_TRUE(Delete(body_request_, std::move(match_params)));
}
TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreMethod) {
@@ -1145,13 +1157,13 @@ TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreMethod) {
ServiceWorkerFetchRequest post_request = body_request_;
post_request.method = "POST";
std::vector<ServiceWorkerResponse> responses;
- CacheStorageCacheQueryParams match_params;
- EXPECT_TRUE(MatchAll(post_request, match_params, &responses));
+ EXPECT_TRUE(MatchAll(post_request, nullptr, &responses));
EXPECT_EQ(0u, responses.size());
- match_params.ignore_method = true;
- EXPECT_TRUE(MatchAll(post_request, match_params, &responses));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_method = true;
+ EXPECT_TRUE(MatchAll(post_request, std::move(match_params), &responses));
EXPECT_EQ(1u, responses.size());
}
@@ -1160,17 +1172,17 @@ TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreVary) {
body_response_.headers["vary"] = "vary_foo";
EXPECT_TRUE(Put(body_request_, body_response_));
std::vector<ServiceWorkerResponse> responses;
- CacheStorageCacheQueryParams match_params;
- EXPECT_TRUE(MatchAll(body_request_, match_params, &responses));
+ EXPECT_TRUE(MatchAll(body_request_, nullptr, &responses));
EXPECT_EQ(1u, responses.size());
body_request_.headers["vary_foo"] = "bar";
- EXPECT_TRUE(MatchAll(body_request_, match_params, &responses));
+ EXPECT_TRUE(MatchAll(body_request_, nullptr, &responses));
EXPECT_EQ(0u, responses.size());
- match_params.ignore_vary = true;
- EXPECT_TRUE(MatchAll(body_request_, match_params, &responses));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_vary = true;
+ EXPECT_TRUE(MatchAll(body_request_, std::move(match_params), &responses));
EXPECT_EQ(1u, responses.size());
}
@@ -1180,9 +1192,9 @@ TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreSearch) {
EXPECT_TRUE(Put(no_body_request_, no_body_response_));
std::vector<ServiceWorkerResponse> responses;
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
- EXPECT_TRUE(MatchAll(body_request_, match_params, &responses));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
+ EXPECT_TRUE(MatchAll(body_request_, std::move(match_params), &responses));
ASSERT_EQ(2u, responses.size());
@@ -1208,13 +1220,13 @@ TEST_P(CacheStorageCacheTestP, MatchAll_Head) {
EXPECT_TRUE(Put(body_request_, body_response_));
std::vector<ServiceWorkerResponse> responses;
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
- EXPECT_TRUE(MatchAll(body_head_request_, match_params, &responses));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
+ EXPECT_TRUE(MatchAll(body_head_request_, match_params->Clone(), &responses));
EXPECT_TRUE(responses.empty());
- match_params.ignore_method = true;
- EXPECT_TRUE(MatchAll(body_head_request_, match_params, &responses));
+ match_params->ignore_method = true;
+ EXPECT_TRUE(MatchAll(body_head_request_, match_params->Clone(), &responses));
ASSERT_EQ(1u, responses.size());
EXPECT_TRUE(
ResponseMetadataEqual(SetCacheName(body_response_), responses[0]));
@@ -1315,10 +1327,10 @@ TEST_P(CacheStorageCacheTestP, KeysWithIgnoreSearchTrue) {
EXPECT_TRUE(Put(body_request_, body_response_));
EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
- EXPECT_TRUE(Keys(body_request_with_query_, match_params));
+ EXPECT_TRUE(Keys(body_request_with_query_, std::move(match_params)));
std::vector<std::string> expected_keys = {
body_request_.url.spec(), body_request_with_query_.url.spec()};
EXPECT_EQ(expected_keys, callback_strings_);
@@ -1330,12 +1342,10 @@ TEST_P(CacheStorageCacheTestP, KeysWithIgnoreSearchFalse) {
EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
// Default value of ignore_search is false.
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = false;
- EXPECT_EQ(match_params.ignore_search,
- CacheStorageCacheQueryParams().ignore_search);
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ EXPECT_EQ(match_params->ignore_search, false);
- EXPECT_TRUE(Keys(body_request_with_query_, match_params));
+ EXPECT_TRUE(Keys(body_request_with_query_, std::move(match_params)));
std::vector<std::string> expected_keys = {
body_request_with_query_.url.spec()};
EXPECT_EQ(expected_keys, callback_strings_);
@@ -1376,9 +1386,9 @@ TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchTrue) {
// The following delete operation will remove both of body_request_ and
// body_request_with_query_ from cache storage.
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
- EXPECT_TRUE(Delete(body_request_with_query_, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
+ EXPECT_TRUE(Delete(body_request_with_query_, std::move(match_params)));
EXPECT_TRUE(Keys());
expected_keys.clear();
@@ -1398,12 +1408,10 @@ TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchFalse) {
EXPECT_EQ(expected_keys, callback_strings_);
// Default value of ignore_search is false.
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = false;
- EXPECT_EQ(match_params.ignore_search,
- CacheStorageCacheQueryParams().ignore_search);
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ EXPECT_EQ(match_params->ignore_search, false);
- EXPECT_TRUE(Delete(body_request_with_query_, match_params));
+ EXPECT_TRUE(Delete(body_request_with_query_, std::move(match_params)));
EXPECT_TRUE(Keys());
std::vector<std::string> expected_keys2{no_body_request_.url.spec(),
@@ -1504,15 +1512,17 @@ TEST_P(CacheStorageCacheTestP, PutWithSideData_BadMessage) {
CopySideDataToResponse(side_data_blob_handle.get(), &response);
- CacheStorageBatchOperation operation;
- operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation.request = body_request_;
- operation.response = response;
- operation.response.blob_size = UINT64_MAX;
-
- std::vector<CacheStorageBatchOperation> operations =
- std::vector<CacheStorageBatchOperation>(1, operation);
- EXPECT_EQ(CacheStorageError::kErrorStorage, BatchOperation(operations));
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kPut;
+ operation->request = body_request_;
+ operation->response = response;
+ operation->response->blob_size = UINT64_MAX;
+
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.emplace_back(std::move(operation));
+ EXPECT_EQ(CacheStorageError::kErrorStorage,
+ BatchOperation(std::move(operations)));
EXPECT_EQ("CSDH_UNEXPECTED_OPERATION", bad_message_reason_);
EXPECT_FALSE(Match(body_request_));
@@ -1836,14 +1846,17 @@ TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
int sequence_out = -1;
- CacheStorageBatchOperation operation1;
- operation1.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation1.request = body_request_;
- operation1.response = body_response_;
+ blink::mojom::BatchOperationPtr operation1 =
+ blink::mojom::BatchOperation::New();
+ operation1->operation_type = blink::mojom::OperationType::kPut;
+ operation1->request = body_request_;
+ operation1->response = body_response_;
std::unique_ptr<base::RunLoop> close_loop1(new base::RunLoop());
+ std::vector<blink::mojom::BatchOperationPtr> operations1;
+ operations1.emplace_back(std::move(operation1));
cache_->BatchOperation(
- std::vector<CacheStorageBatchOperation>(1, operation1),
+ std::move(operations1),
base::BindOnce(&CacheStorageCacheTest::SequenceCallback,
base::Unretained(this), 1, &sequence_out,
close_loop1.get()),
@@ -1852,15 +1865,18 @@ TEST_P(CacheStorageCacheTestP, VerifySerialScheduling) {
// Blocks on creating the cache entry.
base::RunLoop().RunUntilIdle();
- CacheStorageBatchOperation operation2;
- operation2.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation2.request = body_request_;
- operation2.response = body_response_;
+ blink::mojom::BatchOperationPtr operation2 =
+ blink::mojom::BatchOperation::New();
+ operation2->operation_type = blink::mojom::OperationType::kPut;
+ operation2->request = body_request_;
+ operation2->response = body_response_;
delayable_backend->set_delay_open_entry(false);
std::unique_ptr<base::RunLoop> close_loop2(new base::RunLoop());
+ std::vector<blink::mojom::BatchOperationPtr> operations2;
+ operations2.emplace_back(std::move(operation2));
cache_->BatchOperation(
- std::vector<CacheStorageBatchOperation>(1, operation2),
+ std::move(operations2),
base::BindOnce(&CacheStorageCacheTest::SequenceCallback,
base::Unretained(this), 2, &sequence_out,
close_loop2.get()),
diff --git a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
index e7a6c1f7b3f..17157f81340 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -91,13 +91,14 @@ void CacheStorageContextImpl::GetAllOriginsInfo(
return;
}
- cache_manager_->GetAllOriginsUsage(callback);
+ cache_manager_->GetAllOriginsUsage(CacheStorageOwner::kCacheAPI, callback);
}
void CacheStorageContextImpl::DeleteForOrigin(const GURL& origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (cache_manager_)
- cache_manager_->DeleteOriginData(url::Origin::Create(origin));
+ cache_manager_->DeleteOriginData(url::Origin::Create(origin),
+ CacheStorageOwner::kCacheAPI);
}
void CacheStorageContextImpl::AddObserver(
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
index 9680429f601..60669ac676e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -61,7 +62,7 @@ class CacheStorageDispatcherHost::CacheImpl
// blink::mojom::CacheStorageCache implementation:
void Match(const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
MatchCallback callback) override {
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
@@ -73,15 +74,15 @@ class CacheStorageDispatcherHost::CacheImpl
auto scoped_request = std::make_unique<ServiceWorkerFetchRequest>(
request.url, request.method, request.headers, request.referrer,
request.is_reload);
- cache->Match(std::move(scoped_request), match_params,
- base::BindOnce(&CacheImpl::OnCacheMatchCallback,
- weak_factory_.GetWeakPtr(), std::move(callback),
- cache_handle_.Clone()));
+
+ cache->Match(
+ std::move(scoped_request), std::move(match_params),
+ base::BindOnce(&CacheImpl::OnCacheMatchCallback,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnCacheMatchCallback(
blink::mojom::CacheStorageCache::MatchCallback callback,
- CacheStorageCacheHandle cache_handle,
blink::mojom::CacheStorageError error,
std::unique_ptr<ServiceWorkerResponse> response) {
if (error != CacheStorageError::kSuccess) {
@@ -92,8 +93,8 @@ class CacheStorageDispatcherHost::CacheImpl
std::move(callback).Run(blink::mojom::MatchResult::NewResponse(*response));
}
- void MatchAll(const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params,
+ void MatchAll(const base::Optional<ServiceWorkerFetchRequest>& request,
+ blink::mojom::QueryParamsPtr match_params,
MatchAllCallback callback) override {
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
@@ -102,36 +103,22 @@ class CacheStorageDispatcherHost::CacheImpl
return;
}
- if (request.url.is_empty()) {
- cache->MatchAll(
- nullptr, match_params,
- base::BindOnce(&CacheImpl::OnCacheMatchAllCallback,
- weak_factory_.GetWeakPtr(), std::move(callback),
- cache_handle_.Clone()));
- return;
- }
+ std::unique_ptr<ServiceWorkerFetchRequest> request_ptr;
- auto scoped_request = std::make_unique<ServiceWorkerFetchRequest>(
- request.url, request.method, request.headers, request.referrer,
- request.is_reload);
- if (match_params.ignore_search) {
- cache->MatchAll(
- std::move(scoped_request), match_params,
- base::BindOnce(&CacheImpl::OnCacheMatchAllCallback,
- weak_factory_.GetWeakPtr(), std::move(callback),
- cache_handle_.Clone()));
- return;
+ if (request && !request->url.is_empty()) {
+ request_ptr = std::make_unique<ServiceWorkerFetchRequest>(
+ request->url, request->method, request->headers, request->referrer,
+ request->is_reload);
}
- cache->Match(std::move(scoped_request), match_params,
- base::BindOnce(&CacheImpl::OnCacheMatchAllCallbackAdapter,
- weak_factory_.GetWeakPtr(), std::move(callback),
- cache_handle_.Clone()));
+ cache->MatchAll(
+ std::move(request_ptr), std::move(match_params),
+ base::BindOnce(&CacheImpl::OnCacheMatchAllCallback,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnCacheMatchAllCallback(
blink::mojom::CacheStorageCache::MatchAllCallback callback,
- CacheStorageCacheHandle cache_handle,
blink::mojom::CacheStorageError error,
std::vector<ServiceWorkerResponse> responses) {
if (error != CacheStorageError::kSuccess &&
@@ -144,22 +131,8 @@ class CacheStorageDispatcherHost::CacheImpl
blink::mojom::MatchAllResult::NewResponses(std::move(responses)));
}
- void OnCacheMatchAllCallbackAdapter(
- blink::mojom::CacheStorageCache::MatchAllCallback callback,
- CacheStorageCacheHandle cache_handle,
- blink::mojom::CacheStorageError error,
- std::unique_ptr<ServiceWorkerResponse> response) {
- std::vector<ServiceWorkerResponse> responses;
- if (error == CacheStorageError::kSuccess) {
- DCHECK(response);
- responses.push_back(std::move(*response.release()));
- }
- OnCacheMatchAllCallback(std::move(callback), std::move(cache_handle), error,
- std::move(responses));
- }
-
- void Keys(const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params,
+ void Keys(const base::Optional<ServiceWorkerFetchRequest>& request,
+ blink::mojom::QueryParamsPtr match_params,
KeysCallback callback) override {
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
@@ -168,18 +141,21 @@ class CacheStorageDispatcherHost::CacheImpl
return;
}
- auto request_ptr = std::make_unique<ServiceWorkerFetchRequest>(
- request.url, request.method, request.headers, request.referrer,
- request.is_reload);
- cache->Keys(std::move(request_ptr), match_params,
- base::BindOnce(&CacheImpl::OnCacheKeysCallback,
- weak_factory_.GetWeakPtr(), std::move(callback),
- cache_handle_.Clone()));
+ std::unique_ptr<ServiceWorkerFetchRequest> request_ptr;
+
+ if (request) {
+ request_ptr = std::make_unique<ServiceWorkerFetchRequest>(
+ request->url, request->method, request->headers, request->referrer,
+ request->is_reload);
+ }
+ cache->Keys(
+ std::move(request_ptr), std::move(match_params),
+ base::BindOnce(&CacheImpl::OnCacheKeysCallback,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnCacheKeysCallback(
blink::mojom::CacheStorageCache::KeysCallback callback,
- CacheStorageCacheHandle cache_handle,
blink::mojom::CacheStorageError error,
std::unique_ptr<content::CacheStorageCache::Requests> requests) {
if (error != CacheStorageError::kSuccess) {
@@ -190,7 +166,7 @@ class CacheStorageDispatcherHost::CacheImpl
std::move(callback).Run(blink::mojom::CacheKeysResult::NewKeys(*requests));
}
- void Batch(const std::vector<CacheStorageBatchOperation>& batch_operations,
+ void Batch(std::vector<blink::mojom::BatchOperationPtr> batch_operations,
BatchCallback callback) override {
content::CacheStorageCache* cache = cache_handle_.value();
if (!cache) {
@@ -198,17 +174,15 @@ class CacheStorageDispatcherHost::CacheImpl
return;
}
cache->BatchOperation(
- batch_operations,
+ std::move(batch_operations),
base::BindOnce(&CacheImpl::OnCacheBatchCallback,
- weak_factory_.GetWeakPtr(), std::move(callback),
- cache_handle_.Clone()),
+ weak_factory_.GetWeakPtr(), std::move(callback)),
base::BindOnce(&CacheImpl::OnBadMessage, weak_factory_.GetWeakPtr(),
mojo::GetBadMessageCallback()));
}
void OnCacheBatchCallback(
blink::mojom::CacheStorageCache::BatchCallback callback,
- CacheStorageCacheHandle cache_handle,
blink::mojom::CacheStorageError error) {
std::move(callback).Run(error);
}
@@ -257,7 +231,7 @@ void CacheStorageDispatcherHost::Has(
if (!ValidState())
return;
context_->cache_manager()->HasCache(
- origin, base::UTF16ToUTF8(cache_name),
+ origin, CacheStorageOwner::kCacheAPI, base::UTF16ToUTF8(cache_name),
base::BindOnce(&CacheStorageDispatcherHost::OnHasCallback, this,
std::move(callback)));
}
@@ -275,7 +249,7 @@ void CacheStorageDispatcherHost::Open(
if (!ValidState())
return;
context_->cache_manager()->OpenCache(
- origin, base::UTF16ToUTF8(cache_name),
+ origin, CacheStorageOwner::kCacheAPI, base::UTF16ToUTF8(cache_name),
base::BindOnce(&CacheStorageDispatcherHost::OnOpenCallback, this, origin,
std::move(callback)));
}
@@ -292,7 +266,9 @@ void CacheStorageDispatcherHost::Delete(
}
if (!ValidState())
return;
- context_->cache_manager()->DeleteCache(origin, base::UTF16ToUTF8(cache_name),
+ context_->cache_manager()->DeleteCache(origin, CacheStorageOwner::kCacheAPI,
+ base::UTF16ToUTF8(cache_name),
+
std::move(callback));
}
@@ -309,13 +285,14 @@ void CacheStorageDispatcherHost::Keys(
if (!ValidState())
return;
context_->cache_manager()->EnumerateCaches(
- origin, base::BindOnce(&CacheStorageDispatcherHost::OnKeysCallback, this,
- std::move(callback)));
+ origin, CacheStorageOwner::kCacheAPI,
+ base::BindOnce(&CacheStorageDispatcherHost::OnKeysCallback, this,
+ std::move(callback)));
}
void CacheStorageDispatcherHost::Match(
const content::ServiceWorkerFetchRequest& request,
- const content::CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
blink::mojom::CacheStorage::MatchCallback callback) {
TRACE_EVENT0("CacheStorage",
"CacheStorageDispatcherHost::OnCacheStorageMatch");
@@ -330,15 +307,17 @@ void CacheStorageDispatcherHost::Match(
request.url, request.method, request.headers, request.referrer,
request.is_reload);
- if (match_params.cache_name.is_null()) {
+ if (!match_params->cache_name) {
context_->cache_manager()->MatchAllCaches(
- origin, std::move(scoped_request), std::move(match_params),
+ origin, CacheStorageOwner::kCacheAPI, std::move(scoped_request),
+ std::move(match_params),
base::BindOnce(&CacheStorageDispatcherHost::OnMatchCallback, this,
std::move(callback)));
return;
}
+ std::string cache_name = base::UTF16ToUTF8(*match_params->cache_name);
context_->cache_manager()->MatchCache(
- origin, base::UTF16ToUTF8(match_params.cache_name.string()),
+ origin, CacheStorageOwner::kCacheAPI, std::move(cache_name),
std::move(scoped_request), std::move(match_params),
base::BindOnce(&CacheStorageDispatcherHost::OnMatchCallback, this,
std::move(callback)));
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
index 3dde6c6d6a6..f4f99042e39 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -70,7 +70,7 @@ class CONTENT_EXPORT CacheStorageDispatcherHost
void Has(const base::string16& cache_name,
blink::mojom::CacheStorage::HasCallback callback) override;
void Match(const content::ServiceWorkerFetchRequest& request,
- const content::CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
blink::mojom::CacheStorage::MatchCallback callback) override;
void Open(const base::string16& cache_name,
blink::mojom::CacheStorage::OpenCallback callback) override;
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index d87786e203f..eb0fbd228dd 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <map>
+#include <numeric>
#include <set>
#include <utility>
@@ -71,7 +72,8 @@ int64_t GetCacheStorageSize(const proto::CacheStorageIndex& index) {
// sizes (if current), and last modified times.
void ListOriginsAndLastModifiedOnTaskRunner(
std::vector<CacheStorageUsageInfo>* usages,
- base::FilePath root_path) {
+ base::FilePath root_path,
+ CacheStorageOwner owner) {
base::FileEnumerator file_enum(root_path, false /* recursive */,
base::FileEnumerator::DIRECTORIES);
@@ -88,21 +90,26 @@ void ListOriginsAndLastModifiedOnTaskRunner(
proto::CacheStorageIndex index;
if (index.ParseFromString(protobuf)) {
if (index.has_origin()) {
- if (base::GetFileInfo(path, &file_info)) {
- int64_t storage_size = CacheStorage::kSizeUnknown;
- if (file_info.last_modified < index_last_modified)
- storage_size = GetCacheStorageSize(index);
- usages->push_back(CacheStorageUsageInfo(
- GURL(index.origin()), storage_size, file_info.last_modified));
+ if (path ==
+ CacheStorageManager::ConstructOriginPath(
+ root_path, url::Origin::Create(GURL(index.origin())), owner)) {
+ if (base::GetFileInfo(path, &file_info)) {
+ int64_t storage_size = CacheStorage::kSizeUnknown;
+ if (file_info.last_modified < index_last_modified)
+ storage_size = GetCacheStorageSize(index);
+ usages->push_back(CacheStorageUsageInfo(
+ GURL(index.origin()), storage_size, file_info.last_modified));
+ }
}
}
}
}
}
-std::set<url::Origin> ListOriginsOnTaskRunner(base::FilePath root_path) {
+std::set<url::Origin> ListOriginsOnTaskRunner(base::FilePath root_path,
+ CacheStorageOwner owner) {
std::vector<CacheStorageUsageInfo> usages;
- ListOriginsAndLastModifiedOnTaskRunner(&usages, root_path);
+ ListOriginsAndLastModifiedOnTaskRunner(&usages, root_path, owner);
std::set<url::Origin> out_origins;
for (const CacheStorageUsageInfo& usage : usages)
@@ -177,67 +184,89 @@ CacheStorageManager::~CacheStorageManager() = default;
void CacheStorageManager::OpenCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage::CacheAndErrorCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
cache_storage->OpenCache(cache_name, std::move(callback));
}
void CacheStorageManager::HasCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage::BoolAndErrorCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
cache_storage->HasCache(cache_name, std::move(callback));
}
void CacheStorageManager::DeleteCache(const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage::ErrorCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
cache_storage->DoomCache(cache_name, std::move(callback));
}
void CacheStorageManager::EnumerateCaches(
const url::Origin& origin,
+ CacheStorageOwner owner,
CacheStorage::IndexCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
cache_storage->EnumerateCaches(std::move(callback));
}
void CacheStorageManager::MatchCache(
const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback) {
- CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
- cache_storage->MatchCache(cache_name, std::move(request), match_params,
- std::move(callback));
+ cache_storage->MatchCache(cache_name, std::move(request),
+ std::move(match_params), std::move(callback));
}
void CacheStorageManager::MatchAllCaches(
const url::Origin& origin,
+ CacheStorageOwner owner,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback) {
- CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
- cache_storage->MatchAllCaches(std::move(request), match_params,
+ cache_storage->MatchAllCaches(std::move(request), std::move(match_params),
std::move(callback));
}
+void CacheStorageManager::WriteToCache(
+ const url::Origin& origin,
+ CacheStorageOwner owner,
+ const std::string& cache_name,
+ std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ CacheStorage::ErrorCallback callback) {
+ // Cache API should write through the dispatcher.
+ DCHECK_NE(owner, CacheStorageOwner::kCacheAPI);
+
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
+
+ cache_storage->WriteToCache(cache_name, std::move(request),
+ std::move(response), std::move(callback));
+}
+
void CacheStorageManager::SetBlobParametersForCache(
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context) {
@@ -273,6 +302,7 @@ void CacheStorageManager::NotifyCacheContentChanged(const url::Origin& origin,
}
void CacheStorageManager::GetAllOriginsUsage(
+ CacheStorageOwner owner,
CacheStorageContext::GetUsageInfoCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -281,9 +311,11 @@ void CacheStorageManager::GetAllOriginsUsage(
if (IsMemoryBacked()) {
for (const auto& origin_details : cache_storage_map_) {
- usages->push_back(
- CacheStorageUsageInfo(origin_details.first.GetURL(), 0 /* size */,
- base::Time() /* last modified */));
+ if (origin_details.first.second != owner)
+ continue;
+ usages->push_back(CacheStorageUsageInfo(
+ origin_details.first.first.GetURL(), 0 /* size */,
+ base::Time() /* last modified */));
}
GetAllOriginsUsageGetSizes(std::move(usages), std::move(callback));
return;
@@ -293,7 +325,7 @@ void CacheStorageManager::GetAllOriginsUsage(
cache_task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&ListOriginsAndLastModifiedOnTaskRunner, usages_ptr,
- root_path_),
+ root_path_, owner),
base::BindOnce(&CacheStorageManager::GetAllOriginsUsageGetSizes,
weak_ptr_factory_.GetWeakPtr(), std::move(usages),
std::move(callback)));
@@ -325,8 +357,8 @@ void CacheStorageManager::GetAllOriginsUsageGetSizes(
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, barrier_closure);
continue;
}
- CacheStorage* cache_storage =
- FindOrCreateCacheStorage(url::Origin::Create(usage.origin));
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(
+ url::Origin::Create(usage.origin), CacheStorageOwner::kCacheAPI);
cache_storage->Size(
base::BindOnce(&OneOriginSizeReported, barrier_closure, &usage));
}
@@ -334,22 +366,25 @@ void CacheStorageManager::GetAllOriginsUsageGetSizes(
void CacheStorageManager::GetOriginUsage(
const url::Origin& origin,
+ CacheStorageOwner owner,
storage::QuotaClient::GetUsageCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- CacheStorage* cache_storage = FindOrCreateCacheStorage(origin);
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner);
cache_storage->Size(std::move(callback));
}
void CacheStorageManager::GetOrigins(
+ CacheStorageOwner owner,
storage::QuotaClient::GetOriginsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (IsMemoryBacked()) {
std::set<url::Origin> origins;
for (const auto& key_value : cache_storage_map_)
- origins.insert(key_value.first);
+ if (key_value.first.second == owner)
+ origins.insert(key_value.first.first);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), origins));
@@ -358,20 +393,23 @@ void CacheStorageManager::GetOrigins(
PostTaskAndReplyWithResult(
cache_task_runner_.get(), FROM_HERE,
- base::BindOnce(&ListOriginsOnTaskRunner, root_path_),
+ base::BindOnce(&ListOriginsOnTaskRunner, root_path_, owner),
std::move(callback));
}
void CacheStorageManager::GetOriginsForHost(
const std::string& host,
+ CacheStorageOwner owner,
storage::QuotaClient::GetOriginsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (IsMemoryBacked()) {
std::set<url::Origin> origins;
for (const auto& key_value : cache_storage_map_) {
- if (host == net::GetHostOrSpecFromURL(key_value.first.GetURL()))
- origins.insert(key_value.first);
+ if (key_value.first.second != owner)
+ continue;
+ if (host == net::GetHostOrSpecFromURL(key_value.first.first.GetURL()))
+ origins.insert(key_value.first.first);
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), origins));
@@ -380,38 +418,41 @@ void CacheStorageManager::GetOriginsForHost(
PostTaskAndReplyWithResult(
cache_task_runner_.get(), FROM_HERE,
- base::BindOnce(&ListOriginsOnTaskRunner, root_path_),
+ base::BindOnce(&ListOriginsOnTaskRunner, root_path_, owner),
base::BindOnce(&GetOriginsForHostDidListOrigins, host,
std::move(callback)));
}
void CacheStorageManager::DeleteOriginData(
const url::Origin& origin,
+ CacheStorageOwner owner,
storage::QuotaClient::DeletionCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Create the CacheStorage for the origin if it hasn't been loaded yet.
- FindOrCreateCacheStorage(origin);
+ FindOrCreateCacheStorage(origin, owner);
- CacheStorageMap::iterator it = cache_storage_map_.find(origin);
+ CacheStorageMap::iterator it = cache_storage_map_.find({origin, owner});
DCHECK(it != cache_storage_map_.end());
CacheStorage* cache_storage = it->second.release();
cache_storage->ResetManager();
- cache_storage_map_.erase(origin);
+ cache_storage_map_.erase({origin, owner});
cache_storage->GetSizeThenCloseAllCaches(
base::BindOnce(&CacheStorageManager::DeleteOriginDidClose,
- weak_ptr_factory_.GetWeakPtr(), origin,
+ weak_ptr_factory_.GetWeakPtr(), origin, owner,
std::move(callback), base::WrapUnique(cache_storage)));
}
-void CacheStorageManager::DeleteOriginData(const url::Origin& origin) {
+void CacheStorageManager::DeleteOriginData(const url::Origin& origin,
+ CacheStorageOwner owner) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DeleteOriginData(origin, base::DoNothing());
+ DeleteOriginData(origin, owner, base::DoNothing());
}
void CacheStorageManager::DeleteOriginDidClose(
const url::Origin& origin,
+ CacheStorageOwner owner,
storage::QuotaClient::DeletionCallback callback,
std::unique_ptr<CacheStorage> cache_storage,
int64_t origin_size) {
@@ -421,9 +462,11 @@ void CacheStorageManager::DeleteOriginDidClose(
cache_storage.reset();
quota_manager_proxy_->NotifyStorageModified(
- storage::QuotaClient::kServiceWorkerCache, origin,
+ CacheStorageQuotaClient::GetIDFromOwner(owner), origin,
blink::mojom::StorageType::kTemporary, -1 * origin_size);
- NotifyCacheListChanged(origin);
+
+ if (owner == CacheStorageOwner::kCacheAPI)
+ NotifyCacheListChanged(origin);
if (IsMemoryBacked()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -434,7 +477,8 @@ void CacheStorageManager::DeleteOriginDidClose(
PostTaskAndReplyWithResult(
cache_task_runner_.get(), FROM_HERE,
- base::BindOnce(&DeleteDir, ConstructOriginPath(root_path_, origin)),
+ base::BindOnce(&DeleteDir,
+ ConstructOriginPath(root_path_, origin, owner)),
base::BindOnce(&DeleteOriginDidDeleteDir, std::move(callback)));
}
@@ -447,23 +491,25 @@ CacheStorageManager::CacheStorageManager(
quota_manager_proxy_(std::move(quota_manager_proxy)),
weak_ptr_factory_(this) {
if (quota_manager_proxy_.get()) {
- quota_manager_proxy_->RegisterClient(
- new CacheStorageQuotaClient(weak_ptr_factory_.GetWeakPtr()));
+ quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
+ weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kCacheAPI));
+ quota_manager_proxy_->RegisterClient(new CacheStorageQuotaClient(
+ weak_ptr_factory_.GetWeakPtr(), CacheStorageOwner::kBackgroundFetch));
}
}
CacheStorage* CacheStorageManager::FindOrCreateCacheStorage(
- const url::Origin& origin) {
+ const url::Origin& origin,
+ CacheStorageOwner owner) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(request_context_getter_);
- CacheStorageMap::const_iterator it = cache_storage_map_.find(origin);
+ CacheStorageMap::const_iterator it = cache_storage_map_.find({origin, owner});
if (it == cache_storage_map_.end()) {
CacheStorage* cache_storage = new CacheStorage(
- ConstructOriginPath(root_path_, origin), IsMemoryBacked(),
+ ConstructOriginPath(root_path_, origin, owner), IsMemoryBacked(),
cache_task_runner_.get(), request_context_getter_, quota_manager_proxy_,
- blob_context_, this, origin);
- cache_storage_map_.insert(
- std::make_pair(origin, base::WrapUnique(cache_storage)));
+ blob_context_, this, origin, owner);
+ cache_storage_map_[{origin, owner}] = base::WrapUnique(cache_storage);
return cache_storage;
}
return it->second.get();
@@ -472,8 +518,12 @@ CacheStorage* CacheStorageManager::FindOrCreateCacheStorage(
// static
base::FilePath CacheStorageManager::ConstructOriginPath(
const base::FilePath& root_path,
- const url::Origin& origin) {
- const std::string identifier = storage::GetIdentifierFromOrigin(origin);
+ const url::Origin& origin,
+ CacheStorageOwner owner) {
+ std::string identifier = storage::GetIdentifierFromOrigin(origin);
+ if (owner != CacheStorageOwner::kCacheAPI) {
+ identifier += "-" + std::to_string(static_cast<int>(owner));
+ }
const std::string origin_hash = base::SHA1HashString(identifier);
const std::string origin_hash_hex = base::ToLowerASCII(
base::HexEncode(origin_hash.c_str(), origin_hash.length()));
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.h b/chromium/content/browser/cache_storage/cache_storage_manager.h
index f053d4c1dbd..e94dfa631b4 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.h
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.h
@@ -39,6 +39,18 @@ namespace cache_storage_manager_unittest {
class CacheStorageManagerTest;
}
+enum class CacheStorageOwner {
+ kMinValue,
+
+ // Caches that can be accessed by the JS CacheStorage API (developer facing).
+ kCacheAPI = kMinValue,
+
+ // Private cache to store background fetch downloads.
+ kBackgroundFetch,
+
+ kMaxValue = kBackgroundFetch
+};
+
// Keeps track of a CacheStorage per origin. There is one
// CacheStorageManager per ServiceWorkerContextCore.
// TODO(jkarlin): Remove CacheStorage from memory once they're no
@@ -55,33 +67,50 @@ class CONTENT_EXPORT CacheStorageManager {
// Map a database identifier (computed from an origin) to the path.
static base::FilePath ConstructOriginPath(const base::FilePath& root_path,
- const url::Origin& origin);
+ const url::Origin& origin,
+ CacheStorageOwner owner);
virtual ~CacheStorageManager();
// Methods to support the CacheStorage spec. These methods call the
// corresponding CacheStorage method on the appropriate thread.
void OpenCache(const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage::CacheAndErrorCallback callback);
void HasCache(const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage::BoolAndErrorCallback callback);
void DeleteCache(const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
CacheStorage::ErrorCallback callback);
void EnumerateCaches(const url::Origin& origin,
+ CacheStorageOwner owner,
CacheStorage::IndexCallback callback);
void MatchCache(const url::Origin& origin,
+ CacheStorageOwner owner,
const std::string& cache_name,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback);
void MatchAllCaches(const url::Origin& origin,
+ CacheStorageOwner owner,
std::unique_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCacheQueryParams& match_params,
+ blink::mojom::QueryParamsPtr match_params,
CacheStorageCache::ResponseCallback callback);
+ // Method to support writing to a cache directly from CacheStorageManager.
+ // This should be used by non-CacheAPI owners. The Cache API writes are
+ // handled via the dispatcher.
+ void WriteToCache(const url::Origin& origin,
+ CacheStorageOwner owner,
+ const std::string& cache_name,
+ std::unique_ptr<ServiceWorkerFetchRequest> request,
+ std::unique_ptr<ServiceWorkerResponse> response,
+ CacheStorage::ErrorCallback callback);
+
// This must be called before creating any of the public *Cache functions
// above.
void SetBlobParametersForCache(
@@ -106,7 +135,9 @@ class CONTENT_EXPORT CacheStorageManager {
friend class cache_storage_manager_unittest::CacheStorageManagerTest;
friend class CacheStorageQuotaClient;
- typedef std::map<url::Origin, std::unique_ptr<CacheStorage>> CacheStorageMap;
+ typedef std::map<std::pair<url::Origin, CacheStorageOwner>,
+ std::unique_ptr<CacheStorage>>
+ CacheStorageMap;
CacheStorageManager(
const base::FilePath& path,
@@ -114,23 +145,30 @@ class CONTENT_EXPORT CacheStorageManager {
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
// The returned CacheStorage* is owned by this manager.
- CacheStorage* FindOrCreateCacheStorage(const url::Origin& origin);
+ CacheStorage* FindOrCreateCacheStorage(const url::Origin& origin,
+ CacheStorageOwner owner);
// QuotaClient and Browsing Data Deletion support
- void GetAllOriginsUsage(CacheStorageContext::GetUsageInfoCallback callback);
+ void GetAllOriginsUsage(CacheStorageOwner owner,
+ CacheStorageContext::GetUsageInfoCallback callback);
void GetAllOriginsUsageGetSizes(
std::unique_ptr<std::vector<CacheStorageUsageInfo>> usage_info,
CacheStorageContext::GetUsageInfoCallback callback);
void GetOriginUsage(const url::Origin& origin_url,
+ CacheStorageOwner owner,
storage::QuotaClient::GetUsageCallback callback);
- void GetOrigins(storage::QuotaClient::GetOriginsCallback callback);
+ void GetOrigins(CacheStorageOwner owner,
+ storage::QuotaClient::GetOriginsCallback callback);
void GetOriginsForHost(const std::string& host,
+ CacheStorageOwner owner,
storage::QuotaClient::GetOriginsCallback callback);
void DeleteOriginData(const url::Origin& origin,
+ CacheStorageOwner owner,
storage::QuotaClient::DeletionCallback callback);
- void DeleteOriginData(const url::Origin& origin);
+ void DeleteOriginData(const url::Origin& origin, CacheStorageOwner owner);
void DeleteOriginDidClose(const url::Origin& origin,
+ CacheStorageOwner owner,
storage::QuotaClient::DeletionCallback callback,
std::unique_ptr<CacheStorage> cache_storage,
int64_t origin_size);
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
index 2ccc79e2a13..e779d23257c 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -63,6 +63,31 @@ namespace cache_storage_manager_unittest {
using blink::mojom::StorageType;
+class MockCacheStorageQuotaManagerProxy : public MockQuotaManagerProxy {
+ public:
+ MockCacheStorageQuotaManagerProxy(MockQuotaManager* quota_manager,
+ base::SingleThreadTaskRunner* task_runner)
+ : MockQuotaManagerProxy(quota_manager, task_runner) {}
+
+ void RegisterClient(QuotaClient* client) override {
+ registered_clients_.push_back(client);
+ }
+
+ void SimulateQuotaManagerDestroyed() override {
+ for (auto* client : registered_clients_) {
+ client->OnQuotaManagerDestroyed();
+ }
+ registered_clients_.clear();
+ }
+
+ private:
+ ~MockCacheStorageQuotaManagerProxy() override {
+ DCHECK(registered_clients_.empty());
+ }
+
+ std::vector<QuotaClient*> registered_clients_;
+};
+
bool IsIndexFileCurrent(const base::FilePath& cache_dir) {
base::File::Info info;
const base::FilePath index_path =
@@ -234,7 +259,7 @@ class CacheStorageManagerTest : public testing::Test {
mock_quota_manager_->SetQuota(origin2_.GetURL(), StorageType::kTemporary,
1024 * 1024 * 100);
- quota_manager_proxy_ = new MockQuotaManagerProxy(
+ quota_manager_proxy_ = new MockCacheStorageQuotaManagerProxy(
mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
cache_manager_ = CacheStorageManager::Create(
@@ -281,10 +306,12 @@ class CacheStorageManagerTest : public testing::Test {
cache_manager_ = nullptr;
}
- bool Open(const url::Origin& origin, const std::string& cache_name) {
+ bool Open(const url::Origin& origin,
+ const std::string& cache_name,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
base::RunLoop loop;
cache_manager_->OpenCache(
- origin, cache_name,
+ origin, owner, cache_name,
base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -297,10 +324,12 @@ class CacheStorageManagerTest : public testing::Test {
return !error;
}
- bool Has(const url::Origin& origin, const std::string& cache_name) {
+ bool Has(const url::Origin& origin,
+ const std::string& cache_name,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
base::RunLoop loop;
cache_manager_->HasCache(
- origin, cache_name,
+ origin, owner, cache_name,
base::BindOnce(&CacheStorageManagerTest::BoolAndErrorCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -308,10 +337,12 @@ class CacheStorageManagerTest : public testing::Test {
return callback_bool_;
}
- bool Delete(const url::Origin& origin, const std::string& cache_name) {
+ bool Delete(const url::Origin& origin,
+ const std::string& cache_name,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
base::RunLoop loop;
cache_manager_->DeleteCache(
- origin, cache_name,
+ origin, owner, cache_name,
base::BindOnce(&CacheStorageManagerTest::ErrorCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -319,10 +350,11 @@ class CacheStorageManagerTest : public testing::Test {
return callback_bool_;
}
- size_t Keys(const url::Origin& origin) {
+ size_t Keys(const url::Origin& origin,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
base::RunLoop loop;
cache_manager_->EnumerateCaches(
- origin,
+ origin, owner,
base::BindOnce(&CacheStorageManagerTest::CacheMetadataCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -332,25 +364,27 @@ class CacheStorageManagerTest : public testing::Test {
bool StorageMatch(const url::Origin& origin,
const std::string& cache_name,
const GURL& url,
- const CacheStorageCacheQueryParams& match_params =
- CacheStorageCacheQueryParams()) {
+ blink::mojom::QueryParamsPtr match_params = nullptr,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
ServiceWorkerFetchRequest request;
request.url = url;
- return StorageMatchWithRequest(origin, cache_name, request, match_params);
+ return StorageMatchWithRequest(origin, cache_name, request,
+ std::move(match_params), owner);
}
bool StorageMatchWithRequest(
const url::Origin& origin,
const std::string& cache_name,
const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params =
- CacheStorageCacheQueryParams()) {
+ blink::mojom::QueryParamsPtr match_params = nullptr,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
std::unique_ptr<ServiceWorkerFetchRequest> unique_request =
std::make_unique<ServiceWorkerFetchRequest>(request);
base::RunLoop loop;
cache_manager_->MatchCache(
- origin, cache_name, std::move(unique_request), match_params,
+ origin, owner, cache_name, std::move(unique_request),
+ std::move(match_params),
base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -360,23 +394,22 @@ class CacheStorageManagerTest : public testing::Test {
bool StorageMatchAll(const url::Origin& origin,
const GURL& url,
- const CacheStorageCacheQueryParams& match_params =
- CacheStorageCacheQueryParams()) {
+ blink::mojom::QueryParamsPtr match_params = nullptr) {
ServiceWorkerFetchRequest request;
request.url = url;
- return StorageMatchAllWithRequest(origin, request, match_params);
+ return StorageMatchAllWithRequest(origin, request, std::move(match_params));
}
bool StorageMatchAllWithRequest(
const url::Origin& origin,
const ServiceWorkerFetchRequest& request,
- const CacheStorageCacheQueryParams& match_params =
- CacheStorageCacheQueryParams()) {
+ blink::mojom::QueryParamsPtr match_params = nullptr,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
std::unique_ptr<ServiceWorkerFetchRequest> unique_request =
std::make_unique<ServiceWorkerFetchRequest>(request);
base::RunLoop loop;
cache_manager_->MatchAllCaches(
- origin, std::move(unique_request), match_params,
+ origin, owner, std::move(unique_request), std::move(match_params),
base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -384,6 +417,24 @@ class CacheStorageManagerTest : public testing::Test {
return callback_error_ == CacheStorageError::kSuccess;
}
+ bool Write(const url::Origin& origin,
+ CacheStorageOwner owner,
+ const std::string& cache_name,
+ const std::string& request_url) {
+ auto request = std::make_unique<ServiceWorkerFetchRequest>();
+ request->url = GURL(request_url);
+
+ auto response = std::make_unique<ServiceWorkerResponse>();
+
+ base::RunLoop loop;
+ cache_manager_->WriteToCache(
+ origin, owner, cache_name, std::move(request), std::move(response),
+ base::BindOnce(&CacheStorageManagerTest::ErrorCallback,
+ base::Unretained(this), base::Unretained(&loop)));
+ loop.Run();
+ return callback_bool_;
+ }
+
bool CachePut(CacheStorageCache* cache,
const GURL& url,
FetchResponseType response_type = FetchResponseType::kDefault) {
@@ -435,14 +486,17 @@ class CacheStorageManagerTest : public testing::Test {
std::make_unique<
ServiceWorkerHeaderList>() /* cors_exposed_header_names */);
- CacheStorageBatchOperation operation;
- operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- operation.request = request;
- operation.response = response;
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kPut;
+ operation->request = request;
+ operation->response = response;
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.emplace_back(std::move(operation));
base::RunLoop loop;
cache->BatchOperation(
- std::vector<CacheStorageBatchOperation>(1, operation),
+ std::move(operations),
base::BindOnce(&CacheStorageManagerTest::CachePutCallback,
base::Unretained(this), base::Unretained(&loop)),
CacheStorageCache::BadMessageCallback());
@@ -456,14 +510,17 @@ class CacheStorageManagerTest : public testing::Test {
request.url = url;
ServiceWorkerResponse response;
- CacheStorageBatchOperation operation;
- operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
- operation.request = request;
- operation.response = response;
+ blink::mojom::BatchOperationPtr operation =
+ blink::mojom::BatchOperation::New();
+ operation->operation_type = blink::mojom::OperationType::kDelete;
+ operation->request = request;
+ operation->response = response;
+ std::vector<blink::mojom::BatchOperationPtr> operations;
+ operations.emplace_back(std::move(operation));
base::RunLoop loop;
cache->BatchOperation(
- std::vector<CacheStorageBatchOperation>(1, operation),
+ std::move(operations),
base::BindOnce(&CacheStorageManagerTest::CacheDeleteCallback,
base::Unretained(this), base::Unretained(&loop)),
CacheStorageCache::BadMessageCallback());
@@ -478,7 +535,7 @@ class CacheStorageManagerTest : public testing::Test {
request->url = url;
base::RunLoop loop;
cache->Match(
- std::move(request), CacheStorageCacheQueryParams(),
+ std::move(request), nullptr,
base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -487,13 +544,16 @@ class CacheStorageManagerTest : public testing::Test {
}
CacheStorage* CacheStorageForOrigin(const url::Origin& origin) {
- return cache_manager_->FindOrCreateCacheStorage(origin);
+ return cache_manager_->FindOrCreateCacheStorage(
+ origin, CacheStorageOwner::kCacheAPI);
}
- int64_t GetOriginUsage(const url::Origin& origin) {
+ int64_t GetOriginUsage(
+ const url::Origin& origin,
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
base::RunLoop loop;
cache_manager_->GetOriginUsage(
- origin,
+ origin, owner,
base::BindOnce(&CacheStorageManagerTest::UsageCallback,
base::Unretained(this), base::Unretained(&loop)));
loop.Run();
@@ -505,11 +565,12 @@ class CacheStorageManagerTest : public testing::Test {
run_loop->Quit();
}
- std::vector<CacheStorageUsageInfo> GetAllOriginsUsage() {
+ std::vector<CacheStorageUsageInfo> GetAllOriginsUsage(
+ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
base::RunLoop loop;
cache_manager_->GetAllOriginsUsage(
- base::Bind(&CacheStorageManagerTest::AllOriginsUsageCallback,
- base::Unretained(this), base::Unretained(&loop)));
+ owner, base::Bind(&CacheStorageManagerTest::AllOriginsUsageCallback,
+ base::Unretained(this), base::Unretained(&loop)));
loop.Run();
return callback_all_origins_usage_;
}
@@ -574,7 +635,7 @@ class CacheStorageManagerTest : public testing::Test {
scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
scoped_refptr<MockQuotaManager> mock_quota_manager_;
- scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
+ scoped_refptr<MockCacheStorageQuotaManagerProxy> quota_manager_proxy_;
std::unique_ptr<CacheStorageManager> cache_manager_;
CacheStorageCacheHandle callback_cache_handle_;
@@ -618,6 +679,13 @@ TEST_P(CacheStorageManagerTestP, OpenTwoCaches) {
EXPECT_TRUE(Open(origin1_, "bar"));
}
+TEST_P(CacheStorageManagerTestP, OpenSameCacheDifferentOwners) {
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+ CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+ EXPECT_NE(callback_cache_handle_.value(), cache_handle.value());
+}
+
TEST_P(CacheStorageManagerTestP, CachePointersDiffer) {
EXPECT_TRUE(Open(origin1_, "foo"));
CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
@@ -645,6 +713,21 @@ TEST_P(CacheStorageManagerTestP, HasCache) {
EXPECT_TRUE(callback_bool_);
}
+TEST_P(CacheStorageManagerTestP, HasCacheDifferentOwners) {
+ EXPECT_TRUE(Open(origin1_, "public", CacheStorageOwner::kCacheAPI));
+ EXPECT_TRUE(Open(origin1_, "bgf", CacheStorageOwner::kBackgroundFetch));
+
+ EXPECT_TRUE(Has(origin1_, "public", CacheStorageOwner::kCacheAPI));
+ EXPECT_TRUE(callback_bool_);
+ EXPECT_FALSE(Has(origin1_, "bgf", CacheStorageOwner::kCacheAPI));
+ EXPECT_FALSE(callback_bool_);
+
+ EXPECT_TRUE(Has(origin1_, "bgf", CacheStorageOwner::kBackgroundFetch));
+ EXPECT_TRUE(callback_bool_);
+ EXPECT_FALSE(Has(origin1_, "public", CacheStorageOwner::kBackgroundFetch));
+ EXPECT_FALSE(callback_bool_);
+}
+
TEST_P(CacheStorageManagerTestP, HasNonExistent) {
EXPECT_FALSE(Has(origin1_, "foo"));
}
@@ -749,6 +832,27 @@ TEST_P(CacheStorageManagerTestP, StorageMatchAllNoCaches) {
EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_);
}
+TEST_P(CacheStorageManagerTestP, StorageMatchDifferentOwners) {
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+ EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
+ GURL("http://example.com/public")));
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+ EXPECT_TRUE(
+ CachePut(callback_cache_handle_.value(), GURL("http://example.com/bgf")));
+
+ // Check the public cache.
+ EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/public"),
+ nullptr, CacheStorageOwner::kCacheAPI));
+ EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bgf"),
+ nullptr, CacheStorageOwner::kCacheAPI));
+
+ // Check the internal cache.
+ EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/public"),
+ nullptr, CacheStorageOwner::kBackgroundFetch));
+ EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/bgf"),
+ nullptr, CacheStorageOwner::kBackgroundFetch));
+}
+
TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
// Deleting a cache and creating one with the same name and adding an entry
// with the same URL should work. (see crbug.com/542668)
@@ -1194,7 +1298,7 @@ TEST_P(CacheStorageManagerTestP, OpenRunsSerially) {
base::RunLoop open_loop;
cache_manager_->OpenCache(
- origin1_, "foo",
+ origin1_, CacheStorageOwner::kCacheAPI, "foo",
base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback,
base::Unretained(this), base::Unretained(&open_loop)));
@@ -1257,6 +1361,55 @@ TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) {
}
}
+TEST_P(CacheStorageManagerTestP, GetAllOriginsUsageDifferentOwners) {
+ EXPECT_EQ(0ULL, GetAllOriginsUsage(CacheStorageOwner::kCacheAPI).size());
+ EXPECT_EQ(0ULL,
+ GetAllOriginsUsage(CacheStorageOwner::kBackgroundFetch).size());
+
+ // Put one entry in a cache of owner 1.
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+ EXPECT_TRUE(
+ CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
+
+ // Put two entries (of identical size) in two origins in a cache of owner 2.
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+ EXPECT_TRUE(
+ CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(Open(origin2_, "foo", CacheStorageOwner::kBackgroundFetch));
+ EXPECT_TRUE(
+ CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar")));
+
+ std::vector<CacheStorageUsageInfo> usage_cache =
+ GetAllOriginsUsage(CacheStorageOwner::kCacheAPI);
+ EXPECT_EQ(1ULL, usage_cache.size());
+ std::vector<CacheStorageUsageInfo> usage_bgf =
+ GetAllOriginsUsage(CacheStorageOwner::kBackgroundFetch);
+ EXPECT_EQ(2ULL, usage_bgf.size());
+
+ int origin1_index =
+ url::Origin::Create(usage_bgf[0].origin) == origin1_ ? 0 : 1;
+ int origin2_index =
+ url::Origin::Create(usage_bgf[1].origin) == origin2_ ? 1 : 0;
+ EXPECT_NE(origin1_index, origin2_index);
+
+ EXPECT_EQ(usage_cache[0].origin, origin1_.GetURL());
+ EXPECT_EQ(usage_bgf[origin1_index].origin, origin1_.GetURL());
+ EXPECT_EQ(usage_bgf[origin2_index].origin, origin2_.GetURL());
+
+ EXPECT_EQ(usage_cache[0].total_size_bytes,
+ usage_bgf[origin1_index].total_size_bytes);
+
+ if (MemoryOnly()) {
+ EXPECT_TRUE(usage_cache[0].last_modified.is_null());
+ EXPECT_TRUE(usage_bgf[origin1_index].last_modified.is_null());
+ EXPECT_TRUE(usage_bgf[origin2_index].last_modified.is_null());
+ } else {
+ EXPECT_FALSE(usage_cache[0].last_modified.is_null());
+ EXPECT_FALSE(usage_bgf[origin1_index].last_modified.is_null());
+ EXPECT_FALSE(usage_bgf[origin2_index].last_modified.is_null());
+ }
+}
+
TEST_F(CacheStorageManagerTest, GetAllOriginsUsageWithOldIndex) {
// Write a single value (V1) to the cache.
const GURL kFooURL = origin1_.GetURL().Resolve("foo");
@@ -1392,6 +1545,23 @@ TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCaches) {
CachePut(callback_cache_handle_.value(), GURL("http://example.com/baz")));
}
+TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCachesTwoOwners) {
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+ CacheStorageCacheHandle public_handle = std::move(callback_cache_handle_);
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+ CacheStorageCacheHandle bgf_handle = std::move(callback_cache_handle_);
+
+ EXPECT_TRUE(
+ CachePut(public_handle.value(), GURL("http://example.com/public")));
+ EXPECT_TRUE(CachePut(bgf_handle.value(), GURL("http://example.com/bgf")));
+
+ int64_t origin_size = GetOriginUsage(origin1_);
+ EXPECT_LT(0, origin_size);
+
+ EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(origin1_));
+ EXPECT_FALSE(CachePut(public_handle.value(), GURL("http://example.com/baz")));
+}
+
TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCachesAfterDelete) {
// Tests that doomed caches are also deleted by GetSizeThenCloseAllCaches.
EXPECT_TRUE(Open(origin1_, "foo"));
@@ -1422,7 +1592,7 @@ TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
// Create an unreferenced directory next to the referenced one.
base::FilePath origin_path = CacheStorageManager::ConstructOriginPath(
- cache_manager_->root_path(), origin1_);
+ cache_manager_->root_path(), origin1_, CacheStorageOwner::kCacheAPI);
base::FilePath unreferenced_path = origin_path.AppendASCII("bar");
EXPECT_TRUE(CreateDirectory(unreferenced_path));
EXPECT_TRUE(base::DirectoryExists(unreferenced_path));
@@ -1594,10 +1764,10 @@ TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreSearch) {
EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
- match_params));
+ std::move(match_params)));
}
TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreMethod) {
@@ -1610,10 +1780,10 @@ TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreMethod) {
post_request.method = "POST";
EXPECT_FALSE(StorageMatchWithRequest(origin1_, "foo", post_request));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_method = true;
- EXPECT_TRUE(
- StorageMatchWithRequest(origin1_, "foo", post_request, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_method = true;
+ EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", post_request,
+ std::move(match_params)));
}
TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreVary) {
@@ -1634,9 +1804,10 @@ TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreVary) {
request.headers["vary_foo"] = "bar";
EXPECT_FALSE(StorageMatchWithRequest(origin1_, "foo", request));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_vary = true;
- EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", request, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_vary = true;
+ EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", request,
+ std::move(match_params)));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreSearch) {
@@ -1646,10 +1817,10 @@ TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreSearch) {
EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_search = true;
- EXPECT_TRUE(
- StorageMatchAll(origin1_, GURL("http://example.com/foo"), match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_search = true;
+ EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo"),
+ std::move(match_params)));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreMethod) {
@@ -1662,9 +1833,10 @@ TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreMethod) {
post_request.method = "POST";
EXPECT_FALSE(StorageMatchAllWithRequest(origin1_, post_request));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_method = true;
- EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, post_request, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_method = true;
+ EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, post_request,
+ std::move(match_params)));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreVary) {
@@ -1685,9 +1857,34 @@ TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreVary) {
request.headers["vary_foo"] = "bar";
EXPECT_FALSE(StorageMatchAllWithRequest(origin1_, request));
- CacheStorageCacheQueryParams match_params;
- match_params.ignore_vary = true;
- EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, request, match_params));
+ blink::mojom::QueryParamsPtr match_params = blink::mojom::QueryParams::New();
+ match_params->ignore_vary = true;
+ EXPECT_TRUE(
+ StorageMatchAllWithRequest(origin1_, request, std::move(match_params)));
+}
+
+TEST_P(CacheStorageManagerTestP, StorageWriteToCache) {
+ EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+
+ EXPECT_TRUE(Write(origin1_, CacheStorageOwner::kBackgroundFetch, "foo",
+ "http://example.com/foo"));
+
+ // Match request we just wrote.
+ EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
+ nullptr, CacheStorageOwner::kBackgroundFetch));
+
+ // Don't match with different origin.
+ EXPECT_FALSE(StorageMatch(origin2_, "foo", GURL("http://example.com/foo"),
+ nullptr, CacheStorageOwner::kBackgroundFetch));
+ // Don't match with different cache name.
+ EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo"),
+ nullptr, CacheStorageOwner::kBackgroundFetch));
+ // Don't match with different request.
+ EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar"),
+ nullptr, CacheStorageOwner::kBackgroundFetch));
+ // Don't match with different owner.
+ EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
+ nullptr, CacheStorageOwner::kCacheAPI));
}
class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
@@ -1696,8 +1893,8 @@ class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
void SetUp() override {
CacheStorageManagerTest::SetUp();
- quota_client_.reset(
- new CacheStorageQuotaClient(cache_manager_->AsWeakPtr()));
+ quota_client_.reset(new CacheStorageQuotaClient(
+ cache_manager_->AsWeakPtr(), CacheStorageOwner::kCacheAPI));
}
void QuotaUsageCallback(base::RunLoop* run_loop, int64_t usage) {
@@ -1801,6 +1998,15 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForType) {
EXPECT_EQ(2u, QuotaGetOriginsForType());
}
+TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForTypeDifferentOwners) {
+ EXPECT_EQ(0u, QuotaGetOriginsForType());
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ // The |quota_client_| is registered for CacheStorageOwner::kCacheAPI, so this
+ // Open is ignored.
+ EXPECT_TRUE(Open(origin2_, "bar", CacheStorageOwner::kBackgroundFetch));
+ EXPECT_EQ(1u, QuotaGetOriginsForType());
+}
+
TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForHost) {
EXPECT_EQ(0u, QuotaGetOriginsForHost("example.com"));
EXPECT_TRUE(
@@ -1857,7 +2063,8 @@ TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedOriginData) {
// Create a new CacheStorageManager that hasn't yet loaded the origin.
quota_manager_proxy_->SimulateQuotaManagerDestroyed();
cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
- quota_client_.reset(new CacheStorageQuotaClient(cache_manager_->AsWeakPtr()));
+ quota_client_.reset(new CacheStorageQuotaClient(
+ cache_manager_->AsWeakPtr(), CacheStorageOwner::kCacheAPI));
EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
diff --git a/chromium/content/browser/cache_storage/cache_storage_quota_client.cc b/chromium/content/browser/cache_storage/cache_storage_quota_client.cc
index 1eea5a76e35..50086c0cd9e 100644
--- a/chromium/content/browser/cache_storage/cache_storage_quota_client.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_quota_client.cc
@@ -12,16 +12,15 @@
namespace content {
CacheStorageQuotaClient::CacheStorageQuotaClient(
- base::WeakPtr<CacheStorageManager> cache_manager)
- : cache_manager_(cache_manager) {
-}
+ base::WeakPtr<CacheStorageManager> cache_manager,
+ CacheStorageOwner owner)
+ : cache_manager_(cache_manager), owner_(owner) {}
-CacheStorageQuotaClient::~CacheStorageQuotaClient() {
-}
+CacheStorageQuotaClient::~CacheStorageQuotaClient() {}
storage::QuotaClient::ID CacheStorageQuotaClient::id() const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return kServiceWorkerCache;
+ return GetIDFromOwner(owner_);
}
void CacheStorageQuotaClient::OnQuotaManagerDestroyed() {
@@ -38,7 +37,7 @@ void CacheStorageQuotaClient::GetOriginUsage(const url::Origin& origin,
return;
}
- cache_manager_->GetOriginUsage(origin, std::move(callback));
+ cache_manager_->GetOriginUsage(origin, owner_, std::move(callback));
}
void CacheStorageQuotaClient::GetOriginsForType(blink::mojom::StorageType type,
@@ -50,7 +49,7 @@ void CacheStorageQuotaClient::GetOriginsForType(blink::mojom::StorageType type,
return;
}
- cache_manager_->GetOrigins(std::move(callback));
+ cache_manager_->GetOrigins(owner_, std::move(callback));
}
void CacheStorageQuotaClient::GetOriginsForHost(blink::mojom::StorageType type,
@@ -63,7 +62,7 @@ void CacheStorageQuotaClient::GetOriginsForHost(blink::mojom::StorageType type,
return;
}
- cache_manager_->GetOriginsForHost(host, std::move(callback));
+ cache_manager_->GetOriginsForHost(host, owner_, std::move(callback));
}
void CacheStorageQuotaClient::DeleteOriginData(const url::Origin& origin,
@@ -81,7 +80,7 @@ void CacheStorageQuotaClient::DeleteOriginData(const url::Origin& origin,
return;
}
- cache_manager_->DeleteOriginData(origin, std::move(callback));
+ cache_manager_->DeleteOriginData(origin, owner_, std::move(callback));
}
bool CacheStorageQuotaClient::DoesSupport(
@@ -91,4 +90,15 @@ bool CacheStorageQuotaClient::DoesSupport(
return type == blink::mojom::StorageType::kTemporary;
}
+// static
+storage::QuotaClient::ID CacheStorageQuotaClient::GetIDFromOwner(
+ CacheStorageOwner owner) {
+ switch (owner) {
+ case CacheStorageOwner::kCacheAPI:
+ return kServiceWorkerCache;
+ case CacheStorageOwner::kBackgroundFetch:
+ return kBackgroundFetch;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage_quota_client.h b/chromium/content/browser/cache_storage/cache_storage_quota_client.h
index 6eab4ce0324..d3c1620441d 100644
--- a/chromium/content/browser/cache_storage/cache_storage_quota_client.h
+++ b/chromium/content/browser/cache_storage/cache_storage_quota_client.h
@@ -13,15 +13,17 @@
#include "url/origin.h"
namespace content {
+
class CacheStorageManager;
+enum class CacheStorageOwner;
// CacheStorageQuotaClient is owned by the QuotaManager. There is one per
// CacheStorageManager, and therefore one per
// ServiceWorkerContextCore.
class CONTENT_EXPORT CacheStorageQuotaClient : public storage::QuotaClient {
public:
- explicit CacheStorageQuotaClient(
- base::WeakPtr<CacheStorageManager> cache_manager);
+ CacheStorageQuotaClient(base::WeakPtr<CacheStorageManager> cache_manager,
+ CacheStorageOwner owner);
~CacheStorageQuotaClient() override;
// QuotaClient overrides
@@ -40,8 +42,11 @@ class CONTENT_EXPORT CacheStorageQuotaClient : public storage::QuotaClient {
DeletionCallback callback) override;
bool DoesSupport(blink::mojom::StorageType type) const override;
+ static ID GetIDFromOwner(CacheStorageOwner owner);
+
private:
base::WeakPtr<CacheStorageManager> cache_manager_;
+ CacheStorageOwner owner_;
DISALLOW_COPY_AND_ASSIGN(CacheStorageQuotaClient);
};
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index fcc37f21745..b1869a2723c 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -4,6 +4,8 @@
#include "content/browser/child_process_launcher.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
@@ -12,8 +14,8 @@
#include "base/process/launch.h"
#include "build/build_config.h"
#include "content/public/browser/child_process_launcher_utils.h"
-#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
+#include "services/service_manager/embedder/result_codes.h"
namespace content {
@@ -29,12 +31,11 @@ ChildProcessLauncher::ChildProcessLauncher(
const mojo::edk::ProcessErrorCallback& process_error_callback,
bool terminate_on_shutdown)
: client_(client),
- termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
- exit_code_(RESULT_CODE_NORMAL_EXIT),
starting_(true),
+ start_time_(base::TimeTicks::Now()),
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
- defined(UNDEFINED_SANITIZER)
+ defined(UNDEFINED_SANITIZER) || defined(CLANG_COVERAGE)
terminate_child_on_shutdown_(false),
#else
terminate_child_on_shutdown_(terminate_on_shutdown),
@@ -80,7 +81,7 @@ void ChildProcessLauncher::Notify(
if (process_.process.IsValid()) {
client_->OnProcessLaunched();
} else {
- termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED;
+ termination_info_.status = base::TERMINATION_STATUS_LAUNCH_FAILED;
// NOTE: May delete |this|.
client_->OnProcessLaunchFailed(error_code);
@@ -99,40 +100,39 @@ const base::Process& ChildProcessLauncher::GetProcess() const {
return process_.process;
}
-base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
- bool known_dead,
- int* exit_code) {
+ChildProcessTerminationInfo ChildProcessLauncher::GetChildTerminationInfo(
+ bool known_dead) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!process_.process.IsValid()) {
// Make sure to avoid using the default termination status if the process
// hasn't even started yet.
- if (IsStarting())
- termination_status_ = base::TERMINATION_STATUS_STILL_RUNNING;
-
- // Process doesn't exist, so return the cached termination status.
- if (exit_code)
- *exit_code = exit_code_;
- return termination_status_;
+ if (IsStarting()) {
+ termination_info_.status = base::TERMINATION_STATUS_STILL_RUNNING;
+ termination_info_.uptime = base::TimeTicks::Now() - start_time_;
+ DCHECK_LE(base::TimeDelta::FromSeconds(0), termination_info_.uptime);
+ }
+
+ // Process doesn't exist, so return the cached termination info.
+ return termination_info_;
}
- termination_status_ =
- helper_->GetTerminationStatus(process_, known_dead, &exit_code_);
- if (exit_code)
- *exit_code = exit_code_;
+ termination_info_ = helper_->GetTerminationInfo(process_, known_dead);
+ termination_info_.uptime = base::TimeTicks::Now() - start_time_;
+ DCHECK_LE(base::TimeDelta::FromSeconds(0), termination_info_.uptime);
// POSIX: If the process crashed, then the kernel closed the socket for it and
// so the child has already died by the time we get here. Since
- // GetTerminationStatus called waitpid with WNOHANG, it'll reap the process.
- // However, if GetTerminationStatus didn't reap the child (because it was
+ // GetTerminationInfo called waitpid with WNOHANG, it'll reap the process.
+ // However, if GetTerminationInfo didn't reap the child (because it was
// still running), we'll need to Terminate via ProcessWatcher. So we can't
// close the handle here.
- if (termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING) {
- process_.process.Exited(exit_code_);
+ if (termination_info_.status != base::TERMINATION_STATUS_STILL_RUNNING) {
+ process_.process.Exited(termination_info_.exit_code);
process_.process.Close();
}
- return termination_status_;
+ return termination_info_;
}
bool ChildProcessLauncher::Terminate(int exit_code) {
@@ -160,13 +160,6 @@ void ChildProcessLauncher::ResetRegisteredFilesForTesting() {
ChildProcessLauncherHelper::ResetRegisteredFilesForTesting();
}
-#if defined(OS_ANDROID)
-// static
-size_t ChildProcessLauncher::GetNumberOfRendererSlots() {
- return ChildProcessLauncherHelper::GetNumberOfRendererSlots();
-}
-#endif // OS_ANDROID
-
ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
Client* client) {
Client* ret = client_;
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index c9d243c37ea..04787554d23 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_H_
#include <memory>
+#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -14,10 +15,12 @@
#include "base/process/kill.h"
#include "base/process/process.h"
#include "base/sequence_checker.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/child_process_launcher_helper.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/result_codes.h"
#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
@@ -78,7 +81,7 @@ class CONTENT_EXPORT ChildProcessLauncher {
// constructed on.
virtual void OnProcessLaunched() = 0;
- virtual void OnProcessLaunchFailed(int error_code) {};
+ virtual void OnProcessLaunchFailed(int error_code) {}
protected:
virtual ~Client() {}
@@ -118,11 +121,7 @@ class CONTENT_EXPORT ChildProcessLauncher {
// process could be seen as running. With |known_dead| set to true, the
// process will be killed if it was still running. See ZygoteHostImpl for
// more discussion of Linux implementation details.
- // |exit_code| is the exit code of the process if it exited (e.g. status from
- // waitpid if on posix, from GetExitCodeProcess on Windows). |exit_code| may
- // be NULL.
- base::TerminationStatus GetChildTerminationStatus(bool known_dead,
- int* exit_code);
+ ChildProcessTerminationInfo GetChildTerminationInfo(bool known_dead);
// Changes whether the process runs in the background or not. Only call
// this after the process has started.
@@ -153,11 +152,6 @@ class CONTENT_EXPORT ChildProcessLauncher {
// support multiple shell context creation in unit_tests.
static void ResetRegisteredFilesForTesting();
-#if defined(OS_ANDROID)
- // Temporary until crbug.com/693484 is fixed.
- static size_t GetNumberOfRendererSlots();
-#endif // OS_ANDROID
-
private:
friend class internal::ChildProcessLauncherHelper;
@@ -172,9 +166,9 @@ class CONTENT_EXPORT ChildProcessLauncher {
// ChildProcessLauncherHelper once the process was started.
internal::ChildProcessLauncherHelper::Process process_;
- base::TerminationStatus termination_status_;
- int exit_code_;
+ ChildProcessTerminationInfo termination_info_;
bool starting_;
+ base::TimeTicks start_time_;
// Controls whether the child process should be terminated on browser
// shutdown. Default behavior is to terminate the child.
diff --git a/chromium/content/browser/child_process_launcher_helper.h b/chromium/content/browser/child_process_launcher_helper.h
index b9b7a82652b..51d54bb4ab6 100644
--- a/chromium/content/browser/child_process_launcher_helper.h
+++ b/chromium/content/browser/child_process_launcher_helper.h
@@ -14,11 +14,11 @@
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/result_codes.h"
-#include "content/public/common/zygote_buildflags.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "services/catalog/public/cpp/manifest_parsing_util.h"
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
#if defined(OS_ANDROID)
#include "base/android/scoped_java_ref.h"
@@ -35,7 +35,7 @@
#endif
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
-#include "content/public/common/zygote_handle.h"
+#include "services/service_manager/zygote/common/zygote_handle.h" // nogncheck
#endif
namespace base {
@@ -47,14 +47,15 @@ namespace content {
class ChildProcessLauncher;
class SandboxedProcessLauncherDelegate;
struct ChildProcessLauncherPriority;
+struct ChildProcessTerminationInfo;
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
class PosixFileDescriptorInfo;
#endif
namespace internal {
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
using FileMappedForLaunch = PosixFileDescriptorInfo;
#else
using FileMappedForLaunch = base::HandlesToInheritVector;
@@ -78,7 +79,7 @@ class ChildProcessLauncherHelper :
base::Process process;
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
- ZygoteHandle zygote = nullptr;
+ service_manager::ZygoteHandle zygote = nullptr;
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
};
@@ -103,7 +104,8 @@ class ChildProcessLauncherHelper :
// Called in to give implementors a chance at creating a server pipe.
// Platform specific.
- mojo::edk::ScopedPlatformHandle PrepareMojoPipeHandlesOnClientThread();
+ mojo::edk::ScopedInternalPlatformHandle
+ PrepareMojoPipeHandlesOnClientThread();
// Returns the list of files that should be mapped in the child process.
// Platform specific.
@@ -146,12 +148,10 @@ class ChildProcessLauncherHelper :
int client_thread_id() const { return client_thread_id_; }
- // Returns the termination status and sets |exit_code| if non null.
- // See ChildProcessLauncher::GetChildTerminationStatus for more info.
- base::TerminationStatus GetTerminationStatus(
+ // See ChildProcessLauncher::GetChildTerminationInfo for more info.
+ ChildProcessTerminationInfo GetTerminationInfo(
const ChildProcessLauncherHelper::Process& process,
- bool known_dead,
- int* exit_code);
+ bool known_dead);
// Terminates |process|.
// Returns true if the process was stopped, false if the process had not been
@@ -180,7 +180,6 @@ class ChildProcessLauncherHelper :
void OnChildProcessStarted(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint handle);
- static size_t GetNumberOfRendererSlots();
#endif // OS_ANDROID
private:
@@ -190,7 +189,7 @@ class ChildProcessLauncherHelper :
void LaunchOnLauncherThread();
- const mojo::edk::PlatformHandle& mojo_client_handle() const {
+ const mojo::edk::InternalPlatformHandle& mojo_client_handle() const {
return mojo_client_handle_.get();
}
base::CommandLine* command_line() { return command_line_.get(); }
@@ -213,8 +212,8 @@ class ChildProcessLauncherHelper :
std::unique_ptr<base::CommandLine> command_line_;
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate_;
base::WeakPtr<ChildProcessLauncher> child_process_launcher_;
- mojo::edk::ScopedPlatformHandle mojo_client_handle_;
- mojo::edk::ScopedPlatformHandle mojo_server_handle_;
+ mojo::edk::ScopedInternalPlatformHandle mojo_client_handle_;
+ mojo::edk::ScopedInternalPlatformHandle mojo_server_handle_;
bool terminate_on_shutdown_;
std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
broker_client_invitation_;
diff --git a/chromium/content/browser/child_process_launcher_helper_android.cc b/chromium/content/browser/child_process_launcher_helper_android.cc
index 1954e362d8c..07c1a74cec2 100644
--- a/chromium/content/browser/child_process_launcher_helper_android.cc
+++ b/chromium/content/browser/child_process_launcher_helper_android.cc
@@ -20,6 +20,7 @@
#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_switches.h"
#include "jni/ChildProcessLauncherHelper_jni.h"
+#include "services/service_manager/sandbox/switches.h"
using base::android::AttachCurrentThread;
using base::android::JavaParamRef;
@@ -55,12 +56,12 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
// Non-sandboxed utility or renderer process are currently not supported.
DCHECK(process_type == switches::kGpuProcess ||
- !command_line()->HasSwitch(switches::kNoSandbox));
+ !command_line()->HasSwitch(service_manager::switches::kNoSandbox));
}
-mojo::edk::ScopedPlatformHandle
+mojo::edk::ScopedInternalPlatformHandle
ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
- return mojo::edk::ScopedPlatformHandle();
+ return mojo::edk::ScopedInternalPlatformHandle();
}
std::unique_ptr<PosixFileDescriptorInfo>
@@ -148,18 +149,30 @@ void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
const base::LaunchOptions& options) {
}
-base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
+ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
const ChildProcessLauncherHelper::Process& process,
- bool known_dead,
- int* exit_code) {
- if (java_peer_avaiable_on_client_thread_ &&
- Java_ChildProcessLauncherHelper_isOomProtected(AttachCurrentThread(),
- java_peer_)) {
- return base::TERMINATION_STATUS_OOM_PROTECTED;
+ bool known_dead) {
+ ChildProcessTerminationInfo info;
+ info.has_oom_protection_bindings =
+ java_peer_avaiable_on_client_thread_ &&
+ Java_ChildProcessLauncherHelper_hasOomProtectionBindings(
+ AttachCurrentThread(), java_peer_);
+ info.was_killed_intentionally_by_browser =
+ java_peer_avaiable_on_client_thread_ &&
+ Java_ChildProcessLauncherHelper_isKilledByUs(AttachCurrentThread(),
+ java_peer_);
+ bool app_foreground =
+ java_peer_avaiable_on_client_thread_ &&
+ Java_ChildProcessLauncherHelper_isApplicationInForeground(
+ AttachCurrentThread(), java_peer_);
+ if (app_foreground && info.has_oom_protection_bindings) {
+ info.status = base::TERMINATION_STATUS_OOM_PROTECTED;
+ } else {
+ // Note waitpid does not work on Android since these are not actually child
+ // processes. So there is no need for base::GetTerminationInfo.
+ info.status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
}
- // Note waitpid does not work on Android since these are not actually child
- // processes. So there is no need for base::GetTerminationStatus.
- return base::TERMINATION_STATUS_NORMAL_TERMINATION;
+ return info;
}
// static
@@ -228,13 +241,6 @@ void ChildProcessLauncherHelper::OnChildProcessStarted(
PostLaunchOnLauncherThread(std::move(process), launch_result);
}
-// static
-size_t ChildProcessLauncherHelper::GetNumberOfRendererSlots() {
- return static_cast<size_t>(
- Java_ChildProcessLauncherHelper_getNumberOfRendererSlots(
- AttachCurrentThread()));
-}
-
} // namespace internal
} // namespace content
diff --git a/chromium/content/browser/child_process_launcher_helper_fuchsia.cc b/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
index 281f4609d10..cd3095ce794 100644
--- a/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
+++ b/chromium/content/browser/child_process_launcher_helper_fuchsia.cc
@@ -11,6 +11,7 @@
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "services/service_manager/embedder/result_codes.h"
namespace content {
namespace internal {
@@ -23,11 +24,13 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
NOTIMPLEMENTED();
}
-base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
+ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
const ChildProcessLauncherHelper::Process& process,
- bool known_dead,
- int* exit_code) {
- return base::GetTerminationStatus(process.process.Handle(), exit_code);
+ bool known_dead) {
+ ChildProcessTerminationInfo info;
+ info.status =
+ base::GetTerminationStatus(process.process.Handle(), &info.exit_code);
+ return info;
}
// static
@@ -54,13 +57,13 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
}
-mojo::edk::ScopedPlatformHandle
+mojo::edk::ScopedInternalPlatformHandle
ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
// By doing nothing here, StartLaunchOnClientThread() will construct a channel
// pair instead.
- return mojo::edk::ScopedPlatformHandle();
+ return mojo::edk::ScopedInternalPlatformHandle();
}
std::unique_ptr<FileMappedForLaunch>
@@ -114,7 +117,7 @@ void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
ChildProcessLauncherHelper::Process process) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
- process.process.Terminate(RESULT_CODE_NORMAL_EXIT, true);
+ process.process.Terminate(service_manager::RESULT_CODE_NORMAL_EXIT, true);
}
} // namespace internal
diff --git a/chromium/content/browser/child_process_launcher_helper_linux.cc b/chromium/content/browser/child_process_launcher_helper_linux.cc
index 732970c0e83..5db82c367aa 100644
--- a/chromium/content/browser/child_process_launcher_helper_linux.cc
+++ b/chromium/content/browser/child_process_launcher_helper_linux.cc
@@ -9,26 +9,26 @@
#include "content/browser/child_process_launcher_helper.h"
#include "content/browser/child_process_launcher_helper_posix.h"
#include "content/browser/sandbox_host_linux.h"
-#include "content/browser/zygote_host/zygote_communication_linux.h"
-#include "content/browser/zygote_host/zygote_host_impl_linux.h"
#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/common_sandbox_support_linux.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "content/public/common/zygote_handle.h"
#include "gpu/config/gpu_switches.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
+#include "services/service_manager/zygote/common/zygote_handle.h"
+#include "services/service_manager/zygote/host/zygote_communication_linux.h"
+#include "services/service_manager/zygote/host/zygote_host_impl_linux.h"
namespace content {
namespace internal {
-mojo::edk::ScopedPlatformHandle
+mojo::edk::ScopedInternalPlatformHandle
ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
- return mojo::edk::ScopedPlatformHandle();
+ return mojo::edk::ScopedInternalPlatformHandle();
}
void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
@@ -55,7 +55,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableOOPRasterization))) {
const int sandbox_fd = SandboxHostLinux::GetInstance()->GetChildSocket();
- options->fds_to_remap.push_back(std::make_pair(sandbox_fd, GetSandboxFD()));
+ options->fds_to_remap.push_back(
+ std::make_pair(sandbox_fd, service_manager::GetSandboxFD()));
}
options->environ = delegate_->GetEnvironment();
@@ -71,7 +72,7 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
int* launch_result) {
*is_synchronous_launch = true;
- ZygoteHandle zygote_handle =
+ service_manager::ZygoteHandle zygote_handle =
base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoZygote)
? nullptr
: delegate_->GetZygote();
@@ -92,7 +93,7 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
// chrome::kLowestRendererOomScore in chrome/chrome_constants.h, but
// that's not something we can include here.)
const int kLowestRendererOomScore = 300;
- ZygoteHostImpl::GetInstance()->AdjustRendererOOMScore(
+ service_manager::ZygoteHostImpl::GetInstance()->AdjustRendererOOMScore(
handle, kLowestRendererOomScore);
}
#endif
@@ -115,19 +116,21 @@ void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
const base::LaunchOptions& options) {
}
-base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
+ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
const ChildProcessLauncherHelper::Process& process,
- bool known_dead,
- int* exit_code) {
+ bool known_dead) {
+ ChildProcessTerminationInfo info;
if (process.zygote) {
- return process.zygote->GetTerminationStatus(
- process.process.Handle(), known_dead, exit_code);
- }
- if (known_dead) {
- return base::GetKnownDeadTerminationStatus(
- process.process.Handle(), exit_code);
+ info.status = process.zygote->GetTerminationStatus(
+ process.process.Handle(), known_dead, &info.exit_code);
+ } else if (known_dead) {
+ info.status = base::GetKnownDeadTerminationStatus(process.process.Handle(),
+ &info.exit_code);
+ } else {
+ info.status =
+ base::GetTerminationStatus(process.process.Handle(), &info.exit_code);
}
- return base::GetTerminationStatus(process.process.Handle(), exit_code);
+ return info;
}
// static
@@ -142,7 +145,7 @@ bool ChildProcessLauncherHelper::TerminateProcess(const base::Process& process,
void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
ChildProcessLauncherHelper::Process process) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
- process.process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
+ process.process.Terminate(service_manager::RESULT_CODE_NORMAL_EXIT, false);
// On POSIX, we must additionally reap the child.
if (process.zygote) {
// If the renderer was created via a zygote, we have to proxy the reaping
diff --git a/chromium/content/browser/child_process_launcher_helper_mac.cc b/chromium/content/browser/child_process_launcher_helper_mac.cc
index 61f9aa4ec40..902177996e1 100644
--- a/chromium/content/browser/child_process_launcher_helper_mac.cc
+++ b/chromium/content/browser/child_process_launcher_helper_mac.cc
@@ -21,6 +21,7 @@
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "sandbox/mac/seatbelt_exec.h"
+#include "services/service_manager/embedder/result_codes.h"
#include "services/service_manager/sandbox/mac/cdm.sb.h"
#include "services/service_manager/sandbox/mac/common_v2.sb.h"
#include "services/service_manager/sandbox/mac/gpu_v2.sb.h"
@@ -31,14 +32,15 @@
#include "services/service_manager/sandbox/mac/utility.sb.h"
#include "services/service_manager/sandbox/sandbox.h"
#include "services/service_manager/sandbox/sandbox_type.h"
+#include "services/service_manager/sandbox/switches.h"
namespace content {
namespace internal {
-mojo::edk::ScopedPlatformHandle
+mojo::edk::ScopedInternalPlatformHandle
ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
- return mojo::edk::ScopedPlatformHandle();
+ return mojo::edk::ScopedInternalPlatformHandle();
}
void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
@@ -66,8 +68,9 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
auto sandbox_type =
service_manager::SandboxTypeFromCommandLine(*command_line_);
- bool no_sandbox = command_line_->HasSwitch(switches::kNoSandbox) ||
- service_manager::IsUnsandboxedSandboxType(sandbox_type);
+ bool no_sandbox =
+ command_line_->HasSwitch(service_manager::switches::kNoSandbox) ||
+ service_manager::IsUnsandboxedSandboxType(sandbox_type);
// TODO(kerrnel): Delete this switch once the V2 sandbox is always enabled.
bool v2_process = false;
@@ -161,7 +164,8 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
}
base::FilePath helper_executable;
- CHECK(PathService::Get(content::CHILD_PROCESS_EXE, &helper_executable));
+ CHECK(
+ base::PathService::Get(content::CHILD_PROCESS_EXE, &helper_executable));
options->fds_to_remap.push_back(std::make_pair(pipe, pipe));
@@ -221,13 +225,15 @@ void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
broker->GetLock().Release();
}
-base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
+ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
const ChildProcessLauncherHelper::Process& process,
- bool known_dead,
- int* exit_code) {
- return known_dead
- ? base::GetKnownDeadTerminationStatus(process.process.Handle(), exit_code)
- : base::GetTerminationStatus(process.process.Handle(), exit_code);
+ bool known_dead) {
+ ChildProcessTerminationInfo info;
+ info.status = known_dead ? base::GetKnownDeadTerminationStatus(
+ process.process.Handle(), &info.exit_code)
+ : base::GetTerminationStatus(
+ process.process.Handle(), &info.exit_code);
+ return info;
}
// static
@@ -244,7 +250,7 @@ void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
// Client has gone away, so just kill the process. Using exit code 0 means
// that UMA won't treat this as a crash.
- process.process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
+ process.process.Terminate(service_manager::RESULT_CODE_NORMAL_EXIT, false);
base::EnsureProcessTerminated(std::move(process.process));
}
diff --git a/chromium/content/browser/child_process_launcher_helper_posix.cc b/chromium/content/browser/child_process_launcher_helper_posix.cc
index 42e1c9e4cf1..60aedf2a364 100644
--- a/chromium/content/browser/child_process_launcher_helper_posix.cc
+++ b/chromium/content/browser/child_process_launcher_helper_posix.cc
@@ -73,7 +73,7 @@ base::PlatformFile OpenFileIfNecessary(const base::FilePath& path,
std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
- const mojo::edk::PlatformHandle& mojo_client_handle,
+ const mojo::edk::InternalPlatformHandle& mojo_client_handle,
bool include_service_required_files,
const std::string& process_type,
base::CommandLine* command_line) {
@@ -83,12 +83,13 @@ std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
base::SharedMemoryHandle shm = base::FieldTrialList::GetFieldTrialHandle();
if (shm.IsValid()) {
files_to_register->Share(
- kFieldTrialDescriptor,
+ service_manager::kFieldTrialDescriptor,
base::SharedMemory::GetFdFromSharedMemoryHandle(shm));
}
DCHECK(mojo_client_handle.is_valid());
- files_to_register->Share(kMojoIPCChannel, mojo_client_handle.handle);
+ files_to_register->Share(service_manager::kMojoIPCChannel,
+ mojo_client_handle.handle);
// TODO(jcivelli): remove this "if defined" by making
// GetAdditionalMappedFilesForChildProcess a no op on Mac.
diff --git a/chromium/content/browser/child_process_launcher_helper_posix.h b/chromium/content/browser/child_process_launcher_helper_posix.h
index 7f08758cae4..df353a54a11 100644
--- a/chromium/content/browser/child_process_launcher_helper_posix.h
+++ b/chromium/content/browser/child_process_launcher_helper_posix.h
@@ -18,7 +18,7 @@ class FilePath;
namespace mojo {
namespace edk {
-struct PlatformHandle;
+struct InternalPlatformHandle;
} // namespace mojo
} // namespace edk
@@ -33,7 +33,7 @@ namespace internal {
std::unique_ptr<PosixFileDescriptorInfo> CreateDefaultPosixFilesToMap(
int child_process_id,
- const mojo::edk::PlatformHandle& mojo_client_handle,
+ const mojo::edk::InternalPlatformHandle& mojo_client_handle,
bool include_service_required_files,
const std::string& process_type,
base::CommandLine* command_line);
diff --git a/chromium/content/browser/child_process_launcher_helper_win.cc b/chromium/content/browser/child_process_launcher_helper_win.cc
index ca73f6006dc..46c2dbea83d 100644
--- a/chromium/content/browser/child_process_launcher_helper_win.cc
+++ b/chromium/content/browser/child_process_launcher_helper_win.cc
@@ -18,6 +18,7 @@
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "sandbox/win/src/sandbox_types.h"
+#include "services/service_manager/embedder/result_codes.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
namespace content {
@@ -27,12 +28,12 @@ void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
}
-mojo::edk::ScopedPlatformHandle
+mojo::edk::ScopedInternalPlatformHandle
ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
DCHECK_CURRENTLY_ON(client_thread_id_);
if (!delegate_->ShouldLaunchElevated())
- return mojo::edk::ScopedPlatformHandle();
+ return mojo::edk::ScopedInternalPlatformHandle();
mojo::edk::NamedPlatformChannelPair named_pair;
named_pair.PrepareToPassClientHandleToChildProcess(command_line());
@@ -89,11 +90,13 @@ void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
}
-base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
+ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
const ChildProcessLauncherHelper::Process& process,
- bool known_dead,
- int* exit_code) {
- return base::GetTerminationStatus(process.process.Handle(), exit_code);
+ bool known_dead) {
+ ChildProcessTerminationInfo info;
+ info.status =
+ base::GetTerminationStatus(process.process.Handle(), &info.exit_code);
+ return info;
}
// static
@@ -107,7 +110,7 @@ void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
// Client has gone away, so just kill the process. Using exit code 0 means
// that UMA won't treat this as a crash.
- process.process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
+ process.process.Terminate(service_manager::RESULT_CODE_NORMAL_EXIT, false);
}
void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 09d1adb47f3..4bf51fd3352 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -683,12 +683,12 @@ bool ChildProcessSecurityPolicyImpl::CanRedirectToURL(const GURL& url) {
// Note about redirects and special URLs:
// * data-url: Blocked by net::DataProtocolHandler::IsSafeRedirectTarget().
+ // * filesystem-url: Blocked by
+ // storage::FilesystemProtocolHandler::IsSafeRedirectTarget().
// Depending on their inner origins and if the request is browser-initiated or
- // renderer-initiated, blob-urls and filesystem-urls might get blocked by
- // CanCommitURL or in DocumentLoader::RedirectReceived.
- // * blob-url: If not blocked, a 'file not found' response will be
- // generated in net::BlobURLRequestJob::DidStart().
- // * filesystem-url: If not blocked, the response is displayed.
+ // renderer-initiated, blob-urls might get blocked by CanCommitURL or in
+ // DocumentLoader::RedirectReceived. If not blocked, a 'file not found'
+ // response will be generated in net::BlobURLRequestJob::DidStart().
return true;
}
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
index 258f0ff7b32..36a0ee2f3bc 100644
--- a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/mac/foundation_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
diff --git a/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
index a0798bec241..d4b2a798c0c 100644
--- a/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
@@ -21,7 +21,7 @@ class SystemHotkeyMapTest : public ::testing::Test {
NSData* DataFromTestFile(const char* file) {
base::FilePath test_data_dir;
- bool result = PathService::Get(DIR_TEST_DATA, &test_data_dir);
+ bool result = base::PathService::Get(DIR_TEST_DATA, &test_data_dir);
if (!result)
return nil;
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.cc b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
index f7e37d38bfb..924e82dadab 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
@@ -36,12 +36,14 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
update_vsync_parameters_callback_(update_vsync_parameters_callback),
reflector_(nullptr) {}
+#if BUILDFLAG(ENABLE_VULKAN)
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
const scoped_refptr<viz::VulkanContextProvider>& vulkan_context_provider,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback)
: OutputSurface(std::move(vulkan_context_provider)),
update_vsync_parameters_callback_(update_vsync_parameters_callback),
reflector_(nullptr) {}
+#endif
BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
if (reflector_)
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.h b/chromium/content/browser/compositor/browser_compositor_output_surface.h
index 0df130ac73b..941d70bd2a7 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.h
@@ -9,6 +9,7 @@
#include "build/build_config.h"
#include "components/viz/service/display/output_surface.h"
#include "content/common/content_export.h"
+#include "gpu/vulkan/buildflags.h"
namespace cc {
class SoftwareOutputDevice;
@@ -43,10 +44,6 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
// Called when |reflector_| was updated.
virtual void OnReflectorChanged();
-#if defined(OS_MACOSX)
- virtual void SetSurfaceSuspendedForRecycle(bool suspended) = 0;
-#endif
-
protected:
// Constructor used by the accelerated implementation.
BrowserCompositorOutputSurface(
@@ -60,10 +57,12 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
std::unique_ptr<viz::SoftwareOutputDevice> software_device,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback);
+#if BUILDFLAG(ENABLE_VULKAN)
// Constructor used by the Vulkan implementation.
BrowserCompositorOutputSurface(
const scoped_refptr<viz::VulkanContextProvider>& vulkan_context_provider,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback);
+#endif
const UpdateVSyncParametersCallback update_vsync_parameters_callback_;
ReflectorImpl* reflector_;
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
index 2694224b27f..34fbb3a9521 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -16,6 +16,7 @@
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
+#include "gpu/command_buffer/common/swap_buffers_flags.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "ui/gl/gl_utils.h"
@@ -30,7 +31,7 @@ GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
: BrowserCompositorOutputSurface(std::move(context),
update_vsync_parameters_callback,
std::move(overlay_candidate_validator)),
- latency_info_cache_(this) {
+ weak_ptr_factory_(this) {
if (capabilities_.uses_default_gl_framebuffer) {
capabilities_.flipped_output_surface =
context_provider()->ContextCapabilities().flips_vertically;
@@ -39,16 +40,8 @@ GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
context_provider()->ContextCapabilities().num_stencil_bits > 0;
}
-GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {
- // Reset GetCommandBufferProxy() callbacks to avoid calling those callbacks
- // from dtor of the base class.
- GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
- gpu::CommandBufferProxyImpl::SwapBuffersCompletionCallback());
- GetCommandBufferProxy()->SetUpdateVSyncParametersCallback(
- UpdateVSyncParametersCallback());
- GetCommandBufferProxy()->SetPresentationCallback(
- gpu::CommandBufferProxyImpl::PresentationCallback());
-}
+GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() =
+ default;
void GpuBrowserCompositorOutputSurface::SetNeedsVSync(bool needs_vsync) {
#if defined(OS_WIN)
@@ -59,18 +52,16 @@ void GpuBrowserCompositorOutputSurface::SetNeedsVSync(bool needs_vsync) {
}
void GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
+ std::vector<ui::LatencyInfo> latency_info,
const gpu::SwapBuffersCompleteParams& params) {
if (!params.ca_layer_params.is_empty)
client_->DidReceiveCALayerParams(params.ca_layer_params);
if (!params.texture_in_use_responses.empty())
client_->DidReceiveTextureInUseResponses(params.texture_in_use_responses);
- client_->DidReceiveSwapBuffersAck(params.swap_response.swap_id);
- latency_info_cache_.OnSwapBuffersCompleted(params.swap_response);
-}
-
-void GpuBrowserCompositorOutputSurface::LatencyInfoCompleted(
- const std::vector<ui::LatencyInfo>& latency_info) {
+ client_->DidReceiveSwapBuffersAck();
+ UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
+ latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
}
void GpuBrowserCompositorOutputSurface::OnReflectorChanged() {
@@ -89,16 +80,9 @@ void GpuBrowserCompositorOutputSurface::BindToClient(
DCHECK(!client_);
client_ = client;
- // CommandBufferProxy() will always call below callbacks directly (no
- // PostTask), so it is safe to use base::Unretained(this).
- GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
- base::Bind(&GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted,
- base::Unretained(this)));
- GetCommandBufferProxy()->SetUpdateVSyncParametersCallback(
- update_vsync_parameters_callback_);
- GetCommandBufferProxy()->SetPresentationCallback(
- base::Bind(&GpuBrowserCompositorOutputSurface::OnPresentation,
- base::Unretained(this)));
+ GetCommandBufferProxy()->SetUpdateVSyncParametersCallback(base::BindRepeating(
+ &GpuBrowserCompositorOutputSurface::OnUpdateVSyncParameters,
+ weak_ptr_factory_.GetWeakPtr()));
}
void GpuBrowserCompositorOutputSurface::EnsureBackbuffer() {}
@@ -126,7 +110,7 @@ void GpuBrowserCompositorOutputSurface::Reshape(
void GpuBrowserCompositorOutputSurface::SwapBuffers(
viz::OutputSurfaceFrame frame) {
- if (latency_info_cache_.WillSwap(std::move(frame.latency_info)))
+ if (LatencyInfoHasSnapshotRequest(frame.latency_info))
GetCommandBufferProxy()->SetSnapshotRequested();
gfx::Size surface_size = frame.size;
@@ -143,14 +127,29 @@ void GpuBrowserCompositorOutputSurface::SwapBuffers(
set_draw_rectangle_for_frame_ = false;
+ auto swap_callback = base::BindOnce(
+ &GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted,
+ weak_ptr_factory_.GetWeakPtr(), std::move(frame.latency_info));
+ uint32_t flags = gpu::SwapBuffersFlags::kVSyncParams;
+ gpu::ContextSupport::PresentationCallback presentation_callback;
+ if (frame.need_presentation_feedback) {
+ flags |= gpu::SwapBuffersFlags::kPresentationFeedback;
+ presentation_callback =
+ base::BindOnce(&GpuBrowserCompositorOutputSurface::OnPresentation,
+ weak_ptr_factory_.GetWeakPtr());
+ }
if (frame.sub_buffer_rect) {
DCHECK(frame.content_bounds.empty());
context_provider_->ContextSupport()->PartialSwapBuffers(
- *frame.sub_buffer_rect);
+ *frame.sub_buffer_rect, flags, std::move(swap_callback),
+ std::move(presentation_callback));
} else if (!frame.content_bounds.empty()) {
- context_provider_->ContextSupport()->SwapWithBounds(frame.content_bounds);
+ context_provider_->ContextSupport()->SwapWithBounds(
+ frame.content_bounds, flags, std::move(swap_callback),
+ std::move(presentation_callback));
} else {
- context_provider_->ContextSupport()->Swap();
+ context_provider_->ContextSupport()->Swap(flags, std::move(swap_callback),
+ std::move(presentation_callback));
}
}
@@ -172,15 +171,6 @@ gfx::BufferFormat GpuBrowserCompositorOutputSurface::GetOverlayBufferFormat()
return gfx::BufferFormat::RGBX_8888;
}
-bool GpuBrowserCompositorOutputSurface::SurfaceIsSuspendForRecycle() const {
- return false;
-}
-
-#if defined(OS_MACOSX)
-void GpuBrowserCompositorOutputSurface::SetSurfaceSuspendedForRecycle(
- bool suspended) {}
-#endif
-
void GpuBrowserCompositorOutputSurface::SetDrawRectangle(
const gfx::Rect& rect) {
if (set_draw_rectangle_for_frame_)
@@ -195,10 +185,16 @@ void GpuBrowserCompositorOutputSurface::SetDrawRectangle(
}
void GpuBrowserCompositorOutputSurface::OnPresentation(
- uint64_t swap_id,
const gfx::PresentationFeedback& feedback) {
DCHECK(client_);
- client_->DidReceivePresentationFeedback(swap_id, feedback);
+ client_->DidReceivePresentationFeedback(feedback);
+}
+
+void GpuBrowserCompositorOutputSurface::OnUpdateVSyncParameters(
+ base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ if (update_vsync_parameters_callback_)
+ update_vsync_parameters_callback_.Run(timebase, interval);
}
gpu::CommandBufferProxyImpl*
@@ -218,4 +214,8 @@ gpu::VulkanSurface* GpuBrowserCompositorOutputSurface::GetVulkanSurface() {
}
#endif
+unsigned GpuBrowserCompositorOutputSurface::UpdateGpuFence() {
+ return 0;
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
index 95aa6d1983e..1ec2b3e3fdf 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -13,6 +13,7 @@
#include "content/browser/compositor/gpu_vsync_begin_frame_source.h"
#include "gpu/vulkan/buildflags.h"
#include "ui/gfx/swap_result.h"
+#include "ui/latency/latency_tracker.h"
namespace viz {
class CompositorOverlayCandidateValidator;
@@ -37,10 +38,8 @@ class ReflectorTexture;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
// viz::OutputSurface that also handles vsync parameter updates
// arriving from the GPU process.
-class GpuBrowserCompositorOutputSurface
- : public BrowserCompositorOutputSurface,
- public GpuVSyncControl,
- public viz::OutputSurface::LatencyInfoCache::Client {
+class GpuBrowserCompositorOutputSurface : public BrowserCompositorOutputSurface,
+ public GpuVSyncControl {
public:
GpuBrowserCompositorOutputSurface(
scoped_refptr<ui::ContextProviderCommandBuffer> context,
@@ -52,13 +51,11 @@ class GpuBrowserCompositorOutputSurface
// Called when a swap completion is sent from the GPU process.
virtual void OnGpuSwapBuffersCompleted(
+ std::vector<ui::LatencyInfo> latency_info,
const gpu::SwapBuffersCompleteParams& params);
// BrowserCompositorOutputSurface implementation.
void OnReflectorChanged() override;
-#if defined(OS_MACOSX)
- void SetSurfaceSuspendedForRecycle(bool suspended) override;
-#endif
// viz::OutputSurface implementation.
void BindToClient(viz::OutputSurfaceClient* client) override;
@@ -75,8 +72,8 @@ class GpuBrowserCompositorOutputSurface
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
gfx::BufferFormat GetOverlayBufferFormat() const override;
+ unsigned UpdateGpuFence() override;
- bool SurfaceIsSuspendForRecycle() const override;
void SetDrawRectangle(const gfx::Rect& rect) override;
// GpuVSyncControl implementation.
@@ -85,13 +82,10 @@ class GpuBrowserCompositorOutputSurface
gpu::VulkanSurface* GetVulkanSurface() override;
#endif
- // OutputSurface::LatencyInfoCache::Client implementation.
- void LatencyInfoCompleted(
- const std::vector<ui::LatencyInfo>& latency_info) override;
-
protected:
- void OnPresentation(uint64_t swap_id,
- const gfx::PresentationFeedback& feedback);
+ void OnPresentation(const gfx::PresentationFeedback& feedback);
+ void OnUpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval);
gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
viz::OutputSurfaceClient* client_ = nullptr;
@@ -101,9 +95,11 @@ class GpuBrowserCompositorOutputSurface
// True if the draw rectangle has been set at all since the last resize.
bool has_set_draw_rectangle_since_last_resize_ = false;
gfx::Size size_;
- LatencyInfoCache latency_info_cache_;
+ ui::LatencyTracker latency_tracker_;
private:
+ base::WeakPtrFactory<GpuBrowserCompositorOutputSurface> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface);
};
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.cc b/chromium/content/browser/compositor/gpu_output_surface_mac.cc
index 75429bb7c6d..7c5b22d9df7 100644
--- a/chromium/content/browser/compositor/gpu_output_surface_mac.cc
+++ b/chromium/content/browser/compositor/gpu_output_surface_mac.cc
@@ -9,13 +9,10 @@
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
-#include "ui/accelerated_widget_mac/ca_layer_frame_sink.h"
-#include "ui/compositor/compositor.h"
namespace content {
GpuOutputSurfaceMac::GpuOutputSurfaceMac(
- gfx::AcceleratedWidget widget,
scoped_refptr<ui::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
@@ -30,53 +27,8 @@ GpuOutputSurfaceMac::GpuOutputSurfaceMac(
GL_TEXTURE_RECTANGLE_ARB,
GL_RGBA,
gfx::BufferFormat::RGBA_8888,
- gpu_memory_buffer_manager),
- widget_(widget) {}
+ gpu_memory_buffer_manager) {}
GpuOutputSurfaceMac::~GpuOutputSurfaceMac() {}
-void GpuOutputSurfaceMac::SwapBuffers(viz::OutputSurfaceFrame frame) {
- GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers(std::move(frame));
- if (should_show_frames_state_ ==
- SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED) {
- should_show_frames_state_ = SHOULD_SHOW_FRAMES;
- ui::CALayerFrameSink* ca_layer_frame_sink =
- ui::CALayerFrameSink::FromAcceleratedWidget(widget_);
- if (ca_layer_frame_sink)
- ca_layer_frame_sink->SetSuspended(false);
- }
-}
-
-void GpuOutputSurfaceMac::SetSurfaceSuspendedForRecycle(bool suspended) {
- if (suspended) {
- // It may be that there are frames in-flight from the GPU process back to
- // the browser. Make sure that these frames are not displayed by ignoring
- // them in GpuProcessHostUIShim, until the browser issues a SwapBuffers for
- // the new content.
- should_show_frames_state_ = SHOULD_NOT_SHOW_FRAMES_SUSPENDED;
- ui::CALayerFrameSink* ca_layer_frame_sink =
- ui::CALayerFrameSink::FromAcceleratedWidget(widget_);
- if (ca_layer_frame_sink)
- ca_layer_frame_sink->SetSuspended(true);
- } else {
- // Discard the backbuffer before drawing the new frame. This is necessary
- // only when using a ImageTransportSurfaceFBO with a
- // CALayerStorageProvider. Discarding the backbuffer results in the next
- // frame using a new CALayer and CAContext, which guarantees that the
- // browser will not flash stale content when adding the remote CALayer to
- // the NSView hierarchy (it could flash stale content because the system
- // window server is not synchronized with any signals we control or
- // observe).
- if (should_show_frames_state_ == SHOULD_NOT_SHOW_FRAMES_SUSPENDED) {
- DiscardBackbuffer();
- should_show_frames_state_ =
- SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED;
- }
- }
-}
-
-bool GpuOutputSurfaceMac::SurfaceIsSuspendForRecycle() const {
- return should_show_frames_state_ == SHOULD_NOT_SHOW_FRAMES_SUSPENDED;
-}
-
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_output_surface_mac.h b/chromium/content/browser/compositor/gpu_output_surface_mac.h
index efe446e7cd1..73ad778a50a 100644
--- a/chromium/content/browser/compositor/gpu_output_surface_mac.h
+++ b/chromium/content/browser/compositor/gpu_output_surface_mac.h
@@ -15,7 +15,6 @@ class GpuOutputSurfaceMac
: public GpuSurfacelessBrowserCompositorOutputSurface {
public:
GpuOutputSurfaceMac(
- gfx::AcceleratedWidget widget,
scoped_refptr<ui::ContextProviderCommandBuffer> context,
gpu::SurfaceHandle surface_handle,
const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
@@ -24,29 +23,7 @@ class GpuOutputSurfaceMac
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
~GpuOutputSurfaceMac() override;
- // viz::OutputSurface implementation.
- void SwapBuffers(viz::OutputSurfaceFrame frame) override;
- bool SurfaceIsSuspendForRecycle() const override;
-
- // BrowserCompositorOutputSurface implementation.
- void SetSurfaceSuspendedForRecycle(bool suspended) override;
-
private:
- gfx::AcceleratedWidget widget_;
-
- enum ShouldShowFramesState {
- // Frames that come from the GPU process should appear on-screen.
- SHOULD_SHOW_FRAMES,
- // The compositor has been suspended. Any frames that come from the GPU
- // process are for the pre-suspend content and should not be displayed.
- SHOULD_NOT_SHOW_FRAMES_SUSPENDED,
- // The compositor has been un-suspended, but has not yet issued a swap
- // since being un-suspended, so any frames that come from the GPU process
- // are for pre-suspend content and should not be displayed.
- SHOULD_NOT_SHOW_FRAMES_NO_SWAP_AFTER_SUSPENDED,
- };
- ShouldShowFramesState should_show_frames_state_ = SHOULD_SHOW_FRAMES;
-
DISALLOW_COPY_AND_ASSIGN(GpuOutputSurfaceMac);
};
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index 7b9fc4114c5..e679dbb02a8 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -6,6 +6,7 @@
#include <string>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
@@ -25,7 +26,6 @@
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
#include "components/viz/common/gl_helper.h"
-#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "components/viz/common/switches.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/host/renderer_settings_creation.h"
@@ -85,6 +85,7 @@
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h"
+#include "components/viz/service/display_embedder/output_device_backing.h"
#include "components/viz/service/display_embedder/software_output_device_win.h"
#include "ui/gfx/win/rendering_window_manager.h"
#elif defined(USE_OZONE)
@@ -112,7 +113,9 @@
#endif
#if BUILDFLAG(ENABLE_VULKAN)
+#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
#include "content/browser/compositor/vulkan_browser_compositor_output_surface.h"
+#include "gpu/vulkan/init/vulkan_factory.cc"
#endif
using viz::ContextProvider;
@@ -187,16 +190,8 @@ GpuProcessTransportFactory::GpuProcessTransportFactory(
cc::SetClientNameForMetrics("Browser");
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kDisableGpuVsync)) {
- std::string display_vsync_string =
- command_line->GetSwitchValueASCII(switches::kDisableGpuVsync);
- // See comments in gl_switches about this flag. The browser compositor
- // is only unthrottled when "gpu" or no switch value is passed, as it
- // is driven directly by the display compositor.
- if (display_vsync_string != "beginframe") {
- disable_display_vsync_ = true;
- }
- }
+ if (command_line->HasSwitch(switches::kDisableFrameRateLimit))
+ disable_frame_rate_limit_ = true;
if (command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw))
wait_for_all_pipeline_stages_before_draw_ = true;
@@ -227,7 +222,8 @@ GpuProcessTransportFactory::~GpuProcessTransportFactory() {
std::unique_ptr<viz::SoftwareOutputDevice>
GpuProcessTransportFactory::CreateSoftwareOutputDevice(
- gfx::AcceleratedWidget widget) {
+ gfx::AcceleratedWidget widget,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kHeadless))
return base::WrapUnique(new viz::SoftwareOutputDevice);
@@ -241,8 +237,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(OS_WIN)
- return std::make_unique<viz::SoftwareOutputDeviceWin>(software_backing_.get(),
- widget);
+ return CreateSoftwareOutputDeviceWinBrowser(widget, software_backing_.get());
#elif defined(USE_OZONE)
ui::SurfaceFactoryOzone* factory =
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
@@ -254,7 +249,7 @@ GpuProcessTransportFactory::CreateSoftwareOutputDevice(
#elif defined(USE_X11)
return std::make_unique<viz::SoftwareOutputDeviceX11>(widget);
#elif defined(OS_MACOSX)
- return std::make_unique<viz::SoftwareOutputDeviceMac>(widget);
+ return std::make_unique<viz::SoftwareOutputDeviceMac>(std::move(task_runner));
#else
NOTREACHED();
return std::unique_ptr<viz::SoftwareOutputDevice>();
@@ -272,13 +267,21 @@ CreateOverlayCandidateValidator(
std::unique_ptr<viz::CompositorOverlayCandidateValidator> validator;
#if defined(USE_OZONE)
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kEnableHardwareOverlays)) {
- std::string enable_overlay_flag =
- command_line->GetSwitchValueASCII(switches::kEnableHardwareOverlays);
+
+ std::string enable_overlay_flag =
+ command_line->GetSwitchValueASCII(switches::kEnableHardwareOverlays);
+
+ ui::OzonePlatform* ozone_platform = ui::OzonePlatform::GetInstance();
+ DCHECK(ozone_platform);
+ ui::OverlayManagerOzone* overlay_manager =
+ ozone_platform->GetOverlayManager();
+ if (!command_line->HasSwitch(switches::kEnableHardwareOverlays) &&
+ overlay_manager->SupportsOverlays()) {
+ enable_overlay_flag = "single-fullscreen,single-on-top";
+ }
+ if (!enable_overlay_flag.empty()) {
std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates =
- ui::OzonePlatform::GetInstance()
- ->GetOverlayManager()
- ->CreateOverlayCandidates(widget);
+ ozone_platform->GetOverlayManager()->CreateOverlayCandidates(widget);
validator.reset(new viz::CompositorOverlayCandidateValidatorOzone(
std::move(overlay_candidates), enable_overlay_flag));
}
@@ -319,7 +322,11 @@ void GpuProcessTransportFactory::CreateLayerTreeFrameSink(
compositor->widget());
#endif
+#if BUILDFLAG(ENABLE_VULKAN)
const bool use_vulkan = static_cast<bool>(SharedVulkanContextProvider());
+#else
+ const bool use_vulkan = false;
+#endif
const bool use_gpu_compositing =
!compositor->force_software_compositor() && !is_gpu_compositing_disabled_;
if (use_gpu_compositing && !use_vulkan) {
@@ -372,11 +379,16 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
compositor->widget());
#endif
+#if BUILDFLAG(ENABLE_VULKAN)
scoped_refptr<viz::VulkanInProcessContextProvider> vulkan_context_provider =
SharedVulkanContextProvider();
+ bool use_vulkan = vulkan_context_provider != nullptr;
+#else
+ bool use_vulkan = false;
+#endif
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider;
- if (!use_gpu_compositing || vulkan_context_provider) {
+ if (!use_gpu_compositing || use_vulkan) {
// If not using GL compositing, don't keep the old shared worker context.
shared_worker_context_provider_ = nullptr;
} else if (!gpu_channel_host) {
@@ -390,11 +402,12 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
shared_worker_context_provider_ = nullptr;
if (!shared_worker_context_provider_) {
- bool need_alpha_channel = false;
- bool support_locking = true;
- bool support_gles2_interface = false;
- bool support_raster_interface = true;
- bool support_grcontext = false;
+ const bool need_alpha_channel = false;
+ const bool support_locking = true;
+ const bool support_gles2_interface =
+ features::IsUiGpuRasterizationEnabled();
+ const bool support_raster_interface = true;
+ const bool support_grcontext = features::IsUiGpuRasterizationEnabled();
shared_worker_context_provider_ = CreateContextCommon(
gpu_channel_host, gpu::kNullSurfaceHandle, need_alpha_channel,
false /* support_stencil */, support_locking, support_gles2_interface,
@@ -417,11 +430,11 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
// front buffer into a mailbox, insert a sync token, and send the
// mailbox+sync to the ui service process.
gpu::SurfaceHandle surface_handle = data->surface_handle;
- bool need_alpha_channel = false;
- bool support_locking = false;
- bool support_gles2_interface = true;
- bool support_raster_interface = false;
- bool support_grcontext = true;
+ const bool need_alpha_channel = false;
+ const bool support_locking = false;
+ const bool support_gles2_interface = true;
+ const bool support_raster_interface = false;
+ const bool support_grcontext = true;
context_provider = CreateContextCommon(
std::move(gpu_channel_host), surface_handle, need_alpha_channel,
support_stencil, support_locking, support_gles2_interface,
@@ -440,8 +453,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
}
bool gpu_compositing_ready =
- vulkan_context_provider ||
- (context_provider && shared_worker_context_provider_);
+ use_vulkan || (context_provider && shared_worker_context_provider_);
UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor",
gpu_compositing_ready);
if (!gpu_compositing_ready) {
@@ -497,8 +509,9 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
}
display_output_surface =
std::make_unique<SoftwareBrowserCompositorOutputSurface>(
- CreateSoftwareOutputDevice(compositor->widget()),
- std::move(vsync_callback), compositor->task_runner());
+ CreateSoftwareOutputDevice(compositor->widget(),
+ compositor->task_runner()),
+ std::move(vsync_callback));
} else {
DCHECK(context_provider);
const auto& capabilities = context_provider->ContextCapabilities();
@@ -513,8 +526,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
bool disable_overlay_ca_layers = gpu_feature_info.IsWorkaroundEnabled(
gpu::DISABLE_OVERLAY_CA_LAYERS);
display_output_surface = std::make_unique<GpuOutputSurfaceMac>(
- compositor->widget(), context_provider, data->surface_handle,
- vsync_callback,
+ context_provider, data->surface_handle, vsync_callback,
CreateOverlayCandidateValidator(compositor->widget(),
disable_overlay_ca_layers),
GetGpuMemoryBufferManager());
@@ -575,7 +587,13 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
std::move(request),
external_begin_frame_controller_client->GetBoundPtr());
begin_frame_source = external_begin_frame_controller->begin_frame_source();
- } else if (!disable_display_vsync_) {
+ } else if (disable_frame_rate_limit_) {
+ synthetic_begin_frame_source =
+ std::make_unique<viz::BackToBackBeginFrameSource>(
+ std::make_unique<viz::DelayBasedTimeSource>(
+ compositor->task_runner().get()));
+ begin_frame_source = synthetic_begin_frame_source.get();
+ } else {
if (gpu_vsync_control && IsGpuVSyncSignalSupported()) {
gpu_vsync_begin_frame_source =
std::make_unique<GpuVSyncBeginFrameSource>(gpu_vsync_control);
@@ -588,12 +606,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
viz::BeginFrameSource::kNotRestartableId);
begin_frame_source = synthetic_begin_frame_source.get();
}
- } else {
- synthetic_begin_frame_source =
- std::make_unique<viz::BackToBackBeginFrameSource>(
- std::make_unique<viz::DelayBasedTimeSource>(
- compositor->task_runner().get()));
- begin_frame_source = synthetic_begin_frame_source.get();
}
#if defined(OS_WIN)
@@ -645,7 +657,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
GetFrameSinkManager(), data->display.get(), data->display_client.get(),
context_provider, shared_worker_context_provider_,
compositor->task_runner(), GetGpuMemoryBufferManager(),
- viz::ServerSharedBitmapManager::current(),
features::IsVizHitTestingEnabled());
data->display->Resize(compositor->size());
data->display->SetOutputIsSecure(data->output_is_secure);
@@ -654,6 +665,8 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
void GpuProcessTransportFactory::DisableGpuCompositing(
ui::Compositor* guilty_compositor) {
+ DLOG(ERROR) << "Switching to software compositing.";
+
// Change the result of IsGpuCompositingDisabled() before notifying anything.
is_gpu_compositing_disabled_ = true;
@@ -933,20 +946,6 @@ viz::GLHelper* GpuProcessTransportFactory::GetGLHelper() {
return gl_helper_.get();
}
-#if defined(OS_MACOSX)
-void GpuProcessTransportFactory::SetCompositorSuspendedForRecycle(
- ui::Compositor* compositor,
- bool suspended) {
- PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
- if (it == per_compositor_data_.end())
- return;
- PerCompositorData* data = it->second.get();
- DCHECK(data);
- if (data->display_output_surface)
- data->display_output_surface->SetSurfaceSuspendedForRecycle(suspended);
-}
-#endif
-
scoped_refptr<ContextProvider>
GpuProcessTransportFactory::SharedMainThreadContextProvider() {
if (is_gpu_compositing_disabled_)
@@ -1036,19 +1035,28 @@ void GpuProcessTransportFactory::OnLostMainThreadSharedContext() {
lost_shared_main_thread_contexts = nullptr;
}
+#if BUILDFLAG(ENABLE_VULKAN)
scoped_refptr<viz::VulkanInProcessContextProvider>
GpuProcessTransportFactory::SharedVulkanContextProvider() {
if (!shared_vulkan_context_provider_initialized_) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableVulkan)) {
- shared_vulkan_context_provider_ =
- viz::VulkanInProcessContextProvider::Create();
+ vulkan_implementation_ = gpu::CreateVulkanImplementation();
+ if (vulkan_implementation_ &&
+ vulkan_implementation_->InitializeVulkanInstance()) {
+ shared_vulkan_context_provider_ =
+ viz::VulkanInProcessContextProvider::Create(
+ vulkan_implementation_.get());
+ } else {
+ vulkan_implementation_.reset();
+ }
}
shared_vulkan_context_provider_initialized_ = true;
}
return shared_vulkan_context_provider_;
}
+#endif
void GpuProcessTransportFactory::OnContextLost() {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1107,8 +1115,7 @@ GpuProcessTransportFactory::CreateContextCommon(
return base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), GetGpuMemoryBufferManager(), stream_id,
stream_priority, surface_handle, url, automatic_flushes, support_locking,
- support_grcontext, gpu::SharedMemoryLimits(), attributes,
- nullptr /* share_context */, type);
+ support_grcontext, gpu::SharedMemoryLimits(), attributes, type);
}
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index bc7e7750003..02c1ec0d59b 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -22,6 +22,7 @@
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "gpu/ipc/client/gpu_channel_host.h"
+#include "gpu/vulkan/buildflags.h"
#include "services/ui/public/cpp/gpu/command_buffer_metrics.h"
#include "ui/compositor/compositor.h"
@@ -36,6 +37,7 @@ class SurfaceManager;
namespace gpu {
class GpuChannelEstablishFactory;
+class VulkanImplementation;
}
namespace ui {
@@ -105,17 +107,14 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
ui::ContextFactoryPrivate* GetContextFactoryPrivate() override;
viz::FrameSinkManagerImpl* GetFrameSinkManager() override;
viz::GLHelper* GetGLHelper() override;
-#if defined(OS_MACOSX)
- void SetCompositorSuspendedForRecycle(ui::Compositor* compositor,
- bool suspended) override;
-#endif
private:
struct PerCompositorData;
PerCompositorData* CreatePerCompositorData(ui::Compositor* compositor);
std::unique_ptr<viz::SoftwareOutputDevice> CreateSoftwareOutputDevice(
- gfx::AcceleratedWidget widget);
+ gfx::AcceleratedWidget widget,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
void EstablishedGpuChannel(
base::WeakPtr<ui::Compositor> compositor,
bool use_gpu_compositing,
@@ -125,8 +124,10 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
void OnLostMainThreadSharedContext();
+#if BUILDFLAG(ENABLE_VULKAN)
scoped_refptr<viz::VulkanInProcessContextProvider>
SharedVulkanContextProvider();
+#endif
// viz::ContextLostObserver implementation.
void OnContextLost() override;
@@ -149,6 +150,10 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
std::unique_ptr<viz::OutputDeviceBacking> software_backing_;
#endif
+#if BUILDFLAG(ENABLE_VULKAN)
+ std::unique_ptr<gpu::VulkanImplementation> vulkan_implementation_;
+#endif
+
// Depends on SurfaceManager.
typedef std::map<ui::Compositor*, std::unique_ptr<PerCompositorData>>
PerCompositorDataMap;
@@ -163,11 +168,13 @@ class GpuProcessTransportFactory : public ui::ContextFactory,
scoped_refptr<viz::RasterContextProvider> shared_worker_context_provider_;
bool is_gpu_compositing_disabled_ = false;
- bool disable_display_vsync_ = false;
+ bool disable_frame_rate_limit_ = false;
bool wait_for_all_pipeline_stages_before_draw_ = false;
+#if BUILDFLAG(ENABLE_VULKAN)
bool shared_vulkan_context_provider_initialized_ = false;
scoped_refptr<viz::VulkanInProcessContextProvider>
shared_vulkan_context_provider_;
+#endif
gpu::GpuChannelEstablishFactory* const gpu_channel_factory_;
// Service-side impl that controls the compositing mode based on what mode the
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
index c1cb69e4b42..c2a3a8d7b5e 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
@@ -33,6 +33,11 @@ GpuSurfacelessBrowserCompositorOutputSurface::
: GpuBrowserCompositorOutputSurface(std::move(context),
update_vsync_parameters_callback,
std::move(overlay_candidate_validator)),
+ use_gpu_fence_(
+ context_provider_->ContextCapabilities().chromium_gpu_fence &&
+ context_provider_->ContextCapabilities()
+ .use_gpu_fences_for_overlay_planes),
+ gpu_fence_id_(0),
gpu_memory_buffer_manager_(gpu_memory_buffer_manager) {
capabilities_.uses_default_gl_framebuffer = false;
capabilities_.flipped_output_surface = true;
@@ -55,6 +60,8 @@ GpuSurfacelessBrowserCompositorOutputSurface::
GpuSurfacelessBrowserCompositorOutputSurface::
~GpuSurfacelessBrowserCompositorOutputSurface() {
+ if (gpu_fence_id_ > 0)
+ context_provider_->ContextGL()->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
}
bool GpuSurfacelessBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane()
@@ -112,6 +119,7 @@ void GpuSurfacelessBrowserCompositorOutputSurface::Reshape(
}
void GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
+ std::vector<ui::LatencyInfo> latency_info,
const gpu::SwapBuffersCompleteParams& params) {
gpu::SwapBuffersCompleteParams modified_params(params);
bool force_swap = false;
@@ -124,9 +132,22 @@ void GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
force_swap = true;
}
buffer_queue_->PageFlipComplete();
- GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(modified_params);
+ GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
+ std::move(latency_info), modified_params);
if (force_swap)
client_->SetNeedsRedrawRect(gfx::Rect(swap_size_));
}
+unsigned GpuSurfacelessBrowserCompositorOutputSurface::UpdateGpuFence() {
+ if (!use_gpu_fence_)
+ return 0;
+
+ if (gpu_fence_id_ > 0)
+ context_provider_->ContextGL()->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
+
+ gpu_fence_id_ = context_provider_->ContextGL()->CreateGpuFenceCHROMIUM();
+
+ return gpu_fence_id_;
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
index 48a7356fc69..439c8553ab1 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
@@ -48,14 +48,18 @@ class GpuSurfacelessBrowserCompositorOutputSurface
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
gfx::BufferFormat GetOverlayBufferFormat() const override;
+ unsigned UpdateGpuFence() override;
// BrowserCompositorOutputSurface implementation.
void OnGpuSwapBuffersCompleted(
+ std::vector<ui::LatencyInfo> latency_info,
const gpu::SwapBuffersCompleteParams& params) override;
private:
gfx::Size reshape_size_;
gfx::Size swap_size_;
+ bool use_gpu_fence_;
+ unsigned gpu_fence_id_;
std::unique_ptr<viz::GLHelper> gl_helper_;
std::unique_ptr<viz::BufferQueue> buffer_queue_;
diff --git a/chromium/content/browser/compositor/image_transport_factory.h b/chromium/content/browser/compositor/image_transport_factory.h
index 1ac2c66a4e5..0ccaf358643 100644
--- a/chromium/content/browser/compositor/image_transport_factory.h
+++ b/chromium/content/browser/compositor/image_transport_factory.h
@@ -11,7 +11,6 @@
#include "content/common/content_export.h"
namespace ui {
-class Compositor;
class ContextFactory;
class ContextFactoryPrivate;
}
@@ -56,17 +55,6 @@ class CONTENT_EXPORT ImageTransportFactory {
// GLHelper will get destroyed whenever the shared context is lost
// (ImageTransportFactoryObserver::OnLostResources is called).
virtual viz::GLHelper* GetGLHelper() = 0;
-
-#if defined(OS_MACOSX)
- // Called with |suspended| as true when the ui::Compositor has been
- // disconnected from an NSView and may be attached to another one. Called
- // with |suspended| as false after the ui::Compositor has been connected to
- // a new NSView and the first commit targeted at the new NSView has
- // completed. This ensures that content and frames intended for the old
- // NSView will not flash in the new NSView.
- virtual void SetCompositorSuspendedForRecycle(ui::Compositor* compositor,
- bool suspended) = 0;
-#endif
};
} // namespace content
diff --git a/chromium/content/browser/compositor/in_process_display_client.cc b/chromium/content/browser/compositor/in_process_display_client.cc
index 388998baa97..3190c0d90ff 100644
--- a/chromium/content/browser/compositor/in_process_display_client.cc
+++ b/chromium/content/browser/compositor/in_process_display_client.cc
@@ -4,15 +4,25 @@
#include "content/browser/compositor/in_process_display_client.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+
#if defined(OS_MACOSX)
#include "ui/accelerated_widget_mac/ca_layer_frame_sink.h"
#endif
+#if defined(OS_WIN)
+#include <windows.h>
+
+#include "components/viz/common/display/use_layered_window.h"
+#include "components/viz/host/layered_window_updater_impl.h"
+#include "ui/base/win/internal_constants.h"
+#endif
+
namespace content {
InProcessDisplayClient::InProcessDisplayClient(gfx::AcceleratedWidget widget)
: binding_(this) {
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_WIN)
widget_ = widget;
#endif
}
@@ -40,4 +50,24 @@ void InProcessDisplayClient::OnDisplayReceivedCALayerParams(
#endif
}
+void InProcessDisplayClient::DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
+}
+
+void InProcessDisplayClient::CreateLayeredWindowUpdater(
+ viz::mojom::LayeredWindowUpdaterRequest request) {
+#if defined(OS_WIN)
+ if (!viz::NeedsToUseLayerWindow(widget_)) {
+ DLOG(ERROR) << "HWND shouldn't be using a layered window";
+ return;
+ }
+
+ layered_window_updater_ = std::make_unique<viz::LayeredWindowUpdaterImpl>(
+ widget_, std::move(request));
+#else
+// This should never happen on non-Windows platforms.
+#endif
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/in_process_display_client.h b/chromium/content/browser/compositor/in_process_display_client.h
index dd2ef76cddc..baa83594ed5 100644
--- a/chromium/content/browser/compositor/in_process_display_client.h
+++ b/chromium/content/browser/compositor/in_process_display_client.h
@@ -5,18 +5,26 @@
#ifndef CONTENT_BROWSER_COMPOSITOR_IN_PROCESS_DISPLAY_CLIENT_H_
#define CONTENT_BROWSER_COMPOSITOR_IN_PROCESS_DISPLAY_CLIENT_H_
+#include <memory>
+#include <vector>
+
+#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
#include "ui/gfx/native_widget_types.h"
+namespace viz {
+class LayeredWindowUpdaterImpl;
+}
+
namespace content {
// A DisplayClient that can be used to display received
// gfx::CALayerParams in a CALayer tree in this process.
class InProcessDisplayClient : public viz::mojom::DisplayClient {
public:
- InProcessDisplayClient(gfx::AcceleratedWidget widget);
+ explicit InProcessDisplayClient(gfx::AcceleratedWidget widget);
~InProcessDisplayClient() override;
viz::mojom::DisplayClientPtr GetBoundPtr(
@@ -26,11 +34,19 @@ class InProcessDisplayClient : public viz::mojom::DisplayClient {
// viz::mojom::DisplayClient implementation:
void OnDisplayReceivedCALayerParams(
const gfx::CALayerParams& ca_layer_params) override;
+ void DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) override;
+ void CreateLayeredWindowUpdater(
+ viz::mojom::LayeredWindowUpdaterRequest request) override;
mojo::Binding<viz::mojom::DisplayClient> binding_;
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_WIN)
gfx::AcceleratedWidget widget_;
#endif
+
+#if defined(OS_WIN)
+ std::unique_ptr<viz::LayeredWindowUpdaterImpl> layered_window_updater_;
+#endif
};
} // namespace content
diff --git a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
index 05f9a5f3149..2792d4646f5 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -8,7 +8,6 @@
#include "base/logging.h"
#include "build/build_config.h"
-#include "cc/resources/resource_provider.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
@@ -161,7 +160,8 @@ void OffscreenBrowserCompositorOutputSurface::SwapBuffers(
sync_token,
base::BindOnce(
&OffscreenBrowserCompositorOutputSurface::OnSwapBuffersComplete,
- weak_ptr_factory_.GetWeakPtr(), frame.latency_info, ++swap_id_));
+ weak_ptr_factory_.GetWeakPtr(), frame.latency_info,
+ frame.need_presentation_feedback));
}
bool OffscreenBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane()
@@ -178,11 +178,6 @@ OffscreenBrowserCompositorOutputSurface::GetOverlayBufferFormat() const {
return gfx::BufferFormat::RGBX_8888;
}
-bool OffscreenBrowserCompositorOutputSurface::SurfaceIsSuspendForRecycle()
- const {
- return false;
-}
-
GLenum
OffscreenBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
return GLCopyTextureInternalFormat(kFboTextureFormat);
@@ -197,10 +192,12 @@ void OffscreenBrowserCompositorOutputSurface::OnReflectorChanged() {
void OffscreenBrowserCompositorOutputSurface::OnSwapBuffersComplete(
const std::vector<ui::LatencyInfo>& latency_info,
- uint64_t swap_id) {
+ bool need_presentation_feedback) {
RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
- client_->DidReceiveSwapBuffersAck(swap_id);
- client_->DidReceivePresentationFeedback(swap_id, gfx::PresentationFeedback());
+ latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
+ client_->DidReceiveSwapBuffersAck();
+ if (need_presentation_feedback)
+ client_->DidReceivePresentationFeedback(gfx::PresentationFeedback());
}
#if BUILDFLAG(ENABLE_VULKAN)
@@ -211,4 +208,8 @@ OffscreenBrowserCompositorOutputSurface::GetVulkanSurface() {
}
#endif
+unsigned OffscreenBrowserCompositorOutputSurface::UpdateGpuFence() {
+ return 0;
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
index a1f4e6df47f..f123692aebb 100644
--- a/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/offscreen_browser_compositor_output_surface.h
@@ -16,6 +16,7 @@
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "gpu/vulkan/buildflags.h"
#include "ui/latency/latency_info.h"
+#include "ui/latency/latency_tracker.h"
namespace ui {
class ContextProviderCommandBuffer;
@@ -51,28 +52,26 @@ class OffscreenBrowserCompositorOutputSurface
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
gfx::BufferFormat GetOverlayBufferFormat() const override;
- bool SurfaceIsSuspendForRecycle() const override;
uint32_t GetFramebufferCopyTextureFormat() override;
// BrowserCompositorOutputSurface implementation.
void OnReflectorChanged() override;
-#if defined(OS_MACOSX)
- void SetSurfaceSuspendedForRecycle(bool suspended) override {}
-#endif
#if BUILDFLAG(ENABLE_VULKAN)
gpu::VulkanSurface* GetVulkanSurface() override;
#endif
+ unsigned UpdateGpuFence() override;
+
void OnSwapBuffersComplete(const std::vector<ui::LatencyInfo>& latency_info,
- uint64_t swap_id);
+ bool need_presentation_feedback);
viz::OutputSurfaceClient* client_ = nullptr;
gfx::Size reshape_size_;
uint32_t fbo_ = 0;
bool reflector_changed_ = false;
std::unique_ptr<ReflectorTexture> reflector_texture_;
- uint64_t swap_id_ = 0;
+ ui::LatencyTracker latency_tracker_;
base::WeakPtrFactory<OffscreenBrowserCompositorOutputSurface>
weak_ptr_factory_;
diff --git a/chromium/content/browser/compositor/reflector_impl_unittest.cc b/chromium/content/browser/compositor/reflector_impl_unittest.cc
index 3d36fdbb7be..feb02e87cfb 100644
--- a/chromium/content/browser/compositor/reflector_impl_unittest.cc
+++ b/chromium/content/browser/compositor/reflector_impl_unittest.cc
@@ -24,7 +24,7 @@
#include "ui/compositor/test/context_factories_for_test.h"
#if defined(USE_OZONE)
-#include "cc/output/overlay_candidate.h"
+#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
#endif // defined(USE_OZONE)
@@ -102,7 +102,6 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
gfx::BufferFormat GetOverlayBufferFormat() const override {
return gfx::BufferFormat::RGBX_8888;
}
- bool SurfaceIsSuspendForRecycle() const override { return false; }
void OnReflectorChanged() override {
if (!reflector_) {
@@ -113,13 +112,10 @@ class TestOutputSurface : public BrowserCompositorOutputSurface {
}
}
-#if defined(OS_MACOSX)
- void SetSurfaceSuspendedForRecycle(bool suspended) override {}
-#endif
-
#if BUILDFLAG(ENABLE_VULKAN)
gpu::VulkanSurface* GetVulkanSurface() override { return nullptr; }
#endif
+ unsigned UpdateGpuFence() override { return 0; }
private:
std::unique_ptr<ReflectorTexture> reflector_texture_;
@@ -226,8 +222,8 @@ TEST_F(ReflectorImplTest, CheckInvertedOutputSurface) {
#if defined(USE_OZONE)
TEST_F(ReflectorImplTest, CheckOverlayNoReflector) {
- cc::OverlayCandidateList list;
- cc::OverlayCandidate plane_1, plane_2;
+ viz::OverlayCandidateList list;
+ viz::OverlayCandidate plane_1, plane_2;
plane_1.plane_z_order = 0;
plane_2.plane_z_order = 1;
list.push_back(plane_1);
@@ -238,8 +234,8 @@ TEST_F(ReflectorImplTest, CheckOverlayNoReflector) {
TEST_F(ReflectorImplTest, CheckOverlaySWMirroring) {
SetUpReflector();
- cc::OverlayCandidateList list;
- cc::OverlayCandidate plane_1, plane_2;
+ viz::OverlayCandidateList list;
+ viz::OverlayCandidate plane_1, plane_2;
plane_1.plane_z_order = 0;
plane_2.plane_z_order = 1;
list.push_back(plane_1);
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
index d402e04aeea..b5b49363709 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/viz/service/display/output_surface_client.h"
@@ -23,11 +22,9 @@ namespace content {
SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
std::unique_ptr<viz::SoftwareOutputDevice> software_device,
- const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ const UpdateVSyncParametersCallback& update_vsync_parameters_callback)
: BrowserCompositorOutputSurface(std::move(software_device),
update_vsync_parameters_callback),
- task_runner_(std::move(task_runner)),
weak_factory_(this) {}
SoftwareBrowserCompositorOutputSurface::
@@ -74,15 +71,11 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
base::TimeTicks swap_time = base::TimeTicks::Now();
for (auto& latency : frame.latency_info) {
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, swap_time, 1);
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
- swap_time, 1);
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, swap_time,
+ 1);
}
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&RenderWidgetHostImpl::OnGpuSwapBuffersCompleted,
- frame.latency_info));
gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
if (vsync_provider) {
@@ -91,20 +84,22 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
weak_factory_.GetWeakPtr()));
}
- ++swap_id_;
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback,
- weak_factory_.GetWeakPtr(), swap_id_));
+ software_device()->OnSwapBuffers(base::BindOnce(
+ &SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback,
+ weak_factory_.GetWeakPtr(), frame.latency_info,
+ frame.need_presentation_feedback));
}
void SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback(
- uint64_t swap_id) {
- client_->DidReceiveSwapBuffersAck(swap_id);
- client_->DidReceivePresentationFeedback(
- swap_id,
- gfx::PresentationFeedback(base::TimeTicks::Now(), refresh_interval_, 0u));
+ const std::vector<ui::LatencyInfo>& latency_info,
+ bool need_presentation_feedback) {
+ RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
+ latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
+ client_->DidReceiveSwapBuffersAck();
+ if (need_presentation_feedback) {
+ client_->DidReceivePresentationFeedback(gfx::PresentationFeedback(
+ base::TimeTicks::Now(), refresh_interval_, 0u));
+ }
}
void SoftwareBrowserCompositorOutputSurface::UpdateVSyncCallback(
@@ -127,11 +122,6 @@ SoftwareBrowserCompositorOutputSurface::GetOverlayBufferFormat() const {
return gfx::BufferFormat::RGBX_8888;
}
-bool SoftwareBrowserCompositorOutputSurface::SurfaceIsSuspendForRecycle()
- const {
- return false;
-}
-
uint32_t
SoftwareBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
// Not used for software surfaces.
@@ -139,12 +129,6 @@ SoftwareBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
return 0;
}
-#if defined(OS_MACOSX)
-void SoftwareBrowserCompositorOutputSurface::SetSurfaceSuspendedForRecycle(
- bool suspended) {
-}
-#endif
-
#if BUILDFLAG(ENABLE_VULKAN)
gpu::VulkanSurface* SoftwareBrowserCompositorOutputSurface::GetVulkanSurface() {
NOTIMPLEMENTED();
@@ -152,4 +136,8 @@ gpu::VulkanSurface* SoftwareBrowserCompositorOutputSurface::GetVulkanSurface() {
}
#endif
+unsigned SoftwareBrowserCompositorOutputSurface::UpdateGpuFence() {
+ return 0;
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
index 79bc9f5f6b8..80e0836a9d6 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -7,15 +7,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/common/content_export.h"
#include "gpu/vulkan/buildflags.h"
-
-namespace cc {
-class SoftwareOutputDevice;
-}
+#include "ui/latency/latency_tracker.h"
namespace content {
@@ -24,8 +20,7 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
public:
SoftwareBrowserCompositorOutputSurface(
std::unique_ptr<viz::SoftwareOutputDevice> software_device,
- const UpdateVSyncParametersCallback& update_vsync_parameters_callback,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ const UpdateVSyncParametersCallback& update_vsync_parameters_callback);
~SoftwareBrowserCompositorOutputSurface() override;
@@ -44,26 +39,21 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
gfx::BufferFormat GetOverlayBufferFormat() const override;
- bool SurfaceIsSuspendForRecycle() const override;
uint32_t GetFramebufferCopyTextureFormat() override;
#if BUILDFLAG(ENABLE_VULKAN)
gpu::VulkanSurface* GetVulkanSurface() override;
#endif
+ unsigned UpdateGpuFence() override;
private:
- // BrowserCompositorOutputSurface implementation.
-#if defined(OS_MACOSX)
- void SetSurfaceSuspendedForRecycle(bool suspended) override;
-#endif
-
- void SwapBuffersCallback(uint64_t swap_id);
+ void SwapBuffersCallback(const std::vector<ui::LatencyInfo>& latency_info,
+ bool need_presentation_feedback);
void UpdateVSyncCallback(const base::TimeTicks timebase,
const base::TimeDelta interval);
viz::OutputSurfaceClient* client_ = nullptr;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- uint64_t swap_id_ = 0;
base::TimeDelta refresh_interval_;
+ ui::LatencyTracker latency_tracker_;
base::WeakPtrFactory<SoftwareBrowserCompositorOutputSurface> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurface);
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
index 103c816895e..60ece2f2458 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
@@ -130,8 +130,7 @@ SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
std::move(device),
base::Bind(
&SoftwareBrowserCompositorOutputSurfaceTest::UpdateVSyncParameters,
- base::Unretained(this)),
- base::ThreadTaskRunnerHandle::Get());
+ base::Unretained(this)));
}
void SoftwareBrowserCompositorOutputSurfaceTest::UpdateVSyncParameters(
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.cc b/chromium/content/browser/compositor/viz_process_transport_factory.cc
index a2b4b4095c4..7f02b82c3a4 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.cc
@@ -5,6 +5,7 @@
#include "content/browser/compositor/viz_process_transport_factory.h"
#include <utility>
+#include <vector>
#include "base/command_line.h"
#include "base/debug/dump_without_crashing.h"
@@ -30,9 +31,9 @@
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
-#include "gpu/command_buffer/common/context_result.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "ui/base/ui_base_features.h"
#include "ui/compositor/reflector.h"
#if defined(OS_WIN)
@@ -73,7 +74,7 @@ scoped_refptr<ui::ContextProviderCommandBuffer> CreateContextProviderImpl(
std::move(gpu_channel_host), gpu_memory_buffer_manager,
kGpuStreamIdDefault, kGpuStreamPriorityUI, gpu::kNullSurfaceHandle,
std::move(url), kAutomaticFlushes, support_locking, support_grcontext,
- gpu::SharedMemoryLimits(), attributes, nullptr /* share_context */, type);
+ gpu::SharedMemoryLimits(), attributes, type);
}
bool IsContextLost(viz::ContextProvider* context_provider) {
@@ -128,7 +129,7 @@ VizProcessTransportFactory::VizProcessTransportFactory(
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableGpu) ||
command_line->HasSwitch(switches::kDisableGpuCompositing)) {
- CompositingModeFallbackToSoftware();
+ DisableGpuCompositing(nullptr);
}
}
@@ -195,8 +196,15 @@ VizProcessTransportFactory::SharedMainThreadContextProvider() {
return nullptr;
if (!main_context_provider_) {
- CreateContextProviders(
- gpu_channel_establish_factory_->EstablishGpuChannelSync());
+ auto context_result = gpu::ContextResult::kTransientFailure;
+ while (context_result == gpu::ContextResult::kTransientFailure) {
+ context_result = TryCreateContextsForGpuCompositing(
+ gpu_channel_establish_factory_->EstablishGpuChannelSync());
+
+ if (context_result == gpu::ContextResult::kFatalFailure)
+ DisableGpuCompositing(nullptr);
+ }
+ // On kFatalFailure |main_context_provider_| will be null.
}
return main_context_provider_;
@@ -359,19 +367,16 @@ viz::GLHelper* VizProcessTransportFactory::GetGLHelper() {
return nullptr;
}
-#if defined(OS_MACOSX)
-void VizProcessTransportFactory::SetCompositorSuspendedForRecycle(
- ui::Compositor* compositor,
- bool suspended) {
- NOTIMPLEMENTED();
+void VizProcessTransportFactory::OnContextLost() {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VizProcessTransportFactory::OnLostMainThreadSharedContext,
+ weak_ptr_factory_.GetWeakPtr()));
}
-#endif
-void VizProcessTransportFactory::CompositingModeFallbackToSoftware() {
- // This may happen multiple times, since when the viz process (re)starts, it
- // will send this notification if gpu is disabled.
- if (is_gpu_compositing_disabled_)
- return;
+void VizProcessTransportFactory::DisableGpuCompositing(
+ ui::Compositor* guilty_compositor) {
+ DLOG(ERROR) << "Switching to software compositing.";
// Change the result of IsGpuCompositingDisabled() before notifying anything.
is_gpu_compositing_disabled_ = true;
@@ -401,8 +406,15 @@ void VizProcessTransportFactory::CompositingModeFallbackToSoftware() {
to_release.reserve(compositor_data_map_.size());
for (auto& pair : compositor_data_map_) {
ui::Compositor* compositor = pair.first;
- if (!compositor->force_software_compositor())
+ // The |guilty_compositor| is in the process of setting up its FrameSink
+ // so removing it from |compositor_data_map_| would be both pointless and
+ // the cause of a crash.
+ // Compositors with force_software_compositor() do not follow the global
+ // compositing mode, so they do not need to changed.
+ if (compositor != guilty_compositor &&
+ !compositor->force_software_compositor()) {
to_release.push_back(compositor);
+ }
}
for (ui::Compositor* compositor : to_release) {
// Compositor expects to be not visible when releasing its FrameSink.
@@ -417,13 +429,6 @@ void VizProcessTransportFactory::CompositingModeFallbackToSoftware() {
GpuDataManagerImpl::GetInstance()->NotifyGpuInfoUpdate();
}
-void VizProcessTransportFactory::OnContextLost() {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&VizProcessTransportFactory::OnLostMainThreadSharedContext,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
void VizProcessTransportFactory::OnGpuProcessLost() {
// Reconnect HostFrameSinkManager to new GPU process.
ConnectHostFrameSinkManager();
@@ -439,18 +444,18 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
bool gpu_compositing =
!is_gpu_compositing_disabled_ && !compositor->force_software_compositor();
- // Only try to make contexts for gpu compositing.
if (gpu_compositing) {
- // TODO(kylechar): Check GPU compositing status from GpuFeatureInfo.
-
- if (!gpu_channel_host ||
- !CreateContextProviders(std::move(gpu_channel_host))) {
- // Retry on failure. If this isn't possible we should hear that we're
- // falling back to software compositing from the viz process eventually.
+ auto context_result =
+ TryCreateContextsForGpuCompositing(std::move(gpu_channel_host));
+ if (context_result == gpu::ContextResult::kTransientFailure) {
+ // Get a new GpuChannelHost and retry context creation.
gpu_channel_establish_factory_->EstablishGpuChannel(
base::BindOnce(&VizProcessTransportFactory::OnEstablishedGpuChannel,
weak_ptr_factory_.GetWeakPtr(), compositor_weak_ptr));
return;
+ } else if (context_result == gpu::ContextResult::kFatalFailure) {
+ DisableGpuCompositing(compositor);
+ gpu_compositing = false;
}
}
@@ -511,11 +516,6 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
viz::ClientLayerTreeFrameSink::InitParams params;
params.compositor_task_runner = compositor->task_runner();
params.gpu_memory_buffer_manager = GetGpuMemoryBufferManager();
- // TODO(crbug.com/730660): Adding ServerSharedBitmapManager here is just to
- // stop software compositing from crashing the browser process. Software
- // composited areas will be blank since the ShareBitmaps aren't shared with
- // the viz process. This mechanism is being rewritten currently.
- params.shared_bitmap_manager = viz::ServerSharedBitmapManager::current();
params.pipes.compositor_frame_sink_associated_info = std::move(sink_info);
params.pipes.client_request = std::move(client_request);
params.local_surface_id_provider =
@@ -542,27 +542,34 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
#endif
}
-bool VizProcessTransportFactory::CreateContextProviders(
+gpu::ContextResult
+VizProcessTransportFactory::TryCreateContextsForGpuCompositing(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
- constexpr bool kSharedWorkerContextSupportsLocking = true;
- constexpr bool kSharedWorkerContextSupportsGLES2 = false;
- constexpr bool kSharedWorkerContextSupportsRaster = true;
- constexpr bool kSharedWorkerContextSupportsGrContext = false;
- constexpr bool kCompositorContextSupportsLocking = false;
- constexpr bool kCompositorContextSupportsGLES2 = true;
- constexpr bool kCompositorContextSupportsRaster = false;
- constexpr bool kCompositorContextSupportsGrContext = true;
+ DCHECK(!is_gpu_compositing_disabled_);
- if (main_context_provider_ && IsContextLost(main_context_provider_.get())) {
- main_context_provider_->RemoveObserver(this);
- main_context_provider_ = nullptr;
- }
+ // Fallback to software compositing if there is no IPC channel.
+ if (!gpu_channel_host)
+ return gpu::ContextResult::kFatalFailure;
+
+ // Fallback to software compositing if GPU compositing is blacklisted.
+ auto gpu_compositing_status =
+ gpu_channel_host->gpu_feature_info()
+ .status_values[gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING];
+ if (gpu_compositing_status != gpu::kGpuFeatureStatusEnabled)
+ return gpu::ContextResult::kFatalFailure;
if (worker_context_provider_ &&
IsWorkerContextLost(worker_context_provider_.get()))
worker_context_provider_ = nullptr;
if (!worker_context_provider_) {
+ constexpr bool kSharedWorkerContextSupportsLocking = true;
+ constexpr bool kSharedWorkerContextSupportsRaster = true;
+ const bool kSharedWorkerContextSupportsGLES2 =
+ features::IsUiGpuRasterizationEnabled();
+ const bool kSharedWorkerContextSupportsGrContext =
+ features::IsUiGpuRasterizationEnabled();
+
worker_context_provider_ = CreateContextProviderImpl(
gpu_channel_host, GetGpuMemoryBufferManager(),
kSharedWorkerContextSupportsLocking, kSharedWorkerContextSupportsGLES2,
@@ -573,32 +580,42 @@ bool VizProcessTransportFactory::CreateContextProviders(
// Don't observer context loss on |worker_context_provider_| here, that is
// already observered by LayerTreeFrameSink. The lost context will be caught
// when recreating LayerTreeFrameSink(s).
- auto result = worker_context_provider_->BindToCurrentThread();
- if (result != gpu::ContextResult::kSuccess) {
+ auto context_result = worker_context_provider_->BindToCurrentThread();
+ if (context_result != gpu::ContextResult::kSuccess) {
worker_context_provider_ = nullptr;
- return false;
+ return context_result;
}
}
+ if (main_context_provider_ && IsContextLost(main_context_provider_.get())) {
+ main_context_provider_->RemoveObserver(this);
+ main_context_provider_ = nullptr;
+ }
+
if (!main_context_provider_) {
+ constexpr bool kCompositorContextSupportsLocking = false;
+ constexpr bool kCompositorContextSupportsGLES2 = true;
+ constexpr bool kCompositorContextSupportsRaster = false;
+ constexpr bool kCompositorContextSupportsGrContext = true;
+
main_context_provider_ = CreateContextProviderImpl(
std::move(gpu_channel_host), GetGpuMemoryBufferManager(),
kCompositorContextSupportsLocking, kCompositorContextSupportsGLES2,
kCompositorContextSupportsRaster, kCompositorContextSupportsGrContext,
ui::command_buffer_metrics::UI_COMPOSITOR_CONTEXT);
main_context_provider_->SetDefaultTaskRunner(resize_task_runner_);
- main_context_provider_->AddObserver(this);
- auto result = main_context_provider_->BindToCurrentThread();
- if (result != gpu::ContextResult::kSuccess) {
- main_context_provider_->RemoveObserver(this);
- main_context_provider_ = nullptr;
+ auto context_result = main_context_provider_->BindToCurrentThread();
+ if (context_result != gpu::ContextResult::kSuccess) {
worker_context_provider_ = nullptr;
- return false;
+ main_context_provider_ = nullptr;
+ return context_result;
}
+
+ main_context_provider_->AddObserver(this);
}
- return true;
+ return gpu::ContextResult::kSuccess;
}
void VizProcessTransportFactory::OnLostMainThreadSharedContext() {
diff --git a/chromium/content/browser/compositor/viz_process_transport_factory.h b/chromium/content/browser/compositor/viz_process_transport_factory.h
index 44c00cbc446..229b760eb08 100644
--- a/chromium/content/browser/compositor/viz_process_transport_factory.h
+++ b/chromium/content/browser/compositor/viz_process_transport_factory.h
@@ -15,9 +15,9 @@
#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/compositor/in_process_display_client.h"
+#include "gpu/command_buffer/common/context_result.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
-#include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "ui/compositor/compositor.h"
@@ -53,7 +53,6 @@ class ExternalBeginFrameControllerClientImpl;
class VizProcessTransportFactory : public ui::ContextFactory,
public ui::ContextFactoryPrivate,
public ImageTransportFactory,
- public viz::mojom::CompositingModeWatcher,
public viz::ContextLostObserver {
public:
VizProcessTransportFactory(
@@ -106,13 +105,6 @@ class VizProcessTransportFactory : public ui::ContextFactory,
ui::ContextFactory* GetContextFactory() override;
ui::ContextFactoryPrivate* GetContextFactoryPrivate() override;
viz::GLHelper* GetGLHelper() override;
-#if defined(OS_MACOSX)
- void SetCompositorSuspendedForRecycle(ui::Compositor* compositor,
- bool suspended) override;
-#endif
-
- // viz::mojom::CompositingModeWatcher implementation.
- void CompositingModeFallbackToSoftware() override;
// viz::ContextLostObserver implementation.
void OnContextLost() override;
@@ -138,6 +130,12 @@ class VizProcessTransportFactory : public ui::ContextFactory,
DISALLOW_COPY_AND_ASSIGN(CompositorData);
};
+ // Disables GPU compositing. This notifies UI and renderer compositors to drop
+ // LayerTreeFrameSinks and request new ones. If fallback happens while
+ // creating a new LayerTreeFrameSink for UI compositor it should be passed in
+ // as |guilty_compositor| to avoid extra work and reentrancy problems.
+ void DisableGpuCompositing(ui::Compositor* guilty_compositor);
+
// Provided as a callback when the GPU process has crashed.
void OnGpuProcessLost();
@@ -147,10 +145,15 @@ class VizProcessTransportFactory : public ui::ContextFactory,
base::WeakPtr<ui::Compositor> compositor_weak_ptr,
scoped_refptr<gpu::GpuChannelHost> gpu_channel);
- // Creates the necessary shared worker and compositor ContextProviders. If the
- // ContextProviders already exist and haven't been lost then it will do
- // nothing. Returns true if ContextProviders exist.
- bool CreateContextProviders(
+ // Tries to create the raster and main thread ContextProviders. If the
+ // ContextProviders already exist and haven't been lost then this will do
+ // nothing. Also verifies |gpu_channel_host| and checks if GPU compositing is
+ // blacklisted.
+ //
+ // Returns kSuccess if caller can use GPU compositing, kTransientFailure if
+ // caller should try again or kFatalFailure if caller should fallback to
+ // software compositing.
+ gpu::ContextResult TryCreateContextsForGpuCompositing(
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host);
void OnLostMainThreadSharedContext();
diff --git a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
index 72e1b33e041..50ea53d2cec 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
@@ -7,6 +7,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/service/display/output_surface_client.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "gpu/vulkan/vulkan_implementation.h"
#include "gpu/vulkan/vulkan_surface.h"
namespace content {
@@ -25,8 +26,9 @@ VulkanBrowserCompositorOutputSurface::~VulkanBrowserCompositorOutputSurface() {
bool VulkanBrowserCompositorOutputSurface::Initialize(
gfx::AcceleratedWidget widget) {
DCHECK(!surface_);
- std::unique_ptr<gpu::VulkanSurface> surface(
- gpu::VulkanSurface::CreateViewSurface(widget));
+ std::unique_ptr<gpu::VulkanSurface> surface =
+ vulkan_context_provider()->GetVulkanImplementation()->CreateViewSurface(
+ widget);
if (!surface->Initialize(vulkan_context_provider()->GetDeviceQueue(),
gpu::VulkanSurface::DEFAULT_SURFACE_FORMAT)) {
return false;
@@ -78,11 +80,6 @@ gfx::BufferFormat VulkanBrowserCompositorOutputSurface::GetOverlayBufferFormat()
return gfx::BufferFormat::RGBX_8888;
}
-bool VulkanBrowserCompositorOutputSurface::SurfaceIsSuspendForRecycle() const {
- NOTIMPLEMENTED();
- return false;
-}
-
void VulkanBrowserCompositorOutputSurface::Reshape(
const gfx::Size& size,
float device_scale_factor,
@@ -106,17 +103,15 @@ VulkanBrowserCompositorOutputSurface::GetFramebufferCopyTextureFormat() {
void VulkanBrowserCompositorOutputSurface::SwapBuffers(
viz::OutputSurfaceFrame frame) {
surface_->SwapBuffers();
- ++swap_id_;
-
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&VulkanBrowserCompositorOutputSurface::SwapBuffersAck,
- weak_ptr_factory_.GetWeakPtr(), swap_id_));
+ weak_ptr_factory_.GetWeakPtr()));
}
-void VulkanBrowserCompositorOutputSurface::SwapBuffersAck(uint64_t swap_id) {
+void VulkanBrowserCompositorOutputSurface::SwapBuffersAck() {
DCHECK(client_);
- client_->DidReceiveSwapBuffersAck(swap_id);
+ client_->DidReceiveSwapBuffersAck();
}
gpu::VulkanSurface* VulkanBrowserCompositorOutputSurface::GetVulkanSurface() {
diff --git a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
index 9398765c250..7de13ae0e6a 100644
--- a/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/vulkan_browser_compositor_output_surface.h
@@ -39,7 +39,6 @@ class VulkanBrowserCompositorOutputSurface
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
gfx::BufferFormat GetOverlayBufferFormat() const override;
- bool SurfaceIsSuspendForRecycle() const override;
void Reshape(const gfx::Size& size,
float device_scale_factor,
const gfx::ColorSpace& color_space,
@@ -52,11 +51,10 @@ class VulkanBrowserCompositorOutputSurface
gpu::VulkanSurface* GetVulkanSurface() override;
private:
- void SwapBuffersAck(uint64_t swap_id);
+ void SwapBuffersAck();
std::unique_ptr<gpu::VulkanSurface> surface_;
viz::OutputSurfaceClient* client_ = nullptr;
- uint64_t swap_id_ = 0;
base::WeakPtrFactory<VulkanBrowserCompositorOutputSurface> weak_ptr_factory_;
diff --git a/chromium/content/browser/cookie_store/BUILD.gn b/chromium/content/browser/cookie_store/BUILD.gn
new file mode 100644
index 00000000000..d5dbdd7fca9
--- /dev/null
+++ b/chromium/content/browser/cookie_store/BUILD.gn
@@ -0,0 +1,11 @@
+# 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("//third_party/protobuf/proto_library.gni")
+
+proto_library("cookie_store_proto") {
+ sources = [
+ "cookie_change_subscriptions.proto",
+ ]
+}
diff --git a/chromium/content/browser/cookie_store/OWNERS b/chromium/content/browser/cookie_store/OWNERS
new file mode 100644
index 00000000000..b23c10fd54c
--- /dev/null
+++ b/chromium/content/browser/cookie_store/OWNERS
@@ -0,0 +1,8 @@
+# Primary
+pwnall@chromium.org
+
+# Secondary
+jsbell@chromium.org
+
+# TEAM: storage-dev@chromium.org
+# COMPONENT: Blink>Storage>CookiesAPI
diff --git a/chromium/content/browser/cookie_store/cookie_change_subscription.cc b/chromium/content/browser/cookie_store/cookie_change_subscription.cc
new file mode 100644
index 00000000000..78c410148a3
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_change_subscription.cc
@@ -0,0 +1,182 @@
+// 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/cookie_store/cookie_change_subscription.h"
+
+#include <utility>
+
+#include "content/browser/cookie_store/cookie_change_subscriptions.pb.h"
+
+namespace content {
+
+namespace {
+
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatching enums: " #a)
+
+STATIC_ASSERT_ENUM(network::mojom::CookieMatchType::EQUALS,
+ proto::CookieMatchType::EQUALS);
+STATIC_ASSERT_ENUM(network::mojom::CookieMatchType::STARTS_WITH,
+ proto::CookieMatchType::STARTS_WITH);
+
+proto::CookieMatchType CookieMatchTypeToProto(
+ network::mojom::CookieMatchType match_type) {
+ switch (match_type) {
+ case network::mojom::CookieMatchType::EQUALS:
+ return proto::CookieMatchType::EQUALS;
+ case ::network::mojom::CookieMatchType::STARTS_WITH:
+ return proto::CookieMatchType::STARTS_WITH;
+ }
+ NOTREACHED();
+ return proto::CookieMatchType::EQUALS;
+}
+
+network::mojom::CookieMatchType CookieMatchTypeFromProto(
+ proto::CookieMatchType match_type_proto) {
+ switch (match_type_proto) {
+ case proto::CookieMatchType::EQUALS:
+ return network::mojom::CookieMatchType::EQUALS;
+ case proto::CookieMatchType::STARTS_WITH:
+ return ::network::mojom::CookieMatchType::STARTS_WITH;
+ }
+ NOTREACHED();
+ return network::mojom::CookieMatchType::EQUALS;
+}
+
+} // namespace
+
+// static
+base::Optional<std::vector<CookieChangeSubscription>>
+CookieChangeSubscription::DeserializeVector(
+ const std::string& proto_string,
+ int64_t service_worker_registration_id) {
+ proto::CookieChangeSubscriptionsProto subscriptions_proto;
+ if (!subscriptions_proto.ParseFromString(proto_string))
+ return base::nullopt;
+
+ std::vector<CookieChangeSubscription> subscriptions;
+ int subscription_count = subscriptions_proto.subscriptions_size();
+ subscriptions.reserve(subscription_count);
+ for (int i = 0; i < subscription_count; ++i) {
+ base::Optional<CookieChangeSubscription> subscription_opt =
+ CookieChangeSubscription::Create(subscriptions_proto.subscriptions(i),
+ service_worker_registration_id);
+ if (!subscription_opt.has_value())
+ continue;
+ subscriptions.emplace_back(std::move(subscription_opt).value());
+ }
+
+ return base::make_optional(
+ std::vector<CookieChangeSubscription>(std::move(subscriptions)));
+}
+
+// static
+std::vector<CookieChangeSubscription> CookieChangeSubscription::FromMojoVector(
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr> mojo_subscriptions,
+ int64_t service_worker_registration_id) {
+ std::vector<CookieChangeSubscription> subscriptions;
+ subscriptions.reserve(mojo_subscriptions.size());
+ for (const auto& mojo_subscription : mojo_subscriptions) {
+ subscriptions.emplace_back(
+ std::move(mojo_subscription->url), std::move(mojo_subscription->name),
+ mojo_subscription->match_type, service_worker_registration_id);
+ }
+ return subscriptions;
+}
+
+// static
+std::string CookieChangeSubscription::SerializeVector(
+ const std::vector<CookieChangeSubscription>& subscriptions) {
+ proto::CookieChangeSubscriptionsProto subscriptions_proto;
+ for (const auto& subscription : subscriptions)
+ subscription.Serialize(subscriptions_proto.add_subscriptions());
+ return subscriptions_proto.SerializeAsString();
+}
+
+// static
+std::vector<blink::mojom::CookieChangeSubscriptionPtr>
+CookieChangeSubscription::ToMojoVector(
+ const std::vector<CookieChangeSubscription>& subscriptions) {
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr> mojo_subscriptions;
+ mojo_subscriptions.reserve(subscriptions.size());
+ for (const auto& subscription : subscriptions) {
+ auto mojo_subscription = blink::mojom::CookieChangeSubscription::New();
+ subscription.Serialize(mojo_subscription.get());
+ mojo_subscriptions.emplace_back(std::move(mojo_subscription));
+ }
+ return mojo_subscriptions;
+}
+
+// static
+base::Optional<CookieChangeSubscription> CookieChangeSubscription::Create(
+ proto::CookieChangeSubscriptionProto proto,
+ int64_t service_worker_registration_id) {
+ if (!proto.has_url())
+ return base::nullopt;
+ GURL url = GURL(proto.url());
+ if (!url.is_valid())
+ return base::nullopt;
+
+ std::string name = proto.has_name() ? proto.name() : "";
+ ::network::mojom::CookieMatchType match_type =
+ proto.has_match_type() ? CookieMatchTypeFromProto(proto.match_type())
+ : ::network::mojom::CookieMatchType::EQUALS;
+
+ return CookieChangeSubscription(std::move(url), std::move(name), match_type,
+ service_worker_registration_id);
+}
+
+CookieChangeSubscription::CookieChangeSubscription(CookieChangeSubscription&&) =
+ default;
+
+CookieChangeSubscription::~CookieChangeSubscription() = default;
+
+CookieChangeSubscription::CookieChangeSubscription(
+ GURL url,
+ std::string name,
+ ::network::mojom::CookieMatchType match_type,
+ int64_t service_worker_registration_id)
+ : url_(std::move(url)),
+ name_(std::move(name)),
+ match_type_(match_type),
+ service_worker_registration_id_(service_worker_registration_id) {}
+
+void CookieChangeSubscription::Serialize(
+ proto::CookieChangeSubscriptionProto* proto) const {
+ proto->set_match_type(CookieMatchTypeToProto(match_type_));
+ proto->set_name(name_);
+ proto->set_url(url_.spec());
+}
+
+void CookieChangeSubscription::Serialize(
+ blink::mojom::CookieChangeSubscription* mojo_subscription) const {
+ mojo_subscription->url = url_;
+ mojo_subscription->name = name_;
+ mojo_subscription->match_type = match_type_;
+}
+
+bool CookieChangeSubscription::ShouldObserveChangeTo(
+ const net::CanonicalCookie& cookie) const {
+ switch (match_type_) {
+ case ::network::mojom::CookieMatchType::EQUALS:
+ if (cookie.Name() != name_)
+ return false;
+ break;
+ case ::network::mojom::CookieMatchType::STARTS_WITH:
+ if (!base::StartsWith(cookie.Name(), name_, base::CompareCase::SENSITIVE))
+ return false;
+ break;
+ }
+
+ net::CookieOptions net_options;
+ net_options.set_same_site_cookie_mode(
+ net::CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ if (!cookie.IncludeForRequestURL(url_, net_options))
+ return false;
+
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cookie_store/cookie_change_subscription.h b/chromium/content/browser/cookie_store/cookie_change_subscription.h
new file mode 100644
index 00000000000..c2c4839a26d
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_change_subscription.h
@@ -0,0 +1,114 @@
+// 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_COOKIE_STORE_COOKIE_CHANGE_SUBSCRIPTION_H_
+#define CONTENT_BROWSER_COOKIE_STORE_COOKIE_CHANGE_SUBSCRIPTION_H_
+
+#include <memory>
+#include <string>
+
+#include "base/containers/linked_list.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace proto {
+
+class CookieChangeSubscriptionProto;
+
+} // namespace proto
+
+// Represents a single subscription to the list of cookies sent to a URL.
+//
+// The included linked list node and service worker registration ID are used by
+// CookieStoreManager.
+class CookieChangeSubscription
+ : public base::LinkNode<CookieChangeSubscription> {
+ public:
+ // Used to read a service worker's subscriptions from the persistent store.
+ static base::Optional<std::vector<CookieChangeSubscription>>
+ DeserializeVector(const std::string& proto_string,
+ int64_t service_worker_registration_id);
+
+ // Converts subscriptions from a Mojo API call.
+ static std::vector<CookieChangeSubscription> FromMojoVector(
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr> mojo_subscriptions,
+ int64_t service_worker_registration_id);
+
+ // Used to write a service worker's subscriptions to the service worker store.
+ //
+ // Returns the empty string in case of a serialization error.
+ static std::string SerializeVector(
+ const std::vector<CookieChangeSubscription>&);
+
+ // Converts a service worker's subscriptions to a Mojo API call result.
+ static std::vector<blink::mojom::CookieChangeSubscriptionPtr> ToMojoVector(
+ const std::vector<CookieChangeSubscription>&);
+
+ // Public for testing.
+ //
+ // Production code should use the vector-based factory methods above.
+ static base::Optional<CookieChangeSubscription> Create(
+ proto::CookieChangeSubscriptionProto proto,
+ int64_t service_worker_registration_id);
+
+ // Public for testing.
+ //
+ // Production code should use the vector-based factory methods above.
+ CookieChangeSubscription(GURL url,
+ std::string name,
+ ::network::mojom::CookieMatchType match_type,
+ int64_t service_worker_registration_id);
+
+ // LinkNode supports move-construction, but not move assignment.
+ CookieChangeSubscription(CookieChangeSubscription&&);
+ CookieChangeSubscription& operator=(CookieChangeSubscription&&) = delete;
+
+ ~CookieChangeSubscription();
+
+ // The URL whose cookie list is watched for changes.
+ const GURL& url() const { return url_; }
+
+ // Operator for name-based matching.
+ //
+ // This is used to implement both equality and prefix-based name matching.
+ // Supporting the latter helps avoid wasting battery by waking up service
+ // workers unnecessarily.
+ ::network::mojom::CookieMatchType match_type() const { return match_type_; }
+
+ // Operand for the name-based matching operator above.
+ //
+ // For EQUAL matching, the cookie name must precisely match name(). For
+ // STARTS_WITH matching, the cookie name must be prefixed by name().
+ const std::string& name() const { return name_; }
+
+ // The service worker registration that this subscription belongs to.
+ int64_t service_worker_registration_id() const {
+ return service_worker_registration_id_;
+ }
+
+ // Writes the subscription to the given protobuf.
+ void Serialize(proto::CookieChangeSubscriptionProto* proto) const;
+ // Writes the subscription to the given Mojo object.
+ void Serialize(
+ blink::mojom::CookieChangeSubscription* mojo_subscription) const;
+
+ // True if the subscription covers a change to the given cookie.
+ bool ShouldObserveChangeTo(const net::CanonicalCookie& cookie) const;
+
+ private:
+ const GURL url_;
+ const std::string name_;
+ const ::network::mojom::CookieMatchType match_type_;
+ const int64_t service_worker_registration_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(CookieChangeSubscription);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COOKIE_STORE_COOKIE_CHANGE_SUBSCRIPTION_H_
diff --git a/chromium/content/browser/cookie_store/cookie_change_subscriptions.proto b/chromium/content/browser/cookie_store/cookie_change_subscriptions.proto
new file mode 100644
index 00000000000..4ee027f6075
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_change_subscriptions.proto
@@ -0,0 +1,27 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content.proto;
+
+// Proto equivalent of network::mojom::CookieMatchType. Values must match.
+enum CookieMatchType {
+ EQUALS = 0;
+ STARTS_WITH = 1;
+}
+
+// A single cookie change subscription.
+message CookieChangeSubscriptionProto {
+ required string url = 1;
+ optional string name = 2;
+ optional CookieMatchType match_type = 3;
+}
+
+// All cookie change subscriptions belonging to a service worker registration.
+message CookieChangeSubscriptionsProto {
+ repeated CookieChangeSubscriptionProto subscriptions = 1;
+}
diff --git a/chromium/content/browser/cookie_store/cookie_store_context.cc b/chromium/content/browser/cookie_store/cookie_store_context.cc
new file mode 100644
index 00000000000..eeea0d01a97
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_store_context.cc
@@ -0,0 +1,117 @@
+// 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/cookie_store/cookie_store_context.h"
+
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+
+namespace content {
+
+CookieStoreContext::CookieStoreContext()
+ : base::RefCountedDeleteOnSequence<CookieStoreContext>(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)) {}
+
+CookieStoreContext::~CookieStoreContext() {
+ // The destructor must be called on the IO thread, because it runs
+ // cookie_store_manager_'s destructor, and the latter is only accessed on the
+ // IO thread.
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void CookieStoreContext::Initialize(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(!initialize_called_) << __func__ << " called twice";
+ initialize_called_ = true;
+#endif // DCHECK_IS_ON()
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &CookieStoreContext::InitializeOnIOThread, this,
+ std::move(service_worker_context),
+ base::BindOnce(
+ [](scoped_refptr<base::SequencedTaskRunner> task_runner,
+ base::OnceCallback<void(bool)> callback, bool result) {
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), result));
+ },
+ base::SequencedTaskRunnerHandle::Get(), std::move(callback))));
+}
+
+void CookieStoreContext::ListenToCookieChanges(
+ ::network::mojom::NetworkContext* network_context,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(initialize_called_) << __func__ << " called before Initialize()";
+#endif // DCHECK_IS_ON()
+
+ ::network::mojom::CookieManagerPtrInfo cookie_manager_ptr_info;
+ network_context->GetCookieManager(
+ mojo::MakeRequest(&cookie_manager_ptr_info));
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &CookieStoreContext::ListenToCookieChangesOnIOThread, this,
+ std::move(cookie_manager_ptr_info),
+ base::BindOnce(
+ [](scoped_refptr<base::SequencedTaskRunner> task_runner,
+ base::OnceCallback<void(bool)> callback, bool result) {
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), result));
+ },
+ base::SequencedTaskRunnerHandle::Get(), std::move(callback))));
+}
+
+void CookieStoreContext::CreateService(blink::mojom::CookieStoreRequest request,
+ const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if DCHECK_IS_ON()
+ DCHECK(initialize_called_) << __func__ << " called before Initialize()";
+#endif // DCHECK_IS_ON()
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&CookieStoreContext::CreateServiceOnIOThread, this,
+ std::move(request), origin));
+}
+
+void CookieStoreContext::InitializeOnIOThread(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!cookie_store_manager_) << __func__ << " called more than once";
+
+ cookie_store_manager_ =
+ std::make_unique<CookieStoreManager>(std::move(service_worker_context));
+ cookie_store_manager_->LoadAllSubscriptions(std::move(callback));
+}
+
+void CookieStoreContext::ListenToCookieChangesOnIOThread(
+ ::network::mojom::CookieManagerPtrInfo cookie_manager_ptr_info,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(cookie_store_manager_);
+
+ cookie_store_manager_->ListenToCookieChanges(
+ ::network::mojom::CookieManagerPtr(std::move(cookie_manager_ptr_info)),
+ std::move(callback));
+}
+
+void CookieStoreContext::CreateServiceOnIOThread(
+ blink::mojom::CookieStoreRequest request,
+ const url::Origin& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(cookie_store_manager_);
+
+ cookie_store_manager_->CreateService(std::move(request), origin);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cookie_store/cookie_store_context.h b/chromium/content/browser/cookie_store/cookie_store_context.h
new file mode 100644
index 00000000000..0317b9f0773
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_store_context.h
@@ -0,0 +1,98 @@
+// 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_COOKIE_STORE_COOKIE_STORE_CONTEXT_H_
+#define CONTENT_BROWSER_COOKIE_STORE_COOKIE_STORE_CONTEXT_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted_delete_on_sequence.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/cookie_store/cookie_store_manager.h"
+#include "content/common/content_export.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
+#include "url/origin.h"
+
+namespace content {
+
+class CookieStoreManager;
+class ServiceWorkerContextWrapper;
+
+// UI thread handle to a CookieStoreManager.
+//
+// This class is RefCountedDeleteOnSequence because it has members that must be
+// accessed on the IO thread, and therefore must be destroyed on the IO thread.
+// Conceptually, CookieStoreContext instances are owned by StoragePartitionImpl.
+class CONTENT_EXPORT CookieStoreContext
+ : public base::RefCountedDeleteOnSequence<CookieStoreContext> {
+ public:
+ REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+
+ // Creates an empty CookieStoreContext shell.
+ //
+ // Newly created instances must be initialized via Initialize() before any
+ // other methods are used.
+ CookieStoreContext();
+
+ // Creates the underlying CookieStoreManager.
+ //
+ // This must be called before any other CookieStoreContext method.
+ //
+ // The newly created CookieStoreManager starts loading any persisted cookie
+ // change subscriptions from ServiceWorkerStorage. When the loading completes,
+ // the given callback is called with a boolean indicating whether the loading
+ // succeeded.
+ //
+ // It is safe to call all the other methods during the loading operation. This
+ // includes creating and using CookieStore mojo services. The
+ // CookieStoreManager has well-defined semantics if loading from
+ // ServiceWorkerStorage fails, so the caller does not need to handle loading
+ // errors.
+ void Initialize(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ base::OnceCallback<void(bool)> callback);
+
+ // Starts listening to cookie changes from a network service instance.
+ //
+ // The callback is called with the (success / failure) result of subscribing.
+ void ListenToCookieChanges(::network::mojom::NetworkContext* network_context,
+ base::OnceCallback<void(bool)> callback);
+
+ // Routes a mojo request to the CookieStoreManager on the IO thread.
+ void CreateService(blink::mojom::CookieStoreRequest request,
+ const url::Origin& origin);
+
+ private:
+ friend class base::RefCountedDeleteOnSequence<CookieStoreContext>;
+ friend class base::DeleteHelper<CookieStoreContext>;
+ ~CookieStoreContext();
+
+ void InitializeOnIOThread(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ base::OnceCallback<void(bool)> callback);
+
+ void ListenToCookieChangesOnIOThread(
+ ::network::mojom::CookieManagerPtrInfo cookie_manager_ptr_info,
+ base::OnceCallback<void(bool)> callback);
+
+ void CreateServiceOnIOThread(blink::mojom::CookieStoreRequest request,
+ const url::Origin& origin);
+
+ // Only accessed on the IO thread.
+ std::unique_ptr<CookieStoreManager> cookie_store_manager_;
+
+#if DCHECK_IS_ON()
+ // Only accesssed on the UI thread.
+ bool initialize_called_ = false;
+#endif // DCHECK_IS_ON()
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(CookieStoreContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COOKIE_STORE_COOKIE_STORE_CONTEXT_H_
diff --git a/chromium/content/browser/cookie_store/cookie_store_host.cc b/chromium/content/browser/cookie_store/cookie_store_host.cc
new file mode 100644
index 00000000000..685abad2e34
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_store_host.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 "content/browser/cookie_store/cookie_store_host.h"
+
+#include <utility>
+
+#include "content/browser/cookie_store/cookie_store_manager.h"
+#include "url/origin.h"
+
+namespace content {
+
+CookieStoreHost::CookieStoreHost(CookieStoreManager* manager,
+ const url::Origin& origin)
+ : manager_(manager), origin_(origin) {}
+
+CookieStoreHost::~CookieStoreHost() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void CookieStoreHost::AppendSubscriptions(
+ int64_t service_worker_registration_id,
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr> subscriptions,
+ AppendSubscriptionsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ manager_->AppendSubscriptions(service_worker_registration_id, origin_,
+ std::move(subscriptions), std::move(callback));
+}
+
+void CookieStoreHost::GetSubscriptions(int64_t service_worker_registration_id,
+ GetSubscriptionsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ manager_->GetSubscriptions(service_worker_registration_id, origin_,
+ std::move(callback));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cookie_store/cookie_store_host.h b/chromium/content/browser/cookie_store/cookie_store_host.h
new file mode 100644
index 00000000000..af259ddc465
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_store_host.h
@@ -0,0 +1,59 @@
+// 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_COOKIE_STORE_COOKIE_STORE_HOST_H_
+#define CONTENT_BROWSER_COOKIE_STORE_COOKIE_STORE_HOST_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
+#include "url/origin.h"
+
+namespace content {
+
+class CookieStoreManager;
+
+// Stores the state associated with each CookieStore mojo connection.
+//
+// The bulk of the CookieStore implementation is in the CookieStoreManager
+// class. Each StoragePartition has a single associated CookieStoreManager
+// instance. By contrast, each CookieStore mojo connection has an associated
+// CoookieStoreHost instance, which stores the per-connection state.
+//
+// Instances of this class must be accessed exclusively on the IO thread,
+// because they call into CookieStoreManager directly.
+class CookieStoreHost : public blink::mojom::CookieStore {
+ public:
+ CookieStoreHost(CookieStoreManager* manager, const url::Origin& origin);
+ ~CookieStoreHost() override;
+
+ // content::mojom::CookieStore
+ void AppendSubscriptions(
+ int64_t service_worker_registration_id,
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr>,
+ AppendSubscriptionsCallback callback) override;
+ void GetSubscriptions(int64_t service_worker_registration_id,
+ GetSubscriptionsCallback callback) override;
+
+ private:
+ // The raw pointer is safe because CookieStoreManager owns this instance via a
+ // mojo::BindingSet.
+ CookieStoreManager* const manager_;
+
+ const url::Origin origin_;
+
+ // Instances of this class are currently bound to the IO thread, because they
+ // call ServiceWorkerContextWrapper methods that are restricted to the IO
+ // thread. However, the class implementation itself is thread-friendly, so it
+ // only checks that methods are called on the same sequence.
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(CookieStoreHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COOKIE_STORE_COOKIE_STORE_HOST_H_
diff --git a/chromium/content/browser/cookie_store/cookie_store_manager.cc b/chromium/content/browser/cookie_store/cookie_store_manager.cc
new file mode 100644
index 00000000000..8e08a32ed55
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_store_manager.cc
@@ -0,0 +1,530 @@
+// 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/cookie_store/cookie_store_manager.h"
+
+#include <utility>
+
+#include "base/optional.h"
+#include "content/browser/cookie_store/cookie_change_subscriptions.pb.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/public/browser/browser_context.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+// ServiceWorkerStorage user data key for cookie change subscriptions.
+const char kSubscriptionsUserKey[] = "cookie_store_subscriptions";
+
+// Handles the result of ServiceWorkerContextWrapper::StoreRegistrationUserData.
+void HandleStoreRegistrationUserDataStatus(ServiceWorkerStatusCode status) {
+ // The current implementation does not have a good way to handle errors in
+ // StoreRegistrationUserData. Cookie change subscriptions have been added to
+ // the registration during the install event, so it's too late to surface the
+ // error to the renderer. The registration has already been persisted, and the
+ // Service Worker is likely active by now.
+ DLOG_IF(ERROR, status != SERVICE_WORKER_OK)
+ << "StoreRegistrationUserData failed";
+}
+
+} // namespace
+
+CookieStoreManager::CookieStoreManager(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+ : service_worker_context_(std::move(service_worker_context)),
+ cookie_change_listener_binding_(this),
+ registration_user_data_key_(kSubscriptionsUserKey),
+ weak_factory_(this) {
+ service_worker_context_->AddObserver(this);
+}
+
+CookieStoreManager::~CookieStoreManager() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ service_worker_context_->RemoveObserver(this);
+}
+
+void CookieStoreManager::CreateService(blink::mojom::CookieStoreRequest request,
+ const url::Origin& origin) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ bindings_.AddBinding(std::make_unique<CookieStoreHost>(this, origin),
+ std::move(request));
+}
+
+void CookieStoreManager::LoadAllSubscriptions(
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ DCHECK(!done_loading_subscriptions_) << __func__ << " already called";
+
+ service_worker_context_->GetUserDataForAllRegistrations(
+ registration_user_data_key_,
+ base::BindOnce(&CookieStoreManager::ProcessOnDiskSubscriptions,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void CookieStoreManager::ListenToCookieChanges(
+ ::network::mojom::CookieManagerPtr cookie_manager,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ DCHECK(!cookie_manager_) << __func__ << " already called";
+ cookie_manager_ = std::move(cookie_manager);
+
+ DCHECK(!cookie_change_listener_binding_.is_bound());
+ ::network::mojom::CookieChangeListenerPtr cookie_change_listener;
+ cookie_change_listener_binding_.Bind(
+ mojo::MakeRequest(&cookie_change_listener));
+
+ // TODO(pwnall): Switch to an API with subscription confirmation.
+ cookie_manager_->AddGlobalChangeListener(std::move(cookie_change_listener));
+ std::move(callback).Run(true);
+}
+
+void CookieStoreManager::ProcessOnDiskSubscriptions(
+ base::OnceCallback<void(bool)> load_callback,
+ const std::vector<std::pair<int64_t, std::string>>& user_data,
+ ServiceWorkerStatusCode status) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ DCHECK(!done_loading_subscriptions_) << __func__ << " already called";
+ done_loading_subscriptions_ = true;
+
+ if (status != SERVICE_WORKER_OK) {
+ DidLoadAllSubscriptions(false, std::move(load_callback));
+ return;
+ }
+
+ DCHECK(subscriptions_by_registration_.empty());
+ subscriptions_by_registration_.reserve(user_data.size());
+ bool load_success = true;
+ for (const auto& pair : user_data) {
+ int64_t service_worker_registration_id = pair.first;
+ const std::string& proto_string = pair.second;
+
+ base::Optional<std::vector<CookieChangeSubscription>> subscriptions_opt =
+ CookieChangeSubscription::DeserializeVector(
+ proto_string, service_worker_registration_id);
+ if (!subscriptions_opt.has_value()) {
+ load_success = false;
+ continue;
+ }
+
+ ActivateSubscriptions(&subscriptions_opt.value());
+ DCHECK(
+ !subscriptions_by_registration_.count(service_worker_registration_id));
+ subscriptions_by_registration_.emplace(
+ std::move(service_worker_registration_id),
+ std::move(subscriptions_opt).value());
+ }
+
+ DidLoadAllSubscriptions(load_success, std::move(load_callback));
+}
+
+void CookieStoreManager::DidLoadAllSubscriptions(
+ bool succeeded,
+ base::OnceCallback<void(bool)> load_callback) {
+ DCHECK(done_loading_subscriptions_);
+ succeeded_loading_subscriptions_ = succeeded;
+
+ for (auto& callback : subscriptions_loaded_callbacks_)
+ std::move(callback).Run();
+ subscriptions_loaded_callbacks_.clear();
+
+ std::move(load_callback).Run(succeeded);
+}
+
+void CookieStoreManager::AppendSubscriptions(
+ int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr> mojo_subscriptions,
+ blink::mojom::CookieStore::AppendSubscriptionsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (!done_loading_subscriptions_) {
+ subscriptions_loaded_callbacks_.emplace_back(base::BindOnce(
+ &CookieStoreManager::AppendSubscriptions, weak_factory_.GetWeakPtr(),
+ service_worker_registration_id, origin, std::move(mojo_subscriptions),
+ std::move(callback)));
+ return;
+ }
+
+ if (!succeeded_loading_subscriptions_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ // GetLiveRegistration() is sufficient here (as opposed to a flavor of
+ // FindRegistration()) because AppendSubscriptions is only called from the
+ // implementation of the Cookie Store API, which is exposed to
+ // ServiceWorkerGlobalScope. ServiceWorkerGlobalScope references the
+ // service worker's registration via a ServiceWorkerRegistration JavaScript
+ // object, so the registration is guaranteed to be live while the service
+ // worker is executing.
+ //
+ // It is possible for the service worker to get killed while this API call is
+ // in progress, for example, if the service worker code exceeds an event
+ // handling time limit. In that case, the return value will not be observed,
+ // so a false negative is acceptable.
+ ServiceWorkerRegistration* service_worker_registration =
+ service_worker_context_->GetLiveRegistration(
+ service_worker_registration_id);
+ if (!service_worker_registration ||
+ !origin.IsSameOriginWith(
+ url::Origin::Create(service_worker_registration->pattern()))) {
+ // This error case is a good fit for mojo::ReportBadMessage(), because the
+ // renderer has passed an invalid registration ID. However, the code here
+ // might run without a mojo call context, if the original call was delayed
+ // while loading on-disk subscription data.
+ //
+ // While it would be possible to have two code paths for the two situations,
+ // the extra complexity doesn't seem warranted for the limited debuggig
+ // benefits provided by mojo::ReportBadMessage.
+ std::move(callback).Run(false);
+ return;
+ }
+
+ // TODO(crbug.com/843079): This check incorrectly allows an active service
+ // worker version to call the API, if another version
+ // is installing at the same time.
+ if (!service_worker_registration->installing_version()) {
+ // A service worker's cookie change subscriptions can only be modified while
+ // the service worker's install event is handled.
+ std::move(callback).Run(false);
+ return;
+ }
+
+ if (mojo_subscriptions.empty()) {
+ // Empty subscriptions are special-cased so we never have to serialize an
+ // empty array of subscriptions. This is advantageous because the protobuf
+ // serialization of an empty array is the empty string, which is also used
+ // by the convenience protobuf serialization API to signal serialization
+ // failure. So, supporting serializing an empty array would mean we can't
+ // use the convenience serialization API.
+ std::move(callback).Run(true);
+ return;
+ }
+
+ std::vector<CookieChangeSubscription> new_subscriptions =
+ CookieChangeSubscription::FromMojoVector(
+ std::move(mojo_subscriptions), service_worker_registration->id());
+ DCHECK(!new_subscriptions.empty());
+
+ auto old_subscriptions_it =
+ subscriptions_by_registration_.find(service_worker_registration_id);
+ if (old_subscriptions_it == subscriptions_by_registration_.end()) {
+ subscriptions_by_registration_.emplace(service_worker_registration_id,
+ std::move(new_subscriptions));
+ std::move(callback).Run(true);
+ return;
+ }
+
+ std::vector<CookieChangeSubscription>& old_subscriptions =
+ old_subscriptions_it->second;
+ old_subscriptions.reserve(old_subscriptions.size() +
+ new_subscriptions.size());
+ for (auto& new_subscription : new_subscriptions)
+ old_subscriptions.emplace_back(std::move(new_subscription));
+
+ std::move(callback).Run(true);
+}
+
+void CookieStoreManager::GetSubscriptions(
+ int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ blink::mojom::CookieStore::GetSubscriptionsCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (!done_loading_subscriptions_) {
+ subscriptions_loaded_callbacks_.emplace_back(base::BindOnce(
+ &CookieStoreManager::GetSubscriptions, weak_factory_.GetWeakPtr(),
+ service_worker_registration_id, origin, std::move(callback)));
+ return;
+ }
+
+ if (!succeeded_loading_subscriptions_) {
+ std::move(callback).Run(
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr>(), false);
+ return;
+ }
+
+ auto it = subscriptions_by_registration_.find(service_worker_registration_id);
+ if (it == subscriptions_by_registration_.end() || it->second.empty()) {
+ std::move(callback).Run(
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr>(), true);
+ return;
+ }
+
+ const url::Origin& first_origin = url::Origin::Create(it->second[0].url());
+#if DCHECK_IS_ON()
+ for (const auto& subscription : it->second) {
+ DCHECK(
+ first_origin.IsSameOriginWith(url::Origin::Create(subscription.url())))
+ << "Service worker's change subscriptions don't have the same origin";
+ }
+#endif // DCHECK_IS_ON()
+
+ if (!origin.IsSameOriginWith(first_origin)) {
+ // This error case is a good fit for mojo::ReportBadMessage(), because the
+ // renderer has passed an invalid registration ID. However, the code here
+ // might run without a mojo call context, if the original call was delayed
+ // while loading on-disk subscription data.
+ //
+ // While it would be possible to have two code paths for the two situations,
+ // the extra complexity doesn't seem warranted for the limited debuggig
+ // benefits provided by mojo::ReportBadMessage.
+ std::move(callback).Run(
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr>(), false);
+ return;
+ }
+
+ std::move(callback).Run(CookieChangeSubscription::ToMojoVector(it->second),
+ true);
+}
+
+void CookieStoreManager::OnNewLiveRegistration(
+ int64_t service_worker_registration_id,
+ const GURL& pattern) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void CookieStoreManager::OnRegistrationStored(
+ int64_t service_worker_registration_id,
+ const GURL& pattern) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // Waiting for the on-disk subscriptions to be loaded ensures that the
+ // registration's subscriptions aren't activated twice. Without waiting,
+ // there's a risk that LoadAllSubscriptions() sees the result of the
+ // StoreRegistrationUserData() call below.
+ if (!done_loading_subscriptions_) {
+ subscriptions_loaded_callbacks_.emplace_back(base::BindOnce(
+ &CookieStoreManager::OnRegistrationStored, weak_factory_.GetWeakPtr(),
+ service_worker_registration_id, pattern));
+ return;
+ }
+
+ auto it = subscriptions_by_registration_.find(service_worker_registration_id);
+ if (it == subscriptions_by_registration_.end())
+ return;
+
+ ActivateSubscriptions(&it->second);
+
+ std::string subscriptions_data =
+ CookieChangeSubscription::SerializeVector(it->second);
+ DCHECK(!subscriptions_data.empty())
+ << "Failed to create cookie change subscriptions protobuf";
+
+ service_worker_context_->StoreRegistrationUserData(
+ service_worker_registration_id, pattern.GetOrigin(),
+ std::vector<std::pair<std::string, std::string>>(
+ {{registration_user_data_key_, subscriptions_data}}),
+ base::BindOnce(&HandleStoreRegistrationUserDataStatus));
+}
+
+void CookieStoreManager::OnRegistrationDeleted(
+ int64_t service_worker_registration_id,
+ const GURL& pattern) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // Waiting for the on-disk subscriptions to be loaded ensures that the
+ // registration's subscriptions are removed. Without waiting, there's a risk
+ // that a registration's subscriptions will finish loading (and thus remain
+ // active) right after this function runs.
+ if (!done_loading_subscriptions_) {
+ subscriptions_loaded_callbacks_.emplace_back(base::BindOnce(
+ &CookieStoreManager::OnRegistrationDeleted, weak_factory_.GetWeakPtr(),
+ service_worker_registration_id, pattern));
+ return;
+ }
+
+ auto it = subscriptions_by_registration_.find(service_worker_registration_id);
+ if (it == subscriptions_by_registration_.end())
+ return;
+
+ DeactivateSubscriptions(&it->second);
+ subscriptions_by_registration_.erase(it);
+}
+
+void CookieStoreManager::ActivateSubscriptions(
+ std::vector<CookieChangeSubscription>* subscriptions) {
+ if (subscriptions->empty())
+ return;
+
+ // Service workers can only observe changes to cookies for URLs under their
+ // scope. This means all the URLs that the worker is observing must map to the
+ // same domain key (eTLD+1).
+ //
+ // TODO(pwnall): This is the same as implementation as
+ // net::CookieMonsterChangeDispatcher::DomainKey. Extract that
+ // implementation into net/cookies.cookie_util.h and call it.
+ std::string url_key = net::registry_controlled_domains::GetDomainAndRegistry(
+
+ (*subscriptions)[0].url(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ base::LinkedList<CookieChangeSubscription>& url_key_subscriptions_list =
+ subscriptions_by_url_key_[url_key];
+
+ for (auto& subscription : *subscriptions) {
+ DCHECK(!subscription.next() && !subscription.previous())
+ << "Subscription passed to " << __func__ << " already activated";
+ DCHECK_EQ(url_key,
+ net::registry_controlled_domains::GetDomainAndRegistry(
+ subscription.url(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES))
+ << __func__ << " subscriptions belong to different registrations";
+ url_key_subscriptions_list.Append(&subscription);
+ }
+}
+
+void CookieStoreManager::DeactivateSubscriptions(
+ std::vector<CookieChangeSubscription>* subscriptions) {
+ if (subscriptions->empty())
+ return;
+
+ // Service workers can only observe changes to cookies for URLs under their
+ // scope. This means all the URLs that the worker is observing must map to the
+ // same domain key (eTLD+1).
+ //
+ // TODO(pwnall): This has the same implementation as
+ // net::CookieMonsterChangeDispatcher::DomainKey. Extract that
+ // implementation into net/cookies.cookie_util.h and call it.
+ std::string url_key = net::registry_controlled_domains::GetDomainAndRegistry(
+ (*subscriptions)[0].url(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ for (auto& subscription : *subscriptions) {
+ DCHECK(subscription.next() && subscription.previous())
+ << "Subscription passed to " << __func__ << " not previously activated";
+ DCHECK_EQ(url_key,
+ net::registry_controlled_domains::GetDomainAndRegistry(
+ subscription.url(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES))
+ << __func__ << " subscriptions belong to different registrations";
+ subscription.RemoveFromList();
+ }
+ auto it = subscriptions_by_url_key_.find(url_key);
+ DCHECK(it != subscriptions_by_url_key_.end());
+ if (it->second.empty())
+ subscriptions_by_url_key_.erase(it);
+}
+
+void CookieStoreManager::OnStorageWiped() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // Waiting for the on-disk subscriptions to be loaded ensures that all
+ // subscriptions are removed. Without waiting, there's a risk that some
+ // subscriptions will finish loading (and thus remain active) after this
+ // function runs.
+ if (!done_loading_subscriptions_) {
+ subscriptions_loaded_callbacks_.emplace_back(base::BindOnce(
+ &CookieStoreManager::OnStorageWiped, weak_factory_.GetWeakPtr()));
+ return;
+ }
+
+ subscriptions_by_url_key_.clear();
+ subscriptions_by_registration_.clear();
+}
+
+void CookieStoreManager::OnCookieChange(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause) {
+ // Waiting for on-disk subscriptions to be loaded ensures that changes are
+ // delivered to all service workers that subscribed to them in previous
+ // browser sessions. Without waiting, workers might miss cookie changes.
+ if (!done_loading_subscriptions_) {
+ subscriptions_loaded_callbacks_.emplace_back(
+ base::BindOnce(&CookieStoreManager::OnCookieChange,
+ weak_factory_.GetWeakPtr(), cookie, cause));
+ return;
+ }
+
+ // Compute the list of service workers interested in this change. A worker
+ // might have multiple subscriptions that cover this change, but should still
+ // receive a single change event.
+ // TODO(pwnall): This has same as implementation as
+ // net::CookieMonsterChangeDispatcher::DomainKey. Extract that
+ // implementation into net/cookies.cookie_util.h and call it.
+ std::string url_key = net::registry_controlled_domains::GetDomainAndRegistry(
+ cookie.Domain(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ auto it = subscriptions_by_url_key_.find(url_key);
+ if (it == subscriptions_by_url_key_.end())
+ return;
+ std::set<int64_t> interested_registration_ids;
+ const base::LinkedList<CookieChangeSubscription>& subscriptions = it->second;
+ for (const base::LinkNode<CookieChangeSubscription>* node =
+ subscriptions.head();
+ node != subscriptions.end(); node = node->next()) {
+ const CookieChangeSubscription* subscription = node->value();
+ if (subscription->ShouldObserveChangeTo(cookie)) {
+ interested_registration_ids.insert(
+ subscription->service_worker_registration_id());
+ }
+ }
+
+ // Dispatch the change to interested workers.
+ for (int64_t registration_id : interested_registration_ids) {
+ service_worker_context_->FindReadyRegistrationForIdOnly(
+ registration_id,
+ base::BindOnce(
+ [](base::WeakPtr<CookieStoreManager> manager,
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ ServiceWorkerStatusCode find_status,
+ scoped_refptr<ServiceWorkerRegistration> registration) {
+ if (find_status != SERVICE_WORKER_OK)
+ return;
+
+ DCHECK(registration);
+ if (!manager)
+ return;
+ manager->DispatchChangeEvent(std::move(registration), cookie,
+ cause);
+ },
+ weak_factory_.GetWeakPtr(), cookie, cause));
+ }
+}
+
+void CookieStoreManager::DispatchChangeEvent(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause) {
+ scoped_refptr<ServiceWorkerVersion> active_version =
+ registration->active_version();
+ if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
+ active_version->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::COOKIE_CHANGE,
+ base::BindOnce(&CookieStoreManager::DidStartWorkerForChangeEvent,
+ weak_factory_.GetWeakPtr(), std::move(registration),
+ cookie, cause));
+ return;
+ }
+
+ int request_id = active_version->StartRequest(
+ ServiceWorkerMetrics::EventType::COOKIE_CHANGE, base::DoNothing());
+
+ active_version->event_dispatcher()->DispatchCookieChangeEvent(
+ cookie, cause, active_version->CreateSimpleEventCallback(request_id));
+}
+
+void CookieStoreManager::DidStartWorkerForChangeEvent(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ ServiceWorkerStatusCode start_worker_status) {
+ if (start_worker_status != SERVICE_WORKER_OK)
+ return;
+ DispatchChangeEvent(std::move(registration), cookie, cause);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cookie_store/cookie_store_manager.h b/chromium/content/browser/cookie_store/cookie_store_manager.h
new file mode 100644
index 00000000000..19ccf7333b1
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_store_manager.h
@@ -0,0 +1,228 @@
+// 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_COOKIE_STORE_COOKIE_STORE_MANAGER_H_
+#define CONTENT_BROWSER_COOKIE_STORE_COOKIE_STORE_MANAGER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/containers/linked_list.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "content/browser/cookie_store/cookie_change_subscription.h"
+#include "content/browser/cookie_store/cookie_store_host.h"
+#include "content/browser/service_worker/service_worker_context_core_observer.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
+#include "url/origin.h"
+
+class GURL;
+
+namespace content {
+
+class ServiceWorkerContextWrapper;
+class ServiceWorkerRegistration;
+
+// Manages cookie change subscriptions for a StoragePartition's service workers.
+//
+// Subscriptions are stored along with their associated service worker
+// registrations in ServiceWorkerStorage, as user data. When a service worker is
+// unregistered, its cookie change subscriptions are removed. The storage method
+// (user data) is an implementation detail. Callers should not rely on it, as
+// the storage method may change in the future.
+//
+// Instances of this class must be accessed exclusively on the IO thread,
+// because they call into ServiceWorkerContextWrapper methods that are
+// restricted to the IO thread.
+class CookieStoreManager : public ServiceWorkerContextCoreObserver,
+ public ::network::mojom::CookieChangeListener {
+ public:
+ // Creates a CookieStoreManager with an empty in-memory subscription database.
+ //
+ // The in-memory subscription database must be populated with data from disk,
+ // by calling ReadAllSubscriptions().
+ CookieStoreManager(
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+
+ ~CookieStoreManager() override;
+
+ // Creates a mojo connection to a service worker.
+ //
+ // This is called when service workers use the Cookie Store API to subscribe
+ // to cookie changes or obtain the list of cookie changes.
+ void CreateService(blink::mojom::CookieStoreRequest request,
+ const url::Origin& origin);
+
+ // Starts loading the on-disk subscription data.
+ //
+ // Returns after scheduling the work. The callback is called with a boolean
+ // that indicates if the load operation succeeded.
+ //
+ // It is safe to call all the other CookieStoreManager methods during the
+ // loading operation. The CookieStoreManager has well-defined semantics if
+ // loading fails, so it is not necessary to handle loading errors.
+ void LoadAllSubscriptions(base::OnceCallback<void(bool)> callback);
+
+ // Processes cookie changes from a network service instance.
+ void ListenToCookieChanges(::network::mojom::CookieManagerPtr cookie_manager,
+ base::OnceCallback<void(bool)> callback);
+
+ // content::mojom::CookieStore implementation
+ void AppendSubscriptions(
+ int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ std::vector<blink::mojom::CookieChangeSubscriptionPtr> mojo_subscriptions,
+ blink::mojom::CookieStore::AppendSubscriptionsCallback callback);
+ void GetSubscriptions(
+ int64_t service_worker_registration_id,
+ const url::Origin& origin,
+ blink::mojom::CookieStore::GetSubscriptionsCallback callback);
+
+ // ServiceWorkerContextCoreObserver
+ void OnRegistrationStored(int64_t service_worker_registration_id,
+ const GURL& pattern) override;
+ void OnRegistrationDeleted(int64_t service_worker_registration_id,
+ const GURL& pattern) override;
+ void OnNewLiveRegistration(int64_t service_worker_registration_id,
+ const GURL& pattern) override;
+ void OnStorageWiped() override;
+
+ // ::network::mojom::CookieChangeListener
+ void OnCookieChange(const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause) override;
+
+ private:
+ // Updates internal state with the result of loading disk subscription data.
+ //
+ // Called exactly once.
+ void ProcessOnDiskSubscriptions(
+ base::OnceCallback<void(bool)> load_callback,
+ const std::vector<std::pair<int64_t, std::string>>& user_data,
+ ServiceWorkerStatusCode status);
+
+ // Runs all the callbacks waiting for on-disk subscription data.
+ //
+ // Called exactly once, after on-disk subcriptions have been loaded.
+ void DidLoadAllSubscriptions(bool succeeded,
+ base::OnceCallback<void(bool)> load_callback);
+
+ // Starts sending cookie change events to a service worker.
+ //
+ // All subscriptions must belong to the same service worker registration. This
+ // method is not idempotent.
+ void ActivateSubscriptions(
+ std::vector<CookieChangeSubscription>* subscriptions);
+
+ // Stops sending cookie change events to a service worker.
+ //
+ // All subscriptions must belong to the same service worker registration. This
+ // method is not idempotent.
+ void DeactivateSubscriptions(
+ std::vector<CookieChangeSubscription>* subscriptions);
+
+ // Sends a cookie change to interested service workers.
+ //
+ // Must only be called after the on-disk subscription data is successfully
+ // loaded.
+ void DispatchCookieChange(const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause);
+
+ // Sends a cookie change event to one service worker.
+ void DispatchChangeEvent(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause);
+
+ // Called after a service worker was started so it can get a cookie change.
+ void DidStartWorkerForChangeEvent(
+ scoped_refptr<ServiceWorkerRegistration> registration,
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ ServiceWorkerStatusCode start_worker_status);
+
+ // Used to efficiently implement OnRegistrationDeleted().
+ //
+ // When a service worker registration is removed from the system, the
+ // CookieStoreManager needs to remove all the cookie change subscriptions
+ // associated with the registration. Looking up the registration ID in the
+ // |subscriptions_by_registration_| map is done in O(1) time, and then each
+ // subscription is removed from a LinkedList in |subscription_by_url_key_| in
+ // O(1) time.
+ std::unordered_map<int64_t, std::vector<CookieChangeSubscription>>
+ subscriptions_by_registration_;
+
+ // Used to efficiently implement DispatchCookieChange().
+ //
+ // When a cookie change notification comes from the network service, the
+ // CookieStoreManager needs to dispatch events to the workers with relevant
+ // subscriptions. |subscriptions_by_url_key_| indexes change subscriptions
+ // according to the eTLD+1 of the subscription's scope URL, so each cookie
+ // change only needs to be checked against the subscriptions of the service
+ // workers in the same eTLD+1. The reduction in work is signficant, given that
+ // checking whether a subscription matches a cookie isn't very cheap.
+ //
+ // The current implementation's performance profile could have been achieved
+ // with a map from eTLD+1 to registration IDs, which would not have required
+ // linked lists. However, the current approach is more amenable to future
+ // optimizations, such as partitioning by (eTLD+1, cookie name).
+ std::map<std::string, base::LinkedList<CookieChangeSubscription>>
+ subscriptions_by_url_key_;
+
+ // Used to look up and modify service worker registration data.
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+
+ // Tracks the open mojo pipes created by CreateService().
+ //
+ // Each pipe is associated with the CookieStoreHost instance that it is
+ // connected to. When the pipe is closed, the StrongBindingSet automatically
+ // deletes the CookieStoreHost.
+ mojo::StrongBindingSet<blink::mojom::CookieStore> bindings_;
+
+ // Used to receive cookie changes from the network service.
+ ::network::mojom::CookieManagerPtr cookie_manager_;
+ mojo::Binding<::network::mojom::CookieChangeListener>
+ cookie_change_listener_binding_;
+
+ // The service worker registration user data key for subscription data.
+ //
+ // All the subscriptions associated with a registration are stored in a single
+ // user data entry whose key is |registration_user_data_key_|, and whose value
+ // is a serialized CookieChangeSubscriptionsProto.
+ const std::string registration_user_data_key_;
+
+ // Called after all subscriptions have been loaded.
+ //
+ // Callbacks can assume that |done_loading_subscriptions_| is true
+ // and |succeeded_loading_subscriptions_| is set. If the latter is true,
+ // |subscriptions_by_registration_| and |subscriptions_by_url_key_| will also
+ // be populated.
+ std::vector<base::OnceClosure> subscriptions_loaded_callbacks_;
+
+ // Set to true once all subscriptions have been loaded.
+ bool done_loading_subscriptions_ = false;
+
+ // Only defined when |done_loading_subscriptions_| is true.
+ bool succeeded_loading_subscriptions_ = false;
+
+ // Instances of this class are currently bound to the IO thread, because they
+ // call ServiceWorkerContextWrapper methods that are restricted to the IO
+ // thread. However, the class implementation itself is thread-friendly, so it
+ // only checks that methods are called on the same sequence.
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ // Supports having the manager destroyed while waiting for disk I/O.
+ base::WeakPtrFactory<CookieStoreManager> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CookieStoreManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COOKIE_STORE_COOKIE_STORE_MANAGER_H_
diff --git a/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc b/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
new file mode 100644
index 00000000000..68c926cab07
--- /dev/null
+++ b/chromium/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -0,0 +1,863 @@
+// 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 <memory>
+
+#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/cookie_store/cookie_store_context.h"
+#include "content/browser/cookie_store/cookie_store_manager.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace {
+
+// Synchronous proxies to a wrapped CookieStore service's methods.
+class CookieStoreSync {
+ public:
+ using Subscriptions = std::vector<blink::mojom::CookieChangeSubscriptionPtr>;
+
+ // The caller must ensure that the CookieStore service outlives this.
+ explicit CookieStoreSync(blink::mojom::CookieStore* cookie_store_service)
+ : cookie_store_service_(cookie_store_service) {}
+ ~CookieStoreSync() = default;
+
+ bool AppendSubscriptions(int64_t service_worker_registration_id,
+ Subscriptions subscriptions) {
+ bool success;
+ base::RunLoop run_loop;
+ cookie_store_service_->AppendSubscriptions(
+ service_worker_registration_id, std::move(subscriptions),
+ base::BindOnce(
+ [](base::RunLoop* run_loop, bool* success, bool service_success) {
+ *success = service_success;
+ run_loop->Quit();
+ },
+ &run_loop, &success));
+ run_loop.Run();
+ return success;
+ }
+
+ base::Optional<Subscriptions> GetSubscriptions(
+ int64_t service_worker_registration_id) {
+ base::Optional<Subscriptions> result;
+ base::RunLoop run_loop;
+ cookie_store_service_->GetSubscriptions(
+ service_worker_registration_id,
+ base::BindOnce(
+ [](base::RunLoop* run_loop, base::Optional<Subscriptions>* result,
+ Subscriptions service_result, bool service_success) {
+ if (service_success)
+ *result = std::move(service_result);
+ run_loop->Quit();
+ },
+ &run_loop, &result));
+ run_loop.Run();
+ return result;
+ }
+
+ private:
+ blink::mojom::CookieStore* cookie_store_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(CookieStoreSync);
+};
+
+const char kExampleScope[] = "https://example.com/a";
+const char kExampleWorkerScript[] = "https://example.com/a/script.js";
+const char kGoogleScope[] = "https://google.com/a";
+const char kGoogleWorkerScript[] = "https://google.com/a/script.js";
+
+// Mocks a service worker that uses the cookieStore API.
+class CookieStoreWorkerTestHelper : public EmbeddedWorkerTestHelper {
+ public:
+ using EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper;
+
+ // Sets the cookie change subscriptions requested in the next install event.
+ void SetOnInstallSubscriptions(
+ std::vector<CookieStoreSync::Subscriptions> subscription_batches,
+ blink::mojom::CookieStore* cookie_store_service) {
+ install_subscription_batches_ = std::move(subscription_batches);
+ cookie_store_service_ = cookie_store_service;
+ }
+
+ // Spins inside a run loop until a service worker activate event is received.
+ void WaitForActivateEvent() {
+ base::RunLoop run_loop;
+ quit_on_activate_ = &run_loop;
+ run_loop.Run();
+ }
+
+ // The data in the CookieChangeEvents received by the worker.
+ std::vector<
+ std::pair<net::CanonicalCookie, ::network::mojom::CookieChangeCause>>&
+ changes() {
+ return changes_;
+ }
+
+ protected:
+ // Collects the worker's registration ID for OnInstallEvent().
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ControllerServiceWorkerRequest controller_request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
+ blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+ override {
+ ServiceWorkerVersion* service_worker_version =
+ context()->GetLiveVersion(service_worker_version_id);
+ DCHECK(service_worker_version);
+ service_worker_registration_id_ = service_worker_version->registration_id();
+
+ EmbeddedWorkerTestHelper::OnStartWorker(
+ embedded_worker_id, service_worker_version_id, scope, script_url,
+ pause_after_download, std::move(dispatcher_request),
+ std::move(controller_request), std::move(instance_host),
+ std::move(provider_info), std::move(installed_scripts_info));
+ }
+
+ // Cookie change subscriptions can only be created in this event handler.
+ void OnInstallEvent(
+ mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
+ callback) override {
+ for (auto& subscriptions : install_subscription_batches_) {
+ cookie_store_service_->AppendSubscriptions(
+ service_worker_registration_id_, std::move(subscriptions),
+ base::BindOnce([](bool success) {
+ CHECK(success) << "AppendSubscriptions failed";
+ }));
+ }
+ install_subscription_batches_.clear();
+
+ EmbeddedWorkerTestHelper::OnInstallEvent(std::move(callback));
+ }
+
+ // Used to implement WaitForActivateEvent().
+ void OnActivateEvent(
+ mojom::ServiceWorkerEventDispatcher::DispatchActivateEventCallback
+ callback) override {
+ if (quit_on_activate_) {
+ quit_on_activate_->Quit();
+ quit_on_activate_ = nullptr;
+ }
+
+ EmbeddedWorkerTestHelper::OnActivateEvent(std::move(callback));
+ }
+
+ void OnCookieChangeEvent(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
+ callback) override {
+ changes_.emplace_back(cookie, cause);
+ std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
+ base::Time::Now());
+ }
+
+ private:
+ // Used to add cookie change subscriptions during OnInstallEvent().
+ blink::mojom::CookieStore* cookie_store_service_ = nullptr;
+ std::vector<CookieStoreSync::Subscriptions> install_subscription_batches_;
+ int64_t service_worker_registration_id_;
+
+ // Set by WaitForActivateEvent(), used in OnActivateEvent().
+ base::RunLoop* quit_on_activate_ = nullptr;
+
+ // Collects the changes reported to OnCookieChangeEvent().
+ std::vector<
+ std::pair<net::CanonicalCookie, ::network::mojom::CookieChangeCause>>
+ changes_;
+};
+
+} // namespace
+
+// This class cannot be in an anonymous namespace because it needs to be a
+// friend of StoragePartitionImpl, to access its constructor.
+class CookieStoreManagerTest
+ : public testing::Test,
+ public testing::WithParamInterface<bool /* reset_context */> {
+ public:
+ CookieStoreManagerTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ void SetUp() override {
+ // Use an on-disk service worker storage to test saving and loading.
+ ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir());
+
+ ResetServiceWorkerContext();
+ }
+
+ void TearDown() override {
+ thread_bundle_.RunUntilIdle();
+
+ // Smart pointers are reset manually in destruction order because this is
+ // called by ResetServiceWorkerContext().
+ example_service_.reset();
+ google_service_.reset();
+ example_service_ptr_.reset();
+ google_service_ptr_.reset();
+ cookie_manager_.reset();
+ cookie_store_context_ = nullptr;
+ storage_partition_impl_.reset();
+ worker_test_helper_.reset();
+ }
+
+ void ResetServiceWorkerContext() {
+ if (cookie_store_context_)
+ TearDown();
+
+ worker_test_helper_ = std::make_unique<CookieStoreWorkerTestHelper>(
+ user_data_directory_.GetPath());
+ cookie_store_context_ = base::MakeRefCounted<CookieStoreContext>();
+ cookie_store_context_->Initialize(worker_test_helper_->context_wrapper(),
+ base::BindOnce([](bool success) {
+ CHECK(success) << "Initialize failed";
+ }));
+ storage_partition_impl_ = base::WrapUnique(
+ new StoragePartitionImpl(worker_test_helper_->browser_context(),
+ user_data_directory_.GetPath(), nullptr));
+ storage_partition_impl_->SetURLRequestContext(
+ worker_test_helper_->browser_context()
+ ->CreateRequestContextForStoragePartition(
+ user_data_directory_.GetPath(), false, nullptr,
+ URLRequestInterceptorScopedVector()));
+ ::network::mojom::NetworkContext* network_context =
+ storage_partition_impl_->GetNetworkContext();
+ cookie_store_context_->ListenToCookieChanges(
+ network_context, base::BindOnce([](bool success) {
+ CHECK(success) << "ListenToCookieChanges failed";
+ }));
+ network_context->GetCookieManager(mojo::MakeRequest(&cookie_manager_));
+
+ cookie_store_context_->CreateService(
+ mojo::MakeRequest(&example_service_ptr_),
+ url::Origin::Create(GURL(kExampleScope)));
+ example_service_ =
+ std::make_unique<CookieStoreSync>(example_service_ptr_.get());
+
+ cookie_store_context_->CreateService(
+ mojo::MakeRequest(&google_service_ptr_),
+ url::Origin::Create(GURL(kGoogleScope)));
+ google_service_ =
+ std::make_unique<CookieStoreSync>(google_service_ptr_.get());
+ }
+
+ int64_t RegisterServiceWorker(const char* scope, const char* script_url) {
+ bool success = false;
+ int64_t registration_id;
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = GURL(scope);
+ base::RunLoop run_loop;
+ worker_test_helper_->context()->RegisterServiceWorker(
+ GURL(script_url), options,
+ base::BindOnce(
+ [](base::RunLoop* run_loop, bool* success, int64_t* registration_id,
+ ServiceWorkerStatusCode status,
+ const std::string& status_message,
+ int64_t service_worker_registration_id) {
+ *success = (status == SERVICE_WORKER_OK);
+ *registration_id = service_worker_registration_id;
+ EXPECT_EQ(SERVICE_WORKER_OK, status)
+ << ServiceWorkerStatusToString(status);
+ run_loop->Quit();
+ },
+ &run_loop, &success, &registration_id));
+ run_loop.Run();
+ if (!success)
+ return kInvalidRegistrationId;
+
+ worker_test_helper_->WaitForActivateEvent();
+ return registration_id;
+ }
+
+ // Simplified helper for SetCanonicalCookie.
+ //
+ // Creates a CanonicalCookie that is not secure, not http-only,
+ // and not restricted to first parties. Returns false if creation fails.
+ bool SetSessionCookie(const char* name,
+ const char* value,
+ const char* domain,
+ const char* path) {
+ net::CanonicalCookie cookie(
+ name, value, domain, path, base::Time(), base::Time(), base::Time(),
+ /* secure = */ false,
+ /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT);
+ base::RunLoop run_loop;
+ bool success = false;
+ cookie_manager_->SetCanonicalCookie(
+ cookie, /* secure_source = */ true, /* can_modify_httponly = */ true,
+ base::BindOnce(
+ [](base::RunLoop* run_loop, bool* success, bool service_success) {
+ *success = success;
+ run_loop->Quit();
+ },
+ &run_loop, &success));
+ run_loop.Run();
+ return success;
+ }
+
+ bool reset_context_during_test() const { return GetParam(); }
+
+ static constexpr const int64_t kInvalidRegistrationId = -1;
+
+ protected:
+ TestBrowserThreadBundle thread_bundle_;
+ base::ScopedTempDir user_data_directory_;
+ std::unique_ptr<CookieStoreWorkerTestHelper> worker_test_helper_;
+ std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
+ scoped_refptr<CookieStoreContext> cookie_store_context_;
+ ::network::mojom::CookieManagerPtr cookie_manager_;
+
+ blink::mojom::CookieStorePtr example_service_ptr_, google_service_ptr_;
+ std::unique_ptr<CookieStoreSync> example_service_, google_service_;
+};
+
+const int64_t CookieStoreManagerTest::kInvalidRegistrationId;
+
+namespace {
+
+// Useful for sorting a vector of cookie change subscriptions.
+bool CookieChangeSubscriptionLessThan(
+ const blink::mojom::CookieChangeSubscriptionPtr& lhs,
+ const blink::mojom::CookieChangeSubscriptionPtr& rhs) {
+ return std::tie(lhs->name, lhs->match_type, lhs->url) <
+ std::tie(rhs->name, rhs->match_type, rhs->url);
+}
+
+TEST_P(CookieStoreManagerTest, NoSubscriptions) {
+ worker_test_helper_->SetOnInstallSubscriptions(
+ std::vector<CookieStoreSync::Subscriptions>(),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ EXPECT_EQ(0u, all_subscriptions_opt.value().size());
+}
+
+TEST_P(CookieStoreManagerTest, EmptySubscriptions) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ EXPECT_EQ(0u, all_subscriptions_opt.value().size());
+}
+
+TEST_P(CookieStoreManagerTest, OneSubscription) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name_prefix";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ CookieStoreSync::Subscriptions all_subscriptions =
+ std::move(all_subscriptions_opt).value();
+ EXPECT_EQ(1u, all_subscriptions.size());
+ EXPECT_EQ("cookie_name_prefix", all_subscriptions[0]->name);
+ EXPECT_EQ(::network::mojom::CookieMatchType::STARTS_WITH,
+ all_subscriptions[0]->match_type);
+ EXPECT_EQ(GURL(kExampleScope), all_subscriptions[0]->url);
+}
+
+TEST_P(CookieStoreManagerTest, AppendSubscriptionsAfterEmptyInstall) {
+ worker_test_helper_->SetOnInstallSubscriptions(
+ std::vector<CookieStoreSync::Subscriptions>(),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ CookieStoreSync::Subscriptions subscriptions;
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name_prefix";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ EXPECT_FALSE(example_service_->AppendSubscriptions(registration_id,
+ std::move(subscriptions)));
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ EXPECT_EQ(0u, all_subscriptions_opt.value().size());
+}
+
+TEST_P(CookieStoreManagerTest, AppendSubscriptionsAfterInstall) {
+ {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name_prefix";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ }
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ {
+ CookieStoreSync::Subscriptions subscriptions;
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::EQUALS;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ EXPECT_FALSE(example_service_->AppendSubscriptions(
+ registration_id, std::move(subscriptions)));
+ }
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ CookieStoreSync::Subscriptions all_subscriptions =
+ std::move(all_subscriptions_opt).value();
+ EXPECT_EQ(1u, all_subscriptions.size());
+ EXPECT_EQ("cookie_name_prefix", all_subscriptions[0]->name);
+ EXPECT_EQ(::network::mojom::CookieMatchType::STARTS_WITH,
+ all_subscriptions[0]->match_type);
+ EXPECT_EQ(GURL(kExampleScope), all_subscriptions[0]->url);
+}
+
+TEST_P(CookieStoreManagerTest, AppendSubscriptionsFromWrongOrigin) {
+ worker_test_helper_->SetOnInstallSubscriptions(
+ std::vector<CookieStoreSync::Subscriptions>(),
+ example_service_ptr_.get());
+ int64_t example_registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(example_registration_id, kInvalidRegistrationId);
+
+ CookieStoreSync::Subscriptions subscriptions;
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name_prefix";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ EXPECT_FALSE(google_service_->AppendSubscriptions(example_registration_id,
+ std::move(subscriptions)));
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(example_registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ EXPECT_EQ(0u, all_subscriptions_opt.value().size());
+}
+
+TEST_P(CookieStoreManagerTest, AppendSubscriptionsInvalidRegistrationId) {
+ worker_test_helper_->SetOnInstallSubscriptions(
+ std::vector<CookieStoreSync::Subscriptions>(),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ CookieStoreSync::Subscriptions subscriptions;
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name_prefix";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ EXPECT_FALSE(example_service_->AppendSubscriptions(registration_id + 100,
+ std::move(subscriptions)));
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ EXPECT_EQ(0u, all_subscriptions_opt.value().size());
+}
+
+TEST_P(CookieStoreManagerTest, MultiWorkerSubscriptions) {
+ {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name_prefix";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ }
+ int64_t example_registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(example_registration_id, kInvalidRegistrationId);
+
+ {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::EQUALS;
+ subscriptions.back()->url = GURL(kGoogleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ google_service_ptr_.get());
+ }
+ int64_t google_registration_id =
+ RegisterServiceWorker(kGoogleScope, kGoogleWorkerScript);
+ ASSERT_NE(google_registration_id, kInvalidRegistrationId);
+ EXPECT_NE(example_registration_id, google_registration_id);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> example_subscriptions_opt =
+ example_service_->GetSubscriptions(example_registration_id);
+ ASSERT_TRUE(example_subscriptions_opt.has_value());
+ CookieStoreSync::Subscriptions example_subscriptions =
+ std::move(example_subscriptions_opt).value();
+ EXPECT_EQ(1u, example_subscriptions.size());
+ EXPECT_EQ("cookie_name_prefix", example_subscriptions[0]->name);
+ EXPECT_EQ(::network::mojom::CookieMatchType::STARTS_WITH,
+ example_subscriptions[0]->match_type);
+ EXPECT_EQ(GURL(kExampleScope), example_subscriptions[0]->url);
+
+ base::Optional<CookieStoreSync::Subscriptions> google_subscriptions_opt =
+ google_service_->GetSubscriptions(google_registration_id);
+ ASSERT_TRUE(google_subscriptions_opt.has_value());
+ CookieStoreSync::Subscriptions google_subscriptions =
+ std::move(google_subscriptions_opt).value();
+ EXPECT_EQ(1u, google_subscriptions.size());
+ EXPECT_EQ("cookie_name", google_subscriptions[0]->name);
+ EXPECT_EQ(::network::mojom::CookieMatchType::EQUALS,
+ google_subscriptions[0]->match_type);
+ EXPECT_EQ(GURL(kGoogleScope), google_subscriptions[0]->url);
+}
+
+TEST_P(CookieStoreManagerTest, MultipleSubscriptions) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+
+ {
+ batches.emplace_back();
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "name1";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL("https://example.com/a/1");
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "name2";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::EQUALS;
+ subscriptions.back()->url = GURL("https://example.com/a/2");
+ }
+
+ batches.emplace_back();
+
+ {
+ batches.emplace_back();
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "name3";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL("https://example.com/a/3");
+ }
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ CookieStoreSync::Subscriptions all_subscriptions =
+ std::move(all_subscriptions_opt).value();
+
+ std::sort(all_subscriptions.begin(), all_subscriptions.end(),
+ CookieChangeSubscriptionLessThan);
+
+ EXPECT_EQ(3u, all_subscriptions.size());
+ EXPECT_EQ("name1", all_subscriptions[0]->name);
+ EXPECT_EQ(::network::mojom::CookieMatchType::STARTS_WITH,
+ all_subscriptions[0]->match_type);
+ EXPECT_EQ(GURL("https://example.com/a/1"), all_subscriptions[0]->url);
+ EXPECT_EQ("name2", all_subscriptions[1]->name);
+ EXPECT_EQ(::network::mojom::CookieMatchType::EQUALS,
+ all_subscriptions[1]->match_type);
+ EXPECT_EQ(GURL("https://example.com/a/2"), all_subscriptions[1]->url);
+ EXPECT_EQ("name3", all_subscriptions[2]->name);
+ EXPECT_EQ(::network::mojom::CookieMatchType::STARTS_WITH,
+ all_subscriptions[2]->match_type);
+ EXPECT_EQ(GURL("https://example.com/a/3"), all_subscriptions[2]->url);
+}
+
+TEST_P(CookieStoreManagerTest, OneCookieChange) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ ASSERT_EQ(1u, all_subscriptions_opt.value().size());
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ ASSERT_TRUE(
+ SetSessionCookie("cookie-name", "cookie-value", "example.com", "/"));
+ thread_bundle_.RunUntilIdle();
+
+ ASSERT_EQ(1u, worker_test_helper_->changes().size());
+ EXPECT_EQ("cookie-name", worker_test_helper_->changes()[0].first.Name());
+ EXPECT_EQ("cookie-value", worker_test_helper_->changes()[0].first.Value());
+ EXPECT_EQ("example.com", worker_test_helper_->changes()[0].first.Domain());
+ EXPECT_EQ("/", worker_test_helper_->changes()[0].first.Path());
+ EXPECT_EQ(::network::mojom::CookieChangeCause::INSERTED,
+ worker_test_helper_->changes()[0].second);
+}
+
+TEST_P(CookieStoreManagerTest, CookieChangeNameStartsWith) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie-name-2";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ ASSERT_EQ(1u, all_subscriptions_opt.value().size());
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ ASSERT_TRUE(
+ SetSessionCookie("cookie-name-1", "cookie-value-1", "example.com", "/"));
+ thread_bundle_.RunUntilIdle();
+ EXPECT_EQ(0u, worker_test_helper_->changes().size());
+
+ worker_test_helper_->changes().clear();
+ ASSERT_TRUE(
+ SetSessionCookie("cookie-name-2", "cookie-value-2", "example.com", "/"));
+ thread_bundle_.RunUntilIdle();
+
+ ASSERT_EQ(1u, worker_test_helper_->changes().size());
+ EXPECT_EQ("cookie-name-2", worker_test_helper_->changes()[0].first.Name());
+ EXPECT_EQ("cookie-value-2", worker_test_helper_->changes()[0].first.Value());
+ EXPECT_EQ("example.com", worker_test_helper_->changes()[0].first.Domain());
+ EXPECT_EQ("/", worker_test_helper_->changes()[0].first.Path());
+ EXPECT_EQ(::network::mojom::CookieChangeCause::INSERTED,
+ worker_test_helper_->changes()[0].second);
+
+ worker_test_helper_->changes().clear();
+ ASSERT_TRUE(SetSessionCookie("cookie-name-22", "cookie-value-22",
+ "example.com", "/"));
+ thread_bundle_.RunUntilIdle();
+
+ ASSERT_EQ(1u, worker_test_helper_->changes().size());
+ EXPECT_EQ("cookie-name-22", worker_test_helper_->changes()[0].first.Name());
+ EXPECT_EQ("cookie-value-22", worker_test_helper_->changes()[0].first.Value());
+ EXPECT_EQ("example.com", worker_test_helper_->changes()[0].first.Domain());
+ EXPECT_EQ("/", worker_test_helper_->changes()[0].first.Path());
+ EXPECT_EQ(::network::mojom::CookieChangeCause::INSERTED,
+ worker_test_helper_->changes()[0].second);
+}
+
+TEST_P(CookieStoreManagerTest, CookieChangeUrl) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ ASSERT_EQ(1u, all_subscriptions_opt.value().size());
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ ASSERT_TRUE(
+ SetSessionCookie("cookie-name-1", "cookie-value-1", "google.com", "/"));
+ thread_bundle_.RunUntilIdle();
+ ASSERT_EQ(0u, worker_test_helper_->changes().size());
+
+ worker_test_helper_->changes().clear();
+ ASSERT_TRUE(SetSessionCookie("cookie-name-2", "cookie-value-2", "example.com",
+ "/a/subpath"));
+ thread_bundle_.RunUntilIdle();
+ EXPECT_EQ(0u, worker_test_helper_->changes().size());
+
+ worker_test_helper_->changes().clear();
+ ASSERT_TRUE(
+ SetSessionCookie("cookie-name-3", "cookie-value-3", "example.com", "/"));
+ thread_bundle_.RunUntilIdle();
+
+ ASSERT_EQ(1u, worker_test_helper_->changes().size());
+ EXPECT_EQ("cookie-name-3", worker_test_helper_->changes()[0].first.Name());
+ EXPECT_EQ("cookie-value-3", worker_test_helper_->changes()[0].first.Value());
+ EXPECT_EQ("example.com", worker_test_helper_->changes()[0].first.Domain());
+ EXPECT_EQ("/", worker_test_helper_->changes()[0].first.Path());
+ EXPECT_EQ(::network::mojom::CookieChangeCause::INSERTED,
+ worker_test_helper_->changes()[0].second);
+
+ worker_test_helper_->changes().clear();
+ ASSERT_TRUE(
+ SetSessionCookie("cookie-name-4", "cookie-value-4", "example.com", "/a"));
+ thread_bundle_.RunUntilIdle();
+
+ ASSERT_EQ(1u, worker_test_helper_->changes().size());
+ EXPECT_EQ("cookie-name-4", worker_test_helper_->changes()[0].first.Name());
+ EXPECT_EQ("cookie-value-4", worker_test_helper_->changes()[0].first.Value());
+ EXPECT_EQ("example.com", worker_test_helper_->changes()[0].first.Domain());
+ EXPECT_EQ("/a", worker_test_helper_->changes()[0].first.Path());
+ EXPECT_EQ(::network::mojom::CookieChangeCause::INSERTED,
+ worker_test_helper_->changes()[0].second);
+}
+
+TEST_P(CookieStoreManagerTest, GetSubscriptionsFromWrongOrigin) {
+ std::vector<CookieStoreSync::Subscriptions> batches;
+ batches.emplace_back();
+
+ CookieStoreSync::Subscriptions& subscriptions = batches.back();
+ subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+ subscriptions.back()->name = "cookie_name_prefix";
+ subscriptions.back()->match_type =
+ ::network::mojom::CookieMatchType::STARTS_WITH;
+ subscriptions.back()->url = GURL(kExampleScope);
+
+ worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+ example_service_ptr_.get());
+ int64_t example_registration_id =
+ RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+ ASSERT_NE(example_registration_id, kInvalidRegistrationId);
+
+ if (reset_context_during_test())
+ ResetServiceWorkerContext();
+
+ base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+ example_service_->GetSubscriptions(example_registration_id);
+ ASSERT_TRUE(all_subscriptions_opt.has_value());
+ EXPECT_EQ(1u, all_subscriptions_opt.value().size());
+
+ base::Optional<CookieStoreSync::Subscriptions> wrong_subscriptions_opt =
+ google_service_->GetSubscriptions(example_registration_id);
+ EXPECT_FALSE(wrong_subscriptions_opt.has_value());
+}
+
+INSTANTIATE_TEST_CASE_P(CookieStoreManagerTest,
+ CookieStoreManagerTest,
+ testing::Bool() /* reset_storage_during_test */);
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc b/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
index 2f89c680233..86b2b534245 100644
--- a/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
+++ b/chromium/content/browser/dedicated_worker/dedicated_worker_host.cc
@@ -7,11 +7,14 @@
#include "content/browser/dedicated_worker/dedicated_worker_host.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/interface_provider_filtering.h"
#include "content/browser/renderer_interface_binders.h"
+#include "content/browser/websockets/websocket_manager.h"
#include "content/public/browser/render_process_host.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/message_pipe.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "url/origin.h"
@@ -23,8 +26,14 @@ namespace {
// StrongBinding.
class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
public:
- DedicatedWorkerHost(int process_id, const url::Origin& origin)
- : process_id_(process_id), origin_(origin) {}
+ DedicatedWorkerHost(int process_id,
+ int parent_render_frame_id,
+ const url::Origin& origin)
+ : process_id_(process_id),
+ parent_render_frame_id_(parent_render_frame_id),
+ origin_(origin) {
+ RegisterMojoInterfaces();
+ }
// service_manager::mojom::InterfaceProvider:
void GetInterface(const std::string& interface_name,
@@ -33,14 +42,37 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
if (!process)
return;
+ // See if the registry that is specific to this worker host wants to handle
+ // the interface request.
+ if (registry_.TryBindInterface(interface_name, &interface_pipe))
+ return;
+
BindWorkerInterface(interface_name, std::move(interface_pipe), process,
origin_);
}
private:
+ void RegisterMojoInterfaces() {
+ registry_.AddInterface(
+ base::BindRepeating(&WebSocketManager::CreateWebSocket, process_id_,
+ parent_render_frame_id_, origin_));
+ registry_.AddInterface(base::BindRepeating(
+ &DedicatedWorkerHost::CreateUsbDeviceManager, base::Unretained(this)));
+ }
+
+ void CreateUsbDeviceManager(device::mojom::UsbDeviceManagerRequest request) {
+ auto* host =
+ RenderFrameHostImpl::FromID(process_id_, parent_render_frame_id_);
+ GetContentClient()->browser()->CreateUsbDeviceManager(host,
+ std::move(request));
+ }
+
const int process_id_;
+ const int parent_render_frame_id_;
const url::Origin origin_;
+ service_manager::BinderRegistry registry_;
+
DISALLOW_COPY_AND_ASSIGN(DedicatedWorkerHost);
};
@@ -49,8 +81,10 @@ class DedicatedWorkerHost : public service_manager::mojom::InterfaceProvider {
class DedicatedWorkerFactoryImpl : public blink::mojom::DedicatedWorkerFactory {
public:
DedicatedWorkerFactoryImpl(int process_id,
+ int parent_render_frame_id,
const url::Origin& parent_context_origin)
: process_id_(process_id),
+ parent_render_frame_id_(parent_render_frame_id),
parent_context_origin_(parent_context_origin) {}
// blink::mojom::DedicatedWorkerFactory:
@@ -60,15 +94,16 @@ class DedicatedWorkerFactoryImpl : public blink::mojom::DedicatedWorkerFactory {
// TODO(crbug.com/729021): Once |parent_context_origin_| is no longer races
// with the request for |DedicatedWorkerFactory|, enforce that the worker's
// origin either matches the creating document's origin, or is unique.
- mojo::MakeStrongBinding(
- std::make_unique<DedicatedWorkerHost>(process_id_, origin),
- FilterRendererExposedInterfaces(
- blink::mojom::kNavigation_DedicatedWorkerSpec, process_id_,
- std::move(request)));
+ mojo::MakeStrongBinding(std::make_unique<DedicatedWorkerHost>(
+ process_id_, parent_render_frame_id_, origin),
+ FilterRendererExposedInterfaces(
+ blink::mojom::kNavigation_DedicatedWorkerSpec,
+ process_id_, std::move(request)));
}
private:
const int process_id_;
+ const int parent_render_frame_id_;
const url::Origin parent_context_origin_;
DISALLOW_COPY_AND_ASSIGN(DedicatedWorkerFactoryImpl);
@@ -77,12 +112,13 @@ class DedicatedWorkerFactoryImpl : public blink::mojom::DedicatedWorkerFactory {
} // namespace
void CreateDedicatedWorkerHostFactory(
- blink::mojom::DedicatedWorkerFactoryRequest request,
- RenderProcessHost* host,
- const url::Origin& origin) {
- mojo::MakeStrongBinding(
- std::make_unique<DedicatedWorkerFactoryImpl>(host->GetID(), origin),
- std::move(request));
+ int process_id,
+ int parent_render_frame_id,
+ const url::Origin& origin,
+ blink::mojom::DedicatedWorkerFactoryRequest request) {
+ mojo::MakeStrongBinding(std::make_unique<DedicatedWorkerFactoryImpl>(
+ process_id, parent_render_frame_id, origin),
+ std::move(request));
}
} // namespace content
diff --git a/chromium/content/browser/dedicated_worker/dedicated_worker_host.h b/chromium/content/browser/dedicated_worker/dedicated_worker_host.h
index 60bbdd54536..587ab20cb26 100644
--- a/chromium/content/browser/dedicated_worker/dedicated_worker_host.h
+++ b/chromium/content/browser/dedicated_worker/dedicated_worker_host.h
@@ -12,12 +12,12 @@ class Origin;
}
namespace content {
-class RenderProcessHost;
void CreateDedicatedWorkerHostFactory(
- blink::mojom::DedicatedWorkerFactoryRequest request,
- RenderProcessHost* host,
- const url::Origin& origin);
+ int process_id,
+ int parent_render_frame_id,
+ const url::Origin& origin,
+ blink::mojom::DedicatedWorkerFactoryRequest request);
} // namespace content
diff --git a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
index b2b99a142b5..494c1c7acc1 100644
--- a/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/chromium/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -8,7 +8,6 @@
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index 7c9b58aa5e1..a67148429f1 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
-#include "base/message_loop/message_loop.h"
#include "base/observer_list.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_session.h"
@@ -209,16 +208,6 @@ bool DevToolsAgentHostImpl::AttachRestrictedClient(
return InnerAttachClient(client, true /* restricted */);
}
-void DevToolsAgentHostImpl::ForceAttachClient(DevToolsAgentHostClient* client) {
- if (SessionByClient(client))
- return;
- scoped_refptr<DevToolsAgentHostImpl> protect(this);
- if (!sessions_.empty())
- ForceDetachAllSessions();
- DCHECK(sessions_.empty());
- InnerAttachClient(client, false /* restricted */);
-}
-
bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
if (!SessionByClient(client))
return false;
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index c69bf5a70f2..6831704222e 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -38,7 +38,6 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
// DevToolsAgentHost implementation.
void AttachClient(DevToolsAgentHostClient* client) override;
bool AttachRestrictedClient(DevToolsAgentHostClient* client) override;
- void ForceAttachClient(DevToolsAgentHostClient* client) override;
bool DetachClient(DevToolsAgentHostClient* client) override;
bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
const std::string& message) override;
diff --git a/chromium/content/browser/devtools/devtools_http_handler.cc b/chromium/content/browser/devtools/devtools_http_handler.cc
index cae7c566146..c9187e77495 100644
--- a/chromium/content/browser/devtools/devtools_http_handler.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler.cc
@@ -277,7 +277,7 @@ void StartServerOnHandlerThread(
fflush(stderr);
// Write this port to a well-known file in the profile directory
- // so Telemetry can pick it up.
+ // so Telemetry, ChromeDriver, etc. can pick it up.
if (!output_directory.empty()) {
base::FilePath path =
output_directory.Append(kDevToolsActivePortFileName);
diff --git a/chromium/content/browser/devtools/devtools_io_context.cc b/chromium/content/browser/devtools/devtools_io_context.cc
index 1e0ae3d9eee..02bc1faddb1 100644
--- a/chromium/content/browser/devtools/devtools_io_context.cc
+++ b/chromium/content/browser/devtools/devtools_io_context.cc
@@ -4,257 +4,65 @@
#include "content/browser/devtools/devtools_io_context.h"
-#include "base/base64.h"
-#include "base/containers/queue.h"
-#include "base/files/file.h"
-#include "base/files/file_util.h"
+#include "base/bind.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/task_scheduler/lazy_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/third_party/icu/icu_utf.h"
-#include "base/threading/thread_restrictions.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/storage_partition.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_reader.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/fileapi/file_system_context.h"
-#include "storage/common/blob_storage/blob_storage_constants.h"
-
-#include <queue>
+#include "content/browser/devtools/devtools_stream_blob.h"
+#include "content/browser/devtools/devtools_stream_file.h"
namespace content {
-namespace {
+DevToolsIOContext::Stream::Stream(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : RefCountedDeleteOnSequence<DevToolsIOContext::Stream>(
+ std::move(task_runner)) {}
-base::SequencedTaskRunner* impl_task_runner() {
- constexpr base::TaskTraits kBlockingTraits = {base::MayBlock(),
- base::TaskPriority::BACKGROUND};
- static base::LazySequencedTaskRunner s_sequenced_task_unner =
- LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(kBlockingTraits);
- return s_sequenced_task_unner.Get().get();
+std::string DevToolsIOContext::Stream::Register(DevToolsIOContext* context) {
+ static unsigned s_last_stream_handle = 0;
+ const std::string handle = base::UintToString(++s_last_stream_handle);
+ Register(context, handle);
+ return handle;
}
-using storage::BlobReader;
-
-unsigned s_last_stream_handle = 0;
-
-class TempFileStream : public DevToolsIOContext::RWStream {
- public:
- explicit TempFileStream(bool binary);
-
- void Read(off_t position, size_t max_size, ReadCallback callback) override;
- void Close(bool invoke_pending_callbacks) override {}
- void Append(std::unique_ptr<std::string> data) override;
- const std::string& handle() override { return handle_; }
-
- private:
- ~TempFileStream() override;
-
- void ReadOnFileSequence(off_t pos, size_t max_size, ReadCallback callback);
- void AppendOnFileSequence(std::unique_ptr<std::string> data);
- bool InitOnFileSequenceIfNeeded();
-
- const std::string handle_;
- base::File file_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- bool had_errors_;
- off_t last_read_pos_;
- bool binary_;
-
- DISALLOW_COPY_AND_ASSIGN(TempFileStream);
-};
-
-TempFileStream::TempFileStream(bool binary)
- : DevToolsIOContext::RWStream(impl_task_runner()),
- handle_(base::UintToString(++s_last_stream_handle)),
- task_runner_(impl_task_runner()),
- had_errors_(false),
- last_read_pos_(0),
- binary_(binary) {}
-
-TempFileStream::~TempFileStream() {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
+void DevToolsIOContext::Stream::Register(DevToolsIOContext* context,
+ const std::string& handle) {
+ context->RegisterStream(this, handle);
}
-bool TempFileStream::InitOnFileSequenceIfNeeded() {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- base::AssertBlockingAllowed();
- if (had_errors_)
- return false;
- if (file_.IsValid())
- return true;
- base::FilePath temp_path;
- if (!base::CreateTemporaryFile(&temp_path)) {
- LOG(ERROR) << "Failed to create temporary file";
- had_errors_ = true;
- return false;
- }
- const unsigned flags = base::File::FLAG_OPEN_TRUNCATED |
- base::File::FLAG_WRITE | base::File::FLAG_READ |
- base::File::FLAG_DELETE_ON_CLOSE;
- file_.Initialize(temp_path, flags);
- if (!file_.IsValid()) {
- LOG(ERROR) << "Failed to open temporary file: " << temp_path.value()
- << ", " << base::File::ErrorToString(file_.error_details());
- had_errors_ = true;
- DeleteFile(temp_path, false);
- return false;
- }
+bool DevToolsIOContext::Stream::SupportsSeek() const {
return true;
}
-void TempFileStream::Read(off_t position,
- size_t max_size,
- ReadCallback callback) {
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&TempFileStream::ReadOnFileSequence, this,
- position, max_size, std::move(callback)));
-}
+DevToolsIOContext::Stream::~Stream() = default;
-void TempFileStream::Append(std::unique_ptr<std::string> data) {
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&TempFileStream::AppendOnFileSequence, this,
- std::move(data)));
-}
+DevToolsIOContext::DevToolsIOContext() = default;
-void TempFileStream::ReadOnFileSequence(off_t position,
- size_t max_size,
- ReadCallback callback) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- Status status = StatusFailure;
- std::unique_ptr<std::string> data;
- bool base64_encoded = false;
+DevToolsIOContext::~DevToolsIOContext() = default;
- if (file_.IsValid()) {
- std::string buffer;
- buffer.resize(max_size);
- if (position < 0)
- position = last_read_pos_;
- int size_got = file_.ReadNoBestEffort(position, &*buffer.begin(), max_size);
- if (size_got < 0) {
- LOG(ERROR) << "Failed to read temporary file";
- had_errors_ = true;
- file_.Close();
- } else {
- // Provided client has requested sufficient large block, make their
- // life easier by not truncating in the middle of a UTF-8 character.
- if (size_got > 6 && !CBU8_IS_SINGLE(buffer[size_got - 1])) {
- base::TruncateUTF8ToByteSize(buffer, size_got, &buffer);
- size_got = buffer.size();
- } else {
- buffer.resize(size_got);
- }
- data.reset(new std::string(std::move(buffer)));
- status = size_got ? StatusSuccess : StatusEOF;
- last_read_pos_ = position + size_got;
- }
- }
- if (binary_) {
- std::string raw_data(std::move(*data));
- base::Base64Encode(raw_data, data.get());
- base64_encoded = true;
- }
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), std::move(data),
- base64_encoded, status));
+void DevToolsIOContext::RegisterStream(scoped_refptr<Stream> stream,
+ const std::string& id) {
+ bool inserted = streams_.emplace(id, std::move(stream)).second;
+ DCHECK(inserted);
}
-void TempFileStream::AppendOnFileSequence(std::unique_ptr<std::string> data) {
- if (!InitOnFileSequenceIfNeeded())
- return;
- int size_written = file_.WriteAtCurrentPos(&*data->begin(), data->length());
- if (size_written != static_cast<int>(data->length())) {
- LOG(ERROR) << "Failed to write temporary file";
- had_errors_ = true;
- file_.Close();
- }
+scoped_refptr<DevToolsIOContext::Stream> DevToolsIOContext::GetByHandle(
+ const std::string& handle) {
+ auto it = streams_.find(handle);
+ return it == streams_.end() ? nullptr : it->second;
}
-class BlobStream : public DevToolsIOContext::ROStream {
- public:
- using OpenCallback = base::OnceCallback<void(bool)>;
-
- BlobStream()
- : DevToolsIOContext::ROStream(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
- last_read_pos_(0),
- failed_(false),
- is_binary_(false) {}
-
- void Open(scoped_refptr<ChromeBlobStorageContext> context,
- StoragePartition* partition,
- const std::string& handle,
- OpenCallback callback);
-
- void Read(off_t position, size_t max_size, ReadCallback callback) override;
- void Close(bool invoke_pending_callbacks) override;
-
- private:
- struct ReadRequest {
- off_t position;
- size_t max_size;
- ReadCallback callback;
-
- void Fail();
-
- ReadRequest(off_t position, size_t max_size, ReadCallback callback)
- : position(position),
- max_size(max_size),
- callback(std::move(callback)) {}
- };
-
- ~BlobStream() override = default;
-
- void OpenOnIO(scoped_refptr<ChromeBlobStorageContext> blob_context,
- const std::string& uuid,
- OpenCallback callback);
- void ReadOnIO(std::unique_ptr<ReadRequest> request);
- void CloseOnIO(bool invoke_pending_callbacks);
-
- void FailOnIO();
- void FailOnIO(OpenCallback callback) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), false));
- FailOnIO();
- }
-
- void StartReadRequest();
- void CreateReader();
- void BeginRead();
-
- void OnReadComplete(int bytes_read);
- void OnBlobConstructionComplete(storage::BlobStatus status);
- void OnCalculateSizeComplete(int net_error);
-
- static bool IsTextMimeType(const std::string& mime_type);
-
- std::unique_ptr<storage::BlobDataHandle> blob_handle_;
- OpenCallback open_callback_;
- std::unique_ptr<BlobReader> blob_reader_;
- base::queue<std::unique_ptr<ReadRequest>> pending_reads_;
- scoped_refptr<net::IOBufferWithSize> io_buf_;
- off_t last_read_pos_;
- bool failed_;
- bool is_binary_;
-
- DISALLOW_COPY_AND_ASSIGN(BlobStream);
-};
+bool DevToolsIOContext::Close(const std::string& handle) {
+ size_t erased_count = streams_.erase(handle);
+ return !!erased_count;
+}
-void BlobStream::ReadRequest::Fail() {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), nullptr, false,
- ROStream::StatusFailure));
+void DevToolsIOContext::DiscardAllStreams() {
+ streams_.clear();
}
// static
-bool BlobStream::IsTextMimeType(const std::string& mime_type) {
+bool DevToolsIOContext::IsTextMimeType(const std::string& mime_type) {
static const char* kTextMIMETypePrefixes[] = {
"text/", "application/x-javascript", "application/json",
"application/xml"};
@@ -266,267 +74,4 @@ bool BlobStream::IsTextMimeType(const std::string& mime_type) {
return false;
}
-void BlobStream::Open(scoped_refptr<ChromeBlobStorageContext> context,
- StoragePartition* partition,
- const std::string& handle,
- OpenCallback callback) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BlobStream::OpenOnIO, this, context,
- handle, std::move(callback)));
-}
-
-void BlobStream::Read(off_t position, size_t max_size, ReadCallback callback) {
- std::unique_ptr<ReadRequest> request(
- new ReadRequest(position, max_size, std::move(callback)));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BlobStream::ReadOnIO, this, std::move(request)));
-}
-
-void BlobStream::Close(bool invoke_pending_callbacks) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BlobStream::CloseOnIO, this, invoke_pending_callbacks));
-}
-
-void BlobStream::OpenOnIO(scoped_refptr<ChromeBlobStorageContext> blob_context,
- const std::string& uuid,
- OpenCallback callback) {
- DCHECK(!blob_handle_);
-
- storage::BlobStorageContext* bsc = blob_context->context();
- blob_handle_ = bsc->GetBlobDataFromUUID(uuid);
- if (!blob_handle_) {
- LOG(ERROR) << "No blob with uuid: " << uuid;
- FailOnIO(std::move(callback));
- return;
- }
- is_binary_ = !IsTextMimeType(blob_handle_->content_type());
- open_callback_ = std::move(callback);
- blob_handle_->RunOnConstructionComplete(
- base::BindOnce(&BlobStream::OnBlobConstructionComplete, this));
-}
-
-void BlobStream::OnBlobConstructionComplete(storage::BlobStatus status) {
- DCHECK(!BlobStatusIsPending(status));
- if (BlobStatusIsError(status)) {
- LOG(ERROR) << "Blob building failed: " << static_cast<int>(status);
- FailOnIO(std::move(open_callback_));
- return;
- }
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(open_callback_), true));
- if (!pending_reads_.empty())
- StartReadRequest();
-}
-
-void BlobStream::ReadOnIO(std::unique_ptr<ReadRequest> request) {
- if (failed_) {
- request->Fail();
- return;
- }
- pending_reads_.push(std::move(request));
- if (pending_reads_.size() > 1 || open_callback_)
- return;
- StartReadRequest();
-}
-
-void BlobStream::FailOnIO() {
- failed_ = true;
- while (!pending_reads_.empty()) {
- pending_reads_.front()->Fail();
- pending_reads_.pop();
- }
-}
-
-void BlobStream::CloseOnIO(bool invoke_pending_callbacks) {
- if (blob_reader_) {
- blob_reader_->Kill();
- blob_reader_.reset();
- }
- if (blob_handle_)
- blob_handle_.reset();
- if (invoke_pending_callbacks) {
- FailOnIO();
- return;
- }
- failed_ = true;
- pending_reads_ = base::queue<std::unique_ptr<ReadRequest>>();
- open_callback_ = OpenCallback();
-}
-
-void BlobStream::StartReadRequest() {
- DCHECK_GE(pending_reads_.size(), 1UL);
- DCHECK(blob_handle_);
- DCHECK(!failed_);
-
- ReadRequest& request = *pending_reads_.front();
- if (request.position < 0)
- request.position = last_read_pos_;
- if (request.position != last_read_pos_)
- blob_reader_.reset();
- if (!blob_reader_)
- CreateReader();
- else
- BeginRead();
-}
-
-void BlobStream::BeginRead() {
- DCHECK_GE(pending_reads_.size(), 1UL);
- ReadRequest& request = *pending_reads_.front();
- if (!io_buf_ || static_cast<size_t>(io_buf_->size()) < request.max_size)
- io_buf_ = new net::IOBufferWithSize(request.max_size);
- int bytes_read;
- BlobReader::Status status =
- blob_reader_->Read(io_buf_.get(), request.max_size, &bytes_read,
- base::BindOnce(&BlobStream::OnReadComplete, this));
- if (status == BlobReader::Status::IO_PENDING)
- return;
- // This is for uniformity with the asynchronous case.
- if (status == BlobReader::Status::NET_ERROR) {
- bytes_read = blob_reader_->net_error();
- DCHECK_LT(0, bytes_read);
- }
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BlobStream::OnReadComplete, this, bytes_read));
-}
-
-void BlobStream::OnReadComplete(int bytes_read) {
- std::unique_ptr<ReadRequest> request = std::move(pending_reads_.front());
- pending_reads_.pop();
-
- Status status;
- std::unique_ptr<std::string> data(new std::string());
- bool base64_encoded = false;
-
- if (bytes_read < 0) {
- status = StatusFailure;
- LOG(ERROR) << "Error reading blob: " << net::ErrorToString(bytes_read);
- } else if (!bytes_read) {
- status = StatusEOF;
- } else {
- last_read_pos_ += bytes_read;
- status = blob_reader_->remaining_bytes() ? StatusSuccess : StatusEOF;
- if (is_binary_) {
- base64_encoded = true;
- Base64Encode(base::StringPiece(io_buf_->data(), bytes_read), data.get());
- } else {
- // TODO(caseq): truncate at UTF8 boundary.
- *data = std::string(io_buf_->data(), bytes_read);
- }
- }
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(request->callback), std::move(data),
- base64_encoded, status));
- if (!pending_reads_.empty())
- StartReadRequest();
-}
-
-void BlobStream::CreateReader() {
- DCHECK(!blob_reader_);
- blob_reader_ = blob_handle_->CreateReader();
- BlobReader::Status status = blob_reader_->CalculateSize(
- base::BindOnce(&BlobStream::OnCalculateSizeComplete, this));
- if (status != BlobReader::Status::IO_PENDING) {
- OnCalculateSizeComplete(status == BlobReader::Status::NET_ERROR
- ? blob_reader_->net_error()
- : net::OK);
- }
-}
-
-void BlobStream::OnCalculateSizeComplete(int net_error) {
- if (net_error != net::OK) {
- FailOnIO();
- return;
- }
- off_t seek_to = pending_reads_.front()->position;
- if (seek_to != 0UL) {
- if (seek_to >= static_cast<off_t>(blob_reader_->total_size())) {
- OnReadComplete(0);
- return;
- }
- BlobReader::Status status = blob_reader_->SetReadRange(
- seek_to, blob_reader_->total_size() - seek_to);
- if (status != BlobReader::Status::DONE) {
- FailOnIO();
- return;
- }
- }
- BeginRead();
-}
-
-} // namespace
-
-DevToolsIOContext::ROStream::ROStream(
- scoped_refptr<base::SequencedTaskRunner> task_runner)
- : RefCountedDeleteOnSequence<DevToolsIOContext::ROStream>(
- std::move(task_runner)) {}
-
-DevToolsIOContext::ROStream::~ROStream() = default;
-
-DevToolsIOContext::RWStream::RWStream(
- scoped_refptr<base::SequencedTaskRunner> task_runner)
- : DevToolsIOContext::ROStream(std::move(task_runner)) {}
-
-DevToolsIOContext::RWStream::~RWStream() = default;
-
-DevToolsIOContext::DevToolsIOContext() : weak_factory_(this) {}
-
-DevToolsIOContext::~DevToolsIOContext() {
- DiscardAllStreams();
-}
-
-scoped_refptr<DevToolsIOContext::RWStream>
-DevToolsIOContext::CreateTempFileBackedStream(bool binary) {
- scoped_refptr<TempFileStream> result = new TempFileStream(binary);
- bool inserted =
- streams_.insert(std::make_pair(result->handle(), result)).second;
- DCHECK(inserted);
- return result;
-}
-
-scoped_refptr<DevToolsIOContext::ROStream> DevToolsIOContext::GetByHandle(
- const std::string& handle) {
- StreamsMap::const_iterator it = streams_.find(handle);
- return it == streams_.end() ? scoped_refptr<ROStream>() : it->second;
-}
-
-scoped_refptr<DevToolsIOContext::ROStream> DevToolsIOContext::OpenBlob(
- ChromeBlobStorageContext* context,
- StoragePartition* partition,
- const std::string& handle,
- const std::string& uuid) {
- scoped_refptr<BlobStream> result = new BlobStream();
- bool inserted = streams_.insert(std::make_pair(handle, result)).second;
-
- result->Open(context, partition, uuid,
- base::BindOnce(&DevToolsIOContext::OnBlobOpenComplete,
- weak_factory_.GetWeakPtr(), handle));
- DCHECK(inserted);
- return std::move(result);
-}
-
-void DevToolsIOContext::OnBlobOpenComplete(const std::string& handle,
- bool success) {
- if (!success)
- Close(handle);
-}
-
-bool DevToolsIOContext::Close(const std::string& handle) {
- StreamsMap::iterator it = streams_.find(handle);
- if (it == streams_.end())
- return false;
- it->second->Close(false);
- streams_.erase(it);
- return true;
-}
-
-void DevToolsIOContext::DiscardAllStreams() {
- for (auto& entry : streams_)
- entry.second->Close(true);
- return streams_.clear();
-}
-
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_io_context.h b/chromium/content/browser/devtools/devtools_io_context.h
index 7467760000c..be7a2afe4b8 100644
--- a/chromium/content/browser/devtools/devtools_io_context.h
+++ b/chromium/content/browser/devtools/devtools_io_context.h
@@ -5,12 +5,9 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_IO_CONTEXT_H_
#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_IO_CONTEXT_H_
-#include <stddef.h>
-
#include <map>
#include "base/callback.h"
-#include "base/files/file.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
@@ -20,12 +17,10 @@ class SequencedTaskRunner;
}
namespace content {
-class ChromeBlobStorageContext;
-class StoragePartition;
-class DevToolsIOContext {
+class DevToolsIOContext : public base::SupportsWeakPtr<DevToolsIOContext> {
public:
- class ROStream : public base::RefCountedDeleteOnSequence<ROStream> {
+ class Stream : public base::RefCountedDeleteOnSequence<Stream> {
public:
enum Status {
StatusSuccess,
@@ -38,50 +33,42 @@ class DevToolsIOContext {
bool base64_encoded,
int status)>;
+ virtual bool SupportsSeek() const;
virtual void Read(off_t position,
size_t max_size,
ReadCallback callback) = 0;
- virtual void Close(bool invoke_pending_callbacks) = 0;
protected:
- friend class base::DeleteHelper<content::DevToolsIOContext::ROStream>;
- friend class base::RefCountedDeleteOnSequence<ROStream>;
+ friend class base::DeleteHelper<content::DevToolsIOContext::Stream>;
+ friend class base::RefCountedDeleteOnSequence<Stream>;
- explicit ROStream(scoped_refptr<base::SequencedTaskRunner> task_runner);
- virtual ~ROStream() = 0;
+ explicit Stream(scoped_refptr<base::SequencedTaskRunner> task_runner);
+ virtual ~Stream() = 0;
- DISALLOW_COPY_AND_ASSIGN(ROStream);
- };
+ // Sub-class API:
- class RWStream : public ROStream {
- public:
- virtual void Append(std::unique_ptr<std::string> data) = 0;
- virtual const std::string& handle() = 0;
+ // Caller is reposnsible for generating a unique handle.
+ void Register(DevToolsIOContext* context, const std::string& handle);
+ // We generate handle for the caller and return it.
+ std::string Register(DevToolsIOContext* context);
- protected:
- explicit RWStream(scoped_refptr<base::SequencedTaskRunner> task_runner);
- ~RWStream() override = 0;
- DISALLOW_COPY_AND_ASSIGN(RWStream);
+ DISALLOW_COPY_AND_ASSIGN(Stream);
};
DevToolsIOContext();
~DevToolsIOContext();
- scoped_refptr<RWStream> CreateTempFileBackedStream(bool binary);
- scoped_refptr<ROStream> GetByHandle(const std::string& handle);
- scoped_refptr<ROStream> OpenBlob(ChromeBlobStorageContext*,
- StoragePartition*,
- const std::string& handle,
- const std::string& uuid);
-
+ scoped_refptr<Stream> GetByHandle(const std::string& handle);
bool Close(const std::string& handle);
void DiscardAllStreams();
- void OnBlobOpenComplete(const std::string& handle, bool success);
+
+ static bool IsTextMimeType(const std::string& mime_type);
private:
- using StreamsMap = std::map<std::string, scoped_refptr<ROStream>>;
- StreamsMap streams_;
- base::WeakPtrFactory<DevToolsIOContext> weak_factory_;
+ // Registration can only be done by Stream subclasses through Stream methods.
+ void RegisterStream(scoped_refptr<Stream> stream, const std::string& handle);
+
+ std::map<std::string, scoped_refptr<Stream>> streams_;
};
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_manager.cc b/chromium/content/browser/devtools/devtools_manager.cc
index 241e5039fa9..49bb469207f 100644
--- a/chromium/content/browser/devtools/devtools_manager.cc
+++ b/chromium/content/browser/devtools/devtools_manager.cc
@@ -5,7 +5,6 @@
#include "content/browser/devtools/devtools_manager.h"
#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_http_handler.h"
#include "content/browser/devtools/devtools_pipe_handler.h"
diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc
index a37bd100c05..b945b03f214 100644
--- a/chromium/content/browser/devtools/devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc
@@ -9,7 +9,6 @@
#include "base/guid.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -146,7 +145,7 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
TimeDelta::FromMilliseconds(10));
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMilliseconds(10));
base::RunLoop().Run();
EXPECT_FALSE(delegate.renderer_unresponsive_received());
@@ -158,7 +157,7 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
TimeDelta::FromMilliseconds(10));
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMilliseconds(10));
base::RunLoop().Run();
EXPECT_TRUE(delegate.renderer_unresponsive_received());
diff --git a/chromium/content/browser/devtools/devtools_network_interceptor.cc b/chromium/content/browser/devtools/devtools_network_interceptor.cc
index 8213acf5d97..e4206b1f0bd 100644
--- a/chromium/content/browser/devtools/devtools_network_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_network_interceptor.cc
@@ -10,7 +10,7 @@
namespace content {
InterceptedRequestInfo::InterceptedRequestInfo()
- : response_error_code(net::OK) {}
+ : is_navigation(false), response_error_code(net::OK) {}
InterceptedRequestInfo::~InterceptedRequestInfo() = default;
diff --git a/chromium/content/browser/devtools/devtools_network_interceptor.h b/chromium/content/browser/devtools/devtools_network_interceptor.h
index 97c64bc6257..43dbf902448 100644
--- a/chromium/content/browser/devtools/devtools_network_interceptor.h
+++ b/chromium/content/browser/devtools/devtools_network_interceptor.h
@@ -11,6 +11,7 @@
#include "base/unguessable_token.h"
#include "content/browser/devtools/protocol/network.h"
#include "content/public/common/resource_type.h"
+#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/net_errors.h"
namespace content {
@@ -24,6 +25,7 @@ struct InterceptedRequestInfo {
base::UnguessableToken frame_id;
ResourceType resource_type;
bool is_navigation;
+ protocol::Maybe<bool> is_download;
protocol::Maybe<protocol::Object> redirect_headers;
protocol::Maybe<int> redirect_status_code;
protocol::Maybe<protocol::String> redirect_url;
@@ -43,6 +45,10 @@ class DevToolsNetworkInterceptor {
protocol::Network::Backend::ContinueInterceptedRequestCallback;
using GetResponseBodyForInterceptionCallback =
protocol::Network::Backend::GetResponseBodyForInterceptionCallback;
+ using TakeResponseBodyPipeCallback =
+ base::OnceCallback<void(protocol::Response,
+ mojo::ScopedDataPipeConsumerHandle,
+ const std::string& mime_type)>;
struct Modifications {
Modifications();
diff --git a/chromium/content/browser/devtools/devtools_session.cc b/chromium/content/browser/devtools/devtools_session.cc
index b31ca0ada8b..10a84a5ef0a 100644
--- a/chromium/content/browser/devtools/devtools_session.cc
+++ b/chromium/content/browser/devtools/devtools_session.cc
@@ -207,7 +207,11 @@ void DevToolsSession::DispatchProtocolResponse(
// |this| may be deleted at this point.
}
-void DevToolsSession::DispatchProtocolNotification(const std::string& message) {
+void DevToolsSession::DispatchProtocolNotification(
+ const std::string& message,
+ const base::Optional<std::string>& state) {
+ if (state.has_value())
+ state_cookie_ = state.value();
client_->DispatchProtocolMessage(agent_host_, message);
// |this| may be deleted at this point.
}
diff --git a/chromium/content/browser/devtools/devtools_session.h b/chromium/content/browser/devtools/devtools_session.h
index ea900e26bb3..9ae28ad0097 100644
--- a/chromium/content/browser/devtools/devtools_session.h
+++ b/chromium/content/browser/devtools/devtools_session.h
@@ -80,7 +80,9 @@ class DevToolsSession : public protocol::FrontendChannel,
const std::string& message,
int call_id,
const base::Optional<std::string>& state) override;
- void DispatchProtocolNotification(const std::string& message) override;
+ void DispatchProtocolNotification(
+ const std::string& message,
+ const base::Optional<std::string>& state) override;
mojo::AssociatedBinding<blink::mojom::DevToolsSessionHost> binding_;
blink::mojom::DevToolsSessionAssociatedPtr session_ptr_;
diff --git a/chromium/content/browser/devtools/devtools_stream_blob.cc b/chromium/content/browser/devtools/devtools_stream_blob.cc
new file mode 100644
index 00000000000..2dca3fb2bfb
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_stream_blob.cc
@@ -0,0 +1,251 @@
+// 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/devtools/devtools_stream_blob.h"
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/strings/string_piece.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "net/base/io_buffer.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_reader.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+
+namespace content {
+
+using storage::BlobReader;
+
+DevToolsStreamBlob::ReadRequest::ReadRequest(off_t position,
+ size_t max_size,
+ ReadCallback callback)
+ : position(position), max_size(max_size), callback(std::move(callback)) {}
+
+DevToolsStreamBlob::ReadRequest::~ReadRequest() = default;
+
+DevToolsStreamBlob::DevToolsStreamBlob()
+ : DevToolsIOContext::Stream(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
+ last_read_pos_(0),
+ failed_(false),
+ is_binary_(false) {}
+
+DevToolsStreamBlob::~DevToolsStreamBlob() {
+ if (blob_reader_)
+ blob_reader_->Kill();
+}
+
+namespace {
+void UnregisterIfOpenFailed(base::WeakPtr<DevToolsIOContext> context,
+ const std::string& handle,
+ bool success) {
+ if (!success && context)
+ context->Close(handle);
+}
+} // namespace
+
+// static
+scoped_refptr<DevToolsIOContext::Stream> DevToolsStreamBlob::Create(
+ DevToolsIOContext* io_context,
+ ChromeBlobStorageContext* blob_context,
+ StoragePartition* partition,
+ const std::string& handle,
+ const std::string& uuid) {
+ scoped_refptr<DevToolsStreamBlob> result = new DevToolsStreamBlob();
+ result->Register(io_context, handle);
+ result->Open(
+ blob_context, partition, uuid,
+ base::BindOnce(&UnregisterIfOpenFailed, io_context->AsWeakPtr(), handle));
+ return std::move(result);
+}
+
+void DevToolsStreamBlob::ReadRequest::Fail() {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), nullptr, false,
+ Stream::StatusFailure));
+}
+
+void DevToolsStreamBlob::Open(scoped_refptr<ChromeBlobStorageContext> context,
+ StoragePartition* partition,
+ const std::string& handle,
+ OpenCallback callback) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&DevToolsStreamBlob::OpenOnIO, this,
+ context, handle, std::move(callback)));
+}
+
+void DevToolsStreamBlob::Read(off_t position,
+ size_t max_size,
+ ReadCallback callback) {
+ std::unique_ptr<ReadRequest> request(
+ new ReadRequest(position, max_size, std::move(callback)));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&DevToolsStreamBlob::ReadOnIO, this, std::move(request)));
+}
+
+void DevToolsStreamBlob::OpenOnIO(
+ scoped_refptr<ChromeBlobStorageContext> blob_context,
+ const std::string& uuid,
+ OpenCallback callback) {
+ DCHECK(!blob_handle_);
+
+ storage::BlobStorageContext* bsc = blob_context->context();
+ blob_handle_ = bsc->GetBlobDataFromUUID(uuid);
+ if (!blob_handle_) {
+ LOG(ERROR) << "No blob with uuid: " << uuid;
+ FailOnIO(std::move(callback));
+ return;
+ }
+ is_binary_ = !DevToolsIOContext::IsTextMimeType(blob_handle_->content_type());
+ open_callback_ = std::move(callback);
+ blob_handle_->RunOnConstructionComplete(
+ base::BindOnce(&DevToolsStreamBlob::OnBlobConstructionComplete, this));
+}
+
+void DevToolsStreamBlob::OnBlobConstructionComplete(
+ storage::BlobStatus status) {
+ DCHECK(!BlobStatusIsPending(status));
+ if (BlobStatusIsError(status)) {
+ LOG(ERROR) << "Blob building failed: " << static_cast<int>(status);
+ FailOnIO(std::move(open_callback_));
+ return;
+ }
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(open_callback_), true));
+ if (!pending_reads_.empty())
+ StartReadRequest();
+}
+
+void DevToolsStreamBlob::ReadOnIO(std::unique_ptr<ReadRequest> request) {
+ if (failed_) {
+ request->Fail();
+ return;
+ }
+ pending_reads_.push(std::move(request));
+ if (pending_reads_.size() > 1 || open_callback_)
+ return;
+ StartReadRequest();
+}
+
+void DevToolsStreamBlob::FailOnIO() {
+ failed_ = true;
+ while (!pending_reads_.empty()) {
+ pending_reads_.front()->Fail();
+ pending_reads_.pop();
+ }
+}
+
+void DevToolsStreamBlob::FailOnIO(OpenCallback callback) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), false));
+ FailOnIO();
+}
+
+void DevToolsStreamBlob::StartReadRequest() {
+ DCHECK_GE(pending_reads_.size(), 1UL);
+ DCHECK(blob_handle_);
+ DCHECK(!failed_);
+
+ ReadRequest& request = *pending_reads_.front();
+ if (request.position < 0)
+ request.position = last_read_pos_;
+ if (request.position != last_read_pos_)
+ blob_reader_.reset();
+ if (!blob_reader_)
+ CreateReader();
+ else
+ BeginRead();
+}
+
+void DevToolsStreamBlob::BeginRead() {
+ DCHECK_GE(pending_reads_.size(), 1UL);
+ ReadRequest& request = *pending_reads_.front();
+ if (!io_buf_ || static_cast<size_t>(io_buf_->size()) < request.max_size)
+ io_buf_ = new net::IOBufferWithSize(request.max_size);
+ int bytes_read;
+ BlobReader::Status status = blob_reader_->Read(
+ io_buf_.get(), request.max_size, &bytes_read,
+ base::BindOnce(&DevToolsStreamBlob::OnReadComplete, this));
+ if (status == BlobReader::Status::IO_PENDING)
+ return;
+ // This is for uniformity with the asynchronous case.
+ if (status == BlobReader::Status::NET_ERROR) {
+ bytes_read = blob_reader_->net_error();
+ DCHECK_LT(0, bytes_read);
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&DevToolsStreamBlob::OnReadComplete, this, bytes_read));
+}
+
+void DevToolsStreamBlob::OnReadComplete(int bytes_read) {
+ std::unique_ptr<ReadRequest> request = std::move(pending_reads_.front());
+ pending_reads_.pop();
+
+ Status status;
+ std::unique_ptr<std::string> data(new std::string());
+ bool base64_encoded = false;
+
+ if (bytes_read < 0) {
+ status = StatusFailure;
+ LOG(ERROR) << "Error reading blob: " << net::ErrorToString(bytes_read);
+ } else if (!bytes_read) {
+ status = StatusEOF;
+ } else {
+ last_read_pos_ += bytes_read;
+ status = blob_reader_->remaining_bytes() ? StatusSuccess : StatusEOF;
+ if (is_binary_) {
+ base64_encoded = true;
+ Base64Encode(base::StringPiece(io_buf_->data(), bytes_read), data.get());
+ } else {
+ // TODO(caseq): truncate at UTF8 boundary.
+ *data = std::string(io_buf_->data(), bytes_read);
+ }
+ }
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(request->callback), std::move(data),
+ base64_encoded, status));
+ if (!pending_reads_.empty())
+ StartReadRequest();
+}
+
+void DevToolsStreamBlob::CreateReader() {
+ DCHECK(!blob_reader_);
+ blob_reader_ = blob_handle_->CreateReader();
+ BlobReader::Status status = blob_reader_->CalculateSize(
+ base::BindOnce(&DevToolsStreamBlob::OnCalculateSizeComplete, this));
+ if (status != BlobReader::Status::IO_PENDING) {
+ OnCalculateSizeComplete(status == BlobReader::Status::NET_ERROR
+ ? blob_reader_->net_error()
+ : net::OK);
+ }
+}
+
+void DevToolsStreamBlob::OnCalculateSizeComplete(int net_error) {
+ if (net_error != net::OK) {
+ FailOnIO();
+ return;
+ }
+ off_t seek_to = pending_reads_.front()->position;
+ if (seek_to != 0UL) {
+ if (seek_to >= static_cast<off_t>(blob_reader_->total_size())) {
+ OnReadComplete(0);
+ return;
+ }
+ BlobReader::Status status = blob_reader_->SetReadRange(
+ seek_to, blob_reader_->total_size() - seek_to);
+ if (status != BlobReader::Status::DONE) {
+ FailOnIO();
+ return;
+ }
+ }
+ BeginRead();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_stream_blob.h b/chromium/content/browser/devtools/devtools_stream_blob.h
new file mode 100644
index 00000000000..298f857b868
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_stream_blob.h
@@ -0,0 +1,94 @@
+// 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_DEVTOOLS_DEVTOOLS_STREAM_BLOB_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_STREAM_BLOB_H_
+
+#include "base/callback.h"
+#include "base/containers/queue.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/devtools/devtools_io_context.h"
+#include "net/base/net_errors.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+
+#include <memory>
+
+namespace net {
+class IOBufferWithSize;
+}
+
+namespace storage {
+class BlobDataHandle;
+class BlobReader;
+} // namespace storage
+
+namespace content {
+class ChromeBlobStorageContext;
+class StoragePartition;
+
+class DevToolsStreamBlob : public DevToolsIOContext::Stream {
+ public:
+ using OpenCallback = base::OnceCallback<void(bool)>;
+
+ static scoped_refptr<DevToolsIOContext::Stream> Create(
+ DevToolsIOContext* io_context,
+ ChromeBlobStorageContext* blob_context,
+ StoragePartition* partition,
+ const std::string& handle,
+ const std::string& uuid);
+
+ private:
+ DevToolsStreamBlob();
+
+ void Open(scoped_refptr<ChromeBlobStorageContext> context,
+ StoragePartition* partition,
+ const std::string& handle,
+ OpenCallback callback);
+
+ void Read(off_t position, size_t max_size, ReadCallback callback) override;
+
+ struct ReadRequest {
+ off_t position;
+ size_t max_size;
+ ReadCallback callback;
+
+ void Fail();
+
+ ReadRequest() = delete;
+ ReadRequest(off_t position, size_t max_size, ReadCallback callback);
+ ~ReadRequest();
+ };
+
+ ~DevToolsStreamBlob() override;
+
+ void OpenOnIO(scoped_refptr<ChromeBlobStorageContext> blob_context,
+ const std::string& uuid,
+ OpenCallback callback);
+ void ReadOnIO(std::unique_ptr<ReadRequest> request);
+ void CloseOnIO(bool invoke_pending_callbacks);
+
+ void FailOnIO();
+ void FailOnIO(OpenCallback callback);
+
+ void StartReadRequest();
+ void CreateReader();
+ void BeginRead();
+
+ void OnReadComplete(int bytes_read);
+ void OnBlobConstructionComplete(storage::BlobStatus status);
+ void OnCalculateSizeComplete(int net_error);
+
+ std::unique_ptr<storage::BlobDataHandle> blob_handle_;
+ OpenCallback open_callback_;
+ std::unique_ptr<storage::BlobReader> blob_reader_;
+ base::queue<std::unique_ptr<ReadRequest>> pending_reads_;
+ scoped_refptr<net::IOBufferWithSize> io_buf_;
+ off_t last_read_pos_;
+ bool failed_;
+ bool is_binary_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_STREAM_BLOB_H_
diff --git a/chromium/content/browser/devtools/devtools_stream_file.cc b/chromium/content/browser/devtools/devtools_stream_file.cc
new file mode 100644
index 00000000000..c32261e092a
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_stream_file.cc
@@ -0,0 +1,142 @@
+// 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/devtools/devtools_stream_file.h"
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string_util.h"
+#include "base/task_scheduler/lazy_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/third_party/icu/icu_utf.h"
+#include "base/threading/thread_restrictions.h"
+#include "content/public/browser/browser_thread.h"
+#include "storage/browser/fileapi/file_system_context.h"
+
+namespace content {
+
+scoped_refptr<base::SequencedTaskRunner> impl_task_runner() {
+ constexpr base::TaskTraits kBlockingTraits = {base::MayBlock(),
+ base::TaskPriority::BACKGROUND};
+ static base::LazySequencedTaskRunner s_sequenced_task_unner =
+ LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(kBlockingTraits);
+ return s_sequenced_task_unner.Get();
+}
+
+scoped_refptr<DevToolsStreamFile> DevToolsStreamFile::Create(
+ DevToolsIOContext* context,
+ bool binary) {
+ return new DevToolsStreamFile(context, binary);
+}
+
+DevToolsStreamFile::DevToolsStreamFile(DevToolsIOContext* context, bool binary)
+ : DevToolsIOContext::Stream(impl_task_runner()),
+ handle_(Register(context)),
+ binary_(binary),
+ task_runner_(impl_task_runner()),
+ had_errors_(false),
+ last_read_pos_(0) {}
+
+DevToolsStreamFile::~DevToolsStreamFile() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+}
+
+bool DevToolsStreamFile::InitOnFileSequenceIfNeeded() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ base::AssertBlockingAllowed();
+ if (had_errors_)
+ return false;
+ if (file_.IsValid())
+ return true;
+ base::FilePath temp_path;
+ if (!base::CreateTemporaryFile(&temp_path)) {
+ LOG(ERROR) << "Failed to create temporary file";
+ had_errors_ = true;
+ return false;
+ }
+ const unsigned flags = base::File::FLAG_OPEN_TRUNCATED |
+ base::File::FLAG_WRITE | base::File::FLAG_READ |
+ base::File::FLAG_DELETE_ON_CLOSE;
+ file_.Initialize(temp_path, flags);
+ if (!file_.IsValid()) {
+ LOG(ERROR) << "Failed to open temporary file: " << temp_path.value() << ", "
+ << base::File::ErrorToString(file_.error_details());
+ had_errors_ = true;
+ DeleteFile(temp_path, false);
+ return false;
+ }
+ return true;
+}
+
+void DevToolsStreamFile::Read(off_t position,
+ size_t max_size,
+ ReadCallback callback) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&DevToolsStreamFile::ReadOnFileSequence, this,
+ position, max_size, std::move(callback)));
+}
+
+void DevToolsStreamFile::Append(std::unique_ptr<std::string> data) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&DevToolsStreamFile::AppendOnFileSequence, this,
+ std::move(data)));
+}
+
+void DevToolsStreamFile::ReadOnFileSequence(off_t position,
+ size_t max_size,
+ ReadCallback callback) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ Status status = StatusFailure;
+ std::unique_ptr<std::string> data;
+ bool base64_encoded = false;
+
+ if (file_.IsValid()) {
+ std::string buffer;
+ buffer.resize(max_size);
+ if (position < 0)
+ position = last_read_pos_;
+ int size_got = file_.ReadNoBestEffort(position, &*buffer.begin(), max_size);
+ if (size_got < 0) {
+ LOG(ERROR) << "Failed to read temporary file";
+ had_errors_ = true;
+ file_.Close();
+ } else {
+ // Provided client has requested sufficient large block, make their
+ // life easier by not truncating in the middle of a UTF-8 character.
+ if (size_got > 6 && !CBU8_IS_SINGLE(buffer[size_got - 1])) {
+ base::TruncateUTF8ToByteSize(buffer, size_got, &buffer);
+ size_got = buffer.size();
+ } else {
+ buffer.resize(size_got);
+ }
+ data.reset(new std::string(std::move(buffer)));
+ status = size_got ? StatusSuccess : StatusEOF;
+ last_read_pos_ = position + size_got;
+ }
+ }
+ if (binary_) {
+ std::string raw_data(std::move(*data));
+ base::Base64Encode(raw_data, data.get());
+ base64_encoded = true;
+ }
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), std::move(data),
+ base64_encoded, status));
+}
+
+void DevToolsStreamFile::AppendOnFileSequence(
+ std::unique_ptr<std::string> data) {
+ if (!InitOnFileSequenceIfNeeded())
+ return;
+ int size_written = file_.WriteAtCurrentPos(&*data->begin(), data->length());
+ if (size_written != static_cast<int>(data->length())) {
+ LOG(ERROR) << "Failed to write temporary file";
+ had_errors_ = true;
+ file_.Close();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_stream_file.h b/chromium/content/browser/devtools/devtools_stream_file.h
new file mode 100644
index 00000000000..1c63e39f5d0
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_stream_file.h
@@ -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.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_STREAM_FILE_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_STREAM_FILE_H_
+
+#include "base/files/file.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/devtools/devtools_io_context.h"
+
+#include <string>
+
+namespace content {
+
+class DevToolsStreamFile : public DevToolsIOContext::Stream {
+ public:
+ static scoped_refptr<DevToolsStreamFile> Create(DevToolsIOContext* context,
+ bool binary);
+ const std::string& handle() const { return handle_; }
+ void Append(std::unique_ptr<std::string> data);
+
+ private:
+ DevToolsStreamFile(DevToolsIOContext* context, bool binary);
+ ~DevToolsStreamFile() override;
+
+ void Read(off_t position, size_t max_size, ReadCallback callback) override;
+
+ void ReadOnFileSequence(off_t pos, size_t max_size, ReadCallback callback);
+ void AppendOnFileSequence(std::unique_ptr<std::string> data);
+ bool InitOnFileSequenceIfNeeded();
+
+ const std::string handle_;
+ const bool binary_;
+
+ base::File file_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ bool had_errors_;
+ off_t last_read_pos_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_STREAM_FILE_H_
diff --git a/chromium/content/browser/devtools/devtools_stream_pipe.cc b/chromium/content/browser/devtools/devtools_stream_pipe.cc
new file mode 100644
index 00000000000..62c662bb566
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_stream_pipe.cc
@@ -0,0 +1,133 @@
+// 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/devtools/devtools_stream_pipe.h"
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+
+namespace content {
+
+struct DevToolsStreamPipe::ReadRequest {
+ ReadRequest() = delete;
+ ReadRequest(uint32_t max_size, ReadCallback read_callback)
+ : max_size(max_size), read_callback(std::move(read_callback)) {}
+
+ uint32_t max_size;
+ ReadCallback read_callback;
+};
+
+// static
+scoped_refptr<DevToolsStreamPipe> DevToolsStreamPipe::Create(
+ DevToolsIOContext* context,
+ mojo::ScopedDataPipeConsumerHandle pipe,
+ bool is_binary) {
+ return new DevToolsStreamPipe(context, std::move(pipe), is_binary);
+}
+
+DevToolsStreamPipe::DevToolsStreamPipe(DevToolsIOContext* context,
+ mojo::ScopedDataPipeConsumerHandle pipe,
+ bool is_binary)
+ : DevToolsIOContext::Stream(base::SequencedTaskRunnerHandle::Get()),
+ handle_(Register(context)),
+ pipe_(std::move(pipe)),
+ is_binary_(is_binary),
+ pipe_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+ last_status_(StatusSuccess) {
+ MojoResult res = pipe_watcher_.Watch(
+ pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(&DevToolsStreamPipe::OnPipeSignalled,
+ base::Unretained(this)));
+ DCHECK_EQ(MOJO_RESULT_OK, res);
+}
+
+DevToolsStreamPipe::~DevToolsStreamPipe() = default;
+
+bool DevToolsStreamPipe::SupportsSeek() const {
+ return false;
+}
+
+void DevToolsStreamPipe::Read(off_t position,
+ size_t max_size,
+ ReadCallback callback) {
+ DCHECK(position == -1);
+ if (last_status_ != StatusSuccess) {
+ DCHECK(read_requests_.empty());
+ std::move(callback).Run(std::make_unique<std::string>(), false,
+ last_status_);
+ return;
+ }
+ read_requests_.emplace(max_size, std::move(callback));
+ if (read_requests_.size() == 1lu)
+ pipe_watcher_.ArmOrNotify();
+}
+
+void DevToolsStreamPipe::OnPipeSignalled(
+ MojoResult result,
+ const mojo::HandleSignalsState& state) {
+ DCHECK_EQ(StatusSuccess, last_status_);
+ DCHECK(!read_requests_.empty());
+
+ if (result != MOJO_RESULT_OK) {
+ DispatchEOFOrError(state.peer_closed());
+ return;
+ }
+ while (!read_requests_.empty()) {
+ const void* pipe_bytes = nullptr;
+ uint32_t bytes_available = 0;
+ MojoResult res = pipe_->BeginReadData(&pipe_bytes, &bytes_available,
+ MOJO_READ_DATA_FLAG_NONE);
+ if (res == MOJO_RESULT_FAILED_PRECONDITION) {
+ DCHECK(state.peer_closed());
+ DispatchEOFOrError(state.peer_closed());
+ return;
+ }
+ DCHECK_EQ(MOJO_RESULT_OK, res);
+ auto& request = read_requests_.front();
+ const uint32_t bytes_to_read =
+ std::min(bytes_available,
+ request.max_size - static_cast<uint32_t>(buffer_.size()));
+ // Dispatch available bytes (but no more than requested), when there are
+ // multiple requests pending. If we just have a single read request, it's
+ // more efficient (and easier for client) to only dispatch when enough bytes
+ // are available or eof has been reached.
+ const bool fulfill_entire_request = read_requests_.size() == 1ul;
+ if (fulfill_entire_request)
+ buffer_.reserve(request.max_size);
+ buffer_.append(static_cast<const char*>(pipe_bytes), bytes_to_read);
+ pipe_->EndReadData(bytes_to_read);
+ DCHECK_LE(buffer_.size(), request.max_size);
+ if (buffer_.size() < request.max_size && fulfill_entire_request)
+ break;
+ DispatchResponse();
+ if (bytes_to_read == bytes_available)
+ break;
+ }
+ if (!read_requests_.empty())
+ pipe_watcher_.ArmOrNotify();
+}
+
+void DevToolsStreamPipe::DispatchResponse() {
+ auto data = std::make_unique<std::string>(std::move(buffer_));
+ if (is_binary_ && !data->empty())
+ base::Base64Encode(*data, data.get());
+ std::move(read_requests_.front().read_callback)
+ .Run(std::move(data), is_binary_, last_status_);
+ read_requests_.pop();
+}
+
+void DevToolsStreamPipe::DispatchEOFOrError(bool is_eof) {
+ // For consistency with other implementation, do not report EOF or failure
+ // condition along with actual data, do it for the next request instead.
+ if (!buffer_.empty())
+ DispatchResponse();
+ last_status_ = is_eof ? StatusEOF : StatusFailure;
+
+ while (!read_requests_.empty())
+ DispatchResponse();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_stream_pipe.h b/chromium/content/browser/devtools/devtools_stream_pipe.h
new file mode 100644
index 00000000000..b931eaec116
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_stream_pipe.h
@@ -0,0 +1,55 @@
+// 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_DEVTOOLS_DEVTOOLS_STREAM_PIPE_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_STREAM_PIPE_H_
+
+#include "base/callback.h"
+#include "base/containers/queue.h"
+#include "base/memory/scoped_refptr.h"
+#include "content/browser/devtools/devtools_io_context.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+
+#include <memory>
+
+namespace content {
+
+class DevToolsStreamPipe : public DevToolsIOContext::Stream {
+ public:
+ static scoped_refptr<DevToolsStreamPipe> Create(
+ DevToolsIOContext* context,
+ mojo::ScopedDataPipeConsumerHandle pipe,
+ bool is_binary);
+ const std::string& handle() const { return handle_; }
+
+ private:
+ struct ReadRequest;
+
+ DevToolsStreamPipe(DevToolsIOContext* context,
+ mojo::ScopedDataPipeConsumerHandle pipe,
+ bool is_binary);
+ ~DevToolsStreamPipe() override;
+
+ bool SupportsSeek() const override;
+ void Read(off_t position, size_t max_size, ReadCallback callback) override;
+
+ void OnPipeSignalled(MojoResult result,
+ const mojo::HandleSignalsState& state);
+ void DispatchResponse();
+ void DispatchEOFOrError(bool is_eof);
+
+ const std::string handle_;
+ const mojo::ScopedDataPipeConsumerHandle pipe_;
+ const bool is_binary_;
+
+ mojo::SimpleWatcher pipe_watcher_;
+ base::queue<ReadRequest> read_requests_;
+ std::string buffer_;
+ Status last_status_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_STREAM_PIPE_H_
diff --git a/chromium/content/browser/devtools/devtools_target_registry.cc b/chromium/content/browser/devtools/devtools_target_registry.cc
index a426d9e1924..851f75527c4 100644
--- a/chromium/content/browser/devtools/devtools_target_registry.cc
+++ b/chromium/content/browser/devtools/devtools_target_registry.cc
@@ -149,10 +149,12 @@ class DevToolsTargetRegistry::ContentsObserver : public ObserverBase,
void WebContentsDestroyed() override {
NOTREACHED() << "DevToolsTarget Registry clients should be destroyed "
"before WebContents";
+ registry_->UnregisterWebContents(web_contents());
}
~ContentsObserver() override {
- registry_->UnregisterWebContents(web_contents());
+ if (web_contents())
+ registry_->UnregisterWebContents(web_contents());
}
DevToolsTargetRegistry* registry_;
diff --git a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
index 3c9d31b784b..abfa5795a0c 100644
--- a/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
+++ b/chromium/content/browser/devtools/devtools_url_interceptor_request_job.cc
@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/protocol/page.h"
+#include "content/browser/loader/navigation_loader_util.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "ipc/ipc_channel.h"
#include "net/base/completion_once_callback.h"
@@ -21,6 +22,7 @@
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request_context.h"
+#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
namespace {
static const int kInitialBufferSize = 4096;
@@ -119,6 +121,13 @@ DevToolsURLInterceptorRequestJob::SubRequest::SubRequest(
request_->SetResponseHeadersCallback(
devtools_interceptor_request_job->response_headers_callback_);
+ net::URLRequest* original_request =
+ devtools_interceptor_request_job_->request();
+ request_->set_attach_same_site_cookies(
+ original_request->attach_same_site_cookies());
+ request_->set_site_for_cookies(original_request->site_for_cookies());
+ request_->set_initiator(original_request->initiator());
+
// Mimic the ResourceRequestInfoImpl of the original request.
const ResourceRequestInfoImpl* resource_request_info =
static_cast<const ResourceRequestInfoImpl*>(
@@ -134,7 +143,6 @@ DevToolsURLInterceptorRequestJob::SubRequest::SubRequest(
resource_request_info->IsMainFrame(),
resource_request_info->GetResourceType(),
resource_request_info->GetPageTransition(),
- resource_request_info->should_replace_current_entry(),
resource_request_info->IsDownload(), resource_request_info->is_stream(),
resource_request_info->allow_download(),
resource_request_info->HasUserGesture(),
@@ -146,10 +154,10 @@ DevToolsURLInterceptorRequestJob::SubRequest::SubRequest(
resource_request_info->IsPrerendering(),
resource_request_info->GetContext(),
resource_request_info->ShouldReportRawHeaders(),
+ resource_request_info->ShouldReportSecurityInfo(),
resource_request_info->IsAsync(),
resource_request_info->GetPreviewsState(), resource_request_info->body(),
- resource_request_info->initiated_in_secure_context(),
- resource_request_info->suggested_filename());
+ resource_request_info->initiated_in_secure_context());
extra_data->AssociateWithRequest(request_.get());
if (request_details.post_data)
@@ -531,6 +539,22 @@ void SetDevToolsStatus(net::URLRequest* request,
resource_request_info->set_devtools_status(devtools_status);
}
+bool IsDownload(net::URLRequest* orig_request, net::URLRequest* subrequest) {
+ auto* req_info = ResourceRequestInfoImpl::ForRequest(orig_request);
+ // Only happens to downloads that are initiated by the download manager.
+ if (req_info->IsDownload())
+ return true;
+
+ // Note this will not correctly identify a download for the MIME types
+ // inferred with content sniffing. The new interception implementation
+ // should not have this problem, as it's on top of MIME sniffer.
+ std::string mime_type;
+ subrequest->GetMimeType(&mime_type);
+ return req_info->allow_download() &&
+ navigation_loader_util::IsDownload(
+ orig_request->url(), subrequest->response_headers(), mime_type);
+}
+
} // namespace
DevToolsURLInterceptorRequestJob::DevToolsURLInterceptorRequestJob(
@@ -622,9 +646,7 @@ void DevToolsURLInterceptorRequestJob::Start() {
}
void DevToolsURLInterceptorRequestJob::Kill() {
- if (sub_request_)
- sub_request_->Cancel();
-
+ sub_request_.reset();
URLRequestJob::Kill();
}
@@ -839,6 +861,7 @@ void DevToolsURLInterceptorRequestJob::OnInterceptedRequestResponseStarted(
sub_request_->request()->GetResponseCode();
request_info->response_headers =
protocol::Object::fromValue(headers_dict.get(), nullptr);
+ request_info->is_download = IsDownload(request(), sub_request_->request());
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(callback_, std::move(request_info)));
@@ -1056,6 +1079,16 @@ void DevToolsURLInterceptorRequestJob::ProcessInterceptionResponse(
sub_request_->Cancel();
sub_request_.reset();
}
+ if (modifications->error_reason == net::ERR_BLOCKED_BY_CLIENT) {
+ // So we know that these modifications originated from devtools
+ // (also known as inspector), and can therefore annotate the
+ // request. We only do this for one specific error code thus
+ // far, to minimize risk of breaking other usages.
+ ResourceRequestInfoImpl* resource_request_info =
+ ResourceRequestInfoImpl::ForRequest(request());
+ resource_request_info->set_resource_request_blocked_reason(
+ blink::ResourceRequestBlockedReason::kInspector);
+ }
NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
*modifications->error_reason));
return;
diff --git a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
index ced25eb9169..bc91e2d6d59 100644
--- a/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/chromium/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -10,6 +10,7 @@
#include "base/unguessable_token.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/loader/navigation_loader_util.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
@@ -17,6 +18,7 @@
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
namespace content {
@@ -28,6 +30,8 @@ using ContinueInterceptedRequestCallback =
DevToolsNetworkInterceptor::ContinueInterceptedRequestCallback;
using GetResponseBodyForInterceptionCallback =
DevToolsNetworkInterceptor::GetResponseBodyForInterceptionCallback;
+using TakeResponseBodyPipeCallback =
+ DevToolsNetworkInterceptor::TakeResponseBodyPipeCallback;
using Modifications = DevToolsNetworkInterceptor::Modifications;
using InterceptionStage = DevToolsNetworkInterceptor::InterceptionStage;
using protocol::Response;
@@ -169,12 +173,14 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
const base::UnguessableToken& frame_token,
int32_t process_id,
std::unique_ptr<CreateLoaderParameters> create_loader_params,
+ bool is_download,
network::mojom::URLLoaderRequest loader_request,
network::mojom::URLLoaderClientPtr client,
network::mojom::URLLoaderFactoryPtr target_factory);
void GetResponseBody(
std::unique_ptr<GetResponseBodyForInterceptionCallback> callback);
+ void TakeResponseBodyPipe(TakeResponseBodyPipeCallback callback);
void ContinueInterceptedRequest(
std::unique_ptr<Modifications> modifications,
std::unique_ptr<ContinueInterceptedRequestCallback> callback);
@@ -215,13 +221,16 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
void ResponseBodyComplete();
bool ShouldBypassForResponse() const {
+ if (state_ == State::kResponseTaken)
+ return false;
DCHECK_EQ(!!response_metadata_, !!body_reader_);
DCHECK_EQ(state_, State::kResponseReceived);
return !response_metadata_;
}
// network::mojom::URLLoader methods
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
@@ -244,6 +253,8 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
mojo::ScopedDataPipeConsumerHandle body) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+ bool CanGetResponseBody(std::string* error_reason);
+
const std::string id_;
const GlobalRequestId global_req_id_;
const base::UnguessableToken frame_token_;
@@ -255,6 +266,7 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
InterceptionStage stage_;
std::unique_ptr<CreateLoaderParameters> create_loader_params_;
+ const bool is_download_;
mojo::Binding<network::mojom::URLLoaderClient> client_binding_;
mojo::Binding<network::mojom::URLLoader> loader_binding_;
@@ -269,6 +281,7 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
kRedirectReceived,
kAuthRequired,
kResponseReceived,
+ kResponseTaken,
};
State state_;
@@ -280,6 +293,7 @@ class InterceptionJob : public network::mojom::URLLoaderClient,
base::Optional<std::pair<net::RequestPriority, int32_t>> priority_;
DevToolsURLLoaderInterceptor::HandleAuthRequestCallback
pending_auth_callback_;
+ TakeResponseBodyPipeCallback pending_response_body_pipe_callback_;
DISALLOW_COPY_AND_ASSIGN(InterceptionJob);
};
@@ -298,6 +312,7 @@ class DevToolsURLLoaderInterceptor::Impl
void CreateJob(const base::UnguessableToken& frame_token,
int32_t process_id,
+ bool is_download,
std::unique_ptr<CreateLoaderParameters> create_params,
network::mojom::URLLoaderRequest loader_request,
network::mojom::URLLoaderClientPtr client,
@@ -307,10 +322,10 @@ class DevToolsURLLoaderInterceptor::Impl
static int last_id = 0;
std::string id = base::StringPrintf("interception-job-%d", ++last_id);
- InterceptionJob* job =
- new InterceptionJob(this, id, frame_token, process_id,
- std::move(create_params), std::move(loader_request),
- std::move(client), std::move(target_factory));
+ InterceptionJob* job = new InterceptionJob(
+ this, id, frame_token, process_id, std::move(create_params),
+ is_download, std::move(loader_request), std::move(client),
+ std::move(target_factory));
jobs_.emplace(std::move(id), job);
}
@@ -336,6 +351,19 @@ class DevToolsURLLoaderInterceptor::Impl
job->GetResponseBody(std::move(callback));
}
+ void TakeResponseBodyPipe(
+ const std::string& interception_id,
+ DevToolsNetworkInterceptor::TakeResponseBodyPipeCallback callback) {
+ auto it = jobs_.find(interception_id);
+ if (it == jobs_.end()) {
+ std::move(callback).Run(
+ protocol::Response::InvalidParams("Invalid InterceptionId."),
+ mojo::ScopedDataPipeConsumerHandle(), std::string());
+ return;
+ }
+ it->second->TakeResponseBodyPipe(std::move(callback));
+ }
+
void ContinueInterceptedRequest(
const std::string& interception_id,
std::unique_ptr<Modifications> modifications,
@@ -377,6 +405,7 @@ class DevToolsURLLoaderFactoryProxy : public network::mojom::URLLoaderFactory {
DevToolsURLLoaderFactoryProxy(
const base::UnguessableToken& frame_token,
int32_t process_id,
+ bool is_download,
network::mojom::URLLoaderFactoryRequest loader_request,
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
base::WeakPtr<DevToolsURLLoaderInterceptor::Impl> interceptor);
@@ -401,6 +430,7 @@ class DevToolsURLLoaderFactoryProxy : public network::mojom::URLLoaderFactory {
const base::UnguessableToken frame_token_;
const int32_t process_id_;
+ const bool is_download_;
network::mojom::URLLoaderFactoryPtr target_factory_;
base::WeakPtr<DevToolsURLLoaderInterceptor::Impl> interceptor_;
@@ -412,11 +442,13 @@ class DevToolsURLLoaderFactoryProxy : public network::mojom::URLLoaderFactory {
DevToolsURLLoaderFactoryProxy::DevToolsURLLoaderFactoryProxy(
const base::UnguessableToken& frame_token,
int32_t process_id,
+ bool is_download,
network::mojom::URLLoaderFactoryRequest loader_request,
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
base::WeakPtr<DevToolsURLLoaderInterceptor::Impl> interceptor)
: frame_token_(frame_token),
process_id_(process_id),
+ is_download_(is_download),
interceptor_(std::move(interceptor)) {
DETACH_FROM_SEQUENCE(sequence_checker_);
BrowserThread::PostTask(
@@ -449,9 +481,9 @@ void DevToolsURLLoaderFactoryProxy::CreateLoaderAndStart(
routing_id, request_id, options, request, traffic_annotation);
network::mojom::URLLoaderFactoryPtr factory_clone;
target_factory_->Clone(MakeRequest(&factory_clone));
- interceptor->CreateJob(frame_token_, process_id_, std::move(creation_params),
- std::move(loader), std::move(client),
- std::move(factory_clone));
+ interceptor->CreateJob(frame_token_, process_id_, is_download_,
+ std::move(creation_params), std::move(loader),
+ std::move(client), std::move(factory_clone));
}
void DevToolsURLLoaderFactoryProxy::StartOnIO(
@@ -475,7 +507,6 @@ void DevToolsURLLoaderFactoryProxy::Clone(
}
void DevToolsURLLoaderFactoryProxy::OnTargetFactoryError() {
- DCHECK(!target_factory_.is_bound());
delete this;
}
@@ -548,6 +579,15 @@ void DevToolsURLLoaderInterceptor::GetResponseBody(
interception_id, std::move(callback)));
}
+void DevToolsURLLoaderInterceptor::TakeResponseBodyPipe(
+ const std::string& interception_id,
+ DevToolsNetworkInterceptor::TakeResponseBodyPipeCallback callback) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&Impl::TakeResponseBodyPipe, base::Unretained(impl_.get()),
+ interception_id, std::move(callback)));
+}
+
void DevToolsURLLoaderInterceptor::ContinueInterceptedRequest(
const std::string& interception_id,
std::unique_ptr<Modifications> modifications,
@@ -562,6 +602,7 @@ void DevToolsURLLoaderInterceptor::ContinueInterceptedRequest(
bool DevToolsURLLoaderInterceptor::CreateProxyForInterception(
const base::UnguessableToken frame_token,
int process_id,
+ bool is_download,
network::mojom::URLLoaderFactoryRequest* request) const {
if (!enabled_)
return false;
@@ -570,7 +611,7 @@ bool DevToolsURLLoaderInterceptor::CreateProxyForInterception(
network::mojom::URLLoaderFactoryPtrInfo target_ptr_info;
*request = MakeRequest(&target_ptr_info);
- new DevToolsURLLoaderFactoryProxy(frame_token, process_id,
+ new DevToolsURLLoaderFactoryProxy(frame_token, process_id, is_download,
std::move(original_request),
std::move(target_ptr_info), weak_impl_);
return true;
@@ -582,6 +623,7 @@ InterceptionJob::InterceptionJob(
const base::UnguessableToken& frame_token,
int process_id,
std::unique_ptr<CreateLoaderParameters> create_loader_params,
+ bool is_download,
network::mojom::URLLoaderRequest loader_request,
network::mojom::URLLoaderClientPtr client,
network::mojom::URLLoaderFactoryPtr target_factory)
@@ -596,6 +638,7 @@ InterceptionJob::InterceptionJob(
report_upload_(!!create_loader_params->request.request_body),
interceptor_(interceptor),
create_loader_params_(std::move(create_loader_params)),
+ is_download_(is_download),
client_binding_(this),
loader_binding_(this),
client_(std::move(client)),
@@ -622,21 +665,26 @@ InterceptionJob::InterceptionJob(
StartRequest();
}
-void InterceptionJob::GetResponseBody(
- std::unique_ptr<GetResponseBodyForInterceptionCallback> callback) {
- std::string error_reason;
-
+bool InterceptionJob::CanGetResponseBody(std::string* error_reason) {
if (!(stage_ & InterceptionStage::RESPONSE)) {
- error_reason =
+ *error_reason =
"Can only get response body on HeadersReceived pattern matched "
"requests.";
- } else if (state_ != kResponseReceived) {
- DCHECK(waiting_for_resolution_);
- error_reason =
+ return false;
+ }
+ if (state_ != State::kResponseReceived || !waiting_for_resolution_) {
+ *error_reason =
"Can only get response body on requests captured after headers "
"received.";
+ return false;
}
- if (!error_reason.empty()) {
+ return true;
+}
+
+void InterceptionJob::GetResponseBody(
+ std::unique_ptr<GetResponseBodyForInterceptionCallback> callback) {
+ std::string error_reason;
+ if (!CanGetResponseBody(&error_reason)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&GetResponseBodyForInterceptionCallback::sendFailure,
@@ -644,7 +692,6 @@ void InterceptionJob::GetResponseBody(
Response::Error(std::move(error_reason))));
return;
}
-
if (!body_reader_) {
body_reader_ = std::make_unique<BodyReader>(base::BindOnce(
&InterceptionJob::ResponseBodyComplete, base::Unretained(this)));
@@ -654,11 +701,30 @@ void InterceptionJob::GetResponseBody(
body_reader_->AddCallback(std::move(callback));
}
+void InterceptionJob::TakeResponseBodyPipe(
+ TakeResponseBodyPipeCallback callback) {
+ std::string error_reason;
+ if (!CanGetResponseBody(&error_reason)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback),
+ Response::Error(std::move(error_reason)),
+ mojo::ScopedDataPipeConsumerHandle(), std::string()));
+ return;
+ }
+ DCHECK_EQ(state_, State::kResponseReceived);
+ DCHECK(!!response_metadata_);
+ state_ = State::kResponseTaken;
+ pending_response_body_pipe_callback_ = std::move(callback);
+ client_binding_.ResumeIncomingMethodCallProcessing();
+ loader_->ResumeReadingBodyFromNet();
+}
+
void InterceptionJob::ContinueInterceptedRequest(
std::unique_ptr<Modifications> modifications,
std::unique_ptr<ContinueInterceptedRequestCallback> callback) {
Response response = InnerContinueRequest(std::move(modifications));
- // |this| may be destroyed at this pont.
+ // |this| may be destroyed at this point.
bool success = response.isSuccess();
base::OnceClosure task =
success ? base::BindOnce(&ContinueInterceptedRequestCallback::sendSuccess,
@@ -693,9 +759,9 @@ Response InterceptionJob::InnerContinueRequest(
return Response::InvalidParams("authChallengeResponse required.");
return ProcessAuthResponse(
modifications->auth_challenge_response.fromJust());
- } else if (modifications->auth_challenge_response.isJust()) {
- return Response::InvalidParams("authChallengeResponse not expected.");
}
+ if (modifications->auth_challenge_response.isJust())
+ return Response::InvalidParams("authChallengeResponse not expected.");
if (modifications->mark_as_canceled || modifications->error_reason) {
int error = modifications->error_reason
@@ -704,6 +770,14 @@ Response InterceptionJob::InnerContinueRequest(
: net::ERR_FAILED);
network::URLLoaderCompletionStatus status(error);
status.completion_time = base::TimeTicks::Now();
+ if (modifications->error_reason == net::ERR_BLOCKED_BY_CLIENT) {
+ // So we know that these modifications originated from devtools
+ // (also known as inspector), and can therefore annotate the
+ // request. We only do this for one specific error code thus
+ // far, to minimize risk of breaking other usages.
+ status.extended_error_code =
+ static_cast<int>(blink::ResourceRequestBlockedReason::kInspector);
+ }
client_->OnComplete(status);
Shutdown();
return Response::OK();
@@ -737,6 +811,10 @@ Response InterceptionJob::InnerContinueRequest(
}
if (response_metadata_) {
+ if (state_ == State::kResponseTaken) {
+ return Response::InvalidParams(
+ "Unable to continue request as is after body is taken");
+ }
// TODO(caseq): report error if other modifications are present.
DCHECK_EQ(State::kResponseReceived, state_);
DCHECK(!body_reader_);
@@ -1007,7 +1085,11 @@ void InterceptionJob::Shutdown() {
}
// URLLoader methods
-void InterceptionJob::FollowRedirect() {
+void InterceptionJob::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
+ "headers was not supported "
+ "yet. crbug.com/845683";
DCHECK(!waiting_for_resolution_);
network::ResourceRequest* request = &create_loader_params_->request;
@@ -1024,7 +1106,7 @@ void InterceptionJob::FollowRedirect() {
}
if (state_ == State::kRedirectReceived) {
state_ = State::kRequestSent;
- loader_->FollowRedirect();
+ loader_->FollowRedirect(base::nullopt);
return;
}
@@ -1040,17 +1122,17 @@ void InterceptionJob::SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) {
priority_ = std::make_pair(priority, intra_priority_value);
- if (state_ != State::kNotStarted)
+ if (loader_)
loader_->SetPriority(priority, intra_priority_value);
}
void InterceptionJob::PauseReadingBodyFromNet() {
- if (state_ != State::kNotStarted && !body_reader_)
+ if (!body_reader_ && loader_ && state_ != State::kResponseTaken)
loader_->PauseReadingBodyFromNet();
}
void InterceptionJob::ResumeReadingBodyFromNet() {
- if (state_ != State::kNotStarted && !body_reader_)
+ if (!body_reader_ && loader_ && state_ != State::kResponseTaken)
loader_->ResumeReadingBodyFromNet();
}
@@ -1070,7 +1152,13 @@ void InterceptionJob::OnReceiveResponse(
response_metadata_ = std::make_unique<ResponseMetadata>(head);
response_metadata_->downloaded_file = std::move(downloaded_file);
- NotifyClient(BuildRequestInfo(&head));
+ auto request_info = BuildRequestInfo(&head);
+ const network::ResourceRequest& request = create_loader_params_->request;
+ request_info->is_download =
+ request_info->is_navigation && request.allow_download &&
+ (is_download_ || navigation_loader_util::IsDownload(
+ request.url, head.headers.get(), head.mime_type));
+ NotifyClient(std::move(request_info));
}
void InterceptionJob::OnReceiveRedirect(
@@ -1125,6 +1213,17 @@ void InterceptionJob::OnTransferSizeUpdated(int32_t transfer_size_diff) {
void InterceptionJob::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
+ if (pending_response_body_pipe_callback_) {
+ DCHECK_EQ(State::kResponseTaken, state_);
+ DCHECK(!body_reader_);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(pending_response_body_pipe_callback_),
+ Response::OK(), std::move(body),
+ response_metadata_->head.mime_type));
+ return;
+ }
+ DCHECK_EQ(State::kResponseReceived, state_);
if (ShouldBypassForResponse())
client_->OnStartLoadingResponseBody(std::move(body));
else
@@ -1133,12 +1232,18 @@ void InterceptionJob::OnStartLoadingResponseBody(
void InterceptionJob::OnComplete(
const network::URLLoaderCompletionStatus& status) {
- if (ShouldBypassForResponse()) {
+ // Essentially ShouldBypassForResponse(), but skip DCHECKs
+ // since this may be called in any state during shutdown.
+ if (!response_metadata_) {
client_->OnComplete(status);
Shutdown();
return;
}
response_metadata_->status = status;
+ // No need to listen to the channel any more, so just close it, so if the pipe
+ // is closed by the other end, |shutdown| isn't run.
+ client_binding_.Close();
+ loader_.reset();
}
void InterceptionJob::OnAuthRequest(
diff --git a/chromium/content/browser/devtools/devtools_url_loader_interceptor.h b/chromium/content/browser/devtools/devtools_url_loader_interceptor.h
index a05c8bc1f56..3957091b35f 100644
--- a/chromium/content/browser/devtools/devtools_url_loader_interceptor.h
+++ b/chromium/content/browser/devtools/devtools_url_loader_interceptor.h
@@ -40,6 +40,9 @@ class DevToolsURLLoaderInterceptor {
std::unique_ptr<
DevToolsNetworkInterceptor::GetResponseBodyForInterceptionCallback>
callback);
+ void TakeResponseBodyPipe(
+ const std::string& interception_id,
+ DevToolsNetworkInterceptor::TakeResponseBodyPipeCallback callback);
void ContinueInterceptedRequest(
const std::string& interception_id,
std::unique_ptr<DevToolsNetworkInterceptor::Modifications> modifications,
@@ -50,6 +53,7 @@ class DevToolsURLLoaderInterceptor {
bool CreateProxyForInterception(
const base::UnguessableToken frame_token,
int process_id, // 0 for navigation
+ bool is_download,
network::mojom::URLLoaderFactoryRequest* request) const;
private:
diff --git a/chromium/content/browser/devtools/devtools_video_consumer.cc b/chromium/content/browser/devtools/devtools_video_consumer.cc
index 8c9bdd44ade..fb91996670c 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer.cc
@@ -149,9 +149,8 @@ void DevToolsVideoConsumer::OnFrameCaptured(
// Setting |frame|'s visible rect equal to |content_rect| so that only the
// portion of the frame that contain content are used.
frame = media::VideoFrame::WrapExternalData(
- info->pixel_format, info->coded_size, info->visible_rect,
- info->visible_rect.size(), static_cast<uint8_t*>(mapping.get()),
- buffer_size, info->timestamp);
+ info->pixel_format, info->coded_size, content_rect, content_rect.size(),
+ static_cast<uint8_t*>(mapping.get()), buffer_size, info->timestamp);
if (!frame)
return;
frame->AddDestructionObserver(base::BindOnce(
diff --git a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
index adb95d4bbab..20f9b2fdb62 100644
--- a/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_video_consumer_unittest.cc
@@ -18,7 +18,6 @@ namespace {
// Capture parameters.
constexpr gfx::Size kResolution = gfx::Size(320, 180); // Arbitrarily chosen.
constexpr media::VideoPixelFormat kFormat = media::PIXEL_FORMAT_I420;
-constexpr media::VideoPixelStorage kStorage = media::VideoPixelStorage::CPU;
// A non-zero FrameSinkId to prevent validation errors when
// DevToolsVideoConsumer::ChangeTarget(viz::FrameSinkId) is called
@@ -170,7 +169,7 @@ class DevToolsVideoConsumerTest : public testing::Test {
media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New(
base::TimeDelta(), base::Value(base::Value::Type::DICTIONARY), kFormat,
- kStorage, kResolution, gfx::Rect(kResolution));
+ kResolution, gfx::Rect(kResolution));
consumer_->OnFrameCaptured(std::move(buffer), buffer_size, std::move(info),
gfx::Rect(kResolution), gfx::Rect(kResolution),
diff --git a/chromium/content/browser/devtools/forwarding_agent_host.cc b/chromium/content/browser/devtools/forwarding_agent_host.cc
index 2b60cf23d86..1682f1cc880 100644
--- a/chromium/content/browser/devtools/forwarding_agent_host.cc
+++ b/chromium/content/browser/devtools/forwarding_agent_host.cc
@@ -55,12 +55,6 @@ void ForwardingAgentHost::AttachClient(DevToolsAgentHostClient* client) {
session_proxies_[client].reset(new SessionProxy(this, client));
}
-void ForwardingAgentHost::ForceAttachClient(DevToolsAgentHostClient* client) {
- while (!session_proxies_.empty())
- session_proxies_.begin()->second->ConnectionClosed();
- AttachClient(client);
-}
-
bool ForwardingAgentHost::DetachClient(DevToolsAgentHostClient* client) {
auto it = session_proxies_.find(client);
if (it == session_proxies_.end())
diff --git a/chromium/content/browser/devtools/forwarding_agent_host.h b/chromium/content/browser/devtools/forwarding_agent_host.h
index b09b2cf1b5d..3368c916f36 100644
--- a/chromium/content/browser/devtools/forwarding_agent_host.h
+++ b/chromium/content/browser/devtools/forwarding_agent_host.h
@@ -28,7 +28,6 @@ class ForwardingAgentHost : public DevToolsAgentHostImpl {
// DevToolsAgentHost implementation
void AttachClient(DevToolsAgentHostClient* client) override;
- void ForceAttachClient(DevToolsAgentHostClient* client) override;
bool DetachClient(DevToolsAgentHostClient* client) override;
bool DispatchProtocolMessage(DevToolsAgentHostClient* client,
const std::string& message) override;
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 5a364cef4ed..e63b7fc855d 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -14,7 +14,6 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -839,7 +838,7 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshot) {
if (base::SysInfo::IsLowEndDevice()) return;
shell()->LoadURL(
- GURL("data:text/html,<body style='background:#123456'></body>"));
+ GURL("data:text/html,<body style='background:%23123456'></body>"));
WaitForLoadStop(shell()->web_contents());
Attach();
SkBitmap expected_bitmap;
@@ -862,7 +861,7 @@ IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) {
return;
shell()->LoadURL(
- GURL("data:text/html,<body style='background:#123456'></body>"));
+ GURL("data:text/html,<body style='background:%23123456'></body>"));
WaitForLoadStop(shell()->web_contents());
Attach();
SkBitmap expected_bitmap;
@@ -1561,206 +1560,6 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserGetTargets) {
EXPECT_EQ("about:blank", url);
}
-namespace {
-class NavigationFinishedObserver : public content::WebContentsObserver {
- public:
- explicit NavigationFinishedObserver(WebContents* web_contents)
- : WebContentsObserver(web_contents),
- num_finished_(0),
- num_to_wait_for_(0) {}
-
- ~NavigationFinishedObserver() override {}
-
- void DidFinishNavigation(
- content::NavigationHandle* navigation_handle) override {
- if (navigation_handle->WasServerRedirect())
- return;
-
- num_finished_++;
- if (num_finished_ >= num_to_wait_for_ && num_to_wait_for_ != 0) {
- base::RunLoop::QuitCurrentDeprecated();
- }
- }
-
- void WaitForNavigationsToFinish(int num_to_wait_for) {
- if (num_finished_ < num_to_wait_for) {
- num_to_wait_for_ = num_to_wait_for;
- RunMessageLoop();
- }
- num_to_wait_for_ = 0;
- }
-
- private:
- int num_finished_;
- int num_to_wait_for_;
-};
-
-class LoadFinishedObserver : public content::WebContentsObserver {
- public:
- explicit LoadFinishedObserver(WebContents* web_contents)
- : WebContentsObserver(web_contents), num_finished_(0) {}
-
- ~LoadFinishedObserver() override {}
-
- void DidStopLoading() override {
- num_finished_++;
- if (run_loop_.running())
- run_loop_.Quit();
- }
-
- void WaitForLoadToFinish() {
- if (num_finished_ == 0)
- run_loop_.Run();
- }
-
- private:
- int num_finished_;
- base::RunLoop run_loop_;
-};
-
-} // namespace
-
-IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, PageStopLoading) {
- ASSERT_TRUE(embedded_test_server()->Start());
-
- // Navigate to about:blank first so we can make sure there is a target page we
- // can attach to, and have Network.setRequestInterception complete
- // before we start the navigations we're interested in.
- NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
- Attach();
-
- std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
- std::unique_ptr<base::ListValue> patterns(new base::ListValue());
- patterns->Append(std::make_unique<base::DictionaryValue>());
- params->Set("patterns", std::move(patterns));
- SendCommand("Network.setRequestInterception", std::move(params), true);
-
- LoadFinishedObserver load_finished_observer(shell()->web_contents());
-
- // The page will try to navigate twice, however since
- // Network.setRequestInterception is true,
- // it'll wait for confirmation before committing to the navigation.
- GURL test_url = embedded_test_server()->GetURL(
- "/devtools/control_navigations/meta_tag.html");
- shell()->LoadURL(test_url);
-
- // Stop all navigations.
- SendCommand("Page.stopLoading", nullptr);
-
- // Wait for the initial navigation to finish.
- load_finished_observer.WaitForLoadToFinish();
-}
-
-IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ControlNavigationsMainFrame) {
- ASSERT_TRUE(embedded_test_server()->Start());
-
- // Navigate to about:blank first so we can make sure there is a target page we
- // can attach to, and have Network.setRequestInterception complete
- // before we start the navigations we're interested in.
- NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
- Attach();
-
- std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
- std::unique_ptr<base::ListValue> patterns(new base::ListValue());
- patterns->Append(std::make_unique<base::DictionaryValue>());
- params->Set("patterns", std::move(patterns));
- SendCommand("Network.setRequestInterception", std::move(params), true);
-
- NavigationFinishedObserver navigation_finished_observer(
- shell()->web_contents());
-
- GURL test_url = embedded_test_server()->GetURL(
- "/devtools/control_navigations/meta_tag.html");
- shell()->LoadURL(test_url);
-
- std::vector<ExpectedNavigation> expected_navigations = {
- {"http://127.0.0.1/devtools/control_navigations/meta_tag.html",
- false /* expected_is_redirect */, false /* abort */},
- {"http://127.0.0.1/devtools/navigation.html",
- false /* expected_is_redirect */, true /* abort */}};
-
- ProcessNavigationsAnyOrder(std::move(expected_navigations));
-
- // Wait for the initial navigation and the cancelled meta refresh navigation
- // to finish.
- navigation_finished_observer.WaitForNavigationsToFinish(2);
-
- // Check main frame has the expected url.
- EXPECT_EQ(
- "http://127.0.0.1/devtools/control_navigations/meta_tag.html",
- RemovePort(
- shell()->web_contents()->GetMainFrame()->GetLastCommittedURL()));
-}
-
-class IsolatedDevToolsProtocolTest : public DevToolsProtocolTest {
- public:
- ~IsolatedDevToolsProtocolTest() override {}
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- IsolateAllSitesForTesting(command_line);
- }
-};
-
-IN_PROC_BROWSER_TEST_F(IsolatedDevToolsProtocolTest,
- ControlNavigationsChildFrames) {
- content::SetupCrossSiteRedirector(embedded_test_server());
- ASSERT_TRUE(embedded_test_server()->Start());
-
- // Navigate to about:blank first so we can make sure there is a target page we
- // can attach to, and have Network.setRequestInterception complete
- // before we start the navigations we're interested in.
- NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
- Attach();
-
- std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
- std::unique_ptr<base::ListValue> patterns(new base::ListValue());
- patterns->Append(std::make_unique<base::DictionaryValue>());
- params->Set("patterns", std::move(patterns));
- SendCommand("Network.setRequestInterception", std::move(params), true);
-
- NavigationFinishedObserver navigation_finished_observer(
- shell()->web_contents());
-
- GURL test_url = embedded_test_server()->GetURL(
- "/devtools/control_navigations/iframe_navigation.html");
- shell()->LoadURL(test_url);
-
- // Allow main frame navigation, and all iframe navigations to http://a.com
- // Allow initial iframe navigation to http://b.com but dissallow it to
- // navigate to /devtools/navigation.html.
- std::vector<ExpectedNavigation> expected_navigations = {
- {"http://127.0.0.1/devtools/control_navigations/"
- "iframe_navigation.html",
- false /* expected_is_redirect */, false /* abort */},
- {"http://127.0.0.1/cross-site/a.com/devtools/control_navigations/"
- "meta_tag.html",
- false /* expected_is_redirect */, false /* abort */},
- {"http://127.0.0.1/cross-site/b.com/devtools/control_navigations/"
- "meta_tag.html",
- false /* expected_is_redirect */, false /* abort */},
- {"http://a.com/devtools/control_navigations/meta_tag.html",
- true /* expected_is_redirect */, false /* abort */},
- {"http://b.com/devtools/control_navigations/meta_tag.html",
- true /* expected_is_redirect */, false /* abort */},
- {"http://a.com/devtools/navigation.html",
- false /* expected_is_redirect */, false /* abort */},
- {"http://b.com/devtools/navigation.html",
- false /* expected_is_redirect */, true /* abort */}};
-
- ProcessNavigationsAnyOrder(std::move(expected_navigations));
-
- // Wait for each frame's navigation to finish, ignoring redirects.
- navigation_finished_observer.WaitForNavigationsToFinish(3);
-
- // Make sure each frame has the expected url.
- EXPECT_THAT(
- GetAllFrameUrls(),
- ElementsAre("http://127.0.0.1/devtools/control_navigations/"
- "iframe_navigation.html",
- "http://a.com/devtools/navigation.html",
- "http://b.com/devtools/control_navigations/meta_tag.html"));
-}
-
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, VirtualTimeTest) {
NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
Attach();
@@ -2442,11 +2241,12 @@ class CountingDownloadFile : public download::DownloadFileImpl {
// until data is returned.
static int GetNumberActiveFilesFromFileThread() {
int result = -1;
+ base::RunLoop run_loop;
download::GetDownloadTaskRunner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&CountingDownloadFile::GetNumberActiveFiles, &result),
- base::MessageLoop::current()->QuitWhenIdleClosure());
- base::RunLoop().Run();
+ run_loop.QuitWhenIdleClosure());
+ run_loop.Run();
DCHECK_NE(-1, result);
return result;
}
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.cc b/chromium/content/browser/devtools/protocol/emulation_handler.cc
index f61f93491cc..ca11b87a749 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.cc
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.cc
@@ -327,12 +327,22 @@ void EmulationHandler::UpdateTouchEventEmulationState() {
return;
if (host_->GetParent() && !host_->IsCrossProcessSubframe())
return;
+
+ // We only have a single TouchEmulator for all frames, so let the main frame's
+ // EmulationHandler enable/disable it.
+ if (!host_->frame_tree_node()->IsMainFrame())
+ return;
+
if (touch_emulation_enabled_) {
- host_->GetRenderWidgetHost()->GetTouchEmulator()->Enable(
- TouchEmulator::Mode::kEmulatingTouchFromMouse,
- TouchEmulationConfigurationToType(touch_emulation_configuration_));
+ if (auto* touch_emulator =
+ host_->GetRenderWidgetHost()->GetTouchEmulator()) {
+ touch_emulator->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ TouchEmulationConfigurationToType(touch_emulation_configuration_));
+ }
} else {
- host_->GetRenderWidgetHost()->GetTouchEmulator()->Disable();
+ if (auto* touch_emulator = host_->GetRenderWidgetHost()->GetTouchEmulator())
+ touch_emulator->Disable();
}
if (GetWebContents()) {
GetWebContents()->SetForceDisableOverscrollContent(
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index 3556f33c0fb..4440a13e4c4 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -97,10 +97,6 @@ base::TimeTicks GetEventTimeTicks(const Maybe<double>& timestamp) {
: base::TimeTicks::Now();
}
-double GetEventTimestamp(const Maybe<double>& timestamp) {
- return (GetEventTimeTicks(timestamp) - base::TimeTicks()).InSecondsF();
-}
-
bool SetKeyboardEventText(blink::WebUChar* to, Maybe<std::string> from) {
if (!from.isJust())
return true;
@@ -351,7 +347,7 @@ class InputHandler::InputInjector
&DispatchTouchEventCallback::sendSuccess, std::move(callback));
for (size_t i = 0; i < events.size(); i++) {
widget_host_->GetTouchEmulator()->InjectTouchEvent(
- events[i],
+ events[i], widget_host_->GetView(),
i == events.size() - 1 ? std::move(closure) : base::OnceClosure());
}
MaybeSelfDestruct();
@@ -490,7 +486,7 @@ void InputHandler::DispatchKeyEvent(
GetEventModifiers(modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers),
auto_repeat.fromMaybe(false),
is_keypad.fromMaybe(false), location.fromMaybe(0)),
- GetEventTimeTicks(std::move(timestamp)));
+ GetEventTimeTicks(timestamp));
if (!SetKeyboardEventText(event.text, std::move(text))) {
callback->sendFailure(Response::InvalidParams("Invalid 'text' parameter"));
@@ -574,7 +570,7 @@ void InputHandler::DispatchMouseEvent(
maybe_modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
false, 0);
modifiers |= button_modifiers;
- double timestamp = GetEventTimestamp(maybe_timestamp);
+ base::TimeTicks timestamp = GetEventTimeTicks(maybe_timestamp);
std::unique_ptr<blink::WebMouseEvent, ui::WebInputEventDeleter> mouse_event;
blink::WebMouseWheelEvent* wheel_event = nullptr;
@@ -637,7 +633,7 @@ void InputHandler::DispatchTouchEvent(
int modifiers = GetEventModifiers(
maybe_modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
false, 0);
- double timestamp = GetEventTimestamp(maybe_timestamp);
+ base::TimeTicks timestamp = GetEventTimeTicks(maybe_timestamp);
if ((type == blink::WebInputEvent::kTouchStart ||
type == blink::WebInputEvent::kTouchMove) &&
@@ -801,7 +797,7 @@ Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
false, 0) |
button_modifiers,
- GetEventTimestamp(maybe_timestamp));
+ GetEventTimeTicks(maybe_timestamp));
mouse_event = wheel_event;
event.reset(wheel_event);
wheel_event->delta_x = static_cast<float>(delta_x.fromJust());
@@ -817,7 +813,7 @@ Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
modifiers.fromMaybe(blink::WebInputEvent::kNoModifiers), false,
false, 0) |
button_modifiers,
- GetEventTimestamp(maybe_timestamp));
+ GetEventTimeTicks(maybe_timestamp));
event.reset(mouse_event);
}
diff --git a/chromium/content/browser/devtools/protocol/io_handler.cc b/chromium/content/browser/devtools/protocol/io_handler.cc
index 76e77feb568..57c61cd0370 100644
--- a/chromium/content/browser/devtools/protocol/io_handler.cc
+++ b/chromium/content/browser/devtools/protocol/io_handler.cc
@@ -15,6 +15,7 @@
#include "base/strings/string_util.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/devtools/devtools_io_context.h"
+#include "content/browser/devtools/devtools_stream_blob.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -56,21 +57,27 @@ void IOHandler::Read(
static const size_t kDefaultChunkSize = 10 * 1024 * 1024;
static const char kBlobPrefix[] = "blob:";
- scoped_refptr<DevToolsIOContext::ROStream> stream =
+ scoped_refptr<DevToolsIOContext::Stream> stream =
io_context_->GetByHandle(handle);
if (!stream && browser_context_ &&
StartsWith(handle, kBlobPrefix, base::CompareCase::SENSITIVE)) {
ChromeBlobStorageContext* blob_context =
ChromeBlobStorageContext::GetFor(browser_context_);
std::string uuid = handle.substr(strlen(kBlobPrefix));
- stream =
- io_context_->OpenBlob(blob_context, storage_partition_, handle, uuid);
+ stream = DevToolsStreamBlob::Create(io_context_, blob_context,
+ storage_partition_, handle, uuid);
}
if (!stream) {
callback->sendFailure(Response::InvalidParams("Invalid stream handle"));
return;
}
+ if (offset.isJust() && !stream->SupportsSeek()) {
+ callback->sendFailure(
+ Response::InvalidParams("Read offset is specificed for a stream that "
+ "does not support random access"));
+ return;
+ }
stream->Read(offset.fromMaybe(-1), max_size.fromMaybe(kDefaultChunkSize),
base::BindOnce(&IOHandler::ReadComplete,
weak_factory_.GetWeakPtr(), std::move(callback)));
@@ -80,11 +87,11 @@ void IOHandler::ReadComplete(std::unique_ptr<ReadCallback> callback,
std::unique_ptr<std::string> data,
bool base64_encoded,
int status) {
- if (status == DevToolsIOContext::ROStream::StatusFailure) {
+ if (status == DevToolsIOContext::Stream::StatusFailure) {
callback->sendFailure(Response::Error("Read failed"));
return;
}
- bool eof = status == DevToolsIOContext::ROStream::StatusEOF;
+ bool eof = status == DevToolsIOContext::Stream::StatusEOF;
callback->sendSuccess(base64_encoded, std::move(*data), eof);
}
diff --git a/chromium/content/browser/devtools/protocol/memory_handler.cc b/chromium/content/browser/devtools/protocol/memory_handler.cc
index 56c44b1556f..06a5638dab3 100644
--- a/chromium/content/browser/devtools/protocol/memory_handler.cc
+++ b/chromium/content/browser/devtools/protocol/memory_handler.cc
@@ -7,14 +7,18 @@
#include "base/memory/memory_pressure_listener.h"
#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
#include "base/strings/stringprintf.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/bind_interface_helpers.h"
+#include "content/public/common/child_process_host.h"
#include "content/public/common/content_features.h"
namespace content {
namespace protocol {
MemoryHandler::MemoryHandler()
- : DevToolsDomainHandler(Memory::Metainfo::domainName) {
-}
+ : DevToolsDomainHandler(Memory::Metainfo::domainName),
+ process_host_id_(ChildProcessHost::kInvalidUniqueID),
+ weak_factory_(this) {}
MemoryHandler::~MemoryHandler() {}
@@ -22,6 +26,11 @@ void MemoryHandler::Wire(UberDispatcher* dispatcher) {
Memory::Dispatcher::wire(dispatcher, this);
}
+void MemoryHandler::SetRenderer(int process_host_id,
+ RenderFrameHostImpl* frame_host) {
+ process_host_id_ = process_host_id;
+}
+
Response MemoryHandler::GetBrowserSamplingProfile(
std::unique_ptr<Memory::SamplingProfile>* out_profile) {
std::unique_ptr<Array<Memory::SamplingProfileNode>> samples =
@@ -74,5 +83,40 @@ Response MemoryHandler::SimulatePressureNotification(
return Response::OK();
}
+void MemoryHandler::PrepareForLeakDetection(
+ std::unique_ptr<PrepareForLeakDetectionCallback> callback) {
+ if (leak_detection_callback_) {
+ callback->sendFailure(
+ Response::Error("Another leak detection in progress"));
+ return;
+ }
+ RenderProcessHost* process = RenderProcessHost::FromID(process_host_id_);
+ if (!process) {
+ callback->sendFailure(Response::Error("No process to detect leaks in"));
+ return;
+ }
+
+ leak_detection_callback_ = std::move(callback);
+ BindInterface(process, &leak_detector_);
+ leak_detector_.set_connection_error_handler(base::BindOnce(
+ &MemoryHandler::OnLeakDetectorIsGone, base::Unretained(this)));
+ leak_detector_->PerformLeakDetection(base::BindOnce(
+ &MemoryHandler::OnLeakDetectionComplete, weak_factory_.GetWeakPtr()));
+}
+
+void MemoryHandler::OnLeakDetectionComplete(
+ blink::mojom::LeakDetectionResultPtr result) {
+ leak_detection_callback_->sendSuccess();
+ leak_detection_callback_.reset();
+ leak_detector_.reset();
+}
+
+void MemoryHandler::OnLeakDetectorIsGone() {
+ leak_detection_callback_->sendFailure(
+ Response::Error("Failed to run leak detection"));
+ leak_detection_callback_.reset();
+ leak_detector_.reset();
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/memory_handler.h b/chromium/content/browser/devtools/protocol/memory_handler.h
index 1c09b64b5ca..21fa2b92db0 100644
--- a/chromium/content/browser/devtools/protocol/memory_handler.h
+++ b/chromium/content/browser/devtools/protocol/memory_handler.h
@@ -6,8 +6,10 @@
#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_MEMORY_HANDLER_H_
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/memory.h"
+#include "third_party/blink/public/mojom/leak_detector/leak_detector.mojom.h"
namespace content {
namespace protocol {
@@ -19,13 +21,25 @@ class MemoryHandler : public DevToolsDomainHandler,
~MemoryHandler() override;
void Wire(UberDispatcher* dispatcher) override;
+ void SetRenderer(int process_host_id,
+ RenderFrameHostImpl* frame_host) override;
Response GetBrowserSamplingProfile(
std::unique_ptr<Memory::SamplingProfile>* out_profile) override;
Response SetPressureNotificationsSuppressed(bool suppressed) override;
Response SimulatePressureNotification(const std::string& level) override;
+ void PrepareForLeakDetection(
+ std::unique_ptr<PrepareForLeakDetectionCallback> callback) override;
private:
+ void OnLeakDetectionComplete(blink::mojom::LeakDetectionResultPtr result);
+ void OnLeakDetectorIsGone();
+
+ int process_host_id_;
+ blink::mojom::LeakDetectorPtr leak_detector_;
+ std::unique_ptr<PrepareForLeakDetectionCallback> leak_detection_callback_;
+ base::WeakPtrFactory<MemoryHandler> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(MemoryHandler);
};
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index 6d62f72deae..b8ea9fc9205 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -17,14 +17,21 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
+#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/devtools/devtools_interceptor_controller.h"
+#include "content/browser/devtools/devtools_io_context.h"
#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/devtools_stream_pipe.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/devtools/protocol/page.h"
#include "content/browser/devtools/protocol/security.h"
+#include "content/browser/devtools/service_worker_devtools_agent_host.h"
+#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/browser/web_package/signed_exchange_header.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -61,6 +68,7 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
namespace content {
@@ -620,34 +628,45 @@ net::Error NetErrorFromString(const std::string& error, bool* ok) {
return net::ERR_INTERNET_DISCONNECTED;
if (error == Network::ErrorReasonEnum::AddressUnreachable)
return net::ERR_ADDRESS_UNREACHABLE;
+ if (error == Network::ErrorReasonEnum::BlockedByClient)
+ return net::ERR_BLOCKED_BY_CLIENT;
+ if (error == Network::ErrorReasonEnum::BlockedByResponse)
+ return net::ERR_BLOCKED_BY_RESPONSE;
*ok = false;
return net::ERR_FAILED;
}
String NetErrorToString(int net_error) {
- if (net_error == net::ERR_ABORTED)
- return Network::ErrorReasonEnum::Aborted;
- if (net_error == net::ERR_TIMED_OUT)
- return Network::ErrorReasonEnum::TimedOut;
- if (net_error == net::ERR_ACCESS_DENIED)
- return Network::ErrorReasonEnum::AccessDenied;
- if (net_error == net::ERR_CONNECTION_CLOSED)
- return Network::ErrorReasonEnum::ConnectionClosed;
- if (net_error == net::ERR_CONNECTION_RESET)
- return Network::ErrorReasonEnum::ConnectionReset;
- if (net_error == net::ERR_CONNECTION_REFUSED)
- return Network::ErrorReasonEnum::ConnectionRefused;
- if (net_error == net::ERR_CONNECTION_ABORTED)
- return Network::ErrorReasonEnum::ConnectionAborted;
- if (net_error == net::ERR_CONNECTION_FAILED)
- return Network::ErrorReasonEnum::ConnectionFailed;
- if (net_error == net::ERR_NAME_NOT_RESOLVED)
- return Network::ErrorReasonEnum::NameNotResolved;
- if (net_error == net::ERR_INTERNET_DISCONNECTED)
- return Network::ErrorReasonEnum::InternetDisconnected;
- if (net_error == net::ERR_ADDRESS_UNREACHABLE)
- return Network::ErrorReasonEnum::AddressUnreachable;
- return Network::ErrorReasonEnum::Failed;
+ switch (net_error) {
+ case net::ERR_ABORTED:
+ return Network::ErrorReasonEnum::Aborted;
+ case net::ERR_TIMED_OUT:
+ return Network::ErrorReasonEnum::TimedOut;
+ case net::ERR_ACCESS_DENIED:
+ return Network::ErrorReasonEnum::AccessDenied;
+ case net::ERR_CONNECTION_CLOSED:
+ return Network::ErrorReasonEnum::ConnectionClosed;
+ case net::ERR_CONNECTION_RESET:
+ return Network::ErrorReasonEnum::ConnectionReset;
+ case net::ERR_CONNECTION_REFUSED:
+ return Network::ErrorReasonEnum::ConnectionRefused;
+ case net::ERR_CONNECTION_ABORTED:
+ return Network::ErrorReasonEnum::ConnectionAborted;
+ case net::ERR_CONNECTION_FAILED:
+ return Network::ErrorReasonEnum::ConnectionFailed;
+ case net::ERR_NAME_NOT_RESOLVED:
+ return Network::ErrorReasonEnum::NameNotResolved;
+ case net::ERR_INTERNET_DISCONNECTED:
+ return Network::ErrorReasonEnum::InternetDisconnected;
+ case net::ERR_ADDRESS_UNREACHABLE:
+ return Network::ErrorReasonEnum::AddressUnreachable;
+ case net::ERR_BLOCKED_BY_CLIENT:
+ return Network::ErrorReasonEnum::BlockedByClient;
+ case net::ERR_BLOCKED_BY_RESPONSE:
+ return Network::ErrorReasonEnum::BlockedByResponse;
+ default:
+ return Network::ErrorReasonEnum::Failed;
+ }
}
bool AddInterceptedResourceType(
@@ -857,16 +876,75 @@ std::string StripFragment(const GURL& url) {
} // namespace
-NetworkHandler::NetworkHandler(const std::string& host_id)
+class BackgroundSyncRestorer {
+ public:
+ BackgroundSyncRestorer(const std::string& host_id,
+ StoragePartition* storage_partition)
+ : host_id_(host_id), storage_partition_(storage_partition) {
+ SetServiceWorkerOffline(true);
+ }
+
+ ~BackgroundSyncRestorer() { SetServiceWorkerOffline(false); }
+
+ void SetStoragePartition(StoragePartition* storage_partition) {
+ storage_partition_ = storage_partition;
+ }
+
+ private:
+ void SetServiceWorkerOffline(bool offline) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ scoped_refptr<DevToolsAgentHost> host =
+ DevToolsAgentHost::GetForId(host_id_);
+ if (!host || !storage_partition_ ||
+ host->GetType() != DevToolsAgentHost::kTypeServiceWorker) {
+ return;
+ }
+ scoped_refptr<ServiceWorkerDevToolsAgentHost> service_worker_host =
+ static_cast<ServiceWorkerDevToolsAgentHost*>(host.get());
+ scoped_refptr<BackgroundSyncContext> sync_context =
+ static_cast<StoragePartitionImpl*>(storage_partition_)
+ ->GetBackgroundSyncContext();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &SetServiceWorkerOfflineOnIO, sync_context,
+ base::RetainedRef(static_cast<ServiceWorkerContextWrapper*>(
+ storage_partition_->GetServiceWorkerContext())),
+ service_worker_host->version_id(), offline));
+ }
+
+ static void SetServiceWorkerOfflineOnIO(
+ scoped_refptr<BackgroundSyncContext> sync_context,
+ scoped_refptr<ServiceWorkerContextWrapper> swcontext,
+ int64_t version_id,
+ bool offline) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ServiceWorkerVersion* version = swcontext.get()->GetLiveVersion(version_id);
+ if (!version)
+ return;
+ sync_context->background_sync_manager()->EmulateServiceWorkerOffline(
+ version->registration_id(), offline);
+ }
+
+ std::string host_id_;
+ StoragePartition* storage_partition_;
+
+ DISALLOW_COPY_AND_ASSIGN(BackgroundSyncRestorer);
+};
+
+NetworkHandler::NetworkHandler(const std::string& host_id,
+ DevToolsIOContext* io_context)
: DevToolsDomainHandler(Network::Metainfo::domainName),
+ host_id_(host_id),
+ io_context_(io_context),
browser_context_(nullptr),
storage_partition_(nullptr),
host_(nullptr),
enabled_(false),
- host_id_(host_id),
bypass_service_worker_(false),
cache_disabled_(false),
weak_factory_(this) {
+ DCHECK(io_context_);
static bool have_configured_service_worker_context = false;
if (have_configured_service_worker_context)
return;
@@ -902,6 +980,8 @@ void NetworkHandler::SetRenderer(int render_process_host_id,
browser_context_ = nullptr;
}
host_ = frame_host;
+ if (background_sync_restorer_)
+ background_sync_restorer_->SetStoragePartition(storage_partition_);
}
Response NetworkHandler::Enable(Maybe<int> max_total_size,
@@ -1405,6 +1485,36 @@ std::unique_ptr<Network::Response> BuildResponse(
return response;
}
+
+String blockedReason(blink::ResourceRequestBlockedReason reason) {
+ switch (reason) {
+ case blink::ResourceRequestBlockedReason::kCSP:
+ return protocol::Network::BlockedReasonEnum::Csp;
+ case blink::ResourceRequestBlockedReason::kMixedContent:
+ return protocol::Network::BlockedReasonEnum::MixedContent;
+ case blink::ResourceRequestBlockedReason::kOrigin:
+ return protocol::Network::BlockedReasonEnum::Origin;
+ case blink::ResourceRequestBlockedReason::kInspector:
+ return protocol::Network::BlockedReasonEnum::Inspector;
+ case blink::ResourceRequestBlockedReason::kSubresourceFilter:
+ return protocol::Network::BlockedReasonEnum::SubresourceFilter;
+ case blink::ResourceRequestBlockedReason::kContentType:
+ return protocol::Network::BlockedReasonEnum::ContentType;
+ case blink::ResourceRequestBlockedReason::kOther:
+ return protocol::Network::BlockedReasonEnum::Other;
+ }
+ NOTREACHED();
+ return protocol::Network::BlockedReasonEnum::Other;
+}
+
+Maybe<String> GetBlockedReasonFor(
+ const network::URLLoaderCompletionStatus& status) {
+ if (status.error_code != net::ERR_BLOCKED_BY_CLIENT &&
+ status.error_code != net::ERR_BLOCKED_BY_RESPONSE)
+ return Maybe<String>();
+ return blockedReason(static_cast<blink::ResourceRequestBlockedReason>(
+ status.extended_error_code));
+}
} // namespace
void NetworkHandler::NavigationRequestWillBeSent(
@@ -1478,12 +1588,17 @@ void NetworkHandler::NavigationRequestWillBeSent(
void NetworkHandler::RequestSent(const std::string& request_id,
const std::string& loader_id,
const network::ResourceRequest& request,
- const char* initiator_type) {
+ const char* initiator_type,
+ const base::Optional<GURL>& initiator_url) {
if (!enabled_)
return;
std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create());
for (net::HttpRequestHeaders::Iterator it(request.headers); it.GetNext();)
headers_dict->setString(it.name(), it.value());
+ std::unique_ptr<Network::Initiator> initiator =
+ Network::Initiator::Create().SetType(initiator_type).Build();
+ if (initiator_url)
+ initiator->SetUrl(initiator_url->spec());
frontend_->RequestWillBeSent(
request_id, loader_id, StripFragment(request.url),
Network::Request::Create()
@@ -1495,8 +1610,7 @@ void NetworkHandler::RequestSent(const std::string& request_id,
.Build(),
base::TimeTicks::Now().ToInternalValue() /
static_cast<double>(base::Time::kMicrosecondsPerSecond),
- base::Time::Now().ToDoubleT(),
- Network::Initiator::Create().SetType(initiator_type).Build(),
+ base::Time::Now().ToDoubleT(), std::move(initiator),
std::unique_ptr<Network::Response>(),
std::string(Page::ResourceTypeEnum::Other),
Maybe<std::string>() /* frame_id */, request.has_user_gesture);
@@ -1531,7 +1645,8 @@ void NetworkHandler::LoadingComplete(
base::TimeTicks::Now().ToInternalValue() /
static_cast<double>(base::Time::kMicrosecondsPerSecond),
resource_type, net::ErrorToString(status.error_code),
- status.error_code == net::Error::ERR_ABORTED);
+ status.error_code == net::Error::ERR_ABORTED,
+ GetBlockedReasonFor(status));
return;
}
frontend_->LoadingFinished(
@@ -1541,52 +1656,58 @@ void NetworkHandler::LoadingComplete(
status.encoded_data_length);
}
-void NetworkHandler::NavigationFailed(NavigationRequest* navigation_request) {
+void NetworkHandler::OnSignedExchangeReceived(
+ base::Optional<const base::UnguessableToken> devtools_navigation_token,
+ const GURL& outer_request_url,
+ const network::ResourceResponseHead& outer_response,
+ const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ const std::vector<std::string>& error_messages) {
if (!enabled_)
return;
+ std::unique_ptr<Network::SignedExchangeInfo> signed_exchange_info =
+ Network::SignedExchangeInfo::Create()
+ .SetOuterResponse(BuildResponse(outer_request_url, outer_response))
+ .Build();
- static int next_id = 0;
- std::string request_id = base::IntToString(base::GetCurrentProcId()) + "." +
- base::IntToString(++next_id);
- std::string error_string =
- net::ErrorToString(navigation_request->net_error());
- bool cancelled = navigation_request->net_error() == net::Error::ERR_ABORTED;
-
- std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create());
- net::HttpRequestHeaders headers;
- headers.AddHeadersFromString(navigation_request->begin_params()->headers);
- for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();)
- headers_dict->setString(it.name(), it.value());
- frontend_->RequestWillBeSent(
- request_id, "" /* loader_id */,
- StripFragment(navigation_request->common_params().url),
- Network::Request::Create()
- .SetUrl(StripFragment(navigation_request->common_params().url))
- .SetMethod(navigation_request->common_params().method)
- .SetHeaders(Object::fromValue(headers_dict.get(), nullptr))
- // Note: the priority value is copied from
- // ResourceDispatcherHostImpl::BeginNavigationRequest but there isn't
- // a good way of sharing this.
- .SetInitialPriority(resourcePriority(net::HIGHEST))
- .SetReferrerPolicy(referrerPolicy(
- navigation_request->common_params().referrer.policy))
- .Build(),
- base::TimeTicks::Now().ToInternalValue() /
- static_cast<double>(base::Time::kMicrosecondsPerSecond),
- base::Time::Now().ToDoubleT(),
- Network::Initiator::Create()
- .SetType(Network::Initiator::TypeEnum::Parser)
- .Build(),
- std::unique_ptr<Network::Response>(),
- std::string(Page::ResourceTypeEnum::Document),
- Maybe<std::string>() /* frame_id */,
- navigation_request->common_params().has_user_gesture);
-
- frontend_->LoadingFailed(
- request_id,
- base::TimeTicks::Now().ToInternalValue() /
- static_cast<double>(base::Time::kMicrosecondsPerSecond),
- Page::ResourceTypeEnum::Document, error_string, cancelled);
+ if (header) {
+ std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create());
+ for (const auto it : header->response_headers())
+ headers_dict->setString(it.first, it.second);
+
+ const SignedExchangeHeaderParser::Signature& sig = header->signature();
+ std::unique_ptr<Array<Network::SignedExchangeSignature>> signatures =
+ Array<Network::SignedExchangeSignature>::create();
+ signatures->addItem(Network::SignedExchangeSignature::Create()
+ .SetLabel(sig.label)
+ .SetIntegrity(sig.integrity)
+ .SetCertUrl(sig.cert_url.spec())
+ .SetValidityUrl(sig.validity_url.spec())
+ .SetDate(sig.date)
+ .SetExpires(sig.expires)
+ .Build());
+
+ signed_exchange_info->SetHeader(
+ Network::SignedExchangeHeader::Create()
+ .SetRequestUrl(header->request_url().spec())
+ .SetRequestMethod(header->request_method())
+ .SetResponseCode(header->response_code())
+ .SetResponseHeaders(Object::fromValue(headers_dict.get(), nullptr))
+ .SetSignatures(std::move(signatures))
+ .Build());
+ }
+ if (ssl_info)
+ signed_exchange_info->SetSecurityDetails(BuildSecurityDetails(*ssl_info));
+ if (error_messages.size()) {
+ std::unique_ptr<Array<String>> errors = Array<String>::create();
+ for (const auto& message : error_messages)
+ errors->addItem(message);
+ signed_exchange_info->SetErrors(std::move(errors));
+ }
+
+ frontend_->SignedExchangeReceived(
+ devtools_navigation_token ? devtools_navigation_token->ToString() : "",
+ std::move(signed_exchange_info));
}
DispatchResponse NetworkHandler::SetRequestInterception(
@@ -1723,6 +1844,38 @@ void NetworkHandler::GetResponseBodyForInterception(
interceptor->GetResponseBody(interception_id, std::move(callback));
}
+void NetworkHandler::TakeResponseBodyForInterceptionAsStream(
+ const String& interception_id,
+ std::unique_ptr<TakeResponseBodyForInterceptionAsStreamCallback> callback) {
+ if (url_loader_interceptor_) {
+ url_loader_interceptor_->TakeResponseBodyPipe(
+ interception_id,
+ base::BindOnce(&NetworkHandler::OnResponseBodyPipeTaken,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ return;
+ }
+ callback->sendFailure(Response::Error(
+ "Network.takeResponseBodyForInterceptionAsStream is only "
+ "currently supported with --enable-features=NetworkService"));
+}
+
+void NetworkHandler::OnResponseBodyPipeTaken(
+ std::unique_ptr<TakeResponseBodyForInterceptionAsStreamCallback> callback,
+ Response response,
+ mojo::ScopedDataPipeConsumerHandle pipe,
+ const std::string& mime_type) {
+ DCHECK_EQ(response.isSuccess(), pipe.is_valid());
+ if (!response.isSuccess()) {
+ callback->sendFailure(std::move(response));
+ return;
+ }
+ // The pipe stream is owned only by io_context after we return.
+ bool is_binary = !DevToolsIOContext::IsTextMimeType(mime_type);
+ auto stream =
+ DevToolsStreamPipe::Create(io_context_, std::move(pipe), is_binary);
+ callback->sendSuccess(stream->handle());
+}
+
// static
GURL NetworkHandler::ClearUrlRef(const GURL& url) {
if (!url.has_ref())
@@ -1806,10 +1959,11 @@ bool NetworkHandler::ShouldCancelNavigation(
bool NetworkHandler::MaybeCreateProxyForInterception(
const base::UnguessableToken& frame_token,
int process_id,
+ bool is_download,
network::mojom::URLLoaderFactoryRequest* target_factory_request) {
return url_loader_interceptor_ &&
url_loader_interceptor_->CreateProxyForInterception(
- frame_token, process_id, target_factory_request);
+ frame_token, process_id, is_download, target_factory_request);
}
void NetworkHandler::ApplyOverrides(net::HttpRequestHeaders* headers,
@@ -1879,9 +2033,9 @@ void NetworkHandler::RequestIntercepted(
frontend_->RequestIntercepted(
info->interception_id, std::move(info->network_request),
info->frame_id.ToString(), ResourceTypeToString(info->resource_type),
- info->is_navigation, std::move(info->redirect_url),
- std::move(info->auth_challenge), std::move(error_reason),
- std::move(info->http_response_status_code),
+ info->is_navigation, std::move(info->is_download),
+ std::move(info->redirect_url), std::move(info->auth_challenge),
+ std::move(error_reason), std::move(info->http_response_status_code),
std::move(info->response_headers));
}
@@ -1891,7 +2045,14 @@ void NetworkHandler::SetNetworkConditions(
return;
network::mojom::NetworkContext* context =
storage_partition_->GetNetworkContext();
+ bool offline = conditions ? conditions->offline : false;
context->SetNetworkConditions(host_id_, std::move(conditions));
+
+ if (offline == !!background_sync_restorer_)
+ return;
+ background_sync_restorer_.reset(
+ offline ? new BackgroundSyncRestorer(host_id_, storage_partition_)
+ : nullptr);
}
} // namespace protocol
diff --git a/chromium/content/browser/devtools/protocol/network_handler.h b/chromium/content/browser/devtools/protocol/network_handler.h
index 6bf4e7e976a..121d24f0bf5 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.h
+++ b/chromium/content/browser/devtools/protocol/network_handler.h
@@ -6,14 +6,17 @@
#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
#include <memory>
+#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/network.h"
+#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/net_errors.h"
#include "net/cookies/canonical_cookie.h"
#include "services/network/public/mojom/network_service.mojom.h"
@@ -25,6 +28,7 @@ class UnguessableToken;
namespace net {
class HttpRequestHeaders;
class URLRequest;
+class SSLInfo;
} // namespace net
namespace network {
@@ -36,21 +40,24 @@ struct URLLoaderCompletionStatus;
namespace content {
class BrowserContext;
class DevToolsAgentHostImpl;
+class DevToolsIOContext;
class RenderFrameHostImpl;
class InterceptionHandle;
class NavigationHandle;
class NavigationRequest;
class NavigationThrottle;
+class SignedExchangeHeader;
class StoragePartition;
struct GlobalRequestID;
struct InterceptedRequestInfo;
namespace protocol {
+class BackgroundSyncRestorer;
class NetworkHandler : public DevToolsDomainHandler,
public Network::Backend {
public:
- explicit NetworkHandler(const std::string& host_id);
+ NetworkHandler(const std::string& host_id, DevToolsIOContext* io_context);
~NetworkHandler() override;
static std::vector<NetworkHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
@@ -124,10 +131,15 @@ class NetworkHandler : public DevToolsDomainHandler,
const String& interception_id,
std::unique_ptr<GetResponseBodyForInterceptionCallback> callback)
override;
+ void TakeResponseBodyForInterceptionAsStream(
+ const String& interception_id,
+ std::unique_ptr<TakeResponseBodyForInterceptionAsStreamCallback> callback)
+ override;
bool MaybeCreateProxyForInterception(
const base::UnguessableToken& frame_token,
int process_id,
+ bool is_download,
network::mojom::URLLoaderFactoryRequest* target_factory_request);
void ApplyOverrides(net::HttpRequestHeaders* headers,
@@ -137,7 +149,8 @@ class NetworkHandler : public DevToolsDomainHandler,
void RequestSent(const std::string& request_id,
const std::string& loader_id,
const network::ResourceRequest& request,
- const char* initiator_type);
+ const char* initiator_type,
+ const base::Optional<GURL>& initiator_url);
void ResponseReceived(const std::string& request_id,
const std::string& loader_id,
const GURL& url,
@@ -149,7 +162,13 @@ class NetworkHandler : public DevToolsDomainHandler,
const char* resource_type,
const network::URLLoaderCompletionStatus& completion_status);
- void NavigationFailed(NavigationRequest* navigation_request);
+ void OnSignedExchangeReceived(
+ base::Optional<const base::UnguessableToken> devtools_navigation_token,
+ const GURL& outer_request_url,
+ const network::ResourceResponseHead& outer_response,
+ const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ const std::vector<std::string>& error_messages);
bool enabled() const { return enabled_; }
@@ -172,6 +191,15 @@ class NetworkHandler : public DevToolsDomainHandler,
void RequestIntercepted(std::unique_ptr<InterceptedRequestInfo> request_info);
void SetNetworkConditions(network::mojom::NetworkConditionsPtr conditions);
+ void OnResponseBodyPipeTaken(
+ std::unique_ptr<TakeResponseBodyForInterceptionAsStreamCallback> callback,
+ Response response,
+ mojo::ScopedDataPipeConsumerHandle pipe,
+ const std::string& mime_type);
+
+ const std::string host_id_;
+ DevToolsIOContext* const io_context_;
+
std::unique_ptr<Network::Frontend> frontend_;
BrowserContext* browser_context_;
StoragePartition* storage_partition_;
@@ -179,11 +207,11 @@ class NetworkHandler : public DevToolsDomainHandler,
bool enabled_;
std::string user_agent_;
std::vector<std::pair<std::string, std::string>> extra_headers_;
- std::string host_id_;
std::unique_ptr<InterceptionHandle> interception_handle_;
std::unique_ptr<DevToolsURLLoaderInterceptor> url_loader_interceptor_;
bool bypass_service_worker_;
bool cache_disabled_;
+ std::unique_ptr<BackgroundSyncRestorer> background_sync_restorer_;
base::WeakPtrFactory<NetworkHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NetworkHandler);
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index 8dc4689a515..7e497a0402b 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -22,6 +22,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
@@ -41,11 +43,11 @@
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/referrer.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/use_zoom_for_dsf_policy.h"
@@ -103,6 +105,77 @@ std::string EncodeSkBitmap(const SkBitmap& image,
return EncodeImage(gfx::Image::CreateFrom1xBitmap(image), format, quality);
}
+std::unique_ptr<Page::ScreencastFrameMetadata> BuildScreencastFrameMetadata(
+ const gfx::Size& surface_size,
+ float device_scale_factor,
+ float page_scale_factor,
+ const gfx::Vector2dF& root_scroll_offset,
+ float top_controls_height,
+ float top_controls_shown_ratio) {
+ if (surface_size.IsEmpty() || device_scale_factor == 0)
+ return nullptr;
+
+ const gfx::SizeF content_size_dip =
+ gfx::ScaleSize(gfx::SizeF(surface_size), 1 / device_scale_factor);
+ float top_offset_dip = top_controls_height * top_controls_shown_ratio;
+ if (IsUseZoomForDSFEnabled())
+ top_offset_dip /= device_scale_factor;
+ std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
+ Page::ScreencastFrameMetadata::Create()
+ .SetPageScaleFactor(page_scale_factor)
+ .SetOffsetTop(top_offset_dip)
+ .SetDeviceWidth(content_size_dip.width())
+ .SetDeviceHeight(content_size_dip.height())
+ .SetScrollOffsetX(root_scroll_offset.x())
+ .SetScrollOffsetY(root_scroll_offset.y())
+ .SetTimestamp(base::Time::Now().ToDoubleT())
+ .Build();
+ return page_metadata;
+}
+
+// Determines the snapshot size that best-fits the Surface's content to the
+// remote's requested image size.
+gfx::Size DetermineSnapshotSize(const gfx::Size& surface_size,
+ int screencast_max_width,
+ int screencast_max_height) {
+ if (surface_size.IsEmpty())
+ return gfx::Size(); // Nothing to copy (and avoid divide-by-zero below).
+
+ double scale = 1;
+ if (screencast_max_width > 0) {
+ scale = std::min(scale, static_cast<double>(screencast_max_width) /
+ surface_size.width());
+ }
+ if (screencast_max_height > 0) {
+ scale = std::min(scale, static_cast<double>(screencast_max_height) /
+ surface_size.height());
+ }
+ return gfx::ToRoundedSize(gfx::ScaleSize(gfx::SizeF(surface_size), scale));
+}
+
+#if !defined(OS_ANDROID)
+void GetMetadataFromFrame(const media::VideoFrame& frame,
+ double* device_scale_factor,
+ double* page_scale_factor,
+ gfx::Vector2dF* root_scroll_offset) {
+ // Get metadata from |frame| and ensure that no metadata is missing.
+ bool success = true;
+ double root_scroll_offset_x, root_scroll_offset_y;
+ success &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::DEVICE_SCALE_FACTOR, device_scale_factor);
+ success &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::PAGE_SCALE_FACTOR, page_scale_factor);
+ success &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_X, &root_scroll_offset_x);
+ success &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y, &root_scroll_offset_y);
+ DCHECK(success);
+
+ root_scroll_offset->set_x(root_scroll_offset_x);
+ root_scroll_offset->set_y(root_scroll_offset_y);
+}
+#endif // !defined(OS_ANDROID)
+
} // namespace
PageHandler::PageHandler(EmulationHandler* emulation_handler)
@@ -118,9 +191,23 @@ PageHandler::PageHandler(EmulationHandler* emulation_handler)
session_id_(0),
frame_counter_(0),
frames_in_flight_(0),
+#if !defined(OS_ANDROID)
+ video_consumer_(nullptr),
+ last_surface_size_(gfx::Size()),
+#endif // !defined(OS_ANDROID)
host_(nullptr),
emulation_handler_(emulation_handler),
+ observer_(this),
weak_factory_(this) {
+#if !defined(OS_ANDROID)
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ base::FeatureList::IsEnabled(
+ features::kUseVideoCaptureApiForDevToolsSnapshots)) {
+ video_consumer_ = std::make_unique<DevToolsVideoConsumer>(
+ base::BindRepeating(&PageHandler::OnFrameFromVideoConsumer,
+ weak_factory_.GetWeakPtr()));
+ }
+#endif // !defined(OS_ANDROID)
DCHECK(emulation_handler_);
}
@@ -156,22 +243,21 @@ void PageHandler::SetRenderer(int process_host_id,
RenderWidgetHostImpl* widget_host =
host_ ? host_->GetRenderWidgetHost() : nullptr;
- if (widget_host) {
- registrar_.Remove(
- this,
- content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
- content::Source<RenderWidgetHost>(widget_host));
- }
+ if (widget_host && observer_.IsObserving(widget_host))
+ observer_.Remove(widget_host);
host_ = frame_host;
widget_host = host_ ? host_->GetRenderWidgetHost() : nullptr;
- if (widget_host) {
- registrar_.Add(
- this,
- content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
- content::Source<RenderWidgetHost>(widget_host));
+ if (widget_host)
+ observer_.Add(widget_host);
+
+#if !defined(OS_ANDROID)
+ if (video_consumer_ && frame_host) {
+ video_consumer_->SetFrameSinkId(
+ frame_host->GetRenderWidgetHost()->GetFrameSinkId());
}
+#endif // !defined(OS_ANDROID)
}
void PageHandler::Wire(UberDispatcher* dispatcher) {
@@ -204,14 +290,16 @@ void PageHandler::OnSynchronousSwapCompositorFrame(
InnerSwapCompositorFrame();
}
-void PageHandler::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
+void PageHandler::RenderWidgetHostVisibilityChanged(
+ RenderWidgetHost* widget_host,
+ bool became_visible) {
if (!screencast_enabled_)
return;
- DCHECK(type == content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED);
- bool visible = *Details<bool>(details).ptr();
- NotifyScreencastVisibility(visible);
+ NotifyScreencastVisibility(became_visible);
+}
+
+void PageHandler::RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) {
+ observer_.Remove(widget_host);
}
void PageHandler::DidAttachInterstitialPage() {
@@ -277,6 +365,11 @@ Response PageHandler::Disable() {
enabled_ = false;
screencast_enabled_ = false;
+#if !defined(OS_ANDROID)
+ if (video_consumer_)
+ video_consumer_->StopCapture();
+#endif // !defined(OS_ANDROID)
+
if (!pending_dialog_.is_null()) {
WebContentsImpl* web_contents = GetWebContents();
// Leave dialog hanging if there is a manager that can take care of it,
@@ -305,6 +398,14 @@ Response PageHandler::Crash() {
return Response::FallThrough();
}
+Response PageHandler::Close() {
+ WebContentsImpl* web_contents = GetWebContents();
+ if (!web_contents)
+ return Response::Error("Not attached to a page");
+ web_contents->DispatchBeforeUnload();
+ return Response::OK();
+}
+
Response PageHandler::Reload(Maybe<bool> bypassCache,
Maybe<std::string> script_to_evaluate_on_load) {
WebContentsImpl* web_contents = GetWebContents();
@@ -418,14 +519,14 @@ void PageHandler::NavigationReset(NavigationRequest* navigation_request) {
return;
std::string frame_id =
navigation_request->frame_tree_node()->devtools_frame_token().ToString();
- bool success = navigation_request->net_error() != net::OK;
+ bool success = navigation_request->net_error() == net::OK;
std::string error_string =
net::ErrorToString(navigation_request->net_error());
navigate_callback->second->sendSuccess(
frame_id,
Maybe<std::string>(
navigation_request->devtools_navigation_token().ToString()),
- success ? Maybe<std::string>(error_string) : Maybe<std::string>());
+ success ? Maybe<std::string>() : Maybe<std::string>(error_string));
navigate_callbacks_.erase(navigate_callback);
}
@@ -664,22 +765,47 @@ Response PageHandler::StartScreencast(Maybe<std::string> format,
frame_counter_ = 0;
frames_in_flight_ = 0;
capture_every_nth_frame_ = every_nth_frame.fromMaybe(1);
-
bool visible = !widget_host->is_hidden();
NotifyScreencastVisibility(visible);
- if (visible) {
- if (has_compositor_frame_metadata_) {
- InnerSwapCompositorFrame();
- } else {
- widget_host->Send(new ViewMsg_ForceRedraw(widget_host->GetRoutingID(),
- ui::LatencyInfo()));
+
+#if !defined(OS_ANDROID)
+ if (video_consumer_) {
+ gfx::Size surface_size = gfx::Size();
+ RenderWidgetHostViewBase* const view =
+ static_cast<RenderWidgetHostViewBase*>(host_->GetView());
+ if (view) {
+ surface_size = view->GetCompositorViewportPixelSize();
+ last_surface_size_ = surface_size;
}
+
+ gfx::Size snapshot_size = DetermineSnapshotSize(
+ surface_size, screencast_max_width_, screencast_max_height_);
+ if (!snapshot_size.IsEmpty())
+ video_consumer_->SetMinAndMaxFrameSize(snapshot_size, snapshot_size);
+
+ video_consumer_->StartCapture();
+ return Response::FallThrough();
+ }
+#endif // !defined(OS_ANDROID)
+
+ if (!visible)
+ return Response::FallThrough();
+
+ if (has_compositor_frame_metadata_) {
+ InnerSwapCompositorFrame();
+ } else {
+ widget_host->Send(new ViewMsg_ForceRedraw(widget_host->GetRoutingID(),
+ ui::LatencyInfo()));
}
return Response::FallThrough();
}
Response PageHandler::StopScreencast() {
screencast_enabled_ = false;
+#if !defined(OS_ANDROID)
+ if (video_consumer_)
+ video_consumer_->StopCapture();
+#endif // !defined(OS_ANDROID)
return Response::FallThrough();
}
@@ -816,45 +942,24 @@ void PageHandler::InnerSwapCompositorFrame() {
if (!view || !view->IsSurfaceAvailableForCopy())
return;
- // Determine the snapshot size that best-fits the Surface's content to the
- // remote's requested image size.
- const gfx::Size& surface_size = view->GetCompositorViewportPixelSize();
+ const gfx::Size surface_size = view->GetCompositorViewportPixelSize();
if (surface_size.IsEmpty())
- return; // Nothing to copy (and avoid divide-by-zero below).
- double scale = 1;
- if (screencast_max_width_ > 0) {
- scale = std::min(scale, static_cast<double>(screencast_max_width_) /
- surface_size.width());
- }
- if (screencast_max_height_ > 0) {
- scale = std::min(scale, static_cast<double>(screencast_max_height_) /
- surface_size.height());
- }
- const gfx::Size snapshot_size =
- gfx::ToRoundedSize(gfx::ScaleSize(gfx::SizeF(surface_size), scale));
- if (snapshot_size.IsEmpty())
return;
- // Build the ScreencastFrameMetadata associated with this capture attempt.
- const auto& metadata = last_compositor_frame_metadata_;
- if (metadata.device_scale_factor == 0)
+ const gfx::Size snapshot_size = DetermineSnapshotSize(
+ surface_size, screencast_max_width_, screencast_max_height_);
+ if (snapshot_size.IsEmpty())
return;
- const gfx::SizeF content_size_dip = gfx::ScaleSize(
- gfx::SizeF(surface_size), 1 / metadata.device_scale_factor);
- float top_offset_dip =
- metadata.top_controls_height * metadata.top_controls_shown_ratio;
- if (IsUseZoomForDSFEnabled())
- top_offset_dip /= metadata.device_scale_factor;
+
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
- Page::ScreencastFrameMetadata::Create()
- .SetPageScaleFactor(metadata.page_scale_factor)
- .SetOffsetTop(top_offset_dip)
- .SetDeviceWidth(content_size_dip.width())
- .SetDeviceHeight(content_size_dip.height())
- .SetScrollOffsetX(metadata.root_scroll_offset.x())
- .SetScrollOffsetY(metadata.root_scroll_offset.y())
- .SetTimestamp(base::Time::Now().ToDoubleT())
- .Build();
+ BuildScreencastFrameMetadata(
+ surface_size, last_compositor_frame_metadata_.device_scale_factor,
+ last_compositor_frame_metadata_.page_scale_factor,
+ last_compositor_frame_metadata_.root_scroll_offset,
+ last_compositor_frame_metadata_.top_controls_height,
+ last_compositor_frame_metadata_.top_controls_shown_ratio);
+ if (!page_metadata)
+ return;
// Request a copy of the surface as a scaled SkBitmap.
view->CopyFromSurface(
@@ -864,6 +969,51 @@ void PageHandler::InnerSwapCompositorFrame() {
frames_in_flight_++;
}
+#if !defined(OS_ANDROID)
+void PageHandler::OnFrameFromVideoConsumer(
+ scoped_refptr<media::VideoFrame> frame) {
+ if (!host_)
+ return;
+
+ RenderWidgetHostViewBase* const view =
+ static_cast<RenderWidgetHostViewBase*>(host_->GetView());
+ if (!view)
+ return;
+
+ const gfx::Size surface_size = view->GetCompositorViewportPixelSize();
+ if (surface_size.IsEmpty())
+ return;
+
+ // If window has been resized, set the new dimensions.
+ if (surface_size != last_surface_size_) {
+ last_surface_size_ = surface_size;
+ gfx::Size snapshot_size = DetermineSnapshotSize(
+ surface_size, screencast_max_width_, screencast_max_height_);
+ if (!snapshot_size.IsEmpty())
+ video_consumer_->SetMinAndMaxFrameSize(snapshot_size, snapshot_size);
+ return;
+ }
+
+ double device_scale_factor, page_scale_factor;
+ gfx::Vector2dF root_scroll_offset;
+ GetMetadataFromFrame(*frame, &device_scale_factor, &page_scale_factor,
+ &root_scroll_offset);
+ // Top controls are only present on Android. Hence use default values of 0.f.
+ // TODO(dgozman): fix this when viz capture is available on Android.
+ const float kTopControlsHeight = 0.f;
+ const float kTopControlsShownRatio = 0.f;
+ std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
+ BuildScreencastFrameMetadata(surface_size, device_scale_factor,
+ page_scale_factor, root_scroll_offset,
+ kTopControlsHeight, kTopControlsShownRatio);
+ if (!page_metadata)
+ return;
+
+ ScreencastFrameCaptured(std::move(page_metadata),
+ DevToolsVideoConsumer::GetSkBitmapFromFrame(frame));
+}
+#endif // !defined(OS_ANDROID)
+
void PageHandler::ScreencastFrameCaptured(
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata,
const SkBitmap& bitmap) {
@@ -963,5 +1113,25 @@ Response PageHandler::StopLoading() {
return Response::OK();
}
+Response PageHandler::SetWebLifecycleState(const std::string& state) {
+ WebContentsImpl* web_contents = GetWebContents();
+ if (!web_contents)
+ return Response::Error("Not attached to a page");
+ if (state == Page::SetWebLifecycleState::StateEnum::Frozen) {
+ // TODO(fmeawad): Instead of forcing a visibility change, only allow
+ // freezing a page if it was already hidden.
+ web_contents->WasHidden();
+ web_contents->FreezePage();
+ return Response::OK();
+ }
+ if (state == Page::SetWebLifecycleState::StateEnum::Active) {
+ // Making the page visible should make it active as visible pages cannot be
+ // frozen.
+ web_contents->WasShown();
+ return Response::OK();
+ }
+ return Response::Error("Unidentified lifecycle state");
+}
+
} // namespace protocol
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index 8e45be2d993..c9c0b1f1ed4 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -15,18 +15,23 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/page.h"
#include "content/public/browser/javascript_dialog_manager.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/common/javascript_dialog_type.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h"
+#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
#include "url/gurl.h"
+#if !defined(OS_ANDROID)
+#include "content/browser/devtools/devtools_video_consumer.h"
+#endif // !defined(OS_ANDROID)
+
class SkBitmap;
namespace base {
@@ -54,7 +59,7 @@ class EmulationHandler;
class PageHandler : public DevToolsDomainHandler,
public Page::Backend,
- public NotificationObserver {
+ public RenderWidgetHostObserver {
public:
explicit PageHandler(EmulationHandler* handler);
~PageHandler() override;
@@ -90,6 +95,7 @@ class PageHandler : public DevToolsDomainHandler,
Response Disable() override;
Response Crash() override;
+ Response Close() override;
Response Reload(Maybe<bool> bypassCache,
Maybe<std::string> script_to_evaluate_on_load) override;
void Navigate(const std::string& url,
@@ -148,12 +154,17 @@ class PageHandler : public DevToolsDomainHandler,
void GetAppManifest(
std::unique_ptr<GetAppManifestCallback> callback) override;
+ Response SetWebLifecycleState(const std::string& state) override;
+
private:
enum EncodingFormat { PNG, JPEG };
WebContentsImpl* GetWebContents();
void NotifyScreencastVisibility(bool visible);
void InnerSwapCompositorFrame();
+#if !defined(OS_ANDROID)
+ void OnFrameFromVideoConsumer(scoped_refptr<media::VideoFrame> frame);
+#endif // !defined(OS_ANDROID)
void ScreencastFrameCaptured(
std::unique_ptr<Page::ScreencastFrameMetadata> metadata,
const SkBitmap& bitmap);
@@ -174,10 +185,10 @@ class PageHandler : public DevToolsDomainHandler,
const GURL& manifest_url,
blink::mojom::ManifestDebugInfoPtr debug_info);
- // NotificationObserver overrides.
- void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) override;
+ // RenderWidgetHostObserver overrides.
+ void RenderWidgetHostVisibilityChanged(RenderWidgetHost* widget_host,
+ bool became_visible) override;
+ void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override;
bool enabled_;
@@ -195,10 +206,21 @@ class PageHandler : public DevToolsDomainHandler,
int frame_counter_;
int frames_in_flight_;
+#if !defined(OS_ANDROID)
+ // |video_consumer_| consumes video frames from FrameSinkVideoCapturerImpl,
+ // and provides PageHandler with these frames via OnFrameFromVideoConsumer.
+ // This is only used if Viz is enabled and if OS is not Android.
+ std::unique_ptr<DevToolsVideoConsumer> video_consumer_;
+
+ // The last surface size used to determine if frames with new sizes need
+ // to be requested. This changes due to window resizing.
+ gfx::Size last_surface_size_;
+#endif // !defined(OS_ANDROID)
+
RenderFrameHostImpl* host_;
EmulationHandler* emulation_handler_;
std::unique_ptr<Page::Frontend> frontend_;
- NotificationRegistrar registrar_;
+ ScopedObserver<RenderWidgetHost, RenderWidgetHostObserver> observer_;
JavaScriptDialogCallback pending_dialog_;
scoped_refptr<DevToolsDownloadManagerDelegate> download_manager_delegate_;
base::flat_map<base::UnguessableToken, std::unique_ptr<NavigateCallback>>
diff --git a/chromium/content/browser/devtools/protocol/system_info_handler.cc b/chromium/content/browser/devtools/protocol/system_info_handler.cc
index 3a90a35db77..618ad4a9f24 100644
--- a/chromium/content/browser/devtools/protocol/system_info_handler.cc
+++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc
@@ -184,7 +184,8 @@ class SystemInfoHandlerGpuObserver : public content::GpuDataManagerObserver {
// TODO(zmo): CHECK everywhere once https://crbug.com/796386 is fixed.
gpu::GpuFeatureInfo gpu_feature_info =
gpu::ComputeGpuFeatureInfoWithHardwareAccelerationDisabled();
- GpuDataManagerImpl::GetInstance()->UpdateGpuFeatureInfo(gpu_feature_info);
+ GpuDataManagerImpl::GetInstance()->UpdateGpuFeatureInfo(gpu_feature_info,
+ base::nullopt);
UnregisterAndSendResponse();
#else
CHECK(false) << "Gathering system GPU info took more than 5 seconds.";
diff --git a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
index 3d4b128b294..c194d824988 100644
--- a/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
+++ b/chromium/content/browser/devtools/protocol/target_auto_attacher.cc
@@ -25,11 +25,11 @@ void GetMatchingHostsByScopeMap(
const ServiceWorkerDevToolsAgentHost::List& agent_hosts,
const base::flat_set<GURL>& urls,
ScopeAgentsMap* scope_agents_map) {
- base::flat_set<base::StringPiece> host_name_set;
+ base::flat_set<GURL> host_name_set;
for (const GURL& url : urls)
- host_name_set.insert(url.host_piece());
+ host_name_set.insert(url.GetOrigin());
for (const auto& host : agent_hosts) {
- if (host_name_set.find(host->scope().host_piece()) == host_name_set.end())
+ if (host_name_set.find(host->scope().GetOrigin()) == host_name_set.end())
continue;
const auto& it = scope_agents_map->find(host->scope());
if (it == scope_agents_map->end()) {
diff --git a/chromium/content/browser/devtools/protocol/target_handler.cc b/chromium/content/browser/devtools/protocol/target_handler.cc
index 371456d2fb7..1ebf94ff0ef 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.cc
+++ b/chromium/content/browser/devtools/protocol/target_handler.cc
@@ -10,6 +10,7 @@
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/navigation_throttle.h"
@@ -32,6 +33,8 @@ std::unique_ptr<Target::TargetInfo> CreateInfo(DevToolsAgentHost* host) {
.Build();
if (!host->GetOpenerId().empty())
target_info->SetOpenerId(host->GetOpenerId());
+ if (host->GetBrowserContext())
+ target_info->SetBrowserContextId(host->GetBrowserContext()->UniqueId());
return target_info;
}
@@ -389,8 +392,12 @@ Response TargetHandler::CreateBrowserContext(std::string* out_context_id) {
return Response::Error("Not supported");
}
-Response TargetHandler::DisposeBrowserContext(const std::string& context_id,
- bool* out_success) {
+Response TargetHandler::DisposeBrowserContext(const std::string& context_id) {
+ return Response::Error("Not supported");
+}
+
+Response TargetHandler::GetBrowserContexts(
+ std::unique_ptr<protocol::Array<String>>* browser_context_ids) {
return Response::Error("Not supported");
}
diff --git a/chromium/content/browser/devtools/protocol/target_handler.h b/chromium/content/browser/devtools/protocol/target_handler.h
index 6bb18ca0d7b..7d75e62ad4c 100644
--- a/chromium/content/browser/devtools/protocol/target_handler.h
+++ b/chromium/content/browser/devtools/protocol/target_handler.h
@@ -63,8 +63,9 @@ class TargetHandler : public DevToolsDomainHandler,
Response CloseTarget(const std::string& target_id,
bool* out_success) override;
Response CreateBrowserContext(std::string* out_context_id) override;
- Response DisposeBrowserContext(const std::string& context_id,
- bool* out_success) override;
+ Response DisposeBrowserContext(const std::string& context_id) override;
+ Response GetBrowserContexts(
+ std::unique_ptr<protocol::Array<String>>* browser_context_ids) override;
Response CreateTarget(const std::string& url,
Maybe<int> width,
Maybe<int> height,
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index ea314dff3c0..3435d90b298 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -23,11 +23,12 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event_impl.h"
#include "base/trace_event/tracing_agent.h"
-#include "components/tracing/common/trace_config_file.h"
+#include "components/tracing/common/trace_startup_config.h"
#include "components/viz/common/features.h"
#include "content/browser/devtools/devtools_frame_trace_recorder.h"
#include "content/browser/devtools/devtools_io_context.h"
#include "content/browser/devtools/devtools_session.h"
+#include "content/browser/devtools/devtools_stream_file.h"
#include "content/browser/devtools/devtools_traceable_screenshot.h"
#include "content/browser/devtools/devtools_video_consumer.h"
#include "content/browser/frame_host/frame_tree.h"
@@ -125,7 +126,7 @@ class DevToolsStreamEndpoint : public TracingController::TraceDataEndpoint {
public:
explicit DevToolsStreamEndpoint(
base::WeakPtr<TracingHandler> handler,
- const scoped_refptr<DevToolsIOContext::RWStream>& stream)
+ const scoped_refptr<DevToolsStreamFile>& stream)
: stream_(stream), tracing_handler_(handler) {}
void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
@@ -156,7 +157,7 @@ class DevToolsStreamEndpoint : public TracingController::TraceDataEndpoint {
private:
~DevToolsStreamEndpoint() override {}
- scoped_refptr<DevToolsIOContext::RWStream> stream_;
+ scoped_refptr<DevToolsStreamFile> stream_;
base::WeakPtr<TracingHandler> tracing_handler_;
};
@@ -169,8 +170,7 @@ void SendProcessReadyInBrowserEvent(const base::UnguessableToken& frame_token,
auto data = std::make_unique<base::trace_event::TracedValue>();
data->SetString("frame", frame_token.ToString());
data->SetString("processPseudoId", GetProcessHostHex(host));
- data->SetInteger("processId",
- static_cast<int>(base::GetProcId(host->GetHandle())));
+ data->SetInteger("processId", static_cast<int>(host->GetProcess().Pid()));
TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
"ProcessReadyInBrowser", TRACE_EVENT_SCOPE_THREAD,
"data", std::move(data));
@@ -190,7 +190,7 @@ void FillFrameData(base::trace_event::TracedValue* data,
node->parent()->devtools_frame_token().ToString());
if (frame_host) {
RenderProcessHost* process_host = frame_host->GetProcess();
- base::ProcessId process_id = base::GetProcId(process_host->GetHandle());
+ base::ProcessId process_id = process_host->GetProcess().Pid();
if (process_id == base::kNullProcessId) {
data->SetString("processPseudoId", GetProcessHostHex(process_host));
frame_host->GetProcess()->PostTaskWhenProcessIsReady(
@@ -423,8 +423,9 @@ void TracingHandler::End(std::unique_ptr<EndCallback> callback) {
scoped_refptr<TracingController::TraceDataEndpoint> endpoint;
if (return_as_stream_) {
endpoint = new DevToolsStreamEndpoint(
- weak_factory_.GetWeakPtr(), io_context_->CreateTempFileBackedStream(
- gzip_compression_ /* binary */));
+ weak_factory_.GetWeakPtr(),
+ DevToolsStreamFile::Create(io_context_,
+ gzip_compression_ /* binary */));
if (gzip_compression_) {
endpoint = TracingControllerImpl::CreateCompressedStringEndpoint(
endpoint, true /* compress_with_background_priority */);
@@ -620,7 +621,7 @@ void TracingHandler::FrameDeleted(RenderFrameHostImpl* frame_host) {
// static
bool TracingHandler::IsStartupTracingActive() {
- return ::tracing::TraceConfigFile::GetInstance()->IsEnabled();
+ return ::tracing::TraceStartupConfig::GetInstance()->IsEnabled();
}
// static
diff --git a/chromium/content/browser/devtools/protocol_config.json b/chromium/content/browser/devtools/protocol_config.json
index f40789fe6f4..90c595d05dc 100644
--- a/chromium/content/browser/devtools/protocol_config.json
+++ b/chromium/content/browser/devtools/protocol_config.json
@@ -36,19 +36,20 @@
},
{
"domain": "Memory",
- "include": ["getBrowserSamplingProfile", "setPressureNotificationsSuppressed", "simulatePressureNotification"]
+ "include": ["getBrowserSamplingProfile", "setPressureNotificationsSuppressed", "simulatePressureNotification", "prepareForLeakDetection"],
+ "async": ["prepareForLeakDetection"]
},
{
"domain": "Network",
- "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "setUserAgentOverride", "setExtraHTTPHeaders", "canEmulateNetworkConditions", "emulateNetworkConditions", "setBypassServiceWorker", "setRequestInterception", "continueInterceptedRequest", "getResponseBodyForInterception", "setCacheDisabled"],
- "include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted"],
- "async": ["clearBrowserCookies", "clearBrowserCache", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "continueInterceptedRequest", "getResponseBodyForInterception"]
+ "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "setUserAgentOverride", "setExtraHTTPHeaders", "canEmulateNetworkConditions", "emulateNetworkConditions", "setBypassServiceWorker", "setRequestInterception", "continueInterceptedRequest", "getResponseBodyForInterception", "setCacheDisabled", "takeResponseBodyForInterceptionAsStream"],
+ "include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted", "signedExchangeReceived"],
+ "async": ["clearBrowserCookies", "clearBrowserCache", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "continueInterceptedRequest", "getResponseBodyForInterception", "takeResponseBodyForInterceptionAsStream"]
},
{
"domain": "Page",
"include": ["enable", "disable", "reload", "navigate", "stopLoading", "getNavigationHistory", "navigateToHistoryEntry", "captureScreenshot",
"startScreencast", "stopScreencast", "screencastFrameAck", "handleJavaScriptDialog", "setColorPickerEnabled", "requestAppBanner",
- "printToPDF", "bringToFront", "setDownloadBehavior", "getAppManifest", "crash"],
+ "printToPDF", "bringToFront", "setDownloadBehavior", "getAppManifest", "crash", "close", "setWebLifecycleState"],
"include_events": ["colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "screencastVisibilityChanged", "screencastFrame"],
"async": ["captureScreenshot", "printToPDF", "navigate", "getAppManifest"]
},
diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
index f6977596a09..8c663d94e92 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -41,6 +41,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/web_package/signed_exchange_header.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -54,6 +55,7 @@
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
+#include "net/ssl/ssl_info.h"
#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
@@ -215,12 +217,62 @@ void RenderFrameDevToolsAgentHost::OnNavigationResponseReceived(
// static
void RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(
const NavigationRequest& nav_request,
- int error_code) {
+ const network::URLLoaderCompletionStatus& status) {
FrameTreeNode* ftn = nav_request.frame_tree_node();
std::string id = nav_request.devtools_navigation_token().ToString();
DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id,
- protocol::Page::ResourceTypeEnum::Document,
- network::URLLoaderCompletionStatus(error_code));
+ protocol::Page::ResourceTypeEnum::Document, status);
+}
+
+// static
+void RenderFrameDevToolsAgentHost::OnSignedExchangeReceived(
+ FrameTreeNode* frame_tree_node,
+ base::Optional<const base::UnguessableToken> devtools_navigation_token,
+ const GURL& outer_request_url,
+ const network::ResourceResponseHead& outer_response,
+ const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ const std::vector<std::string>& error_messages) {
+ DispatchToAgents(frame_tree_node,
+ &protocol::NetworkHandler::OnSignedExchangeReceived,
+ devtools_navigation_token, outer_request_url, outer_response,
+ header, ssl_info, error_messages);
+}
+
+// static
+void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestSent(
+ FrameTreeNode* frame_tree_node,
+ const base::UnguessableToken& request_id,
+ const base::UnguessableToken& loader_id,
+ const network::ResourceRequest& request,
+ const GURL& signed_exchange_url) {
+ DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::RequestSent,
+ request_id.ToString(), loader_id.ToString(), request,
+ protocol::Network::Initiator::TypeEnum::SignedExchange,
+ signed_exchange_url);
+}
+
+// static
+void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateResponseReceived(
+ FrameTreeNode* frame_tree_node,
+ const base::UnguessableToken& request_id,
+ const base::UnguessableToken& loader_id,
+ const GURL& url,
+ const network::ResourceResponseHead& head) {
+ DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::ResponseReceived,
+ request_id.ToString(), loader_id.ToString(), url,
+ protocol::Page::ResourceTypeEnum::Other, head,
+ protocol::Maybe<std::string>());
+}
+
+// static
+void RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestCompleted(
+ FrameTreeNode* frame_tree_node,
+ const base::UnguessableToken& request_id,
+ const network::URLLoaderCompletionStatus& status) {
+ DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::LoadingComplete,
+ request_id.ToString(),
+ protocol::Page::ResourceTypeEnum::Other, status);
}
// static
@@ -296,6 +348,7 @@ void RenderFrameDevToolsAgentHost::ApplyOverrides(
bool RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
RenderFrameHostImpl* rfh,
bool is_navigation,
+ bool is_download,
network::mojom::URLLoaderFactoryRequest* target_factory_request) {
FrameTreeNode* frame_tree_node = rfh->frame_tree_node();
base::UnguessableToken frame_token = frame_tree_node->devtools_frame_token();
@@ -304,9 +357,10 @@ bool RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
if (!agent_host)
return false;
int process_id = is_navigation ? 0 : rfh->GetProcess()->GetID();
+ DCHECK(!is_download || is_navigation);
for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
- if (network->MaybeCreateProxyForInterception(frame_token, process_id,
- target_factory_request)) {
+ if (network->MaybeCreateProxyForInterception(
+ frame_token, process_id, is_download, target_factory_request)) {
return true;
}
}
@@ -384,7 +438,8 @@ bool RenderFrameDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AddHandler(base::WrapUnique(new protocol::IOHandler(
GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::MemoryHandler()));
- session->AddHandler(base::WrapUnique(new protocol::NetworkHandler(GetId())));
+ session->AddHandler(
+ base::WrapUnique(new protocol::NetworkHandler(GetId(), GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::SchemaHandler()));
session->AddHandler(base::WrapUnique(new protocol::ServiceWorkerHandler()));
session->AddHandler(base::WrapUnique(new protocol::StorageHandler()));
diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
index afd61919b40..d4c77584e64 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -7,11 +7,13 @@
#include <map>
#include <memory>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "build/build_config.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/common/content_export.h"
@@ -26,6 +28,10 @@
#include "ui/android/view_android.h"
#endif // OS_ANDROID
+namespace base {
+class UnguessableToken;
+}
+
namespace network {
struct ResourceResponse;
}
@@ -34,6 +40,10 @@ namespace viz {
class CompositorFrameMetadata;
}
+namespace net {
+class SSLInfo;
+}
+
namespace content {
class BrowserContext;
@@ -43,6 +53,7 @@ class NavigationHandleImpl;
class NavigationRequest;
class NavigationThrottle;
class RenderFrameHostImpl;
+class SignedExchangeHeader;
class CONTENT_EXPORT RenderFrameDevToolsAgentHost
: public DevToolsAgentHostImpl,
@@ -73,6 +84,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
static bool WillCreateURLLoaderFactory(
RenderFrameHostImpl* rfh,
bool is_navigation,
+ bool is_download,
network::mojom::URLLoaderFactoryRequest* loader_factory_request);
static void OnNavigationRequestWillBeSent(
@@ -80,8 +92,34 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
static void OnNavigationResponseReceived(
const NavigationRequest& nav_request,
const network::ResourceResponse& response);
- static void OnNavigationRequestFailed(const NavigationRequest& nav_request,
- int error_code);
+ static void OnNavigationRequestFailed(
+ const NavigationRequest& nav_request,
+ const network::URLLoaderCompletionStatus& status);
+
+ static void OnSignedExchangeReceived(
+ FrameTreeNode* frame_tree_node,
+ base::Optional<const base::UnguessableToken> devtools_navigation_token,
+ const GURL& outer_request_url,
+ const network::ResourceResponseHead& outer_response,
+ const base::Optional<SignedExchangeHeader>& header,
+ const base::Optional<net::SSLInfo>& ssl_info,
+ const std::vector<std::string>& error_messages);
+ static void OnSignedExchangeCertificateRequestSent(
+ FrameTreeNode* frame_tree_node,
+ const base::UnguessableToken& request_id,
+ const base::UnguessableToken& loader_id,
+ const network::ResourceRequest& request,
+ const GURL& signed_exchange_url);
+ static void OnSignedExchangeCertificateResponseReceived(
+ FrameTreeNode* frame_tree_node,
+ const base::UnguessableToken& request_id,
+ const base::UnguessableToken& loader_id,
+ const GURL& url,
+ const network::ResourceResponseHead& head);
+ static void OnSignedExchangeCertificateRequestCompleted(
+ FrameTreeNode* frame_tree_node,
+ const base::UnguessableToken& request_id,
+ const network::URLLoaderCompletionStatus& status);
static std::vector<std::unique_ptr<NavigationThrottle>>
CreateNavigationThrottles(NavigationHandleImpl* navigation_handle);
diff --git a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
index b4886cc9754..64801cf7cda 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -126,7 +126,8 @@ bool ServiceWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AttachToAgent(agent_ptr_);
}
session->AddHandler(base::WrapUnique(new protocol::InspectorHandler()));
- session->AddHandler(base::WrapUnique(new protocol::NetworkHandler(GetId())));
+ session->AddHandler(
+ base::WrapUnique(new protocol::NetworkHandler(GetId(), GetIOContext())));
session->AddHandler(base::WrapUnique(new protocol::SchemaHandler()));
return true;
}
diff --git a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
index 456e9938e8e..453f52c6da9 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
@@ -72,6 +72,8 @@ class ServiceWorkerDevToolsAgentHost : public DevToolsAgentHostImpl {
// Returns the time when the ServiceWorker was doomed.
base::Time version_doomed_time() const { return version_doomed_time_; }
+ int64_t version_id() const { return version_id_; }
+
bool Matches(const ServiceWorkerContextCore* context, int64_t version_id);
private:
diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.cc b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
index 3414d0e9e9a..60007e08358 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_manager.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
@@ -188,7 +188,8 @@ void ServiceWorkerDevToolsManager::NavigationPreloadRequestSent(
for (auto* network :
protocol::NetworkHandler::ForAgentHost(it->second.get())) {
network->RequestSent(request_id, std::string(), request,
- protocol::Network::Initiator::TypeEnum::Preload);
+ protocol::Network::Initiator::TypeEnum::Preload,
+ base::nullopt /* initiator_url */);
}
}
diff --git a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
index 485edd42a67..fd40420eed3 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -68,7 +68,8 @@ bool SharedWorkerDevToolsAgentHost::Close() {
bool SharedWorkerDevToolsAgentHost::AttachSession(DevToolsSession* session) {
session->AddHandler(std::make_unique<protocol::InspectorHandler>());
- session->AddHandler(std::make_unique<protocol::NetworkHandler>(GetId()));
+ session->AddHandler(
+ std::make_unique<protocol::NetworkHandler>(GetId(), GetIOContext()));
session->AddHandler(std::make_unique<protocol::SchemaHandler>());
session->SetRenderer(worker_host_ ? worker_host_->process_id() : -1, nullptr);
if (state_ == WORKER_READY)
diff --git a/chromium/content/browser/dom_storage/OWNERS b/chromium/content/browser/dom_storage/OWNERS
index 1e82b965531..19d6324eaf3 100644
--- a/chromium/content/browser/dom_storage/OWNERS
+++ b/chromium/content/browser/dom_storage/OWNERS
@@ -1,8 +1,5 @@
dmurph@chromium.org
mek@chromium.org
-# OOO until this comment is removed.
-michaeln@chromium.org
-
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>DOMStorage
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
index 8089997ca7b..efa6d8dc10f 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -283,6 +283,19 @@ DOMStorageContextWrapper::RecreateSessionStorage(
}
void DOMStorageContextWrapper::StartScavengingUnusedSessionStorage() {
+ if (mojo_session_state_) {
+ // base::Unretained is safe here, because the mojo_session_state_ won't be
+ // deleted until a ShutdownAndDelete task has been ran on the
+ // mojo_task_runner_, and as soon as that task is posted,
+ // mojo_session_state_ is set to null, preventing further tasks from being
+ // queued.
+ mojo_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SessionStorageContextMojo::ScavengeUnusedNamespaces,
+ base::Unretained(mojo_session_state_),
+ base::OnceClosure()));
+ return;
+ }
DCHECK(context_.get());
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
@@ -305,12 +318,6 @@ void DOMStorageContextWrapper::SetForceKeepSessionState() {
FROM_HERE,
base::BindOnce(&LocalStorageContextMojo::SetForceKeepSessionState,
base::Unretained(mojo_state_)));
- if (mojo_session_state_) {
- mojo_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&SessionStorageContextMojo::SetForceKeepSessionState,
- base::Unretained(mojo_session_state_)));
- }
}
void DOMStorageContextWrapper::Shutdown() {
diff --git a/chromium/content/browser/dom_storage/dom_storage_database.h b/chromium/content/browser/dom_storage/dom_storage_database.h
index 122b6646826..5ea7d79329b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database.h
+++ b/chromium/content/browser/dom_storage/dom_storage_database.h
@@ -123,6 +123,8 @@ class CONTENT_EXPORT DOMStorageDatabase {
bool failed_to_open_;
bool tried_to_recreate_;
bool known_to_be_empty_;
+
+ DISALLOW_COPY_AND_ASSIGN(DOMStorageDatabase);
};
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
index 38e62495ad3..5226a1a7a26 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
@@ -310,12 +310,18 @@ TEST(DOMStorageDatabaseTest, TestSimpleRemoveOneValue) {
TEST(DOMStorageDatabaseTest, TestCanOpenAndReadWebCoreDatabase) {
base::FilePath dir_test_data;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
- base::FilePath webcore_database = dir_test_data.AppendASCII("dom_storage");
- webcore_database =
- webcore_database.AppendASCII("webcore_test_database.localstorage");
+ ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &dir_test_data));
+ base::FilePath test_data = dir_test_data.AppendASCII("dom_storage");
+ test_data = test_data.AppendASCII("webcore_test_database.localstorage");
+ ASSERT_TRUE(base::PathExists(test_data));
- ASSERT_TRUE(base::PathExists(webcore_database));
+ // Create a temporary copy of the WebCore test database, in case DIR_TEST_DATA
+ // is read-only.
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath webcore_database =
+ temp_dir.GetPath().AppendASCII("dom_storage");
+ ASSERT_TRUE(base::CopyFile(test_data, webcore_database));
DOMStorageDatabase db(webcore_database);
DOMStorageValuesMap values;
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
index c6975829bbe..369046443da 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -679,7 +679,7 @@ void LocalStorageContextMojo::InitiateConnection(bool in_memory_only) {
// We were not given a subdirectory. Use a memory backed database.
connector_->BindInterface(file::mojom::kServiceName, &leveldb_service_);
leveldb_service_->OpenInMemory(
- memory_dump_id_, MakeRequest(&database_),
+ memory_dump_id_, "local-storage", MakeRequest(&database_),
base::BindOnce(&LocalStorageContextMojo::OnDatabaseOpened,
weak_ptr_factory_.GetWeakPtr(), true));
}
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo.h b/chromium/content/browser/dom_storage/local_storage_context_mojo.h
index 2d7799a7920..3670af2a646 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo.h
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo.h
@@ -134,7 +134,6 @@ class CONTENT_EXPORT LocalStorageContextMojo
void GetStatistics(size_t* total_cache_size, size_t* unused_wrapper_count);
void OnCommitResult(leveldb::mojom::DatabaseError error);
- void OnReconnectedToDB();
// These values are written to logs. New enum values can be added, but
// existing enums must never be renumbered or deleted and reused.
diff --git a/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
index 1603bdb3282..b758d40ec16 100644
--- a/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
+++ b/chromium/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -10,6 +10,7 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
#include "build/build_config.h"
#include "components/services/filesystem/public/interfaces/file_system.mojom.h"
#include "components/services/leveldb/public/cpp/util.h"
@@ -18,12 +19,16 @@
#include "content/browser/dom_storage/dom_storage_database.h"
#include "content/browser/dom_storage/dom_storage_namespace.h"
#include "content/browser/dom_storage/dom_storage_task_runner.h"
+#include "content/browser/dom_storage/test/fake_leveldb_database_error_on_write.h"
+#include "content/browser/dom_storage/test/fake_leveldb_service.h"
+#include "content/browser/dom_storage/test/mojo_test_with_file_service.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "content/test/fake_leveldb_database.h"
+#include "content/test/leveldb_wrapper_test_util.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
@@ -32,7 +37,7 @@
#include "services/file/public/mojom/constants.mojom.h"
#include "services/file/user_id_map.h"
#include "services/service_manager/public/cpp/service_context.h"
-#include "services/service_manager/public/cpp/service_test.h"
+#include "services/service_manager/public/cpp/test/test_service_decorator.h"
#include "services/service_manager/public/mojom/service_factory.mojom.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -45,34 +50,19 @@ using leveldb::Uint8VectorToStdString;
namespace content {
namespace {
+using test::FakeLevelDBService;
+using test::FakeLevelDBDatabaseErrorOnWrite;
+
// An empty namespace is the local storage namespace.
constexpr const char kLocalStorageNamespaceId[] = "";
-void SuccessCallback(base::OnceClosure callback,
- bool* success_out,
- bool success) {
- if (success_out)
- *success_out = success;
- std::move(callback).Run();
-}
-
-void GetStorageUsageCallback(const base::Closure& callback,
+void GetStorageUsageCallback(const base::RepeatingClosure& callback,
std::vector<LocalStorageUsageInfo>* out_result,
std::vector<LocalStorageUsageInfo> result) {
*out_result = std::move(result);
callback.Run();
}
-void GetCallback(const base::Closure& callback,
- bool* success_out,
- std::vector<uint8_t>* value_out,
- bool success,
- const std::vector<uint8_t>& value) {
- *success_out = success;
- *value_out = value;
- callback.Run();
-}
-
class TestLevelDBObserver : public mojom::LevelDBObserver {
public:
struct Observation {
@@ -123,29 +113,6 @@ class TestLevelDBObserver : public mojom::LevelDBObserver {
mojo::AssociatedBinding<mojom::LevelDBObserver> binding_;
};
-class GetAllCallback : public mojom::LevelDBWrapperGetAllCallback {
- public:
- static mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo CreateAndBind(
- base::OnceClosure callback) {
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo ptr_info;
- auto request = mojo::MakeRequest(&ptr_info);
- mojo::MakeStrongAssociatedBinding(
- base::WrapUnique(new GetAllCallback(std::move(callback))),
- std::move(request));
- return ptr_info;
- }
-
- private:
- GetAllCallback(base::OnceClosure callback) : callback_(std::move(callback)) {}
-
- void Complete(bool success) override {
- EXPECT_TRUE(success);
- std::move(callback_).Run();
- }
-
- base::OnceClosure callback_;
-};
-
} // namespace
class LocalStorageContextMojoTest : public testing::Test {
@@ -223,12 +190,8 @@ class LocalStorageContextMojoTest : public testing::Test {
mojom::LevelDBWrapperPtr dummy_wrapper; // To make sure values are cached.
context()->OpenLocalStorage(kOrigin, MakeRequest(&wrapper));
context()->OpenLocalStorage(kOrigin, MakeRequest(&dummy_wrapper));
- base::RunLoop run_loop;
- bool success = false;
std::vector<uint8_t> result;
- wrapper->Get(key, base::BindOnce(&GetCallback, run_loop.QuitClosure(),
- &success, &result));
- run_loop.Run();
+ bool success = test::GetSync(wrapper.get(), key, &result);
return success ? base::Optional<std::vector<uint8_t>>(result)
: base::nullopt;
}
@@ -668,25 +631,17 @@ TEST_F(LocalStorageContextMojoTest, Migration) {
EXPECT_FALSE(mock_data().empty());
{
- base::RunLoop run_loop;
- bool success = false;
std::vector<uint8_t> result;
- wrapper->Get(LocalStorageContextMojo::MigrateString(key),
- base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
- &result));
- run_loop.Run();
+ bool success = test::GetSync(
+ wrapper.get(), LocalStorageContextMojo::MigrateString(key), &result);
EXPECT_TRUE(success);
EXPECT_EQ(LocalStorageContextMojo::MigrateString(value), result);
}
{
- base::RunLoop run_loop;
- bool success = false;
std::vector<uint8_t> result;
- wrapper->Get(LocalStorageContextMojo::MigrateString(key2),
- base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
- &result));
- run_loop.Run();
+ bool success = test::GetSync(
+ wrapper.get(), LocalStorageContextMojo::MigrateString(key2), &result);
EXPECT_TRUE(success);
EXPECT_EQ(LocalStorageContextMojo::MigrateString(value), result);
}
@@ -730,25 +685,18 @@ TEST_F(LocalStorageContextMojoTest, FixUp) {
MakeRequest(&dummy_wrapper));
{
- base::RunLoop run_loop;
- bool success = false;
std::vector<uint8_t> result;
- wrapper->Get(leveldb::StdStringToUint8Vector("\x01key"),
- base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
- &result));
- run_loop.Run();
+ bool success = test::GetSync(
+ wrapper.get(), leveldb::StdStringToUint8Vector("\x01key"), &result);
EXPECT_TRUE(success);
EXPECT_EQ(leveldb::StdStringToUint8Vector("value1"), result);
}
{
- base::RunLoop run_loop;
- bool success = false;
std::vector<uint8_t> result;
- wrapper->Get(leveldb::StdStringToUint8Vector("\x01"
- "foo"),
- base::BindOnce(&GetCallback, run_loop.QuitClosure(), &success,
- &result));
- run_loop.Run();
+ bool success = test::GetSync(wrapper.get(),
+ leveldb::StdStringToUint8Vector("\x01"
+ "foo"),
+ &result);
EXPECT_TRUE(success);
EXPECT_EQ(leveldb::StdStringToUint8Vector("value3"), result);
}
@@ -798,82 +746,13 @@ TEST_F(LocalStorageContextMojoTest, ShutdownClearsData) {
}
}
-namespace {
-
-class ServiceTestClient : public service_manager::test::ServiceTestClient,
- public service_manager::mojom::ServiceFactory {
- public:
- explicit ServiceTestClient(service_manager::test::ServiceTest* test)
- : service_manager::test::ServiceTestClient(test) {
- registry_.AddInterface<service_manager::mojom::ServiceFactory>(base::Bind(
- &ServiceTestClient::BindServiceFactoryRequest, base::Unretained(this)));
- }
- ~ServiceTestClient() override {}
-
- protected:
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override {
- registry_.BindInterface(interface_name, std::move(interface_pipe));
- }
-
- void CreateService(
- service_manager::mojom::ServiceRequest request,
- const std::string& name,
- service_manager::mojom::PIDReceiverPtr pid_receiver) override {
- if (name == file::mojom::kServiceName) {
- file_service_context_.reset(new service_manager::ServiceContext(
- file::CreateFileService(), std::move(request)));
- }
- }
-
- void BindServiceFactoryRequest(
- service_manager::mojom::ServiceFactoryRequest request) {
- service_factory_bindings_.AddBinding(this, std::move(request));
- }
-
- private:
- service_manager::BinderRegistry registry_;
- mojo::BindingSet<service_manager::mojom::ServiceFactory>
- service_factory_bindings_;
- std::unique_ptr<service_manager::ServiceContext> file_service_context_;
-};
-
-} // namespace
-
class LocalStorageContextMojoTestWithService
- : public service_manager::test::ServiceTest {
+ : public test::MojoTestWithFileService {
public:
- LocalStorageContextMojoTestWithService() : ServiceTest("content_unittests") {}
+ LocalStorageContextMojoTestWithService() {}
~LocalStorageContextMojoTestWithService() override {}
protected:
- void SetUp() override {
- ServiceTest::SetUp();
- ASSERT_TRUE(temp_path_.CreateUniqueTempDir());
- file::AssociateServiceUserIdWithUserDir(test_userid(),
- temp_path_.GetPath());
- }
-
- void TearDown() override {
- service_manager::ServiceContext::ClearGlobalBindersForTesting(
- file::mojom::kServiceName);
- ServiceTest::TearDown();
- }
-
- std::unique_ptr<service_manager::Service> CreateService() override {
- return std::make_unique<ServiceTestClient>(this);
- }
-
- const base::FilePath& temp_path() { return temp_path_.GetPath(); }
-
- base::FilePath FirstEntryInDir() {
- base::FileEnumerator enumerator(
- temp_path(), false /* recursive */,
- base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
- return enumerator.Next();
- }
-
void DoTestPut(LocalStorageContextMojo* context,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value) {
@@ -882,9 +761,8 @@ class LocalStorageContextMojoTestWithService
base::RunLoop run_loop;
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
MakeRequest(&wrapper));
- wrapper->Put(
- key, value, base::nullopt, "source",
- base::BindOnce(&SuccessCallback, run_loop.QuitClosure(), &success));
+ wrapper->Put(key, value, base::nullopt, "source",
+ test::MakeSuccessCallback(run_loop.QuitClosure(), &success));
run_loop.Run();
EXPECT_TRUE(success);
wrapper.reset();
@@ -900,15 +778,14 @@ class LocalStorageContextMojoTestWithService
base::RunLoop run_loop;
std::vector<content::mojom::KeyValuePtr> data;
- auto callback = [](std::vector<content::mojom::KeyValuePtr>* data_out,
- leveldb::mojom::DatabaseError status,
- std::vector<content::mojom::KeyValuePtr> data) {
- EXPECT_EQ(status, leveldb::mojom::DatabaseError::OK);
- data_out->swap(data);
- };
- wrapper->GetAll(GetAllCallback::CreateAndBind(run_loop.QuitClosure()),
- base::BindOnce(callback, &data));
+ leveldb::mojom::DatabaseError status;
+ bool done = false;
+ wrapper->GetAll(
+ test::GetAllCallback::CreateAndBind(&done, run_loop.QuitClosure()),
+ test::MakeGetAllCallback(&status, &data));
run_loop.Run();
+ EXPECT_TRUE(done);
+ EXPECT_EQ(status, leveldb::mojom::DatabaseError::OK);
for (auto& entry : data) {
if (key == entry->key) {
@@ -920,9 +797,14 @@ class LocalStorageContextMojoTestWithService
return false;
}
- private:
- base::ScopedTempDir temp_path_;
+ base::FilePath FirstEntryInDir() {
+ base::FileEnumerator enumerator(
+ temp_path(), false /* recursive */,
+ base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
+ return enumerator.Next();
+ }
+ private:
DISALLOW_COPY_AND_ASSIGN(LocalStorageContextMojoTestWithService);
};
@@ -1115,99 +997,15 @@ TEST_F(LocalStorageContextMojoTestWithService, CorruptionOnDisk) {
context->ShutdownAndDelete();
}
-namespace {
-
-class FakeLevelDBService : public leveldb::mojom::LevelDBService {
- public:
- void Open(filesystem::mojom::DirectoryPtr,
- const std::string& dbname,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
- memory_dump_id,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest request,
- OpenCallback callback) override {
- open_requests_.push_back(
- {false, dbname, std::move(request), std::move(callback)});
- if (on_open_callback_)
- on_open_callback_.Run();
- }
-
- void OpenWithOptions(
- const leveldb_env::Options& options,
- filesystem::mojom::DirectoryPtr,
- const std::string& dbname,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
- memory_dump_id,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest request,
- OpenCallback callback) override {
- open_requests_.push_back(
- {false, dbname, std::move(request), std::move(callback)});
- if (on_open_callback_)
- on_open_callback_.Run();
- }
-
- void OpenInMemory(
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
- memory_dump_id,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest request,
- OpenCallback callback) override {
- open_requests_.push_back(
- {true, "", std::move(request), std::move(callback)});
- if (on_open_callback_)
- on_open_callback_.Run();
- }
-
- void Destroy(filesystem::mojom::DirectoryPtr,
- const std::string& dbname,
- DestroyCallback callback) override {
- destroy_requests_.push_back({dbname});
- std::move(callback).Run(leveldb::mojom::DatabaseError::OK);
- }
-
- struct OpenRequest {
- bool in_memory;
- std::string dbname;
- leveldb::mojom::LevelDBDatabaseAssociatedRequest request;
- OpenCallback callback;
- };
- std::vector<OpenRequest> open_requests_;
- base::Closure on_open_callback_;
-
- struct DestroyRequest {
- std::string dbname;
- };
- std::vector<DestroyRequest> destroy_requests_;
-
- void Bind(const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe,
- const service_manager::BindSourceInfo& source_info) {
- bindings_.AddBinding(
- this, leveldb::mojom::LevelDBServiceRequest(std::move(interface_pipe)));
- }
-
- private:
- mojo::BindingSet<leveldb::mojom::LevelDBService> bindings_;
-};
-
-class FakeLevelDBDatabaseErrorOnWrite : public FakeLevelDBDatabase {
- public:
- explicit FakeLevelDBDatabaseErrorOnWrite(
- std::map<std::vector<uint8_t>, std::vector<uint8_t>>* mock_data)
- : FakeLevelDBDatabase(mock_data) {}
-
- void Write(std::vector<leveldb::mojom::BatchedOperationPtr> operations,
- WriteCallback callback) override {
- std::move(callback).Run(leveldb::mojom::DatabaseError::IO_ERROR);
- }
-};
-
-} // namespace
-
TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
FakeLevelDBService mock_leveldb_service;
- service_manager::ServiceContext::SetGlobalBinderForTesting(
- file::mojom::kServiceName, leveldb::mojom::LevelDBService::Name_,
- base::Bind(&FakeLevelDBService::Bind,
- base::Unretained(&mock_leveldb_service)));
+ ResetFileServiceAndConnector(
+ service_manager::TestServiceDecorator::CreateServiceWithUniqueOverride(
+ file::CreateFileService(),
+
+ leveldb::mojom::LevelDBService::Name_,
+ base::BindRepeating(&test::FakeLevelDBService::Bind,
+ base::Unretained(&mock_leveldb_service))));
std::map<std::vector<uint8_t>, std::vector<uint8_t>> test_data;
@@ -1226,7 +1024,7 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
mojom::LevelDBWrapperPtr wrapper3;
{
base::RunLoop loop;
- mock_leveldb_service.on_open_callback_ = loop.QuitClosure();
+ mock_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
MakeRequest(&wrapper1));
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
@@ -1244,19 +1042,19 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
// Verify one attempt was made to open the database, and connect that request
// with a database implementation that always fails on write.
- ASSERT_EQ(1u, mock_leveldb_service.open_requests_.size());
- auto& open_request = mock_leveldb_service.open_requests_[0];
+ ASSERT_EQ(1u, mock_leveldb_service.open_requests().size());
+ auto& open_request = mock_leveldb_service.open_requests()[0];
auto mock_db = mojo::MakeStrongAssociatedBinding(
std::make_unique<FakeLevelDBDatabaseErrorOnWrite>(&test_data),
std::move(open_request.request));
std::move(open_request.callback).Run(leveldb::mojom::DatabaseError::OK);
- mock_leveldb_service.open_requests_.clear();
+ mock_leveldb_service.open_requests().clear();
// Setup a RunLoop so we can wait until LocalStorageContextMojo tries to
// reconnect to the database, which should happen after several commit
// errors.
base::RunLoop reopen_loop;
- mock_leveldb_service.on_open_callback_ = reopen_loop.QuitClosure();
+ mock_leveldb_service.SetOnOpenCallback(reopen_loop.QuitClosure());
// Start a put operation on the third connection before starting to commit
// a lot of data on the first origin. This put operation should result in a
@@ -1274,12 +1072,10 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
value[0]++;
wrapper1.set_connection_error_handler(put_loop.QuitClosure());
wrapper1->Put(key, value, base::nullopt, "source",
- base::BindOnce(
- [](base::Closure quit_closure, bool success) {
- EXPECT_TRUE(success);
- quit_closure.Run();
- },
- put_loop.QuitClosure()));
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
put_loop.RunUntilIdle();
values_written++;
// And we need to flush after every change. Otherwise changes get batched up
@@ -1300,34 +1096,31 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
EXPECT_TRUE(wrapper2.encountered_error());
// And the old database should have been destroyed.
- EXPECT_EQ(1u, mock_leveldb_service.destroy_requests_.size());
+ EXPECT_EQ(1u, mock_leveldb_service.destroy_requests().size());
// Reconnect wrapper1 to the database, and try to read a value.
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
MakeRequest(&wrapper1));
base::RunLoop delete_loop;
bool success = true;
- auto callback = [](bool* success_out, const base::Closure& callback,
- bool success) {
- *success_out = success;
- callback.Run();
- };
TestLevelDBObserver observer3;
wrapper1->AddObserver(observer3.Bind());
- wrapper1->Delete(
- key, base::nullopt, "source",
- base::BindOnce(callback, &success, delete_loop.QuitClosure()));
+ wrapper1->Delete(key, base::nullopt, "source",
+ base::BindLambdaForTesting([&](bool success_in) {
+ success = success_in;
+ delete_loop.Quit();
+ }));
// Wait for LocalStorageContextMojo to try to reconnect to the database, and
// connect that new request to a properly functioning database.
reopen_loop.Run();
- ASSERT_EQ(1u, mock_leveldb_service.open_requests_.size());
- auto& reopen_request = mock_leveldb_service.open_requests_[0];
+ ASSERT_EQ(1u, mock_leveldb_service.open_requests().size());
+ auto& reopen_request = mock_leveldb_service.open_requests()[0];
mock_db = mojo::MakeStrongAssociatedBinding(
std::make_unique<FakeLevelDBDatabase>(&test_data),
std::move(reopen_request.request));
std::move(reopen_request.callback).Run(leveldb::mojom::DatabaseError::OK);
- mock_leveldb_service.open_requests_.clear();
+ mock_leveldb_service.open_requests().clear();
// And deleting the value from the new wrapper should have failed (as the
// database is empty).
@@ -1358,10 +1151,11 @@ TEST_F(LocalStorageContextMojoTestWithService, RecreateOnCommitFailure) {
TEST_F(LocalStorageContextMojoTestWithService,
DontRecreateOnRepeatedCommitFailure) {
FakeLevelDBService mock_leveldb_service;
- service_manager::ServiceContext::SetGlobalBinderForTesting(
- file::mojom::kServiceName, leveldb::mojom::LevelDBService::Name_,
- base::Bind(&FakeLevelDBService::Bind,
- base::Unretained(&mock_leveldb_service)));
+ ResetFileServiceAndConnector(
+ service_manager::TestServiceDecorator::CreateServiceWithUniqueOverride(
+ file::CreateFileService(), leveldb::mojom::LevelDBService::Name_,
+ base::BindRepeating(&test::FakeLevelDBService::Bind,
+ base::Unretained(&mock_leveldb_service))));
std::map<std::vector<uint8_t>, std::vector<uint8_t>> test_data;
@@ -1377,7 +1171,7 @@ TEST_F(LocalStorageContextMojoTestWithService,
mojom::LevelDBWrapperPtr wrapper;
{
base::RunLoop loop;
- mock_leveldb_service.on_open_callback_ = loop.QuitClosure();
+ mock_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
context->OpenLocalStorage(url::Origin::Create(GURL("http://foobar.com")),
MakeRequest(&wrapper));
loop.Run();
@@ -1385,19 +1179,19 @@ TEST_F(LocalStorageContextMojoTestWithService,
// Verify one attempt was made to open the database, and connect that request
// with a database implementation that always fails on write.
- ASSERT_EQ(1u, mock_leveldb_service.open_requests_.size());
- auto& open_request = mock_leveldb_service.open_requests_[0];
+ ASSERT_EQ(1u, mock_leveldb_service.open_requests().size());
+ auto& open_request = mock_leveldb_service.open_requests()[0];
auto mock_db = mojo::MakeStrongAssociatedBinding(
std::make_unique<FakeLevelDBDatabaseErrorOnWrite>(&test_data),
std::move(open_request.request));
std::move(open_request.callback).Run(leveldb::mojom::DatabaseError::OK);
- mock_leveldb_service.open_requests_.clear();
+ mock_leveldb_service.open_requests().clear();
// Setup a RunLoop so we can wait until LocalStorageContextMojo tries to
// reconnect to the database, which should happen after several commit
// errors.
base::RunLoop reopen_loop;
- mock_leveldb_service.on_open_callback_ = reopen_loop.QuitClosure();
+ mock_leveldb_service.SetOnOpenCallback(reopen_loop.QuitClosure());
// Repeatedly write data to the database, to trigger enough commit errors.
base::Optional<std::vector<uint8_t>> old_value;
@@ -1408,12 +1202,10 @@ TEST_F(LocalStorageContextMojoTestWithService,
value[0]++;
wrapper.set_connection_error_handler(put_loop.QuitClosure());
wrapper->Put(key, value, old_value, "source",
- base::BindOnce(
- [](base::Closure quit_closure, bool success) {
- EXPECT_TRUE(success);
- quit_closure.Run();
- },
- put_loop.QuitClosure()));
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
old_value = std::vector<uint8_t>(value);
put_loop.RunUntilIdle();
// And we need to flush after every change. Otherwise changes get batched up
@@ -1434,16 +1226,16 @@ TEST_F(LocalStorageContextMojoTestWithService,
// connect that new request with a database implementation that always fails
// on write.
reopen_loop.Run();
- ASSERT_EQ(1u, mock_leveldb_service.open_requests_.size());
- auto& reopen_request = mock_leveldb_service.open_requests_[0];
+ ASSERT_EQ(1u, mock_leveldb_service.open_requests().size());
+ auto& reopen_request = mock_leveldb_service.open_requests()[0];
mock_db = mojo::MakeStrongAssociatedBinding(
std::make_unique<FakeLevelDBDatabaseErrorOnWrite>(&test_data),
std::move(reopen_request.request));
std::move(reopen_request.callback).Run(leveldb::mojom::DatabaseError::OK);
- mock_leveldb_service.open_requests_.clear();
+ mock_leveldb_service.open_requests().clear();
// The old database should also have been destroyed.
- EXPECT_EQ(1u, mock_leveldb_service.destroy_requests_.size());
+ EXPECT_EQ(1u, mock_leveldb_service.destroy_requests().size());
// Reconnect a wrapper to the database, and repeatedly write data to it again.
// This time all should just keep getting written, and commit errors are
@@ -1458,12 +1250,10 @@ TEST_F(LocalStorageContextMojoTestWithService,
value[0]++;
wrapper.set_connection_error_handler(put_loop.QuitClosure());
wrapper->Put(key, value, old_value, "source",
- base::BindOnce(
- [](base::Closure quit_closure, bool success) {
- EXPECT_TRUE(success);
- quit_closure.Run();
- },
- put_loop.QuitClosure()));
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
put_loop.RunUntilIdle();
old_value = value;
// And we need to flush after every change. Otherwise changes get batched up
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo.cc b/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
index 1297a78569c..0f4bf4aed6c 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -4,80 +4,869 @@
#include "content/browser/dom_storage/session_storage_context_mojo.h"
+#include <inttypes.h>
+#include <cctype> // for std::isalnum
+#include <cstring>
+#include <utility>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/debug/stack_trace.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/sys_info.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "build/build_config.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
+#include "content/browser/dom_storage/session_storage_leveldb_wrapper.h"
+#include "content/browser/dom_storage/session_storage_namespace_impl_mojo.h"
#include "content/browser/leveldb_wrapper_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
+#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/common/content_features.h"
+#include "services/file/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
+#include "third_party/leveldatabase/env_chromium.h"
+#include "third_party/leveldatabase/leveldb_chrome.h"
+#include "url/gurl.h"
namespace content {
+namespace {
+// After this many consecutive commit errors we'll throw away the entire
+// database.
+const int kSessionStorageCommitErrorThreshold = 8;
+
+// Limits on the cache size and number of areas in memory, over which the areas
+// are purged.
+#if defined(OS_ANDROID)
+const unsigned kMaxSessionStorageAreaCount = 10;
+const size_t kMaxSessionStorageCacheSize = 2 * 1024 * 1024;
+#else
+const unsigned kMaxSessionStorageAreaCount = 50;
+const size_t kMaxSessionStorageCacheSize = 20 * 1024 * 1024;
+#endif
+
+enum class SessionStorageCachePurgeReason {
+ kNotNeeded,
+ kSizeLimitExceeded,
+ kAreaCountLimitExceeded,
+ kInactiveOnLowEndDevice,
+ kAggressivePurgeTriggered
+};
+
+void RecordSessionStorageCachePurgedHistogram(
+ SessionStorageCachePurgeReason reason,
+ size_t purged_size_kib) {
+ UMA_HISTOGRAM_COUNTS_100000("SessionStorageContext.CachePurgedInKB",
+ purged_size_kib);
+ switch (reason) {
+ case SessionStorageCachePurgeReason::kSizeLimitExceeded:
+ UMA_HISTOGRAM_COUNTS_100000(
+ "SessionStorageContext.CachePurgedInKB.SizeLimitExceeded",
+ purged_size_kib);
+ break;
+ case SessionStorageCachePurgeReason::kAreaCountLimitExceeded:
+ UMA_HISTOGRAM_COUNTS_100000(
+ "SessionStorageContext.CachePurgedInKB.AreaCountLimitExceeded",
+ purged_size_kib);
+ break;
+ case SessionStorageCachePurgeReason::kInactiveOnLowEndDevice:
+ UMA_HISTOGRAM_COUNTS_100000(
+ "SessionStorageContext.CachePurgedInKB.InactiveOnLowEndDevice",
+ purged_size_kib);
+ break;
+ case SessionStorageCachePurgeReason::kAggressivePurgeTriggered:
+ UMA_HISTOGRAM_COUNTS_100000(
+ "SessionStorageContext.CachePurgedInKB.AggressivePurgeTriggered",
+ purged_size_kib);
+ break;
+ case SessionStorageCachePurgeReason::kNotNeeded:
+ NOTREACHED();
+ break;
+ }
+}
+} // namespace
SessionStorageContextMojo::SessionStorageContextMojo(
- scoped_refptr<base::SequencedTaskRunner> task_runner,
+ scoped_refptr<base::SequencedTaskRunner> memory_dump_task_runner,
service_manager::Connector* connector,
- base::Optional<base::FilePath> partition_directory,
+ base::Optional<base::FilePath> local_partition_directory,
std::string leveldb_name)
: connector_(connector ? connector->Clone() : nullptr),
- partition_directory_path_(std::move(partition_directory)),
+ partition_directory_path_(std::move(local_partition_directory)),
leveldb_name_(std::move(leveldb_name)),
+ memory_dump_id_(base::StringPrintf("SessionStorage/0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(this))),
+ is_low_end_device_(base::SysInfo::IsLowEndDevice()),
weak_ptr_factory_(this) {
DCHECK(base::FeatureList::IsEnabled(features::kMojoSessionStorage));
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->RegisterDumpProviderWithSequencedTaskRunner(
+ this, "SessionStorage", std::move(memory_dump_task_runner),
+ base::trace_event::MemoryDumpProvider::Options());
+}
+
+SessionStorageContextMojo::~SessionStorageContextMojo() {
+ DCHECK_EQ(connection_state_, CONNECTION_SHUTDOWN);
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
}
-SessionStorageContextMojo::~SessionStorageContextMojo() {}
void SessionStorageContextMojo::OpenSessionStorage(
int process_id,
const std::string& namespace_id,
mojom::SessionStorageNamespaceRequest request) {
- // TODO(dmurph): Check the process ID against the origin like so:
- // if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin(
- // process_id, origin.GetURL())) {
- // bindings_.ReportBadMessage("Access denied for sessionStorage request");
- // return;
- // }
- NOTREACHED();
+ if (connection_state_ != CONNECTION_FINISHED) {
+ RunWhenConnected(
+ base::BindOnce(&SessionStorageContextMojo::OpenSessionStorage,
+ weak_ptr_factory_.GetWeakPtr(), process_id, namespace_id,
+ std::move(request)));
+ return;
+ }
+ auto found = namespaces_.find(namespace_id);
+ DCHECK(found != namespaces_.end()) << namespace_id;
+
+ if (!found->second->IsPopulated() &&
+ !found->second->waiting_on_clone_population()) {
+ found->second->PopulateFromMetadata(
+ database_.get(), metadata_.GetOrCreateNamespaceEntry(namespace_id),
+ data_maps_);
+ }
+
+ PurgeUnusedWrappersIfNeeded();
+ found->second->Bind(std::move(request), process_id);
+
+ size_t total_cache_size, unused_wrapper_count;
+ GetStatistics(&total_cache_size, &unused_wrapper_count);
+ // Track the total sessionStorage cache size.
+ UMA_HISTOGRAM_COUNTS_100000("SessionStorageContext.CacheSizeInKB",
+ total_cache_size / 1024);
}
void SessionStorageContextMojo::CreateSessionNamespace(
const std::string& namespace_id) {
- NOTREACHED();
+ if (namespaces_.find(namespace_id) != namespaces_.end())
+ return;
+
+ namespaces_.emplace(std::make_pair(
+ namespace_id, CreateSessionStorageNamespaceImplMojo(namespace_id)));
}
void SessionStorageContextMojo::CloneSessionNamespace(
const std::string& namespace_id_to_clone,
const std::string& clone_namespace_id) {
- NOTREACHED();
+ if (namespaces_.find(clone_namespace_id) != namespaces_.end())
+ return;
+
+ std::unique_ptr<SessionStorageNamespaceImplMojo> namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(clone_namespace_id);
+ namespace_impl->SetWaitingForClonePopulation();
+ namespaces_.emplace(
+ std::make_pair(clone_namespace_id, std::move(namespace_impl)));
}
void SessionStorageContextMojo::DeleteSessionNamespace(
const std::string& namespace_id,
bool should_persist) {
- NOTREACHED();
+ // The object hierarchy uses iterators bound to the metadata object, so make
+ // sure to delete the object hierarchy first.
+ namespaces_.erase(namespace_id);
+
+ if (!has_scavenged_ && should_persist)
+ protected_namespaces_from_scavenge_.insert(namespace_id);
+
+ if (!should_persist) {
+ RunWhenConnected(
+ base::BindOnce(&SessionStorageContextMojo::DoDatabaseDelete,
+ weak_ptr_factory_.GetWeakPtr(), namespace_id));
+ }
}
void SessionStorageContextMojo::Flush() {
- NOTREACHED();
+ if (connection_state_ != CONNECTION_FINISHED) {
+ RunWhenConnected(base::BindOnce(&SessionStorageContextMojo::Flush,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+ for (const auto& it : data_maps_)
+ it.second->level_db_wrapper()->ScheduleImmediateCommit();
}
void SessionStorageContextMojo::GetStorageUsage(
GetStorageUsageCallback callback) {
- NOTREACHED();
+ if (connection_state_ != CONNECTION_FINISHED) {
+ RunWhenConnected(base::BindOnce(&SessionStorageContextMojo::GetStorageUsage,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(callback)));
+ return;
+ }
+
+ const SessionStorageMetadata::NamespaceOriginMap& all_namespaces =
+ metadata_.namespace_origin_map();
+
+ std::vector<SessionStorageUsageInfo> result;
+ result.reserve(all_namespaces.size());
+ for (const auto& pair : all_namespaces) {
+ for (const auto& origin_map_pair : pair.second) {
+ SessionStorageUsageInfo info = {origin_map_pair.first.GetURL(),
+ pair.first};
+ result.push_back(std::move(info));
+ }
+ }
+ std::move(callback).Run(std::move(result));
}
-void SessionStorageContextMojo::DeleteStorage(
- const url::Origin& origin,
- const std::string& persistent_namespace_id) {
- NOTREACHED();
+
+void SessionStorageContextMojo::DeleteStorage(const url::Origin& origin,
+ const std::string& namespace_id) {
+ if (connection_state_ != CONNECTION_FINISHED) {
+ RunWhenConnected(base::BindOnce(&SessionStorageContextMojo::DeleteStorage,
+ weak_ptr_factory_.GetWeakPtr(), origin,
+ namespace_id));
+ return;
+ }
+ auto found = namespaces_.find(namespace_id);
+ if (found != namespaces_.end()) {
+ found->second->RemoveOriginData(origin);
+ } else {
+ // If we don't have the namespace loaded, then we can delete it all
+ // using the metadata.
+ std::vector<leveldb::mojom::BatchedOperationPtr> delete_operations;
+ metadata_.DeleteArea(namespace_id, origin, &delete_operations);
+ database_->Write(std::move(delete_operations),
+ base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
+ base::Unretained(this)));
+ }
}
void SessionStorageContextMojo::ShutdownAndDelete() {
- delete this;
+ DCHECK_NE(connection_state_, CONNECTION_SHUTDOWN);
+
+ // Nothing to do if no connection to the database was ever finished.
+ if (connection_state_ != CONNECTION_FINISHED) {
+ connection_state_ = CONNECTION_SHUTDOWN;
+ OnShutdownComplete(leveldb::mojom::DatabaseError::OK);
+ return;
+ }
+ connection_state_ = CONNECTION_SHUTDOWN;
+
+ // Flush any uncommitted data.
+ for (const auto& it : data_maps_) {
+ auto* wrapper = it.second->level_db_wrapper();
+ LOCAL_HISTOGRAM_BOOLEAN(
+ "SessionStorageContext.ShutdownAndDelete.MaybeDroppedChanges",
+ wrapper->has_pending_load_tasks());
+ wrapper->ScheduleImmediateCommit();
+ // TODO(dmurph): Monitor the above histogram, and if dropping changes is
+ // common then handle that here.
+ wrapper->CancelAllPendingRequests();
+ }
+
+ OnShutdownComplete(leveldb::mojom::DatabaseError::OK);
}
void SessionStorageContextMojo::PurgeMemory() {
- NOTREACHED();
+ size_t total_cache_size, unused_wrapper_count;
+ GetStatistics(&total_cache_size, &unused_wrapper_count);
+
+ // Purge all wrappers that don't have bindings.
+ for (auto it = namespaces_.begin(); it != namespaces_.end();) {
+ if (!it->second->IsBound()) {
+ it = namespaces_.erase(it);
+ continue;
+ }
+ it->second->PurgeUnboundWrappers();
+ }
+
+ // Track the size of cache purged.
+ size_t final_total_cache_size;
+ GetStatistics(&final_total_cache_size, &unused_wrapper_count);
+ size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
+ RecordSessionStorageCachePurgedHistogram(
+ SessionStorageCachePurgeReason::kAggressivePurgeTriggered,
+ purged_size_kib);
}
void SessionStorageContextMojo::PurgeUnusedWrappersIfNeeded() {
- NOTREACHED();
+ size_t total_cache_size, unused_wrapper_count;
+ GetStatistics(&total_cache_size, &unused_wrapper_count);
+
+ // Nothing to purge.
+ if (!unused_wrapper_count)
+ return;
+
+ SessionStorageCachePurgeReason purge_reason =
+ SessionStorageCachePurgeReason::kNotNeeded;
+
+ if (total_cache_size > kMaxSessionStorageCacheSize)
+ purge_reason = SessionStorageCachePurgeReason::kSizeLimitExceeded;
+ else if (data_maps_.size() > kMaxSessionStorageAreaCount)
+ purge_reason = SessionStorageCachePurgeReason::kAreaCountLimitExceeded;
+ else if (is_low_end_device_)
+ purge_reason = SessionStorageCachePurgeReason::kInactiveOnLowEndDevice;
+
+ if (purge_reason == SessionStorageCachePurgeReason::kNotNeeded)
+ return;
+
+ // Purge all wrappers that don't have bindings.
+ for (auto it = namespaces_.begin(); it != namespaces_.end();) {
+ if (!it->second->IsBound())
+ it = namespaces_.erase(it);
+ }
+
+ size_t final_total_cache_size;
+ GetStatistics(&final_total_cache_size, &unused_wrapper_count);
+ size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
+ RecordSessionStorageCachePurgedHistogram(
+ SessionStorageCachePurgeReason::kAggressivePurgeTriggered,
+ purged_size_kib);
+}
+
+void SessionStorageContextMojo::ScavengeUnusedNamespaces(
+ base::OnceClosure done) {
+ if (has_scavenged_)
+ return;
+ if (connection_state_ != CONNECTION_FINISHED) {
+ RunWhenConnected(
+ base::BindOnce(&SessionStorageContextMojo::ScavengeUnusedNamespaces,
+ weak_ptr_factory_.GetWeakPtr(), std::move(done)));
+ return;
+ }
+ has_scavenged_ = true;
+ std::vector<std::string> namespaces_to_delete;
+ for (const auto& metadata_namespace : metadata_.namespace_origin_map()) {
+ const std::string& namespace_id = metadata_namespace.first;
+ if (namespaces_.find(namespace_id) != namespaces_.end() ||
+ protected_namespaces_from_scavenge_.find(namespace_id) !=
+ protected_namespaces_from_scavenge_.end()) {
+ continue;
+ }
+ namespaces_to_delete.push_back(namespace_id);
+ }
+ std::vector<leveldb::mojom::BatchedOperationPtr> delete_operations;
+ for (const auto& namespace_id : namespaces_to_delete) {
+ metadata_.DeleteNamespace(namespace_id, &delete_operations);
+ }
+
+ if (!delete_operations.empty()) {
+ database_->Write(std::move(delete_operations),
+ base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
+ base::Unretained(this)));
+ }
+ protected_namespaces_from_scavenge_.clear();
+ if (done)
+ std::move(done).Run();
+}
+
+bool SessionStorageContextMojo::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ if (connection_state_ != CONNECTION_FINISHED)
+ return true;
+
+ std::string context_name =
+ base::StringPrintf("site_storage/sessionstorage/0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(this));
+
+ // Account for leveldb memory usage, which actually lives in the file service.
+ auto* global_dump = pmd->CreateSharedGlobalAllocatorDump(memory_dump_id_);
+ // The size of the leveldb dump will be added by the leveldb service.
+ auto* leveldb_mad = pmd->CreateAllocatorDump(context_name + "/leveldb");
+ // Specifies that the current context is responsible for keeping memory alive.
+ int kImportance = 2;
+ pmd->AddOwnershipEdge(leveldb_mad->guid(), global_dump->guid(), kImportance);
+
+ if (args.level_of_detail ==
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
+ size_t total_cache_size, unused_wrapper_count;
+ GetStatistics(&total_cache_size, &unused_wrapper_count);
+ auto* mad = pmd->CreateAllocatorDump(context_name + "/cache_size");
+ mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ total_cache_size);
+ mad->AddScalar("total_areas",
+ base::trace_event::MemoryAllocatorDump::kUnitsObjects,
+ data_maps_.size());
+ return true;
+ }
+ for (const auto& it : data_maps_) {
+ // Limit the url length to 50 and strip special characters.
+ const auto& origin = it.second->map_data()->origin();
+ std::string url = origin.Serialize().substr(0, 50);
+ for (size_t index = 0; index < url.size(); ++index) {
+ if (!std::isalnum(url[index]))
+ url[index] = '_';
+ }
+ std::string wrapper_dump_name = base::StringPrintf(
+ "%s/%s/0x%" PRIXPTR, context_name.c_str(), url.c_str(),
+ reinterpret_cast<uintptr_t>(it.second->level_db_wrapper()));
+ it.second->level_db_wrapper()->OnMemoryDump(wrapper_dump_name, pmd);
+ }
+ return true;
+}
+
+void SessionStorageContextMojo::OnDataMapCreation(
+ const std::vector<uint8_t>& map_prefix,
+ SessionStorageDataMap* map) {
+ DCHECK(data_maps_.find(map_prefix) == data_maps_.end());
+ data_maps_.emplace(std::piecewise_construct,
+ std::forward_as_tuple(map_prefix),
+ std::forward_as_tuple(map));
+}
+
+void SessionStorageContextMojo::OnDataMapDestruction(
+ const std::vector<uint8_t>& map_prefix) {
+ data_maps_.erase(map_prefix);
+}
+
+void SessionStorageContextMojo::OnCommitResult(
+ leveldb::mojom::DatabaseError error) {
+ DCHECK_EQ(connection_state_, CONNECTION_FINISHED);
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.CommitResult",
+ leveldb::GetLevelDBStatusUMAValue(error),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ if (error == leveldb::mojom::DatabaseError::OK) {
+ commit_error_count_ = 0;
+ return;
+ }
+ commit_error_count_++;
+ if (commit_error_count_ > kSessionStorageCommitErrorThreshold) {
+ if (tried_to_recover_from_commit_errors_) {
+ // We already tried to recover from a high commit error rate before, but
+ // are still having problems: there isn't really anything left to try, so
+ // just ignore errors.
+ return;
+ }
+ tried_to_recover_from_commit_errors_ = true;
+
+ // Deleting LevelDBWrappers in here could cause more commits (and commit
+ // errors), but those commits won't reach OnCommitResult because the wrapper
+ // will have been deleted before the commit finishes.
+ DeleteAndRecreateDatabase(
+ "SessionStorageContext.OpenResultAfterCommitErrors");
+ }
+}
+
+void SessionStorageContextMojo::SetDatabaseForTesting(
+ leveldb::mojom::LevelDBDatabaseAssociatedPtr database) {
+ DCHECK_EQ(connection_state_, NO_CONNECTION);
+ connection_state_ = CONNECTION_IN_PROGRESS;
+ database_ = std::move(database);
+ OnDatabaseOpened(true, leveldb::mojom::DatabaseError::OK);
+}
+
+void SessionStorageContextMojo::FlushAreaForTesting(
+ const std::string& namespace_id,
+ const url::Origin& origin) {
+ if (connection_state_ != CONNECTION_FINISHED)
+ return;
+ const auto& it = namespaces_.find(namespace_id);
+ if (it == namespaces_.end())
+ return;
+ it->second->FlushOriginForTesting(origin);
+}
+
+scoped_refptr<SessionStorageMetadata::MapData>
+SessionStorageContextMojo::RegisterNewAreaMap(
+ SessionStorageMetadata::NamespaceEntry namespace_entry,
+ const url::Origin& origin) {
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ scoped_refptr<SessionStorageMetadata::MapData> map_entry =
+ metadata_.RegisterNewMap(namespace_entry, origin, &save_operations);
+
+ database_->Write(std::move(save_operations),
+ base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
+ base::Unretained(this)));
+ return map_entry;
+}
+
+void SessionStorageContextMojo::RegisterShallowClonedNamespace(
+ SessionStorageMetadata::NamespaceEntry source_namespace_entry,
+ const std::string& new_namespace_id,
+ const SessionStorageNamespaceImplMojo::OriginAreas& clone_from_areas) {
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ SessionStorageMetadata::NamespaceEntry namespace_entry =
+ metadata_.GetOrCreateNamespaceEntry(new_namespace_id);
+ metadata_.RegisterShallowClonedNamespace(source_namespace_entry,
+ namespace_entry, &save_operations);
+ database_->Write(std::move(save_operations),
+ base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
+ base::Unretained(this)));
+
+ auto it = namespaces_.find(new_namespace_id);
+ if (it != namespaces_.end()) {
+ it->second->PopulateAsClone(database_.get(), namespace_entry,
+ clone_from_areas);
+ return;
+ }
+
+ auto namespace_impl = CreateSessionStorageNamespaceImplMojo(new_namespace_id);
+ namespace_impl->PopulateAsClone(database_.get(), namespace_entry,
+ clone_from_areas);
+ namespaces_.emplace(
+ std::make_pair(new_namespace_id, std::move(namespace_impl)));
+}
+
+std::unique_ptr<SessionStorageNamespaceImplMojo>
+SessionStorageContextMojo::CreateSessionStorageNamespaceImplMojo(
+ std::string namespace_id) {
+ SessionStorageNamespaceImplMojo::RegisterShallowClonedNamespace
+ add_namespace_callback = base::BindRepeating(
+ &SessionStorageContextMojo::RegisterShallowClonedNamespace,
+ base::Unretained(this));
+ SessionStorageLevelDBWrapper::RegisterNewAreaMap map_id_callback =
+ base::BindRepeating(&SessionStorageContextMojo::RegisterNewAreaMap,
+ base::Unretained(this));
+
+ return std::make_unique<SessionStorageNamespaceImplMojo>(
+ std::move(namespace_id), this, std::move(add_namespace_callback),
+ std::move(map_id_callback));
+}
+
+void SessionStorageContextMojo::DoDatabaseDelete(
+ const std::string& namespace_id) {
+ DCHECK_EQ(connection_state_, CONNECTION_FINISHED);
+ std::vector<leveldb::mojom::BatchedOperationPtr> delete_operations;
+ metadata_.DeleteNamespace(namespace_id, &delete_operations);
+ database_->Write(std::move(delete_operations),
+ base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
+ base::Unretained(this)));
+}
+
+void SessionStorageContextMojo::RunWhenConnected(base::OnceClosure callback) {
+ DCHECK_NE(connection_state_, CONNECTION_SHUTDOWN);
+
+ // If we don't have a filesystem_connection_, we'll need to establish one.
+ if (connection_state_ == NO_CONNECTION) {
+ connection_state_ = CONNECTION_IN_PROGRESS;
+ InitiateConnection();
+ }
+
+ if (connection_state_ == CONNECTION_IN_PROGRESS) {
+ // Queue this OpenSessionStorage call for when we have a level db pointer.
+ on_database_opened_callbacks_.push_back(std::move(callback));
+ return;
+ }
+
+ std::move(callback).Run();
+}
+
+void SessionStorageContextMojo::InitiateConnection(bool in_memory_only) {
+ DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
+ // Unit tests might not always have a Connector, use in-memory only if that
+ // happens.
+ if (!connector_) {
+ OnDatabaseOpened(false, leveldb::mojom::DatabaseError::OK);
+ return;
+ }
+
+ if (partition_directory_path_ && !in_memory_only) {
+ // We were given a subdirectory to write to. Get it and use a disk backed
+ // database.
+ connector_->BindInterface(file::mojom::kServiceName, &file_system_);
+ file_system_->GetSubDirectory(
+ partition_directory_path_.value().AsUTF8Unsafe(),
+ MakeRequest(&partition_directory_),
+ base::BindOnce(&SessionStorageContextMojo::OnDirectoryOpened,
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
+ // We were not given a subdirectory. Use a memory backed database.
+ connector_->BindInterface(file::mojom::kServiceName, &leveldb_service_);
+ leveldb_service_->OpenInMemory(
+ memory_dump_id_, "SessionStorageDatabase", MakeRequest(&database_),
+ base::BindOnce(&SessionStorageContextMojo::OnDatabaseOpened,
+ weak_ptr_factory_.GetWeakPtr(), true));
+ }
+}
+
+void SessionStorageContextMojo::OnDirectoryOpened(base::File::Error err) {
+ if (err != base::File::FILE_OK) {
+ // We failed to open the directory; continue with startup so that we create
+ // the |level_db_wrappers_|.
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DirectoryOpenError", -err,
+ -base::File::FILE_ERROR_MAX);
+ LogDatabaseOpenResult(OpenResult::kDirectoryOpenFailed);
+ OnDatabaseOpened(false, leveldb::mojom::DatabaseError::OK);
+ return;
+ }
+
+ // Now that we have a directory, connect to the LevelDB service and get our
+ // database.
+ connector_->BindInterface(file::mojom::kServiceName, &leveldb_service_);
+
+ // We might still need to use the directory, so create a clone.
+ filesystem::mojom::DirectoryPtr partition_directory_clone;
+ partition_directory_->Clone(MakeRequest(&partition_directory_clone));
+
+ leveldb_env::Options options;
+ options.create_if_missing = true;
+ options.max_open_files = 0; // use minimum
+ // Default write_buffer_size is 4 MB but that might leave a 3.999
+ // memory allocation in RAM from a log file recovery.
+ options.write_buffer_size = 64 * 1024;
+ options.block_cache = leveldb_chrome::GetSharedWebBlockCache();
+ leveldb_service_->OpenWithOptions(
+ std::move(options), std::move(partition_directory_clone), leveldb_name_,
+ memory_dump_id_, MakeRequest(&database_),
+ base::BindOnce(&SessionStorageContextMojo::OnDatabaseOpened,
+ weak_ptr_factory_.GetWeakPtr(), false));
+}
+
+void SessionStorageContextMojo::OnDatabaseOpened(
+ bool in_memory,
+ leveldb::mojom::DatabaseError status) {
+ if (status != leveldb::mojom::DatabaseError::OK) {
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DatabaseOpenError",
+ leveldb::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ if (in_memory) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "SessionStorageContext.DatabaseOpenError.Memory",
+ leveldb::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DatabaseOpenError.Disk",
+ leveldb::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ }
+ LogDatabaseOpenResult(OpenResult::kDatabaseOpenFailed);
+ // If we failed to open the database, try to delete and recreate the
+ // database, or ultimately fallback to an in-memory database.
+ DeleteAndRecreateDatabase(
+ "SessionStorageContext.OpenResultAfterOpenFailed");
+ return;
+ }
+
+ // Verify DB schema version.
+ if (database_) {
+ database_->Get(
+ std::vector<uint8_t>(
+ SessionStorageMetadata::kDatabaseVersionBytes,
+ std::end(SessionStorageMetadata::kDatabaseVersionBytes)),
+ base::BindOnce(&SessionStorageContextMojo::OnGotDatabaseVersion,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+
+ OnConnectionFinished();
+}
+
+void SessionStorageContextMojo::OnGotDatabaseVersion(
+ leveldb::mojom::DatabaseError status,
+ const std::vector<uint8_t>& value) {
+ std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations;
+ if (status == leveldb::mojom::DatabaseError::NOT_FOUND) {
+ // New database, or schema v0. We must treat this as a schema v0 database.
+ metadata_.ParseDatabaseVersion(base::nullopt, &migration_operations);
+ } else if (status == leveldb::mojom::DatabaseError::OK) {
+ if (!metadata_.ParseDatabaseVersion(value, &migration_operations)) {
+ LogDatabaseOpenResult(OpenResult::kInvalidVersion);
+ DeleteAndRecreateDatabase(
+ "SessionStorageContext.OpenResultAfterInvalidVersion");
+ return;
+ }
+ database_initialized_ = true;
+ } else {
+ // Other read error. Possibly database corruption.
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.ReadVersionError",
+ leveldb::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ LogDatabaseOpenResult(OpenResult::kVersionReadError);
+ DeleteAndRecreateDatabase(
+ "SessionStorageContext.OpenResultAfterReadVersionError");
+ return;
+ }
+ connection_state_ = FETCHING_METADATA;
+
+ base::RepeatingClosure barrier = base::BarrierClosure(
+ 2, base::BindOnce(&SessionStorageContextMojo::OnConnectionFinished,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ std::vector<uint8_t> namespace_prefix(
+ SessionStorageMetadata::kNamespacePrefixBytes,
+ std::end(SessionStorageMetadata::kNamespacePrefixBytes));
+ std::vector<uint8_t> next_map_id_key(
+ SessionStorageMetadata::kNextMapIdKeyBytes,
+ std::end(SessionStorageMetadata::kNextMapIdKeyBytes));
+ database_->GetPrefixed(
+ namespace_prefix,
+ base::BindOnce(&SessionStorageContextMojo::OnGotNamespaces,
+ weak_ptr_factory_.GetWeakPtr(), barrier,
+ std::move(migration_operations)));
+ database_->Get(next_map_id_key,
+ base::BindOnce(&SessionStorageContextMojo::OnGotNextMapId,
+ weak_ptr_factory_.GetWeakPtr(), barrier));
+}
+
+void SessionStorageContextMojo::OnGotNamespaces(
+ base::OnceClosure done,
+ std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations,
+ leveldb::mojom::DatabaseError status,
+ std::vector<leveldb::mojom::KeyValuePtr> values) {
+ DCHECK(connection_state_ == FETCHING_METADATA);
+ bool parsing_failure =
+ status == leveldb::mojom::DatabaseError::OK &&
+ !metadata_.ParseNamespaces(std::move(values), &migration_operations);
+ if (status != leveldb::mojom::DatabaseError::OK || parsing_failure) {
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.ReadNamespacesError",
+ leveldb::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ LogDatabaseOpenResult(OpenResult::kNamespacesReadError);
+ DeleteAndRecreateDatabase(
+ "SessionStorageContext.OpenResultAfterReadNamespacesError");
+ return;
+ }
+
+ // Write all of our migration operations if we have any.
+ if (!migration_operations.empty()) {
+ database_->Write(std::move(migration_operations),
+ base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
+ base::Unretained(this)));
+ }
+ std::move(done).Run();
+}
+
+void SessionStorageContextMojo::OnGotNextMapId(
+ base::OnceClosure done,
+ leveldb::mojom::DatabaseError status,
+ const std::vector<uint8_t>& map_id) {
+ DCHECK(connection_state_ == FETCHING_METADATA);
+ if (status == leveldb::mojom::DatabaseError::NOT_FOUND) {
+ std::move(done).Run();
+ return;
+ }
+ if (status == leveldb::mojom::DatabaseError::OK) {
+ metadata_.ParseNextMapId(map_id);
+ std::move(done).Run();
+ return;
+ }
+
+ // Other read error. Possibly database corruption.
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.ReadNextMapIdError",
+ leveldb::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ LogDatabaseOpenResult(OpenResult::kNamespacesReadError);
+ DeleteAndRecreateDatabase(
+ "SessionStorageContext.OpenResultAfterReadNextMapIdError");
+}
+
+void SessionStorageContextMojo::OnConnectionFinished() {
+ DCHECK(!database_ || connection_state_ == FETCHING_METADATA);
+ if (!database_) {
+ partition_directory_.reset();
+ file_system_.reset();
+ leveldb_service_.reset();
+ }
+
+ // If connection was opened successfully, reset tried_to_recreate_during_open_
+ // to enable recreating the database on future errors.
+ if (database_)
+ tried_to_recreate_during_open_ = false;
+
+ open_result_histogram_ = nullptr;
+
+ // |database_| should be known to either be valid or invalid by now. Run our
+ // delayed bindings.
+ connection_state_ = CONNECTION_FINISHED;
+ std::vector<base::OnceClosure> callbacks;
+ std::swap(callbacks, on_database_opened_callbacks_);
+ for (size_t i = 0; i < callbacks.size(); ++i)
+ std::move(callbacks[i]).Run();
+}
+
+void SessionStorageContextMojo::DeleteAndRecreateDatabase(
+ const char* histogram_name) {
+ // We're about to set database_ to null, so delete the LevelDBWrappers
+ // that might still be using the old database.
+ for (const auto& it : data_maps_)
+ it.second->level_db_wrapper()->CancelAllPendingRequests();
+
+ for (const auto& namespace_pair : namespaces_) {
+ namespace_pair.second->Reset();
+ }
+ DCHECK(data_maps_.empty());
+
+ // Reset state to be in process of connecting. This will cause requests for
+ // LevelDBWrappers to be queued until the connection is complete.
+ connection_state_ = CONNECTION_IN_PROGRESS;
+ commit_error_count_ = 0;
+ database_ = nullptr;
+ open_result_histogram_ = histogram_name;
+
+ bool recreate_in_memory = false;
+
+ // If tried to recreate database on disk already, try again but this time
+ // in memory.
+ if (tried_to_recreate_during_open_ && !!partition_directory_path_) {
+ recreate_in_memory = true;
+ } else if (tried_to_recreate_during_open_) {
+ // Give up completely, run without any database.
+ OnConnectionFinished();
+ return;
+ }
+
+ tried_to_recreate_during_open_ = true;
+
+ // Unit tests might not have a bound file_service_, in which case there is
+ // nothing to retry.
+ if (!file_system_.is_bound()) {
+ OnConnectionFinished();
+ return;
+ }
+
+ protected_namespaces_from_scavenge_.clear();
+
+ // Destroy database, and try again.
+ if (partition_directory_.is_bound()) {
+ leveldb_service_->Destroy(
+ std::move(partition_directory_), leveldb_name_,
+ base::BindOnce(&SessionStorageContextMojo::OnDBDestroyed,
+ weak_ptr_factory_.GetWeakPtr(), recreate_in_memory));
+ } else {
+ // No directory, so nothing to destroy. Retrying to recreate will probably
+ // fail, but try anyway.
+ InitiateConnection(recreate_in_memory);
+ }
+}
+
+void SessionStorageContextMojo::OnDBDestroyed(
+ bool recreate_in_memory,
+ leveldb::mojom::DatabaseError status) {
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DestroyDBResult",
+ leveldb::GetLevelDBStatusUMAValue(status),
+ leveldb_env::LEVELDB_STATUS_MAX);
+ // We're essentially ignoring the status here. Even if destroying failed we
+ // still want to go ahead and try to recreate.
+ InitiateConnection(recreate_in_memory);
+}
+
+void SessionStorageContextMojo::OnShutdownComplete(
+ leveldb::mojom::DatabaseError error) {
+ delete this;
+}
+
+void SessionStorageContextMojo::GetStatistics(size_t* total_cache_size,
+ size_t* unused_wrapper_count) {
+ *total_cache_size = 0;
+ *unused_wrapper_count = 0;
+ for (const auto& it : data_maps_) {
+ *total_cache_size += it.second->level_db_wrapper()->memory_used();
+ if (it.second->binding_count() == 0)
+ (*unused_wrapper_count)++;
+ }
+}
+
+void SessionStorageContextMojo::LogDatabaseOpenResult(OpenResult result) {
+ if (result != OpenResult::kSuccess) {
+ LOG(ERROR) << "Got error when openning: " << static_cast<int>(result);
+ UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.OpenError", result);
+ }
+ if (open_result_histogram_) {
+ base::UmaHistogramEnumeration(open_result_histogram_, result);
+ }
}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo.h b/chromium/content/browser/dom_storage/session_storage_context_mojo.h
index 919c1356d22..6361d3a2bfd 100644
--- a/chromium/content/browser/dom_storage/session_storage_context_mojo.h
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo.h
@@ -6,18 +6,25 @@
#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_CONTEXT_MOJO_H_
#include <stdint.h>
+#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "content/browser/dom_storage/session_storage_data_map.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/browser/dom_storage/session_storage_namespace_impl_mojo.h"
#include "content/common/content_export.h"
#include "content/common/leveldb_wrapper.mojom.h"
#include "content/common/storage_partition_service.mojom.h"
#include "content/public/browser/session_storage_usage_info.h"
+#include "services/file/public/mojom/file_system.mojom.h"
#include "url/origin.h"
namespace base {
@@ -29,9 +36,16 @@ class Connector;
} // namespace service_manager
namespace content {
+struct SessionStorageUsageInfo;
// Used for mojo-based SessionStorage implementation.
-class CONTENT_EXPORT SessionStorageContextMojo {
+// Created on the UI thread, but all further methods are called on the task
+// runner passed to the constructor. Furthermore since destruction of this class
+// can involve asynchronous steps, it can only be deleted by calling
+// ShutdownAndDelete (on the correct task runner).
+class CONTENT_EXPORT SessionStorageContextMojo
+ : public base::trace_event::MemoryDumpProvider,
+ public SessionStorageDataMap::Listener {
public:
using GetStorageUsageCallback =
base::OnceCallback<void(std::vector<SessionStorageUsageInfo>)>;
@@ -39,9 +53,8 @@ class CONTENT_EXPORT SessionStorageContextMojo {
SessionStorageContextMojo(
scoped_refptr<base::SequencedTaskRunner> task_runner,
service_manager::Connector* connector,
- base::Optional<base::FilePath> partition_directory,
+ base::Optional<base::FilePath> local_partition_directory,
std::string leveldb_name);
- ~SessionStorageContextMojo();
void OpenSessionStorage(int process_id,
const std::string& namespace_id,
@@ -50,24 +63,21 @@ class CONTENT_EXPORT SessionStorageContextMojo {
void CreateSessionNamespace(const std::string& namespace_id);
void CloneSessionNamespace(const std::string& namespace_id_to_clone,
const std::string& clone_namespace_id);
+
void DeleteSessionNamespace(const std::string& namespace_id,
bool should_persist);
- void Flush();
- // Used by content settings to alter the behavior around
- // what data to keep and what data to discard at shutdown.
- // The policy is not so straight forward to describe, see
- // the implementation for details.
- void SetForceKeepSessionState() { force_keep_session_state_ = true; }
+ void Flush();
void GetStorageUsage(GetStorageUsageCallback callback);
+
void DeleteStorage(const url::Origin& origin,
- const std::string& persistent_namespace_id);
+ const std::string& namespace_id);
- // Called when the owning BrowserContext is ending.
- // Schedules the commit of any unsaved changes and will delete
- // and keep data on disk per the content settings and special storage
- // policies.
+ // Called when the owning BrowserContext is ending. Schedules the commit of
+ // any unsaved changes then deletes this object. All data on disk (where there
+ // was no call to |DeleteSessionNamespace| will stay on disk for later
+ // restoring.
void ShutdownAndDelete();
// Clears any caches, to free up as much memory as possible. Next access to
@@ -77,16 +87,148 @@ class CONTENT_EXPORT SessionStorageContextMojo {
// Clears unused leveldb wrappers, when thresholds are reached.
void PurgeUnusedWrappersIfNeeded();
- base::WeakPtr<SessionStorageContextMojo> AsWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
+ // Any namespaces that have been loaded from disk and have not had a
+ // corresponding CreateSessionNamespace() call will be deleted. Called after
+ // startup. The calback is used for unittests, and is called after the
+ // scavenging has finished (but not necessarily saved to disk). A null
+ // callback is ok.
+ void ScavengeUnusedNamespaces(base::OnceClosure done);
+
+ // base::trace_event::MemoryDumpProvider implementation:
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
+ // SessionStorageLevelDBWrapper::Listener implementation:
+ void OnDataMapCreation(const std::vector<uint8_t>& map_prefix,
+ SessionStorageDataMap* map) override;
+ void OnDataMapDestruction(const std::vector<uint8_t>& map_prefix) override;
+ void OnCommitResult(leveldb::mojom::DatabaseError error) override;
+
+ // Sets the database for testing.
+ void SetDatabaseForTesting(
+ leveldb::mojom::LevelDBDatabaseAssociatedPtr database);
+
+ leveldb::mojom::LevelDBDatabase* DatabaseForTesting() {
+ return database_.get();
}
+ void FlushAreaForTesting(const std::string& namespace_id,
+ const url::Origin& origin);
+
private:
+ // Object deletion is done through |ShutdownAndDelete()|.
+ ~SessionStorageContextMojo() override;
+
+ scoped_refptr<SessionStorageMetadata::MapData> RegisterNewAreaMap(
+ SessionStorageMetadata::NamespaceEntry namespace_entry,
+ const url::Origin& origin);
+
+ void RegisterShallowClonedNamespace(
+ SessionStorageMetadata::NamespaceEntry source_namespace_entry,
+ const std::string& new_namespace_id,
+ const SessionStorageNamespaceImplMojo::OriginAreas& clone_from_areas);
+
+ std::unique_ptr<SessionStorageNamespaceImplMojo>
+ CreateSessionStorageNamespaceImplMojo(std::string namespace_id);
+
+ void DoDatabaseDelete(const std::string& namespace_id);
+
+ // Runs |callback| immediately if already connected to a database, otherwise
+ // delays running |callback| untill after a connection has been established.
+ // Initiates connecting to the database if no connection is in progress yet.
+ void RunWhenConnected(base::OnceClosure callback);
+
+ // Part of our asynchronous directory opening called from RunWhenConnected().
+ void InitiateConnection(bool in_memory_only = false);
+ void OnDirectoryOpened(base::File::Error err);
+ void OnDatabaseOpened(bool in_memory, leveldb::mojom::DatabaseError status);
+ void OnGotDatabaseVersion(leveldb::mojom::DatabaseError status,
+ const std::vector<uint8_t>& value);
+ void OnGotNamespaces(
+ base::OnceClosure done,
+ std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations,
+ leveldb::mojom::DatabaseError status,
+ std::vector<leveldb::mojom::KeyValuePtr> values);
+ void OnGotNextMapId(base::OnceClosure done,
+ leveldb::mojom::DatabaseError status,
+ const std::vector<uint8_t>& map_id);
+ void OnConnectionFinished();
+ void DeleteAndRecreateDatabase(const char* histogram_name);
+ void OnDBDestroyed(bool recreate_in_memory,
+ leveldb::mojom::DatabaseError status);
+
+ void OnGotMetaData(GetStorageUsageCallback callback,
+ leveldb::mojom::DatabaseError status,
+ std::vector<leveldb::mojom::KeyValuePtr> data);
+
+ void OnShutdownComplete(leveldb::mojom::DatabaseError error);
+
+ void GetStatistics(size_t* total_cache_size, size_t* unused_wrapper_count);
+
+ // These values are written to logs. New enum values can be added, but
+ // existing enums must never be renumbered or deleted and reused.
+ enum class OpenResult {
+ kDirectoryOpenFailed = 0,
+ kDatabaseOpenFailed = 1,
+ kInvalidVersion = 2,
+ kVersionReadError = 3,
+ kNamespacesReadError = 4,
+ kSuccess = 6,
+ kMaxValue = kSuccess
+ };
+
+ void LogDatabaseOpenResult(OpenResult result);
+
+ // Since the session storage object hierarchy references iterators owned by
+ // the metadata, make sure it is destroyed last on destruction.
+ SessionStorageMetadata metadata_;
+
std::unique_ptr<service_manager::Connector> connector_;
const base::Optional<base::FilePath> partition_directory_path_;
std::string leveldb_name_;
- bool force_keep_session_state_ = false;
+ enum ConnectionState {
+ NO_CONNECTION,
+ FETCHING_METADATA,
+ CONNECTION_IN_PROGRESS,
+ CONNECTION_FINISHED,
+ CONNECTION_SHUTDOWN
+ } connection_state_ = NO_CONNECTION;
+ bool database_initialized_ = false;
+
+ file::mojom::FileSystemPtr file_system_;
+ filesystem::mojom::DirectoryPtr partition_directory_;
+
+ base::trace_event::MemoryAllocatorDumpGuid memory_dump_id_;
+
+ leveldb::mojom::LevelDBServicePtr leveldb_service_;
+ leveldb::mojom::LevelDBDatabaseAssociatedPtr database_;
+ bool tried_to_recreate_during_open_ = false;
+
+ std::vector<base::OnceClosure> on_database_opened_callbacks_;
+
+ // The removal of items from this map is managed by the refcounting in
+ // SessionStorageDataMap.
+ // Populated after the database is connected.
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*> data_maps_;
+ // Populated on OpenSessionStorage calls.
+ std::map<std::string, std::unique_ptr<SessionStorageNamespaceImplMojo>>
+ namespaces_;
+
+ // Scavenging only happens once.
+ bool has_scavenged_ = false;
+ // When namespaces are destroyed but marked as persistent, a scavenge should
+ // not delete them. Cleared after ScavengeUnusedNamespaces is called.
+ std::set<std::string> protected_namespaces_from_scavenge_;
+
+ bool is_low_end_device_;
+ // Counts consecutive commit errors. If this number reaches a threshold, the
+ // whole database is thrown away.
+ int commit_error_count_ = 0;
+ bool tried_to_recover_from_commit_errors_ = false;
+
+ // Name of an extra histogram to log open results to, if not null.
+ const char* open_result_histogram_ = nullptr;
base::WeakPtrFactory<SessionStorageContextMojo> weak_ptr_factory_;
};
diff --git a/chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc b/chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
new file mode 100644
index 00000000000..1b9ee547d47
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
@@ -0,0 +1,762 @@
+// 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/dom_storage/session_storage_context_mojo.h"
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/guid.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "content/browser/dom_storage/session_storage_database.h"
+#include "content/browser/dom_storage/test/fake_leveldb_database_error_on_write.h"
+#include "content/browser/dom_storage/test/fake_leveldb_service.h"
+#include "content/browser/dom_storage/test/mojo_test_with_file_service.h"
+#include "content/common/dom_storage/dom_storage_types.h"
+#include "content/public/browser/session_storage_usage_info.h"
+#include "content/public/common/content_features.h"
+#include "content/public/test/test_utils.h"
+#include "content/test/leveldb_wrapper_test_util.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "services/file/file_service.h"
+#include "services/file/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#include "services/service_manager/public/cpp/test/test_service_decorator.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+using leveldb::StdStringToUint8Vector;
+using leveldb::String16ToUint8Vector;
+using leveldb::Uint8VectorToStdString;
+using leveldb::mojom::DatabaseError;
+using leveldb::mojom::KeyValuePtr;
+
+static const char kSessionStorageDirectory[] = "Session Storage";
+static const int kTestProcessId = 0;
+
+void GetStorageUsageCallback(base::OnceClosure callback,
+ std::vector<SessionStorageUsageInfo>* out_result,
+ std::vector<SessionStorageUsageInfo> result) {
+ *out_result = std::move(result);
+ std::move(callback).Run();
+}
+
+class SessionStorageContextMojoTest : public test::MojoTestWithFileService {
+ public:
+ SessionStorageContextMojoTest() {}
+
+ ~SessionStorageContextMojoTest() override {
+ if (context_)
+ ShutdownContext();
+ }
+
+ void SetUp() override {
+ features_.InitAndEnableFeature(features::kMojoSessionStorage);
+ }
+
+ SessionStorageContextMojo* context() {
+ if (!context_) {
+ context_ = new SessionStorageContextMojo(
+ base::SequencedTaskRunnerHandle::Get(), connector(), base::FilePath(),
+ kSessionStorageDirectory);
+ }
+ return context_;
+ }
+
+ void ShutdownContext() {
+ context_->ShutdownAndDelete();
+ context_ = nullptr;
+ base::RunLoop().RunUntilIdle();
+ }
+
+ std::vector<SessionStorageUsageInfo> GetStorageUsageSync() {
+ base::RunLoop run_loop;
+ std::vector<SessionStorageUsageInfo> result;
+ context()->GetStorageUsage(base::BindOnce(&GetStorageUsageCallback,
+ run_loop.QuitClosure(), &result));
+ run_loop.Run();
+ return result;
+ }
+
+ void DoTestPut(const std::string& namespace_id,
+ const url::Origin& origin,
+ base::StringPiece key,
+ base::StringPiece value,
+ const std::string& source) {
+ context()->CreateSessionNamespace(namespace_id);
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ mojo::MakeRequest(&ss_namespace));
+ mojom::LevelDBWrapperAssociatedPtr leveldb;
+ ss_namespace->OpenArea(origin, mojo::MakeRequest(&leveldb));
+ EXPECT_TRUE(test::PutSync(
+ leveldb.get(), leveldb::StringPieceToUint8Vector(key),
+ leveldb::StringPieceToUint8Vector(value), base::nullopt, source));
+ context()->DeleteSessionNamespace(namespace_id, true);
+ }
+
+ base::Optional<std::vector<uint8_t>> DoTestGet(
+ const std::string& namespace_id,
+ const url::Origin& origin,
+ base::StringPiece key) {
+ context()->CreateSessionNamespace(namespace_id);
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ mojo::MakeRequest(&ss_namespace));
+ mojom::LevelDBWrapperAssociatedPtr leveldb;
+ ss_namespace->OpenArea(origin, mojo::MakeRequest(&leveldb));
+
+ // Use the GetAll interface because Gets are being removed.
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ context()->DeleteSessionNamespace(namespace_id, true);
+
+ std::vector<uint8_t> key_as_bytes = leveldb::StringPieceToUint8Vector(key);
+ for (const auto& key_value : data) {
+ if (key_value->key == key_as_bytes) {
+ return key_value->value;
+ }
+ }
+ return base::nullopt;
+ }
+
+ private:
+ base::test::ScopedFeatureList features_;
+ SessionStorageContextMojo* context_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(SessionStorageContextMojoTest);
+};
+
+TEST_F(SessionStorageContextMojoTest, MigrationV0ToV1) {
+ std::string namespace_id1 = base::GenerateGUID();
+ std::string namespace_id2 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ url::Origin origin2 = url::Origin::Create(GURL("http://example.com"));
+ base::string16 key = base::ASCIIToUTF16("key");
+ base::string16 value = base::ASCIIToUTF16("value");
+ base::string16 key2 = base::ASCIIToUTF16("key2");
+ key2.push_back(0xd83d);
+ key2.push_back(0xde00);
+
+ base::FilePath old_db_path =
+ temp_path().AppendASCII(kSessionStorageDirectory);
+ {
+ scoped_refptr<SessionStorageDatabase> db =
+ base::MakeRefCounted<SessionStorageDatabase>(
+ old_db_path, base::ThreadTaskRunnerHandle::Get().get());
+ DOMStorageValuesMap data;
+ data[key] = base::NullableString16(value, false);
+ data[key2] = base::NullableString16(value, false);
+ EXPECT_TRUE(db->CommitAreaChanges(namespace_id1, origin1, false, data));
+ EXPECT_TRUE(db->CloneNamespace(namespace_id1, namespace_id2));
+ }
+ EXPECT_TRUE(base::PathExists(old_db_path));
+
+ // The first call to context() here constructs it.
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->CreateSessionNamespace(namespace_id2);
+
+ mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ mojom::SessionStorageNamespacePtr ss_namespace2;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ mojo::MakeRequest(&ss_namespace2));
+
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o1;
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o2;
+ ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
+ ss_namespace2->OpenArea(origin2, mojo::MakeRequest(&leveldb_n2_o2));
+
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_n2_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ // There should have been a migration to get rid of the "map-0-" refcount
+ // field.
+ EXPECT_EQ(2ul, data.size());
+ std::vector<uint8_t> key_as_vector =
+ StdStringToUint8Vector(base::UTF16ToUTF8(key));
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(key_as_vector, String16ToUint8Vector(value))));
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(key_as_vector, String16ToUint8Vector(value))));
+}
+
+TEST_F(SessionStorageContextMojoTest, StartupShutdownSave) {
+ std::string namespace_id1 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ context()->CreateSessionNamespace(namespace_id1);
+
+ mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // Verify no data.
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_n1_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(0ul, data.size());
+
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+
+ // Verify data is there.
+ status = test::GetAllSync(leveldb_n1_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+
+ // Delete the namespace and shutdown the context, BUT persist the namespace so
+ // it can be loaded again.
+ context()->DeleteSessionNamespace(namespace_id1, true);
+ ShutdownContext();
+
+ // This will re-open the context, and load the persisted namespace.
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // The data from before should be here.
+ status = test::GetAllSync(leveldb_n1_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+
+ // Delete the namespace and shutdown the context and do not persist the data.
+ context()->DeleteSessionNamespace(namespace_id1, false);
+ ShutdownContext();
+
+ // This will re-open the context, and the namespace should be empty.
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // The data from before should be here.
+ status = test::GetAllSync(leveldb_n1_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(0ul, data.size());
+}
+
+TEST_F(SessionStorageContextMojoTest, Cloning) {
+ std::string namespace_id1 = base::GenerateGUID();
+ std::string namespace_id2 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ context()->CreateSessionNamespace(namespace_id1);
+ mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // Context-triggered clone before the put. The clone doesn't actually count
+ // until a clone comes from the namespace.
+ context()->CloneSessionNamespace(namespace_id1, namespace_id2);
+
+ // Put some data.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+
+ ss_namespace1->Clone(namespace_id2);
+ leveldb_n1_o1.FlushForTesting();
+
+ // Open the second namespace.
+ mojom::SessionStorageNamespacePtr ss_namespace2;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+ mojo::MakeRequest(&ss_namespace2));
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o1;
+ ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
+
+ // Delete the namespace and shutdown the context, BUT persist the namespace so
+ // it can be loaded again. This tests the case where our cloning works even
+ // though the namespace is deleted (but persisted on disk).
+ context()->DeleteSessionNamespace(namespace_id1, true);
+
+ // The data from before should be in namespace 2.
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_n2_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+
+ // Put some data in namespace 2.
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n2_o1.get(), leveldb::StringPieceToUint8Vector("key2"),
+ leveldb::StringPieceToUint8Vector("value2"), base::nullopt, "source1"));
+ status = test::GetAllSync(leveldb_n2_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(2ul, data.size());
+
+ // Re-open namespace 1, check that we don't have the extra data.
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+ // We should only have the first value.
+ status = test::GetAllSync(leveldb_n1_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+}
+
+TEST_F(SessionStorageContextMojoTest, Scavenging) {
+ // Create our namespace, destroy our context and leave that namespace on disk,
+ // and verify that it is scavenged if we re-create the context without calling
+ // CreateSessionNamespace.
+
+ // Create, verify we have no data.
+ std::string namespace_id1 = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ context()->CreateSessionNamespace(namespace_id1);
+
+ // This scavenge call should NOT delete the namespace, as we just created it.
+ {
+ base::RunLoop loop;
+ context()->ScavengeUnusedNamespaces(loop.QuitClosure());
+ loop.Run();
+ }
+ // Restart context.
+ ShutdownContext();
+ context()->CreateSessionNamespace(namespace_id1);
+
+ mojom::SessionStorageNamespacePtr ss_namespace1;
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n1_o1;
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+ EXPECT_TRUE(test::PutSync(
+ leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+ leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+
+ // This scavenge call should NOT delete the namespace, as we never called
+ // delete.
+ context()->ScavengeUnusedNamespaces(base::OnceClosure());
+
+ // Restart context.
+ ShutdownContext();
+ context()->CreateSessionNamespace(namespace_id1);
+
+ // Delete the namespace and shutdown the context, BUT persist the namespace so
+ // it can be loaded again.
+ context()->DeleteSessionNamespace(namespace_id1, true);
+
+ // This scavenge call should NOT delete the namespace, as we explicity
+ // persisted the namespace.
+ {
+ base::RunLoop loop;
+ context()->ScavengeUnusedNamespaces(loop.QuitClosure());
+ loop.Run();
+ }
+
+ ShutdownContext();
+
+ // Re-open the context, load the persisted namespace, and verify we still have
+ // data.
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_n1_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+
+ // Shutting down the context without an explicit DeleteSessionNamespace should
+ // leave the data on disk.
+ ShutdownContext();
+
+ // Re-open the context, and scavenge should now remove the namespace as there
+ // has been no call to CreateSessionNamespace. Check the data is empty.
+ {
+ base::RunLoop loop;
+ context()->ScavengeUnusedNamespaces(loop.QuitClosure());
+ loop.Run();
+ }
+ context()->CreateSessionNamespace(namespace_id1);
+ context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+ mojo::MakeRequest(&ss_namespace1));
+ ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+ status = test::GetAllSync(leveldb_n1_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(0ul, data.size());
+}
+
+TEST_F(SessionStorageContextMojoTest, InvalidVersionOnDisk) {
+ std::string namespace_id = base::GenerateGUID();
+ url::Origin origin = url::Origin::Create(GURL("http://foobar.com"));
+
+ // Create context and add some data to it (and check it's there).
+ DoTestPut(namespace_id, origin, "key", "value", "source");
+ base::Optional<std::vector<uint8_t>> opt_value =
+ DoTestGet(namespace_id, origin, "key");
+ ASSERT_TRUE(opt_value);
+ EXPECT_EQ(leveldb::StringPieceToUint8Vector("value"), opt_value.value());
+
+ ShutdownContext();
+ {
+ // Mess up version number in database.
+ leveldb_env::ChromiumEnv env;
+ std::unique_ptr<leveldb::DB> db;
+ leveldb_env::Options options;
+ options.env = &env;
+ base::FilePath db_path =
+ temp_path().Append(FILE_PATH_LITERAL("Session Storage"));
+ ASSERT_TRUE(leveldb_env::OpenDB(options, db_path.AsUTF8Unsafe(), &db).ok());
+ ASSERT_TRUE(db->Put(leveldb::WriteOptions(), "version", "argh").ok());
+ }
+
+ opt_value = DoTestGet(namespace_id, origin, "key");
+ EXPECT_FALSE(opt_value);
+
+ // Write data again.
+ DoTestPut(namespace_id, origin, "key", "value", "source");
+
+ ShutdownContext();
+
+ // Data should have been preserved now.
+ opt_value = DoTestGet(namespace_id, origin, "key");
+ ASSERT_TRUE(opt_value);
+ EXPECT_EQ(leveldb::StringPieceToUint8Vector("value"), opt_value.value());
+ ShutdownContext();
+}
+
+TEST_F(SessionStorageContextMojoTest, CorruptionOnDisk) {
+ std::string namespace_id = base::GenerateGUID();
+ url::Origin origin = url::Origin::Create(GURL("http://foobar.com"));
+
+ // Create context and add some data to it (and check it's there).
+ DoTestPut(namespace_id, origin, "key", "value", "source");
+ base::Optional<std::vector<uint8_t>> opt_value =
+ DoTestGet(namespace_id, origin, "key");
+ ASSERT_TRUE(opt_value);
+ EXPECT_EQ(leveldb::StringPieceToUint8Vector("value"), opt_value.value());
+
+ ShutdownContext();
+ // Also flush Task Scheduler tasks to make sure the leveldb is fully closed.
+ content::RunAllTasksUntilIdle();
+
+ // Delete manifest files to mess up opening DB.
+ base::FilePath db_path =
+ temp_path().Append(FILE_PATH_LITERAL("Session Storage"));
+ base::FileEnumerator file_enum(db_path, true, base::FileEnumerator::FILES,
+ FILE_PATH_LITERAL("MANIFEST*"));
+ for (base::FilePath name = file_enum.Next(); !name.empty();
+ name = file_enum.Next()) {
+ base::DeleteFile(name, false);
+ }
+ opt_value = DoTestGet(namespace_id, origin, "key");
+ EXPECT_FALSE(opt_value);
+
+ // Write data again.
+ DoTestPut(namespace_id, origin, "key", "value", "source");
+
+ ShutdownContext();
+
+ // Data should have been preserved now.
+ opt_value = DoTestGet(namespace_id, origin, "key");
+ ASSERT_TRUE(opt_value);
+ EXPECT_EQ(leveldb::StringPieceToUint8Vector("value"), opt_value.value());
+ ShutdownContext();
+}
+
+TEST_F(SessionStorageContextMojoTest, RecreateOnCommitFailure) {
+ std::string namespace_id = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+ url::Origin origin2 = url::Origin::Create(GURL("http://asf.com"));
+ url::Origin origin3 = url::Origin::Create(GURL("http://example.com"));
+
+ test::FakeLevelDBService fake_leveldb_service;
+ ResetFileServiceAndConnector(
+ service_manager::TestServiceDecorator::CreateServiceWithUniqueOverride(
+ file::CreateFileService(), leveldb::mojom::LevelDBService::Name_,
+ base::BindRepeating(&test::FakeLevelDBService::Bind,
+ base::Unretained(&fake_leveldb_service))));
+
+ // Open three connections to the database.
+ mojom::LevelDBWrapperAssociatedPtr wrapper1;
+ mojom::LevelDBWrapperAssociatedPtr wrapper2;
+ mojom::LevelDBWrapperAssociatedPtr wrapper3;
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ context()->CreateSessionNamespace(namespace_id);
+ {
+ base::RunLoop loop;
+ fake_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
+ context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ mojo::MakeRequest(&ss_namespace));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper1));
+ ss_namespace->OpenArea(origin2, mojo::MakeRequest(&wrapper2));
+ ss_namespace->OpenArea(origin3, mojo::MakeRequest(&wrapper3));
+ loop.Run();
+ }
+
+ // Add observers to the first two connections.
+ testing::StrictMock<test::MockLevelDBObserver> observer1;
+ wrapper1->AddObserver(observer1.Bind());
+ EXPECT_FALSE(wrapper1.encountered_error());
+ testing::StrictMock<test::MockLevelDBObserver> observer3;
+ wrapper3->AddObserver(observer3.Bind());
+
+ // Verify one attempt was made to open the database, and connect that request
+ // with a database implementation that always fails on write.
+ ASSERT_EQ(1u, fake_leveldb_service.open_requests().size());
+ auto& open_request = fake_leveldb_service.open_requests()[0];
+ std::map<std::vector<uint8_t>, std::vector<uint8_t>> test_data;
+ auto mock_db = mojo::MakeStrongAssociatedBinding(
+ std::make_unique<test::FakeLevelDBDatabaseErrorOnWrite>(&test_data),
+ std::move(open_request.request));
+ std::move(open_request.callback).Run(leveldb::mojom::DatabaseError::OK);
+ fake_leveldb_service.open_requests().clear();
+
+ // Setup a RunLoop so we can wait until LocalStorageContextMojo tries to
+ // reconnect to the database, which should happen after several commit
+ // errors.
+ base::RunLoop reopen_loop;
+ fake_leveldb_service.SetOnOpenCallback(reopen_loop.QuitClosure());
+
+ // Start a put operation on the third connection before starting to commit
+ // a lot of data on the first origin. This put operation should result in a
+ // pending commit that will get cancelled when the database connection is
+ // closed.
+ auto value = leveldb::StringPieceToUint8Vector("avalue");
+ EXPECT_CALL(observer3, KeyAdded(leveldb::StringPieceToUint8Vector("w3key"),
+ value, "source"))
+ .Times(1);
+ wrapper3->Put(leveldb::StringPieceToUint8Vector("w3key"), value,
+ base::nullopt, "source",
+ base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
+
+ // Repeatedly write data to the database, to trigger enough commit errors.
+ int i = 0;
+ while (!wrapper1.encountered_error()) {
+ ++i;
+ base::RunLoop put_loop;
+ // Every write needs to be different to make sure there actually is a
+ // change to commit.
+ std::vector<uint8_t> old_value = value;
+ value[0]++;
+ wrapper1.set_connection_error_handler(put_loop.QuitClosure());
+
+ if (i == 1) {
+ EXPECT_CALL(observer1, ShouldSendOldValueOnMutations(false)).Times(1);
+ EXPECT_CALL(observer1, KeyAdded(leveldb::StringPieceToUint8Vector("key"),
+ value, "source"))
+ .Times(1);
+ } else {
+ EXPECT_CALL(observer1,
+ KeyChanged(leveldb::StringPieceToUint8Vector("key"), value,
+ old_value, "source"))
+ .Times(1);
+ }
+ wrapper1->Put(leveldb::StringPieceToUint8Vector("key"), value,
+ base::nullopt, "source",
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
+ wrapper1.FlushForTesting();
+ put_loop.RunUntilIdle();
+ // And we need to flush after every change. Otherwise changes get batched up
+ // and only one commit is done some time later.
+ context()->FlushAreaForTesting(namespace_id, origin1);
+ }
+ // Make sure all messages to the DB have been processed (Flush above merely
+ // schedules a commit, but there is no guarantee about those having been
+ // processed yet).
+ if (mock_db)
+ mock_db->FlushForTesting();
+ // At this point enough commit failures should have happened to cause the
+ // connection to the database to have been severed.
+ EXPECT_FALSE(mock_db);
+
+ // The connection to the second wrapper should have closed as well.
+ EXPECT_TRUE(wrapper2.encountered_error());
+ EXPECT_TRUE(ss_namespace.encountered_error());
+
+ // And the old database should have been destroyed.
+ EXPECT_EQ(1u, fake_leveldb_service.destroy_requests().size());
+
+ // Reconnect wrapper1 to the database, and try to read a value.
+ context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ mojo::MakeRequest(&ss_namespace));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper1));
+
+ base::RunLoop delete_loop;
+ bool success = true;
+ test::MockLevelDBObserver observer4;
+ wrapper1->AddObserver(observer4.Bind());
+ wrapper1->Delete(leveldb::StringPieceToUint8Vector("key"), base::nullopt,
+ "source", base::BindLambdaForTesting([&](bool success_in) {
+ success = success_in;
+ delete_loop.Quit();
+ }));
+
+ // Wait for LocalStorageContextMojo to try to reconnect to the database, and
+ // connect that new request to a properly functioning database.
+ reopen_loop.Run();
+ ASSERT_EQ(1u, fake_leveldb_service.open_requests().size());
+ auto& reopen_request = fake_leveldb_service.open_requests()[0];
+ mock_db = mojo::MakeStrongAssociatedBinding(
+ std::make_unique<FakeLevelDBDatabase>(&test_data),
+ std::move(reopen_request.request));
+ std::move(reopen_request.callback).Run(leveldb::mojom::DatabaseError::OK);
+ fake_leveldb_service.open_requests().clear();
+
+ // And deleting the value from the new wrapper should have failed (as the
+ // database is empty).
+ delete_loop.Run();
+ wrapper1 = nullptr;
+ ss_namespace.reset();
+ context()->DeleteSessionNamespace(namespace_id, true);
+
+ {
+ // Committing data should now work.
+ DoTestPut(namespace_id, origin1, "key", "value", "source");
+ base::Optional<std::vector<uint8_t>> opt_value =
+ DoTestGet(namespace_id, origin1, "key");
+ ASSERT_TRUE(opt_value);
+ EXPECT_EQ(leveldb::StringPieceToUint8Vector("value"), opt_value.value());
+ }
+}
+
+TEST_F(SessionStorageContextMojoTest, DontRecreateOnRepeatedCommitFailure) {
+ std::string namespace_id = base::GenerateGUID();
+ url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+
+ test::FakeLevelDBService fake_leveldb_service;
+ ResetFileServiceAndConnector(
+ service_manager::TestServiceDecorator::CreateServiceWithUniqueOverride(
+ file::CreateFileService(), leveldb::mojom::LevelDBService::Name_,
+ base::BindRepeating(&test::FakeLevelDBService::Bind,
+ base::Unretained(&fake_leveldb_service))));
+
+ std::map<std::vector<uint8_t>, std::vector<uint8_t>> test_data;
+
+ // Open three connections to the database.
+ mojom::LevelDBWrapperAssociatedPtr wrapper;
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ context()->CreateSessionNamespace(namespace_id);
+ {
+ base::RunLoop loop;
+ fake_leveldb_service.SetOnOpenCallback(loop.QuitClosure());
+ context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ mojo::MakeRequest(&ss_namespace));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper));
+ loop.Run();
+ }
+
+ // Verify one attempt was made to open the database, and connect that request
+ // with a database implementation that always fails on write.
+ ASSERT_EQ(1u, fake_leveldb_service.open_requests().size());
+ auto& open_request = fake_leveldb_service.open_requests()[0];
+ auto mock_db = mojo::MakeStrongAssociatedBinding(
+ std::make_unique<test::FakeLevelDBDatabaseErrorOnWrite>(&test_data),
+ std::move(open_request.request));
+ std::move(open_request.callback).Run(leveldb::mojom::DatabaseError::OK);
+ fake_leveldb_service.open_requests().clear();
+
+ // Setup a RunLoop so we can wait until LocalStorageContextMojo tries to
+ // reconnect to the database, which should happen after several commit
+ // errors.
+ base::RunLoop reopen_loop;
+ fake_leveldb_service.SetOnOpenCallback(reopen_loop.QuitClosure());
+
+ // Repeatedly write data to the database, to trigger enough commit errors.
+ auto value = leveldb::StringPieceToUint8Vector("avalue");
+ base::Optional<std::vector<uint8_t>> old_value = base::nullopt;
+ while (!wrapper.encountered_error()) {
+ base::RunLoop put_loop;
+ // Every write needs to be different to make sure there actually is a
+ // change to commit.
+ wrapper.set_connection_error_handler(put_loop.QuitClosure());
+ wrapper->Put(leveldb::StringPieceToUint8Vector("key"), value, old_value,
+ "source", base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
+ wrapper.FlushForTesting();
+ put_loop.RunUntilIdle();
+ // And we need to flush after every change. Otherwise changes get batched up
+ // and only one commit is done some time later.
+ context()->FlushAreaForTesting(namespace_id, origin1);
+
+ old_value = value;
+ value[0]++;
+ }
+ // Make sure all messages to the DB have been processed (Flush above merely
+ // schedules a commit, but there is no guarantee about those having been
+ // processed yet).
+ if (mock_db)
+ mock_db->FlushForTesting();
+ // At this point enough commit failures should have happened to cause the
+ // connection to the database to have been severed.
+ EXPECT_FALSE(mock_db);
+
+ // Wait for LocalStorageContextMojo to try to reconnect to the database, and
+ // connect that new request with a database implementation that always fails
+ // on write.
+ reopen_loop.Run();
+ ASSERT_EQ(1u, fake_leveldb_service.open_requests().size());
+ auto& reopen_request = fake_leveldb_service.open_requests()[0];
+ mock_db = mojo::MakeStrongAssociatedBinding(
+ std::make_unique<test::FakeLevelDBDatabaseErrorOnWrite>(&test_data),
+ std::move(reopen_request.request));
+ std::move(reopen_request.callback).Run(leveldb::mojom::DatabaseError::OK);
+ fake_leveldb_service.open_requests().clear();
+
+ // The old database should also have been destroyed.
+ EXPECT_EQ(1u, fake_leveldb_service.destroy_requests().size());
+
+ // Reconnect a wrapper to the database, and repeatedly write data to it again.
+ // This time all should just keep getting written, and commit errors are
+ // getting ignored.
+ context()->OpenSessionStorage(kTestProcessId, namespace_id,
+ mojo::MakeRequest(&ss_namespace));
+ ss_namespace->OpenArea(origin1, mojo::MakeRequest(&wrapper));
+ old_value = base::nullopt;
+ for (int i = 0; i < 64; ++i) {
+ base::RunLoop put_loop;
+ // Every write needs to be different to make sure there actually is a
+ // change to commit.
+ wrapper.set_connection_error_handler(put_loop.QuitClosure());
+ wrapper->Put(leveldb::StringPieceToUint8Vector("key"), value, old_value,
+ "source", base::BindLambdaForTesting([&](bool success) {
+ EXPECT_TRUE(success);
+ put_loop.Quit();
+ }));
+ wrapper.FlushForTesting();
+ put_loop.RunUntilIdle();
+ // And we need to flush after every change. Otherwise changes get batched up
+ // and only one commit is done some time later.
+ context()->FlushAreaForTesting(namespace_id, origin1);
+
+ old_value = value;
+ value[0]++;
+ }
+ // Make sure all messages to the DB have been processed (Flush above merely
+ // schedules a commit, but there is no guarantee about those having been
+ // processed yet).
+ if (mock_db)
+ mock_db->FlushForTesting();
+ EXPECT_TRUE(mock_db);
+ EXPECT_FALSE(wrapper.encountered_error());
+
+ context()->DeleteSessionNamespace(namespace_id, false);
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_data_map.cc b/chromium/content/browser/dom_storage/session_storage_data_map.cc
new file mode 100644
index 00000000000..4580e195381
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_data_map.cc
@@ -0,0 +1,105 @@
+// 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/dom_storage/session_storage_data_map.h"
+
+#include "base/sys_info.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "content/common/dom_storage/dom_storage_types.h"
+
+namespace content {
+
+// static
+scoped_refptr<SessionStorageDataMap> SessionStorageDataMap::Create(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_data,
+ leveldb::mojom::LevelDBDatabase* database) {
+ return base::WrapRefCounted(
+ new SessionStorageDataMap(listener, std::move(map_data), database));
+}
+
+// static
+scoped_refptr<SessionStorageDataMap> SessionStorageDataMap::CreateClone(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_data,
+ LevelDBWrapperImpl* clone_from) {
+ return base::WrapRefCounted(
+ new SessionStorageDataMap(listener, std::move(map_data), clone_from));
+}
+
+std::vector<leveldb::mojom::BatchedOperationPtr>
+SessionStorageDataMap::PrepareToCommit() {
+ return std::vector<leveldb::mojom::BatchedOperationPtr>();
+}
+
+void SessionStorageDataMap::DidCommit(leveldb::mojom::DatabaseError error) {
+ listener_->OnCommitResult(error);
+}
+
+SessionStorageDataMap::SessionStorageDataMap(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_data,
+ leveldb::mojom::LevelDBDatabase* database)
+ : listener_(listener),
+ map_data_(std::move(map_data)),
+ wrapper_impl_(std::make_unique<LevelDBWrapperImpl>(database,
+ map_data_->KeyPrefix(),
+ this,
+ GetOptions())),
+ level_db_wrapper_ptr_(wrapper_impl_.get()) {
+ DCHECK(listener_);
+ DCHECK(map_data_);
+ listener_->OnDataMapCreation(map_data_->MapNumberAsBytes(), this);
+}
+
+SessionStorageDataMap::SessionStorageDataMap(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_data,
+ LevelDBWrapperImpl* forking_from)
+ : listener_(listener),
+ map_data_(std::move(map_data)),
+ wrapper_impl_(forking_from->ForkToNewPrefix(map_data_->KeyPrefix(),
+ this,
+ GetOptions())),
+ level_db_wrapper_ptr_(wrapper_impl_.get()) {
+ DCHECK(listener_);
+ DCHECK(map_data_);
+ listener_->OnDataMapCreation(map_data_->MapNumberAsBytes(), this);
+}
+
+SessionStorageDataMap::~SessionStorageDataMap() {
+ listener_->OnDataMapDestruction(map_data_->MapNumberAsBytes());
+}
+
+void SessionStorageDataMap::RemoveBindingReference() {
+ DCHECK_GT(binding_count_, 0);
+ --binding_count_;
+ if (binding_count_ > 0)
+ return;
+ // Don't delete ourselves, but do schedule an immediate commit. Possible
+ // deletion will happen under memory pressure or when another sessionstorage
+ // area is opened.
+ level_db_wrapper()->ScheduleImmediateCommit();
+}
+
+// static
+LevelDBWrapperImpl::Options SessionStorageDataMap::GetOptions() {
+ // Delay for a moment after a value is set in anticipation
+ // of other values being set, so changes are batched.
+ constexpr const base::TimeDelta kCommitDefaultDelaySecs =
+ base::TimeDelta::FromSeconds(5);
+
+ // To avoid excessive IO we apply limits to the amount of data being
+ // written and the frequency of writes.
+ LevelDBWrapperImpl::Options options;
+ options.max_size = kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance;
+ options.default_commit_delay = kCommitDefaultDelaySecs;
+ options.max_bytes_per_hour = kPerStorageAreaQuota;
+ options.max_commits_per_hour = 60;
+ options.cache_mode = LevelDBWrapperImpl::CacheMode::KEYS_ONLY_WHEN_POSSIBLE;
+ return options;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_data_map.h b/chromium/content/browser/dom_storage/session_storage_data_map.h
new file mode 100644
index 00000000000..b4f60811a9a
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_data_map.h
@@ -0,0 +1,107 @@
+// 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_DOM_STORAGE_SESSION_STORAGE_DATA_MAP_H_
+#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATA_MAP_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/optional.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/browser/leveldb_wrapper_impl.h"
+#include "content/common/content_export.h"
+#include "content/common/leveldb_wrapper.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+
+namespace content {
+
+// Holds the LevelDBWrapper for a session storage data map. Every
+// namespace-origin area has a data map. To support shallow copying of the data
+// (copy-on-write), a single data map can be shared between multiple namespaces.
+// Thus this class is refcounted. This class has a one-to-one relationship with
+// the SessionStorageMetadata::MapData object, accessible from |map_data()|.
+//
+// Neither this data map nor the inner LevelDBWrapper is bound to, as it needs
+// to be shared between multiple connections if it is shallow-copied. However,
+// it does allow it's user to keep track of the number of binding using
+// |binding_count()|, |AddBindingReference()|, and |RemoveBindingReference()|.
+class CONTENT_EXPORT SessionStorageDataMap final
+ : public LevelDBWrapperImpl::Delegate,
+ public base::RefCounted<SessionStorageDataMap> {
+ public:
+ class CONTENT_EXPORT Listener {
+ public:
+ virtual ~Listener() {}
+ virtual void OnDataMapCreation(const std::vector<uint8_t>& map_id,
+ SessionStorageDataMap* map) = 0;
+ virtual void OnDataMapDestruction(const std::vector<uint8_t>& map_id) = 0;
+ virtual void OnCommitResult(leveldb::mojom::DatabaseError error) = 0;
+ };
+
+ static scoped_refptr<SessionStorageDataMap> Create(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_data,
+ leveldb::mojom::LevelDBDatabase* database);
+
+ static scoped_refptr<SessionStorageDataMap> CreateClone(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_data,
+ LevelDBWrapperImpl* clone_from);
+
+ Listener* listener() const { return listener_; }
+
+ LevelDBWrapperImpl* level_db_wrapper() { return level_db_wrapper_ptr_; }
+
+ scoped_refptr<SessionStorageMetadata::MapData> map_data() {
+ return map_data_.get();
+ }
+
+ int binding_count() { return binding_count_; }
+ void AddBindingReference() { ++binding_count_; }
+ // When the binding count reaches 0, we schedule an immediate commit on our
+ // wrapper, but we don't close the connection.
+ void RemoveBindingReference();
+
+ // Note: this is irrelevant, as the parent wrapper is handling binding.
+ void OnNoBindings() override {}
+
+ std::vector<leveldb::mojom::BatchedOperationPtr> PrepareToCommit() override;
+
+ void DidCommit(leveldb::mojom::DatabaseError error) override;
+
+ private:
+ friend class base::RefCounted<SessionStorageDataMap>;
+
+ SessionStorageDataMap(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_entry,
+ leveldb::mojom::LevelDBDatabase* database);
+ SessionStorageDataMap(
+ Listener* listener,
+ scoped_refptr<SessionStorageMetadata::MapData> map_entry,
+ LevelDBWrapperImpl* forking_from);
+ ~SessionStorageDataMap() override;
+
+ static LevelDBWrapperImpl::Options GetOptions();
+
+ Listener* listener_;
+ int binding_count_ = 0;
+ scoped_refptr<SessionStorageMetadata::MapData> map_data_;
+ std::unique_ptr<LevelDBWrapperImpl> wrapper_impl_;
+ // Holds the same value as |wrapper_impl_|. The reason for this is that
+ // during destruction of the LevelDBWrapperImpl instance we might still get
+ // called and need access to the LevelDBWrapperImpl instance. The
+ // unique_ptr could already be null, but this field should still be valid.
+ // TODO(dmurph): Change delegate ownership so this doesn't have to be done.
+ LevelDBWrapperImpl* level_db_wrapper_ptr_;
+
+ DISALLOW_COPY_AND_ASSIGN(SessionStorageDataMap);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATA_MAP_H_
diff --git a/chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc b/chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc
new file mode 100644
index 00000000000..97af433c270
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_data_map_unittest.cc
@@ -0,0 +1,186 @@
+// 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/dom_storage/session_storage_data_map.h"
+
+#include <map>
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "content/test/fake_leveldb_database.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+using leveldb::StdStringToUint8Vector;
+using leveldb::Uint8VectorToStdString;
+
+class MockListener : public SessionStorageDataMap::Listener {
+ public:
+ MockListener() {}
+ ~MockListener() override {}
+ MOCK_METHOD2(OnDataMapCreation,
+ void(const std::vector<uint8_t>& map_id,
+ SessionStorageDataMap* map));
+ MOCK_METHOD1(OnDataMapDestruction, void(const std::vector<uint8_t>& map_id));
+ MOCK_METHOD1(OnCommitResult, void(leveldb::mojom::DatabaseError error));
+};
+
+void GetAllDataCallback(leveldb::mojom::DatabaseError* status_out,
+ std::vector<mojom::KeyValuePtr>* data_out,
+ leveldb::mojom::DatabaseError status,
+ std::vector<mojom::KeyValuePtr> data) {
+ *status_out = status;
+ *data_out = std::move(data);
+}
+
+base::OnceCallback<void(leveldb::mojom::DatabaseError status,
+ std::vector<mojom::KeyValuePtr> data)>
+MakeGetAllCallback(leveldb::mojom::DatabaseError* status_out,
+ std::vector<mojom::KeyValuePtr>* data_out) {
+ return base::BindOnce(&GetAllDataCallback, status_out, data_out);
+}
+
+class GetAllCallback : public mojom::LevelDBWrapperGetAllCallback {
+ public:
+ static mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo CreateAndBind(
+ bool* result,
+ base::OnceClosure callback) {
+ mojom::LevelDBWrapperGetAllCallbackAssociatedPtr ptr;
+ auto request = mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr);
+ mojo::MakeStrongAssociatedBinding(
+ base::WrapUnique(new GetAllCallback(result, std::move(callback))),
+ std::move(request));
+ return ptr.PassInterface();
+ }
+
+ private:
+ GetAllCallback(bool* result, base::OnceClosure callback)
+ : result_(result), callback_(std::move(callback)) {}
+ void Complete(bool success) override {
+ *result_ = success;
+ if (callback_)
+ std::move(callback_).Run();
+ }
+
+ bool* result_;
+ base::OnceClosure callback_;
+};
+
+class SessionStorageDataMapTest : public testing::Test {
+ public:
+ SessionStorageDataMapTest()
+ : test_origin_(url::Origin::Create(GURL("http://host1.com:1"))),
+ database_(&mock_data_) {
+ // Should show up in first map.
+ mock_data_[StdStringToUint8Vector("map-1-key1")] =
+ StdStringToUint8Vector("data1");
+ // Dummy data to verify we don't delete everything.
+ mock_data_[StdStringToUint8Vector("map-3-key1")] =
+ StdStringToUint8Vector("data3");
+ }
+ ~SessionStorageDataMapTest() override {}
+
+ protected:
+ base::test::ScopedTaskEnvironment task_environment_;
+ testing::StrictMock<MockListener> listener_;
+ url::Origin test_origin_;
+ std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_;
+ FakeLevelDBDatabase database_;
+};
+
+} // namespace
+
+TEST_F(SessionStorageDataMapTest, BasicEmptyCreation) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+
+ scoped_refptr<SessionStorageDataMap> map = SessionStorageDataMap::Create(
+ &listener_,
+ base::MakeRefCounted<SessionStorageMetadata::MapData>(1, test_origin_),
+ &database_);
+
+ leveldb::mojom::DatabaseError status;
+ std::vector<mojom::KeyValuePtr> data;
+ bool done = false;
+ base::RunLoop loop;
+ map->level_db_wrapper()->GetAll(
+ GetAllCallback::CreateAndBind(&done, loop.QuitClosure()),
+ MakeGetAllCallback(&status, &data));
+ loop.Run();
+
+ EXPECT_TRUE(done);
+ ASSERT_EQ(1u, data.size());
+ EXPECT_EQ(StdStringToUint8Vector("key1"), data[0]->key);
+ EXPECT_EQ(StdStringToUint8Vector("data1"), data[0]->value);
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+
+ // Test data is not cleared on deletion.
+ map = nullptr;
+ EXPECT_EQ(2u, mock_data_.size());
+}
+
+TEST_F(SessionStorageDataMapTest, Clone) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+
+ scoped_refptr<SessionStorageDataMap> map1 = SessionStorageDataMap::Create(
+ &listener_,
+ base::MakeRefCounted<SessionStorageMetadata::MapData>(1, test_origin_),
+ &database_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("2"), testing::_))
+ .Times(1);
+ // One call on fork.
+ EXPECT_CALL(listener_, OnCommitResult(leveldb::mojom::DatabaseError::OK))
+ .Times(1);
+
+ scoped_refptr<SessionStorageDataMap> map2 =
+ SessionStorageDataMap::CreateClone(
+ &listener_,
+ base::MakeRefCounted<SessionStorageMetadata::MapData>(2,
+ test_origin_),
+ map1->level_db_wrapper());
+
+ leveldb::mojom::DatabaseError status;
+ std::vector<mojom::KeyValuePtr> data;
+ bool done = false;
+ base::RunLoop loop;
+ map2->level_db_wrapper()->GetAll(
+ GetAllCallback::CreateAndBind(&done, loop.QuitClosure()),
+ MakeGetAllCallback(&status, &data));
+ loop.Run();
+
+ EXPECT_TRUE(done);
+ ASSERT_EQ(1u, data.size());
+ EXPECT_EQ(StdStringToUint8Vector("key1"), data[0]->key);
+ EXPECT_EQ(StdStringToUint8Vector("data1"), data[0]->value);
+
+ // Test that the data was copied.
+ EXPECT_EQ(StdStringToUint8Vector("data1"),
+ mock_data_[StdStringToUint8Vector("map-2-key1")]);
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("2")))
+ .Times(1);
+
+ // Test data is not cleared on deletion.
+ map1 = nullptr;
+ map2 = nullptr;
+ EXPECT_EQ(3u, mock_data_.size());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index ef35996152a..8af5497c82c 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -191,6 +191,7 @@ bool SessionStorageDatabase::CommitAreaChanges(
if (!GetMapForArea(namespace_id, origin.GetURL().spec(),
leveldb::ReadOptions(), &exists, &map_id))
return false;
+
if (exists) {
int64_t ref_count;
if (!GetMapRefCount(map_id, &ref_count))
@@ -398,6 +399,12 @@ void SessionStorageDatabase::OnMemoryDump(
tracker_dump->GetSizeInternal());
}
+void SessionStorageDatabase::SetDatabaseForTesting(
+ std::unique_ptr<leveldb::DB> db) {
+ CHECK(!db_);
+ db_ = std::move(db);
+}
+
bool SessionStorageDatabase::LazyOpen(bool create_if_needed) {
base::AutoLock auto_lock(db_lock_);
if (db_error_ || is_inconsistent_) {
diff --git a/chromium/content/browser/dom_storage/session_storage_database.h b/chromium/content/browser/dom_storage/session_storage_database.h
index 842213cd608..e1ec30e83d3 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.h
+++ b/chromium/content/browser/dom_storage/session_storage_database.h
@@ -99,6 +99,12 @@ class CONTENT_EXPORT SessionStorageDatabase
// Adds memory statistics to |pmd| for chrome://tracing.
void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd);
+ // Used in testing to set an easier to handle in-memory database. Should
+ // happen before any database operations.
+ void SetDatabaseForTesting(std::unique_ptr<leveldb::DB> db);
+
+ leveldb::DB* db() const { return db_.get(); }
+
private:
class DBOperation;
friend class SessionStorageDatabase::DBOperation;
diff --git a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.cc b/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.cc
new file mode 100644
index 00000000000..2e20a45d2c3
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.cc
@@ -0,0 +1,165 @@
+// 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/dom_storage/session_storage_leveldb_wrapper.h"
+
+#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
+#include "content/browser/dom_storage/session_storage_data_map.h"
+#include "content/common/dom_storage/dom_storage_types.h"
+#include "third_party/leveldatabase/env_chromium.h"
+
+namespace content {
+
+SessionStorageLevelDBWrapper::SessionStorageLevelDBWrapper(
+ SessionStorageMetadata::NamespaceEntry namespace_entry,
+ url::Origin origin,
+ scoped_refptr<SessionStorageDataMap> data_map,
+ RegisterNewAreaMap register_new_map_callback)
+ : namespace_entry_(namespace_entry),
+ origin_(std::move(origin)),
+ shared_data_map_(std::move(data_map)),
+ register_new_map_callback_(std::move(register_new_map_callback)),
+ binding_(this) {}
+
+SessionStorageLevelDBWrapper::~SessionStorageLevelDBWrapper() {
+ if (binding_.is_bound())
+ shared_data_map_->RemoveBindingReference();
+}
+
+void SessionStorageLevelDBWrapper::Bind(
+ mojom::LevelDBWrapperAssociatedRequest request) {
+ DCHECK(!IsBound());
+ shared_data_map_->AddBindingReference();
+ binding_.Bind(std::move(request));
+ binding_.set_connection_error_handler(
+ base::BindOnce(&SessionStorageLevelDBWrapper::OnConnectionError,
+ base::Unretained(this)));
+}
+
+std::unique_ptr<SessionStorageLevelDBWrapper>
+SessionStorageLevelDBWrapper::Clone(
+ SessionStorageMetadata::NamespaceEntry namespace_entry) {
+ DCHECK(namespace_entry_ != namespace_entry);
+ return base::WrapUnique(new SessionStorageLevelDBWrapper(
+ namespace_entry, origin_, shared_data_map_, register_new_map_callback_));
+}
+
+// LevelDBWrapper:
+void SessionStorageLevelDBWrapper::AddObserver(
+ mojom::LevelDBObserverAssociatedPtrInfo observer) {
+ mojom::LevelDBObserverAssociatedPtr observer_ptr;
+ observer_ptr.Bind(std::move(observer));
+ mojo::InterfacePtrSetElementId ptr_id =
+ shared_data_map_->level_db_wrapper()->AddObserver(
+ std::move(observer_ptr));
+ observer_ptrs_.push_back(ptr_id);
+}
+
+void SessionStorageLevelDBWrapper::Put(
+ const std::vector<uint8_t>& key,
+ const std::vector<uint8_t>& value,
+ const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const std::string& source,
+ PutCallback callback) {
+ DCHECK(IsBound());
+ DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
+ if (shared_data_map_->map_data()->ReferenceCount() > 1)
+ CreateNewMap(NewMapType::FORKED, base::nullopt);
+ shared_data_map_->level_db_wrapper()->Put(key, value, client_old_value,
+ source, std::move(callback));
+}
+
+void SessionStorageLevelDBWrapper::Delete(
+ const std::vector<uint8_t>& key,
+ const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const std::string& source,
+ DeleteCallback callback) {
+ DCHECK(IsBound());
+ DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
+ if (shared_data_map_->map_data()->ReferenceCount() > 1)
+ CreateNewMap(NewMapType::FORKED, base::nullopt);
+ shared_data_map_->level_db_wrapper()->Delete(key, client_old_value, source,
+ std::move(callback));
+}
+
+void SessionStorageLevelDBWrapper::DeleteAll(const std::string& source,
+ DeleteAllCallback callback) {
+ DCHECK(IsBound());
+ DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
+ if (shared_data_map_->map_data()->ReferenceCount() > 1) {
+ CreateNewMap(NewMapType::EMPTY_FROM_DELETE_ALL, source);
+ std::move(callback).Run(true);
+ return;
+ }
+ shared_data_map_->level_db_wrapper()->DeleteAll(source, std::move(callback));
+}
+
+void SessionStorageLevelDBWrapper::Get(const std::vector<uint8_t>& key,
+ GetCallback callback) {
+ DCHECK(IsBound());
+ DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
+ shared_data_map_->level_db_wrapper()->Get(key, std::move(callback));
+}
+
+void SessionStorageLevelDBWrapper::GetAll(
+ mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback,
+ GetAllCallback callback) {
+ DCHECK(IsBound());
+ DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
+ shared_data_map_->level_db_wrapper()->GetAll(std::move(complete_callback),
+ std::move(callback));
+}
+
+// Note: this can be called after invalidation of the |namespace_entry_|.
+void SessionStorageLevelDBWrapper::OnConnectionError() {
+ shared_data_map_->RemoveBindingReference();
+ // Make sure we totally unbind the binding - this doesn't seem to happen
+ // automatically on connection error. The bound status is used in the
+ // destructor to know if |RemoveBindingReference| was already called.
+ if (binding_.is_bound())
+ binding_.Unbind();
+}
+
+void SessionStorageLevelDBWrapper::CreateNewMap(
+ NewMapType map_type,
+ const base::Optional<std::string>& delete_all_source) {
+ std::vector<mojom::LevelDBObserverAssociatedPtr> ptrs_to_move;
+ for (const mojo::InterfacePtrSetElementId& ptr_id : observer_ptrs_) {
+ DCHECK(shared_data_map_->level_db_wrapper()->HasObserver(ptr_id));
+ ptrs_to_move.push_back(
+ shared_data_map_->level_db_wrapper()->RemoveObserver(ptr_id));
+ }
+ observer_ptrs_.clear();
+ shared_data_map_->RemoveBindingReference();
+ switch (map_type) {
+ case NewMapType::FORKED:
+ shared_data_map_ = SessionStorageDataMap::CreateClone(
+ shared_data_map_->listener(),
+ register_new_map_callback_.Run(namespace_entry_, origin_),
+ shared_data_map_->level_db_wrapper());
+ break;
+ case NewMapType::EMPTY_FROM_DELETE_ALL: {
+ // The code optimizes the 'delete all' for shared maps by just creating
+ // a new map instead of forking. However, we still need the observers to
+ // be correctly called. To do that, we manually call them here.
+ shared_data_map_ = SessionStorageDataMap::Create(
+ shared_data_map_->listener(),
+ register_new_map_callback_.Run(namespace_entry_, origin_),
+ shared_data_map_->level_db_wrapper()->database());
+ for (auto& ptr : ptrs_to_move) {
+ ptr->AllDeleted(delete_all_source.value_or("\n"));
+ }
+ break;
+ }
+ }
+ shared_data_map_->AddBindingReference();
+
+ for (auto& observer_ptr : ptrs_to_move) {
+ observer_ptrs_.push_back(shared_data_map_->level_db_wrapper()->AddObserver(
+ std::move(observer_ptr)));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.h b/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.h
new file mode 100644
index 00000000000..0a856c8b05a
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper.h
@@ -0,0 +1,106 @@
+// 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_DOM_STORAGE_SESSION_STORAGE_LEVELDB_WRAPPER_H_
+#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_LEVELDB_WRAPPER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/optional.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/browser/leveldb_wrapper_impl.h"
+#include "content/common/content_export.h"
+#include "content/common/leveldb_wrapper.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "url/origin.h"
+
+namespace content {
+class SessionStorageDataMap;
+
+// This class provides session storage access to the renderer by binding to the
+// LevelDBWrapper mojom interface. It represents the data stored for a
+// namespace-origin area.
+//
+// This class delegates calls to SessionStorageDataMap objects, and can share
+// them with other SessionStorageLevelDBImpl instances to support shallow
+// cloning (copy-on-write). This should be done through the |Clone()| method and
+// not manually.
+//
+// During forking, this class is responsible for dealing with moving its
+// observers from the SessionStorageDataMap's LevelDBWrapper to the new forked
+// SessionStorageDataMap's LevelDBWrapper.
+class CONTENT_EXPORT SessionStorageLevelDBWrapper
+ : public mojom::LevelDBWrapper {
+ public:
+ using RegisterNewAreaMap =
+ base::RepeatingCallback<scoped_refptr<SessionStorageMetadata::MapData>(
+ SessionStorageMetadata::NamespaceEntry namespace_entry,
+ const url::Origin& origin)>;
+
+ // Creates a wrapper for the given |namespace_entry|-|origin| data area. All
+ // LevelDBWrapper calls are delegated to the |data_map|. The
+ // |register_new_map_callback| is called when a shared |data_map| needs to be
+ // forked for the copy-on-write behavior and a new map needs to be registered.
+ SessionStorageLevelDBWrapper(
+ SessionStorageMetadata::NamespaceEntry namespace_entry,
+ url::Origin origin,
+ scoped_refptr<SessionStorageDataMap> data_map,
+ RegisterNewAreaMap register_new_map_callback);
+ ~SessionStorageLevelDBWrapper() override;
+
+ // Creates a shallow copy clone for the new namespace entry.
+ // This doesn't change the refcount of the underlying map - that operation
+ // must be done using SessionStorageMetadata::RegisterShallowClonedNamespace.
+ std::unique_ptr<SessionStorageLevelDBWrapper> Clone(
+ SessionStorageMetadata::NamespaceEntry namespace_entry);
+
+ void Bind(mojom::LevelDBWrapperAssociatedRequest request);
+
+ bool IsBound() const { return binding_.is_bound(); }
+
+ SessionStorageDataMap* data_map() { return shared_data_map_.get(); }
+
+ // LevelDBWrapper:
+ void AddObserver(mojom::LevelDBObserverAssociatedPtrInfo observer) override;
+ void Put(const std::vector<uint8_t>& key,
+ const std::vector<uint8_t>& value,
+ const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const std::string& source,
+ PutCallback callback) override;
+ void Delete(const std::vector<uint8_t>& key,
+ const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const std::string& source,
+ DeleteCallback callback) override;
+ void DeleteAll(const std::string& source,
+ DeleteAllCallback callback) override;
+ void Get(const std::vector<uint8_t>& key, GetCallback callback) override;
+ void GetAll(
+ mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback,
+ GetAllCallback callback) override;
+
+ private:
+ void OnConnectionError();
+
+ enum class NewMapType { FORKED, EMPTY_FROM_DELETE_ALL };
+
+ void CreateNewMap(NewMapType map_type,
+ const base::Optional<std::string>& delete_all_source);
+
+ SessionStorageMetadata::NamespaceEntry namespace_entry_;
+ url::Origin origin_;
+ scoped_refptr<SessionStorageDataMap> shared_data_map_;
+ RegisterNewAreaMap register_new_map_callback_;
+
+ std::vector<mojo::InterfacePtrSetElementId> observer_ptrs_;
+ mojo::AssociatedBinding<mojom::LevelDBWrapper> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(SessionStorageLevelDBWrapper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_LEVELDB_WRAPPER_H_
diff --git a/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc b/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc
new file mode 100644
index 00000000000..6f768e0a050
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc
@@ -0,0 +1,376 @@
+// 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/dom_storage/session_storage_leveldb_wrapper.h"
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/guid.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread.h"
+#include "components/services/leveldb/leveldb_service_impl.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
+#include "content/browser/dom_storage/session_storage_data_map.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/fake_leveldb_database.h"
+#include "content/test/gmock_util.h"
+#include "content/test/leveldb_wrapper_test_util.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+using leveldb::StdStringToUint8Vector;
+using leveldb::Uint8VectorToStdString;
+using leveldb::mojom::DatabaseError;
+
+template <typename Interface, typename Impl>
+void CreateStrongBindingOnTaskRunner(
+ scoped_refptr<base::SequencedTaskRunner> runner,
+ mojo::InterfacePtr<Interface>* interface_ptr,
+ std::unique_ptr<Impl> interface) {
+ runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ base::IgnoreResult(&mojo::MakeStrongBinding<Interface, Impl>),
+ std::move(interface), mojo::MakeRequest(interface_ptr)));
+}
+
+class MockListener : public SessionStorageDataMap::Listener {
+ public:
+ MockListener() = default;
+ ~MockListener() override = default;
+ MOCK_METHOD2(OnDataMapCreation,
+ void(const std::vector<uint8_t>& map_id,
+ SessionStorageDataMap* map));
+ MOCK_METHOD1(OnDataMapDestruction, void(const std::vector<uint8_t>& map_id));
+ MOCK_METHOD1(OnCommitResult, void(DatabaseError error));
+};
+
+class SessionStorageLevelDBWrapperTest : public testing::Test {
+ public:
+ SessionStorageLevelDBWrapperTest()
+ : test_namespace_id1_(base::GenerateGUID()),
+ test_namespace_id2_(base::GenerateGUID()),
+ test_origin1_(url::Origin::Create(GURL("https://host1.com:1/"))),
+ test_origin2_(url::Origin::Create(GURL("https://host2.com:2/"))) {
+ auto file_runner =
+ base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()});
+ CreateStrongBindingOnTaskRunner(
+ base::CreateSequencedTaskRunnerWithTraits({}), &leveldb_service_,
+ std::make_unique<leveldb::LevelDBServiceImpl>(std::move(file_runner)));
+
+ leveldb_service_->OpenInMemory(
+ base::nullopt, "SessionStorageLevelDBWrapperTestDatabase",
+ mojo::MakeRequest(&leveldb_database_), base::DoNothing());
+
+ leveldb_database_->Put(StdStringToUint8Vector("map-0-key1"),
+ StdStringToUint8Vector("data1"), base::DoNothing());
+
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations =
+ metadata_.SetupNewDatabase();
+ auto map_id = metadata_.RegisterNewMap(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
+ &save_operations);
+ DCHECK(map_id->KeyPrefix() == StdStringToUint8Vector("map-0-"));
+ leveldb_database_->Write(std::move(save_operations), base::DoNothing());
+ }
+ ~SessionStorageLevelDBWrapperTest() override = default;
+
+ scoped_refptr<SessionStorageMetadata::MapData> RegisterNewAreaMap(
+ SessionStorageMetadata::NamespaceEntry namespace_entry,
+ const url::Origin& origin) {
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ auto map_data =
+ metadata_.RegisterNewMap(namespace_entry, origin, &save_operations);
+ leveldb_database_->Write(std::move(save_operations), base::DoNothing());
+ return map_data;
+ }
+
+ SessionStorageLevelDBWrapper::RegisterNewAreaMap
+ GetRegisterNewAreaMapCallback() {
+ return base::BindRepeating(
+ &SessionStorageLevelDBWrapperTest::RegisterNewAreaMap,
+ base::Unretained(this));
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment environment_;
+ const std::string test_namespace_id1_;
+ const std::string test_namespace_id2_;
+ const url::Origin test_origin1_;
+ const url::Origin test_origin2_;
+ leveldb::mojom::LevelDBServicePtr leveldb_service_;
+ leveldb::mojom::LevelDBDatabaseAssociatedPtr leveldb_database_;
+ SessionStorageMetadata metadata_;
+
+ testing::StrictMock<MockListener> listener_;
+};
+} // namespace
+
+TEST_F(SessionStorageLevelDBWrapperTest, BasicUsage) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ auto ss_leveldb_impl = std::make_unique<SessionStorageLevelDBWrapper>(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
+ SessionStorageDataMap::Create(
+ &listener_,
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)
+ ->second[test_origin1_],
+ leveldb_database_.get()),
+ GetRegisterNewAreaMapCallback());
+
+ mojom::LevelDBWrapperAssociatedPtr ss_leveldb;
+ ss_leveldb_impl->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb));
+
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(ss_leveldb.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ ASSERT_EQ(1ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+}
+
+TEST_F(SessionStorageLevelDBWrapperTest, Cloning) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ auto ss_leveldb_impl1 = std::make_unique<SessionStorageLevelDBWrapper>(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
+ SessionStorageDataMap::Create(
+ &listener_,
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)
+ ->second[test_origin1_],
+ leveldb_database_.get()),
+ GetRegisterNewAreaMapCallback());
+
+ // Perform a shallow clone.
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ metadata_.RegisterShallowClonedNamespace(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_),
+ &save_operations);
+ leveldb_database_->Write(std::move(save_operations), base::DoNothing());
+ auto ss_leveldb_impl2 = ss_leveldb_impl1->Clone(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_));
+
+ mojom::LevelDBWrapperAssociatedPtr ss_leveldb1;
+ ss_leveldb_impl1->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb1));
+ mojom::LevelDBWrapperAssociatedPtr ss_leveldb2;
+ ss_leveldb_impl2->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb2));
+
+ // Same maps are used.
+ EXPECT_EQ(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map());
+
+ // The |Put| call will fork the maps.
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK))
+ .Times(testing::AnyNumber());
+ EXPECT_TRUE(test::PutSync(ss_leveldb2.get(), StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"), base::nullopt,
+ ""));
+
+ // The maps were forked on the above put.
+ EXPECT_NE(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map());
+
+ // Check map 1 data.
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(ss_leveldb1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ ASSERT_EQ(1ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
+
+ // Check map 2 data.
+ data.clear();
+ status = test::GetAllSync(ss_leveldb2.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ ASSERT_EQ(2ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+
+ ss_leveldb_impl1 = nullptr;
+ ss_leveldb_impl2 = nullptr;
+}
+
+TEST_F(SessionStorageLevelDBWrapperTest, ObserverTransfer) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ auto ss_leveldb_impl1 = std::make_unique<SessionStorageLevelDBWrapper>(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
+ SessionStorageDataMap::Create(
+ &listener_,
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)
+ ->second[test_origin1_],
+ leveldb_database_.get()),
+ GetRegisterNewAreaMapCallback());
+
+ // Create the mojo binding.
+ mojom::LevelDBWrapperAssociatedPtr ss_leveldb1;
+ ss_leveldb_impl1->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb1));
+
+ // Create the observer, and attach it to the mojo bound implementation.
+ testing::StrictMock<test::MockLevelDBObserver> mock_observer;
+ mojo::AssociatedBinding<mojom::LevelDBObserver> observer_binding(
+ &mock_observer);
+ mojom::LevelDBObserverAssociatedPtrInfo observer_ptr_info;
+ observer_binding.Bind(mojo::MakeRequest(&observer_ptr_info));
+ ss_leveldb1->AddObserver(std::move(observer_ptr_info));
+
+ // Perform a shallow clone.
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ metadata_.RegisterShallowClonedNamespace(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_),
+ &save_operations);
+ leveldb_database_->Write(std::move(save_operations), base::DoNothing());
+ auto ss_leveldb_impl2 = ss_leveldb_impl1->Clone(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_));
+ mojom::LevelDBWrapperAssociatedPtr ss_leveldb2;
+ ss_leveldb_impl2->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb2));
+
+ // Wait for our future commits to finish.
+ base::RunLoop commit_waiters;
+ auto barrier = base::BarrierClosure(3, commit_waiters.QuitClosure());
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK))
+ .Times(3)
+ .WillRepeatedly(base::test::RunClosure(barrier));
+
+ // Do a change on the new interface. There should be no observation.
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+ EXPECT_TRUE(test::PutSync(ss_leveldb2.get(), StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"), base::nullopt,
+ ""));
+ ss_leveldb_impl2->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
+
+ // Do a change on the old interface.
+ EXPECT_CALL(mock_observer,
+ KeyChanged(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data2"),
+ StdStringToUint8Vector("data1"), "ss_leveldb1"))
+ .Times(1);
+ EXPECT_TRUE(test::PutSync(ss_leveldb1.get(), StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data2"),
+ StdStringToUint8Vector("data1"), "ss_leveldb1"));
+ ss_leveldb_impl1->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
+
+ // Wait for the commits.
+ commit_waiters.Run();
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+
+ ss_leveldb_impl1 = nullptr;
+ ss_leveldb_impl2 = nullptr;
+}
+
+TEST_F(SessionStorageLevelDBWrapperTest, DeleteAllOnShared) {
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ auto ss_leveldb_impl1 = std::make_unique<SessionStorageLevelDBWrapper>(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_,
+ SessionStorageDataMap::Create(
+ &listener_,
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_)
+ ->second[test_origin1_],
+ leveldb_database_.get()),
+ GetRegisterNewAreaMapCallback());
+
+ // Perform a shallow clone.
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ metadata_.RegisterShallowClonedNamespace(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_),
+ &save_operations);
+ leveldb_database_->Write(std::move(save_operations), base::DoNothing());
+ auto ss_leveldb_impl2 = ss_leveldb_impl1->Clone(
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_));
+
+ mojom::LevelDBWrapperAssociatedPtr ss_leveldb1;
+ ss_leveldb_impl1->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb1));
+ mojom::LevelDBWrapperAssociatedPtr ss_leveldb2;
+ ss_leveldb_impl2->Bind(
+ mojo::MakeRequestAssociatedWithDedicatedPipe(&ss_leveldb2));
+
+ // Same maps are used.
+ EXPECT_EQ(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map());
+
+ // Create the observer, attach to the first namespace.
+ testing::StrictMock<test::MockLevelDBObserver> mock_observer;
+ mojo::AssociatedBinding<mojom::LevelDBObserver> observer_binding(
+ &mock_observer);
+ mojom::LevelDBObserverAssociatedPtrInfo observer_ptr_info;
+ observer_binding.Bind(mojo::MakeRequest(&observer_ptr_info));
+ ss_leveldb1->AddObserver(std::move(observer_ptr_info));
+
+ // The |DeleteAll| call will fork the maps, and the observer should see a
+ // DeleteAll.
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+ // There should be no commits, as we don't actually have to change any data.
+ // |ss_leveldb_impl1| should just switch to a new, empty map.
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(0);
+ EXPECT_CALL(mock_observer, AllDeleted("source")).Times(1);
+ EXPECT_TRUE(test::DeleteAllSync(ss_leveldb1.get(), "source"));
+
+ // The maps were forked on the above call.
+ EXPECT_NE(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map());
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+
+ ss_leveldb_impl1 = nullptr;
+ ss_leveldb_impl2 = nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_metadata.cc b/chromium/content/browser/dom_storage/session_storage_metadata.cc
new file mode 100644
index 00000000000..d129f92e127
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_metadata.cc
@@ -0,0 +1,427 @@
+// 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/dom_storage/session_storage_metadata.h"
+
+#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "content/common/dom_storage/dom_storage_namespace_ids.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+using leveldb::mojom::BatchedOperation;
+using leveldb::mojom::BatchOperationType;
+using leveldb::mojom::BatchedOperationPtr;
+
+// Example layout of the database:
+// | key | value |
+// |----------------------------------------|--------------------|
+// | map-1-a | b (a = b in map 1) |
+// | ... | |
+// | namespace-<36 char guid 1>-origin1 | 1 (mapid) |
+// | namespace-<36 char guid 1>-origin2 | 2 |
+// | namespace-<36 char guid 2>-origin1 | 1 (shallow copy) |
+// | namespace-<36 char guid 2>-origin2 | 2 (shallow copy) |
+// | namespace-<36 char guid 3>-origin1 | 3 (deep copy) |
+// | namespace-<36 char guid 3>-origin2 | 2 (shallow copy) |
+// | next-map-id | 4 |
+// | version | 1 |
+// Example area key: namespace-dabc53e1_8291_4de5_824f_dab8aa69c846-origin2
+//
+// All number values (map numbers and the version) are string conversions of
+// numbers. Map keys are converted to UTF-8 and the values stay as UTF-16.
+
+// This is "map-" (without the quotes).
+constexpr const uint8_t kMapIdPrefixBytes[] = {'m', 'a', 'p', '-'};
+
+constexpr const size_t kNamespacePrefixLength =
+ arraysize(SessionStorageMetadata::kNamespacePrefixBytes);
+constexpr const uint8_t kNamespaceOriginSeperatorByte = '-';
+constexpr const size_t kNamespaceOriginSeperatorLength = 1;
+constexpr const size_t kPrefixBeforeOriginLength =
+ kNamespacePrefixLength + kSessionStorageNamespaceIdLength +
+ kNamespaceOriginSeperatorLength;
+
+bool ValueToNumber(const std::vector<uint8_t>& value, int64_t* out) {
+ return base::StringToInt64(leveldb::Uint8VectorToStringPiece(value), out);
+}
+
+std::vector<uint8_t> NumberToValue(int64_t map_number) {
+ return leveldb::StdStringToUint8Vector(base::NumberToString(map_number));
+}
+} // namespace
+
+constexpr const int64_t SessionStorageMetadata::kMinSessionStorageSchemaVersion;
+constexpr const int64_t
+ SessionStorageMetadata::kLatestSessionStorageSchemaVersion;
+constexpr const int64_t SessionStorageMetadata::kInvalidDatabaseVersion;
+constexpr const int64_t SessionStorageMetadata::kInvalidMapId;
+constexpr const uint8_t SessionStorageMetadata::kDatabaseVersionBytes[];
+constexpr const uint8_t SessionStorageMetadata::kNamespacePrefixBytes[];
+constexpr const uint8_t SessionStorageMetadata::kNextMapIdKeyBytes[];
+
+SessionStorageMetadata::MapData::MapData(int64_t map_number, url::Origin origin)
+ : number_as_bytes_(NumberToValue(map_number)),
+ key_prefix_(SessionStorageMetadata::GetMapPrefix(number_as_bytes_)),
+ origin_(std::move(origin)) {}
+SessionStorageMetadata::MapData::~MapData() = default;
+
+SessionStorageMetadata::SessionStorageMetadata() {}
+
+SessionStorageMetadata::~SessionStorageMetadata() {}
+
+std::vector<leveldb::mojom::BatchedOperationPtr>
+SessionStorageMetadata::SetupNewDatabase() {
+ next_map_id_ = 0;
+ next_map_id_from_namespaces_ = 0;
+ namespace_origin_map_.clear();
+
+ std::vector<leveldb::mojom::BatchedOperationPtr> operations;
+ operations.reserve(2);
+ operations.push_back(BatchedOperation::New(
+ BatchOperationType::PUT_KEY,
+ std::vector<uint8_t>(std::begin(kDatabaseVersionBytes),
+ std::end(kDatabaseVersionBytes)),
+ LatestDatabaseVersionAsVector()));
+ operations.push_back(
+ BatchedOperation::New(BatchOperationType::PUT_KEY,
+ std::vector<uint8_t>(std::begin(kNextMapIdKeyBytes),
+ std::end(kNextMapIdKeyBytes)),
+ NumberToValue(next_map_id_)));
+ return operations;
+}
+
+bool SessionStorageMetadata::ParseDatabaseVersion(
+ base::Optional<std::vector<uint8_t>> value,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* upgrade_operations) {
+ if (!value) {
+ initial_database_version_from_disk_ = 0;
+ } else {
+ if (!ValueToNumber(value.value(), &initial_database_version_from_disk_)) {
+ initial_database_version_from_disk_ = kInvalidDatabaseVersion;
+ return false;
+ }
+ if (initial_database_version_from_disk_ ==
+ kLatestSessionStorageSchemaVersion)
+ return true;
+ }
+ if (initial_database_version_from_disk_ < kMinSessionStorageSchemaVersion)
+ return false;
+ upgrade_operations->push_back(BatchedOperation::New(
+ BatchOperationType::PUT_KEY,
+ std::vector<uint8_t>(std::begin(kDatabaseVersionBytes),
+ std::end(kDatabaseVersionBytes)),
+ LatestDatabaseVersionAsVector()));
+ return true;
+}
+
+bool SessionStorageMetadata::ParseNamespaces(
+ std::vector<leveldb::mojom::KeyValuePtr> values,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* upgrade_operations) {
+ namespace_origin_map_.clear();
+ next_map_id_from_namespaces_ = 0;
+ // Since the data is ordered, all namespace data is in one spot. This keeps a
+ // reference to the last namespace data map to be more efficient.
+ std::string last_namespace_id;
+ std::map<url::Origin, scoped_refptr<MapData>>* last_namespace = nullptr;
+ std::map<int64_t, scoped_refptr<MapData>> maps;
+ bool error = false;
+ for (const leveldb::mojom::KeyValuePtr& key_value : values) {
+ size_t key_size = key_value->key.size();
+
+ base::StringPiece key_as_string =
+ leveldb::Uint8VectorToStringPiece(key_value->key);
+
+ if (key_size < kNamespacePrefixLength) {
+ LOG(ERROR) << "Key size is less than prefix length: " << key_as_string;
+ error = true;
+ break;
+ }
+
+ // The key must start with 'namespace-'.
+ if (!key_as_string.starts_with(base::StringPiece(
+ reinterpret_cast<const char*>(kNamespacePrefixBytes),
+ kNamespacePrefixLength))) {
+ LOG(ERROR) << "Key must start with 'namespace-': " << key_as_string;
+ error = true;
+ break;
+ }
+
+ // Old databases have a dummy 'namespace-' entry.
+ if (key_size == kNamespacePrefixLength)
+ continue;
+
+ // Check that the prefix is 'namespace-<guid>-
+ if (key_size < kPrefixBeforeOriginLength ||
+ key_as_string[kPrefixBeforeOriginLength - 1] !=
+ static_cast<const char>(kNamespaceOriginSeperatorByte)) {
+ LOG(ERROR) << "Prefix is not 'namespace-<guid>-': " << key_as_string;
+ error = true;
+ break;
+ }
+
+ // Old databases have a dummy 'namespace-<guid>-' entry.
+ if (key_size == kPrefixBeforeOriginLength)
+ continue;
+
+ base::StringPiece namespace_id = key_as_string.substr(
+ kNamespacePrefixLength, kSessionStorageNamespaceIdLength);
+
+ base::StringPiece origin_str =
+ key_as_string.substr(kPrefixBeforeOriginLength);
+
+ int64_t map_number;
+ if (!ValueToNumber(key_value->value, &map_number)) {
+ error = true;
+ LOG(ERROR) << "Could not parse map number "
+ << leveldb::Uint8VectorToStringPiece(key_value->value);
+ break;
+ }
+
+ if (map_number >= next_map_id_from_namespaces_)
+ next_map_id_from_namespaces_ = map_number + 1;
+
+ auto origin_gurl = GURL(origin_str);
+ if (!origin_gurl.is_valid()) {
+ LOG(ERROR) << "Invalid origin " << origin_str;
+ error = true;
+ break;
+ }
+
+ auto origin = url::Origin::Create(origin_gurl);
+ if (namespace_id != last_namespace_id) {
+ last_namespace_id = namespace_id.as_string();
+ DCHECK(namespace_origin_map_.find(last_namespace_id) ==
+ namespace_origin_map_.end());
+ last_namespace = &(namespace_origin_map_[last_namespace_id]);
+ }
+ auto map_it = maps.find(map_number);
+ if (map_it == maps.end()) {
+ map_it =
+ maps.emplace(std::piecewise_construct,
+ std::forward_as_tuple(map_number),
+ std::forward_as_tuple(new MapData(map_number, origin)))
+ .first;
+ }
+ map_it->second->IncReferenceCount();
+
+ last_namespace->emplace(std::make_pair(std::move(origin), map_it->second));
+ }
+ if (error) {
+ namespace_origin_map_.clear();
+ next_map_id_from_namespaces_ = 0;
+ return false;
+ }
+ if (next_map_id_ == 0 || next_map_id_ < next_map_id_from_namespaces_)
+ next_map_id_ = next_map_id_from_namespaces_;
+
+ // Namespace metadata migration.
+ DCHECK_NE(kInvalidDatabaseVersion, initial_database_version_from_disk_);
+ if (initial_database_version_from_disk_ == 0) {
+ // Remove the dummy 'namespaces-' entry.
+ upgrade_operations->push_back(BatchedOperation::New(
+ BatchOperationType::DELETE_KEY,
+ std::vector<uint8_t>(std::begin(kNamespacePrefixBytes),
+ std::end(kNamespacePrefixBytes)),
+ base::nullopt));
+ // Remove all the refcount storage.
+ for (const auto& map_pair : maps) {
+ upgrade_operations->push_back(
+ BatchedOperation::New(BatchOperationType::DELETE_KEY,
+ map_pair.second->KeyPrefix(), base::nullopt));
+ }
+ }
+
+ return true;
+}
+
+void SessionStorageMetadata::ParseNextMapId(
+ const std::vector<uint8_t>& map_id) {
+ if (!ValueToNumber(map_id, &next_map_id_))
+ next_map_id_ = next_map_id_from_namespaces_;
+ if (next_map_id_ < next_map_id_from_namespaces_)
+ next_map_id_ = next_map_id_from_namespaces_;
+}
+
+// static
+std::vector<uint8_t> SessionStorageMetadata::LatestDatabaseVersionAsVector() {
+ return NumberToValue(kLatestSessionStorageSchemaVersion);
+}
+
+scoped_refptr<SessionStorageMetadata::MapData>
+SessionStorageMetadata::RegisterNewMap(
+ NamespaceEntry namespace_entry,
+ const url::Origin& origin,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* save_operations) {
+ auto new_map_data = base::MakeRefCounted<MapData>(next_map_id_, origin);
+ ++next_map_id_;
+
+ save_operations->push_back(BatchedOperation::New(
+ BatchOperationType::PUT_KEY,
+ std::vector<uint8_t>(
+ SessionStorageMetadata::kNextMapIdKeyBytes,
+ std::end(SessionStorageMetadata::kNextMapIdKeyBytes)),
+ NumberToValue(next_map_id_)));
+
+ std::map<url::Origin, scoped_refptr<MapData>>& namespace_origins =
+ namespace_entry->second;
+ auto namespace_it = namespace_origins.find(origin);
+ if (namespace_it != namespace_origins.end()) {
+ // Check the old map doesn't have the same number as the new map.
+ DCHECK(namespace_it->second->MapNumberAsBytes() !=
+ new_map_data->MapNumberAsBytes());
+ DCHECK_GT(namespace_it->second->ReferenceCount(), 1)
+ << "A new map should never be registered for an area that has a "
+ "single-refcount map.";
+ // There was already an area key here, so decrement that map reference.
+ namespace_it->second->DecReferenceCount();
+ namespace_it->second = new_map_data;
+ } else {
+ namespace_origins.emplace(std::make_pair(origin, new_map_data));
+ }
+ new_map_data->IncReferenceCount();
+
+ save_operations->push_back(BatchedOperation::New(
+ BatchOperationType::PUT_KEY, GetAreaKey(namespace_entry->first, origin),
+ new_map_data->MapNumberAsBytes()));
+
+ return new_map_data;
+}
+
+void SessionStorageMetadata::RegisterShallowClonedNamespace(
+ NamespaceEntry source_namespace,
+ NamespaceEntry destination_namespace,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* save_operations) {
+ std::map<url::Origin, scoped_refptr<MapData>>& source_origins =
+ source_namespace->second;
+ std::map<url::Origin, scoped_refptr<MapData>>& destination_origins =
+ destination_namespace->second;
+ DCHECK_EQ(0ul, destination_origins.size());
+
+ save_operations->reserve(save_operations->size() + source_origins.size());
+ for (const auto& origin_map_pair : source_origins) {
+ destination_origins.emplace(std::piecewise_construct,
+ std::forward_as_tuple(origin_map_pair.first),
+ std::forward_as_tuple(origin_map_pair.second));
+ origin_map_pair.second->IncReferenceCount();
+
+ save_operations->push_back(BatchedOperation::New(
+ BatchOperationType::PUT_KEY,
+ GetAreaKey(destination_namespace->first, origin_map_pair.first),
+ origin_map_pair.second->MapNumberAsBytes()));
+ }
+}
+
+void SessionStorageMetadata::DeleteNamespace(
+ const std::string& namespace_id,
+ std::vector<BatchedOperationPtr>* delete_operations) {
+ auto it = namespace_origin_map_.find(namespace_id);
+ if (it == namespace_origin_map_.end())
+ return;
+
+ delete_operations->push_back(
+ BatchedOperation::New(BatchOperationType::DELETE_PREFIXED_KEY,
+ GetNamespacePrefix(namespace_id), base::nullopt));
+
+ const std::map<url::Origin, scoped_refptr<MapData>>& origins = it->second;
+ for (const auto& origin_map_pair : origins) {
+ MapData* map_data = origin_map_pair.second.get();
+ DCHECK_GT(map_data->ReferenceCount(), 0);
+ map_data->DecReferenceCount();
+ if (map_data->ReferenceCount() == 0) {
+ delete_operations->push_back(
+ BatchedOperation::New(BatchOperationType::DELETE_PREFIXED_KEY,
+ map_data->KeyPrefix(), base::nullopt));
+ }
+ }
+
+ namespace_origin_map_.erase(it);
+}
+
+void SessionStorageMetadata::DeleteArea(
+ const std::string& namespace_id,
+ const url::Origin& origin,
+ std::vector<BatchedOperationPtr>* delete_operations) {
+ NamespaceEntry ns_entry = namespace_origin_map_.find(namespace_id);
+ if (ns_entry == namespace_origin_map_.end())
+ return;
+
+ auto origin_map_it = ns_entry->second.find(origin);
+ if (origin_map_it == ns_entry->second.end())
+ return;
+
+ MapData* map_data = origin_map_it->second.get();
+
+ delete_operations->push_back(
+ BatchedOperation::New(BatchOperationType::DELETE_KEY,
+ GetAreaKey(namespace_id, origin), base::nullopt));
+
+ DCHECK_GT(map_data->ReferenceCount(), 0);
+ map_data->DecReferenceCount();
+ if (map_data->ReferenceCount() == 0) {
+ delete_operations->push_back(
+ BatchedOperation::New(BatchOperationType::DELETE_PREFIXED_KEY,
+ map_data->KeyPrefix(), base::nullopt));
+ }
+ ns_entry->second.erase(origin_map_it);
+}
+
+SessionStorageMetadata::NamespaceEntry
+SessionStorageMetadata::GetOrCreateNamespaceEntry(
+ const std::string& namespace_id) {
+ // Note: if the entry exists, emplace will return the existing entry and NOT
+ // insert a new entry.
+ return namespace_origin_map_
+ .emplace(std::piecewise_construct, std::forward_as_tuple(namespace_id),
+ std::forward_as_tuple())
+ .first;
+}
+
+// static
+std::vector<uint8_t> SessionStorageMetadata::GetNamespacePrefix(
+ const std::string& namespace_id) {
+ std::vector<uint8_t> namespace_prefix(
+ SessionStorageMetadata::kNamespacePrefixBytes,
+ std::end(SessionStorageMetadata::kNamespacePrefixBytes));
+ namespace_prefix.insert(namespace_prefix.end(), namespace_id.data(),
+ namespace_id.data() + namespace_id.size());
+ namespace_prefix.push_back(kNamespaceOriginSeperatorByte);
+ return namespace_prefix;
+}
+
+// static
+std::vector<uint8_t> SessionStorageMetadata::GetAreaKey(
+ const std::string& namespace_id,
+ const url::Origin& origin) {
+ std::vector<uint8_t> area_key(
+ SessionStorageMetadata::kNamespacePrefixBytes,
+ std::end(SessionStorageMetadata::kNamespacePrefixBytes));
+ area_key.insert(area_key.end(), namespace_id.begin(), namespace_id.end());
+ area_key.push_back(kNamespaceOriginSeperatorByte);
+ std::string origin_str = origin.GetURL().spec();
+ area_key.insert(area_key.end(), origin_str.data(),
+ origin_str.data() + origin_str.size());
+ return area_key;
+}
+
+// static
+std::vector<uint8_t> SessionStorageMetadata::GetMapPrefix(int64_t map_number) {
+ return GetMapPrefix(NumberToValue(map_number));
+}
+
+// static
+std::vector<uint8_t> SessionStorageMetadata::GetMapPrefix(
+ const std::vector<uint8_t>& map_number_as_bytes) {
+ std::vector<uint8_t> map_prefix(kMapIdPrefixBytes,
+ std::end(kMapIdPrefixBytes));
+ map_prefix.insert(map_prefix.end(), map_number_as_bytes.begin(),
+ map_number_as_bytes.end());
+ map_prefix.push_back(kNamespaceOriginSeperatorByte);
+ return map_prefix;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_metadata.h b/chromium/content/browser/dom_storage/session_storage_metadata.h
new file mode 100644
index 00000000000..c1a6b861979
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_metadata.h
@@ -0,0 +1,182 @@
+// 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_DOM_STORAGE_SESSION_STORAGE_METADATA_H_
+#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_METADATA_H_
+
+#include <stdint.h>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
+#include "content/common/content_export.h"
+#include "url/origin.h"
+
+namespace content {
+
+// Holds the metadata information for a session storage database. This includes
+// logic for parsing and saving database content.
+class CONTENT_EXPORT SessionStorageMetadata {
+ public:
+ // Version 0 represents the old SessionStorageDatabase where we never stored a
+ // version. This class stores '0' as the version in this case. Version 1
+ // removes 'namespaces-' dummy entry, and 'map-_-' refcount entries that are
+ // present in version 0.
+ static constexpr const int64_t kMinSessionStorageSchemaVersion = 0;
+ static constexpr const int64_t kLatestSessionStorageSchemaVersion = 1;
+
+ static constexpr const int64_t kInvalidDatabaseVersion = -1;
+ static constexpr const int64_t kInvalidMapId = -1;
+
+ static constexpr const uint8_t kDatabaseVersionBytes[] = {'v', 'e', 'r', 's',
+ 'i', 'o', 'n'};
+
+ static constexpr const uint8_t kNamespacePrefixBytes[] = {
+ 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '-'};
+
+ // This is "next-map-id" (without the quotes).
+ static constexpr const uint8_t kNextMapIdKeyBytes[] = {
+ 'n', 'e', 'x', 't', '-', 'm', 'a', 'p', '-', 'i', 'd'};
+
+ // Represents a map which can be shared by multiple areas.
+ // The |DeleteNamespace| and |DeleteArea| methods can destroy any MapData
+ // objects who are no longer referenced by another namespace.
+ // Maps (and thus MapData objects) can only be shared for the same origin.
+ class CONTENT_EXPORT MapData : public base::RefCounted<MapData> {
+ public:
+ explicit MapData(int64_t map_number, url::Origin origin);
+
+ const url::Origin& origin() const { return origin_; }
+
+ // The number of namespaces that reference this map.
+ int ReferenceCount() const { return reference_count_; }
+
+ // The key prefix for the map data (e.g. "map-2-").
+ const std::vector<uint8_t>& KeyPrefix() const { return key_prefix_; }
+
+ // The number of the map as bytes (e.g. "2").
+ const std::vector<uint8_t>& MapNumberAsBytes() const {
+ return number_as_bytes_;
+ }
+
+ private:
+ friend class base::RefCounted<MapData>;
+ friend class SessionStorageMetadata;
+ ~MapData();
+
+ void IncReferenceCount() { ++reference_count_; }
+ void DecReferenceCount() { --reference_count_; }
+
+ // The map number as bytes (e.g. "2"). These bytes are the string
+ // representation of the map number.
+ std::vector<uint8_t> number_as_bytes_;
+ std::vector<uint8_t> key_prefix_;
+ url::Origin origin_;
+ int reference_count_ = 0;
+ };
+
+ using NamespaceOriginMap =
+ std::map<std::string, std::map<url::Origin, scoped_refptr<MapData>>>;
+ using NamespaceEntry = NamespaceOriginMap::iterator;
+
+ SessionStorageMetadata();
+ ~SessionStorageMetadata();
+
+ // For a new database, this saves the database version, clears the metadata,
+ // and returns the operations to save to disk.
+ std::vector<leveldb::mojom::BatchedOperationPtr> SetupNewDatabase();
+
+ // This parses the database version from the bytes that were stored on
+ // disk, or if there was no version saved then passes a base::nullopt. This
+ // call is not necessary on new databases. The |upgrade_operations| are
+ // populated with any operations needed to upgrade the databases versioning
+ // metadata. Note this is different than the namespaces metadata, which will
+ // be upgraded in ParseNamespaces.
+ // Returns if the parsing is correct and we support the version read.
+ bool ParseDatabaseVersion(
+ base::Optional<std::vector<uint8_t>> value,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* upgrade_operations);
+
+ // Parses all namespaces and maps, and stores all metadata locally. This
+ // invalidates all NamespaceEntry and MapData objects. If there is a parsing
+ // error, the namespaces will be cleared.If the version given to
+ // |ParseDatabaseVersion| is an older version, any namespace metadata upgrades
+ // will be populated in |upgrade_operations|. This call is not necessary on
+ // new databases.
+ bool ParseNamespaces(
+ std::vector<leveldb::mojom::KeyValuePtr> values,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* upgrade_operations);
+
+ // Parses the next map id from the given bytes. If that fails, then it uses
+ // the next available id from parsing the namespaces. This call is not
+ // necessary on new databases.
+ void ParseNextMapId(const std::vector<uint8_t>& map_id);
+
+ // Creates new map data for the given namespace-origin area. If the area
+ // entry exists, then it will decrement the refcount of the old map. The
+ // |save_operations| save the new or modified area entry, as well as saving
+ // the next available map id.
+ // Note: It is invalid to call this method for an area that has a map with
+ // only one reference.
+ scoped_refptr<MapData> RegisterNewMap(
+ NamespaceEntry namespace_entry,
+ const url::Origin& origin,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* save_operations);
+
+ // Registers an origin-map in the |destination_namespace| from every
+ // origin-map in the |source_namespace|. The |destination_namespace| must have
+ // no origin-maps. All maps in the destination namespace are the same maps as
+ // the source namespace. All database operations to save the namespace origin
+ // metadata are put in |save_operations|.
+ void RegisterShallowClonedNamespace(
+ NamespaceEntry source_namespace,
+ NamespaceEntry destination_namespace,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* save_operations);
+
+ // Deletes the given namespace any any maps that no longer have any
+ // references. This will invalidate all NamespaceEntry objects for the
+ // |namespace_id|, and can invalidate any MapData objects whose reference
+ // count hits zero.
+ void DeleteNamespace(
+ const std::string& namespace_id,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* delete_operations);
+
+ // This removes the metadata entry for this namespace-origin area. If the map
+ // at this entry isn't reference by any other area (refcount hits 0), then
+ // this will delete that map on disk and invalidate that MapData.
+ void DeleteArea(
+ const std::string& namespace_id,
+ const url::Origin& origin,
+ std::vector<leveldb::mojom::BatchedOperationPtr>* delete_operations);
+
+ NamespaceEntry GetOrCreateNamespaceEntry(const std::string& namespace_id);
+
+ const NamespaceOriginMap& namespace_origin_map() const {
+ return namespace_origin_map_;
+ }
+
+ int64_t NextMapId() const { return next_map_id_; }
+
+ private:
+ static std::vector<uint8_t> LatestDatabaseVersionAsVector();
+
+ static std::vector<uint8_t> GetNamespacePrefix(
+ const std::string& namespace_id);
+ static std::vector<uint8_t> GetAreaKey(const std::string& namespace_id,
+ const url::Origin& origin);
+ static std::vector<uint8_t> GetMapPrefix(int64_t map_number);
+ static std::vector<uint8_t> GetMapPrefix(
+ const std::vector<uint8_t>& map_number_as_bytes);
+
+ int64_t initial_database_version_from_disk_ = kInvalidDatabaseVersion;
+ int64_t next_map_id_ = kInvalidMapId;
+ int64_t next_map_id_from_namespaces_ = 0;
+
+ NamespaceOriginMap namespace_origin_map_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_METADATA_H_
diff --git a/chromium/content/browser/dom_storage/session_storage_metadata_unittest.cc b/chromium/content/browser/dom_storage/session_storage_metadata_unittest.cc
new file mode 100644
index 00000000000..e6e58fb07cb
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_metadata_unittest.cc
@@ -0,0 +1,480 @@
+// 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/dom_storage/session_storage_metadata.h"
+
+#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "content/browser/dom_storage/session_storage_database.h"
+#include "content/browser/indexed_db/leveldb/leveldb_env.h"
+#include "content/common/dom_storage/dom_storage_types.h"
+#include "content/test/fake_leveldb_database.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/env_chromium.h"
+#include "third_party/leveldatabase/leveldb_chrome.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/options.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+namespace {
+using leveldb::StdStringToUint8Vector;
+using leveldb::Uint8VectorToStdString;
+using leveldb::mojom::DatabaseError;
+
+void GetCallback(std::vector<uint8_t>* value_out,
+ DatabaseError error,
+ const std::vector<uint8_t>& value) {
+ *value_out = value;
+}
+
+void ErrorCallback(DatabaseError* error_out, DatabaseError error) {
+ *error_out = error;
+}
+
+void GetAllCallback(std::vector<leveldb::mojom::KeyValuePtr>* values_out,
+ DatabaseError error,
+ std::vector<leveldb::mojom::KeyValuePtr> values) {
+ *values_out = std::move(values);
+}
+
+class SessionStorageMetadataTest : public testing::Test {
+ public:
+ SessionStorageMetadataTest()
+ : test_namespace1_id_(base::GenerateGUID()),
+ test_namespace2_id_(base::GenerateGUID()),
+ test_namespace3_id_(base::GenerateGUID()),
+ test_origin1_(url::Origin::Create(GURL("http://host1:1/"))),
+ test_origin2_(url::Origin::Create(GURL("http://host2:2/"))),
+ database_(&mock_data_) {
+ next_map_id_key_ = std::vector<uint8_t>(
+ std::begin(SessionStorageMetadata::kNextMapIdKeyBytes),
+ std::end(SessionStorageMetadata::kNextMapIdKeyBytes));
+ database_version_key_ = std::vector<uint8_t>(
+ std::begin(SessionStorageMetadata::kDatabaseVersionBytes),
+ std::end(SessionStorageMetadata::kDatabaseVersionBytes));
+ namespaces_prefix_key_ = std::vector<uint8_t>(
+ std::begin(SessionStorageMetadata::kNamespacePrefixBytes),
+ std::end(SessionStorageMetadata::kNamespacePrefixBytes));
+ }
+ ~SessionStorageMetadataTest() override {}
+
+ void ReadMetadataFromDatabase(SessionStorageMetadata* metadata) {
+ std::vector<uint8_t> value;
+ database_.Get(database_version_key_, base::BindOnce(&GetCallback, &value));
+ std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations;
+ EXPECT_TRUE(metadata->ParseDatabaseVersion(value, &migration_operations));
+ EXPECT_TRUE(migration_operations.empty());
+ database_.Get(next_map_id_key_, base::BindOnce(&GetCallback, &value));
+ metadata->ParseNextMapId(value);
+ std::vector<leveldb::mojom::KeyValuePtr> values;
+ database_.GetPrefixed(namespaces_prefix_key_,
+ base::BindOnce(&GetAllCallback, &values));
+ EXPECT_TRUE(
+ metadata->ParseNamespaces(std::move(values), &migration_operations));
+ EXPECT_TRUE(migration_operations.empty());
+ }
+
+ void SetupTestData() {
+ // | key | value |
+ // |----------------------------------------|--------------------|
+ // | map-1-key1 | data1 |
+ // | map-3-key1 | data3 |
+ // | map-4-key1 | data4 |
+ // | namespace-<guid 1>-http://host1:1/ | 1 |
+ // | namespace-<guid 1>-http://host2:2/ | 3 |
+ // | namespace-<guid 2>-http://host1:1/ | 1 |
+ // | namespace-<guid 2>-http://host2:2/ | 4 |
+ // | next-map-id | 5 |
+ // | version | 1 |
+ mock_data_[StdStringToUint8Vector(
+ std::string("namespace-") + test_namespace1_id_ + "-" +
+ test_origin1_.GetURL().spec())] = StdStringToUint8Vector("1");
+ mock_data_[StdStringToUint8Vector(
+ std::string("namespace-") + test_namespace1_id_ + "-" +
+ test_origin2_.GetURL().spec())] = StdStringToUint8Vector("3");
+ mock_data_[StdStringToUint8Vector(
+ std::string("namespace-") + test_namespace2_id_ + "-" +
+ test_origin1_.GetURL().spec())] = StdStringToUint8Vector("1");
+ mock_data_[StdStringToUint8Vector(
+ std::string("namespace-") + test_namespace2_id_ + "-" +
+ test_origin2_.GetURL().spec())] = StdStringToUint8Vector("4");
+
+ mock_data_[next_map_id_key_] = StdStringToUint8Vector("5");
+
+ mock_data_[StdStringToUint8Vector("map-1-key1")] =
+ StdStringToUint8Vector("data1");
+ mock_data_[StdStringToUint8Vector("map-3-key1")] =
+ StdStringToUint8Vector("data3");
+ mock_data_[StdStringToUint8Vector("map-4-key1")] =
+ StdStringToUint8Vector("data4");
+
+ mock_data_[database_version_key_] = StdStringToUint8Vector("1");
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ std::string test_namespace1_id_;
+ std::string test_namespace2_id_;
+ std::string test_namespace3_id_;
+ url::Origin test_origin1_;
+ url::Origin test_origin2_;
+ std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_;
+ FakeLevelDBDatabase database_;
+
+ std::vector<uint8_t> database_version_key_;
+ std::vector<uint8_t> next_map_id_key_;
+ std::vector<uint8_t> namespaces_prefix_key_;
+};
+
+TEST_F(SessionStorageMetadataTest, SaveNewMetadata) {
+ SessionStorageMetadata metadata;
+ std::vector<leveldb::mojom::BatchedOperationPtr> operations =
+ metadata.SetupNewDatabase();
+
+ DatabaseError error;
+ database_.Write(std::move(operations),
+ base::BindOnce(&ErrorCallback, &error));
+ EXPECT_EQ(DatabaseError::OK, error);
+
+ EXPECT_EQ(StdStringToUint8Vector("1"), mock_data_[database_version_key_]);
+ EXPECT_EQ(StdStringToUint8Vector("0"), mock_data_[next_map_id_key_]);
+}
+
+TEST_F(SessionStorageMetadataTest, LoadingData) {
+ SetupTestData();
+ SessionStorageMetadata metadata;
+ ReadMetadataFromDatabase(&metadata);
+
+ EXPECT_EQ(5, metadata.NextMapId());
+ EXPECT_EQ(2ul, metadata.namespace_origin_map().size());
+
+ // Namespace 1 should have 2 origins, referencing map 1 and 3. Map 1 is shared
+ // between namespace 1 and namespace 2.
+ auto entry = metadata.GetOrCreateNamespaceEntry(test_namespace1_id_);
+ EXPECT_EQ(test_namespace1_id_, entry->first);
+ EXPECT_EQ(2ul, entry->second.size());
+ EXPECT_EQ(StdStringToUint8Vector("map-1-"),
+ entry->second[test_origin1_]->KeyPrefix());
+ EXPECT_EQ(2, entry->second[test_origin1_]->ReferenceCount());
+ EXPECT_EQ(StdStringToUint8Vector("map-3-"),
+ entry->second[test_origin2_]->KeyPrefix());
+ EXPECT_EQ(1, entry->second[test_origin2_]->ReferenceCount());
+
+ // Namespace 2 is the same, except the second origin references map 4.
+ entry = metadata.GetOrCreateNamespaceEntry(test_namespace2_id_);
+ EXPECT_EQ(test_namespace2_id_, entry->first);
+ EXPECT_EQ(2ul, entry->second.size());
+ EXPECT_EQ(StdStringToUint8Vector("map-1-"),
+ entry->second[test_origin1_]->KeyPrefix());
+ EXPECT_EQ(2, entry->second[test_origin1_]->ReferenceCount());
+ EXPECT_EQ(StdStringToUint8Vector("map-4-"),
+ entry->second[test_origin2_]->KeyPrefix());
+ EXPECT_EQ(1, entry->second[test_origin2_]->ReferenceCount());
+}
+
+TEST_F(SessionStorageMetadataTest, SaveNewMap) {
+ SetupTestData();
+ SessionStorageMetadata metadata;
+ ReadMetadataFromDatabase(&metadata);
+
+ std::vector<leveldb::mojom::BatchedOperationPtr> operations;
+ auto ns1_entry = metadata.GetOrCreateNamespaceEntry(test_namespace1_id_);
+ auto map_data =
+ metadata.RegisterNewMap(ns1_entry, test_origin1_, &operations);
+ ASSERT_TRUE(map_data);
+
+ // Verify in-memory metadata is correct.
+ EXPECT_EQ(StdStringToUint8Vector("map-5-"),
+ ns1_entry->second[test_origin1_]->KeyPrefix());
+ EXPECT_EQ(1, ns1_entry->second[test_origin1_]->ReferenceCount());
+ EXPECT_EQ(1, metadata.GetOrCreateNamespaceEntry(test_namespace2_id_)
+ ->second[test_origin1_]
+ ->ReferenceCount());
+
+ DatabaseError error;
+ database_.Write(std::move(operations),
+ base::BindOnce(&ErrorCallback, &error));
+ EXPECT_EQ(DatabaseError::OK, error);
+
+ // Verify metadata was written to disk.
+ EXPECT_EQ(StdStringToUint8Vector("6"), mock_data_[next_map_id_key_]);
+ EXPECT_EQ(StdStringToUint8Vector("5"),
+ mock_data_[StdStringToUint8Vector(std::string("namespace-") +
+ test_namespace1_id_ + "-" +
+ test_origin1_.GetURL().spec())]);
+}
+
+TEST_F(SessionStorageMetadataTest, ShallowCopies) {
+ SetupTestData();
+ SessionStorageMetadata metadata;
+ ReadMetadataFromDatabase(&metadata);
+
+ auto ns1_entry = metadata.GetOrCreateNamespaceEntry(test_namespace1_id_);
+ auto ns3_entry = metadata.GetOrCreateNamespaceEntry(test_namespace3_id_);
+
+ std::vector<leveldb::mojom::BatchedOperationPtr> operations;
+ metadata.RegisterShallowClonedNamespace(ns1_entry, ns3_entry, &operations);
+
+ DatabaseError error;
+ database_.Write(std::move(operations),
+ base::BindOnce(&ErrorCallback, &error));
+ EXPECT_EQ(DatabaseError::OK, error);
+
+ // Verify in-memory metadata is correct.
+ EXPECT_EQ(StdStringToUint8Vector("map-1-"),
+ ns3_entry->second[test_origin1_]->KeyPrefix());
+ EXPECT_EQ(StdStringToUint8Vector("map-3-"),
+ ns3_entry->second[test_origin2_]->KeyPrefix());
+ EXPECT_EQ(ns1_entry->second[test_origin1_].get(),
+ ns3_entry->second[test_origin1_].get());
+ EXPECT_EQ(ns1_entry->second[test_origin2_].get(),
+ ns3_entry->second[test_origin2_].get());
+ EXPECT_EQ(3, ns3_entry->second[test_origin1_]->ReferenceCount());
+ EXPECT_EQ(2, ns3_entry->second[test_origin2_]->ReferenceCount());
+
+ // Verify metadata was written to disk.
+ EXPECT_EQ(StdStringToUint8Vector("1"),
+ mock_data_[StdStringToUint8Vector(std::string("namespace-") +
+ test_namespace3_id_ + "-" +
+ test_origin1_.GetURL().spec())]);
+ EXPECT_EQ(StdStringToUint8Vector("3"),
+ mock_data_[StdStringToUint8Vector(std::string("namespace-") +
+ test_namespace3_id_ + "-" +
+ test_origin2_.GetURL().spec())]);
+}
+
+TEST_F(SessionStorageMetadataTest, DeleteNamespace) {
+ SetupTestData();
+ SessionStorageMetadata metadata;
+ ReadMetadataFromDatabase(&metadata);
+
+ std::vector<leveldb::mojom::BatchedOperationPtr> operations;
+ metadata.DeleteNamespace(test_namespace1_id_, &operations);
+ DatabaseError error;
+ database_.Write(std::move(operations),
+ base::BindOnce(&ErrorCallback, &error));
+ EXPECT_EQ(DatabaseError::OK, error);
+
+ EXPECT_FALSE(
+ base::ContainsKey(metadata.namespace_origin_map(), test_namespace1_id_));
+
+ // Verify in-memory metadata is correct.
+ auto ns2_entry = metadata.GetOrCreateNamespaceEntry(test_namespace2_id_);
+ EXPECT_EQ(1, ns2_entry->second[test_origin1_]->ReferenceCount());
+ EXPECT_EQ(1, ns2_entry->second[test_origin2_]->ReferenceCount());
+
+ // Verify metadata and data was deleted from disk.
+ EXPECT_FALSE(base::ContainsKey(
+ mock_data_,
+ StdStringToUint8Vector(std::string("namespace-") + test_namespace1_id_ +
+ "-" + test_origin1_.GetURL().spec())));
+ EXPECT_FALSE(base::ContainsKey(
+ mock_data_,
+ StdStringToUint8Vector(std::string("namespace-") + test_namespace1_id_ +
+ "-" + test_origin2_.GetURL().spec())));
+ EXPECT_FALSE(
+ base::ContainsKey(mock_data_, StdStringToUint8Vector("map-3-key1")));
+ EXPECT_TRUE(
+ base::ContainsKey(mock_data_, StdStringToUint8Vector("map-1-key1")));
+}
+
+TEST_F(SessionStorageMetadataTest, DeleteArea) {
+ SetupTestData();
+ SessionStorageMetadata metadata;
+ ReadMetadataFromDatabase(&metadata);
+
+ // First delete an area with a shared map.
+ std::vector<leveldb::mojom::BatchedOperationPtr> operations;
+ metadata.DeleteArea(test_namespace1_id_, test_origin1_, &operations);
+ DatabaseError error;
+ database_.Write(std::move(operations),
+ base::BindOnce(&ErrorCallback, &error));
+ EXPECT_EQ(DatabaseError::OK, error);
+
+ // Verify in-memory metadata is correct.
+ auto ns1_entry = metadata.GetOrCreateNamespaceEntry(test_namespace1_id_);
+ auto ns2_entry = metadata.GetOrCreateNamespaceEntry(test_namespace2_id_);
+ EXPECT_FALSE(base::ContainsKey(ns1_entry->second, test_origin1_));
+ EXPECT_EQ(1, ns1_entry->second[test_origin2_]->ReferenceCount());
+ EXPECT_EQ(1, ns2_entry->second[test_origin1_]->ReferenceCount());
+ EXPECT_EQ(1, ns2_entry->second[test_origin2_]->ReferenceCount());
+
+ // Verify only the applicable data was deleted.
+ EXPECT_FALSE(base::ContainsKey(
+ mock_data_,
+ StdStringToUint8Vector(std::string("namespace-") + test_namespace1_id_ +
+ "-" + test_origin1_.GetURL().spec())));
+ EXPECT_TRUE(base::ContainsKey(
+ mock_data_,
+ StdStringToUint8Vector(std::string("namespace-") + test_namespace1_id_ +
+ "-" + test_origin2_.GetURL().spec())));
+ EXPECT_TRUE(
+ base::ContainsKey(mock_data_, StdStringToUint8Vector("map-1-key1")));
+ EXPECT_TRUE(
+ base::ContainsKey(mock_data_, StdStringToUint8Vector("map-4-key1")));
+
+ // Now delete an area with a unique map.
+ operations.clear();
+ metadata.DeleteArea(test_namespace2_id_, test_origin2_, &operations);
+ database_.Write(std::move(operations),
+ base::BindOnce(&ErrorCallback, &error));
+ EXPECT_EQ(DatabaseError::OK, error);
+
+ // Verify in-memory metadata is correct.
+ EXPECT_FALSE(base::ContainsKey(ns1_entry->second, test_origin1_));
+ EXPECT_EQ(1, ns1_entry->second[test_origin2_]->ReferenceCount());
+ EXPECT_EQ(1, ns2_entry->second[test_origin1_]->ReferenceCount());
+ EXPECT_FALSE(base::ContainsKey(ns2_entry->second, test_origin2_));
+
+ // Verify only the applicable data was deleted.
+ EXPECT_TRUE(base::ContainsKey(
+ mock_data_,
+ StdStringToUint8Vector(std::string("namespace-") + test_namespace2_id_ +
+ "-" + test_origin1_.GetURL().spec())));
+ EXPECT_FALSE(base::ContainsKey(
+ mock_data_,
+ StdStringToUint8Vector(std::string("namespace-") + test_namespace2_id_ +
+ "-" + test_origin2_.GetURL().spec())));
+ EXPECT_TRUE(
+ base::ContainsKey(mock_data_, StdStringToUint8Vector("map-1-key1")));
+ EXPECT_TRUE(
+ base::ContainsKey(mock_data_, StdStringToUint8Vector("map-3-key1")));
+ EXPECT_FALSE(
+ base::ContainsKey(mock_data_, StdStringToUint8Vector("map-4-key1")));
+}
+
+class SessionStorageMetadataMigrationTest : public testing::Test {
+ public:
+ SessionStorageMetadataMigrationTest()
+ : test_namespace1_id_(base::GenerateGUID()),
+ test_namespace2_id_(base::GenerateGUID()),
+ test_origin1_(url::Origin::Create(GURL("http://host1:1/"))) {
+ next_map_id_key_ = std::vector<uint8_t>(
+ std::begin(SessionStorageMetadata::kNextMapIdKeyBytes),
+ std::end(SessionStorageMetadata::kNextMapIdKeyBytes));
+ database_version_key_ = std::vector<uint8_t>(
+ std::begin(SessionStorageMetadata::kDatabaseVersionBytes),
+ std::end(SessionStorageMetadata::kDatabaseVersionBytes));
+ namespaces_prefix_key_ = std::vector<uint8_t>(
+ std::begin(SessionStorageMetadata::kNamespacePrefixBytes),
+ std::end(SessionStorageMetadata::kNamespacePrefixBytes));
+ }
+ ~SessionStorageMetadataMigrationTest() override = default;
+
+ void SetUp() override {
+ ASSERT_TRUE(temp_path_.CreateUniqueTempDir());
+ in_memory_env_ =
+ leveldb_chrome::NewMemEnv("SessionStorage", LevelDBEnv::Get());
+ leveldb_env::Options options;
+ options.create_if_missing = true;
+ options.env = in_memory_env_.get();
+ std::unique_ptr<leveldb::DB> db;
+ leveldb::Status s =
+ leveldb_env::OpenDB(options, temp_path_.GetPath().AsUTF8Unsafe(), &db);
+ ASSERT_TRUE(s.ok()) << s.ToString();
+ old_ss_database_ = base::MakeRefCounted<SessionStorageDatabase>(
+ temp_path_.GetPath(), base::ThreadTaskRunnerHandle::Get().get());
+ old_ss_database_->SetDatabaseForTesting(std::move(db));
+ }
+
+ leveldb::DB* db() { return old_ss_database_->db(); }
+
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::ScopedTempDir temp_path_;
+ std::string test_namespace1_id_;
+ std::string test_namespace2_id_;
+ url::Origin test_origin1_;
+ std::unique_ptr<leveldb::Env> in_memory_env_;
+ scoped_refptr<SessionStorageDatabase> old_ss_database_;
+
+ std::vector<uint8_t> database_version_key_;
+ std::vector<uint8_t> next_map_id_key_;
+ std::vector<uint8_t> namespaces_prefix_key_;
+};
+
+TEST_F(SessionStorageMetadataMigrationTest, MigrateV0ToV1) {
+ base::string16 key = base::ASCIIToUTF16("key");
+ base::string16 value = base::ASCIIToUTF16("value");
+ base::string16 key2 = base::ASCIIToUTF16("key2");
+ key2.push_back(0xd83d);
+ key2.push_back(0xde00);
+ DOMStorageValuesMap data;
+ data[key] = base::NullableString16(value, false);
+ data[key2] = base::NullableString16(value, false);
+ EXPECT_TRUE(old_ss_database_->CommitAreaChanges(test_namespace1_id_,
+ test_origin1_, false, data));
+ EXPECT_TRUE(old_ss_database_->CloneNamespace(test_namespace1_id_,
+ test_namespace2_id_));
+
+ SessionStorageMetadata metadata;
+ // Read non-existant version, give new version to save.
+ leveldb::ReadOptions options;
+ std::string db_value;
+ leveldb::Status s = db()->Get(options, leveldb::Slice("version"), &db_value);
+ EXPECT_TRUE(s.IsNotFound());
+ std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations;
+ EXPECT_TRUE(
+ metadata.ParseDatabaseVersion(base::nullopt, &migration_operations));
+ EXPECT_FALSE(migration_operations.empty());
+ EXPECT_EQ(1ul, migration_operations.size());
+
+ // Grab the next map id, verify it doesn't crash.
+ s = db()->Get(options, leveldb::Slice("next-map-id"), &db_value);
+ EXPECT_TRUE(s.ok());
+ metadata.ParseNextMapId(leveldb::StdStringToUint8Vector(db_value));
+
+ // Get all keys-value pairs with the given key prefix
+ std::vector<leveldb::mojom::KeyValuePtr> values;
+ {
+ std::unique_ptr<leveldb::Iterator> it(db()->NewIterator(options));
+ it->Seek(leveldb::Slice("namespace-"));
+ for (; it->Valid(); it->Next()) {
+ if (!it->key().starts_with(leveldb::Slice("namespace-")))
+ break;
+ leveldb::mojom::KeyValuePtr kv = leveldb::mojom::KeyValue::New();
+ kv->key = leveldb::GetVectorFor(it->key());
+ kv->value = leveldb::GetVectorFor(it->value());
+ values.push_back(std::move(kv));
+ }
+ EXPECT_TRUE(it->status().ok());
+ }
+
+ EXPECT_TRUE(
+ metadata.ParseNamespaces(std::move(values), &migration_operations));
+ EXPECT_FALSE(migration_operations.empty());
+ EXPECT_EQ(3ul, migration_operations.size());
+
+ EXPECT_TRUE(base::ContainsValue(
+ migration_operations,
+ leveldb::mojom::BatchedOperation::New(
+ leveldb::mojom::BatchOperationType::PUT_KEY,
+ StdStringToUint8Vector("version"), StdStringToUint8Vector("1"))));
+ EXPECT_TRUE(base::ContainsValue(
+ migration_operations,
+ leveldb::mojom::BatchedOperation::New(
+ leveldb::mojom::BatchOperationType::DELETE_KEY,
+ StdStringToUint8Vector("map-0-"), base::nullopt)));
+ EXPECT_TRUE(base::ContainsValue(
+ migration_operations,
+ leveldb::mojom::BatchedOperation::New(
+ leveldb::mojom::BatchOperationType::DELETE_KEY,
+ StdStringToUint8Vector("namespace-"), base::nullopt)));
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc
new file mode 100644
index 00000000000..d02473e3d23
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.cc
@@ -0,0 +1,178 @@
+// 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/dom_storage/session_storage_namespace_impl_mojo.h"
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+
+#include "components/services/leveldb/public/cpp/util.h"
+#include "content/public/browser/child_process_security_policy.h"
+
+namespace content {
+
+SessionStorageNamespaceImplMojo::SessionStorageNamespaceImplMojo(
+ std::string namespace_id,
+ SessionStorageDataMap::Listener* data_map_listener,
+ RegisterShallowClonedNamespace add_namespace_callback,
+ SessionStorageLevelDBWrapper::RegisterNewAreaMap register_new_map_callback)
+ : namespace_id_(std::move(namespace_id)),
+ data_map_listener_(data_map_listener),
+ add_namespace_callback_(std::move(add_namespace_callback)),
+ register_new_map_callback_(std::move(register_new_map_callback)) {}
+
+SessionStorageNamespaceImplMojo::~SessionStorageNamespaceImplMojo() = default;
+
+bool SessionStorageNamespaceImplMojo::HasAreaForOrigin(
+ const url::Origin& origin) const {
+ return origin_areas_.find(origin) != origin_areas_.end();
+}
+
+void SessionStorageNamespaceImplMojo::PopulateFromMetadata(
+ leveldb::mojom::LevelDBDatabase* database,
+ SessionStorageMetadata::NamespaceEntry namespace_metadata,
+ const std::map<std::vector<uint8_t>, SessionStorageDataMap*>&
+ current_data_maps) {
+ DCHECK(!IsPopulated());
+ DCHECK(!waiting_on_clone_population());
+ database_ = database;
+ populated_ = true;
+ namespace_entry_ = namespace_metadata;
+ for (const auto& pair : namespace_entry_->second) {
+ scoped_refptr<SessionStorageDataMap> data_map;
+ auto map_it = current_data_maps.find(pair.second->MapNumberAsBytes());
+ if (map_it == current_data_maps.end()) {
+ data_map = SessionStorageDataMap::Create(data_map_listener_, pair.second,
+ database_);
+ } else {
+ data_map = base::WrapRefCounted(map_it->second);
+ }
+ origin_areas_[pair.first] = std::make_unique<SessionStorageLevelDBWrapper>(
+ namespace_entry_, pair.first, std::move(data_map),
+ register_new_map_callback_);
+ }
+}
+
+void SessionStorageNamespaceImplMojo::PopulateAsClone(
+ leveldb::mojom::LevelDBDatabase* database,
+ SessionStorageMetadata::NamespaceEntry namespace_metadata,
+ const OriginAreas& areas_to_clone) {
+ DCHECK(!IsPopulated());
+ database_ = database;
+ populated_ = true;
+ waiting_on_clone_population_ = false;
+ namespace_entry_ = namespace_metadata;
+ std::transform(areas_to_clone.begin(), areas_to_clone.end(),
+ std::inserter(origin_areas_, origin_areas_.begin()),
+ [namespace_metadata](const auto& source) {
+ return std::make_pair(
+ source.first, source.second->Clone(namespace_metadata));
+ });
+ if (!run_after_clone_population_.empty()) {
+ for (base::OnceClosure& callback : run_after_clone_population_)
+ std::move(callback).Run();
+ run_after_clone_population_.clear();
+ }
+}
+
+void SessionStorageNamespaceImplMojo::Reset() {
+ namespace_entry_ = SessionStorageMetadata::NamespaceEntry();
+ process_id_ = ChildProcessHost::kInvalidUniqueID;
+ database_ = nullptr;
+ waiting_on_clone_population_ = false;
+ bind_waiting_on_clone_population_ = false;
+ run_after_clone_population_.clear();
+ populated_ = false;
+ origin_areas_.clear();
+ bindings_.CloseAllBindings();
+}
+
+void SessionStorageNamespaceImplMojo::Bind(
+ mojom::SessionStorageNamespaceRequest request,
+ int process_id) {
+ if (waiting_on_clone_population_) {
+ bind_waiting_on_clone_population_ = true;
+ run_after_clone_population_.push_back(
+ base::BindOnce(&SessionStorageNamespaceImplMojo::Bind,
+ base::Unretained(this), std::move(request), process_id));
+ return;
+ }
+ DCHECK(IsPopulated());
+ process_id_ = process_id;
+ bindings_.AddBinding(this, std::move(request));
+ bind_waiting_on_clone_population_ = false;
+}
+
+void SessionStorageNamespaceImplMojo::PurgeUnboundWrappers() {
+ auto it = origin_areas_.begin();
+ while (it != origin_areas_.end()) {
+ if (!it->second->IsBound())
+ it = origin_areas_.erase(it);
+ }
+}
+
+void SessionStorageNamespaceImplMojo::RemoveOriginData(
+ const url::Origin& origin) {
+ if (waiting_on_clone_population_) {
+ run_after_clone_population_.push_back(
+ base::BindOnce(&SessionStorageNamespaceImplMojo::RemoveOriginData,
+ base::Unretained(this), origin));
+ return;
+ }
+ DCHECK(IsPopulated());
+ auto it = origin_areas_.find(origin);
+ if (it == origin_areas_.end())
+ return;
+ // Renderer process expects |source| to always be two newline separated
+ // strings.
+ it->second->DeleteAll("\n", base::DoNothing());
+ it->second->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
+}
+
+void SessionStorageNamespaceImplMojo::OpenArea(
+ const url::Origin& origin,
+ mojom::LevelDBWrapperAssociatedRequest database) {
+ DCHECK(IsPopulated());
+ DCHECK(!bindings_.empty());
+ DCHECK_NE(process_id_, ChildProcessHost::kInvalidUniqueID);
+ if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin(
+ process_id_, origin.GetURL())) {
+ bindings_.ReportBadMessage("Access denied for sessionStorage request");
+ return;
+ }
+ auto it = origin_areas_.find(origin);
+ if (it == origin_areas_.end()) {
+ it = origin_areas_
+ .emplace(std::make_pair(
+ origin, std::make_unique<SessionStorageLevelDBWrapper>(
+ namespace_entry_, origin,
+ SessionStorageDataMap::Create(
+ data_map_listener_,
+ register_new_map_callback_.Run(
+ namespace_entry_, origin),
+ database_),
+ register_new_map_callback_)))
+ .first;
+ }
+ it->second->Bind(std::move(database));
+}
+
+void SessionStorageNamespaceImplMojo::Clone(
+ const std::string& clone_to_namespace) {
+ add_namespace_callback_.Run(namespace_entry_, clone_to_namespace,
+ origin_areas_);
+}
+
+void SessionStorageNamespaceImplMojo::FlushOriginForTesting(
+ const url::Origin& origin) {
+ if (!IsPopulated())
+ return;
+ auto it = origin_areas_.find(origin);
+ if (it == origin_areas_.end())
+ return;
+ it->second->data_map()->level_db_wrapper()->ScheduleImmediateCommit();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
new file mode 100644
index 00000000000..5936c469fc7
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
@@ -0,0 +1,158 @@
+// 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_DOM_STORAGE_SESSION_STORAGE_NAMESPACE_IMPL_MOJO_H_
+#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_NAMESPACE_IMPL_MOJO_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/ref_counted.h"
+#include "content/browser/dom_storage/session_storage_data_map.h"
+#include "content/browser/dom_storage/session_storage_leveldb_wrapper.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/common/leveldb_wrapper.mojom.h"
+#include "content/common/storage_partition_service.mojom.h"
+#include "content/public/common/child_process_host.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "url/origin.h"
+
+namespace content {
+
+// Implements the mojo interface SessionStorageNamespace. Stores data maps per
+// origin, which are accessible using the LevelDBWrapper interface with the
+// |OpenArea| call. Supports cloning (shallow cloning with copy-on-write
+// behavior) from another SessionStorageNamespaceImplMojo.
+//
+// This class is populated & bound in the following patterns:
+// 1. The namespace is new or being populated from data on disk, and
+// |PopulateFromMetadata| is called. Afterwards |Bind| can be called.
+// 2. The namespace is being created as a clone from a |Clone| call on another
+// SessionStorageNamespaceImplMojo. PopulateFromMetadata is called with the
+// data from the other namespace, and then |Bind| can be called afterwards.
+// 3. The namespace is being created as a clone, but the |Clone| call from the
+// source namespace hasn't been called yet. |SetWaitingForClonePopulation| is
+// called first, after which |Bind| can be called. The actually binding
+// doesn't happen until |PopulateAsClone| is finally called with the source
+// namespace data.
+// Note: The reason for cases 2 and 3 is because there are two ways the Session
+// Storage system knows about clones. First, it gets the |Clone| call on the
+// source namespace, coming from the renderer doing the navigation, and in the
+// correct order with any session storage modifications from that source
+// renderer. Second, the RenderViewHostImpl of the navigated-to-frame will
+// create the cloned namespace and expect to manage it's lifetime that way, and
+// this can happen before the first case, as they are on different task runners.
+class CONTENT_EXPORT SessionStorageNamespaceImplMojo final
+ : public mojom::SessionStorageNamespace {
+ public:
+ using OriginAreas =
+ std::map<url::Origin, std::unique_ptr<SessionStorageLevelDBWrapper>>;
+ using RegisterShallowClonedNamespace = base::RepeatingCallback<void(
+ SessionStorageMetadata::NamespaceEntry source_namespace,
+ const std::string& destination_namespace,
+ const OriginAreas& areas_to_clone)>;
+
+ // Constructs a namespace with the given |namespace_id|, expecting to be
+ // populated and bound later (see class comment). The |database| and
+ // |data_map_listener| are given to any data maps constructed for this
+ // namespace. The |add_namespace_callback| is called when the |Clone| method
+ // is called by mojo. The |register_new_map_callback| is given to the the
+ // SessionStorageLevelDBWrapper's, used per-origin, that are bound to in
+ // OpenArea.
+ SessionStorageNamespaceImplMojo(
+ std::string namespace_id,
+ SessionStorageDataMap::Listener* data_map_listener,
+ RegisterShallowClonedNamespace add_namespace_callback,
+ SessionStorageLevelDBWrapper::RegisterNewAreaMap
+ register_new_map_callback);
+
+ ~SessionStorageNamespaceImplMojo() override;
+
+ // Returns if a storage area exists for the given origin in this map.
+ bool HasAreaForOrigin(const url::Origin& origin) const;
+
+ void SetWaitingForClonePopulation() { waiting_on_clone_population_ = true; }
+
+ bool waiting_on_clone_population() { return waiting_on_clone_population_; }
+
+ // Called when this is a new namespace, or when the namespace was loaded from
+ // disk. Should be called before |Bind|.
+ void PopulateFromMetadata(
+ leveldb::mojom::LevelDBDatabase* database,
+ SessionStorageMetadata::NamespaceEntry namespace_metadata,
+ const std::map<std::vector<uint8_t>, SessionStorageDataMap*>&
+ current_data_maps);
+
+ // Can either be called before |Bind|, or if the source namespace isn't
+ // available yet, |SetWaitingForClonePopulation| can be called. Then |Bind|
+ // will work, and hold onto the request until after this method is called.
+ void PopulateAsClone(
+ leveldb::mojom::LevelDBDatabase* database,
+ SessionStorageMetadata::NamespaceEntry namespace_metadata,
+ const OriginAreas& areas_to_clone);
+
+ // Resets to a pre-populated and pre-bound state. Used when the owner needs to
+ // delete & recreate the database.
+ void Reset();
+
+ SessionStorageMetadata::NamespaceEntry namespace_entry() {
+ return namespace_entry_;
+ }
+
+ bool IsPopulated() const { return populated_; }
+
+ // Must be preceded by a call to |PopulateFromMetadata|, |PopulateAsClone|, or
+ // |SetWaitingForClonePopulation|. For the later case, |PopulateAsClone| must
+ // eventually be called before the SessionStorageNamespaceRequest can be
+ // bound.
+ void Bind(mojom::SessionStorageNamespaceRequest request, int process_id);
+
+ bool IsBound() const {
+ return !bindings_.empty() || bind_waiting_on_clone_population_;
+ }
+
+ // Removes any LevelDBWrappers bound in |OpenArea| that are no longer bound.
+ void PurgeUnboundWrappers();
+
+ // Removes data for the given origin from this namespace. If there is no data
+ // map for that given origin, this does nothing.
+ void RemoveOriginData(const url::Origin& origin);
+
+ // SessionStorageNamespace:
+ // Connects the given database mojo request to the data map for the given
+ // origin. Before connection, it checks to make sure the |process_id| given to
+ // the |Bind| method can access the given origin.
+ void OpenArea(const url::Origin& origin,
+ mojom::LevelDBWrapperAssociatedRequest database) override;
+
+ // Simply calls the |add_namespace_callback_| callback with this namespace's
+ // data.
+ void Clone(const std::string& clone_to_namespace) override;
+
+ void FlushOriginForTesting(const url::Origin& origin);
+
+ private:
+ const std::string namespace_id_;
+ SessionStorageMetadata::NamespaceEntry namespace_entry_;
+ int process_id_ = ChildProcessHost::kInvalidUniqueID;
+ leveldb::mojom::LevelDBDatabase* database_;
+
+ SessionStorageDataMap::Listener* data_map_listener_;
+ RegisterShallowClonedNamespace add_namespace_callback_;
+ SessionStorageLevelDBWrapper::RegisterNewAreaMap register_new_map_callback_;
+
+ bool waiting_on_clone_population_ = false;
+ bool bind_waiting_on_clone_population_ = false;
+ std::vector<base::OnceClosure> run_after_clone_population_;
+
+ bool populated_ = false;
+ OriginAreas origin_areas_;
+ mojo::BindingSet<mojom::SessionStorageNamespace> bindings_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_NAMESPACE_IMPL_MOJO_H_
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
new file mode 100644
index 00000000000..7ee00233e60
--- /dev/null
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
@@ -0,0 +1,458 @@
+// 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/dom_storage/session_storage_namespace_impl_mojo.h"
+
+#include "base/guid.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/dom_storage/session_storage_data_map.h"
+#include "content/browser/dom_storage/session_storage_metadata.h"
+#include "content/test/fake_leveldb_database.h"
+#include "content/test/leveldb_wrapper_test_util.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+using leveldb::StdStringToUint8Vector;
+using leveldb::mojom::DatabaseError;
+using NamespaceEntry = SessionStorageMetadata::NamespaceEntry;
+
+constexpr const int kTestProcessIdOrigin1 = 11;
+constexpr const int kTestProcessIdAllOrigins = 12;
+constexpr const int kTestProcessIdOrigin3 = 13;
+
+class MockListener : public SessionStorageDataMap::Listener {
+ public:
+ MockListener() {}
+ ~MockListener() override {}
+ MOCK_METHOD2(OnDataMapCreation,
+ void(const std::vector<uint8_t>& map_id,
+ SessionStorageDataMap* map));
+ MOCK_METHOD1(OnDataMapDestruction, void(const std::vector<uint8_t>& map_id));
+ MOCK_METHOD1(OnCommitResult, void(leveldb::mojom::DatabaseError error));
+};
+
+class SessionStorageNamespaceImplMojoTest : public testing::Test {
+ public:
+ SessionStorageNamespaceImplMojoTest()
+ : test_namespace_id1_(base::GenerateGUID()),
+ test_namespace_id2_(base::GenerateGUID()),
+ test_origin1_(url::Origin::Create(GURL("https://host1.com:1/"))),
+ test_origin2_(url::Origin::Create(GURL("https://host2.com:2/"))),
+ test_origin3_(url::Origin::Create(GURL("https://host3.com:3/"))),
+ database_(&mock_data_) {}
+ ~SessionStorageNamespaceImplMojoTest() override = default;
+
+ void SetUp() override {
+ // Create a database that already has a namespace saved.
+ metadata_.SetupNewDatabase();
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ NamespaceEntry entry =
+ metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_);
+ auto map_id =
+ metadata_.RegisterNewMap(entry, test_origin1_, &save_operations);
+ DCHECK(map_id->KeyPrefix() == StdStringToUint8Vector("map-0-"));
+ database_.Write(std::move(save_operations), base::DoNothing());
+ // Put some data in one of the maps.
+ mock_data_[StdStringToUint8Vector("map-0-key1")] =
+ StdStringToUint8Vector("data1");
+
+ auto* security_policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ security_policy->Add(kTestProcessIdOrigin1);
+ security_policy->Add(kTestProcessIdAllOrigins);
+ security_policy->Add(kTestProcessIdOrigin3);
+ security_policy->AddIsolatedOrigins(
+ {test_origin1_, test_origin2_, test_origin3_});
+ security_policy->LockToOrigin(kTestProcessIdOrigin1,
+ test_origin1_.GetURL());
+ security_policy->LockToOrigin(kTestProcessIdOrigin3,
+ test_origin3_.GetURL());
+
+ mojo::edk::SetDefaultProcessErrorCallback(
+ base::BindRepeating(&SessionStorageNamespaceImplMojoTest::OnBadMessage,
+ base::Unretained(this)));
+ }
+
+ void OnBadMessage(const std::string& reason) { bad_message_called_ = true; }
+
+ void TearDown() override {
+ auto* security_policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ security_policy->Remove(kTestProcessIdOrigin1);
+ security_policy->Remove(kTestProcessIdAllOrigins);
+ security_policy->Remove(kTestProcessIdOrigin3);
+
+ mojo::edk::SetDefaultProcessErrorCallback(
+ mojo::edk::ProcessErrorCallback());
+ }
+
+ // Creates a SessionStorageNamespaceImplMojo, saves it in the namespaces_ map,
+ // and returns a pointer to the object.
+ SessionStorageNamespaceImplMojo* CreateSessionStorageNamespaceImplMojo(
+ const std::string& namespace_id) {
+ DCHECK(namespaces_.find(namespace_id) == namespaces_.end());
+ SessionStorageNamespaceImplMojo::RegisterShallowClonedNamespace
+ add_namespace_callback =
+ base::BindRepeating(&SessionStorageNamespaceImplMojoTest::
+ RegisterShallowClonedNamespace,
+ base::Unretained(this));
+ SessionStorageLevelDBWrapper::RegisterNewAreaMap map_id_callback =
+ base::BindRepeating(
+ &SessionStorageNamespaceImplMojoTest::RegisterNewAreaMap,
+ base::Unretained(this));
+
+ auto namespace_impl = std::make_unique<SessionStorageNamespaceImplMojo>(
+ namespace_id, &listener_, std::move(add_namespace_callback),
+ std::move(map_id_callback));
+ auto* namespace_impl_ptr = namespace_impl.get();
+ namespaces_[namespace_id] = std::move(namespace_impl);
+ return namespace_impl_ptr;
+ }
+
+ scoped_refptr<SessionStorageMetadata::MapData> RegisterNewAreaMap(
+ NamespaceEntry namespace_entry,
+ const url::Origin& origin) {
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ auto map_data =
+ metadata_.RegisterNewMap(namespace_entry, origin, &save_operations);
+ database_.Write(std::move(save_operations), base::DoNothing());
+ return map_data;
+ }
+
+ void RegisterShallowClonedNamespace(
+ NamespaceEntry source_namespace,
+ const std::string& destination_namespace,
+ const SessionStorageNamespaceImplMojo::OriginAreas& areas_to_clone) {
+ std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
+ NamespaceEntry namespace_entry =
+ metadata_.GetOrCreateNamespaceEntry(destination_namespace);
+ metadata_.RegisterShallowClonedNamespace(source_namespace, namespace_entry,
+ &save_operations);
+ database_.Write(std::move(save_operations), base::DoNothing());
+
+ auto it = namespaces_.find(destination_namespace);
+ if (it == namespaces_.end()) {
+ auto* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(destination_namespace);
+ namespace_impl->PopulateAsClone(&database_, namespace_entry,
+ areas_to_clone);
+ return;
+ }
+ it->second->PopulateAsClone(&database_, namespace_entry, areas_to_clone);
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment task_environment_;
+ const std::string test_namespace_id1_;
+ const std::string test_namespace_id2_;
+ const url::Origin test_origin1_;
+ const url::Origin test_origin2_;
+ const url::Origin test_origin3_;
+ SessionStorageMetadata metadata_;
+ bool bad_message_called_ = false;
+
+ std::map<std::string, std::unique_ptr<SessionStorageNamespaceImplMojo>>
+ namespaces_;
+
+ testing::StrictMock<MockListener> listener_;
+ std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_;
+ FakeLevelDBDatabase database_;
+};
+
+TEST_F(SessionStorageNamespaceImplMojoTest, MetadataLoad) {
+ // Exercises creation, population, binding, and getting all data.
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
+
+ mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
+
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ namespaces_.clear();
+}
+
+TEST_F(SessionStorageNamespaceImplMojoTest, MetadataLoadWithMapOperations) {
+ // Exercises creation, population, binding, and a map operation, and then
+ // getting all the data.
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
+
+ mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
+
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(1);
+ test::PutSync(leveldb_1.get(), StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"), base::nullopt, "");
+
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(2ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ namespaces_.clear();
+}
+
+TEST_F(SessionStorageNamespaceImplMojoTest, CloneBeforeBind) {
+ // Exercises cloning the namespace before we bind to the new cloned namespace.
+ SessionStorageNamespaceImplMojo* namespace_impl1 =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+ SessionStorageNamespaceImplMojo* namespace_impl2 =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id2_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl1->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ mojom::SessionStorageNamespacePtr ss_namespace1;
+ namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1),
+ kTestProcessIdOrigin1);
+ ss_namespace1->Clone(test_namespace_id2_);
+ ss_namespace1.FlushForTesting();
+
+ ASSERT_TRUE(namespace_impl2->IsPopulated());
+
+ mojom::SessionStorageNamespacePtr ss_namespace2;
+ namespace_impl2->Bind(mojo::MakeRequest(&ss_namespace2),
+ kTestProcessIdOrigin1);
+ mojom::LevelDBWrapperAssociatedPtr leveldb_2;
+ ss_namespace2->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_2));
+
+ // Do a put in the cloned namespace.
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(2);
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+ test::PutSync(leveldb_2.get(), StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"), base::nullopt, "");
+
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_2.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(2ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+ namespaces_.clear();
+}
+
+TEST_F(SessionStorageNamespaceImplMojoTest, CloneAfterBind) {
+ // Exercises cloning the namespace before we bind to the new cloned namespace.
+ // Unlike the test above, we create a new area for the test_origin2_ in the
+ // new namespace.
+ SessionStorageNamespaceImplMojo* namespace_impl1 =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+ SessionStorageNamespaceImplMojo* namespace_impl2 =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id2_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl1->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ mojom::SessionStorageNamespacePtr ss_namespace1;
+ namespace_impl1->Bind(mojo::MakeRequest(&ss_namespace1),
+ kTestProcessIdOrigin1);
+
+ // Set that we are waiting for clone, so binding is possible.
+ namespace_impl2->SetWaitingForClonePopulation();
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
+ .Times(1);
+ // Get a new area.
+ mojom::SessionStorageNamespacePtr ss_namespace2;
+ namespace_impl2->Bind(mojo::MakeRequest(&ss_namespace2),
+ kTestProcessIdAllOrigins);
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o1;
+ mojom::LevelDBWrapperAssociatedPtr leveldb_n2_o2;
+ ss_namespace2->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_n2_o1));
+ ss_namespace2->OpenArea(test_origin2_, mojo::MakeRequest(&leveldb_n2_o2));
+
+ // Finally do the clone.
+ ss_namespace1->Clone(test_namespace_id2_);
+ ss_namespace1.FlushForTesting();
+ EXPECT_FALSE(bad_message_called_);
+ ASSERT_TRUE(namespace_impl2->IsPopulated());
+
+ // Do a put in the cloned namespace.
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(1);
+ test::PutSync(leveldb_n2_o2.get(), StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"), base::nullopt, "");
+
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_n2_o1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key1"),
+ StdStringToUint8Vector("data1"))));
+
+ data.clear();
+ status = test::GetAllSync(leveldb_n2_o2.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(1ul, data.size());
+ EXPECT_TRUE(base::ContainsValue(
+ data, mojom::KeyValue::New(StdStringToUint8Vector("key2"),
+ StdStringToUint8Vector("data2"))));
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1")))
+ .Times(1);
+ namespaces_.clear();
+}
+
+TEST_F(SessionStorageNamespaceImplMojoTest, RemoveOriginData) {
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
+
+ mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
+ ss_namespace.FlushForTesting();
+
+ EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(1);
+ namespace_impl->RemoveOriginData(test_origin1_);
+
+ std::vector<mojom::KeyValuePtr> data;
+ DatabaseError status = test::GetAllSync(leveldb_1.get(), &data);
+ EXPECT_EQ(DatabaseError::OK, status);
+ EXPECT_EQ(0ul, data.size());
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ namespaces_.clear();
+}
+
+TEST_F(SessionStorageNamespaceImplMojoTest, ProcessLockedToOtherOrigin) {
+ // Tries to open an area with a process that is locked to a different origin
+ // and verifies the bad message callback.
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
+ mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ ss_namespace->OpenArea(test_origin3_, mojo::MakeRequest(&leveldb_1));
+ ss_namespace.FlushForTesting();
+ EXPECT_TRUE(bad_message_called_);
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ namespaces_.clear();
+}
+
+TEST_F(SessionStorageNamespaceImplMojoTest, PurgeUnused) {
+ // Verifies that wrappers are kept alive after the area is unbound, and they
+ // are removed when PurgeUnboundWrappers() is called.
+ SessionStorageNamespaceImplMojo* namespace_impl =
+ CreateSessionStorageNamespaceImplMojo(test_namespace_id1_);
+
+ EXPECT_CALL(listener_,
+ OnDataMapCreation(StdStringToUint8Vector("0"), testing::_))
+ .Times(1);
+
+ namespace_impl->PopulateFromMetadata(
+ &database_, metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_),
+ std::map<std::vector<uint8_t>, SessionStorageDataMap*>());
+
+ mojom::SessionStorageNamespacePtr ss_namespace;
+ namespace_impl->Bind(mojo::MakeRequest(&ss_namespace), kTestProcessIdOrigin1);
+
+ mojom::LevelDBWrapperAssociatedPtr leveldb_1;
+ ss_namespace->OpenArea(test_origin1_, mojo::MakeRequest(&leveldb_1));
+ EXPECT_TRUE(namespace_impl->HasAreaForOrigin(test_origin1_));
+
+ EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
+ .Times(1);
+ leveldb_1.reset();
+ EXPECT_TRUE(namespace_impl->HasAreaForOrigin(test_origin1_));
+
+ namespace_impl->PurgeUnboundWrappers();
+ EXPECT_FALSE(namespace_impl->HasAreaForOrigin(test_origin1_));
+
+ namespaces_.clear();
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc b/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc
index 93027498724..d5d418186a1 100644
--- a/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc
+++ b/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc
@@ -6,7 +6,7 @@
#include "components/download/public/common/download_task_runner.h"
#include "content/browser/url_loader_factory_getter.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_url_loader_factory.h"
@@ -31,7 +31,7 @@ BlobDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() {
storage::BlobURLLoaderFactory::Create(
std::move(blob_data_handle_), url_,
mojo::MakeRequest(&url_loader_factory_ptr_info));
- return base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
+ return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
std::move(url_loader_factory_ptr_info));
}
diff --git a/chromium/content/browser/download/byte_stream_input_stream.cc b/chromium/content/browser/download/byte_stream_input_stream.cc
index 24782195796..d62aefaa703 100644
--- a/chromium/content/browser/download/byte_stream_input_stream.cc
+++ b/chromium/content/browser/download/byte_stream_input_stream.cc
@@ -4,13 +4,16 @@
#include "content/browser/download/byte_stream_input_stream.h"
+#include "components/download/public/common/download_task_runner.h"
#include "content/browser/byte_stream.h"
namespace content {
ByteStreamInputStream::ByteStreamInputStream(
std::unique_ptr<ByteStreamReader> stream_reader)
- : stream_reader_(std::move(stream_reader)),
+ : stream_reader_(
+ stream_reader.release(),
+ base::OnTaskRunnerDeleter(download::GetDownloadTaskRunner())),
completion_status_(download::DOWNLOAD_INTERRUPT_REASON_NONE) {}
ByteStreamInputStream::~ByteStreamInputStream() = default;
diff --git a/chromium/content/browser/download/byte_stream_input_stream.h b/chromium/content/browser/download/byte_stream_input_stream.h
index 1deaeb4b5a7..3ec4cbca9ff 100644
--- a/chromium/content/browser/download/byte_stream_input_stream.h
+++ b/chromium/content/browser/download/byte_stream_input_stream.h
@@ -30,7 +30,7 @@ class CONTENT_EXPORT ByteStreamInputStream : public download::InputStream {
private:
// ByteStreamReader to read from.
- std::unique_ptr<ByteStreamReader> stream_reader_;
+ std::unique_ptr<ByteStreamReader, base::OnTaskRunnerDeleter> stream_reader_;
// Status when the response completes.
download::DownloadInterruptReason completion_status_;
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index e642ee09851..1cae12047b7 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -18,7 +18,6 @@
#include "base/format_macros.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/path_service.h"
@@ -125,7 +124,7 @@ class DownloadTestContentBrowserClient : public TestContentBrowserClient {
class MockDownloadItemObserver : public download::DownloadItem::Observer {
public:
MockDownloadItemObserver() {}
- virtual ~MockDownloadItemObserver() {}
+ ~MockDownloadItemObserver() override {}
MOCK_METHOD1(OnDownloadUpdated, void(download::DownloadItem*));
MOCK_METHOD1(OnDownloadOpened, void(download::DownloadItem*));
@@ -139,7 +138,7 @@ class MockDownloadManagerObserver : public DownloadManager::Observer {
manager_ = manager;
manager->AddObserver(this);
}
- virtual ~MockDownloadManagerObserver() {
+ ~MockDownloadManagerObserver() override {
if (manager_)
manager_->RemoveObserver(this);
}
@@ -147,7 +146,7 @@ class MockDownloadManagerObserver : public DownloadManager::Observer {
MOCK_METHOD2(OnDownloadCreated,
void(DownloadManager*, download::DownloadItem*));
MOCK_METHOD1(ModelChanged, void(DownloadManager*));
- void ManagerGoingDown(DownloadManager* manager) {
+ void ManagerGoingDown(DownloadManager* manager) override {
DCHECK_EQ(manager_, manager);
MockManagerGoingDown(manager);
@@ -370,7 +369,7 @@ class CountingDownloadFile : public download::DownloadFileImpl {
download::GetDownloadTaskRunner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&CountingDownloadFile::GetNumberActiveFiles, &result),
- base::MessageLoop::current()->QuitWhenIdleClosure());
+ base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
base::RunLoop().Run();
DCHECK_NE(-1, result);
return result;
@@ -576,6 +575,46 @@ class DownloadCreateObserver : DownloadManager::Observer {
base::Closure completion_closure_;
};
+class ErrorStreamCountingObserver : download::DownloadItem::Observer {
+ public:
+ ErrorStreamCountingObserver() : item_(nullptr), count_(0){};
+
+ ~ErrorStreamCountingObserver() override {
+ if (item_)
+ item_->RemoveObserver(this);
+ }
+
+ void OnDownloadUpdated(download::DownloadItem* download) override {
+ std::unique_ptr<base::HistogramSamples> samples =
+ histogram_tester_.GetHistogramSamplesSinceCreation(
+ "Download.ParallelDownloadAddStreamSuccess");
+ if (samples->GetCount(0 /* failure */) == count_ &&
+ !completion_closure_.is_null())
+ base::ResetAndReturn(&completion_closure_).Run();
+ }
+
+ void OnDownloadDestroyed(download::DownloadItem* download) override {
+ item_ = nullptr;
+ }
+
+ void WaitForFinished(download::DownloadItem* item, int count) {
+ item_ = item;
+ count_ = count;
+ if (item_) {
+ item_->AddObserver(this);
+ base::RunLoop run_loop;
+ completion_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+ }
+
+ private:
+ base::HistogramTester histogram_tester_;
+ download::DownloadItem* item_;
+ int count_;
+ base::Closure completion_closure_;
+};
+
bool IsDownloadInState(download::DownloadItem::DownloadState state,
download::DownloadItem* item) {
return item->GetState() == state;
@@ -723,7 +762,7 @@ class DownloadContentTest : public ContentBrowserTest {
test_delegate_->SetDownloadManager(manager);
base::FilePath test_data_dir;
- ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &test_data_dir));
+ ASSERT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &test_data_dir));
embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
embedded_test_server()->RegisterRequestHandler(
base::Bind(&SlowDownloadHttpResponse::HandleSlowDownloadRequest));
@@ -974,7 +1013,8 @@ class ParallelDownloadTest : public DownloadContentTest {
void RunResumptionTest(
const download::DownloadItem::ReceivedSlices& received_slices,
int64_t total_length,
- size_t expected_request_count) {
+ size_t expected_request_count,
+ bool support_partial_response) {
EXPECT_TRUE(
base::FeatureList::IsEnabled(download::features::kParallelDownloading));
GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
@@ -983,6 +1023,7 @@ class ParallelDownloadTest : public DownloadContentTest {
parameters.etag = "ABC";
parameters.size = total_length;
parameters.last_modified = std::string();
+ parameters.support_partial_response = support_partial_response;
// Needed to specify HTTP connection type to create parallel download.
parameters.connection_type = net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1;
TestDownloadHttpResponse::StartServing(parameters, server_url);
@@ -999,12 +1040,17 @@ class ParallelDownloadTest : public DownloadContentTest {
// Resume the parallel download with sparse file and received slices data.
download->Resume();
WaitForCompletion(download);
- test_response_handler()->WaitUntilCompletion(expected_request_count);
-
- // Verify number of requests sent to the server.
- const TestDownloadResponseHandler::CompletedRequests& completed_requests =
- test_response_handler()->completed_requests();
- EXPECT_EQ(expected_request_count, completed_requests.size());
+ // TODO(qinmin): count the failed partial responses in DownloadJob when
+ // support_partial_response is false. EmbeddedTestServer doesn't know
+ // whether completing or canceling the response will come first.
+ if (support_partial_response) {
+ test_response_handler()->WaitUntilCompletion(expected_request_count);
+
+ // Verify number of requests sent to the server.
+ const TestDownloadResponseHandler::CompletedRequests& completed_requests =
+ test_response_handler()->completed_requests();
+ EXPECT_EQ(expected_request_count, completed_requests.size());
+ }
// Verify download content on disk.
ReadAndVerifyFileContents(parameters.pattern_generator_seed,
@@ -1013,6 +1059,7 @@ class ParallelDownloadTest : public DownloadContentTest {
// Verifies parallel download completion.
void RunCompletionTest(TestDownloadHttpResponse::Parameters& parameters) {
+ ErrorStreamCountingObserver observer;
EXPECT_TRUE(
base::FeatureList::IsEnabled(download::features::kParallelDownloading));
@@ -1026,22 +1073,28 @@ class ParallelDownloadTest : public DownloadContentTest {
parameters.connection_type = net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1;
TestRequestPauseHandler request_pause_handler;
parameters.on_pause_handler = request_pause_handler.GetOnPauseHandler();
+ // Send some data for the first request and pause it so download won't
+ // complete before other parallel requests are created.
parameters.pause_offset = DownloadRequestCore::kDownloadByteStreamSize;
TestDownloadHttpResponse::StartServing(parameters, server_url);
download::DownloadItem* download =
StartDownloadAndReturnItem(shell(), server_url);
- // Send some data for the first request and pause it so download won't
- // complete before other parallel requests are created.
- test_response_handler()->WaitUntilCompletion(2u);
+
+ if (parameters.support_partial_response)
+ test_response_handler()->WaitUntilCompletion(2u);
+ else
+ observer.WaitForFinished(download, 2);
// Now resume the first request.
request_pause_handler.Resume();
WaitForCompletion(download);
- test_response_handler()->WaitUntilCompletion(3u);
- const TestDownloadResponseHandler::CompletedRequests& completed_requests =
- test_response_handler()->completed_requests();
- EXPECT_EQ(kTestRequestCount, static_cast<int>(completed_requests.size()));
+ if (parameters.support_partial_response) {
+ test_response_handler()->WaitUntilCompletion(3u);
+ const TestDownloadResponseHandler::CompletedRequests& completed_requests =
+ test_response_handler()->completed_requests();
+ EXPECT_EQ(3u, completed_requests.size());
+ }
ReadAndVerifyFileContents(parameters.pattern_generator_seed,
parameters.size, download->GetTargetFilePath());
}
@@ -2141,7 +2194,14 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
EXPECT_TRUE(EnsureNoPendingDownloads());
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumedDownload) {
+// Flaky on ASAN. crbug.com/838403
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_RemoveResumedDownload DISABLED_RemoveResumedDownload
+#else
+#define MAYBE_RemoveResumedDownload RemoveResumedDownload
+#endif // defined(ADDRESS_SANITIZER)
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, MAYBE_RemoveResumedDownload) {
SetupErrorInjectionDownloads();
TestDownloadHttpResponse::Parameters parameters =
TestDownloadHttpResponse::Parameters::WithSingleInterruption(
@@ -2180,7 +2240,13 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumedDownload) {
test_response_handler()->WaitUntilCompletion(2u);
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumedDownload) {
+// TODO(qinmin): Flaky crashes on ASAN Linux. https://crbug.com/836689
+#if defined(OS_LINUX) && defined(ADDRESS_SANITIZER)
+#define MAYBE_CancelResumedDownload DISABLED_CancelResumedDownload
+#else
+#define MAYBE_CancelResumedDownload CancelResumedDownload
+#endif
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, MAYBE_CancelResumedDownload) {
SetupErrorInjectionDownloads();
TestDownloadHttpResponse::Parameters parameters =
TestDownloadHttpResponse::Parameters::WithSingleInterruption(
@@ -2919,7 +2985,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeServerError) {
}
// A cross-origin request that fails before it gets a response from the server
-// should result in the old page staying current.
+// should result in a network error page.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeNetworkError) {
SetupErrorInjectionDownloads();
GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
@@ -3169,6 +3235,17 @@ IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, OnlyFirstRequestValid) {
RunCompletionTest(parameters);
}
+// The server will send Accept-Ranges header without partial response.
+IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, NoPartialResponse) {
+ TestDownloadHttpResponse::Parameters parameters;
+ parameters.etag = "ABC";
+ parameters.size = 5097152;
+ parameters.support_byte_ranges = true;
+ parameters.support_partial_response = false;
+
+ RunCompletionTest(parameters);
+}
+
// Verify parallel download resumption.
IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, Resumption) {
// Create the received slices data, the last request is not finished and the
@@ -3179,7 +3256,8 @@ IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, Resumption) {
download::DownloadItem::ReceivedSlice(2000000, 1000,
false /* finished */)};
- RunResumptionTest(received_slices, 3000000, kTestRequestCount);
+ RunResumptionTest(received_slices, 3000000, kTestRequestCount,
+ true /* support_partial_response */);
}
// Verifies that if the last slice is finished, parallel download resumption
@@ -3194,7 +3272,8 @@ IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, ResumptionLastSliceFinished) {
// The server shouldn't receive an additional request, since the last slice
// is marked as finished.
- RunResumptionTest(received_slices, 3000000, kTestRequestCount - 1);
+ RunResumptionTest(received_slices, 3000000, kTestRequestCount - 1,
+ true /* support_partial_response */);
}
// Verifies that if the last slice is finished, but the database record is not
@@ -3210,7 +3289,23 @@ IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, ResumptionLastSliceUnfinished) {
// Client will send an out of range request where server will send back HTTP
// range not satisfied, and download can complete.
- RunResumptionTest(received_slices, 3000000, kTestRequestCount);
+ RunResumptionTest(received_slices, 3000000, kTestRequestCount,
+ true /* support_partial_response */);
+}
+
+// Verify that if server doesn't support partial response, resuming a parallel
+// download should complete the download.
+IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, ResumptionNoPartialResponse) {
+ // Create the received slices data, the last request is not finished and the
+ // server will send more data to finish the last slice.
+ std::vector<download::DownloadItem::ReceivedSlice> received_slices = {
+ download::DownloadItem::ReceivedSlice(0, 1000),
+ download::DownloadItem::ReceivedSlice(1000000, 1000),
+ download::DownloadItem::ReceivedSlice(2000000, 1000,
+ false /* finished */)};
+
+ RunResumptionTest(received_slices, 3000000, kTestRequestCount,
+ false /* support_partial_response */);
}
// Test to verify that the browser-side enforcement of X-Frame-Options does
@@ -3375,7 +3470,8 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, FetchErrorResponseBodyResumption) {
std::string("header_value"));
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, ForceDownloadMultipartRelatedPage) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ DISABLED_ForceDownloadMultipartRelatedPage) {
// Force downloading the MHTML.
DownloadTestContentBrowserClient new_client;
new_client.set_allowed_rendering_mhtml_over_http(false);
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index 316ddd4982c..081c7a2c2f1 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -14,9 +14,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
-#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
@@ -27,7 +25,6 @@
#include "components/download/downloader/in_progress/in_progress_cache_impl.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_file.h"
-#include "components/download/public/common/download_file_factory.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item_factory.h"
#include "components/download/public/common/download_item_impl.h"
@@ -37,13 +34,14 @@
#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/download_utils.h"
-#include "components/download/public/common/resource_downloader.h"
#include "components/download/public/common/url_download_handler_factory.h"
#include "content/browser/byte_stream.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/download/blob_download_url_loader_factory_getter.h"
#include "content/browser/download/byte_stream_input_stream.h"
#include "content/browser/download/download_resource_handler.h"
+#include "content/browser/download/download_url_loader_factory_getter_impl.h"
#include "content/browser/download/download_utils.h"
#include "content/browser/download/network_download_url_loader_factory_getter.h"
#include "content/browser/download/url_downloader.h"
@@ -54,7 +52,6 @@
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/throttling_url_loader.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_item_utils.h"
@@ -104,7 +101,7 @@ StoragePartitionImpl* GetStoragePartition(BrowserContext* context,
}
bool CanRequestURLFromRenderer(int render_process_id, GURL url) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Check if the renderer is permitted to request the requested URL.
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
render_process_id, url)) {
@@ -115,11 +112,12 @@ bool CanRequestURLFromRenderer(int render_process_id, GURL url) {
return true;
}
+// Creates an interrupted download and calls StartDownload. Can be called on
+// any thread.
void CreateInterruptedDownload(
- download::DownloadUrlParameters* params,
+ std::unique_ptr<download::DownloadUrlParameters> params,
download::DownloadInterruptReason reason,
base::WeakPtr<DownloadManagerImpl> download_manager) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<download::DownloadCreateInfo> failed_created_info(
new download::DownloadCreateInfo(
base::Time::Now(), base::WrapUnique(new download::DownloadSaveInfo)));
@@ -135,29 +133,6 @@ void CreateInterruptedDownload(
nullptr, params->callback()));
}
-// Helper functions for DownloadItem -> DownloadEntry for InProgressCache.
-
-uint64_t GetUniqueDownloadId() {
- // Get a new UKM download_id that is not 0.
- uint64_t download_id = 0;
- do {
- download_id = base::RandUint64();
- } while (download_id == 0);
- return download_id;
-}
-
-download::DownloadEntry CreateDownloadEntryFromItem(
- const download::DownloadItem& item,
- const std::string& request_origin,
- download::DownloadSource download_source,
- bool fetch_error_body,
- const download::DownloadUrlParameters::RequestHeadersType&
- request_headers) {
- return download::DownloadEntry(item.GetGuid(), request_origin,
- download_source, fetch_error_body,
- request_headers, GetUniqueDownloadId());
-}
-
void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
content::ResourceContext* resource_context,
@@ -189,8 +164,10 @@ void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
// If the download was accepted, the DownloadResourceHandler is now
// responsible for driving the request to completion.
// Otherwise, create an interrupted download.
- if (reason != download::DOWNLOAD_INTERRUPT_REASON_NONE)
- CreateInterruptedDownload(params.get(), reason, download_manager);
+ if (reason != download::DOWNLOAD_INTERRUPT_REASON_NONE) {
+ CreateInterruptedDownload(std::move(params), reason, download_manager);
+ return;
+ }
} else {
downloader.reset(UrlDownloader::BeginDownload(download_manager,
std::move(url_request),
@@ -204,48 +181,6 @@ void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
download_manager, std::move(downloader)));
}
-void BeginResourceDownload(
- std::unique_ptr<download::DownloadUrlParameters> params,
- std::unique_ptr<network::ResourceRequest> request,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- uint32_t download_id,
- base::WeakPtr<DownloadManagerImpl> download_manager,
- const GURL& site_url,
- const GURL& tab_url,
- const GURL& tab_referrer_url,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
- nullptr, base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
-
- // Check if the renderer is permitted to request the requested URL.
- if (params->render_process_host_id() >= 0 &&
- !CanRequestURLFromRenderer(params->render_process_host_id(),
- params->url())) {
- CreateInterruptedDownload(
- params.get(),
- download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST,
- download_manager);
- } else {
- // TODO(qinmin): Check the storage permission before creating the URLLoader.
- // This is already done for context menu download, but it is missing for
- // download service and download resumption.
- downloader.reset(
- download::ResourceDownloader::BeginDownload(
- download_manager, std::move(params), std::move(request),
- url_loader_factory_getter->GetURLLoaderFactory(), site_url, tab_url,
- tab_referrer_url, download_id, false, task_runner)
- .release());
- }
- task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(
- &download::UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
- download_manager, std::move(downloader)));
-}
-
class DownloadItemFactoryImpl : public download::DownloadItemFactory {
public:
DownloadItemFactoryImpl() {}
@@ -314,83 +249,32 @@ base::FilePath GetTemporaryDownloadDirectory() {
}
#endif
-} // namespace
-
-// Responsible for persisting the in-progress metadata associated with a
-// download.
-class InProgressDownloadObserver : public download::DownloadItem::Observer {
- public:
- explicit InProgressDownloadObserver(
- download::InProgressCache* in_progress_cache);
- ~InProgressDownloadObserver() override;
-
- private:
- // download::DownloadItem::Observer
- void OnDownloadUpdated(download::DownloadItem* download) override;
- void OnDownloadRemoved(download::DownloadItem* download) override;
-
- // The persistent cache to store in-progress metadata.
- download::InProgressCache* in_progress_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(InProgressDownloadObserver);
-};
-
-InProgressDownloadObserver::InProgressDownloadObserver(
- download::InProgressCache* in_progress_cache)
- : in_progress_cache_(in_progress_cache) {}
-
-InProgressDownloadObserver::~InProgressDownloadObserver() = default;
-
-void InProgressDownloadObserver::OnDownloadUpdated(
- download::DownloadItem* download) {
- // TODO(crbug.com/778425): Properly handle fail/resume/retry for downloads
- // that are in the INTERRUPTED state for a long time.
- if (!in_progress_cache_)
- return;
-
- switch (download->GetState()) {
- case download::DownloadItem::DownloadState::COMPLETE:
- // Intentional fallthrough.
- case download::DownloadItem::DownloadState::CANCELLED:
- if (in_progress_cache_)
- in_progress_cache_->RemoveEntry(download->GetGuid());
- break;
-
- case download::DownloadItem::DownloadState::INTERRUPTED:
- // Intentional fallthrough.
- case download::DownloadItem::DownloadState::IN_PROGRESS: {
- // Make sure the entry exists in the cache.
- base::Optional<download::DownloadEntry> entry_opt =
- in_progress_cache_->RetrieveEntry(download->GetGuid());
- download::DownloadEntry entry;
- if (!entry_opt.has_value()) {
- entry = CreateDownloadEntryFromItem(
- *download, std::string(), /* request_origin */
- download::DownloadSource::UNKNOWN, false, /* fetch_error_body */
- download::DownloadUrlParameters::RequestHeadersType());
- in_progress_cache_->AddOrReplaceEntry(entry);
- break;
- }
- entry = entry_opt.value();
- break;
+scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+CreateDownloadURLLoaderFactoryGetter(StoragePartitionImpl* storage_partition,
+ RenderFrameHost* rfh,
+ bool is_download) {
+ network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info;
+ network::mojom::URLLoaderFactoryRequest proxy_factory_request;
+ if (rfh) {
+ network::mojom::URLLoaderFactoryPtrInfo devtools_factory_ptr_info;
+ network::mojom::URLLoaderFactoryRequest devtools_factory_request =
+ MakeRequest(&devtools_factory_ptr_info);
+ if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+ static_cast<RenderFrameHostImpl*>(rfh), true, is_download,
+ &devtools_factory_request)) {
+ proxy_factory_ptr_info = std::move(devtools_factory_ptr_info);
+ proxy_factory_request = std::move(devtools_factory_request);
}
-
- default:
- break;
}
+ return base::MakeRefCounted<NetworkDownloadURLLoaderFactoryGetter>(
+ storage_partition->url_loader_factory_getter(),
+ std::move(proxy_factory_ptr_info), std::move(proxy_factory_request));
}
-void InProgressDownloadObserver::OnDownloadRemoved(
- download::DownloadItem* download) {
- if (!in_progress_cache_)
- return;
-
- in_progress_cache_->RemoveEntry(download->GetGuid());
-}
+} // namespace
DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
: item_factory_(new DownloadItemFactoryImpl()),
- file_factory_(new download::DownloadFileFactory()),
shutdown_needed_(true),
initialized_(false),
history_db_initialized_(false),
@@ -403,6 +287,13 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
download::UrlDownloadHandlerFactory::Install(new UrlDownloaderFactory());
+ in_progress_manager_ = std::make_unique<download::InProgressDownloadManager>(
+ this, base::BindRepeating(&IsOriginSecure));
+ in_progress_manager_->Initialize(
+ IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(),
+ base::BindOnce(&DownloadManagerImpl::PostInitialization,
+ weak_factory_.GetWeakPtr(),
+ DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE));
}
DownloadManagerImpl::~DownloadManagerImpl() {
@@ -485,28 +376,6 @@ bool DownloadManagerImpl::ShouldOpenDownload(
void DownloadManagerImpl::SetDelegate(DownloadManagerDelegate* delegate) {
delegate_ = delegate;
-
- // If initialization has not occurred and there's a delegate and cache,
- // initialize and indicate initialization is complete. Else, just indicate it
- // is ok to continue.
- if (initialized_ || in_progress_cache_initialized_)
- return;
-
- base::RepeatingClosure post_init_callback = base::BindRepeating(
- &DownloadManagerImpl::PostInitialization, weak_factory_.GetWeakPtr(),
- DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE);
-
- if (delegate_) {
- download::InProgressCache* in_progress_cache =
- delegate_->GetInProgressCache();
- if (in_progress_cache) {
- in_progress_cache->Initialize(std::move(post_init_callback));
- return;
- }
- }
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- std::move(post_init_callback));
}
DownloadManagerDelegate* DownloadManagerImpl::GetDelegate() const {
@@ -539,6 +408,8 @@ void DownloadManagerImpl::Shutdown() {
// We'll have nothing more to report to the observers after this point.
observers_.Clear();
+ in_progress_manager_->ShutDown();
+
if (delegate_)
delegate_->Shutdown();
delegate_ = nullptr;
@@ -558,86 +429,7 @@ bool DownloadManagerImpl::InterceptDownload(
return true;
}
-void DownloadManagerImpl::StartDownload(
- std::unique_ptr<download::DownloadCreateInfo> info,
- std::unique_ptr<download::InputStream> stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
- const download::DownloadUrlParameters::OnStartedCallback& on_started) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(info);
-
- uint32_t download_id = info->download_id;
- bool new_download = (download_id == download::DownloadItem::kInvalidId);
- if (new_download &&
- info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE &&
- InterceptDownload(*info)) {
- download::GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
- return;
- }
-
- // |stream| is only non-nil if the download request was successful.
- DCHECK((info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE &&
- !stream->IsEmpty()) ||
- (info->result != download::DOWNLOAD_INTERRUPT_REASON_NONE &&
- stream->IsEmpty()));
- DVLOG(20) << __func__ << "() result="
- << download::DownloadInterruptReasonToString(info->result);
- if (new_download) {
- download::RecordDownloadConnectionSecurity(info->url(), info->url_chain);
- download::RecordDownloadContentTypeSecurity(
- info->url(), info->url_chain, info->mime_type,
- base::BindRepeating(&IsOriginSecure));
- }
- base::Callback<void(uint32_t)> got_id(base::Bind(
- &DownloadManagerImpl::StartDownloadWithId, weak_factory_.GetWeakPtr(),
- base::Passed(&info), base::Passed(&stream),
- std::move(shared_url_loader_factory), on_started, new_download));
- if (new_download) {
- GetNextId(std::move(got_id));
- } else {
- std::move(got_id).Run(download_id);
- }
-}
-
-void DownloadManagerImpl::StartDownloadWithId(
- std::unique_ptr<download::DownloadCreateInfo> info,
- std::unique_ptr<download::InputStream> stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
- const download::DownloadUrlParameters::OnStartedCallback& on_started,
- bool new_download,
- uint32_t id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK_NE(download::DownloadItem::kInvalidId, id);
- download::DownloadItemImpl* download = nullptr;
- if (new_download) {
- download = CreateActiveItem(id, *info);
- } else {
- auto item_iterator = downloads_.find(id);
- // Trying to resume an interrupted download.
- if (item_iterator == downloads_.end() ||
- (item_iterator->second->GetState() ==
- download::DownloadItem::CANCELLED)) {
- // If the download is no longer known to the DownloadManager, then it was
- // removed after it was resumed. Ignore. If the download is cancelled
- // while resuming, then also ignore the request.
- if (info->request_handle)
- info->request_handle->CancelRequest(true);
- if (!on_started.is_null())
- on_started.Run(nullptr,
- download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
- // The ByteStreamReader lives and dies on the download sequence.
- if (info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE)
- download::GetDownloadTaskRunner()->DeleteSoon(FROM_HERE,
- stream.release());
- return;
- }
- download = item_iterator->second.get();
- }
- DownloadItemUtils::AttachInfo(
- download, GetBrowserContext(),
- WebContentsImpl::FromRenderFrameHostID(info->render_process_id,
- info->render_frame_id));
-
+base::FilePath DownloadManagerImpl::GetDefaultDownloadDirectory() {
base::FilePath default_download_directory;
#if defined(USE_X11)
// TODO(thomasanderson,crbug.com/784010): Remove this when all Linux
@@ -660,60 +452,61 @@ void DownloadManagerImpl::StartDownloadWithId(
GetContentClient()->browser()->GetDefaultDownloadDirectory();
}
- if (delegate_) {
- download::InProgressCache* in_progress_cache =
- delegate_->GetInProgressCache();
- if (in_progress_cache) {
- base::Optional<download::DownloadEntry> entry_opt =
- in_progress_cache->RetrieveEntry(download->GetGuid());
- if (!entry_opt.has_value()) {
- in_progress_cache->AddOrReplaceEntry(CreateDownloadEntryFromItem(
- *download, info->request_origin, info->download_source,
- info->fetch_error_body, info->request_headers));
- }
- }
+ return default_download_directory;
+}
- if (!in_progress_download_observer_) {
- in_progress_download_observer_.reset(
- new InProgressDownloadObserver(delegate_->GetInProgressCache()));
- }
- // May already observe this item, remove observer first.
- download->RemoveObserver(in_progress_download_observer_.get());
- download->AddObserver(in_progress_download_observer_.get());
- }
+void DownloadManagerImpl::OnNewDownloadStarted(
+ download::DownloadItem* download) {
+ for (auto& observer : observers_)
+ observer.OnDownloadCreated(this, download);
+}
- std::unique_ptr<download::DownloadFile> download_file;
+download::DownloadItemImpl* DownloadManagerImpl::GetDownloadItem(
+ uint32_t id,
+ bool new_download,
+ const download::DownloadCreateInfo& info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_NE(download::DownloadItem::kInvalidId, id);
- if (info->result == download::DOWNLOAD_INTERRUPT_REASON_NONE) {
- DCHECK(stream.get());
- download_file.reset(file_factory_->CreateFile(
- std::move(info->save_info), default_download_directory,
- std::move(stream), id, download->DestinationObserverAsWeakPtr()));
+ download::DownloadItemImpl* download = nullptr;
+ if (new_download) {
+ download = CreateActiveItem(id, info);
+ } else {
+ auto item_iterator = downloads_.find(id);
+ // Trying to resume an interrupted download.
+ if (item_iterator == downloads_.end() ||
+ (item_iterator->second->GetState() ==
+ download::DownloadItem::CANCELLED)) {
+ return nullptr;
+ }
+ download = item_iterator->second.get();
}
- // It is important to leave info->save_info intact in the case of an interrupt
- // so that the download::DownloadItem can salvage what it can out of a failed
- // resumption attempt.
+ DownloadItemUtils::AttachInfo(
+ download, GetBrowserContext(),
+ WebContentsImpl::FromRenderFrameHostID(info.render_process_id,
+ info.render_frame_id));
+ return download;
+}
+net::URLRequestContextGetter* DownloadManagerImpl::GetURLRequestContextGetter(
+ const download::DownloadCreateInfo& info) {
StoragePartition* storage_partition = GetStoragePartition(
- browser_context_, info->render_process_id, info->render_frame_id);
-
- download->Start(
- std::move(download_file), std::move(info->request_handle), *info,
- std::move(shared_url_loader_factory),
- storage_partition ? storage_partition->GetURLRequestContext() : nullptr);
-
- // For interrupted downloads, Start() will transition the state to
- // IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
- // For new downloads, we notify here, rather than earlier, so that
- // the download_file is bound to download and all the usual
- // setters (e.g. Cancel) work.
- if (new_download) {
- for (auto& observer : observers_)
- observer.OnDownloadCreated(this, download);
- }
+ browser_context_, info.render_process_id, info.render_frame_id);
+ return storage_partition ? storage_partition->GetURLRequestContext()
+ : nullptr;
+}
- if (!on_started.is_null())
- on_started.Run(download, download::DOWNLOAD_INTERRUPT_REASON_NONE);
+void DownloadManagerImpl::StartDownload(
+ std::unique_ptr<download::DownloadCreateInfo> info,
+ std::unique_ptr<download::InputStream> stream,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
+ const download::DownloadUrlParameters::OnStartedCallback& on_started) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(info);
+ in_progress_manager_->StartDownload(std::move(info), std::move(stream),
+ std::move(url_loader_factory_getter),
+ on_started);
}
void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
@@ -762,14 +555,13 @@ void DownloadManagerImpl::CreateSavePackageDownloadItem(
int render_process_id,
int render_frame_id,
std::unique_ptr<download::DownloadRequestHandleInterface> request_handle,
- const ukm::SourceId ukm_source_id,
const DownloadItemImplCreated& item_created) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- GetNextId(base::Bind(
- &DownloadManagerImpl::CreateSavePackageDownloadItemWithId,
- weak_factory_.GetWeakPtr(), main_file_path, page_url, mime_type,
- render_process_id, render_frame_id,
- base::Passed(std::move(request_handle)), ukm_source_id, item_created));
+ GetNextId(
+ base::Bind(&DownloadManagerImpl::CreateSavePackageDownloadItemWithId,
+ weak_factory_.GetWeakPtr(), main_file_path, page_url,
+ mime_type, render_process_id, render_frame_id,
+ base::Passed(std::move(request_handle)), item_created));
}
void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
@@ -779,7 +571,6 @@ void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
int render_process_id,
int render_frame_id,
std::unique_ptr<download::DownloadRequestHandleInterface> request_handle,
- const ukm::SourceId ukm_source_id,
const DownloadItemImplCreated& item_created,
uint32_t id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -797,23 +588,6 @@ void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
observer.OnDownloadCreated(this, download_item);
if (!item_created.is_null())
item_created.Run(download_item);
-
- // Add download_id and source_id for UKM.
- auto* delegate = GetDelegate();
- if (delegate) {
- download::InProgressCache* in_progress_cache =
- delegate_->GetInProgressCache();
- if (in_progress_cache) {
- base::Optional<download::DownloadEntry> entry_opt =
- in_progress_cache->RetrieveEntry(download_item->GetGuid());
- if (!entry_opt.has_value()) {
- in_progress_cache->AddOrReplaceEntry(CreateDownloadEntryFromItem(
- *download_item, std::string(), /* request_origin */
- download::DownloadSource::UNKNOWN, false, /* fetch_error_body */
- download::DownloadUrlParameters::RequestHeadersType()));
- }
- }
- }
}
// Resume a download of a specific URL. We send the request to the
@@ -823,11 +597,8 @@ void DownloadManagerImpl::ResumeInterruptedDownload(
std::unique_ptr<download::DownloadUrlParameters> params,
uint32_t id,
const GURL& site_url) {
- StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetStoragePartitionForSite(browser_context_, site_url));
- params->set_url_request_context_getter(
- storage_partition->GetURLRequestContext());
- BeginDownloadInternal(std::move(params), nullptr, id, storage_partition);
+ BeginDownloadInternal(std::move(params), nullptr /* blob_data_handle */,
+ nullptr /* blob_url_loader_factory */, id, site_url);
}
void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
@@ -837,12 +608,12 @@ void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
void DownloadManagerImpl::SetDownloadFileFactoryForTesting(
std::unique_ptr<download::DownloadFileFactory> file_factory) {
- file_factory_ = std::move(file_factory);
+ in_progress_manager_->set_file_factory(std::move(file_factory));
}
download::DownloadFileFactory*
DownloadManagerImpl::GetDownloadFileFactoryForTesting() {
- return file_factory_.get();
+ return in_progress_manager_->file_factory();
}
void DownloadManagerImpl::DownloadRemoved(
@@ -865,14 +636,7 @@ void DownloadManagerImpl::DownloadInterrupted(
base::Optional<download::DownloadEntry> DownloadManagerImpl::GetInProgressEntry(
download::DownloadItemImpl* download) {
- if (!download || !delegate_)
- return base::Optional<download::DownloadEntry>();
-
- download::InProgressCache* in_progress_cache =
- delegate_->GetInProgressCache();
- if (in_progress_cache)
- return in_progress_cache->RetrieveEntry(download->GetGuid());
- return base::Optional<download::DownloadEntry>();
+ return in_progress_manager_->GetInProgressEntry(download);
}
bool DownloadManagerImpl::IsOffTheRecord() const {
@@ -881,16 +645,7 @@ bool DownloadManagerImpl::IsOffTheRecord() const {
void DownloadManagerImpl::ReportBytesWasted(
download::DownloadItemImpl* download) {
- if (!delegate_)
- return;
- auto entry_opt = GetInProgressEntry(download);
- if (entry_opt.has_value()) {
- download::DownloadEntry entry = entry_opt.value();
- entry.bytes_wasted = download->GetBytesWasted();
- download::InProgressCache* in_progress_cache =
- delegate_->GetInProgressCache();
- in_progress_cache->AddOrReplaceEntry(entry);
- }
+ in_progress_manager_->ReportBytesWasted(download);
}
void DownloadManagerImpl::OnUrlDownloadHandlerCreated(
@@ -930,10 +685,6 @@ download::DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest(
const GURL& url = url_request->original_url();
- // Check if the renderer is permitted to request the requested URL.
- if (!CanRequestURLFromRenderer(params->render_process_host_id(), url))
- return download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST;
-
const net::URLRequestContext* request_context = url_request->context();
if (!request_context->job_factory()->IsHandledProtocol(url.scheme())) {
DVLOG(1) << "Download request for unsupported protocol: "
@@ -960,15 +711,13 @@ download::DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest(
void DownloadManagerImpl::InterceptNavigation(
std::unique_ptr<network::ResourceRequest> resource_request,
std::vector<GURL> url_chain,
- const base::Optional<std::string>& suggested_filename,
scoped_refptr<network::ResourceResponse> response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
net::CertStatus cert_status,
int frame_tree_node_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!delegate_) {
- for (auto& observer : observers_)
- observer.OnDownloadDropped(this);
+ DropDownload();
return;
}
@@ -982,7 +731,7 @@ void DownloadManagerImpl::InterceptNavigation(
on_download_checks_done = base::BindOnce(
&DownloadManagerImpl::InterceptNavigationOnChecksComplete,
weak_factory_.GetWeakPtr(), web_contents_getter,
- std::move(resource_request), std::move(url_chain), suggested_filename,
+ std::move(resource_request), std::move(url_chain),
std::move(response), cert_status,
std::move(url_loader_client_endpoints));
@@ -1015,12 +764,14 @@ int DownloadManagerImpl::RemoveDownloadsByURLAndTime(
void DownloadManagerImpl::DownloadUrl(
std::unique_ptr<download::DownloadUrlParameters> params) {
- DownloadUrl(std::move(params), nullptr);
+ DownloadUrl(std::move(params), nullptr /* blob_data_handle */,
+ nullptr /* blob_url_loader_factory */);
}
void DownloadManagerImpl::DownloadUrl(
std::unique_ptr<download::DownloadUrlParameters> params,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle) {
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
if (params->post_id() >= 0) {
// Check this here so that the traceback is more useful.
DCHECK(params->prefer_cache());
@@ -1030,11 +781,12 @@ void DownloadManagerImpl::DownloadUrl(
download::RecordDownloadCountWithSource(
download::DownloadCountTypes::DOWNLOAD_TRIGGERED_COUNT,
params->download_source());
- StoragePartitionImpl* storage_partition =
- GetStoragePartition(browser_context_, params->render_process_host_id(),
- params->render_frame_host_routing_id());
+ auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(),
+ params->render_frame_host_routing_id());
BeginDownloadInternal(std::move(params), std::move(blob_data_handle),
- download::DownloadItem::kInvalidId, storage_partition);
+ std::move(blob_url_loader_factory),
+ download::DownloadItem::kInvalidId,
+ rfh ? rfh->GetSiteInstance()->GetSiteURL() : GURL());
}
void DownloadManagerImpl::AddObserver(Observer* observer) {
@@ -1166,10 +918,11 @@ download::DownloadItem* DownloadManagerImpl::GetDownloadByGuid(
void DownloadManagerImpl::OnUrlDownloadStarted(
std::unique_ptr<download::DownloadCreateInfo> download_create_info,
std::unique_ptr<download::InputStream> stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const download::DownloadUrlParameters::OnStartedCallback& callback) {
StartDownload(std::move(download_create_info), std::move(stream),
- std::move(shared_url_loader_factory), callback);
+ std::move(url_loader_factory_getter), callback);
}
void DownloadManagerImpl::OnUrlDownloadStopped(
@@ -1215,31 +968,35 @@ void DownloadManagerImpl::ShowDownloadInShell(
delegate_->ShowDownloadInShell(download);
}
+void DownloadManagerImpl::DropDownload() {
+ download::RecordDownloadCount(download::DOWNLOAD_DROPPED_COUNT);
+ for (auto& observer : observers_)
+ observer.OnDownloadDropped(this);
+}
+
void DownloadManagerImpl::InterceptNavigationOnChecksComplete(
ResourceRequestInfo::WebContentsGetter web_contents_getter,
std::unique_ptr<network::ResourceRequest> resource_request,
std::vector<GURL> url_chain,
- const base::Optional<std::string>& suggested_filename,
scoped_refptr<network::ResourceResponse> response,
net::CertStatus cert_status,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
bool is_download_allowed) {
if (!is_download_allowed) {
- for (auto& observer : observers_)
- observer.OnDownloadDropped(this);
+ DropDownload();
return;
}
int render_process_id = -1;
int render_frame_id = -1;
GURL site_url, tab_url, tab_referrer_url;
+ RenderFrameHost* render_frame_host = nullptr;
WebContents* web_contents = std::move(web_contents_getter).Run();
if (web_contents) {
- RenderFrameHost* render_frame_host = web_contents->GetMainFrame();
+ render_frame_host = web_contents->GetMainFrame();
if (render_frame_host) {
render_process_id = render_frame_host->GetProcess()->GetID();
render_frame_id = render_frame_host->GetRoutingID();
- site_url = render_frame_host->GetSiteInstance()->GetSiteURL();
}
NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
if (entry) {
@@ -1249,92 +1006,115 @@ void DownloadManagerImpl::InterceptNavigationOnChecksComplete(
}
StoragePartitionImpl* storage_partition =
GetStoragePartition(browser_context_, render_process_id, render_frame_id);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DownloadManagerImpl::CreateDownloadHandlerForNavigation,
- weak_factory_.GetWeakPtr(), std::move(resource_request),
- render_process_id, render_frame_id, site_url, tab_url,
- tab_referrer_url, std::move(url_chain), suggested_filename,
- std::move(response), std::move(cert_status),
- std::move(url_loader_client_endpoints),
- storage_partition->url_loader_factory_getter(),
- base::MessageLoop::current()->task_runner()));
+ in_progress_manager_->InterceptDownloadFromNavigation(
+ std::move(resource_request), render_process_id, render_frame_id, site_url,
+ tab_url, tab_referrer_url, std::move(url_chain), std::move(response),
+ std::move(cert_status), std::move(url_loader_client_endpoints),
+ CreateDownloadURLLoaderFactoryGetter(storage_partition, render_frame_host,
+ false));
}
-// static
-void DownloadManagerImpl::CreateDownloadHandlerForNavigation(
- base::WeakPtr<DownloadManagerImpl> download_manager,
- std::unique_ptr<network::ResourceRequest> resource_request,
- int render_process_id,
- int render_frame_id,
+void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
+ std::unique_ptr<download::DownloadUrlParameters> params,
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ uint32_t id,
const GURL& site_url,
- const GURL& tab_url,
- const GURL& tab_referrer_url,
- std::vector<GURL> url_chain,
- const base::Optional<std::string>& suggested_filename,
- scoped_refptr<network::ResourceResponse> response,
- net::CertStatus cert_status,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ bool is_download_allowed) {
+ if (!is_download_allowed) {
+ DropDownload();
+ return;
+ }
- download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr resource_downloader(
- download::ResourceDownloader::InterceptNavigationResponse(
- download_manager, std::move(resource_request), render_process_id,
- render_frame_id, site_url, tab_url, tab_referrer_url,
- std::move(url_chain), suggested_filename, std::move(response),
- std::move(cert_status), std::move(url_loader_client_endpoints),
- url_loader_factory_getter->GetNetworkFactory(), task_runner)
- .release(),
- base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
+ GURL tab_url, tab_referrer_url;
+ auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(),
+ params->render_frame_host_routing_id());
+ if (rfh) {
+ auto* web_contents = WebContents::FromRenderFrameHost(rfh);
+ NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
+ if (entry) {
+ tab_url = entry->GetURL();
+ tab_referrer_url = entry->GetReferrer().url;
+ }
+ }
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&DownloadManagerImpl::OnUrlDownloadHandlerCreated,
- download_manager, std::move(resource_downloader)));
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter;
+ if (blob_url_loader_factory) {
+ DCHECK(params->url().SchemeIsBlob());
+ url_loader_factory_getter =
+ base::MakeRefCounted<DownloadURLLoaderFactoryGetterImpl>(
+ blob_url_loader_factory->Clone());
+ } else if (params->url().SchemeIsBlob()) {
+ url_loader_factory_getter =
+ base::MakeRefCounted<BlobDownloadURLLoaderFactoryGetter>(
+ params->url(), std::move(blob_data_handle));
+ } else {
+ StoragePartitionImpl* storage_partition =
+ static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetStoragePartitionForSite(browser_context_,
+ site_url));
+ url_loader_factory_getter =
+ CreateDownloadURLLoaderFactoryGetter(storage_partition, rfh, true);
+ }
+
+ in_progress_manager_->BeginDownload(std::move(params),
+ std::move(url_loader_factory_getter), id,
+ site_url, tab_url, tab_referrer_url);
}
void DownloadManagerImpl::BeginDownloadInternal(
std::unique_ptr<download::DownloadUrlParameters> params,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
uint32_t id,
- StoragePartitionImpl* storage_partition) {
+ const GURL& site_url) {
+ // Check if the renderer is permitted to request the requested URL.
+ if (params->render_process_host_id() >= 0 &&
+ !CanRequestURLFromRenderer(params->render_process_host_id(),
+ params->url())) {
+ CreateInterruptedDownload(
+ std::move(params),
+ download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST,
+ weak_factory_.GetWeakPtr());
+ return;
+ }
+
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- std::unique_ptr<network::ResourceRequest> request =
- download::CreateResourceRequest(params.get());
- GURL site_url, tab_url, tab_referrer_url;
auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(),
params->render_frame_host_routing_id());
- if (rfh) {
- site_url = rfh->GetSiteInstance()->GetSiteURL();
- auto* web_contents = WebContents::FromRenderFrameHost(rfh);
- NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
- if (entry) {
- tab_url = entry->GetURL();
- tab_referrer_url = entry->GetReferrer().url;
+ bool content_initiated = params->content_initiated();
+ // If it's from the web, we don't trust it, so we push the throttle on.
+ if (rfh && content_initiated) {
+ ResourceRequestInfo::WebContentsGetter web_contents_getter =
+ base::BindRepeating(WebContents::FromFrameTreeNodeId,
+ rfh->GetFrameTreeNodeId());
+ const GURL& url = params->url();
+ const std::string& method = params->method();
+
+ base::OnceCallback<void(bool /* download allowed */)>
+ on_can_download_checks_done = base::BindOnce(
+ &DownloadManagerImpl::BeginResourceDownloadOnChecksComplete,
+ weak_factory_.GetWeakPtr(), std::move(params),
+ std::move(blob_data_handle), std::move(blob_url_loader_factory),
+ id, site_url);
+ if (delegate_) {
+ delegate_->CheckDownloadAllowed(std::move(web_contents_getter), url,
+ method,
+ std::move(on_can_download_checks_done));
+ return;
}
}
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter;
- if (params->url().SchemeIs(url::kBlobScheme)) {
- url_loader_factory_getter =
- base::MakeRefCounted<BlobDownloadURLLoaderFactoryGetter>(
- params->url(), std::move(blob_data_handle));
- } else {
- url_loader_factory_getter =
- base::MakeRefCounted<NetworkDownloadURLLoaderFactoryGetter>(
- storage_partition->url_loader_factory_getter());
- }
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&BeginResourceDownload, std::move(params),
- std::move(request), std::move(url_loader_factory_getter),
- id, weak_factory_.GetWeakPtr(), site_url, tab_url,
- tab_referrer_url,
- base::MessageLoop::current()->task_runner()));
+ BeginResourceDownloadOnChecksComplete(
+ std::move(params), std::move(blob_data_handle),
+ std::move(blob_url_loader_factory), id, site_url,
+ rfh ? !content_initiated : true);
} else {
+ StoragePartition* storage_partition =
+ BrowserContext::GetStoragePartitionForSite(browser_context_, site_url);
+ params->set_url_request_context_getter(
+ storage_partition->GetURLRequestContext());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&BeginDownload, std::move(params),
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index 13ae60ba113..041492c4347 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -22,6 +22,7 @@
#include "base/synchronization/lock.h"
#include "components/download/public/common/download_item_impl_delegate.h"
#include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/in_progress_download_manager.h"
#include "components/download/public/common/url_download_handler.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/common/content_export.h"
@@ -41,12 +42,11 @@ class DownloadRequestHandleInterface;
namespace content {
class ResourceContext;
-class StoragePartitionImpl;
-class URLLoaderFactoryGetter;
class CONTENT_EXPORT DownloadManagerImpl
: public DownloadManager,
public download::UrlDownloadHandler::Delegate,
+ public download::InProgressDownloadManager::Delegate,
private download::DownloadItemImplDelegate {
public:
using DownloadItemImplCreated =
@@ -69,7 +69,6 @@ class CONTENT_EXPORT DownloadManagerImpl
int render_process_id,
int render_frame_id,
std::unique_ptr<download::DownloadRequestHandleInterface> request_handle,
- const ukm::SourceId ukm_source_id,
const DownloadItemImplCreated& item_created);
// DownloadManager functions.
@@ -77,12 +76,12 @@ class CONTENT_EXPORT DownloadManagerImpl
DownloadManagerDelegate* GetDelegate() const override;
void Shutdown() override;
void GetAllDownloads(DownloadVector* result) override;
- void StartDownload(
- std::unique_ptr<download::DownloadCreateInfo> info,
- std::unique_ptr<download::InputStream> stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
- const download::DownloadUrlParameters::OnStartedCallback& on_started)
- override;
+ void StartDownload(std::unique_ptr<download::DownloadCreateInfo> info,
+ std::unique_ptr<download::InputStream> stream,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
+ const download::DownloadUrlParameters::OnStartedCallback&
+ on_started) override;
int RemoveDownloadsByURLAndTime(
const base::Callback<bool(const GURL&)>& url_filter,
@@ -90,9 +89,10 @@ class CONTENT_EXPORT DownloadManagerImpl
base::Time remove_end) override;
void DownloadUrl(
std::unique_ptr<download::DownloadUrlParameters> parameters) override;
- void DownloadUrl(
- std::unique_ptr<download::DownloadUrlParameters> params,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle) override;
+ void DownloadUrl(std::unique_ptr<download::DownloadUrlParameters> params,
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ scoped_refptr<network::SharedURLLoaderFactory>
+ blob_url_loader_factory) override;
void AddObserver(Observer* observer) override;
void RemoveObserver(Observer* observer) override;
download::DownloadItem* CreateDownloadItem(
@@ -135,7 +135,8 @@ class CONTENT_EXPORT DownloadManagerImpl
void OnUrlDownloadStarted(
std::unique_ptr<download::DownloadCreateInfo> download_create_info,
std::unique_ptr<download::InputStream> stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const download::DownloadUrlParameters::OnStartedCallback& callback)
override;
void OnUrlDownloadStopped(download::UrlDownloadHandler* downloader) override;
@@ -165,7 +166,6 @@ class CONTENT_EXPORT DownloadManagerImpl
void InterceptNavigation(
std::unique_ptr<network::ResourceRequest> resource_request,
std::vector<GURL> url_chain,
- const base::Optional<std::string>& suggested_filename,
scoped_refptr<network::ResourceResponse> response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
net::CertStatus cert_status,
@@ -181,14 +181,6 @@ class CONTENT_EXPORT DownloadManagerImpl
friend class DownloadManagerTest;
friend class DownloadTest;
- void StartDownloadWithId(
- std::unique_ptr<download::DownloadCreateInfo> info,
- std::unique_ptr<download::InputStream> stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
- const download::DownloadUrlParameters::OnStartedCallback& on_started,
- bool new_download,
- uint32_t id);
-
void CreateSavePackageDownloadItemWithId(
const base::FilePath& main_file_path,
const GURL& page_url,
@@ -196,13 +188,20 @@ class CONTENT_EXPORT DownloadManagerImpl
int render_process_id,
int render_frame_id,
std::unique_ptr<download::DownloadRequestHandleInterface> request_handle,
- const ukm::SourceId ukm_source_id,
const DownloadItemImplCreated& on_started,
uint32_t id);
- // Intercepts the download to another system if applicable. Returns true if
- // the download was intercepted.
- bool InterceptDownload(const download::DownloadCreateInfo& info);
+ // InProgressDownloadManager::Delegate implementations.
+ bool InterceptDownload(const download::DownloadCreateInfo& info) override;
+ base::FilePath GetDefaultDownloadDirectory() override;
+ download::DownloadItemImpl* GetDownloadItem(
+ uint32_t id,
+ bool new_download,
+ const download::DownloadCreateInfo& info) override;
+ net::URLRequestContextGetter* GetURLRequestContextGetter(
+ const download::DownloadCreateInfo& info) override;
+ void OnNewDownloadStarted(download::DownloadItem* download) override;
+ void GetNextId(const DownloadIdCallback& callback) override;
// Create a new active item based on the info. Separate from
// StartDownload() for testing.
@@ -210,9 +209,6 @@ class CONTENT_EXPORT DownloadManagerImpl
uint32_t id,
const download::DownloadCreateInfo& info);
- // Get next download id. |callback| is called on the UI thread and may
- // be called synchronously.
- void GetNextId(const DownloadIdCallback& callback);
// Called with the result of DownloadManagerDelegate::CheckForFileExistence.
// Updates the state of the file and then notifies this update to the file's
@@ -220,7 +216,6 @@ class CONTENT_EXPORT DownloadManagerImpl
void OnFileExistenceChecked(uint32_t download_id, bool result);
// Overridden from DownloadItemImplDelegate
- // (Note that |GetBrowserContext| are present in both interfaces.)
void DetermineDownloadTarget(download::DownloadItemImpl* item,
const DownloadTargetCallback& callback) override;
bool ShouldCompleteDownload(download::DownloadItemImpl* item,
@@ -245,48 +240,36 @@ class CONTENT_EXPORT DownloadManagerImpl
bool IsOffTheRecord() const override;
void ReportBytesWasted(download::DownloadItemImpl* download) override;
+ // Drops a download before it is created.
+ void DropDownload();
+
// Helper method to start or resume a download.
void BeginDownloadInternal(
std::unique_ptr<download::DownloadUrlParameters> params,
std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
uint32_t id,
- StoragePartitionImpl* storage_partition);
+ const GURL& site_url);
void InterceptNavigationOnChecksComplete(
ResourceRequestInfo::WebContentsGetter web_contents_getter,
std::unique_ptr<network::ResourceRequest> resource_request,
std::vector<GURL> url_chain,
- const base::Optional<std::string>& suggested_filename,
scoped_refptr<network::ResourceResponse> response,
net::CertStatus cert_status,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
bool is_download_allowed);
-
- // Called when a navigation turns to be a download. Create a new
- // DownloadHandler. It will be used to continue the loading instead of the
- // regular document loader. Must be called on the IO thread.
- static void CreateDownloadHandlerForNavigation(
- base::WeakPtr<DownloadManagerImpl> download_manager,
- std::unique_ptr<network::ResourceRequest> resource_request,
- int render_process_id,
- int render_frame_id,
+ void BeginResourceDownloadOnChecksComplete(
+ std::unique_ptr<download::DownloadUrlParameters> params,
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
+ uint32_t id,
const GURL& site_url,
- const GURL& tab_url,
- const GURL& tab_referrer_url,
- std::vector<GURL> url_chain,
- const base::Optional<std::string>& suggested_filename,
- scoped_refptr<network::ResourceResponse> response,
- net::CertStatus cert_status,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+ bool is_download_allowed);
// Factory for creation of downloads items.
std::unique_ptr<download::DownloadItemFactory> item_factory_;
- // Factory for the creation of download files.
- std::unique_ptr<download::DownloadFileFactory> file_factory_;
-
// |downloads_| is the owning set for all downloads known to the
// DownloadManager. This includes downloads started by the user in
// this session, downloads initialized from the history system, and
@@ -325,9 +308,12 @@ class CONTENT_EXPORT DownloadManagerImpl
// Allows an embedder to control behavior. Guaranteed to outlive this object.
DownloadManagerDelegate* delegate_;
+ // TODO(qinmin): remove this once network service is enabled by default.
std::vector<download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr>
url_download_handlers_;
+ std::unique_ptr<download::InProgressDownloadManager> in_progress_manager_;
+
base::WeakPtrFactory<DownloadManagerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DownloadManagerImpl);
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index ccbc17a8954..9ccc49d3df7 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -72,7 +72,7 @@ namespace {
class MockDownloadManagerDelegate : public DownloadManagerDelegate {
public:
MockDownloadManagerDelegate();
- virtual ~MockDownloadManagerDelegate();
+ ~MockDownloadManagerDelegate() override;
MOCK_METHOD0(Shutdown, void());
MOCK_METHOD1(GetNextId, void(const DownloadIdCallback&));
@@ -119,10 +119,6 @@ class MockDownloadItemFactory
// we don't keep dangling pointers.
void RemoveItem(int id);
- // Sets |has_observer_calls_| to reflect whether we expect to add/remove
- // observers during the CreateActiveItem.
- void SetHasObserverCalls(bool observer_calls);
-
// Overridden methods from DownloadItemFactory.
download::DownloadItemImpl* CreatePersistedItem(
download::DownloadItemImplDelegate* delegate,
@@ -165,16 +161,20 @@ class MockDownloadItemFactory
std::unique_ptr<download::DownloadRequestHandleInterface> request_handle)
override;
+ void set_is_download_started(bool is_download_started) {
+ is_download_started_ = is_download_started;
+ }
+
private:
std::map<uint32_t, download::MockDownloadItemImpl*> items_;
download::DownloadItemImplDelegate item_delegate_;
- bool has_observer_calls_;
+ bool is_download_started_;
DISALLOW_COPY_AND_ASSIGN(MockDownloadItemFactory);
};
MockDownloadItemFactory::MockDownloadItemFactory()
- : has_observer_calls_(false) {}
+ : is_download_started_(false) {}
MockDownloadItemFactory::~MockDownloadItemFactory() {}
@@ -200,10 +200,6 @@ void MockDownloadItemFactory::RemoveItem(int id) {
items_.erase(id);
}
-void MockDownloadItemFactory::SetHasObserverCalls(bool has_observer_calls) {
- has_observer_calls_ = has_observer_calls;
-}
-
download::DownloadItemImpl* MockDownloadItemFactory::CreatePersistedItem(
download::DownloadItemImplDelegate* delegate,
const std::string& guid,
@@ -253,18 +249,16 @@ download::DownloadItemImpl* MockDownloadItemFactory::CreateActiveItem(
.WillRepeatedly(Return(download_id));
EXPECT_CALL(*result, GetGuid())
.WillRepeatedly(ReturnRefOfCopy(base::GenerateGUID()));
+ if (is_download_started_) {
+ EXPECT_CALL(*result, RemoveObserver(_));
+ EXPECT_CALL(*result, AddObserver(_));
+ }
items_[download_id] = result;
// Active items are created and then immediately are called to start
// the download.
EXPECT_CALL(*result, MockStart(_, _));
- // In the StartDownload case, expect the remove/add observer calls.
- if (has_observer_calls_) {
- EXPECT_CALL(*result, RemoveObserver(_));
- EXPECT_CALL(*result, AddObserver(_));
- }
-
return result;
}
@@ -291,7 +285,7 @@ class MockDownloadFileFactory
public base::SupportsWeakPtr<MockDownloadFileFactory> {
public:
MockDownloadFileFactory() {}
- virtual ~MockDownloadFileFactory() {}
+ ~MockDownloadFileFactory() override {}
// Overridden method from DownloadFileFactory
MOCK_METHOD2(MockCreateFile,
@@ -311,7 +305,7 @@ class MockDownloadFileFactory
class MockDownloadManagerObserver : public DownloadManager::Observer {
public:
MockDownloadManagerObserver() {}
- ~MockDownloadManagerObserver() {}
+ ~MockDownloadManagerObserver() override {}
MOCK_METHOD2(OnDownloadCreated,
void(DownloadManager*, download::DownloadItem*));
MOCK_METHOD1(ManagerGoingDown, void(DownloadManager*));
@@ -320,7 +314,7 @@ class MockDownloadManagerObserver : public DownloadManager::Observer {
class MockByteStreamReader : public ByteStreamReader {
public:
- virtual ~MockByteStreamReader() {}
+ ~MockByteStreamReader() override {}
MOCK_METHOD2(Read, StreamState(scoped_refptr<net::IOBuffer>*, size_t*));
MOCK_CONST_METHOD0(GetStatus, int());
MOCK_METHOD1(RegisterCallback, void(const base::Closure&));
@@ -456,14 +450,11 @@ class DownloadManagerTest : public testing::Test {
base::Unretained(this)));
}
- void SetHasObserverCalls(bool has_observer_calls) {
- mock_download_item_factory_->SetHasObserverCalls(has_observer_calls);
- }
-
protected:
// Key test variable; we'll keep it available to sub-classes.
std::unique_ptr<DownloadManagerImpl> download_manager_;
base::WeakPtr<MockDownloadFileFactory> mock_download_file_factory_;
+ base::WeakPtr<MockDownloadItemFactory> mock_download_item_factory_;
// Target detetermined callback.
bool callback_called_;
@@ -477,7 +468,6 @@ class DownloadManagerTest : public testing::Test {
private:
TestBrowserThreadBundle thread_bundle_;
- base::WeakPtr<MockDownloadItemFactory> mock_download_item_factory_;
std::unique_ptr<MockDownloadManagerDelegate> mock_download_manager_delegate_;
std::unique_ptr<MockDownloadManagerObserver> observer_;
std::unique_ptr<TestBrowserContext> browser_context_;
@@ -488,8 +478,6 @@ class DownloadManagerTest : public testing::Test {
// Confirm the appropriate invocations occur when you start a download.
TEST_F(DownloadManagerTest, StartDownload) {
- SetHasObserverCalls(true);
-
std::unique_ptr<download::DownloadCreateInfo> info(
new download::DownloadCreateInfo);
std::unique_ptr<ByteStreamReader> stream(new MockByteStreamReader);
@@ -517,12 +505,11 @@ TEST_F(DownloadManagerTest, StartDownload) {
MockCreateFile(Ref(*info->save_info.get()), input_stream.get()))
.WillOnce(Return(mock_file));
+ mock_download_item_factory_->set_is_download_started(true);
download_manager_->StartDownload(
std::move(info), std::move(input_stream), nullptr,
download::DownloadUrlParameters::OnStartedCallback());
EXPECT_TRUE(download_manager_->GetDownload(local_id));
-
- SetHasObserverCalls(false);
}
// Confirm that calling DetermineDownloadTarget behaves properly if the delegate
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index b7eb780ae47..3b2045e18ee 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -203,12 +203,6 @@ DownloadRequestCore::DownloadRequestCore(
is_partial_request_ = save_info_->offset > 0;
} else {
save_info_.reset(new download::DownloadSaveInfo);
- ResourceRequestInfoImpl* request_info =
- ResourceRequestInfoImpl::ForRequest(request_);
- if (request_info && request_info->suggested_filename().has_value()) {
- save_info_->suggested_name =
- base::UTF8ToUTF16(*request_info->suggested_filename());
- }
}
}
@@ -216,7 +210,7 @@ DownloadRequestCore::~DownloadRequestCore() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Remove output stream callback if a stream exists.
if (stream_writer_)
- stream_writer_->RegisterCallback(base::Closure());
+ stream_writer_->RegisterCallback(base::RepeatingClosure());
}
std::unique_ptr<download::DownloadCreateInfo>
@@ -286,7 +280,7 @@ bool DownloadRequestCore::OnResponseStarted(
download::GetDownloadTaskRunner(), kDownloadByteStreamSize,
&stream_writer_, &stream_reader);
stream_writer_->RegisterCallback(
- base::Bind(&DownloadRequestCore::ResumeRequest, AsWeakPtr()));
+ base::BindRepeating(&DownloadRequestCore::ResumeRequest, AsWeakPtr()));
if (!override_mime_type.empty())
create_info->mime_type = override_mime_type;
diff --git a/chromium/content/browser/download/download_url_loader_factory_getter_impl.cc b/chromium/content/browser/download/download_url_loader_factory_getter_impl.cc
new file mode 100644
index 00000000000..e26386c8bb6
--- /dev/null
+++ b/chromium/content/browser/download/download_url_loader_factory_getter_impl.cc
@@ -0,0 +1,25 @@
+// 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/download/download_url_loader_factory_getter_impl.h"
+
+namespace content {
+
+DownloadURLLoaderFactoryGetterImpl::DownloadURLLoaderFactoryGetterImpl(
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory)
+ : url_loader_factory_info_(std::move(url_loader_factory)) {}
+
+DownloadURLLoaderFactoryGetterImpl::~DownloadURLLoaderFactoryGetterImpl() =
+ default;
+
+scoped_refptr<network::SharedURLLoaderFactory>
+DownloadURLLoaderFactoryGetterImpl::GetURLLoaderFactory() {
+ if (!url_loader_factory_) {
+ url_loader_factory_ = network::SharedURLLoaderFactory::Create(
+ std::move(url_loader_factory_info_));
+ }
+ return url_loader_factory_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/download/download_url_loader_factory_getter_impl.h b/chromium/content/browser/download/download_url_loader_factory_getter_impl.h
new file mode 100644
index 00000000000..d002dbb1e14
--- /dev/null
+++ b/chromium/content/browser/download/download_url_loader_factory_getter_impl.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 CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
+#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
+
+#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace content {
+
+// Class for retrieving a fixed SharedURLLoaderFactory.
+class DownloadURLLoaderFactoryGetterImpl
+ : public download::DownloadURLLoaderFactoryGetter {
+ public:
+ explicit DownloadURLLoaderFactoryGetterImpl(
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory);
+
+ // download::DownloadURLLoaderFactoryGetter implementation.
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
+
+ protected:
+ ~DownloadURLLoaderFactoryGetterImpl() override;
+
+ private:
+ // Only one of the following two members is ever set. Initially that would be
+ // |url_loader_factory_info_|, but after GetURLLoaderFactory is called for the
+ // first time instead |url_loader_factory_| will be set. This is safe because
+ // GetURLLoaderFactory is always called from the same thread.
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info_;
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadURLLoaderFactoryGetterImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
diff --git a/chromium/content/browser/download/download_utils.cc b/chromium/content/browser/download/download_utils.cc
index c9e72c38329..ab0e360a306 100644
--- a/chromium/content/browser/download/download_utils.cc
+++ b/chromium/content/browser/download/download_utils.cc
@@ -6,6 +6,7 @@
#include "base/format_macros.h"
#include "base/process/process_handle.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/task_scheduler/post_task.h"
#include "components/download/downloader/in_progress/download_entry.h"
diff --git a/chromium/content/browser/download/drag_download_file_browsertest.cc b/chromium/content/browser/download/drag_download_file_browsertest.cc
index f080504c23c..c267b435449 100644
--- a/chromium/content/browser/download/drag_download_file_browsertest.cc
+++ b/chromium/content/browser/download/drag_download_file_browsertest.cc
@@ -6,8 +6,8 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
+#include "base/run_loop.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/drag_download_file.h"
#include "content/browser/download/drag_download_util.h"
@@ -41,7 +41,7 @@ class MockDownloadFileObserver : public ui::DownloadFileObserver {
MOCK_METHOD0(OnDownloadAborted, void());
private:
- virtual ~MockDownloadFileObserver() {}
+ ~MockDownloadFileObserver() override {}
DISALLOW_COPY_AND_ASSIGN(MockDownloadFileObserver);
};
@@ -54,7 +54,7 @@ class DragDownloadFileTest : public ContentBrowserTest {
void Succeed() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::MessageLoopForUI::current()->QuitWhenIdleClosure());
+ base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
}
void FailFast() {
@@ -70,7 +70,7 @@ class DragDownloadFileTest : public ContentBrowserTest {
->GetDownloadManagerDelegate());
delegate->SetDownloadBehaviorForTesting(downloads_directory());
base::FilePath test_data_dir;
- ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &test_data_dir));
+ ASSERT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &test_data_dir));
embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
ASSERT_TRUE(embedded_test_server()->Start());
}
diff --git a/chromium/content/browser/download/mhtml_generation_manager.cc b/chromium/content/browser/download/mhtml_generation_manager.cc
index de16bb4ffc9..7d67b75473e 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.cc
+++ b/chromium/content/browser/download/mhtml_generation_manager.cc
@@ -94,8 +94,7 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
// RenderProcessHostObserver:
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override;
+ const ChildProcessTerminationInfo& info) override;
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
void MarkAsFinished();
@@ -262,8 +261,7 @@ MhtmlSaveStatus MHTMLGenerationManager::Job::SendToNextRenderFrame() {
void MHTMLGenerationManager::Job::RenderProcessExited(
RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {
+ const ChildProcessTerminationInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
MHTMLGenerationManager::GetInstance()->RenderProcessExited(this);
}
diff --git a/chromium/content/browser/download/network_download_url_loader_factory_getter.cc b/chromium/content/browser/download/network_download_url_loader_factory_getter.cc
index df96621f93b..fe132fb4489 100644
--- a/chromium/content/browser/download/network_download_url_loader_factory_getter.cc
+++ b/chromium/content/browser/download/network_download_url_loader_factory_getter.cc
@@ -7,12 +7,17 @@
#include "components/download/public/common/download_task_runner.h"
#include "content/browser/url_loader_factory_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
namespace content {
NetworkDownloadURLLoaderFactoryGetter::NetworkDownloadURLLoaderFactoryGetter(
- scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter)
- : url_loader_factory_getter_(url_loader_factory_getter) {}
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+ network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info,
+ network::mojom::URLLoaderFactoryRequest proxy_factory_request)
+ : url_loader_factory_getter_(url_loader_factory_getter),
+ proxy_factory_ptr_info_(std::move(proxy_factory_ptr_info)),
+ proxy_factory_request_(std::move(proxy_factory_request)) {}
NetworkDownloadURLLoaderFactoryGetter::
~NetworkDownloadURLLoaderFactoryGetter() = default;
@@ -21,7 +26,18 @@ scoped_refptr<network::SharedURLLoaderFactory>
NetworkDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() {
DCHECK(download::GetIOTaskRunner());
DCHECK(download::GetIOTaskRunner()->BelongsToCurrentThread());
- return url_loader_factory_getter_->GetNetworkFactory();
+ if (lazy_factory_)
+ return lazy_factory_;
+ if (proxy_factory_request_.is_pending()) {
+ url_loader_factory_getter_->CloneNetworkFactory(
+ std::move(proxy_factory_request_));
+ lazy_factory_ =
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(proxy_factory_ptr_info_));
+ } else {
+ lazy_factory_ = url_loader_factory_getter_->GetNetworkFactory();
+ }
+ return lazy_factory_;
}
} // namespace content
diff --git a/chromium/content/browser/download/network_download_url_loader_factory_getter.h b/chromium/content/browser/download/network_download_url_loader_factory_getter.h
index cf6eaa10182..95eb89382e4 100644
--- a/chromium/content/browser/download/network_download_url_loader_factory_getter.h
+++ b/chromium/content/browser/download/network_download_url_loader_factory_getter.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_DOWNLOAD_NETWORK_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace content {
@@ -15,8 +16,10 @@ class URLLoaderFactoryGetter;
class NetworkDownloadURLLoaderFactoryGetter
: public download::DownloadURLLoaderFactoryGetter {
public:
- explicit NetworkDownloadURLLoaderFactoryGetter(
- scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter);
+ NetworkDownloadURLLoaderFactoryGetter(
+ scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+ network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info,
+ network::mojom::URLLoaderFactoryRequest proxy_factory_request);
// download::DownloadURLLoaderFactoryGetter implementation.
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
@@ -26,6 +29,9 @@ class NetworkDownloadURLLoaderFactoryGetter
private:
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> lazy_factory_;
+ network::mojom::URLLoaderFactoryPtrInfo proxy_factory_ptr_info_;
+ network::mojom::URLLoaderFactoryRequest proxy_factory_request_;
DISALLOW_COPY_AND_ASSIGN(NetworkDownloadURLLoaderFactoryGetter);
};
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index ce081e96056..7035f3e49d4 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -14,7 +14,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -29,6 +29,7 @@
#include "components/download/public/common/download_stats.h"
#include "components/download/public/common/download_task_runner.h"
#include "components/download/public/common/download_ukm_helper.h"
+#include "components/download/public/common/download_utils.h"
#include "components/filename_generation/filename_generation.h"
#include "components/url_formatter/url_formatter.h"
#include "content/browser/bad_message.h"
@@ -85,7 +86,7 @@ const int32_t kMaxFileOrdinalNumber = 9999;
// is less than MAX_PATH
#if defined(OS_WIN)
const uint32_t kMaxFilePathLength = MAX_PATH - 1;
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
const uint32_t kMaxFilePathLength = PATH_MAX - 1;
#endif
@@ -255,6 +256,12 @@ void SavePackage::InternalInit() {
DCHECK(download_manager_);
download::RecordSavePackageEvent(download::SAVE_PACKAGE_STARTED);
+
+ ukm_source_id_ = ukm::UkmRecorder::GetNewSourceID();
+ ukm_download_id_ = download::GetUniqueDownloadId();
+ download::DownloadUkmHelper::RecordDownloadStarted(
+ ukm_download_id_, ukm_source_id_, download::DownloadContent::TEXT,
+ download::DownloadSource::UNKNOWN);
}
bool SavePackage::Init(
@@ -277,11 +284,8 @@ bool SavePackage::Init(
std::unique_ptr<download::DownloadRequestHandleInterface> request_handle(
new SavePackageRequestHandle(AsWeakPtr()));
- // The download manager keeps ownership but adds us as an observer.
- ukm::SourceId ukm_source_id = ukm::UkmRecorder::GetNewSourceID();
-
download::DownloadUkmHelper::UpdateSourceURL(
- ukm::UkmRecorder::Get(), ukm_source_id,
+ ukm::UkmRecorder::Get(), ukm_source_id_,
web_contents()->GetLastCommittedURL());
RenderFrameHost* frame_host = web_contents()->GetMainFrame();
download_manager_->CreateSavePackageDownloadItem(
@@ -289,7 +293,7 @@ bool SavePackage::Init(
((save_type_ == SAVE_PAGE_TYPE_AS_MHTML) ? "multipart/related"
: "text/html"),
frame_host->GetProcess()->GetID(), frame_host->GetRoutingID(),
- std::move(request_handle), std::move(ukm_source_id),
+ std::move(request_handle),
base::Bind(&SavePackage::InitWithDownloadItem, AsWeakPtr(),
download_created_callback));
return true;
@@ -356,12 +360,12 @@ void SavePackage::OnMHTMLGenerated(int64_t size) {
// '/path/to/save_dir' + '/' + NAME_MAX.
uint32_t SavePackage::GetMaxPathLengthForDirectory(
const base::FilePath& base_dir) {
-#if defined(OS_POSIX)
+#if defined(OS_WIN)
+ return kMaxFilePathLength;
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
return std::min(
kMaxFilePathLength,
static_cast<uint32_t>(base_dir.value().length()) + NAME_MAX + 1);
-#else
- return kMaxFilePathLength;
#endif
}
@@ -693,6 +697,10 @@ void SavePackage::Finish() {
// Record finish.
download::RecordSavePackageEvent(download::SAVE_PACKAGE_FINISHED);
+ // TODO(qinmin): report the actual file size and duration for the download.
+ download::DownloadUkmHelper::RecordDownloadCompleted(ukm_download_id_, 1,
+ base::TimeDelta(), 0);
+
// Record any errors that occurred.
if (wrote_to_completed_file_)
download::RecordSavePackageEvent(download::SAVE_PACKAGE_WRITE_TO_COMPLETED);
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index d4ad79aec82..c3385f8f3da 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -30,6 +30,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/referrer.h"
#include "net/base/net_errors.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
#include "url/gurl.h"
class GURL;
@@ -418,6 +419,10 @@ class CONTENT_EXPORT SavePackage
// Unique ID for this SavePackage.
const SavePackageId unique_id_;
+ // UKM IDs for reporting.
+ ukm::SourceId ukm_source_id_;
+ uint64_t ukm_download_id_;
+
DISALLOW_COPY_AND_ASSIGN(SavePackage);
};
diff --git a/chromium/content/browser/download/save_package_unittest.cc b/chromium/content/browser/download/save_package_unittest.cc
index 6aa71fcf441..4494255a467 100644
--- a/chromium/content/browser/download/save_package_unittest.cc
+++ b/chromium/content/browser/download/save_package_unittest.cc
@@ -30,7 +30,7 @@ namespace content {
#define HTML_EXTENSION ".html"
#if defined(OS_WIN)
#define FPL_HTML_EXTENSION L".html"
-#else
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
#define FPL_HTML_EXTENSION ".html"
#endif
@@ -40,7 +40,7 @@ namespace {
#if defined(OS_WIN)
const uint32_t kMaxFilePathLength = MAX_PATH - 1;
const uint32_t kMaxFileNameLength = MAX_PATH - 1;
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
const uint32_t kMaxFilePathLength = PATH_MAX - 1;
const uint32_t kMaxFileNameLength = NAME_MAX;
#endif
diff --git a/chromium/content/browser/download/url_downloader_factory.cc b/chromium/content/browser/download/url_downloader_factory.cc
index 342a24ab99d..752cea70a5d 100644
--- a/chromium/content/browser/download/url_downloader_factory.cc
+++ b/chromium/content/browser/download/url_downloader_factory.cc
@@ -5,6 +5,7 @@
#include "content/browser/download/url_downloader_factory.h"
#include "components/download/public/common/download_item.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "content/browser/download/download_request_core.h"
#include "content/browser/download/url_downloader.h"
@@ -18,7 +19,8 @@ download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
UrlDownloaderFactory::CreateUrlDownloadHandler(
std::unique_ptr<download::DownloadUrlParameters> params,
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
std::unique_ptr<net::URLRequest> url_request =
DownloadRequestCore::CreateRequestOnIOThread(
diff --git a/chromium/content/browser/download/url_downloader_factory.h b/chromium/content/browser/download/url_downloader_factory.h
index cd187b55971..ae908ecaeca 100644
--- a/chromium/content/browser/download/url_downloader_factory.h
+++ b/chromium/content/browser/download/url_downloader_factory.h
@@ -7,6 +7,10 @@
#include "components/download/public/common/url_download_handler_factory.h"
+namespace download {
+class DownloadURLLoaderFactoryGetter;
+};
+
namespace content {
// Class for creating UrlDownloader object.
@@ -21,7 +25,8 @@ class UrlDownloaderFactory : public download::UrlDownloadHandlerFactory {
CreateUrlDownloadHandler(
std::unique_ptr<download::DownloadUrlParameters> params,
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ shared_url_loader_factory,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override;
};
diff --git a/chromium/content/browser/file_url_loader_factory.cc b/chromium/content/browser/file_url_loader_factory.cc
index 8bf1bcedd08..f260e71a625 100644
--- a/chromium/content/browser/file_url_loader_factory.cc
+++ b/chromium/content/browser/file_url_loader_factory.cc
@@ -107,7 +107,8 @@ class FileURLDirectoryLoader
}
// network::mojom::URLLoader:
- void FollowRedirect() override {}
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {}
void ProceedWithResponse() override { NOTREACHED(); }
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override {}
@@ -188,7 +189,7 @@ class FileURLDirectoryLoader
#if defined(OS_WIN)
const base::string16& title = path_.value();
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
const base::string16& title =
base::WideToUTF16(base::SysNativeMBToWide(path_.value()));
#endif
@@ -210,7 +211,7 @@ class FileURLDirectoryLoader
filename.value() != base::FilePath::kParentDirectory) {
#if defined(OS_WIN)
std::string raw_bytes; // Empty on Windows means UTF-8 encoded name.
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
const std::string& raw_bytes = filename.value();
#endif
pending_data_.append(net::GetDirectoryListingEntry(
@@ -315,7 +316,8 @@ class FileURLLoader : public network::mojom::URLLoader {
}
// network::mojom::URLLoader:
- void FollowRedirect() override {}
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {}
void ProceedWithResponse() override {}
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override {}
@@ -454,12 +456,12 @@ class FileURLLoader : public network::mojom::URLLoader {
observer->OnStart();
base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
- net::Error net_error = net::FileErrorToNetError(file.error_details());
- if (observer)
- observer->OnOpenComplete(net_error);
if (!file.IsValid()) {
- if (observer)
+ if (observer) {
+ observer->OnBytesRead(nullptr, 0u, file.error_details());
observer->OnDoneReading();
+ }
+ net::Error net_error = net::FileErrorToNetError(file.error_details());
client->OnComplete(network::URLLoaderCompletionStatus(net_error));
MaybeDeleteSelf();
return;
@@ -471,10 +473,13 @@ class FileURLLoader : public network::mojom::URLLoader {
base::File::Error read_error = base::File::GetLastFileError();
DCHECK_NE(base::File::FILE_OK, read_error);
if (observer) {
+ // This can happen when the file is unreadable (which can happen during
+ // corruption). We need to be sure to inform
+ // the observer that we've finished reading so that it can proceed.
observer->OnBytesRead(nullptr, 0u, read_error);
observer->OnDoneReading();
}
- net_error = net::FileErrorToNetError(read_error);
+ net::Error net_error = net::FileErrorToNetError(read_error);
client->OnComplete(network::URLLoaderCompletionStatus(net_error));
return;
} else if (observer) {
diff --git a/chromium/content/browser/fileapi/OWNERS b/chromium/content/browser/fileapi/OWNERS
index c72d620620e..b295e075046 100644
--- a/chromium/content/browser/fileapi/OWNERS
+++ b/chromium/content/browser/fileapi/OWNERS
@@ -1,5 +1,5 @@
jsbell@chromium.org
-michaeln@chromium.org
+mek@chromium.org
pwnall@chromium.org
jianli@chromium.org
tzik@chromium.org
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index 4d8ecc2bab9..aef88c1d686 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -5,6 +5,7 @@
#include "content/browser/fileapi/browser_file_system_helper.h"
#include <stddef.h>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -62,11 +63,8 @@ FileSystemOptions CreateBrowserFileSystemOptions(bool is_incognito) {
switches::kAllowFileAccessFromFiles)) {
additional_allowed_schemes.push_back(url::kFileScheme);
}
- leveldb::Env* env_override = nullptr;
- if (is_incognito)
- env_override = leveldb_chrome::NewMemEnv(leveldb::Env::Default());
- return FileSystemOptions(profile_mode, additional_allowed_schemes,
- env_override);
+ return FileSystemOptions(profile_mode, is_incognito,
+ additional_allowed_schemes);
}
} // namespace
@@ -98,13 +96,11 @@ scoped_refptr<storage::FileSystemContext> CreateFileSystemContext(
std::move(additional_backends), url_request_auto_mount_handlers,
profile_path, CreateBrowserFileSystemOptions(is_incognito));
- std::vector<storage::FileSystemType> types;
- file_system_context->GetFileSystemTypes(&types);
- for (size_t i = 0; i < types.size(); ++i) {
+ for (const storage::FileSystemType& type :
+ file_system_context->GetFileSystemTypes()) {
ChildProcessSecurityPolicyImpl::GetInstance()
->RegisterFileSystemPermissionPolicy(
- types[i],
- storage::FileSystemContext::GetPermissionPolicy(types[i]));
+ type, storage::FileSystemContext::GetPermissionPolicy(type));
}
return file_system_context;
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc b/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc
index c1c84c39825..1b0cff4dbf9 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper_unittest.cc
@@ -62,7 +62,7 @@ TEST(BrowserFileSystemHelperTest,
new base::NullTaskRunner);
storage::FileSystemOptions file_system_options(
storage::FileSystemOptions::PROFILE_MODE_NORMAL,
- std::vector<std::string>(), nullptr);
+ false /* force_in_memory */, std::vector<std::string>());
scoped_refptr<storage::FileSystemContext> test_file_system_context(
new storage::FileSystemContext(
io_task_runner.get(), file_task_runner.get(),
diff --git a/chromium/content/browser/fileapi/file_system_url_loader_factory.cc b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
new file mode 100644
index 00000000000..0b426204681
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory.cc
@@ -0,0 +1,644 @@
+// 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/fileapi/file_system_url_loader_factory.h"
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/stringprintf.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "build/build_config.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/child_process_host.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/system/string_data_pipe_producer.h"
+#include "net/base/directory_listing.h"
+#include "net/base/io_buffer.h"
+#include "net/base/mime_sniffer.h"
+#include "net/base/mime_util.h"
+#include "net/http/http_byte_range.h"
+#include "net/http/http_util.h"
+#include "storage/browser/fileapi/file_stream_reader.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/common/fileapi/file_system_util.h"
+
+using filesystem::mojom::DirectoryEntry;
+using storage::FileStreamReader;
+using storage::FileSystemContext;
+using storage::FileSystemOperation;
+using storage::FileSystemRequestInfo;
+using storage::FileSystemURL;
+using storage::VirtualPath;
+
+namespace content {
+namespace {
+
+struct FactoryParams {
+ int render_process_host_id;
+ int frame_tree_node_id;
+ scoped_refptr<FileSystemContext> file_system_context;
+ std::string storage_domain;
+};
+
+constexpr size_t kDefaultFileSystemUrlPipeSize = 65536;
+
+// Implementation sniffs the first file chunk to determine the mime-type.
+static_assert(kDefaultFileSystemUrlPipeSize >= net::kMaxBytesToSniff,
+ "Default file data pipe size must be at least as large as a "
+ "MIME-type sniffing buffer.");
+
+scoped_refptr<net::HttpResponseHeaders> CreateHttpResponseHeaders(
+ int response_code) {
+ std::string raw_headers;
+ raw_headers.append(base::StringPrintf("HTTP/1.1 %d OK", response_code));
+
+ // Tell WebKit never to cache this content.
+ raw_headers.append(1, '\0');
+ raw_headers.append(net::HttpRequestHeaders::kCacheControl);
+ raw_headers.append(": no-cache");
+
+ raw_headers.append(2, '\0');
+ return base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
+}
+
+bool GetMimeType(const FileSystemURL& url, std::string* mime_type) {
+ DCHECK(url.is_valid());
+ base::FilePath::StringType extension = url.path().Extension();
+ if (!extension.empty())
+ extension = extension.substr(1);
+ return net::GetWellKnownMimeTypeFromExtension(extension, mime_type);
+}
+
+// Common implementation shared between the file and directory URLLoaders.
+class FileSystemEntryURLLoader
+ : public network::mojom::URLLoader,
+ public base::SupportsWeakPtr<FileSystemEntryURLLoader> {
+ public:
+ explicit FileSystemEntryURLLoader(FactoryParams params)
+ : binding_(this), params_(std::move(params)) {}
+
+ // network::mojom::URLLoader:
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {}
+ void ProceedWithResponse() override {}
+ void SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) override {}
+ void PauseReadingBodyFromNet() override {}
+ void ResumeReadingBodyFromNet() override {}
+
+ protected:
+ virtual void FileSystemIsMounted() = 0;
+
+ void Start(const network::ResourceRequest& request,
+ network::mojom::URLLoaderRequest loader,
+ network::mojom::URLLoaderClientPtrInfo client_info,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
+ io_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FileSystemEntryURLLoader::StartOnIOThread, AsWeakPtr(),
+ request, std::move(loader), std::move(client_info)));
+ }
+
+ void MaybeDeleteSelf() {
+ if (!binding_.is_bound() && !client_.is_bound())
+ delete this;
+ }
+
+ void OnClientComplete(network::URLLoaderCompletionStatus status) {
+ client_->OnComplete(status);
+ client_.reset();
+ MaybeDeleteSelf();
+ }
+
+ void OnClientComplete(base::File::Error file_error) {
+ OnClientComplete(net::FileErrorToNetError(file_error));
+ }
+
+ void OnClientComplete(net::Error net_error) {
+ OnClientComplete(network::URLLoaderCompletionStatus(net_error));
+ }
+
+ mojo::Binding<network::mojom::URLLoader> binding_;
+ network::mojom::URLLoaderClientPtr client_;
+ FactoryParams params_;
+ std::unique_ptr<mojo::StringDataPipeProducer> data_producer_;
+ net::HttpByteRange byte_range_;
+ FileSystemURL url_;
+
+ private:
+ void StartOnIOThread(const network::ResourceRequest& request,
+ network::mojom::URLLoaderRequest loader,
+ network::mojom::URLLoaderClientPtrInfo client_info) {
+ binding_.Bind(std::move(loader));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &FileSystemEntryURLLoader::OnConnectionError, base::Unretained(this)));
+
+ client_.Bind(std::move(client_info));
+
+ if (!request.url.is_valid()) {
+ OnClientComplete(net::ERR_INVALID_URL);
+ return;
+ }
+
+ if (params_.render_process_host_id != ChildProcessHost::kInvalidUniqueID &&
+ !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+ params_.render_process_host_id, request.url)) {
+ DVLOG(1) << "Denied unauthorized request for "
+ << request.url.possibly_invalid_spec();
+ OnClientComplete(net::ERR_INVALID_URL);
+ return;
+ }
+
+ std::string range_header;
+ if (request.headers.GetHeader(net::HttpRequestHeaders::kRange,
+ &range_header)) {
+ std::vector<net::HttpByteRange> ranges;
+ if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+ if (ranges.size() == 1) {
+ byte_range_ = ranges[0];
+ } else {
+ // We don't support multiple range requests in one single URL request.
+ // TODO(adamk): decide whether we want to support multiple range
+ // requests.
+ OnClientComplete(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+ return;
+ }
+ }
+ }
+
+ url_ = params_.file_system_context->CrackURL(request.url);
+ if (!url_.is_valid()) {
+ const FileSystemRequestInfo request_info = {request.url, nullptr,
+ params_.storage_domain,
+ params_.frame_tree_node_id};
+ params_.file_system_context->AttemptAutoMountForURLRequest(
+ request_info,
+ base::BindOnce(&FileSystemEntryURLLoader::DidAttemptAutoMount,
+ AsWeakPtr(), request));
+ return;
+ }
+ FileSystemIsMounted();
+ }
+
+ void DidAttemptAutoMount(const network::ResourceRequest& request,
+ base::File::Error result) {
+ if (result != base::File::Error::FILE_OK) {
+ OnClientComplete(result);
+ return;
+ }
+ url_ = params_.file_system_context->CrackURL(request.url);
+ if (!url_.is_valid()) {
+ OnClientComplete(net::ERR_FILE_NOT_FOUND);
+ return;
+ }
+ FileSystemIsMounted();
+ }
+
+ void OnConnectionError() {
+ binding_.Close();
+ MaybeDeleteSelf();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemEntryURLLoader);
+};
+
+class FileSystemDirectoryURLLoader : public FileSystemEntryURLLoader {
+ public:
+ static void CreateAndStart(
+ const network::ResourceRequest& request,
+ network::mojom::URLLoaderRequest loader,
+ network::mojom::URLLoaderClientPtrInfo client_info,
+ FactoryParams params,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
+ // Owns itself. Will live as long as its URLLoader and URLLoaderClientPtr
+ // bindings are alive - essentially until either the client gives up or all
+ // file directory has been sent to it.
+ auto* filesystem_loader =
+ new FileSystemDirectoryURLLoader(std::move(params));
+ filesystem_loader->Start(request, std::move(loader), std::move(client_info),
+ io_task_runner);
+ }
+
+ private:
+ explicit FileSystemDirectoryURLLoader(FactoryParams params)
+ : FileSystemEntryURLLoader(params) {}
+
+ void FileSystemIsMounted() override {
+ DCHECK(url_.is_valid());
+ if (!params_.file_system_context->CanServeURLRequest(url_)) {
+ // In incognito mode the API is not usable and there should be no data.
+ if (VirtualPath::IsRootPath(url_.virtual_path())) {
+ // Return an empty directory if the filesystem root is queried.
+ DidReadDirectory(base::File::FILE_OK, std::vector<DirectoryEntry>(),
+ /*has_more=*/false);
+ return;
+ }
+ // In incognito mode the API is not usable and there should be no data.
+ OnClientComplete(net::ERR_FILE_NOT_FOUND);
+ return;
+ }
+ params_.file_system_context->operation_runner()->ReadDirectory(
+ url_,
+ base::BindRepeating(&FileSystemDirectoryURLLoader::DidReadDirectory,
+ base::AsWeakPtr(this)));
+ }
+
+ void DidReadDirectory(base::File::Error result,
+ std::vector<DirectoryEntry> entries,
+ bool has_more) {
+ if (result != base::File::FILE_OK) {
+ net::Error rv = net::ERR_FILE_NOT_FOUND;
+ if (result == base::File::FILE_ERROR_INVALID_URL)
+ rv = net::ERR_INVALID_URL;
+ OnClientComplete(rv);
+ return;
+ }
+
+ if (data_.empty()) {
+ base::FilePath relative_path = url_.path();
+#if defined(OS_POSIX)
+ relative_path =
+ base::FilePath(FILE_PATH_LITERAL("/") + relative_path.value());
+#endif
+ const base::string16& title = relative_path.LossyDisplayName();
+ data_.append(net::GetDirectoryListingHeader(title));
+ }
+
+ entries_.insert(entries_.end(), entries.begin(), entries.end());
+
+ if (!has_more) {
+ if (entries_.size())
+ GetMetadata(/*index=*/0);
+ else
+ WriteDirectoryData();
+ }
+ }
+
+ void GetMetadata(size_t index) {
+ const DirectoryEntry& entry = entries_[index];
+ const FileSystemURL entry_url =
+ params_.file_system_context->CreateCrackedFileSystemURL(
+ url_.origin(), url_.type(),
+ url_.path().Append(base::FilePath(entry.name)));
+ DCHECK(entry_url.is_valid());
+ params_.file_system_context->operation_runner()->GetMetadata(
+ entry_url,
+ FileSystemOperation::GET_METADATA_FIELD_SIZE |
+ FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
+ base::BindRepeating(&FileSystemDirectoryURLLoader::DidGetMetadata,
+ base::AsWeakPtr(this), index));
+ }
+
+ void DidGetMetadata(size_t index,
+ base::File::Error result,
+ const base::File::Info& file_info) {
+ if (result != base::File::FILE_OK) {
+ OnClientComplete(result);
+ return;
+ }
+
+ const DirectoryEntry& entry = entries_[index];
+ const base::string16& name = base::FilePath(entry.name).LossyDisplayName();
+ data_.append(net::GetDirectoryListingEntry(
+ name, std::string(),
+ entry.type == filesystem::mojom::FsFileType::DIRECTORY, file_info.size,
+ file_info.last_modified));
+
+ if (index < entries_.size() - 1)
+ GetMetadata(index + 1);
+ else
+ WriteDirectoryData();
+ }
+
+ void WriteDirectoryData() {
+ mojo::DataPipe pipe(std::max(data_.size(), kDefaultFileSystemUrlPipeSize));
+ if (!pipe.consumer_handle.is_valid()) {
+ OnClientComplete(net::ERR_FAILED);
+ return;
+ }
+
+ network::ResourceResponseHead head;
+ head.mime_type = "text/plain";
+ head.charset = "utf-8";
+ head.content_length = data_.size();
+ head.headers = CreateHttpResponseHeaders(200);
+
+ client_->OnReceiveResponse(head, /*downloaded_file=*/nullptr);
+ client_->OnStartLoadingResponseBody(std::move(pipe.consumer_handle));
+
+ data_producer_ = std::make_unique<mojo::StringDataPipeProducer>(
+ std::move(pipe.producer_handle));
+
+ data_producer_->Write(
+ base::StringPiece(data_),
+ mojo::StringDataPipeProducer::AsyncWritingMode::
+ STRING_STAYS_VALID_UNTIL_COMPLETION,
+ base::BindOnce(&FileSystemDirectoryURLLoader::OnDirectoryWritten,
+ base::Unretained(this)));
+ }
+
+ void OnDirectoryWritten(MojoResult result) {
+ // All the data has been written now. Close the data pipe. The consumer will
+ // be notified that there will be no more data to read from now.
+ data_producer_.reset();
+ directory_data_ = nullptr;
+ entries_.clear();
+ data_.clear();
+
+ OnClientComplete(result == MOJO_RESULT_OK ? net::OK : net::ERR_FAILED);
+ }
+
+ std::string data_;
+ std::vector<DirectoryEntry> entries_;
+ scoped_refptr<net::IOBuffer> directory_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemDirectoryURLLoader);
+};
+
+class FileSystemFileURLLoader : public FileSystemEntryURLLoader {
+ public:
+ static void CreateAndStart(
+ const network::ResourceRequest& request,
+ network::mojom::URLLoaderRequest loader,
+ network::mojom::URLLoaderClientPtrInfo client_info,
+ FactoryParams params,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
+ // Owns itself. Will live as long as its URLLoader and URLLoaderClientPtr
+ // bindings are alive - essentially until either the client gives up or all
+ // file data has been sent to it.
+ auto* filesystem_loader =
+ new FileSystemFileURLLoader(std::move(params), request, io_task_runner);
+
+ filesystem_loader->Start(request, std::move(loader), std::move(client_info),
+ io_task_runner);
+ }
+
+ private:
+ FileSystemFileURLLoader(
+ FactoryParams params,
+ const network::ResourceRequest& request,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner)
+ : FileSystemEntryURLLoader(std::move(params)),
+ original_request_(request),
+ io_task_runner_(io_task_runner) {}
+
+ void FileSystemIsMounted() override {
+ DCHECK(url_.is_valid());
+ if (!params_.file_system_context->CanServeURLRequest(url_)) {
+ // In incognito mode the API is not usable and there should be no data.
+ OnClientComplete(net::ERR_FILE_NOT_FOUND);
+ return;
+ }
+ params_.file_system_context->operation_runner()->GetMetadata(
+ url_,
+ FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
+ FileSystemOperation::GET_METADATA_FIELD_SIZE,
+ base::AdaptCallbackForRepeating(base::BindOnce(
+ &FileSystemFileURLLoader::DidGetMetadata, base::AsWeakPtr(this))));
+ }
+
+ void DidGetMetadata(base::File::Error error_code,
+ const base::File::Info& file_info) {
+ if (error_code != base::File::FILE_OK) {
+ OnClientComplete(error_code == base::File::FILE_ERROR_INVALID_URL
+ ? net::ERR_INVALID_URL
+ : net::ERR_FILE_NOT_FOUND);
+ return;
+ }
+
+ if (!byte_range_.ComputeBounds(file_info.size)) {
+ OnClientComplete(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
+ return;
+ }
+
+ if (file_info.is_directory) {
+ // Redirect to the directory URLLoader.
+ GURL::Replacements replacements;
+ std::string new_path = original_request_.url.path();
+ new_path.push_back('/');
+ replacements.SetPathStr(new_path);
+ const GURL directory_url =
+ original_request_.url.ReplaceComponents(replacements);
+
+ net::RedirectInfo redirect_info;
+ redirect_info.new_method = "GET";
+ redirect_info.status_code = 301;
+ head_.headers = CreateHttpResponseHeaders(redirect_info.status_code);
+ redirect_info.new_url =
+ original_request_.url.ReplaceComponents(replacements);
+ head_.encoded_data_length = 0;
+ client_->OnReceiveRedirect(redirect_info, head_);
+
+ // Restart the request with a directory loader.
+ network::ResourceRequest new_request = original_request_;
+ new_request.url = redirect_info.new_url;
+ FileSystemDirectoryURLLoader::CreateAndStart(
+ new_request, binding_.Unbind(), client_.PassInterface(),
+ std::move(params_), io_task_runner_);
+ MaybeDeleteSelf();
+ return;
+ }
+
+ remaining_bytes_ = byte_range_.last_byte_position() -
+ byte_range_.first_byte_position() + 1;
+ DCHECK_GE(remaining_bytes_, 0);
+
+ DCHECK(!reader_.get());
+ reader_ = params_.file_system_context->CreateFileStreamReader(
+ url_, byte_range_.first_byte_position(), remaining_bytes_,
+ base::Time());
+
+ mojo::DataPipe pipe(remaining_bytes_);
+ if (!pipe.consumer_handle.is_valid()) {
+ OnClientComplete(net::ERR_FAILED);
+ return;
+ }
+ consumer_handle_ = std::move(pipe.consumer_handle);
+
+ head_.mime_type = "text/html"; // Will sniff file and possibly override.
+ head_.charset = "utf-8";
+ head_.content_length = remaining_bytes_;
+ head_.headers = CreateHttpResponseHeaders(200);
+
+ data_producer_ = std::make_unique<mojo::StringDataPipeProducer>(
+ std::move(pipe.producer_handle));
+
+ file_data_ = new net::IOBuffer(kDefaultFileSystemUrlPipeSize);
+ ReadMoreFileData();
+ }
+
+ void ReadMoreFileData() {
+ int64_t bytes_to_read = std::min(
+ static_cast<int64_t>(kDefaultFileSystemUrlPipeSize), remaining_bytes_);
+ if (!bytes_to_read) {
+ OnFileWritten(MOJO_RESULT_OK);
+ return;
+ }
+ net::CompletionCallback read_callback = base::BindRepeating(
+ &FileSystemFileURLLoader::DidReadMoreFileData, base::AsWeakPtr(this));
+ const int rv =
+ reader_->Read(file_data_.get(), bytes_to_read, read_callback);
+ if (rv == net::ERR_IO_PENDING) {
+ // async callback will be called.
+ return;
+ }
+ std::move(read_callback).Run(rv);
+ }
+
+ void DidReadMoreFileData(int result) {
+ if (result <= 0) {
+ OnFileWritten(result);
+ return;
+ }
+
+ if (consumer_handle_.is_valid()) {
+ if (byte_range_.first_byte_position() == 0) {
+ // Only sniff for mime-type in the first block of the file.
+ std::string type_hint;
+ GetMimeType(url_, &type_hint);
+ SniffMimeType(file_data_->data(), result, url_.ToGURL(), type_hint,
+ net::ForceSniffFileUrlsForHtml::kDisabled,
+ &head_.mime_type);
+ }
+
+ client_->OnReceiveResponse(head_, /*downloaded_file=*/nullptr);
+ client_->OnStartLoadingResponseBody(std::move(consumer_handle_));
+ }
+ remaining_bytes_ -= result;
+ DCHECK_GE(remaining_bytes_, 0);
+
+ WriteFileData(result);
+ }
+
+ void WriteFileData(int bytes_read) {
+ data_producer_->Write(
+ base::StringPiece(file_data_->data(), bytes_read),
+ mojo::StringDataPipeProducer::AsyncWritingMode::
+ STRING_STAYS_VALID_UNTIL_COMPLETION,
+ base::BindOnce(&FileSystemFileURLLoader::OnFileDataWritten,
+ base::AsWeakPtr(this)));
+ }
+
+ void OnFileDataWritten(MojoResult result) {
+ if (result != MOJO_RESULT_OK || remaining_bytes_ == 0) {
+ OnFileWritten(result);
+ return;
+ }
+ ReadMoreFileData();
+ }
+
+ void OnFileWritten(MojoResult result) {
+ // All the data has been written now. Close the data pipe. The consumer will
+ // be notified that there will be no more data to read from now.
+ data_producer_.reset();
+ file_data_ = nullptr;
+
+ OnClientComplete(result == MOJO_RESULT_OK ? net::OK : net::ERR_FAILED);
+ }
+
+ int64_t remaining_bytes_ = 0;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle_;
+ std::unique_ptr<FileStreamReader> reader_;
+ scoped_refptr<net::IOBuffer> file_data_;
+ network::ResourceResponseHead head_;
+ const network::ResourceRequest original_request_;
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemFileURLLoader);
+};
+
+// A URLLoaderFactory used for the filesystem:// scheme used when the Network
+// Service is enabled.
+class FileSystemURLLoaderFactory : public network::mojom::URLLoaderFactory {
+ public:
+ FileSystemURLLoaderFactory(
+ FactoryParams params,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner)
+ : params_(std::move(params)), io_task_runner_(io_task_runner) {}
+
+ ~FileSystemURLLoaderFactory() override = default;
+
+ network::mojom::URLLoaderFactoryPtr CreateBinding() {
+ network::mojom::URLLoaderFactoryPtr factory;
+ bindings_.AddBinding(this, mojo::MakeRequest(&factory));
+ return factory;
+ }
+
+ private:
+ void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& request,
+ network::mojom::URLLoaderClientPtr client,
+ const net::MutableNetworkTrafficAnnotationTag&
+ traffic_annotation) override {
+ DVLOG(1) << "CreateLoaderAndStart: " << request.url;
+
+ const std::string path = request.url.path();
+
+ // If the path ends with a /, we know it's a directory. If the path refers
+ // to a directory and gets dispatched to FileSystemFileURLLoader, that class
+ // will redirect to FileSystemDirectoryURLLoader.
+ if (!path.empty() && path.back() == '/') {
+ FileSystemDirectoryURLLoader::CreateAndStart(request, std::move(loader),
+ client.PassInterface(),
+ params_, io_task_runner_);
+ return;
+ }
+
+ FileSystemFileURLLoader::CreateAndStart(request, std::move(loader),
+ client.PassInterface(), params_,
+ io_task_runner_);
+ }
+
+ void Clone(network::mojom::URLLoaderFactoryRequest loader) override {
+ bindings_.AddBinding(this, std::move(loader));
+ }
+
+ const FactoryParams params_;
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemURLLoaderFactory);
+};
+
+} // anonymous namespace
+
+std::unique_ptr<network::mojom::URLLoaderFactory>
+CreateFileSystemURLLoaderFactory(
+ RenderFrameHost* render_frame_host,
+ bool is_navigation,
+ scoped_refptr<FileSystemContext> file_system_context,
+ const std::string& storage_domain) {
+ // Get the RPH ID for security checks for non-navigation resource requests.
+ int render_process_host_id = is_navigation
+ ? ChildProcessHost::kInvalidUniqueID
+ : render_frame_host->GetProcess()->GetID();
+
+ FactoryParams params = {render_process_host_id,
+ render_frame_host->GetFrameTreeNodeId(),
+ file_system_context, storage_domain};
+
+ return std::make_unique<FileSystemURLLoaderFactory>(
+ std::move(params),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/fileapi/file_system_url_loader_factory.h b/chromium/content/browser/fileapi/file_system_url_loader_factory.h
new file mode 100644
index 00000000000..2cfda1e18ec
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory.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 CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_URL_LOADER_FACTORY_H_
+#define CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_URL_LOADER_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "storage/browser/fileapi/file_system_context.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+// Create a URLLoaderFactory to serve filesystem: requests from the given
+// |file_system_context| and |storage_domain|.
+CONTENT_EXPORT std::unique_ptr<network::mojom::URLLoaderFactory>
+CreateFileSystemURLLoaderFactory(
+ RenderFrameHost* render_frame_host,
+ bool is_navigation,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
+ const std::string& storage_domain);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FILEAPI_FILE_SYSTEM_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc b/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc
new file mode 100644
index 00000000000..79fd580333d
--- /dev/null
+++ b/chromium/content/browser/fileapi/file_system_url_loader_factory_browsertest.cc
@@ -0,0 +1,817 @@
+// 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 <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/i18n/unicodestring.h"
+#include "base/rand_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "content/browser/fileapi/file_system_url_loader_factory.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/shell/browser/shell.h"
+#include "net/base/mime_util.h"
+#include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/test/async_file_test_helper.h"
+#include "storage/browser/test/mock_special_storage_policy.h"
+#include "storage/browser/test/test_file_system_backend.h"
+#include "storage/browser/test/test_file_system_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/icu/source/i18n/unicode/datefmt.h"
+#include "third_party/icu/source/i18n/unicode/regex.h"
+
+using content::AsyncFileTestHelper;
+using network::mojom::URLLoaderFactory;
+using storage::FileSystemContext;
+using storage::FileSystemOperationContext;
+using storage::FileSystemURL;
+
+namespace content {
+namespace {
+
+// We always use the TEMPORARY FileSystem in these tests.
+const char kFileSystemURLPrefix[] = "filesystem:http://remote/temporary/";
+
+const char kValidExternalMountPoint[] = "mnt_name";
+
+const char kTestFileData[] = "0123456789";
+
+void FillBuffer(char* buffer, size_t len) {
+ base::RandBytes(buffer, len);
+}
+
+// An auto mounter that will try to mount anything for |storage_domain| =
+// "automount", but will only succeed for the mount point "mnt_name".
+bool TestAutoMountForURLRequest(
+ const storage::FileSystemRequestInfo& request_info,
+ const storage::FileSystemURL& filesystem_url,
+ base::OnceCallback<void(base::File::Error result)> callback) {
+ if (request_info.storage_domain != "automount")
+ return false;
+
+ std::vector<base::FilePath::StringType> components;
+ filesystem_url.path().GetComponents(&components);
+ std::string mount_point = base::FilePath(components[0]).AsUTF8Unsafe();
+
+ if (mount_point == kValidExternalMountPoint) {
+ storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ kValidExternalMountPoint, storage::kFileSystemTypeTest,
+ storage::FileSystemMountOption(), base::FilePath());
+ std::move(callback).Run(base::File::FILE_OK);
+ } else {
+ std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
+ }
+ return true;
+}
+
+void ReadDataPipeInternal(mojo::DataPipeConsumerHandle handle,
+ std::string* result,
+ base::OnceClosure quit_closure) {
+ while (true) {
+ uint32_t num_bytes;
+ const void* buffer = nullptr;
+ MojoResult rv =
+ handle.BeginReadData(&buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ switch (rv) {
+ case MOJO_RESULT_BUSY:
+ case MOJO_RESULT_INVALID_ARGUMENT:
+ NOTREACHED();
+ return;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ std::move(quit_closure).Run();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ReadDataPipeInternal, handle, result,
+ std::move(quit_closure)));
+ return;
+ case MOJO_RESULT_OK:
+ EXPECT_NE(nullptr, buffer);
+ EXPECT_GT(num_bytes, 0u);
+ uint32_t before_size = result->size();
+ result->append(static_cast<const char*>(buffer), num_bytes);
+ uint32_t read_size = result->size() - before_size;
+ EXPECT_EQ(num_bytes, read_size);
+ rv = handle.EndReadData(read_size);
+ EXPECT_EQ(MOJO_RESULT_OK, rv);
+ break;
+ }
+ }
+ NOTREACHED();
+ return;
+}
+
+std::string ReadDataPipe(mojo::ScopedDataPipeConsumerHandle handle) {
+ EXPECT_TRUE(handle.is_valid());
+ if (!handle.is_valid())
+ return "";
+ std::string result;
+ base::RunLoop loop;
+ ReadDataPipeInternal(handle.get(), &result, loop.QuitClosure());
+ loop.Run();
+ return result;
+}
+
+// Directory listings can have a HTML header in the file to format the response.
+// This function determines if a single line in the response is for a directory
+// entry.
+bool IsDirectoryListingLine(const std::string& line) {
+ return line.find("<script>addRow(\"") == 0;
+}
+
+// Is the line a title inserted by net::GetDirectoryListingHeader?
+bool IsDirectoryListingTitle(const std::string& line) {
+ return line.find("<script>start(\"") == 0;
+}
+
+void ShutdownFileSystemContextOnIOThread(
+ scoped_refptr<FileSystemContext> file_system_context) {
+ if (!file_system_context)
+ return;
+ file_system_context->Shutdown();
+ file_system_context = nullptr;
+}
+
+} // namespace
+
+class FileSystemURLLoaderFactoryTest : public ContentBrowserTest {
+ protected:
+ FileSystemURLLoaderFactoryTest() : weak_factory_(this) {}
+ ~FileSystemURLLoaderFactoryTest() override = default;
+
+ void SetUpOnMainThread() override {
+ feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ special_storage_policy_ = new MockSpecialStoragePolicy;
+ file_system_context_ =
+ CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
+
+ // We use the main thread so that we can get the root path synchronously.
+ file_system_context_->OpenFileSystem(
+ GURL("http://remote/"), storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::BindOnce(&FileSystemURLLoaderFactoryTest::OnOpenFileSystem,
+ weak_factory_.GetWeakPtr()));
+ base::RunLoop().RunUntilIdle();
+ ContentBrowserTest::SetUpOnMainThread();
+ }
+
+ void TearDownOnMainThread() override {
+ loader_.reset();
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ShutdownFileSystemContextOnIOThread,
+ std::move(file_system_context_)));
+ special_storage_policy_ = nullptr;
+ // FileReader posts a task to close the file in destructor.
+ base::RunLoop().RunUntilIdle();
+ ContentBrowserTest::TearDownOnMainThread();
+ }
+
+ void SetUpAutoMountContext(base::FilePath* mnt_point) {
+ *mnt_point = temp_dir_.GetPath().AppendASCII("auto_mount_dir");
+ ASSERT_TRUE(base::CreateDirectory(*mnt_point));
+
+ std::vector<std::unique_ptr<storage::FileSystemBackend>>
+ additional_providers;
+ additional_providers.push_back(std::make_unique<TestFileSystemBackend>(
+ base::ThreadTaskRunnerHandle::Get().get(), *mnt_point));
+
+ std::vector<storage::URLRequestAutoMountHandler> handlers = {
+ base::BindRepeating(&TestAutoMountForURLRequest)};
+
+ file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting(
+ nullptr, std::move(additional_providers), handlers,
+ temp_dir_.GetPath());
+ }
+
+ void SetFileUpAutoMountContext() {
+ base::FilePath mnt_point;
+ SetUpAutoMountContext(&mnt_point);
+
+ ASSERT_EQ(static_cast<int>(sizeof(kTestFileData)) - 1,
+ base::WriteFile(mnt_point.AppendASCII("foo"), kTestFileData,
+ sizeof(kTestFileData) - 1));
+ }
+
+ FileSystemURL CreateURL(const base::FilePath& file_path) {
+ return file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://remote"), storage::kFileSystemTypeTemporary, file_path);
+ }
+
+ void CreateDirectory(const base::StringPiece& dir_name) {
+ base::FilePath path = base::FilePath().AppendASCII(dir_name);
+ std::unique_ptr<FileSystemOperationContext> context(NewOperationContext());
+ ASSERT_EQ(base::File::FILE_OK,
+ file_util()->CreateDirectory(context.get(), CreateURL(path),
+ false /* exclusive */,
+ false /* recursive */));
+ }
+
+ void WriteFile(const base::StringPiece& file_name,
+ const char* buf,
+ int buf_size) {
+ FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
+ GURL("http://remote"), storage::kFileSystemTypeTemporary,
+ base::FilePath().AppendASCII(file_name));
+ ASSERT_EQ(base::File::FILE_OK,
+ AsyncFileTestHelper::CreateFileWithData(
+ file_system_context_.get(), url, buf, buf_size));
+ }
+
+ void EnsureFileExists(const base::StringPiece file_name) {
+ base::FilePath path = base::FilePath().AppendASCII(file_name);
+ std::unique_ptr<FileSystemOperationContext> context(NewOperationContext());
+ ASSERT_EQ(
+ base::File::FILE_OK,
+ file_util()->EnsureFileExists(context.get(), CreateURL(path), nullptr));
+ }
+
+ void TruncateFile(const base::StringPiece file_name, int64_t length) {
+ base::FilePath path = base::FilePath().AppendASCII(file_name);
+ std::unique_ptr<FileSystemOperationContext> context(NewOperationContext());
+ ASSERT_EQ(base::File::FILE_OK,
+ file_util()->Truncate(context.get(), CreateURL(path), length));
+ }
+
+ // If |size| is negative, the reported size is ignored.
+ void VerifyListingEntry(const std::string& entry_line,
+ const std::string& name,
+ const std::string& url,
+ bool is_directory,
+ int64_t size) {
+#define NUMBER "([0-9-]*)"
+#define STR "([^\"]*)"
+ icu::UnicodeString pattern("^<script>addRow\\(\"" STR "\",\"" STR
+ "\",(0|1)," NUMBER ",\"" STR "\"," NUMBER
+ ",\"" STR "\"\\);</script>");
+#undef NUMBER
+#undef STR
+ icu::UnicodeString input(entry_line.c_str());
+
+ UErrorCode status = U_ZERO_ERROR;
+ icu::RegexMatcher match(pattern, input, 0, status);
+
+ EXPECT_TRUE(match.find());
+ EXPECT_EQ(7, match.groupCount());
+ EXPECT_EQ(icu::UnicodeString(name.c_str()), match.group(1, status));
+ EXPECT_EQ(icu::UnicodeString(url.c_str()), match.group(2, status));
+ EXPECT_EQ(icu::UnicodeString(is_directory ? "1" : "0"),
+ match.group(3, status));
+ if (size >= 0) {
+ icu::UnicodeString size_string(
+ base::FormatBytesUnlocalized(size).c_str());
+ EXPECT_EQ(size_string, match.group(5, status));
+ }
+
+ icu::UnicodeString date_ustr(match.group(7, status));
+ std::unique_ptr<icu::DateFormat> formatter(
+ icu::DateFormat::createDateTimeInstance(icu::DateFormat::kShort));
+ UErrorCode parse_status = U_ZERO_ERROR;
+ UDate udate = formatter->parse(date_ustr, parse_status);
+ EXPECT_TRUE(U_SUCCESS(parse_status));
+ base::Time date = base::Time::FromJsTime(udate);
+ EXPECT_FALSE(date.is_null());
+ }
+
+ GURL CreateFileSystemURL(const std::string& path) {
+ return GURL(kFileSystemURLPrefix + path);
+ }
+
+ std::unique_ptr<network::TestURLLoaderClient> TestLoad(const GURL& url) {
+ auto client = TestLoadHelper(url, /*extra_headers=*/nullptr,
+ file_system_context_.get());
+ client->RunUntilComplete();
+ return client;
+ }
+
+ std::unique_ptr<network::TestURLLoaderClient> TestLoadWithContext(
+ const GURL& url,
+ FileSystemContext* file_system_context) {
+ auto client =
+ TestLoadHelper(url, /*extra_headers=*/nullptr, file_system_context);
+ client->RunUntilComplete();
+ return client;
+ }
+
+ std::unique_ptr<network::TestURLLoaderClient> TestLoadWithHeaders(
+ const GURL& url,
+ const net::HttpRequestHeaders* extra_headers) {
+ auto client =
+ TestLoadHelper(url, extra_headers, file_system_context_.get());
+ client->RunUntilComplete();
+ return client;
+ }
+
+ std::unique_ptr<network::TestURLLoaderClient> TestLoadNoRun(const GURL& url) {
+ return TestLoadHelper(url, /*extra_headers=*/nullptr,
+ file_system_context_.get());
+ }
+
+ // |temp_dir_| must be deleted last.
+ base::ScopedTempDir temp_dir_;
+ network::mojom::URLLoaderPtr loader_;
+
+ private:
+ storage::FileSystemFileUtil* file_util() {
+ return file_system_context_->sandbox_delegate()->sync_file_util();
+ }
+
+ FileSystemOperationContext* NewOperationContext() {
+ FileSystemOperationContext* context(
+ new FileSystemOperationContext(file_system_context_.get()));
+ context->set_allowed_bytes_growth(1024);
+ return context;
+ }
+
+ void OnOpenFileSystem(const GURL& root_url,
+ const std::string& name,
+ base::File::Error result) {
+ ASSERT_EQ(base::File::FILE_OK, result);
+ }
+
+ RenderFrameHost* render_frame_host() const {
+ return shell()->web_contents()->GetMainFrame();
+ }
+
+ // Starts |request| using |loader_factory| and sets |out_loader| and
+ // |out_loader_client| to the resulting URLLoader and its URLLoaderClient. The
+ // caller can then use functions like client.RunUntilComplete() to wait for
+ // completion.
+ void StartRequest(
+ URLLoaderFactory* loader_factory,
+ const network::ResourceRequest& request,
+ network::mojom::URLLoaderPtr* out_loader,
+ std::unique_ptr<network::TestURLLoaderClient>* out_loader_client) {
+ *out_loader_client = std::make_unique<network::TestURLLoaderClient>();
+ loader_factory->CreateLoaderAndStart(
+ mojo::MakeRequest(out_loader), 0, 0, network::mojom::kURLLoadOptionNone,
+ request, (*out_loader_client)->CreateInterfacePtr(),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+ }
+
+ content::WebContents* GetWebContents() { return shell()->web_contents(); }
+
+ std::unique_ptr<network::TestURLLoaderClient> TestLoadHelper(
+ const GURL& url,
+ const net::HttpRequestHeaders* extra_headers,
+ FileSystemContext* file_system_context) {
+ network::ResourceRequest request;
+ request.url = url;
+ if (extra_headers)
+ request.headers.MergeFrom(*extra_headers);
+ const std::string storage_domain = url.GetOrigin().host();
+
+ auto factory = content::CreateFileSystemURLLoaderFactory(
+ render_frame_host(), /*is_navigation=*/false, file_system_context,
+ storage_domain);
+ std::unique_ptr<network::TestURLLoaderClient> client;
+ StartRequest(factory.get(), request, &loader_, &client);
+ return client;
+ }
+
+ base::test::ScopedFeatureList feature_list_;
+ scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<FileSystemContext> file_system_context_;
+ base::WeakPtrFactory<FileSystemURLLoaderFactoryTest> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSystemURLLoaderFactoryTest);
+};
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, DirectoryListing) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ CreateDirectory("foo");
+ CreateDirectory("foo/bar");
+ CreateDirectory("foo/bar/baz");
+
+ EnsureFileExists("foo/bar/hoge");
+ TruncateFile("foo/bar/hoge", 10);
+
+ auto client = TestLoad(CreateFileSystemURL("foo/bar/"));
+
+ ASSERT_TRUE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_GT(response_text.size(), 0ul);
+
+ std::istringstream in(response_text);
+ std::string line;
+
+ std::string listing_header;
+ std::vector<std::string> listing_entries;
+ while (!!std::getline(in, line)) {
+ if (listing_header.empty() && IsDirectoryListingTitle(line)) {
+ listing_header = line;
+ continue;
+ }
+ if (IsDirectoryListingLine(line))
+ listing_entries.push_back(line);
+ }
+
+#if defined(OS_WIN)
+ EXPECT_EQ("<script>start(\"foo\\\\bar\");</script>", listing_header);
+#elif defined(OS_POSIX)
+ EXPECT_EQ("<script>start(\"/foo/bar\");</script>", listing_header);
+#endif
+
+ ASSERT_EQ(2U, listing_entries.size());
+ std::sort(listing_entries.begin(), listing_entries.end());
+ VerifyListingEntry(listing_entries[0], "baz", "baz", true, 0);
+ VerifyListingEntry(listing_entries[1], "hoge", "hoge", false, 10);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, InvalidURL) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ auto client = TestLoad(GURL("filesystem:/foo/bar/baz"));
+ ASSERT_FALSE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_INVALID_URL, client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchRoot) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ auto client = TestLoad(GURL("filesystem:http://remote/persistent/somedir/"));
+ ASSERT_FALSE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchDirectory) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ auto client = TestLoad(CreateFileSystemURL("somedir/"));
+ ASSERT_FALSE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, Cancel) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ CreateDirectory("foo");
+ auto client = TestLoadNoRun(CreateFileSystemURL("foo/"));
+ ASSERT_FALSE(client->has_received_response());
+ ASSERT_FALSE(client->has_received_completion());
+
+ client.reset();
+ loader_.reset();
+ base::RunLoop().RunUntilIdle();
+ // If we get here, success! we didn't crash!
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, Incognito) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ CreateDirectory("foo");
+
+ scoped_refptr<FileSystemContext> file_system_context =
+ CreateIncognitoFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
+
+ auto client =
+ TestLoadWithContext(CreateFileSystemURL("/"), file_system_context.get());
+ ASSERT_TRUE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_GT(response_text.size(), 0ul);
+
+ std::istringstream in(response_text);
+
+ int num_entries = 0;
+ std::string line;
+ while (!!std::getline(in, line)) {
+ if (IsDirectoryListingLine(line))
+ num_entries++;
+ }
+
+ EXPECT_EQ(0, num_entries);
+
+ client = TestLoadWithContext(CreateFileSystemURL("foo"),
+ file_system_context.get());
+ ASSERT_FALSE(client->has_received_response());
+ ASSERT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+ AutoMountDirectoryListing) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath mnt_point;
+ SetUpAutoMountContext(&mnt_point);
+ EXPECT_TRUE(base::CreateDirectory(mnt_point));
+ EXPECT_TRUE(base::CreateDirectory(mnt_point.AppendASCII("foo")));
+ EXPECT_EQ(10,
+ base::WriteFile(mnt_point.AppendASCII("bar"), "1234567890", 10));
+
+ auto client =
+ TestLoad(GURL("filesystem:http://automount/external/mnt_name/"));
+
+ ASSERT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_GT(response_text.size(), 0ul);
+
+ std::istringstream in(response_text);
+ std::string line;
+ EXPECT_TRUE(std::getline(in, line)); // |line| contains the temp dir path.
+
+ // Result order is not guaranteed, so sort the results.
+ std::vector<std::string> listing_entries;
+ while (!!std::getline(in, line)) {
+ if (IsDirectoryListingLine(line))
+ listing_entries.push_back(line);
+ }
+
+ ASSERT_EQ(2U, listing_entries.size());
+ std::sort(listing_entries.begin(), listing_entries.end());
+ VerifyListingEntry(listing_entries[0], "bar", "bar", false, 10);
+ VerifyListingEntry(listing_entries[1], "foo", "foo", true, -1);
+
+ EXPECT_TRUE(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ kValidExternalMountPoint));
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, AutoMountInvalidRoot) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath mnt_point;
+ SetUpAutoMountContext(&mnt_point);
+ auto client = TestLoad(GURL("filesystem:http://automount/external/invalid"));
+
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+
+ EXPECT_FALSE(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ "invalid"));
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, AutoMountNoHandler) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath mnt_point;
+ SetUpAutoMountContext(&mnt_point);
+ auto client = TestLoad(GURL("filesystem:http://noauto/external/mnt_name"));
+
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+
+ EXPECT_FALSE(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ kValidExternalMountPoint));
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileTest) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
+ auto client = TestLoad(CreateFileSystemURL("file1.dat"));
+
+ EXPECT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_EQ(kTestFileData, response_text);
+ ASSERT_TRUE(client->response_head().headers) << "No response headers";
+ EXPECT_EQ(200, client->response_head().headers->response_code());
+ std::string cache_control;
+ EXPECT_TRUE(client->response_head().headers->GetNormalizedHeader(
+ "cache-control", &cache_control));
+ EXPECT_EQ("no-cache", cache_control);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+ FileTestFullSpecifiedRange) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ const size_t buffer_size = 4000;
+ std::unique_ptr<char[]> buffer(new char[buffer_size]);
+ FillBuffer(buffer.get(), buffer_size);
+ WriteFile("bigfile", buffer.get(), buffer_size);
+
+ const size_t first_byte_position = 500;
+ const size_t last_byte_position = buffer_size - first_byte_position;
+ std::string partial_buffer_string(buffer.get() + first_byte_position,
+ buffer.get() + last_byte_position + 1);
+
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(
+ net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(first_byte_position, last_byte_position)
+ .GetHeaderValue());
+ auto client = TestLoadWithHeaders(CreateFileSystemURL("bigfile"), &headers);
+
+ ASSERT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_TRUE(partial_buffer_string == response_text);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+ FileTestHalfSpecifiedRange) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ const size_t buffer_size = 4000;
+ std::unique_ptr<char[]> buffer(new char[buffer_size]);
+ FillBuffer(buffer.get(), buffer_size);
+ WriteFile("bigfile", buffer.get(), buffer_size);
+
+ const size_t first_byte_position = 500;
+ std::string partial_buffer_string(buffer.get() + first_byte_position,
+ buffer.get() + buffer_size);
+
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(
+ net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::RightUnbounded(first_byte_position).GetHeaderValue());
+ auto client = TestLoadWithHeaders(CreateFileSystemURL("bigfile"), &headers);
+ ASSERT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ // Don't use EXPECT_EQ, it will print out a lot of garbage if check failed.
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_TRUE(partial_buffer_string == response_text);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+ FileTestMultipleRangesNotSupported) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(net::HttpRequestHeaders::kRange,
+ "bytes=0-5,10-200,200-300");
+ auto client = TestLoadWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+ client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileRangeOutOfBounds) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(net::HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(500, 1000).GetHeaderValue());
+ auto client = TestLoadWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
+
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
+ client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileDirRedirect) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ CreateDirectory("dir");
+ auto client = TestLoad(CreateFileSystemURL("dir"));
+
+ EXPECT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_TRUE(client->has_received_redirect());
+ EXPECT_EQ(301, client->redirect_info().status_code);
+ EXPECT_EQ(CreateFileSystemURL("dir/"), client->redirect_info().new_url);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileNoSuchRoot) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ auto client = TestLoad(GURL("filesystem:http://remote/persistent/somefile"));
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, NoSuchFile) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ auto client = TestLoad(CreateFileSystemURL("somefile"));
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileCancel) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
+ auto client = TestLoadNoRun(CreateFileSystemURL("file1.dat"));
+
+ // client.reset();
+ base::RunLoop().RunUntilIdle();
+ // If we get here, success! we didn't crash!
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileGetMimeType) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ std::string file_data =
+ "<!DOCTYPE HTML><html><head>test</head>"
+ "<body>foo</body></html>";
+ const char kFilename[] = "hoge.html";
+ WriteFile(kFilename, file_data.data(), file_data.size());
+
+ std::string mime_type_direct;
+ base::FilePath::StringType extension =
+ base::FilePath().AppendASCII(kFilename).Extension();
+ if (!extension.empty())
+ extension = extension.substr(1);
+ EXPECT_TRUE(
+ net::GetWellKnownMimeTypeFromExtension(extension, &mime_type_direct));
+
+ auto client = TestLoad(CreateFileSystemURL(kFilename));
+ EXPECT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+
+ EXPECT_EQ(mime_type_direct, client->response_head().mime_type);
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileIncognito) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ WriteFile("file", kTestFileData, base::size(kTestFileData) - 1);
+
+ // Creates a new filesystem context for incognito mode.
+ scoped_refptr<FileSystemContext> file_system_context =
+ CreateIncognitoFileSystemContextForTesting(nullptr, temp_dir_.GetPath());
+
+ // The request should return NOT_FOUND error if it's in incognito mode.
+ auto client = TestLoadWithContext(CreateFileSystemURL("file"),
+ file_system_context.get());
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+
+ // Make sure it returns success with regular (non-incognito) context.
+ client = TestLoad(CreateFileSystemURL("file"));
+ ASSERT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_EQ(kTestFileData, response_text);
+ EXPECT_EQ(200, client->response_head().headers->response_code());
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileAutoMountFileTest) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ SetFileUpAutoMountContext();
+ auto client =
+ TestLoad(GURL("filesystem:http://automount/external/mnt_name/foo"));
+
+ ASSERT_TRUE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ std::string response_text = ReadDataPipe(client->response_body_release());
+ EXPECT_EQ(kTestFileData, response_text);
+ EXPECT_EQ(200, client->response_head().headers->response_code());
+
+ std::string cache_control;
+ EXPECT_TRUE(client->response_head().headers->GetNormalizedHeader(
+ "cache-control", &cache_control));
+ EXPECT_EQ("no-cache", cache_control);
+
+ ASSERT_TRUE(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ kValidExternalMountPoint));
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest,
+ FileAutoMountInvalidRoot) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ SetFileUpAutoMountContext();
+ auto client =
+ TestLoad(GURL("filesystem:http://automount/external/invalid/foo"));
+
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+
+ ASSERT_FALSE(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ "invalid"));
+}
+
+IN_PROC_BROWSER_TEST_F(FileSystemURLLoaderFactoryTest, FileAutoMountNoHandler) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ SetFileUpAutoMountContext();
+ auto client =
+ TestLoad(GURL("filesystem:http://noauto/external/mnt_name/foo"));
+
+ EXPECT_FALSE(client->has_received_response());
+ EXPECT_TRUE(client->has_received_completion());
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, client->completion_status().error_code);
+
+ ASSERT_FALSE(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ kValidExternalMountPoint));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/fileapi/fileapi_browsertest.cc b/chromium/content/browser/fileapi/fileapi_browsertest.cc
index e50f1569a17..617593c8f18 100644
--- a/chromium/content/browser/fileapi/fileapi_browsertest.cc
+++ b/chromium/content/browser/fileapi/fileapi_browsertest.cc
@@ -20,7 +20,7 @@ class FileAPIBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(FileAPIBrowserTest, FileInputChooserParams) {
base::FilePath file;
- EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file));
file = file.AppendASCII("bar");
NavigateToURL(shell(), GetTestUrl(".", "file_input.html"));
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.h b/chromium/content/browser/fileapi/fileapi_message_filter.h
index f699cc7b53d..7188c686f4d 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.h
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.h
@@ -16,7 +16,6 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
-#include "base/files/file_util_proxy.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
index 3093189171d..c996e7c34e2 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -44,13 +44,11 @@ class FileAPIMessageFilterTest : public testing::Test {
file_system_context_ =
CreateFileSystemContextForTesting(nullptr, base::FilePath());
- std::vector<storage::FileSystemType> types;
- file_system_context_->GetFileSystemTypes(&types);
- for (size_t i = 0; i < types.size(); ++i) {
+ for (const storage::FileSystemType& type :
+ file_system_context_->GetFileSystemTypes()) {
ChildProcessSecurityPolicyImpl::GetInstance()
->RegisterFileSystemPermissionPolicy(
- types[i],
- storage::FileSystemContext::GetPermissionPolicy(types[i]));
+ type, storage::FileSystemContext::GetPermissionPolicy(type));
}
blob_storage_context_ = ChromeBlobStorageContext::GetFor(&browser_context_);
diff --git a/chromium/content/browser/find_request_manager.cc b/chromium/content/browser/find_request_manager.cc
index b1d214c35f0..34c5307b0fa 100644
--- a/chromium/content/browser/find_request_manager.cc
+++ b/chromium/content/browser/find_request_manager.cc
@@ -9,9 +9,10 @@
#include "base/containers/queue.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/associated_interface_provider_impl.h"
#include "content/common/frame_messages.h"
-#include "content/common/input_messages.h"
#include "content/public/browser/guest_mode.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
namespace content {
@@ -218,10 +219,8 @@ class FindRequestManager::FrameObserver : public WebContentsObserver {
FindRequestManager::ActivateNearestFindResultState::
ActivateNearestFindResultState() = default;
FindRequestManager::ActivateNearestFindResultState::
-ActivateNearestFindResultState(float x, float y)
- : current_request_id(GetNextID()),
- x(x),
- y(y) {}
+ ActivateNearestFindResultState(float x, float y)
+ : current_request_id(GetNextID()), point(x, y) {}
FindRequestManager::ActivateNearestFindResultState::
~ActivateNearestFindResultState() {}
@@ -271,8 +270,13 @@ void FindRequestManager::Find(int request_id,
void FindRequestManager::StopFinding(StopFindAction action) {
for (WebContentsImpl* contents : contents_->GetWebContentsAndAllInner()) {
- contents->SendToAllFrames(
- new FrameMsg_StopFinding(MSG_ROUTING_NONE, action));
+ for (FrameTreeNode* node : contents->GetFrameTree()->Nodes()) {
+ RenderFrameHostImpl* rfh = node->current_frame_host();
+ if (!CheckFrame(rfh) || !rfh->IsRenderFrameLive())
+ continue;
+ rfh->GetFindInPage()->StopFinding(
+ static_cast<blink::mojom::StopFindAction>(action));
+ }
}
current_session_id_ = kInvalidId;
@@ -284,7 +288,7 @@ void FindRequestManager::StopFinding(StopFindAction action) {
#endif
}
-void FindRequestManager::OnFindReply(RenderFrameHost* rfh,
+void FindRequestManager::OnFindReply(RenderFrameHostImpl* rfh,
int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
@@ -338,8 +342,7 @@ void FindRequestManager::OnFindReply(RenderFrameHost* rfh,
// The new active match is in a different frame than the previous, so
// the previous active frame needs to be informed (to clear its active
// match highlighting).
- active_frame_->Send(new FrameMsg_ClearActiveFindMatch(
- active_frame_->GetRoutingID()));
+ ClearActiveFindMatch();
}
active_frame_ = rfh;
relative_active_match_ordinal_ = active_match_ordinal;
@@ -374,6 +377,19 @@ void FindRequestManager::OnFindReply(RenderFrameHost* rfh,
FinalUpdateReceived(request_id, rfh);
}
+void FindRequestManager::OnActivateNearestFindResultReply(
+ RenderFrameHostImpl* rfh,
+ int request_id,
+ const gfx::Rect& active_match_rect,
+ int number_of_matches,
+ int active_match_ordinal,
+ bool final_update) {
+ if (active_match_ordinal > 0)
+ contents_->SetFocusedFrame(rfh->frame_tree_node(), rfh->GetSiteInstance());
+ OnFindReply(rfh, request_id, number_of_matches, active_match_rect,
+ active_match_ordinal, final_update);
+}
+
void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
if (current_session_id_ == kInvalidId || !CheckFrame(rfh))
return;
@@ -436,6 +452,10 @@ void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
}
}
+void FindRequestManager::ClearActiveFindMatch() {
+ active_frame_->GetFindInPage()->ClearActiveFindMatch();
+}
+
#if defined(OS_ANDROID)
void FindRequestManager::ActivateNearestFindResult(float x, float y) {
if (current_session_id_ == kInvalidId)
@@ -447,20 +467,24 @@ void FindRequestManager::ActivateNearestFindResult(float x, float y) {
// frame) from the point (x, y), defined in find-in-page coordinates.
for (WebContentsImpl* contents : contents_->GetWebContentsAndAllInner()) {
for (FrameTreeNode* node : contents->GetFrameTree()->Nodes()) {
- RenderFrameHost* rfh = node->current_frame_host();
+ RenderFrameHostImpl* rfh = node->current_frame_host();
if (!CheckFrame(rfh) || !rfh->IsRenderFrameLive())
continue;
activate_.pending_replies.insert(rfh);
- rfh->Send(new FrameMsg_GetNearestFindResult(rfh->GetRoutingID(),
- activate_.current_request_id,
- activate_.x, activate_.y));
+ // Lifetime of FindRequestManager > RenderFrameHost > Mojo connection,
+ // so it's safe to bind |this| and |rfh|.
+ rfh->GetFindInPage()->GetNearestFindResult(
+ activate_.point,
+ base::BindOnce(&FindRequestManager::OnGetNearestFindResultReply,
+ base::Unretained(this), rfh,
+ activate_.current_request_id));
}
}
}
-void FindRequestManager::OnGetNearestFindResultReply(RenderFrameHost* rfh,
+void FindRequestManager::OnGetNearestFindResultReply(RenderFrameHostImpl* rfh,
int request_id,
float distance) {
if (request_id != activate_.current_request_id ||
@@ -484,7 +508,7 @@ void FindRequestManager::RequestFindMatchRects(int current_version) {
// Request the latest find match rects from each frame.
for (WebContentsImpl* contents : contents_->GetWebContentsAndAllInner()) {
for (FrameTreeNode* node : contents->GetFrameTree()->Nodes()) {
- RenderFrameHost* rfh = node->current_frame_host();
+ RenderFrameHostImpl* rfh = node->current_frame_host();
if (!CheckFrame(rfh) || !rfh->IsRenderFrameLive())
continue;
@@ -493,7 +517,9 @@ void FindRequestManager::RequestFindMatchRects(int current_version) {
auto it = match_rects_.frame_rects.find(rfh);
int version = (it != match_rects_.frame_rects.end()) ? it->second.version
: kInvalidId;
- rfh->Send(new FrameMsg_FindMatchRects(rfh->GetRoutingID(), version));
+ rfh->GetFindInPage()->FindMatchRects(
+ version, base::BindOnce(&FindRequestManager::OnFindMatchRectsReply,
+ base::Unretained(this), rfh));
}
}
}
@@ -752,9 +778,14 @@ void FindRequestManager::RemoveNearestFindResultPendingReply(
activate_.pending_replies.erase(it);
if (activate_.pending_replies.empty() &&
CheckFrame(activate_.nearest_frame)) {
- activate_.nearest_frame->Send(new FrameMsg_ActivateNearestFindResult(
- activate_.nearest_frame->GetRoutingID(),
- current_session_id_, activate_.x, activate_.y));
+ // Lifetime of FindRequestManager > activate_.nearest_frame > Mojo
+ // connection, so it's safe to bind |this| and |activate_.nearest_frame|
+ activate_.nearest_frame->GetFindInPage()->ActivateNearestFindResult(
+ activate_.point,
+ base::BindOnce(&FindRequestManager::OnActivateNearestFindResultReply,
+ base::Unretained(this),
+ base::Unretained(activate_.nearest_frame),
+ current_session_id_));
}
}
diff --git a/chromium/content/browser/find_request_manager.h b/chromium/content/browser/find_request_manager.h
index 1939bc57742..ae95c1325af 100644
--- a/chromium/content/browser/find_request_manager.h
+++ b/chromium/content/browser/find_request_manager.h
@@ -21,6 +21,7 @@
namespace content {
class RenderFrameHost;
+class RenderFrameHostImpl;
class WebContentsImpl;
// FindRequestManager manages all of the find-in-page requests/replies
@@ -47,26 +48,37 @@ class CONTENT_EXPORT FindRequestManager {
// Called when a reply is received from a frame with the results from a
// find request.
- void OnFindReply(RenderFrameHost* rfh,
+ void OnFindReply(RenderFrameHostImpl* rfh,
int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update);
+ // Called when a reply for ActivateNearestFindResult is received.
+ void OnActivateNearestFindResultReply(RenderFrameHostImpl* rfh,
+ int request_id,
+ const gfx::Rect& active_match_rect,
+ int number_of_matches,
+ int active_match_ordinal,
+ bool final_update);
+
// Removes a frame from the set of frames being searched. This should be
// called whenever a frame is discovered to no longer exist.
void RemoveFrame(RenderFrameHost* rfh);
+ // Tells active frame to clear the active match highlighting.
+ void ClearActiveFindMatch();
+
#if defined(OS_ANDROID)
// Selects and zooms to the find result nearest to the point (x, y), defined
// in find-in-page coordinates.
void ActivateNearestFindResult(float x, float y);
// Called when a reply is received from a frame in response to the
- // GetNearestFindResult IPC.
- void OnGetNearestFindResultReply(RenderFrameHost* rfh,
- int nearest_find_result_request_id,
+ // GetNearestFindResult mojo call.
+ void OnGetNearestFindResultReply(RenderFrameHostImpl* rfh,
+ int request_id,
float distance);
// Requests the rects of the current find matches from the renderer process.
@@ -178,17 +190,13 @@ class CONTENT_EXPORT FindRequestManager {
// its replies.
int current_request_id = kInvalidId;
- // The x value of the requested point, in find-in-page coordinates.
- float x = 0.0f;
-
- // The y value of the requested point, in find-in-page coordinates.
- float y = 0.0f;
+ // The value of the requested point, in find-in-page coordinates.
+ gfx::PointF point = gfx::PointF(0.0f, 0.0f);
- // The distance to the nearest result found so far.
float nearest_distance = FLT_MAX;
// The frame containing the nearest result found so far.
- RenderFrameHost* nearest_frame = nullptr;
+ RenderFrameHostImpl* nearest_frame = nullptr;
// Nearest find result replies are still pending for these frames.
std::unordered_set<RenderFrameHost*> pending_replies;
@@ -286,7 +294,7 @@ class CONTENT_EXPORT FindRequestManager {
int number_of_matches_;
// The frame containing the active match, if one exists, or nullptr otherwise.
- RenderFrameHost* active_frame_;
+ RenderFrameHostImpl* active_frame_;
// The active match ordinal relative to the matches found in its own frame.
int relative_active_match_ordinal_;
diff --git a/chromium/content/browser/frame_host/OWNERS b/chromium/content/browser/frame_host/OWNERS
index 6f288e7a3bc..e9d9c4fcfaf 100644
--- a/chromium/content/browser/frame_host/OWNERS
+++ b/chromium/content/browser/frame_host/OWNERS
@@ -1 +1,4 @@
# COMPONENT: Internals>Sandbox>SiteIsolation
+
+# For surface ID propagation and synchronization
+per-file render_widget_host_view_guest*=fsamuel@chromium.org
diff --git a/chromium/content/browser/frame_host/ancestor_throttle.cc b/chromium/content/browser/frame_host/ancestor_throttle.cc
index 86f1df5ad43..129c3777020 100644
--- a/chromium/content/browser/frame_host/ancestor_throttle.cc
+++ b/chromium/content/browser/frame_host/ancestor_throttle.cc
@@ -58,7 +58,14 @@ enum XFrameOptionsHistogram {
// The 'frame-ancestors' CSP directive should take effect instead.
BYPASS = 8,
- XFRAMEOPTIONS_HISTOGRAM_MAX = BYPASS
+ // Navigation would have been blocked if we applied 'X-Frame-Options' to
+ // redirects.
+ //
+ // TODO(mkwst): Rename this when we make a decision around
+ // https://crbug.com/835465.
+ REDIRECT_WOULD_BE_BLOCKED = 9,
+
+ XFRAMEOPTIONS_HISTOGRAM_MAX = REDIRECT_WOULD_BE_BLOCKED
};
void RecordXFrameOptionsUsage(XFrameOptionsHistogram usage) {
@@ -99,7 +106,31 @@ std::unique_ptr<NavigationThrottle> AncestorThrottle::MaybeCreateThrottleFor(
AncestorThrottle::~AncestorThrottle() {}
NavigationThrottle::ThrottleCheckResult
+AncestorThrottle::WillRedirectRequest() {
+ // During a redirect, we don't know which RenderFrameHost we'll end up in,
+ // so we can't log reliably to the console. We should be able to work around
+ // this iff we decide to ship the redirect-blocking behavior, but for now
+ // we'll just skip the console-logging bits to collect metrics.
+ NavigationThrottle::ThrottleCheckResult result =
+ ProcessResponseImpl(LoggingDisposition::DO_NOT_LOG_TO_CONSOLE);
+
+ if (result.action() == NavigationThrottle::BLOCK_RESPONSE)
+ RecordXFrameOptionsUsage(REDIRECT_WOULD_BE_BLOCKED);
+
+ // TODO(mkwst): We need to decide whether we'll be able to get away with
+ // tightening the XFO check to include redirect responses once we have a
+ // feel for the REDIRECT_WOULD_BE_BLOCKED numbers we're collecting above.
+ // Until then, we'll allow the response to proceed: https://crbug.com/835465.
+ return NavigationThrottle::PROCEED;
+}
+
+NavigationThrottle::ThrottleCheckResult
AncestorThrottle::WillProcessResponse() {
+ return ProcessResponseImpl(LoggingDisposition::LOG_TO_CONSOLE);
+}
+
+NavigationThrottle::ThrottleCheckResult AncestorThrottle::ProcessResponseImpl(
+ LoggingDisposition logging) {
DCHECK(!navigation_handle()->IsInMainFrame());
NavigationHandleImpl* handle =
@@ -116,18 +147,21 @@ AncestorThrottle::WillProcessResponse() {
switch (disposition) {
case HeaderDisposition::CONFLICT:
- ParseError(header_value, disposition);
+ if (logging == LoggingDisposition::LOG_TO_CONSOLE)
+ ParseError(header_value, disposition);
RecordXFrameOptionsUsage(CONFLICT);
return NavigationThrottle::BLOCK_RESPONSE;
case HeaderDisposition::INVALID:
- ParseError(header_value, disposition);
+ if (logging == LoggingDisposition::LOG_TO_CONSOLE)
+ ParseError(header_value, disposition);
RecordXFrameOptionsUsage(INVALID);
// TODO(mkwst): Consider failing here.
return NavigationThrottle::PROCEED;
case HeaderDisposition::DENY:
- ConsoleError(disposition);
+ if (logging == LoggingDisposition::LOG_TO_CONSOLE)
+ ConsoleError(disposition);
RecordXFrameOptionsUsage(DENY);
return NavigationThrottle::BLOCK_RESPONSE;
@@ -139,7 +173,8 @@ AncestorThrottle::WillProcessResponse() {
while (parent) {
if (!parent->current_origin().IsSameOriginWith(current_origin)) {
RecordXFrameOptionsUsage(SAMEORIGIN_BLOCKED);
- ConsoleError(disposition);
+ if (logging == LoggingDisposition::LOG_TO_CONSOLE)
+ ConsoleError(disposition);
// TODO(mkwst): Stop recording this metric once we convince other
// vendors to follow our lead with XFO: SAMEORIGIN processing.
diff --git a/chromium/content/browser/frame_host/ancestor_throttle.h b/chromium/content/browser/frame_host/ancestor_throttle.h
index bef0114b8aa..c0c3d7d0dc9 100644
--- a/chromium/content/browser/frame_host/ancestor_throttle.h
+++ b/chromium/content/browser/frame_host/ancestor_throttle.h
@@ -38,16 +38,21 @@ class CONTENT_EXPORT AncestorThrottle : public NavigationThrottle {
~AncestorThrottle() override;
+ NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override;
NavigationThrottle::ThrottleCheckResult WillProcessResponse() override;
const char* GetNameForLogging() override;
private:
+ enum class LoggingDisposition { LOG_TO_CONSOLE, DO_NOT_LOG_TO_CONSOLE };
+
FRIEND_TEST_ALL_PREFIXES(AncestorThrottleTest, ParsingXFrameOptions);
FRIEND_TEST_ALL_PREFIXES(AncestorThrottleTest, ErrorsParsingXFrameOptions);
FRIEND_TEST_ALL_PREFIXES(AncestorThrottleTest,
IgnoreWhenFrameAncestorsPresent);
explicit AncestorThrottle(NavigationHandle* handle);
+ NavigationThrottle::ThrottleCheckResult ProcessResponseImpl(
+ LoggingDisposition);
void ParseError(const std::string& value, HeaderDisposition disposition);
void ConsoleError(HeaderDisposition disposition);
diff --git a/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc b/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc
new file mode 100644
index 00000000000..f25ed52f307
--- /dev/null
+++ b/chromium/content/browser/frame_host/blocked_scheme_navigation_browsertest.cc
@@ -0,0 +1,1418 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base64.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/strings/pattern.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "build/buildflag.h"
+#include "content/browser/site_per_process_browsertest.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/download_test_observer.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_download_manager_delegate.h"
+#include "net/base/escape.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "content/public/browser/plugin_service.h"
+#include "content/public/common/webplugininfo.h"
+#endif
+
+namespace content {
+
+namespace {
+
+// The pattern to catch messages printed by the browser when navigation to a
+// URL is blocked.
+const char kNavigationBlockedMessage[] =
+ "Not allowed to navigate top frame to %s URL:*";
+
+// The message printed by the data or filesystem URL when it successfully
+// navigates.
+const char kNavigationSuccessfulMessage[] = "NAVIGATION_SUCCESSFUL";
+
+// A "Hello World" pdf.
+const char kPDF[] =
+ "%PDF-1.7\n"
+ "1 0 obj << /Type /Page /Parent 3 0 R /Resources 5 0 R /Contents 2 0 R >>\n"
+ "endobj\n"
+ "2 0 obj << /Length 51 >>\n"
+ " stream BT\n"
+ " /F1 12 Tf\n"
+ " 1 0 0 1 100 20 Tm\n"
+ " (Hello World)Tj\n"
+ " ET\n"
+ " endstream\n"
+ "endobj\n"
+ "3 0 obj << /Type /Pages /Kids [ 1 0 R ] /Count 1 /MediaBox [ 0 0 300 50] "
+ ">>\n"
+ "endobj\n"
+ "4 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont/Arial >>\n"
+ "endobj\n"
+ "5 0 obj << /ProcSet[/PDF/Text] /Font <</F1 4 0 R >> >>\n"
+ "endobj\n"
+ "6 0 obj << /Type /Catalog /Pages 3 0 R >>\n"
+ "endobj\n"
+ "trailer << /Root 6 0 R >>\n";
+
+enum ExpectedNavigationStatus { NAVIGATION_BLOCKED, NAVIGATION_ALLOWED };
+
+// This class is similar to ConsoleObserverDelegate in that it listens and waits
+// for specific console messages. The difference from ConsoleObserverDelegate is
+// that this class immediately stops waiting if it sees a message matching
+// fail_pattern, instead of waiting for a message matching success_pattern.
+class BlockedURLWarningConsoleObserverDelegate : public WebContentsDelegate {
+ public:
+ enum Status {
+ NO_MESSAGE,
+ SAW_SUCCESS_MESSAGE,
+ SAW_FAILURE_MESSAGE,
+ };
+ BlockedURLWarningConsoleObserverDelegate(WebContents* web_contents,
+ const std::string& success_filter,
+ const std::string& fail_filter)
+ : web_contents_(web_contents),
+ success_filter_(success_filter),
+ fail_filter_(fail_filter),
+ status_(NO_MESSAGE) {}
+
+ ~BlockedURLWarningConsoleObserverDelegate() override {}
+
+ // WebContentsDelegate method:
+ bool DidAddMessageToConsole(WebContents* source,
+ int32_t level,
+ const base::string16& message,
+ int32_t line_no,
+ const base::string16& source_id) override {
+ DCHECK(source == web_contents_);
+ const std::string ascii_message = base::UTF16ToASCII(message);
+ if (base::MatchPattern(ascii_message, fail_filter_)) {
+ status_ = SAW_FAILURE_MESSAGE;
+ run_loop_.Quit();
+ }
+ if (base::MatchPattern(ascii_message, success_filter_)) {
+ status_ = SAW_SUCCESS_MESSAGE;
+ run_loop_.Quit();
+ }
+ return false;
+ }
+
+ void Wait() { run_loop_.Run(); }
+
+ Status status() const { return status_; }
+
+ private:
+ WebContents* web_contents_;
+ const std::string success_filter_;
+ const std::string fail_filter_;
+ base::RunLoop run_loop_;
+ Status status_;
+};
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+// This class registers a fake PDF plugin handler so that navigations with a PDF
+// mime type end up with a navigation and don't simply download the file.
+class ScopedPluginRegister {
+ public:
+ ScopedPluginRegister(content::PluginService* plugin_service)
+ : plugin_service_(plugin_service) {
+ const char kPluginName[] = "PDF";
+ const char kPdfMimeType[] = "application/pdf";
+ const char kPdfFileType[] = "pdf";
+ WebPluginInfo plugin_info;
+ plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
+ plugin_info.name = base::ASCIIToUTF16(kPluginName);
+ plugin_info.mime_types.push_back(
+ WebPluginMimeType(kPdfMimeType, kPdfFileType, std::string()));
+ plugin_service_->RegisterInternalPlugin(plugin_info, false);
+ plugin_service_->RefreshPlugins();
+ }
+
+ ~ScopedPluginRegister() {
+ std::vector<WebPluginInfo> plugins;
+ plugin_service_->GetInternalPlugins(&plugins);
+ EXPECT_EQ(1u, plugins.size());
+ plugin_service_->UnregisterInternalPlugin(plugins[0].path);
+ plugin_service_->RefreshPlugins();
+
+ plugins.clear();
+ plugin_service_->GetInternalPlugins(&plugins);
+ EXPECT_TRUE(plugins.empty());
+ }
+
+ private:
+ content::PluginService* plugin_service_;
+};
+#endif // BUILDFLAG(ENABLE_PLUGINS)
+
+} // namespace
+
+class BlockedSchemeNavigationBrowserTest
+ : public ContentBrowserTest,
+ public testing::WithParamInterface<const char*> {
+ public:
+#if BUILDFLAG(ENABLE_PLUGINS)
+ BlockedSchemeNavigationBrowserTest()
+ : scoped_plugin_register_(PluginService::GetInstance()) {}
+#else
+ BlockedSchemeNavigationBrowserTest() {}
+#endif // BUILDFLAG(ENABLE_PLUGINS)
+
+ protected:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ base::FilePath path;
+ ASSERT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &path));
+ path = path.AppendASCII("data_url_navigations.html");
+ ASSERT_TRUE(base::PathExists(path));
+
+ std::string contents;
+ ASSERT_TRUE(base::ReadFileToString(path, &contents));
+ data_url_ = GURL(std::string("data:text/html,") + contents);
+
+ ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
+ ShellDownloadManagerDelegate* delegate =
+ static_cast<ShellDownloadManagerDelegate*>(
+ shell()
+ ->web_contents()
+ ->GetBrowserContext()
+ ->GetDownloadManagerDelegate());
+ delegate->SetDownloadBehaviorForTesting(downloads_directory_.GetPath());
+ }
+
+ void Navigate(const GURL& url) {
+ content::DOMMessageQueue message_queue;
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ std::string message;
+ while (message_queue.WaitForMessage(&message)) {
+ if (message == "\"READY\"")
+ break;
+ }
+ }
+
+ // Creates a filesystem: URL on the current origin.
+ GURL CreateFileSystemUrl(const std::string& filename,
+ const std::string& content,
+ const std::string& mime_type) {
+ const char kCreateFilesystemUrlScript[] =
+ "var contents = `%s`;"
+ "webkitRequestFileSystem(window.TEMPORARY, 1024, fs => {"
+ " fs.root.getFile('%s', {create: true}, entry => {"
+ " entry.createWriter(w => {"
+ " w.write(new Blob([contents], {type: '%s'}));"
+ " w.onwrite = function(evt) {"
+ " domAutomationController.send(entry.toURL());"
+ " }"
+ " });"
+ " });"
+ "});";
+ std::string filesystem_url_string;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell()->web_contents()->GetMainFrame(),
+ base::StringPrintf(kCreateFilesystemUrlScript, content.c_str(),
+ filename.c_str(), mime_type.c_str()),
+ &filesystem_url_string));
+ GURL filesystem_url(filesystem_url_string);
+ EXPECT_TRUE(filesystem_url.is_valid());
+ EXPECT_TRUE(filesystem_url.SchemeIsFileSystem());
+ return filesystem_url;
+ }
+
+ bool IsDataURLTest() const {
+ return std::string(url::kDataScheme) == GetParam();
+ }
+
+ GURL CreateEmptyURLWithBlockedScheme() {
+ return CreateURLWithBlockedScheme("empty.html", "<html></html>",
+ "text/html");
+ }
+
+ GURL CreateURLWithBlockedScheme(const std::string& filename,
+ const std::string& content,
+ const std::string& mimetype) {
+ if (IsDataURLTest()) {
+ return GURL(
+ base::StringPrintf("data:%s,%s", mimetype.c_str(), content.c_str()));
+ }
+ // We need an origin to create a filesystem URL on, so navigate to one.
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("a.com", "/simple_page.html"));
+ return CreateFileSystemUrl(filename, content, mimetype);
+ }
+
+ GURL GetTestURL() {
+ return embedded_test_server()->GetURL(
+ base::StringPrintf("/%s_url_navigations.html", GetParam()));
+ }
+
+ // Adds an iframe to |rfh| pointing to |url|.
+ void AddIFrame(RenderFrameHost* rfh, const GURL& url) {
+ content::DOMMessageQueue message_queue;
+ const std::string javascript = base::StringPrintf(
+ "f = document.createElement('iframe'); f.src = '%s';"
+ "document.body.appendChild(f);",
+ url.spec().c_str());
+ TestNavigationObserver observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+ observer.Wait();
+ std::string message;
+ while (message_queue.WaitForMessage(&message)) {
+ if (message == "\"READY\"")
+ break;
+ }
+ }
+
+ // Runs |javascript| on the first child frame and checks for a navigation.
+ void TestNavigationFromFrame(
+ const std::string& scheme,
+ const std::string& javascript,
+ ExpectedNavigationStatus expected_navigation_status) {
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckNavigation(shell(), child, scheme, javascript,
+ expected_navigation_status);
+ }
+
+ // Runs |javascript| on the first child frame and expects a download to occur.
+ void TestDownloadFromFrame(const std::string& javascript) {
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckDownload(child, javascript);
+ }
+
+ // Runs |javascript| on the first child frame and checks for a navigation to
+ // the PDF file pointed by the test case.
+ void TestPDFNavigationFromFrame(
+ const std::string& scheme,
+ const std::string& javascript,
+ ExpectedNavigationStatus expected_navigation_status) {
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckPDFNavigation(child, scheme, javascript,
+ expected_navigation_status);
+ }
+
+ // Same as TestNavigationFromFrame, but instead of navigating, the child frame
+ // tries to open a new window with a blocked URL (data or filesystem)
+ void TestWindowOpenFromFrame(
+ const std::string& scheme,
+ const std::string& javascript,
+ ExpectedNavigationStatus expected_navigation_status) {
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckWindowOpen(child, scheme, javascript,
+ expected_navigation_status);
+ }
+
+ // Executes |javascript| on |rfh| and waits for a console message based on
+ // |expected_navigation_status|.
+ // - Blocked navigations should print kDataUrlBlockedPattern.
+ // - Allowed navigations should print kNavigationSuccessfulMessage.
+ void ExecuteScriptAndCheckNavigation(
+ Shell* shell,
+ RenderFrameHost* rfh,
+ const std::string& scheme,
+ const std::string& javascript,
+ ExpectedNavigationStatus expected_navigation_status) {
+ if (expected_navigation_status == NAVIGATION_ALLOWED)
+ ExecuteScriptAndCheckNavigationAllowed(shell, rfh, javascript, scheme);
+ else
+ ExecuteScriptAndCheckNavigationBlocked(shell, rfh, javascript, scheme);
+ }
+
+ protected:
+ // Similar to ExecuteScriptAndCheckNavigation(), but doesn't wait for a
+ // console message if the navigation is expected to be allowed (this is
+ // because PDF files can't print to the console).
+ void ExecuteScriptAndCheckPDFNavigation(
+ RenderFrameHost* rfh,
+ const std::string& scheme,
+ const std::string& javascript,
+ ExpectedNavigationStatus expected_navigation_status) {
+ const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
+
+ const std::string expected_message =
+ (expected_navigation_status == NAVIGATION_ALLOWED)
+ ? std::string()
+ : base::StringPrintf(kNavigationBlockedMessage, scheme.c_str());
+
+ std::unique_ptr<ConsoleObserverDelegate> console_delegate;
+ if (!expected_message.empty()) {
+ console_delegate.reset(new ConsoleObserverDelegate(
+ shell()->web_contents(), expected_message));
+ shell()->web_contents()->SetDelegate(console_delegate.get());
+ }
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+
+ if (console_delegate) {
+ console_delegate->Wait();
+ shell()->web_contents()->SetDelegate(nullptr);
+ }
+
+ switch (expected_navigation_status) {
+ case NAVIGATION_ALLOWED:
+ navigation_observer.Wait();
+ // The new page should have the expected scheme.
+ EXPECT_TRUE(
+ shell()->web_contents()->GetLastCommittedURL().SchemeIs(scheme));
+ EXPECT_TRUE(navigation_observer.last_navigation_url().SchemeIs(scheme));
+ EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
+ break;
+
+ case NAVIGATION_BLOCKED:
+ // Original page shouldn't navigate away.
+ EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
+ EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
+ break;
+
+ default:
+ NOTREACHED();
+ }
+ }
+
+ // Executes |javascript| on |rfh| and waits for a new window to be opened.
+ // Does not check for console messages (it's currently not possible to
+ // concurrently wait for a new shell to be created and a console message to be
+ // printed on that new shell).
+ void ExecuteScriptAndCheckWindowOpen(
+ RenderFrameHost* rfh,
+ const std::string& scheme,
+ const std::string& javascript,
+ ExpectedNavigationStatus expected_navigation_status) {
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ switch (expected_navigation_status) {
+ case NAVIGATION_ALLOWED:
+ EXPECT_TRUE(
+ new_shell->web_contents()->GetLastCommittedURL().SchemeIs(scheme));
+ break;
+
+ case NAVIGATION_BLOCKED:
+ EXPECT_TRUE(
+ new_shell->web_contents()->GetLastCommittedURL().is_empty());
+ break;
+
+ default:
+ NOTREACHED();
+ }
+ }
+
+ // Executes |javascript| on |rfh| and waits for a download to be started by
+ // a window.open call.
+ void ExecuteScriptAndCheckWindowOpenDownload(RenderFrameHost* rfh,
+ const std::string& javascript) {
+ const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
+ ShellAddedObserver new_shell_observer;
+ DownloadManager* download_manager = BrowserContext::GetDownloadManager(
+ shell()->web_contents()->GetBrowserContext());
+
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+ Shell* new_shell = new_shell_observer.GetShell();
+
+ DownloadTestObserverTerminal download_observer(
+ download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+
+ WaitForLoadStop(new_shell->web_contents());
+ // If no download happens, this will timeout.
+ download_observer.WaitForFinished();
+
+ EXPECT_TRUE(
+ new_shell->web_contents()->GetLastCommittedURL().spec().empty());
+ // No navigation should commit.
+ EXPECT_FALSE(
+ new_shell->web_contents()->GetController().GetLastCommittedEntry());
+ // Original page shouldn't navigate away.
+ EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
+ }
+
+ // Executes |javascript| on |rfh| and waits for a download to be started.
+ void ExecuteScriptAndCheckDownload(RenderFrameHost* rfh,
+ const std::string& javascript) {
+ const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
+ DownloadManager* download_manager = BrowserContext::GetDownloadManager(
+ shell()->web_contents()->GetBrowserContext());
+ DownloadTestObserverTerminal download_observer(
+ download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+ // If no download happens, this will timeout.
+ download_observer.WaitForFinished();
+
+ // Original page shouldn't navigate away.
+ EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
+ }
+
+ // Initiates a browser initiated navigation to |url| and waits for a download
+ // to be started.
+ void NavigateAndCheckDownload(const GURL& url) {
+ const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
+ DownloadManager* download_manager = BrowserContext::GetDownloadManager(
+ shell()->web_contents()->GetBrowserContext());
+ DownloadTestObserverTerminal download_observer(
+ download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+ NavigateToURL(shell(), url);
+
+ // If no download happens, this will timeout.
+ download_observer.WaitForFinished();
+
+ // Original page shouldn't navigate away.
+ EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
+ }
+
+ // data URL form of the file at content/test/data/data_url_navigations.html
+ GURL data_url() const { return data_url_; }
+
+ std::string GetNavigationBlockedMessage() const {
+ return base::StringPrintf(kNavigationBlockedMessage, GetParam());
+ }
+
+ private:
+ // Executes |javascript| on |rfh| and waits for a console message that
+ // indicates the navigation has completed. |scheme| is the scheme being
+ // tested.
+ static void ExecuteScriptAndCheckNavigationAllowed(
+ Shell* shell,
+ RenderFrameHost* rfh,
+ const std::string& javascript,
+ const std::string& scheme) {
+ // Should see success message, should never see blocked message.
+ const std::string blocked_message =
+ base::StringPrintf(kNavigationBlockedMessage, scheme.c_str());
+ BlockedURLWarningConsoleObserverDelegate console_delegate(
+ shell->web_contents(), kNavigationSuccessfulMessage, blocked_message);
+ shell->web_contents()->SetDelegate(&console_delegate);
+
+ TestNavigationObserver navigation_observer(shell->web_contents());
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+ console_delegate.Wait();
+ EXPECT_EQ(BlockedURLWarningConsoleObserverDelegate::SAW_SUCCESS_MESSAGE,
+ console_delegate.status());
+ shell->web_contents()->SetDelegate(nullptr);
+ navigation_observer.Wait();
+
+ // The new page should have the expected scheme.
+ EXPECT_EQ(navigation_observer.last_navigation_url(),
+ shell->web_contents()->GetLastCommittedURL());
+ EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
+ }
+
+ // Similar to ExecuteScriptAndCheckNavigationAllowed. Executes |javascript| on
+ // |rfh| and waits for a console message that indicates the navigation has
+ // been blocked. |scheme| is the scheme being tested.
+ static void ExecuteScriptAndCheckNavigationBlocked(
+ Shell* shell,
+ RenderFrameHost* rfh,
+ const std::string& javascript,
+ const std::string& scheme) {
+ const GURL original_url(shell->web_contents()->GetLastCommittedURL());
+
+ // Should see blocked message, should never see success message.
+ const std::string blocked_message =
+ base::StringPrintf(kNavigationBlockedMessage, scheme.c_str());
+ BlockedURLWarningConsoleObserverDelegate console_delegate(
+ shell->web_contents(), kNavigationSuccessfulMessage, blocked_message);
+ shell->web_contents()->SetDelegate(&console_delegate);
+
+ TestNavigationObserver navigation_observer(shell->web_contents());
+ EXPECT_TRUE(ExecuteScript(rfh, javascript));
+ console_delegate.Wait();
+ EXPECT_EQ(BlockedURLWarningConsoleObserverDelegate::SAW_FAILURE_MESSAGE,
+ console_delegate.status());
+ shell->web_contents()->SetDelegate(nullptr);
+
+ // Original page shouldn't navigate away.
+ EXPECT_EQ(original_url, shell->web_contents()->GetLastCommittedURL());
+ EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
+ }
+
+ base::ScopedTempDir downloads_directory_;
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ ScopedPluginRegister scoped_plugin_register_;
+#endif // BUILDFLAG(ENABLE_PLUGINS)
+
+ GURL data_url_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlockedSchemeNavigationBrowserTest);
+};
+
+INSTANTIATE_TEST_CASE_P(,
+ BlockedSchemeNavigationBrowserTest,
+ ::testing::Values(url::kDataScheme,
+ url::kFileSystemScheme));
+
+////////////////////////////////////////////////////////////////////////////////
+// Blocked schemes with HTML mimetype
+//
+// Tests that a browser initiated navigation to a blocked scheme doesn't show a
+// console warning and is not blocked.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ BrowserInitiated_Allow) {
+ const GURL kUrl(CreateURLWithBlockedScheme(
+ "test.html",
+ "<html><script>console.log('NAVIGATION_SUCCESSFUL');</script></html>",
+ "text/html"));
+ if (IsDataURLTest()) {
+ BlockedURLWarningConsoleObserverDelegate console_delegate(
+ shell()->web_contents(), kNavigationSuccessfulMessage,
+ GetNavigationBlockedMessage());
+
+ shell()->web_contents()->SetDelegate(&console_delegate);
+ EXPECT_TRUE(NavigateToURL(shell(), kUrl));
+ console_delegate.Wait();
+ shell()->web_contents()->SetDelegate(nullptr);
+ EXPECT_TRUE(
+ shell()->web_contents()->GetLastCommittedURL().SchemeIs(GetParam()));
+
+ } else {
+ // Navigate to a.com and create a filesystem URL on it.
+ // For filesystem: tests we create a new shell and navigate that shell to
+ // the filesystem: URL created above. Navigating the a tab away from the
+ // original page may clear all filesystem: URLs associated with that origin,
+ // so we keep the origin around in the original shell.
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(), "window.open('about:blank');"));
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ BlockedURLWarningConsoleObserverDelegate console_delegate(
+ new_shell->web_contents(), kNavigationSuccessfulMessage,
+ GetNavigationBlockedMessage());
+ new_shell->web_contents()->SetDelegate(&console_delegate);
+ EXPECT_TRUE(NavigateToURL(new_shell, kUrl));
+
+ console_delegate.Wait();
+ new_shell->web_contents()->SetDelegate(nullptr);
+ EXPECT_TRUE(
+ new_shell->web_contents()->GetLastCommittedURL().SchemeIs(GetParam()));
+ }
+}
+
+// Tests that a content initiated navigation to a blocked scheme is blocked.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ HTML_Navigation_Block) {
+ Navigate(GetTestURL());
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('navigate-top-frame-to-html').click()",
+ NAVIGATION_BLOCKED);
+}
+
+class DataUrlNavigationBrowserTestWithFeatureFlag
+ : public BlockedSchemeNavigationBrowserTest {
+ public:
+ DataUrlNavigationBrowserTestWithFeatureFlag() {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAllowContentInitiatedDataUrlNavigations);
+ }
+ ~DataUrlNavigationBrowserTestWithFeatureFlag() override {}
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(DataUrlNavigationBrowserTestWithFeatureFlag);
+};
+
+// Tests that a content initiated navigation to a data URL is allowed if
+// blocking is disabled with a feature flag.
+IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTestWithFeatureFlag,
+ HTML_Navigation_Allow_FeatureFlag) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("/data_url_navigations.html")));
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), url::kDataScheme,
+ "document.getElementById('navigate-top-frame-to-html').click()",
+ NAVIGATION_ALLOWED);
+}
+
+// Tests that a window.open to a blocked scheme with HTML mime type is blocked.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ HTML_WindowOpen_Block) {
+ Navigate(GetTestURL());
+ ExecuteScriptAndCheckWindowOpen(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('window-open-html').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Tests that a form post to a blocked scheme with HTML mime type is blocked.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ HTML_FormPost_Block) {
+ Navigate(GetTestURL());
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('form-post-to-html').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Tests that clicking <a download> link downloads the URL even with a blocked
+// scheme.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest, HTML_Download) {
+ Navigate(GetTestURL());
+ ExecuteScriptAndCheckDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('download-link').click()");
+}
+
+// Tests that navigating the main frame to a blocked scheme with HTML mimetype
+// from a subframe is blocked.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ HTML_NavigationFromFrame_Block) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(
+ shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL(
+ "b.com", base::StringPrintf("/%s_url_navigations.html", GetParam())));
+
+ TestNavigationFromFrame(
+ GetParam(),
+ "document.getElementById('navigate-top-frame-to-html').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Tests that opening a new window with a blocked scheme from a subframe is
+// blocked.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ HTML_WindowOpenFromFrame_Block) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(
+ shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL(
+ "b.com", base::StringPrintf("/%s_url_navigations.html", GetParam())));
+
+ TestWindowOpenFromFrame(GetParam(),
+ "document.getElementById('window-open-html').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Tests that navigation to a blocked scheme is blocked even if the top frame is
+// already has a blocked scheme.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ HTML_Navigation_SameScheme_Block) {
+ if (IsDataURLTest()) {
+ EXPECT_TRUE(NavigateToURL(shell(), data_url()));
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), url::kDataScheme,
+ "document.getElementById('navigate-top-frame-to-html').click()",
+ NAVIGATION_BLOCKED);
+ } else {
+ // We need an origin to create a filesystem URL on, so navigate to one.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ const GURL kFilesystemURL1(
+ CreateFileSystemUrl("empty1.html", "empty1", "text/html"));
+ const GURL kFilesystemURL2(
+ CreateFileSystemUrl("empty2.html", "empty2", "text/html"));
+
+ // Create a new shell and navigate that shell to the filesystem: URL created
+ // above. Navigating the a tab away from the
+ // original page may clear all filesystem: URLs associated with that origin,
+ // so we keep the origin around in the original shell.
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(), "window.open('about:blank');"));
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ EXPECT_TRUE(NavigateToURL(new_shell, kFilesystemURL1));
+ ExecuteScriptAndCheckNavigation(
+ new_shell, new_shell->web_contents()->GetMainFrame(),
+ url::kFileSystemScheme,
+ base::StringPrintf("window.location='%s';",
+ kFilesystemURL2.spec().c_str()),
+ NAVIGATION_BLOCKED);
+ }
+}
+
+// Tests that a form post to a blocked scheme with HTML mime type is blocked
+// even if the top frame is already a blocked scheme.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ HTML_FormPost_SameScheme_Block) {
+ if (IsDataURLTest()) {
+ EXPECT_TRUE(NavigateToURL(shell(), data_url()));
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), url::kDataScheme,
+ "document.getElementById('form-post-to-html').click()",
+ NAVIGATION_BLOCKED);
+ } else {
+ // We need an origin to create a filesystem URL on, so navigate to one.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ const GURL kFilesystemURL1(
+ CreateFileSystemUrl("target.html", "form target", "text/html"));
+ const GURL kFilesystemURL2(CreateFileSystemUrl(
+ "form.html",
+ base::StringPrintf("<html><form id=f method=post action='%s'><input "
+ "type=submit "
+ "onclick=document.getElementById('f').click() "
+ "id=btn-submit></form></html>",
+ kFilesystemURL1.spec().c_str()),
+ "text/html"));
+
+ // Create a new shell and navigate that shell to the filesystem: URL created
+ // above. Navigating the a tab away from the
+ // original page may clear all filesystem: URLs associated with that origin,
+ // so we keep the origin around in the original shell.
+ ShellAddedObserver new_shell_observer;
+ // TODO(crbug/811558): about:blank might commit without needing to wait.
+ // Remove the wait.
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(), "window.open('about:blank');"));
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ EXPECT_TRUE(NavigateToURL(new_shell, kFilesystemURL2));
+ ExecuteScriptAndCheckNavigation(
+ new_shell, new_shell->web_contents()->GetMainFrame(),
+ url::kFileSystemScheme, "document.getElementById('btn-submit').click()",
+ NAVIGATION_BLOCKED);
+ }
+}
+
+// Tests that navigating the top frame to a blocked scheme with HTML mimetype is
+// blocked even if the top frame already has a blocked scheme.
+IN_PROC_BROWSER_TEST_P(
+ BlockedSchemeNavigationBrowserTest,
+ HTML_NavigationFromFrame_TopFrameHasBlockedScheme_Block) {
+ EXPECT_TRUE(NavigateToURL(shell(), CreateEmptyURLWithBlockedScheme()));
+ AddIFrame(shell()->web_contents()->GetMainFrame(), GetTestURL());
+
+ TestNavigationFromFrame(
+ GetParam(),
+ "document.getElementById('navigate-top-frame-to-html').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Tests that opening a new window with a blocked scheme with HTML mimetype is
+// blocked even if the top frame already has a blocked scheme.
+IN_PROC_BROWSER_TEST_P(
+ BlockedSchemeNavigationBrowserTest,
+ HTML_WindowOpenFromFrame_TopFrameHasBlockedScheme_Block) {
+ // Create an empty URL with a blocked scheme, navigate to it, and add a frame.
+ EXPECT_TRUE(NavigateToURL(shell(), CreateEmptyURLWithBlockedScheme()));
+ AddIFrame(shell()->web_contents()->GetMainFrame(), GetTestURL());
+
+ TestWindowOpenFromFrame(GetParam(),
+ "document.getElementById('window-open-html').click()",
+ NAVIGATION_BLOCKED);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Blocked schemes with octet-stream mimetype (binary)
+//
+// Test direct navigations to a binary mime types.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ OctetStream_BrowserInitiated) {
+ const GURL kUrl(CreateURLWithBlockedScheme("test.html", "test",
+ "application/octet-stream"));
+
+ if (IsDataURLTest()) {
+ // Navigations to data URLs with unknown mime types should end up as
+ // downloads.
+ NavigateAndCheckDownload(kUrl);
+ } else {
+ // Navigations to filesystem URLs never end up as downloads.
+ EXPECT_TRUE(NavigateToURL(shell(), kUrl));
+ EXPECT_EQ(kUrl, shell()->web_contents()->GetLastCommittedURL());
+ }
+}
+
+#if defined(OS_ANDROID)
+// Flaky on android: https://crbug.com/734563
+#define MAYBE_DataUrl_OctetStream_WindowOpen \
+ DISABLED_DataUrl_OctetStream_WindowOpen
+#else
+#define MAYBE_DataUrl_OctetStream_WindowOpen DataUrl_OctetStream_WindowOpen
+#endif
+
+// Test window.open to a data URL with binary mimetype.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ DataUrl_OctetStream_WindowOpen) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/data_url_navigations.html")));
+ // Navigations to data URLs with unknown mime types should end up as
+ // downloads.
+ ExecuteScriptAndCheckWindowOpenDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('window-open-octetstream').click()");
+}
+
+// Test window.open to a filesystem URL with binary mimetype.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ FilesystemUrl_OctetStream_WindowOpen) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/filesystem_url_navigations.html")));
+ // Navigations to filesystem URLs never end up as downloads.
+ ExecuteScriptAndCheckWindowOpen(
+ shell()->web_contents()->GetMainFrame(), url::kFileSystemScheme,
+ "document.getElementById('window-open-octetstream').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Test navigation to a data URL with binary mimetype.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ DataUrl_OctetStream_Navigation) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/data_url_navigations.html")));
+ // Navigations to data URLs with unknown mime types should end up as
+ // downloads.
+ ExecuteScriptAndCheckDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('navigate-top-frame-to-octetstream').click()");
+}
+
+// Test navigation to a filesystem URL with binary mimetype.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ FilesystemUrl_OctetStream_Navigation) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/filesystem_url_navigations.html")));
+ // Navigations to filesystem URLs never end up as downloads.
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), url::kFileSystemScheme,
+ "document.getElementById('navigate-top-frame-to-octetstream').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Test form post to a data URL with binary mimetype.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ DataUrl_OctetStream_FormPost) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/data_url_navigations.html")));
+ // Form posts to data URLs with unknown mime types should end up as
+ // downloads.
+ ExecuteScriptAndCheckDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('form-post-to-octetstream').click()");
+}
+
+// Test form post to a filesystem URL with binary mimetype.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ FilesystemUrl_OctetStream_FormPost) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/filesystem_url_navigations.html")));
+ // Navigations to filesystem URLs never end up as downloads.
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), url::kFileSystemScheme,
+ "document.getElementById('form-post-to-octetstream').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Tests navigation of the main frame to a data URL with a binary mimetype
+// from a subframe. These navigations should end up as downloads.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ DataUrl_OctetStream_NavigationFromFrame) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(
+ shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
+ TestDownloadFromFrame(
+ "document.getElementById('navigate-top-frame-to-octetstream').click()");
+}
+
+// Tests navigation of the main frame to a filesystem URL with a binary mimetype
+// from a subframe. Navigations to filesystem URLs never end up as downloads.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ FilesystemUrl_OctetStream_NavigationFromFrame) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL("b.com",
+ "/filesystem_url_navigations.html"));
+
+ TestNavigationFromFrame(
+ url::kFileSystemScheme,
+ "document.getElementById('navigate-top-frame-to-octetstream').click()",
+ NAVIGATION_BLOCKED);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// URLs with unknown mimetype
+//
+// Test direct navigation to an unknown mime type.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ UnknownMimeType_BrowserInitiated_Download) {
+ const GURL kUrl(
+ CreateURLWithBlockedScheme("test.html", "test", "unknown/mimetype"));
+
+ if (IsDataURLTest()) {
+ // Navigations to data URLs with unknown mime types should end up as
+ // downloads.
+ NavigateAndCheckDownload(kUrl);
+ } else {
+ // Navigations to filesystem URLs never end up as downloads.
+ EXPECT_TRUE(NavigateToURL(shell(), kUrl));
+ EXPECT_EQ(kUrl, shell()->web_contents()->GetLastCommittedURL());
+ }
+}
+
+#if defined(OS_ANDROID)
+// Flaky on android: https://crbug.com/734563
+#define MAYBE_UnknownMimeType_WindowOpen DISABLED_UnknownMimeType_WindowOpen
+#else
+#define MAYBE_UnknownMimeType_WindowOpen UnknownMimeType_WindowOpen
+#endif
+
+// Test window.open to a blocked scheme with an unknown mime type.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ MAYBE_UnknownMimeType_WindowOpen) {
+ Navigate(GetTestURL());
+ if (IsDataURLTest()) {
+ // Navigations to data URLs with unknown mime types should end up as
+ // downloads.
+ ExecuteScriptAndCheckWindowOpenDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('window-open-unknown-mimetype').click()");
+ } else {
+ // Navigations to filesystem URLs never end up as downloads.
+ ExecuteScriptAndCheckWindowOpen(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('window-open-unknown-mimetype').click()",
+ NAVIGATION_BLOCKED);
+ }
+}
+
+// Test navigation to a data URL with an unknown mime type.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ DataUrl_UnknownMimeType_Navigation) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/data_url_navigations.html")));
+ // Navigations to data URLs with unknown mime types should end up as
+ // downloads.
+ ExecuteScriptAndCheckDownload(shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('navigate-top-frame-"
+ "to-unknown-mimetype').click()");
+}
+
+// Test navigation to a filesystem URL with an unknown mime type.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ FilesystemUrl_UnknownMimeType_Navigation) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/filesystem_url_navigations.html")));
+ // Navigations to filesystem URLs never end up as downloads.
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), url::kFileSystemScheme,
+ "document.getElementById('navigate-top-frame-to-unknown-mimetype')."
+ "click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Test form post to a data URL with an unknown mime type.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ DataUrl_UnknownMimeType_FormPost) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/data_url_navigations.html")));
+ // Form posts to data URLs with unknown mime types should end up as
+ // downloads.
+ ExecuteScriptAndCheckDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('form-post-to-unknown-mimetype').click()");
+}
+
+// Test form post to a filesystem URL with an unknown mime type.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ FilesystemUrl_UnknownMimeType_FormPost) {
+ Navigate(embedded_test_server()->GetURL(
+ base::StringPrintf("/filesystem_url_navigations.html")));
+ // Navigations to filesystem URLs never end up as downloads.
+ ExecuteScriptAndCheckNavigation(
+ shell(), shell()->web_contents()->GetMainFrame(), url::kFileSystemScheme,
+ "document.getElementById('form-post-to-unknown-mimetype').click()",
+ NAVIGATION_BLOCKED);
+}
+
+// Test navigation of the main frame to a data URL with an unknown mimetype from
+// a subframe. These navigations should end up as downloads.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ DataUrl_UnknownMimeType_NavigationFromFrame) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(
+ shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
+
+ TestDownloadFromFrame(
+ "document.getElementById('navigate-top-frame-to-unknown-mimetype')."
+ "click()");
+}
+
+// Test navigation of the main frame to a filesystem URL with an unknown
+// mimetype from a subframe. Navigations to filesystem URLs don't end up as
+// downloads.
+IN_PROC_BROWSER_TEST_F(BlockedSchemeNavigationBrowserTest,
+ FilesystemUrl_UnknownMimeType_NavigationFromFrame) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL("b.com",
+ "/filesystem_url_navigations.html"));
+
+ TestNavigationFromFrame(url::kFileSystemScheme,
+ "document.getElementById('navigate-top-frame-to-"
+ "unknown-mimetype').click()",
+ NAVIGATION_BLOCKED);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// URLs with PDF mimetype
+//
+// Tests that a browser initiated navigation to a blocked scheme URL with PDF
+// mime type is allowed, or initiates a download on Android.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ PDF_BrowserInitiatedNavigation_Allow) {
+ std::string pdf_base64;
+ base::Base64Encode(kPDF, &pdf_base64);
+ const GURL kPDFUrl(CreateURLWithBlockedScheme(
+ "test.pdf", IsDataURLTest() ? pdf_base64 : kPDF, "application/pdf"));
+
+#if !defined(OS_ANDROID)
+ TestNavigationObserver observer(shell()->web_contents());
+ EXPECT_TRUE(NavigateToURL(shell(), kPDFUrl));
+ EXPECT_EQ(kPDFUrl, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_TRUE(
+ shell()->web_contents()->GetLastCommittedURL().SchemeIs(GetParam()));
+#else
+ NavigateAndCheckDownload(kPDFUrl);
+#endif
+}
+
+// Tests that a window.open to a blocked scheme is blocked if the URL has a
+// mime type that will be handled by a plugin (PDF in this case).
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ PDF_WindowOpen_Block) {
+ Navigate(GetTestURL());
+
+#if !defined(OS_ANDROID)
+ ExecuteScriptAndCheckWindowOpen(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('window-open-pdf').click()", NAVIGATION_BLOCKED);
+#else
+ if (IsDataURLTest()) {
+ // On Android, data URL PDFs are downloaded upon navigation.
+ ExecuteScriptAndCheckDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('window-open-pdf').click()");
+ } else {
+ // On Android, filesystem PDF URLs are navigated and should be blocked.
+ ExecuteScriptAndCheckWindowOpen(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('window-open-pdf').click()",
+ NAVIGATION_BLOCKED);
+ }
+#endif
+}
+
+// Test that a navigation to a blocked scheme URL is blocked if the URL has a
+// mime type that will be handled by a plugin (PDF in this case).
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ PDF_Navigation_Block) {
+ Navigate(GetTestURL());
+
+#if !defined(OS_ANDROID)
+ ExecuteScriptAndCheckPDFNavigation(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('navigate-top-frame-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+#else
+ if (IsDataURLTest()) {
+ // On Android, data URL PDFs are downloaded upon navigation.
+ ExecuteScriptAndCheckDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('navigate-top-frame-to-pdf').click()");
+ } else {
+ // On Android, filesystem PDF URLs are navigated and should be blocked.
+ ExecuteScriptAndCheckPDFNavigation(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('navigate-top-frame-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+ }
+#endif
+}
+
+// Test that a form post to a blocked scheme is blocked if the URL has a mime
+// type that will be handled by a plugin (PDF in this case).
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest, PDF_FormPost_Block) {
+ Navigate(GetTestURL());
+
+#if !defined(OS_ANDROID)
+ ExecuteScriptAndCheckPDFNavigation(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('form-post-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+#else
+ if (IsDataURLTest()) {
+ // On Android, data URL PDFs are downloaded upon navigation.
+ ExecuteScriptAndCheckDownload(
+ shell()->web_contents()->GetMainFrame(),
+ "document.getElementById('form-post-to-pdf').click()");
+ } else {
+ // On Android, filesystem PDF URLs are navigated and should be blocked.
+ ExecuteScriptAndCheckPDFNavigation(
+ shell()->web_contents()->GetMainFrame(), GetParam(),
+ "document.getElementById('form-post-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+ }
+#endif
+}
+
+// Tests that navigating the main frame to a blocked scheme with PDF mimetype
+// from a subframe is blocked, or is downloaded on Android.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ PDF_NavigationFromFrame_Block) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(
+ shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL(
+ "b.com", base::StringPrintf("/%s_url_navigations.html", GetParam())));
+
+#if !defined(OS_ANDROID)
+ TestPDFNavigationFromFrame(
+ GetParam(),
+ "document.getElementById('navigate-top-frame-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+#else
+ if (IsDataURLTest()) {
+ // On Android, data URL PDFs are downloaded upon navigation.
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckDownload(
+ child, "document.getElementById('navigate-top-frame-to-pdf').click()");
+ } else {
+ // On Android, filesystem PDF URLs are navigated and should be blocked.
+ TestPDFNavigationFromFrame(
+ GetParam(),
+ "document.getElementById('navigate-top-frame-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+ }
+#endif
+}
+
+// Tests that opening a window with a blocked scheme with PDF mimetype from a
+// subframe is blocked, or is downloaded on Android.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ PDF_WindowOpenFromFrame_Block) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/simple_page.html")));
+ AddIFrame(shell()->web_contents()->GetMainFrame(),
+ embedded_test_server()->GetURL(
+ base::StringPrintf("/%s_url_navigations.html", GetParam())));
+
+#if !defined(OS_ANDROID)
+ TestWindowOpenFromFrame(GetParam(),
+ "document.getElementById('window-open-pdf').click()",
+ NAVIGATION_BLOCKED);
+#else
+ if (IsDataURLTest()) {
+ // On Android, data URL PDFs are downloaded upon navigation.
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckDownload(
+ child, "document.getElementById('window-open-pdf').click()");
+ } else {
+ // On Android, filesystem PDF URLs are navigated and should be blocked.
+ TestWindowOpenFromFrame(
+ GetParam(), "document.getElementById('window-open-pdf').click()",
+ NAVIGATION_BLOCKED);
+ }
+#endif
+}
+
+// Tests that navigating the top frame to a blocked scheme with PDF mimetype
+// from a subframe is blocked even if the top frame already has a blocked
+// scheme.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ PDF_NavigationFromFrame_TopFrameHasBlockedScheme_Block) {
+ EXPECT_TRUE(NavigateToURL(shell(), CreateEmptyURLWithBlockedScheme()));
+ AddIFrame(shell()->web_contents()->GetMainFrame(), GetTestURL());
+
+#if !defined(OS_ANDROID)
+ TestPDFNavigationFromFrame(
+ GetParam(),
+ "document.getElementById('navigate-top-frame-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+#else
+ if (IsDataURLTest()) {
+ // On Android, data URL PDFs are downloaded upon navigation.
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckDownload(
+ child, "document.getElementById('navigate-top-frame-to-pdf').click()");
+ } else {
+ // On Android, filesystem PDF URLs are navigated and should be blocked.
+ TestPDFNavigationFromFrame(
+ GetParam(),
+ "document.getElementById('navigate-top-frame-to-pdf').click()",
+ NAVIGATION_BLOCKED);
+ }
+#endif
+}
+
+// Tests that opening a window with a blocked scheme with PDF mimetype from a
+// subframe is blocked even if the top frame already has a blocked scheme.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ PDF_WindowOpenFromFrame_TopFrameHasBlockedScheme_Block) {
+ EXPECT_TRUE(NavigateToURL(shell(), CreateEmptyURLWithBlockedScheme()));
+ AddIFrame(shell()->web_contents()->GetMainFrame(), GetTestURL());
+
+#if !defined(OS_ANDROID)
+ TestWindowOpenFromFrame(GetParam(),
+ "document.getElementById('window-open-pdf').click()",
+ NAVIGATION_BLOCKED);
+#else
+ if (IsDataURLTest()) {
+ // On Android, data URL PDFs are downloaded upon navigation.
+ RenderFrameHost* child =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child);
+ if (AreAllSitesIsolatedForTesting()) {
+ ASSERT_TRUE(child->IsCrossProcessSubframe());
+ }
+ ExecuteScriptAndCheckDownload(
+ child, "document.getElementById('window-open-pdf').click()");
+ } else {
+ // On Android, filesystem PDF URLs are navigated to and should be blocked.
+ TestWindowOpenFromFrame(
+ GetParam(), "document.getElementById('window-open-pdf').click()",
+ NAVIGATION_BLOCKED);
+ }
+#endif
+}
+
+// Test case to verify that redirects to blocked schemes are properly
+// disallowed, even when invoked through history navigations. See
+// https://crbug.com/723796.
+IN_PROC_BROWSER_TEST_P(BlockedSchemeNavigationBrowserTest,
+ WindowOpenRedirectAndBack) {
+ Navigate(GetTestURL());
+
+ // This test will need to navigate the newly opened window.
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(),
+ "document.getElementById('window-open-redirect').click()"));
+ Shell* new_shell = new_shell_observer.GetShell();
+ NavigationController* controller =
+ &new_shell->web_contents()->GetController();
+ WaitForLoadStop(new_shell->web_contents());
+
+ // The window.open() should have resulted in an error page. The blocked
+ // URL should be in both the actual and the virtual URL.
+ {
+ EXPECT_EQ(0, controller->GetLastCommittedEntryIndex());
+ NavigationEntry* entry = controller->GetLastCommittedEntry();
+ EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
+ EXPECT_FALSE(entry->GetURL().SchemeIs(url::kDataScheme));
+ EXPECT_FALSE(entry->GetURL().SchemeIs(url::kFileSystemScheme));
+ EXPECT_TRUE(base::StartsWith(
+ entry->GetURL().spec(),
+ embedded_test_server()->GetURL("/server-redirect?").spec(),
+ base::CompareCase::SENSITIVE));
+ EXPECT_EQ(entry->GetURL(), entry->GetVirtualURL());
+ }
+
+ // Navigate forward and then go back to ensure the navigation to data: or
+ // filesystem: URL is blocked. Use a browser-initiated back navigation,
+ // equivalent to user pressing the back button.
+ EXPECT_TRUE(
+ NavigateToURL(new_shell, embedded_test_server()->GetURL("/title1.html")));
+ EXPECT_EQ(1, controller->GetLastCommittedEntryIndex());
+ {
+ TestNavigationObserver observer(new_shell->web_contents());
+ controller->GoBack();
+ observer.Wait();
+
+ NavigationEntry* entry = controller->GetLastCommittedEntry();
+ EXPECT_EQ(0, controller->GetLastCommittedEntryIndex());
+ EXPECT_FALSE(entry->GetURL().SchemeIs(url::kDataScheme));
+ EXPECT_FALSE(entry->GetURL().SchemeIs(url::kFileSystemScheme));
+ EXPECT_TRUE(base::StartsWith(
+ entry->GetURL().spec(),
+ embedded_test_server()->GetURL("/server-redirect?").spec(),
+ base::CompareCase::SENSITIVE));
+ EXPECT_EQ(entry->GetURL(), entry->GetVirtualURL());
+ }
+
+ // Do another new navigation, but then use JavaScript to navigate back,
+ // equivalent to document executing JS.
+ EXPECT_TRUE(
+ NavigateToURL(new_shell, embedded_test_server()->GetURL("/title1.html")));
+ EXPECT_EQ(1, controller->GetLastCommittedEntryIndex());
+ {
+ TestNavigationObserver observer(new_shell->web_contents());
+ EXPECT_TRUE(ExecuteScript(new_shell, "history.go(-1)"));
+ observer.Wait();
+
+ NavigationEntry* entry = controller->GetLastCommittedEntry();
+ EXPECT_EQ(0, controller->GetLastCommittedEntryIndex());
+ EXPECT_FALSE(entry->GetURL().SchemeIs(url::kDataScheme));
+ EXPECT_FALSE(entry->GetURL().SchemeIs(url::kFileSystemScheme));
+ EXPECT_TRUE(base::StartsWith(
+ entry->GetURL().spec(),
+ embedded_test_server()->GetURL("/server-redirect?").spec(),
+ base::CompareCase::SENSITIVE));
+ EXPECT_EQ(entry->GetURL(), entry->GetVirtualURL());
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/data_url_navigation_throttle.cc b/chromium/content/browser/frame_host/blocked_scheme_navigation_throttle.cc
index 2835bda8b7d..48613b4fb7c 100644
--- a/chromium/content/browser/frame_host/data_url_navigation_throttle.cc
+++ b/chromium/content/browser/frame_host/blocked_scheme_navigation_throttle.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 "content/browser/frame_host/data_url_navigation_throttle.h"
+#include "content/browser/frame_host/blocked_scheme_navigation_throttle.h"
#include "base/feature_list.h"
#include "base/strings/stringprintf.h"
@@ -20,51 +20,47 @@
namespace content {
namespace {
-const char kConsoleError[] =
- "Not allowed to navigate top frame to data URL: %s";
+const char kConsoleError[] = "Not allowed to navigate top frame to %s URL: %s";
}
-DataUrlNavigationThrottle::DataUrlNavigationThrottle(
+BlockedSchemeNavigationThrottle::BlockedSchemeNavigationThrottle(
NavigationHandle* navigation_handle)
: NavigationThrottle(navigation_handle) {}
-DataUrlNavigationThrottle::~DataUrlNavigationThrottle() {}
+BlockedSchemeNavigationThrottle::~BlockedSchemeNavigationThrottle() {}
NavigationThrottle::ThrottleCheckResult
-DataUrlNavigationThrottle::WillProcessResponse() {
+BlockedSchemeNavigationThrottle::WillProcessResponse() {
NavigationHandleImpl* handle =
static_cast<NavigationHandleImpl*>(navigation_handle());
if (handle->IsDownload())
return PROCEED;
- // We treat <a download href="data:.."> as a navigation, but it will always
- // result in a download, not a top-level navigation, so not blocking it here.
- if (handle->GetSuggestedFilename().has_value())
- return PROCEED;
-
RenderFrameHost* top_frame =
handle->frame_tree_node()->frame_tree()->root()->current_frame_host();
top_frame->AddMessageToConsole(
CONSOLE_MESSAGE_LEVEL_ERROR,
- base::StringPrintf(kConsoleError, handle->GetURL().spec().c_str()));
+ base::StringPrintf(kConsoleError, handle->GetURL().scheme().c_str(),
+ handle->GetURL().spec().c_str()));
return CANCEL;
}
-const char* DataUrlNavigationThrottle::GetNameForLogging() {
- return "DataUrlNavigationThrottle";
+const char* BlockedSchemeNavigationThrottle::GetNameForLogging() {
+ return "BlockedSchemeNavigationThrottle";
}
// static
std::unique_ptr<NavigationThrottle>
-DataUrlNavigationThrottle::CreateThrottleForNavigation(
+BlockedSchemeNavigationThrottle::CreateThrottleForNavigation(
NavigationHandle* navigation_handle) {
if (navigation_handle->IsInMainFrame() &&
navigation_handle->IsRendererInitiated() &&
!navigation_handle->IsSameDocument() &&
- navigation_handle->GetURL().SchemeIs(url::kDataScheme) &&
+ (navigation_handle->GetURL().SchemeIs(url::kDataScheme) ||
+ navigation_handle->GetURL().SchemeIs(url::kFileSystemScheme)) &&
!base::FeatureList::IsEnabled(
features::kAllowContentInitiatedDataUrlNavigations)) {
- return std::make_unique<DataUrlNavigationThrottle>(navigation_handle);
+ return std::make_unique<BlockedSchemeNavigationThrottle>(navigation_handle);
}
return nullptr;
}
diff --git a/chromium/content/browser/frame_host/blocked_scheme_navigation_throttle.h b/chromium/content/browser/frame_host/blocked_scheme_navigation_throttle.h
new file mode 100644
index 00000000000..40e56d660aa
--- /dev/null
+++ b/chromium/content/browser/frame_host/blocked_scheme_navigation_throttle.h
@@ -0,0 +1,35 @@
+// Copyright 2017 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_FRAME_HOST_BLOCKED_SCHEME_NAVIGATION_THROTTLE_H_
+#define CONTENT_BROWSER_FRAME_HOST_BLOCKED_SCHEME_NAVIGATION_THROTTLE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "content/public/browser/navigation_throttle.h"
+
+namespace content {
+
+// Blocks renderer-initiated top-frame navigations to certain URL schemes
+// (currently data: and filesystem:).
+class BlockedSchemeNavigationThrottle : public NavigationThrottle {
+ public:
+ explicit BlockedSchemeNavigationThrottle(NavigationHandle* navigation_handle);
+ ~BlockedSchemeNavigationThrottle() override;
+
+ // NavigationThrottle method:
+ ThrottleCheckResult WillProcessResponse() override;
+ const char* GetNameForLogging() override;
+
+ static std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
+ NavigationHandle* navigation_handle);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BlockedSchemeNavigationThrottle);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_BLOCKED_SCHEME_NAVIGATION_THROTTLE_H_
diff --git a/chromium/content/browser/frame_host/cross_process_frame_connector.cc b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
index 5a706cd6e3f..337d713ddfa 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -5,12 +5,14 @@
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_hittest.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/cursor_manager.h"
@@ -44,6 +46,13 @@ CrossProcessFrameConnector::CrossProcessFrameConnector(
}
CrossProcessFrameConnector::~CrossProcessFrameConnector() {
+ if (!IsVisible()) {
+ // MaybeLogCrash will check 1) if there was a crash or not and 2) if the
+ // crash might have been already logged earlier as kCrashedWhileVisible or
+ // kShownAfterCrashing.
+ MaybeLogCrash(CrashVisibility::kNeverVisibleAfterCrash);
+ }
+
// Notify the view of this object being destroyed, if the view still exists.
SetView(nullptr);
}
@@ -52,11 +61,14 @@ bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CrossProcessFrameConnector, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateResizeParams, OnUpdateResizeParams)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_SynchronizeVisualProperties,
+ OnSynchronizeVisualProperties)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateViewportIntersection,
OnUpdateViewportIntersection)
IPC_MESSAGE_HANDLER(FrameHostMsg_VisibilityChanged, OnVisibilityChanged)
IPC_MESSAGE_HANDLER(FrameHostMsg_SetIsInert, OnSetIsInert)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_SetInheritedEffectiveTouchAction,
+ OnSetInheritedEffectiveTouchAction)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateRenderThrottlingStatus,
OnUpdateRenderThrottlingStatus)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -94,6 +106,14 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
// visibility in case the frame owner is hidden in parent process. We should
// try to move these updates to a single IPC (see https://crbug.com/750179).
if (view_) {
+ if (has_crashed_ && !IsVisible()) {
+ // MaybeLogCrash will check 1) if there was a crash or not and 2) if the
+ // crash might have been already logged earlier as kCrashedWhileVisible or
+ // kShownAfterCrashing.
+ MaybeLogCrash(CrashVisibility::kNeverVisibleAfterCrash);
+ }
+ is_crash_already_logged_ = has_crashed_ = false;
+
view_->SetFrameConnectorDelegate(this);
if (is_hidden_)
OnVisibilityChanged(false);
@@ -106,6 +126,21 @@ void CrossProcessFrameConnector::SetView(RenderWidgetHostViewChildFrame* view) {
}
void CrossProcessFrameConnector::RenderProcessGone() {
+ has_crashed_ = true;
+
+ FrameTreeNode* node = frame_proxy_in_parent_renderer_->frame_tree_node();
+ int process_id = node->current_frame_host()->GetProcess()->GetID();
+ for (node = node->parent(); node; node = node->parent()) {
+ if (node->current_frame_host()->GetProcess()->GetID() == process_id) {
+ // The crash will be already logged by the ancestor - ignore this crash in
+ // the current instance of the CrossProcessFrameConnector.
+ is_crash_already_logged_ = true;
+ }
+ }
+
+ if (IsVisible())
+ MaybeLogCrash(CrashVisibility::kCrashedWhileVisible);
+
frame_proxy_in_parent_renderer_->Send(new FrameMsg_ChildFrameProcessGone(
frame_proxy_in_parent_renderer_->GetRoutingID()));
}
@@ -140,7 +175,7 @@ gfx::PointF CrossProcessFrameConnector::TransformPointToRootCoordSpace(
return transformed_point;
}
-bool CrossProcessFrameConnector::TransformPointToLocalCoordSpace(
+bool CrossProcessFrameConnector::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
const viz::SurfaceId& local_surface_id,
@@ -169,7 +204,8 @@ bool CrossProcessFrameConnector::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
const viz::SurfaceId& local_surface_id,
- gfx::PointF* transformed_point) {
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
if (!root_view)
return false;
@@ -179,14 +215,14 @@ bool CrossProcessFrameConnector::TransformPointToCoordSpaceForView(
// be siblings). To account for this, the point is first transformed into the
// root coordinate space and then the root is asked to perform the conversion.
if (!root_view->TransformPointToLocalCoordSpace(point, local_surface_id,
- transformed_point))
+ transformed_point, source))
return false;
if (target_view == root_view)
return true;
return root_view->TransformPointToCoordSpaceForView(
- *transformed_point, target_view, transformed_point);
+ *transformed_point, target_view, transformed_point, source);
}
void CrossProcessFrameConnector::ForwardProcessAckedTouchEvent(
@@ -270,13 +306,15 @@ void CrossProcessFrameConnector::UnlockMouse() {
root_view->UnlockMouse();
}
-void CrossProcessFrameConnector::OnUpdateResizeParams(
+void CrossProcessFrameConnector::OnSynchronizeVisualProperties(
const viz::SurfaceId& surface_id,
- const FrameResizeParams& resize_params) {
+ const FrameVisualProperties& visual_properties) {
// If the |screen_space_rect| or |screen_info| of the frame has changed, then
// the viz::LocalSurfaceId must also change.
- if ((last_received_local_frame_size_ != resize_params.local_frame_size ||
- screen_info_ != resize_params.screen_info) &&
+ if ((last_received_local_frame_size_ != visual_properties.local_frame_size ||
+ screen_info_ != visual_properties.screen_info ||
+ capture_sequence_number() !=
+ visual_properties.capture_sequence_number) &&
local_surface_id_ == surface_id.local_surface_id()) {
bad_message::ReceivedBadMessage(
frame_proxy_in_parent_renderer_->GetProcess(),
@@ -284,8 +322,8 @@ void CrossProcessFrameConnector::OnUpdateResizeParams(
return;
}
- last_received_local_frame_size_ = resize_params.local_frame_size;
- UpdateResizeParams(surface_id, resize_params);
+ last_received_local_frame_size_ = visual_properties.local_frame_size;
+ SynchronizeVisualProperties(surface_id, visual_properties);
}
void CrossProcessFrameConnector::OnUpdateViewportIntersection(
@@ -296,10 +334,23 @@ void CrossProcessFrameConnector::OnUpdateViewportIntersection(
if (view_)
view_->UpdateViewportIntersection(viewport_intersection,
compositor_visible_rect);
+
+ if (IsVisible()) {
+ // MaybeLogCrash will check 1) if there was a crash or not and 2) if the
+ // crash might have been already logged earlier as kCrashedWhileVisible or
+ // kShownAfterCrashing.
+ MaybeLogCrash(CrashVisibility::kShownAfterCrashing);
+ }
}
void CrossProcessFrameConnector::OnVisibilityChanged(bool visible) {
is_hidden_ = !visible;
+ if (IsVisible()) {
+ // MaybeLogCrash will check 1) if there was a crash or not and 2) if the
+ // crash might have been already logged earlier as kCrashedWhileVisible or
+ // kShownAfterCrashing.
+ MaybeLogCrash(CrashVisibility::kShownAfterCrashing);
+ }
if (!view_)
return;
@@ -327,6 +378,13 @@ void CrossProcessFrameConnector::OnSetIsInert(bool inert) {
view_->SetIsInert();
}
+void CrossProcessFrameConnector::OnSetInheritedEffectiveTouchAction(
+ cc::TouchAction touch_action) {
+ inherited_effective_touch_action_ = touch_action;
+ if (view_)
+ view_->UpdateInheritedEffectiveTouchAction();
+}
+
RenderWidgetHostViewBase*
CrossProcessFrameConnector::GetRootRenderWidgetHostView() {
// Tests may not have frame_proxy_in_parent_renderer_ set.
@@ -384,6 +442,11 @@ bool CrossProcessFrameConnector::IsInert() const {
return is_inert_;
}
+cc::TouchAction CrossProcessFrameConnector::InheritedEffectiveTouchAction()
+ const {
+ return inherited_effective_touch_action_;
+}
+
bool CrossProcessFrameConnector::IsHidden() const {
return is_hidden_;
}
@@ -404,11 +467,10 @@ void CrossProcessFrameConnector::EmbedRendererWindowTreeClientInParent(
}
#endif
-void CrossProcessFrameConnector::ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
- frame_proxy_in_parent_renderer_->Send(new FrameMsg_ResizeDueToAutoResize(
- frame_proxy_in_parent_renderer_->GetRoutingID(), sequence_number));
+void CrossProcessFrameConnector::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
+ frame_proxy_in_parent_renderer_->Send(new FrameMsg_DidUpdateVisualProperties(
+ frame_proxy_in_parent_renderer_->GetRoutingID(), metadata));
}
void CrossProcessFrameConnector::SetVisibilityForChildViews(
@@ -471,4 +533,34 @@ bool CrossProcessFrameConnector::IsSubtreeThrottled() const {
return subtree_throttled_;
}
+void CrossProcessFrameConnector::MaybeLogCrash(CrashVisibility visibility) {
+ if (!has_crashed_)
+ return;
+
+ // Only log once per renderer crash.
+ if (is_crash_already_logged_)
+ return;
+ is_crash_already_logged_ = true;
+
+ // Actually log the UMA.
+ UMA_HISTOGRAM_ENUMERATION("Stability.ChildFrameCrash.Visibility", visibility);
+}
+
+bool CrossProcessFrameConnector::IsVisible() {
+ if (is_hidden_)
+ return false;
+ if (viewport_intersection_rect().IsEmpty())
+ return false;
+
+ Visibility embedder_visibility =
+ frame_proxy_in_parent_renderer_->frame_tree_node()
+ ->current_frame_host()
+ ->delegate()
+ ->GetVisibility();
+ if (embedder_visibility != Visibility::VISIBLE)
+ return false;
+
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/cross_process_frame_connector.h b/chromium/content/browser/frame_host/cross_process_frame_connector.h
index 95e72d659cb..21759b18be7 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -7,12 +7,13 @@
#include <stdint.h>
+#include "cc/input/touch_action.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "content/browser/renderer_host/frame_connector_delegate.h"
#include "content/common/content_export.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
namespace IPC {
class Message;
@@ -84,15 +85,17 @@ class CONTENT_EXPORT CrossProcessFrameConnector
gfx::PointF TransformPointToRootCoordSpace(
const gfx::PointF& point,
const viz::SurfaceId& surface_id) override;
- bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
- const viz::SurfaceId& original_surface,
- const viz::SurfaceId& local_surface_id,
- gfx::PointF* transformed_point) override;
+ bool TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ const viz::SurfaceId& local_surface_id,
+ gfx::PointF* transformed_point) override;
bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
const viz::SurfaceId& local_surface_id,
- gfx::PointF* transformed_point) override;
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY) override;
void ForwardProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
void BubbleScrollEvent(const blink::WebGestureEvent& event) override;
@@ -104,6 +107,7 @@ class CONTENT_EXPORT CrossProcessFrameConnector
const gfx::Size& max_size) override;
void DisableAutoResize() override;
bool IsInert() const override;
+ cc::TouchAction InheritedEffectiveTouchAction() const override;
bool IsHidden() const override;
bool IsThrottled() const override;
bool IsSubtreeThrottled() const override;
@@ -111,8 +115,8 @@ class CONTENT_EXPORT CrossProcessFrameConnector
void EmbedRendererWindowTreeClientInParent(
ui::mojom::WindowTreeClientPtr window_tree_client) override;
#endif
- void ResizeDueToAutoResize(const gfx::Size& new_size,
- uint64_t sequence_number) override;
+ void DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) override;
// Set the visibility of immediate child views, i.e. views whose parent view
// is |view_|.
@@ -125,6 +129,26 @@ class CONTENT_EXPORT CrossProcessFrameConnector
return GetRootRenderWidgetHostView();
}
+ // This enum backs a histogram - please do not modify or remove the existing
+ // enum values below (adding new values is okay, but please remember to also
+ // update enums.xml in this case). See enums.xml for descriptions of enum
+ // values.
+ enum class CrashVisibility {
+ kCrashedWhileVisible = 0,
+ kShownAfterCrashing = 1,
+ kNeverVisibleAfterCrash = 2,
+ kMaxValue = kNeverVisibleAfterCrash
+ };
+ // Logs the Stability.ChildFrameCrash.Visibility metric after checking that a
+ // crash has indeed happened and checking that the crash has not already been
+ // logged in UMA.
+ void MaybeLogCrash(CrashVisibility visibility);
+
+ // Returns whether the child widget is actually visible to the user. This is
+ // different from the IsHidden override, and takes into account viewport
+ // intersection as well as the visibility of the RenderFrameHostDelegate.
+ bool IsVisible();
+
private:
friend class MockCrossProcessFrameConnector;
@@ -133,12 +157,14 @@ class CONTENT_EXPORT CrossProcessFrameConnector
void ResetScreenSpaceRect();
// Handlers for messages received from the parent frame.
- void OnUpdateResizeParams(const viz::SurfaceId& surface_id,
- const FrameResizeParams& frame_resize_params);
+ void OnSynchronizeVisualProperties(
+ const viz::SurfaceId& surface_id,
+ const FrameVisualProperties& visual_properties);
void OnUpdateViewportIntersection(const gfx::Rect& viewport_intersection,
const gfx::Rect& compositor_visible_rect);
void OnVisibilityChanged(bool visible);
void OnSetIsInert(bool);
+ void OnSetInheritedEffectiveTouchAction(cc::TouchAction);
void OnUpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled);
@@ -147,6 +173,8 @@ class CONTENT_EXPORT CrossProcessFrameConnector
RenderFrameProxyHost* frame_proxy_in_parent_renderer_;
bool is_inert_ = false;
+ cc::TouchAction inherited_effective_touch_action_ =
+ cc::TouchAction::kTouchActionAuto;
bool is_throttled_ = false;
bool subtree_throttled_ = false;
@@ -157,6 +185,14 @@ class CONTENT_EXPORT CrossProcessFrameConnector
bool is_scroll_bubbling_;
+ // Used to make sure we only log UMA once per renderer crash.
+ bool is_crash_already_logged_ = false;
+
+ // Used to make sure that MaybeLogCrash only logs the UMA in case of an actual
+ // crash (in case it is called from the destructor of
+ // CrossProcessFrameConnector or when WebContentsImpl::WasShown is called).
+ bool has_crashed_ = false;
+
// The last pre-transform frame size received from the parent renderer.
// |last_received_local_frame_size_| may be in DIP if use zoom for DSF is
// off.
@@ -168,4 +204,3 @@ class CONTENT_EXPORT CrossProcessFrameConnector
} // namespace content
#endif // CONTENT_BROWSER_FRAME_HOST_CROSS_PROCESS_FRAME_CONNECTOR_H_
-
diff --git a/chromium/content/browser/frame_host/data_url_navigation_browsertest.cc b/chromium/content/browser/frame_host/data_url_navigation_browsertest.cc
deleted file mode 100644
index 02d8c983202..00000000000
--- a/chromium/content/browser/frame_host/data_url_navigation_browsertest.cc
+++ /dev/null
@@ -1,1032 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/strings/pattern.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
-#include "build/buildflag.h"
-#include "content/browser/site_per_process_browsertest.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/browser_side_navigation_policy.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/public/test/download_test_observer.h"
-#include "content/public/test/test_navigation_observer.h"
-#include "content/shell/browser/shell.h"
-#include "content/shell/browser/shell_download_manager_delegate.h"
-#include "net/base/escape.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "ppapi/buildflags/buildflags.h"
-
-#if BUILDFLAG(ENABLE_PLUGINS)
-#include "content/public/browser/plugin_service.h"
-#include "content/public/common/webplugininfo.h"
-#endif
-
-namespace content {
-
-namespace {
-
-// The pattern to catch messages printed by the browser when a data URL
-// navigation is blocked.
-const char kDataUrlBlockedPattern[] =
- "Not allowed to navigate top frame to data URL:*";
-
-// The message printed by the data URL when it successfully navigates.
-const char kDataUrlSuccessfulMessage[] = "NAVIGATION_SUCCESSFUL";
-
-// A "Hello World" PDF encoded as a data URL. Source of this PDF:
-// -------------------------
-// %PDF-1.7
-// 1 0 obj << /Type /Page /Parent 3 0 R /Resources 5 0 R /Contents 2 0 R >>
-// endobj
-// 2 0 obj << /Length 51 >>
-// stream BT
-// /F1 12 Tf
-// 1 0 0 1 100 20 Tm
-// (Hello World)Tj
-// ET
-// endstream
-// endobj
-// 3 0 obj << /Type /Pages /Kids [ 1 0 R ] /Count 1 /MediaBox [ 0 0 300 50] >>
-// endobj
-// 4 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont/Arial >>
-// endobj
-// 5 0 obj << /ProcSet[/PDF/Text] /Font <</F1 4 0 R >> >>
-// endobj
-// 6 0 obj << /Type /Catalog /Pages 3 0 R >>
-// endobj
-// trailer << /Root 6 0 R >>
-// -------------------------
-const char kPdfUrl[] =
- "data:application/pdf;base64,JVBERi0xLjcKMSAwIG9iaiA8PCAvVHlwZSAvUGFnZSAvUG"
- "FyZW50IDMgMCBSIC9SZXNvdXJjZXMgNSAwIFIgL0NvbnRlbnRzIDIgMCBSID4+CmVuZG9iagoy"
- "IDAgb2JqIDw8IC9MZW5ndGggNTEgPj4KIHN0cmVhbSBCVAogL0YxIDEyIFRmCiAxIDAgMCAxID"
- "EwMCAyMCBUbQogKEhlbGxvIFdvcmxkKVRqCiBFVAogZW5kc3RyZWFtCmVuZG9iagozIDAgb2Jq"
- "IDw8IC9UeXBlIC9QYWdlcyAvS2lkcyBbIDEgMCBSIF0gL0NvdW50IDEgL01lZGlhQm94IFsgMC"
- "AwIDMwMCA1MF0gPj4KZW5kb2JqCjQgMCBvYmogPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1R5"
- "cGUxIC9OYW1lIC9GMSAvQmFzZUZvbnQvQXJpYWwgPj4KZW5kb2JqCjUgMCBvYmogPDwgL1Byb2"
- "NTZXRbL1BERi9UZXh0XSAvRm9udCA8PC9GMSA0IDAgUiA+PiA+PgplbmRvYmoKNiAwIG9iaiA8"
- "PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMyAwIFIgPj4KZW5kb2JqCnRyYWlsZXIgPDwgL1Jvb3"
- "QgNiAwIFIgPj4K";
-
-enum ExpectedNavigationStatus { NAVIGATION_BLOCKED, NAVIGATION_ALLOWED };
-
-// This class is similar to ConsoleObserverDelegate in that it listens and waits
-// for specific console messages. The difference from ConsoleObserverDelegate is
-// that this class immediately stops waiting if it sees a message matching
-// fail_pattern, instead of waiting for a message matching success_pattern.
-class DataURLWarningConsoleObserverDelegate : public WebContentsDelegate {
- public:
- DataURLWarningConsoleObserverDelegate(
- WebContents* web_contents,
- ExpectedNavigationStatus expected_navigation_status)
- : web_contents_(web_contents),
- success_filter_(expected_navigation_status == NAVIGATION_ALLOWED
- ? kDataUrlSuccessfulMessage
- : kDataUrlBlockedPattern),
- fail_filter_(expected_navigation_status == NAVIGATION_ALLOWED
- ? kDataUrlBlockedPattern
- : kDataUrlSuccessfulMessage),
- message_loop_runner_(
- new MessageLoopRunner(MessageLoopRunner::QuitMode::IMMEDIATE)),
- saw_failure_message_(false) {}
- ~DataURLWarningConsoleObserverDelegate() override {}
-
- void Wait() { message_loop_runner_->Run(); }
-
- // WebContentsDelegate method:
- bool DidAddMessageToConsole(WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) override {
- DCHECK(source == web_contents_);
- const std::string ascii_message = base::UTF16ToASCII(message);
- if (base::MatchPattern(ascii_message, fail_filter_)) {
- saw_failure_message_ = true;
- message_loop_runner_->Quit();
- }
- if (base::MatchPattern(ascii_message, success_filter_)) {
- message_loop_runner_->Quit();
- }
- return false;
- }
-
- // Returns true if the observer encountered a message that matches
- // |fail_filter_|.
- bool saw_failure_message() const { return saw_failure_message_; }
-
- private:
- WebContents* web_contents_;
- const std::string success_filter_;
- const std::string fail_filter_;
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
- bool saw_failure_message_;
-};
-
-#if BUILDFLAG(ENABLE_PLUGINS)
-// This class registers a fake PDF plugin handler so that data URL navigations
-// with a PDF mime type end up with a navigation and don't simply download the
-// file.
-class ScopedPluginRegister {
- public:
- ScopedPluginRegister(content::PluginService* plugin_service)
- : plugin_service_(plugin_service) {
- const char kPluginName[] = "PDF";
- const char kPdfMimeType[] = "application/pdf";
- const char kPdfFileType[] = "pdf";
- WebPluginInfo plugin_info;
- plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
- plugin_info.name = base::ASCIIToUTF16(kPluginName);
- plugin_info.mime_types.push_back(
- WebPluginMimeType(kPdfMimeType, kPdfFileType, std::string()));
- plugin_service_->RegisterInternalPlugin(plugin_info, false);
- plugin_service_->RefreshPlugins();
- }
-
- ~ScopedPluginRegister() {
- std::vector<WebPluginInfo> plugins;
- plugin_service_->GetInternalPlugins(&plugins);
- EXPECT_EQ(1u, plugins.size());
- plugin_service_->UnregisterInternalPlugin(plugins[0].path);
- plugin_service_->RefreshPlugins();
-
- plugins.clear();
- plugin_service_->GetInternalPlugins(&plugins);
- EXPECT_TRUE(plugins.empty());
- }
-
- private:
- content::PluginService* plugin_service_;
-};
-#endif // BUILDFLAG(ENABLE_PLUGINS)
-
-} // namespace
-
-class DataUrlNavigationBrowserTest : public ContentBrowserTest {
- public:
-#if BUILDFLAG(ENABLE_PLUGINS)
- DataUrlNavigationBrowserTest()
- : scoped_plugin_register_(PluginService::GetInstance()) {}
-#else
- DataUrlNavigationBrowserTest() {}
-#endif // BUILDFLAG(ENABLE_PLUGINS)
-
- protected:
- void SetUpOnMainThread() override {
- host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(embedded_test_server()->Start());
-
- base::FilePath path;
- ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &path));
- path = path.AppendASCII("data_url_navigations.html");
- ASSERT_TRUE(base::PathExists(path));
-
- std::string contents;
- ASSERT_TRUE(base::ReadFileToString(path, &contents));
- data_url_ = GURL(std::string("data:text/html,") + contents);
-
- ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
- ShellDownloadManagerDelegate* delegate =
- static_cast<ShellDownloadManagerDelegate*>(
- shell()
- ->web_contents()
- ->GetBrowserContext()
- ->GetDownloadManagerDelegate());
- delegate->SetDownloadBehaviorForTesting(downloads_directory_.GetPath());
- }
-
- // Adds an iframe to |rfh| pointing to |url|.
- void AddIFrame(RenderFrameHost* rfh, const GURL& url) {
- const std::string javascript = base::StringPrintf(
- "f = document.createElement('iframe'); f.src = '%s';"
- "document.body.appendChild(f);",
- url.spec().c_str());
- TestNavigationObserver observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(rfh, javascript));
- observer.Wait();
- }
-
- // Runs |javascript| on the first child frame and checks for a navigation.
- void TestNavigationFromFrame(
- const std::string& javascript,
- ExpectedNavigationStatus expected_navigation_status) {
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckNavigation(child, javascript,
- expected_navigation_status);
- }
-
- // Runs |javascript| on the first child frame and expects a download to occur.
- void TestDownloadFromFrame(const std::string& javascript) {
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckNavigationDownload(child, javascript);
- }
-
- // Runs |javascript| on the first child frame and checks for a navigation to
- // the PDF file pointed by the test case.
- void TestPDFNavigationFromFrame(
- const std::string& javascript,
- ExpectedNavigationStatus expected_navigation_status) {
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckPDFNavigation(child, javascript,
- expected_navigation_status);
- }
-
- // Same as TestNavigationFromFrame, but instead of navigating, the child frame
- // tries to open a new window with a data URL.
- void TestWindowOpenFromFrame(
- const std::string& javascript,
- ExpectedNavigationStatus expected_navigation_status) {
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckWindowOpen(child, javascript,
- expected_navigation_status);
- }
-
- // Executes |javascript| on |rfh| and waits for a console message based on
- // |expected_navigation_status|.
- // - Blocked navigations should print kDataUrlBlockedPattern.
- // - Allowed navigations should print kDataUrlSuccessfulMessage.
- void ExecuteScriptAndCheckNavigation(
- RenderFrameHost* rfh,
- const std::string& javascript,
- ExpectedNavigationStatus expected_navigation_status) {
- const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
- const std::string expected_message;
-
- DataURLWarningConsoleObserverDelegate console_delegate(
- shell()->web_contents(), expected_navigation_status);
- shell()->web_contents()->SetDelegate(&console_delegate);
-
- TestNavigationObserver navigation_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(rfh, javascript));
- console_delegate.Wait();
- EXPECT_FALSE(console_delegate.saw_failure_message());
- shell()->web_contents()->SetDelegate(nullptr);
-
- switch (expected_navigation_status) {
- case NAVIGATION_ALLOWED:
- navigation_observer.Wait();
- // The new page should have a data URL.
- EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
- url::kDataScheme));
- EXPECT_TRUE(navigation_observer.last_navigation_url().SchemeIs(
- url::kDataScheme));
- EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
- break;
-
- case NAVIGATION_BLOCKED:
- // Original page shouldn't navigate away.
- EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
- EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
- break;
-
- default:
- NOTREACHED();
- }
- }
-
- // Similar to ExecuteScriptAndCheckNavigation(), but doesn't wait for a
- // console message if the navigation is expected to be allowed (this is
- // because PDF files can't print to the console).
- void ExecuteScriptAndCheckPDFNavigation(
- RenderFrameHost* rfh,
- const std::string& javascript,
- ExpectedNavigationStatus expected_navigation_status) {
- const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
-
- const std::string expected_message =
- (expected_navigation_status == NAVIGATION_ALLOWED)
- ? std::string()
- : kDataUrlBlockedPattern;
-
- std::unique_ptr<ConsoleObserverDelegate> console_delegate;
- if (!expected_message.empty()) {
- console_delegate.reset(new ConsoleObserverDelegate(
- shell()->web_contents(), expected_message));
- shell()->web_contents()->SetDelegate(console_delegate.get());
- }
-
- TestNavigationObserver navigation_observer(shell()->web_contents());
- EXPECT_TRUE(ExecuteScript(rfh, javascript));
-
- if (console_delegate) {
- console_delegate->Wait();
- shell()->web_contents()->SetDelegate(nullptr);
- }
-
- switch (expected_navigation_status) {
- case NAVIGATION_ALLOWED:
- navigation_observer.Wait();
- // The new page should have a data URL.
- EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
- url::kDataScheme));
- EXPECT_TRUE(navigation_observer.last_navigation_url().SchemeIs(
- url::kDataScheme));
- EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
- break;
-
- case NAVIGATION_BLOCKED:
- // Original page shouldn't navigate away.
- EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
- EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
- break;
-
- default:
- NOTREACHED();
- }
- }
-
- // Executes |javascript| on |rfh| and waits for a new window to be opened.
- // Does not check for console messages (it's currently not possible to
- // concurrently wait for a new shell to be created and a console message to be
- // printed on that new shell).
- void ExecuteScriptAndCheckWindowOpen(
- RenderFrameHost* rfh,
- const std::string& javascript,
- ExpectedNavigationStatus expected_navigation_status) {
- ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(ExecuteScript(rfh, javascript));
-
- Shell* new_shell = new_shell_observer.GetShell();
- WaitForLoadStop(new_shell->web_contents());
-
- switch (expected_navigation_status) {
- case NAVIGATION_ALLOWED:
- EXPECT_TRUE(new_shell->web_contents()->GetLastCommittedURL().SchemeIs(
- url::kDataScheme));
- break;
-
- case NAVIGATION_BLOCKED:
- EXPECT_TRUE(
- new_shell->web_contents()->GetLastCommittedURL().is_empty());
- break;
-
- default:
- NOTREACHED();
- }
- }
-
- // Executes |javascript| on |rfh| and waits for a download to be started by
- // a window.open call.
- void ExecuteScriptAndCheckWindowOpenDownload(RenderFrameHost* rfh,
- const std::string& javascript) {
- const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
- ShellAddedObserver new_shell_observer;
- DownloadManager* download_manager = BrowserContext::GetDownloadManager(
- shell()->web_contents()->GetBrowserContext());
-
- EXPECT_TRUE(ExecuteScript(rfh, javascript));
- Shell* new_shell = new_shell_observer.GetShell();
-
- DownloadTestObserverTerminal download_observer(
- download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
-
- WaitForLoadStop(new_shell->web_contents());
- // If no download happens, this will timeout.
- download_observer.WaitForFinished();
-
- EXPECT_TRUE(
- new_shell->web_contents()->GetLastCommittedURL().spec().empty());
- // No navigation should commit.
- EXPECT_FALSE(
- new_shell->web_contents()->GetController().GetLastCommittedEntry());
- // Original page shouldn't navigate away.
- EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
- }
-
- // Executes |javascript| on |rfh| and waits for a download to be started.
- void ExecuteScriptAndCheckNavigationDownload(RenderFrameHost* rfh,
- const std::string& javascript) {
- const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
- DownloadManager* download_manager = BrowserContext::GetDownloadManager(
- shell()->web_contents()->GetBrowserContext());
- DownloadTestObserverTerminal download_observer(
- download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
-
- EXPECT_TRUE(ExecuteScript(rfh, javascript));
- // If no download happens, this will timeout.
- download_observer.WaitForFinished();
-
- // Original page shouldn't navigate away.
- EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
- }
-
- // Initiates a browser initiated navigation to |url| and waits for a download
- // to be started.
- void NavigateAndCheckDownload(const GURL& url) {
- const GURL original_url(shell()->web_contents()->GetLastCommittedURL());
- DownloadManager* download_manager = BrowserContext::GetDownloadManager(
- shell()->web_contents()->GetBrowserContext());
- DownloadTestObserverTerminal download_observer(
- download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
- NavigateToURL(shell(), url);
-
- // If no download happens, this will timeout.
- download_observer.WaitForFinished();
-
- // Original page shouldn't navigate away.
- EXPECT_EQ(original_url, shell()->web_contents()->GetLastCommittedURL());
- }
-
- // data URL form of the file at content/test/data/data_url_navigations.html
- GURL data_url() const { return data_url_; }
-
- private:
- base::ScopedTempDir downloads_directory_;
-
-#if BUILDFLAG(ENABLE_PLUGINS)
- ScopedPluginRegister scoped_plugin_register_;
-#endif // BUILDFLAG(ENABLE_PLUGINS)
-
- GURL data_url_;
-
- DISALLOW_COPY_AND_ASSIGN(DataUrlNavigationBrowserTest);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// data URLs with HTML mimetype
-//
-// Tests that a browser initiated navigation to a data URL doesn't show a
-// console warning and is not blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, BrowserInitiated_Allow) {
- DataURLWarningConsoleObserverDelegate console_delegate(
- shell()->web_contents(), NAVIGATION_ALLOWED);
- shell()->web_contents()->SetDelegate(&console_delegate);
-
- NavigateToURL(shell(), GURL("data:text/"
- "html,<html><script>console.log('NAVIGATION_"
- "SUCCESSFUL');</script>"));
- console_delegate.Wait();
- shell()->web_contents()->SetDelegate(nullptr);
-
- EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
- url::kDataScheme));
-}
-
-// Tests that a content initiated navigation to a data URL is blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_Navigation_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckNavigation(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('navigate-top-frame-to-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-class DataUrlNavigationBrowserTestWithFeatureFlag
- : public DataUrlNavigationBrowserTest {
- public:
- DataUrlNavigationBrowserTestWithFeatureFlag() {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAllowContentInitiatedDataUrlNavigations);
- }
- ~DataUrlNavigationBrowserTestWithFeatureFlag() override {}
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(DataUrlNavigationBrowserTestWithFeatureFlag);
-};
-
-// Tests that a content initiated navigation to a data URL is allowed if
-// blocking is disabled with a feature flag.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTestWithFeatureFlag,
- HTML_Navigation_Allow_FeatureFlag) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckNavigation(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('navigate-top-frame-to-html').click()",
- NAVIGATION_ALLOWED);
-}
-
-// Tests that a window.open to a data URL with HTML mime type is blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_WindowOpen_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckWindowOpen(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('window-open-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-// Tests that a form post to a data URL with HTML mime type is blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, HTML_FormPost_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckNavigation(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('form-post-to-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-// Tests that navigating the main frame to a data URL with HTML mimetype from a
-// subframe is blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- HTML_NavigationFromFrame_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("a.com", "/simple_page.html"));
- AddIFrame(
- shell()->web_contents()->GetMainFrame(),
- embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
-
- TestNavigationFromFrame(
- "document.getElementById('navigate-top-frame-to-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-// Tests that opening a new data URL window from a subframe is blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- HTML_WindowOpenFromFrame_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("a.com", "/simple_page.html"));
- AddIFrame(
- shell()->web_contents()->GetMainFrame(),
- embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
-
- TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-// Tests that navigation to a data URL is blocked even if the top frame is
-// already a data URL.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- HTML_Navigation_DataToData_Block) {
- NavigateToURL(shell(), data_url());
- ExecuteScriptAndCheckNavigation(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('navigate-top-frame-to-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-// Tests that a form post to a data URL with HTML mime type is blocked even if
-// the top frame is already a data URL.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- HTML_FormPost_DataToData_Block) {
- NavigateToURL(shell(), data_url());
- ExecuteScriptAndCheckNavigation(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('form-post-to-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-// Tests that navigating the top frame to a data URL with HTML mimetype is
-// blocked even if the top frame is already a data URL.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- HTML_NavigationFromFrame_TopFrameIsDataURL_Block) {
- const GURL top_url(
- base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
- embedded_test_server()
- ->GetURL("/data_url_navigations.html")
- .spec()
- .c_str()));
- NavigateToURL(shell(), top_url);
-
- TestNavigationFromFrame(
- "document.getElementById('navigate-top-frame-to-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-// Tests that opening a new window with a data URL with HTML mimetype is blocked
-// even if the top frame is already a data URL.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- HTML_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
- const GURL top_url(
- base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
- embedded_test_server()
- ->GetURL("/data_url_navigations.html")
- .spec()
- .c_str()));
- NavigateToURL(shell(), top_url);
-
- TestWindowOpenFromFrame("document.getElementById('window-open-html').click()",
- NAVIGATION_BLOCKED);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// data URLs with octet-stream mimetype (binary)
-//
-// Test that a direct navigation to a binary mime type initiates a download.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- OctetStream_BrowserInitiated_Download) {
- NavigateAndCheckDownload(GURL("data:application/octet-stream,test"));
-}
-
-#if defined(OS_ANDROID)
-// Flaky on android: https://crbug.com/734563
-#define MAYBE_OctetStream_WindowOpen_Download \
- DISABLED_OctetStream_WindowOpen_Download
-#else
-#define MAYBE_OctetStream_WindowOpen_Download OctetStream_WindowOpen_Download
-#endif
-
-// Test that window.open to a data URL results in a download if the URL has a
-// binary mime type.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- MAYBE_OctetStream_WindowOpen_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckWindowOpenDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('window-open-octetstream').click()");
-}
-
-// Test that a navigation to a data URL results in a download if the URL has a
-// binary mime type.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- OctetStream_Navigation_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckNavigationDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('navigate-top-frame-to-octetstream').click()");
-}
-
-// Test that a form post to a data URL results in a download if the URL has a
-// binary mime type.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- OctetStream_FormPost_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckNavigationDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('form-post-to-octetstream').click()");
-}
-
-// Tests that navigating the main frame from a subframe results in a download
-// if the URL has a binary mimetype.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- OctetStream_NavigationFromFrame_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("a.com", "/simple_page.html"));
- AddIFrame(
- shell()->web_contents()->GetMainFrame(),
- embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
-
- TestDownloadFromFrame(
- "document.getElementById('navigate-top-frame-to-octetstream').click()");
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// data URLs with unknown mimetype
-//
-// Test that a direct navigation to an unknown mime type initiates a download.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- UnknownMimeType_BrowserInitiated_Download) {
- NavigateAndCheckDownload(GURL("data:unknown/mimetype,test"));
-}
-
-#if defined(OS_ANDROID)
-// Flaky on android: https://crbug.com/734563
-#define MAYBE_UnknownMimeType_WindowOpen_Download \
- DISABLED_UnknownMimeType_WindowOpen_Download
-#else
-#define MAYBE_UnknownMimeType_WindowOpen_Download \
- UnknownMimeType_WindowOpen_Download
-#endif
-
-// Test that window.open to a data URL results in a download if the URL has an
-// unknown mime type.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- MAYBE_UnknownMimeType_WindowOpen_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckWindowOpenDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('window-open-unknown-mimetype').click()");
-}
-
-// Test that a navigation to a data URL results in a download if the URL has an
-// unknown mime type.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- UnknownMimeType_Navigation_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckNavigationDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('navigate-top-"
- "frame-to-unknown-mimetype').click()");
-}
-
-// Test that a form post to a data URL results in a download if the URL has an
-// unknown mime type.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- UnknownMimeType_FormPost_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
- ExecuteScriptAndCheckNavigationDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('form-post-to-unknown-mimetype').click()");
-}
-
-// Tests that navigating the main frame from a subframe results in a download
-// if the URL has an unknown mimetype.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- UnknownMimeType_NavigationFromFrame_Download) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("a.com", "/simple_page.html"));
- AddIFrame(
- shell()->web_contents()->GetMainFrame(),
- embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
-
- TestDownloadFromFrame(
- "document.getElementById('navigate-top-frame-to-unknown-mimetype').click("
- ")");
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// data URLs with PDF mimetype
-//
-// Tests that a browser initiated navigation to a data URL with PDF mime type is
-// allowed, or initiates a download on Android.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- PDF_BrowserInitiatedNavigation_Allow) {
-#if !defined(OS_ANDROID)
- TestNavigationObserver observer(shell()->web_contents());
- NavigateToURL(shell(), GURL(kPdfUrl));
- EXPECT_EQ(GURL(kPdfUrl), observer.last_navigation_url());
- EXPECT_TRUE(observer.last_navigation_succeeded());
- EXPECT_TRUE(shell()->web_contents()->GetLastCommittedURL().SchemeIs(
- url::kDataScheme));
-#else
- // On Android, PDFs are downloaded upon navigation.
- NavigateAndCheckDownload(GURL(kPdfUrl));
-#endif
-}
-
-// Tests that a window.open to a data URL is blocked if the data URL has a
-// mime type that will be handled by a plugin (PDF in this case).
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_WindowOpen_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
-
-#if !defined(OS_ANDROID)
- ExecuteScriptAndCheckWindowOpen(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('window-open-pdf').click()", NAVIGATION_BLOCKED);
-#else
- // On Android, PDFs are downloaded upon navigation.
- ExecuteScriptAndCheckNavigationDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('window-open-pdf').click()");
-#endif
-}
-
-// Test that a navigation to a data URL is blocked if the data URL has a mime
-// type that will be handled by a plugin (PDF in this case).
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_Navigation_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
-
-#if !defined(OS_ANDROID)
- ExecuteScriptAndCheckPDFNavigation(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('navigate-top-frame-to-pdf').click()",
- NAVIGATION_BLOCKED);
-#else
- // On Android, PDFs are downloaded upon navigation.
- ExecuteScriptAndCheckNavigationDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('navigate-top-frame-to-pdf').click()");
-#endif
-}
-
-// Test that a form post to a data URL is blocked if the data URL has a mime
-// type that will be handled by a plugin (PDF in this case).
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest, PDF_FormPost_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
-
-#if !defined(OS_ANDROID)
- ExecuteScriptAndCheckPDFNavigation(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('form-post-to-pdf').click()",
- NAVIGATION_BLOCKED);
-#else
- // On Android, PDFs are downloaded upon navigation.
- ExecuteScriptAndCheckNavigationDownload(
- shell()->web_contents()->GetMainFrame(),
- "document.getElementById('form-post-to-pdf').click()");
-#endif
-}
-
-// Tests that navigating the main frame to a data URL with PDF mimetype from a
-// subframe is blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- PDF_NavigationFromFrame_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("a.com", "/simple_page.html"));
- AddIFrame(
- shell()->web_contents()->GetMainFrame(),
- embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
-
-#if !defined(OS_ANDROID)
- TestPDFNavigationFromFrame(
- "document.getElementById('navigate-top-frame-to-pdf').click()",
- NAVIGATION_BLOCKED);
-#else
- // On Android, PDFs are downloaded upon navigation.
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckNavigationDownload(
- child, "document.getElementById('navigate-top-frame-to-pdf').click()");
-#endif
-}
-
-// Tests that opening a window with a data URL with PDF mimetype from a
-// subframe is blocked.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- PDF_WindowOpenFromFrame_Block) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("a.com", "/simple_page.html"));
- AddIFrame(
- shell()->web_contents()->GetMainFrame(),
- embedded_test_server()->GetURL("b.com", "/data_url_navigations.html"));
-
-#if !defined(OS_ANDROID)
- TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
- NAVIGATION_BLOCKED);
-#else
- // On Android, PDFs are downloaded upon navigation.
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckNavigationDownload(
- child, "document.getElementById('window-open-pdf').click()");
-#endif
-}
-
-// Tests that navigating the top frame to a data URL with PDF mimetype from a
-// subframe is blocked even if the top frame is already a data URL.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- PDF_NavigationFromFrame_TopFrameIsDataURL_Block) {
- const GURL top_url(
- base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
- embedded_test_server()
- ->GetURL("/data_url_navigations.html")
- .spec()
- .c_str()));
- NavigateToURL(shell(), top_url);
-
-#if !defined(OS_ANDROID)
- TestPDFNavigationFromFrame(
- "document.getElementById('navigate-top-frame-to-pdf').click()",
- NAVIGATION_BLOCKED);
-#else
- // On Android, PDFs are downloaded upon navigation.
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckNavigationDownload(
- child, "document.getElementById('navigate-top-frame-to-pdf').click()");
-#endif
-}
-
-// Tests that opening a window with a data URL with PDF mimetype from a
-// subframe is blocked even if the top frame is already a data URL.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- PDF_WindowOpenFromFrame_TopFrameIsDataURL_Block) {
- const GURL top_url(
- base::StringPrintf("data:text/html, <iframe src='%s'></iframe>",
- embedded_test_server()
- ->GetURL("/data_url_navigations.html")
- .spec()
- .c_str()));
- NavigateToURL(shell(), top_url);
-
-#if !defined(OS_ANDROID)
- TestWindowOpenFromFrame("document.getElementById('window-open-pdf').click()",
- NAVIGATION_BLOCKED);
-#else
- // On Android, PDFs are downloaded upon navigation.
- RenderFrameHost* child =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child);
- if (AreAllSitesIsolatedForTesting()) {
- ASSERT_TRUE(child->IsCrossProcessSubframe());
- }
- ExecuteScriptAndCheckNavigationDownload(
- child, "document.getElementById('window-open-pdf').click()");
-#endif
-}
-
-// Test case to verify that redirects to data: URLs are properly disallowed,
-// even when invoked through history navigations.
-// See https://crbug.com/723796.
-IN_PROC_BROWSER_TEST_F(DataUrlNavigationBrowserTest,
- WindowOpenRedirectAndBack) {
- NavigateToURL(shell(),
- embedded_test_server()->GetURL("/data_url_navigations.html"));
-
- // This test will need to navigate the newly opened window.
- ShellAddedObserver new_shell_observer;
- EXPECT_TRUE(
- ExecuteScript(shell()->web_contents(),
- "document.getElementById('window-open-redirect').click()"));
- Shell* new_shell = new_shell_observer.GetShell();
- NavigationController* controller =
- &new_shell->web_contents()->GetController();
- WaitForLoadStop(new_shell->web_contents());
-
- // The window.open() should have resulted in an error page. The blocked
- // URL should be in both the actual and the virtual URL.
- {
- EXPECT_EQ(0, controller->GetLastCommittedEntryIndex());
- NavigationEntry* entry = controller->GetLastCommittedEntry();
- EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
- EXPECT_FALSE(entry->GetURL().SchemeIs(url::kDataScheme));
- EXPECT_TRUE(base::StartsWith(
- entry->GetURL().spec(),
- embedded_test_server()->GetURL("/server-redirect?").spec(),
- base::CompareCase::SENSITIVE));
- EXPECT_EQ(entry->GetURL(), entry->GetVirtualURL());
- }
-
- // Navigate forward and then go back to ensure the navigation to data: URL
- // is blocked. Use a browser-initiated back navigation, equivalent to user
- // pressing the back button.
- EXPECT_TRUE(
- NavigateToURL(new_shell, embedded_test_server()->GetURL("/title1.html")));
- EXPECT_EQ(1, controller->GetLastCommittedEntryIndex());
- {
- TestNavigationObserver observer(new_shell->web_contents());
- controller->GoBack();
- observer.Wait();
-
- NavigationEntry* entry = controller->GetLastCommittedEntry();
- EXPECT_EQ(0, controller->GetLastCommittedEntryIndex());
- EXPECT_FALSE(entry->GetURL().SchemeIs(url::kDataScheme));
- EXPECT_TRUE(base::StartsWith(
- entry->GetURL().spec(),
- embedded_test_server()->GetURL("/server-redirect?").spec(),
- base::CompareCase::SENSITIVE));
- EXPECT_EQ(entry->GetURL(), entry->GetVirtualURL());
- }
-
- // Do another new navigation, but then use JavaScript to navigate back,
- // equivalent to document executing JS.
- EXPECT_TRUE(
- NavigateToURL(new_shell, embedded_test_server()->GetURL("/title1.html")));
- EXPECT_EQ(1, controller->GetLastCommittedEntryIndex());
- {
- TestNavigationObserver observer(new_shell->web_contents());
- EXPECT_TRUE(ExecuteScript(new_shell, "history.go(-1)"));
- observer.Wait();
-
- NavigationEntry* entry = controller->GetLastCommittedEntry();
- EXPECT_EQ(0, controller->GetLastCommittedEntryIndex());
- EXPECT_FALSE(entry->GetURL().SchemeIs(url::kDataScheme));
- EXPECT_TRUE(base::StartsWith(
- entry->GetURL().spec(),
- embedded_test_server()->GetURL("/server-redirect?").spec(),
- base::CompareCase::SENSITIVE));
- EXPECT_EQ(entry->GetURL(), entry->GetVirtualURL());
- }
-}
-
-} // content
diff --git a/chromium/content/browser/frame_host/data_url_navigation_throttle.h b/chromium/content/browser/frame_host/data_url_navigation_throttle.h
deleted file mode 100644
index 14a2038e74e..00000000000
--- a/chromium/content/browser/frame_host/data_url_navigation_throttle.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 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_FRAME_HOST_DATA_URL_NAVIGATION_THROTTLE_
-#define CONTENT_BROWSER_FRAME_HOST_DATA_URL_NAVIGATION_THROTTLE_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "content/public/browser/navigation_throttle.h"
-
-namespace content {
-
-class DataUrlNavigationThrottle : public NavigationThrottle {
- public:
- explicit DataUrlNavigationThrottle(NavigationHandle* navigation_handle);
- ~DataUrlNavigationThrottle() override;
-
- // NavigationThrottle method:
- ThrottleCheckResult WillProcessResponse() override;
- const char* GetNameForLogging() override;
-
- static std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
- NavigationHandle* navigation_handle);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DataUrlNavigationThrottle);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_FRAME_HOST_DATA_URL_NAVIGATION_THROTTLE_
diff --git a/chromium/content/browser/frame_host/form_submission_throttle.cc b/chromium/content/browser/frame_host/form_submission_throttle.cc
index 1201e5d114f..893445d5ebe 100644
--- a/chromium/content/browser/frame_host/form_submission_throttle.cc
+++ b/chromium/content/browser/frame_host/form_submission_throttle.cc
@@ -82,9 +82,10 @@ FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(bool is_redirect) {
// TODO(estark): Move this check into NavigationRequest and split it into (1)
// check report-only CSP, (2) upgrade request if needed, (3) check enforced
// CSP to match how frame-src works. https://crbug.com/713388
- if (render_frame->IsAllowedByCsp(CSPDirective::FormAction, url, is_redirect,
- handle->source_location(),
- CSPContext::CHECK_ALL_CSP)) {
+ if (render_frame->IsAllowedByCsp(
+ CSPDirective::FormAction, url, is_redirect,
+ false /* is_response_check */, handle->source_location(),
+ CSPContext::CHECK_ALL_CSP, true /* is_form_submission */)) {
return NavigationThrottle::PROCEED;
}
diff --git a/chromium/content/browser/frame_host/form_submission_throttle_browsertest.cc b/chromium/content/browser/frame_host/form_submission_throttle_browsertest.cc
index 92ef88f5459..96083c75c22 100644
--- a/chromium/content/browser/frame_host/form_submission_throttle_browsertest.cc
+++ b/chromium/content/browser/frame_host/form_submission_throttle_browsertest.cc
@@ -73,7 +73,6 @@ IN_PROC_BROWSER_TEST_F(FormSubmissionBrowserTest,
false, // started_from_context_menu
CSPDisposition::CHECK, // should_check_main_world_csp
true, // is_form_submission
- base::nullopt, // suggested_filename
nullptr); // navigation_ui_data
// Test the expectations with a FormSubmissionThrottle.
@@ -111,7 +110,6 @@ IN_PROC_BROWSER_TEST_F(FormSubmissionBrowserTest,
false, // started_from_context_menu
CSPDisposition::DO_NOT_CHECK, // should_check_main_world_csp
true, // is_form_submission
- base::nullopt, // suggested_filename
nullptr); // navigation_ui_data
// Test that the navigation is allowed because "should_by_pass_main_world_csp"
diff --git a/chromium/content/browser/frame_host/frame_navigation_entry.cc b/chromium/content/browser/frame_host/frame_navigation_entry.cc
index 7768085a3c9..117f24c9b57 100644
--- a/chromium/content/browser/frame_host/frame_navigation_entry.cc
+++ b/chromium/content/browser/frame_host/frame_navigation_entry.cc
@@ -25,7 +25,8 @@ FrameNavigationEntry::FrameNavigationEntry(
const std::vector<GURL>& redirect_chain,
const PageState& page_state,
const std::string& method,
- int64_t post_id)
+ int64_t post_id,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory)
: frame_unique_name_(frame_unique_name),
item_sequence_number_(item_sequence_number),
document_sequence_number_(document_sequence_number),
@@ -36,7 +37,8 @@ FrameNavigationEntry::FrameNavigationEntry(
redirect_chain_(redirect_chain),
page_state_(page_state),
method_(method),
- post_id_(post_id) {}
+ post_id_(post_id),
+ blob_url_loader_factory_(std::move(blob_url_loader_factory)) {}
FrameNavigationEntry::~FrameNavigationEntry() {
}
@@ -48,7 +50,7 @@ FrameNavigationEntry* FrameNavigationEntry::Clone() const {
copy->UpdateEntry(frame_unique_name_, item_sequence_number_,
document_sequence_number_, site_instance_.get(), nullptr,
url_, referrer_, redirect_chain_, page_state_, method_,
- post_id_);
+ post_id_, nullptr /* blob_url_loader_factory */);
return copy;
}
@@ -63,7 +65,8 @@ void FrameNavigationEntry::UpdateEntry(
const std::vector<GURL>& redirect_chain,
const PageState& page_state,
const std::string& method,
- int64_t post_id) {
+ int64_t post_id,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
frame_unique_name_ = frame_unique_name;
item_sequence_number_ = item_sequence_number;
document_sequence_number_ = document_sequence_number;
@@ -75,6 +78,7 @@ void FrameNavigationEntry::UpdateEntry(
page_state_ = page_state;
method_ = method;
post_id_ = post_id;
+ blob_url_loader_factory_ = std::move(blob_url_loader_factory);
}
void FrameNavigationEntry::set_item_sequence_number(
diff --git a/chromium/content/browser/frame_host/frame_navigation_entry.h b/chromium/content/browser/frame_host/frame_navigation_entry.h
index 64e2033dca1..50076c1af7e 100644
--- a/chromium/content/browser/frame_host/frame_navigation_entry.h
+++ b/chromium/content/browser/frame_host/frame_navigation_entry.h
@@ -13,6 +13,7 @@
#include "content/public/common/page_state.h"
#include "content/public/common/referrer.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
@@ -31,34 +32,38 @@ class CONTENT_EXPORT FrameNavigationEntry
: public base::RefCounted<FrameNavigationEntry> {
public:
FrameNavigationEntry();
- FrameNavigationEntry(const std::string& frame_unique_name,
- int64_t item_sequence_number,
- int64_t document_sequence_number,
- scoped_refptr<SiteInstanceImpl> site_instance,
- scoped_refptr<SiteInstanceImpl> source_site_instance,
- const GURL& url,
- const Referrer& referrer,
- const std::vector<GURL>& redirect_chain,
- const PageState& page_state,
- const std::string& method,
- int64_t post_id);
+ FrameNavigationEntry(
+ const std::string& frame_unique_name,
+ int64_t item_sequence_number,
+ int64_t document_sequence_number,
+ scoped_refptr<SiteInstanceImpl> site_instance,
+ scoped_refptr<SiteInstanceImpl> source_site_instance,
+ const GURL& url,
+ const Referrer& referrer,
+ const std::vector<GURL>& redirect_chain,
+ const PageState& page_state,
+ const std::string& method,
+ int64_t post_id,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
// Creates a copy of this FrameNavigationEntry that can be modified
// independently from the original.
FrameNavigationEntry* Clone() const;
// Updates all the members of this entry.
- void UpdateEntry(const std::string& frame_unique_name,
- int64_t item_sequence_number,
- int64_t document_sequence_number,
- SiteInstanceImpl* site_instance,
- scoped_refptr<SiteInstanceImpl> source_site_instance,
- const GURL& url,
- const Referrer& referrer,
- const std::vector<GURL>& redirect_chain,
- const PageState& page_state,
- const std::string& method,
- int64_t post_id);
+ void UpdateEntry(
+ const std::string& frame_unique_name,
+ int64_t item_sequence_number,
+ int64_t document_sequence_number,
+ SiteInstanceImpl* site_instance,
+ scoped_refptr<SiteInstanceImpl> source_site_instance,
+ const GURL& url,
+ const Referrer& referrer,
+ const std::vector<GURL>& redirect_chain,
+ const PageState& page_state,
+ const std::string& method,
+ int64_t post_id,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
// The unique name of the frame this entry is for. This is a stable name for
// the frame based on its position in the tree and relation to other named
@@ -137,6 +142,16 @@ class CONTENT_EXPORT FrameNavigationEntry
scoped_refptr<network::ResourceRequestBody> GetPostData(
std::string* content_type) const;
+ // Optional URLLoaderFactory to facilitate blob URL loading.
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory()
+ const {
+ return blob_url_loader_factory_;
+ }
+ void set_blob_url_loader_factory(
+ scoped_refptr<network::SharedURLLoaderFactory> factory) {
+ blob_url_loader_factory_ = std::move(factory);
+ }
+
private:
friend class base::RefCounted<FrameNavigationEntry>;
virtual ~FrameNavigationEntry();
@@ -165,6 +180,7 @@ class CONTENT_EXPORT FrameNavigationEntry
PageState page_state_;
std::string method_;
int64_t post_id_;
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(FrameNavigationEntry);
};
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index fc076ea5376..a99f5ab0ee5 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -42,46 +42,6 @@ base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
const double kLoadingProgressMinimum = 0.1;
const double kLoadingProgressDone = 1.0;
-void RecordUniqueNameSize(FrameTreeNode* node) {
- const auto& unique_name = node->current_replication_state().unique_name;
-
- // Don't record numbers for the root node, which always has an empty unique
- // name.
- if (!node->parent()) {
- DCHECK(unique_name.empty());
- return;
- }
-
- // The original requested name is derived from the browsing context name and
- // is essentially unbounded in size...
- UMA_HISTOGRAM_COUNTS_1M(
- "SessionRestore.FrameUniqueNameOriginalRequestedNameSize",
- node->current_replication_state().name.size());
- // If the name is a frame path, attempt to normalize the statistics based on
- // the number of frames in the frame path.
- if (base::StartsWith(unique_name, "<!--framePath //",
- base::CompareCase::SENSITIVE)) {
- size_t depth = 1;
- while (node->parent()) {
- ++depth;
- node = node->parent();
- }
- // The max possible size of a unique name is 80 characters, so the expected
- // size per component shouldn't be much more than that.
- UMA_HISTOGRAM_COUNTS_100(
- "SessionRestore.FrameUniqueNameWithFramePathSizePerComponent",
- round(unique_name.size() / static_cast<float>(depth)));
- // Blink allows a maximum of ~1024 subframes in a document, so this should
- // be less than (80 character name + 1 character delimiter) * 1024.
- UMA_HISTOGRAM_COUNTS_100000(
- "SessionRestore.FrameUniqueNameWithFramePathSize", unique_name.size());
- } else {
- UMA_HISTOGRAM_COUNTS_100(
- "SessionRestore.FrameUniqueNameFromRequestedNameSize",
- unique_name.size());
- }
-}
-
} // namespace
// This observer watches the opener of its owner FrameTreeNode and clears the
@@ -170,8 +130,6 @@ FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
std::make_pair(frame_tree_node_id_, this));
CHECK(result.second);
- RecordUniqueNameSize(this);
-
// Note: this should always be done last in the constructor.
blame_context_.Initialize();
}
@@ -262,9 +220,6 @@ void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
}
void FrameTreeNode::ResetForNewProcess() {
- current_frame_host()->SetLastCommittedUrl(GURL());
- blame_context_.TakeSnapshot();
-
// Remove child nodes from the tree, then delete them. This destruction
// operation will notify observers.
std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
@@ -360,8 +315,6 @@ void FrameTreeNode::SetFrameName(const std::string& name,
// Note the unique name should only be able to change before the first real
// load is committed, but that's not strongly enforced here.
- if (unique_name != replication_state_.unique_name)
- RecordUniqueNameSize(this);
render_manager_.OnDidUpdateName(name, unique_name);
replication_state_.name = name;
replication_state_.unique_name = unique_name;
@@ -603,8 +556,7 @@ bool FrameTreeNode::StopLoading() {
expected_pending_nav_entry_id =
navigation_request_->navigation_handle()->pending_nav_entry_id();
}
- navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id,
- false /* is_download */);
+ navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
}
ResetNavigationRequest(false, true);
}
diff --git a/chromium/content/browser/frame_host/frame_tree_node_blame_context.cc b/chromium/content/browser/frame_host/frame_tree_node_blame_context.cc
index a99affdbb9d..6ef7d236990 100644
--- a/chromium/content/browser/frame_host/frame_tree_node_blame_context.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node_blame_context.cc
@@ -4,6 +4,7 @@
#include "content/browser/frame_host/frame_tree_node_blame_context.h"
+#include "base/process/process_handle.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event_argument.h"
#include "content/browser/frame_host/frame_tree.h"
@@ -45,13 +46,10 @@ void FrameTreeNodeBlameContext::AsValueInto(
if (!current_frame_host)
return;
- // On Windows, |rph->GetHandle()| does not duplicate ownership of the
- // process handle and the render host still retains it. Therefore, we
- // cannot create a base::Process object, which provides a proper way to get
- // a process id, from the handle. For a stopgap, we use this deprecated
- // function that does not require the ownership (http://crbug.com/417532).
- int process_id = base::GetProcId(
- current_frame_host->GetProcess()->GetHandle());
+ int process_id = base::kNullProcessId;
+ if (current_frame_host->GetProcess()->GetProcess().IsValid())
+ process_id = current_frame_host->GetProcess()->GetProcess().Pid();
+
if (process_id >= 0) {
int routing_id = current_frame_host->GetRoutingID();
DCHECK_NE(routing_id, MSG_ROUTING_NONE);
diff --git a/chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc b/chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
index 5e9ee40d23a..d4397cd9f66 100644
--- a/chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
@@ -208,7 +208,7 @@ TEST_F(FrameTreeNodeBlameContextTest, URLChange) {
trace_analyzer::Start("*");
root()->SetCurrentURL(url1);
root()->SetCurrentURL(url2);
- root()->ResetForNewProcess();
+ root()->SetCurrentURL(GURL());
auto analyzer = trace_analyzer::Stop();
trace_analyzer::TraceEventVector events;
diff --git a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc b/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
deleted file mode 100644
index 9c14f5735ff..00000000000
--- a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2017 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/frame_host/input/legacy_ipc_frame_input_handler.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/input/ime_text_span_conversions.h"
-#include "content/common/input_messages.h"
-
-namespace content {
-
-LegacyIPCFrameInputHandler::LegacyIPCFrameInputHandler(
- RenderFrameHostImpl* frame_host)
- : frame_host_(frame_host), routing_id_(frame_host->GetRoutingID()) {}
-
-LegacyIPCFrameInputHandler::~LegacyIPCFrameInputHandler() {}
-
-void LegacyIPCFrameInputHandler::SetCompositionFromExistingText(
- int32_t start,
- int32_t end,
- const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
- SendInput(std::make_unique<InputMsg_SetCompositionFromExistingText>(
- routing_id_, start, end,
- ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans)));
-}
-
-void LegacyIPCFrameInputHandler::ExtendSelectionAndDelete(int32_t before,
- int32_t after) {
- SendInput(std::make_unique<InputMsg_ExtendSelectionAndDelete>(routing_id_,
- before, after));
-}
-
-void LegacyIPCFrameInputHandler::DeleteSurroundingText(int32_t before,
- int32_t after) {
- SendInput(std::make_unique<InputMsg_DeleteSurroundingText>(routing_id_,
- before, after));
-}
-
-void LegacyIPCFrameInputHandler::DeleteSurroundingTextInCodePoints(
- int32_t before,
- int32_t after) {
- SendInput(std::make_unique<InputMsg_DeleteSurroundingTextInCodePoints>(
- routing_id_, before, after));
-}
-
-void LegacyIPCFrameInputHandler::SetEditableSelectionOffsets(int32_t start,
- int32_t end) {
- SendInput(std::make_unique<InputMsg_SetEditableSelectionOffsets>(routing_id_,
- start, end));
-}
-
-void LegacyIPCFrameInputHandler::ExecuteEditCommand(
- const std::string& command,
- const base::Optional<base::string16>& value) {
- if (!value) {
- SendInput(std::make_unique<InputMsg_ExecuteNoValueEditCommand>(routing_id_,
- command));
- }
-}
-
-void LegacyIPCFrameInputHandler::Undo() {
- SendInput(std::make_unique<InputMsg_Undo>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::Redo() {
- SendInput(std::make_unique<InputMsg_Redo>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::Cut() {
- SendInput(std::make_unique<InputMsg_Cut>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::Copy() {
- SendInput(std::make_unique<InputMsg_Copy>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::CopyToFindPboard() {
-#if defined(OS_MACOSX)
- SendInput(std::make_unique<InputMsg_CopyToFindPboard>(routing_id_));
-#endif
-}
-
-void LegacyIPCFrameInputHandler::Paste() {
- SendInput(std::make_unique<InputMsg_Paste>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::PasteAndMatchStyle() {
- SendInput(std::make_unique<InputMsg_PasteAndMatchStyle>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::Replace(const base::string16& word) {
- SendInput(std::make_unique<InputMsg_Replace>(routing_id_, word));
-}
-
-void LegacyIPCFrameInputHandler::ReplaceMisspelling(
- const base::string16& word) {
- SendInput(std::make_unique<InputMsg_ReplaceMisspelling>(routing_id_, word));
-}
-
-void LegacyIPCFrameInputHandler::Delete() {
- SendInput(std::make_unique<InputMsg_Delete>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::SelectAll() {
- SendInput(std::make_unique<InputMsg_SelectAll>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::CollapseSelection() {
- SendInput(std::make_unique<InputMsg_CollapseSelection>(routing_id_));
-}
-
-void LegacyIPCFrameInputHandler::SelectRange(const gfx::Point& point,
- const gfx::Point& extent) {
- SendInput(std::make_unique<InputMsg_SelectRange>(routing_id_, point, extent));
-}
-
-void LegacyIPCFrameInputHandler::AdjustSelectionByCharacterOffset(
- int32_t start,
- int32_t end,
- blink::mojom::SelectionMenuBehavior selection_menu_behavior) {
- SendInput(std::make_unique<InputMsg_AdjustSelectionByCharacterOffset>(
- routing_id_, start, end,
- selection_menu_behavior == blink::mojom::SelectionMenuBehavior::kShow));
-}
-
-void LegacyIPCFrameInputHandler::MoveRangeSelectionExtent(
- const gfx::Point& extent) {
- SendInput(
- std::make_unique<InputMsg_MoveRangeSelectionExtent>(routing_id_, extent));
-}
-
-void LegacyIPCFrameInputHandler::ScrollFocusedEditableNodeIntoRect(
- const gfx::Rect& rect) {
- SendInput(std::make_unique<InputMsg_ScrollFocusedEditableNodeIntoRect>(
- routing_id_, rect));
-}
-
-void LegacyIPCFrameInputHandler::MoveCaret(const gfx::Point& point) {
- SendInput(std::make_unique<InputMsg_MoveCaret>(routing_id_, point));
-}
-
-void LegacyIPCFrameInputHandler::GetWidgetInputHandler(
- mojom::WidgetInputHandlerAssociatedRequest interface_request,
- mojom::WidgetInputHandlerHostPtr host) {
- NOTREACHED();
-}
-
-void LegacyIPCFrameInputHandler::SendInput(
- std::unique_ptr<IPC::Message> message) {
- static_cast<LegacyInputRouterImpl*>(
- frame_host_->GetRenderWidgetHost()->input_router())
- ->SendInput(std::move(message));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h b/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
deleted file mode 100644
index 8fc6bf9076b..00000000000
--- a/chromium/content/browser/frame_host/input/legacy_ipc_frame_input_handler.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2017 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_FRAME_HOST_INPUT_LEGACY_IPC_FRAME_INPUT_HANDLER_H_
-#define CONTENT_BROWSER_FRAME_HOST_INPUT_LEGACY_IPC_FRAME_INPUT_HANDLER_H_
-
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/common/input/input_handler.mojom.h"
-
-namespace content {
-
-// An instance of a mojom::FrameInputHandler based on chrome IPC.
-// This class is a temporary class to allow the input messages to
-// remain as Chrome IPC messages but progressively work at moving
-// them to mojo.
-class CONTENT_EXPORT LegacyIPCFrameInputHandler
- : public mojom::FrameInputHandler {
- public:
- explicit LegacyIPCFrameInputHandler(RenderFrameHostImpl* frame_host);
- ~LegacyIPCFrameInputHandler() override;
-
- // mojom::FrameInputHandler overrides.
- void SetCompositionFromExistingText(
- int32_t start,
- int32_t end,
- const std::vector<ui::ImeTextSpan>& ime_text_spans) override;
- void ExtendSelectionAndDelete(int32_t before, int32_t after) override;
- void DeleteSurroundingText(int32_t before, int32_t after) override;
- void DeleteSurroundingTextInCodePoints(int32_t before,
- int32_t after) override;
- void SetEditableSelectionOffsets(int32_t start, int32_t end) override;
- void ExecuteEditCommand(const std::string& command,
- const base::Optional<base::string16>& value) override;
- void Undo() override;
- void Redo() override;
- void Cut() override;
- void Copy() override;
- void CopyToFindPboard() override;
- void Paste() override;
- void PasteAndMatchStyle() override;
- void Replace(const base::string16& word) override;
- void ReplaceMisspelling(const base::string16& word) override;
- void Delete() override;
- void SelectAll() override;
- void CollapseSelection() override;
- void SelectRange(const gfx::Point& base, const gfx::Point& extent) override;
- void AdjustSelectionByCharacterOffset(
- int32_t start,
- int32_t end,
- blink::mojom::SelectionMenuBehavior selection_menu_behavior) override;
- void MoveRangeSelectionExtent(const gfx::Point& extent) override;
- void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override;
- void MoveCaret(const gfx::Point& point) override;
- void GetWidgetInputHandler(
- mojom::WidgetInputHandlerAssociatedRequest interface_request,
- mojom::WidgetInputHandlerHostPtr host) override;
-
- private:
- void SendInput(std::unique_ptr<IPC::Message> message);
-
- RenderFrameHostImpl* frame_host_;
- int routing_id_;
-
- DISALLOW_COPY_AND_ASSIGN(LegacyIPCFrameInputHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_FRAME_HOST_INPUT_LEGACY_IPC_FRAME_INPUT_HANDLER_H_
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index 94e29b878e1..ad9de41d1e3 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -40,7 +40,6 @@
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/buildflags.h"
#include "content/common/frame_messages.h"
-#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -51,6 +50,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/bindings_policy.h"
@@ -90,6 +90,9 @@ class InterstitialPageImpl::InterstitialPageRVHDelegateView
void GotFocus(RenderWidgetHostImpl* render_widget_host) override;
void LostFocus(RenderWidgetHostImpl* render_widget_host) override;
void TakeFocus(bool reverse) override;
+ int GetTopControlsHeight() const override;
+ int GetBottomControlsHeight() const override;
+ bool DoBrowserControlsShrinkBlinkSize() const override;
virtual void OnFindReply(int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
@@ -183,6 +186,7 @@ InterstitialPageImpl::InterstitialPageImpl(
create_view_(true),
pause_throbber_(false),
delegate_(delegate),
+ widget_observer_(this),
weak_ptr_factory_(this) {
InitInterstitialPageMap();
}
@@ -227,10 +231,8 @@ void InterstitialPageImpl::Show() {
// cancel the blocked requests. We cannot do that on
// NOTIFY_WEB_CONTENTS_DESTROYED as at that point the RenderViewHost has
// already been destroyed.
- notification_registrar_.Add(
- this, NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
- Source<RenderWidgetHost>(
- controller_->delegate()->GetRenderViewHost()->GetWidget()));
+ widget_observer_.Add(
+ controller_->delegate()->GetRenderViewHost()->GetWidget());
// Update the g_web_contents_to_interstitial_page map.
iter = g_web_contents_to_interstitial_page->find(web_contents_);
@@ -319,6 +321,19 @@ void InterstitialPageImpl::Hide() {
web_contents_ = nullptr;
}
+void InterstitialPageImpl::RenderWidgetHostDestroyed(
+ content::RenderWidgetHost* widget_host) {
+ widget_observer_.Remove(widget_host);
+ if (action_taken_ == NO_ACTION) {
+ // The RenderViewHost is being destroyed (as part of the tab being
+ // closed); make sure we clear the blocked requests.
+ RenderViewHost* rvh = RenderViewHost::From(widget_host);
+ DCHECK(rvh->GetProcess()->GetID() == original_child_id_ &&
+ rvh->GetRoutingID() == original_rvh_id_);
+ TakeActionOnResourceDispatcher(CANCEL);
+ }
+}
+
void InterstitialPageImpl::Observe(
int type,
const NotificationSource& source,
@@ -337,17 +352,6 @@ void InterstitialPageImpl::Observe(
Disable();
TakeActionOnResourceDispatcher(CANCEL);
break;
- case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED:
- if (action_taken_ == NO_ACTION) {
- // The RenderViewHost is being destroyed (as part of the tab being
- // closed); make sure we clear the blocked requests.
- RenderViewHost* rvh =
- RenderViewHost::From(Source<RenderWidgetHost>(source).ptr());
- DCHECK(rvh->GetProcess()->GetID() == original_child_id_ &&
- rvh->GetRoutingID() == original_rvh_id_);
- TakeActionOnResourceDispatcher(CANCEL);
- }
- break;
default:
NOTREACHED();
}
@@ -780,6 +784,11 @@ void InterstitialPageImpl::SetFocusedFrame(FrameTreeNode* node,
}
}
+Visibility InterstitialPageImpl::GetVisibility() const {
+ // Interstitials always occlude the underlying web content.
+ return Visibility::OCCLUDED;
+}
+
void InterstitialPageImpl::CreateNewWidget(int32_t render_process_id,
int32_t route_id,
mojom::WidgetPtr widget,
@@ -980,6 +989,39 @@ void InterstitialPageImpl::InterstitialPageRVHDelegateView::TakeFocus(
web_contents->GetDelegateView()->TakeFocus(reverse);
}
+int InterstitialPageImpl::InterstitialPageRVHDelegateView::
+ GetTopControlsHeight() const {
+ if (!interstitial_page_->web_contents())
+ return 0;
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(interstitial_page_->web_contents());
+ if (!web_contents || !web_contents->GetDelegateView())
+ return 0;
+ return web_contents->GetDelegateView()->GetTopControlsHeight();
+}
+
+int InterstitialPageImpl::InterstitialPageRVHDelegateView::
+ GetBottomControlsHeight() const {
+ if (!interstitial_page_->web_contents())
+ return 0;
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(interstitial_page_->web_contents());
+ if (!web_contents || !web_contents->GetDelegateView())
+ return 0;
+ return web_contents->GetDelegateView()->GetBottomControlsHeight();
+}
+
+bool InterstitialPageImpl::InterstitialPageRVHDelegateView::
+ DoBrowserControlsShrinkBlinkSize() const {
+ if (!interstitial_page_->web_contents())
+ return false;
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(interstitial_page_->web_contents());
+ if (!web_contents || !web_contents->GetDelegateView())
+ return false;
+ return web_contents->GetDelegateView()->DoBrowserControlsShrinkBlinkSize();
+}
+
void InterstitialPageImpl::InterstitialPageRVHDelegateView::OnFindReply(
int request_id, int number_of_matches, const gfx::Rect& selection_rect,
int active_match_ordinal, bool final_update) {
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index 79df2f4834c..d23262f505e 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
#include "build/build_config.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/navigator_delegate.h"
@@ -21,6 +22,7 @@
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/renderer_preferences.h"
#include "url/gurl.h"
@@ -45,6 +47,7 @@ enum ResourceRequestAction {
class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
public NotificationObserver,
public RenderFrameHostDelegate,
+ public RenderWidgetHostObserver,
public RenderViewHostDelegate,
public RenderWidgetHostDelegate,
public NavigatorDelegate {
@@ -134,6 +137,7 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
const gfx::Rect& initial_rect,
bool user_gesture) override;
void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) override;
+ Visibility GetVisibility() const override;
// RenderViewHostDelegate implementation:
RenderViewHostDelegateView* GetDelegateView() override;
@@ -208,6 +212,9 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
DISALLOW_COPY_AND_ASSIGN(UnderlyingContentObserver);
};
+ // RenderWidgetHostObserver implementation:
+ void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override;
+
// Disable the interstitial:
// - if it is not yet showing, then it won't be shown.
// - any command sent by the RenderViewHost will be ignored.
@@ -306,6 +313,8 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
scoped_refptr<SessionStorageNamespace> session_storage_namespace_;
+ ScopedObserver<RenderWidgetHost, RenderWidgetHostObserver> widget_observer_;
+
base::WeakPtrFactory<InterstitialPageImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(InterstitialPageImpl);
diff --git a/chromium/content/browser/frame_host/keep_alive_handle_factory.cc b/chromium/content/browser/frame_host/keep_alive_handle_factory.cc
index a68870d4572..068c8ec250d 100644
--- a/chromium/content/browser/frame_host/keep_alive_handle_factory.cc
+++ b/chromium/content/browser/frame_host/keep_alive_handle_factory.cc
@@ -4,10 +4,8 @@
#include "content/browser/frame_host/keep_alive_handle_factory.h"
-#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
-#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_features.h"
@@ -18,9 +16,11 @@ namespace content {
class KeepAliveHandleFactory::Context final : public base::RefCounted<Context> {
public:
- explicit Context(RenderProcessHost* process_host)
- : process_id_(process_host->GetID()), weak_ptr_factory_(this) {
- DCHECK(!process_host->IsKeepAliveRefCountDisabled());
+ explicit Context(int process_id)
+ : process_id_(process_id), weak_ptr_factory_(this) {
+ RenderProcessHost* process_host = RenderProcessHost::FromID(process_id_);
+ if (!process_host || process_host->IsKeepAliveRefCountDisabled())
+ return;
process_host->IncrementKeepAliveRefCount(
RenderProcessHost::KeepAliveClientType::kFetch);
}
@@ -37,12 +37,11 @@ class KeepAliveHandleFactory::Context final : public base::RefCounted<Context> {
RenderProcessHost::KeepAliveClientType::kFetch);
}
- void DetachLater() {
+ void DetachLater(base::TimeDelta timeout) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostDelayedTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Context::Detach, weak_ptr_factory_.GetWeakPtr()),
- timeout_);
+ base::BindOnce(&Context::Detach, AsWeakPtr()), timeout);
}
void AddBinding(std::unique_ptr<mojom::KeepAliveHandle> impl,
@@ -50,7 +49,7 @@ class KeepAliveHandleFactory::Context final : public base::RefCounted<Context> {
binding_set_.AddBinding(std::move(impl), std::move(request));
}
- void set_timeout(base::TimeDelta timeout) { timeout_ = timeout; }
+ base::WeakPtr<Context> AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
private:
friend class base::RefCounted<Context>;
@@ -59,7 +58,6 @@ class KeepAliveHandleFactory::Context final : public base::RefCounted<Context> {
mojo::StrongBindingSet<mojom::KeepAliveHandle> binding_set_;
const int process_id_;
bool detached_ = false;
- base::TimeDelta timeout_;
base::WeakPtrFactory<Context> weak_ptr_factory_;
@@ -80,19 +78,28 @@ class KeepAliveHandleFactory::KeepAliveHandleImpl final
};
KeepAliveHandleFactory::KeepAliveHandleFactory(RenderProcessHost* process_host)
- : context_(base::MakeRefCounted<Context>(process_host)) {}
+ : process_id_(process_host->GetID()) {}
KeepAliveHandleFactory::~KeepAliveHandleFactory() {
- context_->DetachLater();
+ if (context_)
+ context_->DetachLater(timeout_);
}
void KeepAliveHandleFactory::Create(mojom::KeepAliveHandleRequest request) {
- context_->AddBinding(std::make_unique<KeepAliveHandleImpl>(context_),
- std::move(request));
+ scoped_refptr<Context> context;
+ if (context_) {
+ context = context_.get();
+ } else {
+ context = base::MakeRefCounted<Context>(process_id_);
+ context_ = context->AsWeakPtr();
+ }
+
+ context->AddBinding(std::make_unique<KeepAliveHandleImpl>(context),
+ std::move(request));
}
void KeepAliveHandleFactory::SetTimeout(base::TimeDelta timeout) {
- context_->set_timeout(timeout);
+ timeout_ = timeout;
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/keep_alive_handle_factory.h b/chromium/content/browser/frame_host/keep_alive_handle_factory.h
index 226886ed6e6..d5eb453b468 100644
--- a/chromium/content/browser/frame_host/keep_alive_handle_factory.h
+++ b/chromium/content/browser/frame_host/keep_alive_handle_factory.h
@@ -6,6 +6,8 @@
#define CONTENT_BROWSER_FRAME_HOST_KEEP_ALIVE_HANDLE_FACTORY_H_
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "content/common/frame.mojom.h"
namespace content {
@@ -32,7 +34,9 @@ class KeepAliveHandleFactory final {
class KeepAliveHandleImpl;
class Context;
- scoped_refptr<Context> context_;
+ const int process_id_;
+ base::TimeDelta timeout_;
+ base::WeakPtr<Context> context_;
DISALLOW_COPY_AND_ASSIGN(KeepAliveHandleFactory);
};
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
index 1093809604f..7136ac7c8df 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -156,7 +156,13 @@ void NavigationControllerAndroid::ReloadBypassingCache(
navigation_controller_->Reload(ReloadType::BYPASSING_CACHE, check_for_repost);
}
-void NavigationControllerAndroid::RequestRestoreLoad(
+jboolean NavigationControllerAndroid::NeedsReload(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ return navigation_controller_->NeedsReload();
+}
+
+void NavigationControllerAndroid::SetNeedsReload(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
navigation_controller_->SetNeedsReload();
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.h b/chromium/content/browser/frame_host/navigation_controller_android.h
index b87821cd542..0a3afdfea50 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.h
+++ b/chromium/content/browser/frame_host/navigation_controller_android.h
@@ -55,8 +55,10 @@ class CONTENT_EXPORT NavigationControllerAndroid {
void ReloadBypassingCache(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean check_for_repost);
- void RequestRestoreLoad(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
+ jboolean NeedsReload(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
+ void SetNeedsReload(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
void CancelPendingReload(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
void GoToNavigationIndex(JNIEnv* env,
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 475a2bd192d..74ff6b4286c 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -251,7 +251,8 @@ std::unique_ptr<NavigationEntry> NavigationController::CreateNavigationEntry(
ui::PageTransition transition,
bool is_renderer_initiated,
const std::string& extra_headers,
- BrowserContext* browser_context) {
+ BrowserContext* browser_context,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
// Fix up the given URL before letting it be rewritten, so that any minor
// cleanup (e.g., removing leading dots) will not lead to a virtual URL.
GURL dest_url(url);
@@ -270,8 +271,8 @@ std::unique_ptr<NavigationEntry> NavigationController::CreateNavigationEntry(
NavigationEntryImpl* entry = new NavigationEntryImpl(
nullptr, // The site instance for tabs is sent on navigation
// (WebContents::GetSiteInstance).
- loaded_url, referrer, base::string16(), transition,
- is_renderer_initiated);
+ loaded_url, referrer, base::string16(), transition, is_renderer_initiated,
+ blob_url_loader_factory);
entry->SetVirtualURL(dest_url);
entry->set_user_typed_url(dest_url);
entry->set_update_virtual_url_with_url(reverse_on_redirect);
@@ -447,15 +448,18 @@ void NavigationControllerImpl::Reload(ReloadType reload_type,
// Create a navigation entry that resembles the current one, but do not
// copy page id, site instance, content state, or timestamp.
NavigationEntryImpl* nav_entry = NavigationEntryImpl::FromNavigationEntry(
- CreateNavigationEntry(
- entry->GetURL(), entry->GetReferrer(), entry->GetTransitionType(),
- false, entry->extra_headers(), browser_context_).release());
+ CreateNavigationEntry(entry->GetURL(), entry->GetReferrer(),
+ entry->GetTransitionType(), false,
+ entry->extra_headers(), browser_context_,
+ nullptr /* blob_url_loader_factory */)
+ .release());
// Mark the reload type as NO_RELOAD, so navigation will not be considered
// a reload in the renderer.
reload_type = ReloadType::NONE;
nav_entry->set_should_replace_entry(true);
+ nav_entry->set_is_renderer_initiated(entry->is_renderer_initiated());
pending_entry_ = nav_entry;
DCHECK_EQ(-1, pending_entry_index_);
} else {
@@ -794,7 +798,7 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
node, -1, -1, nullptr,
static_cast<SiteInstanceImpl*>(params.source_site_instance.get()),
params.url, params.referrer, params.redirect_chain, PageState(),
- "GET", -1);
+ "GET", -1, params.blob_url_loader_factory);
}
}
@@ -805,11 +809,11 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
base::ReplaceChars(params.extra_headers, "\n", "\r\n", &extra_headers_crlf);
entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
params.url, params.referrer, params.transition_type,
- params.is_renderer_initiated, extra_headers_crlf, browser_context_));
+ params.is_renderer_initiated, extra_headers_crlf, browser_context_,
+ params.blob_url_loader_factory));
entry->set_source_site_instance(
static_cast<SiteInstanceImpl*>(params.source_site_instance.get()));
entry->SetRedirectChain(params.redirect_chain);
- entry->set_suggested_filename(params.suggested_filename);
}
// Set the FTN ID (only used in non-site-per-process, for tests).
@@ -882,7 +886,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
LoadCommittedDetails* details,
- bool is_navigation_within_page,
+ bool is_same_document_navigation,
NavigationHandleImpl* navigation_handle) {
is_initial_navigation_ = false;
@@ -917,7 +921,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
details->type = ClassifyNavigation(rfh, params);
// is_same_document must be computed before the entry gets committed.
- details->is_same_document = is_navigation_within_page;
+ details->is_same_document = is_same_document_navigation;
// Save reload type and timestamp for a reload navigation to detect
// consecutive reloads when the next reload is requested.
@@ -1181,7 +1185,7 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
rfh->frame_tree_node()->unique_name(), params.item_sequence_number,
params.document_sequence_number, rfh->GetSiteInstance(), nullptr,
params.url, params.referrer, params.redirects, params.page_state,
- params.method, params.post_id);
+ params.method, params.post_id, nullptr /* blob_url_loader_factory */);
new_entry = GetLastCommittedEntry()->CloneAndReplace(
frame_entry, true, rfh->frame_tree_node(),
@@ -1461,7 +1465,7 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
rfh->frame_tree_node(), params.item_sequence_number,
params.document_sequence_number, rfh->GetSiteInstance(), nullptr,
params.url, params.referrer, params.redirects, params.page_state,
- params.method, params.post_id);
+ params.method, params.post_id, nullptr /* blob_url_loader_factory */);
// The redirected to page should not inherit the favicon from the previous
// page.
@@ -1529,7 +1533,7 @@ void NavigationControllerImpl::RendererDidNavigateToSamePage(
rfh->frame_tree_node(), params.item_sequence_number,
params.document_sequence_number, rfh->GetSiteInstance(), nullptr,
params.url, params.referrer, params.redirects, params.page_state,
- params.method, params.post_id);
+ params.method, params.post_id, nullptr /* blob_url_loader_factory */);
DiscardNonCommittedEntries();
}
@@ -1560,7 +1564,7 @@ void NavigationControllerImpl::RendererDidNavigateNewSubframe(
rfh->frame_tree_node()->unique_name(), params.item_sequence_number,
params.document_sequence_number, rfh->GetSiteInstance(), nullptr,
params.url, params.referrer, params.redirects, params.page_state,
- params.method, params.post_id));
+ params.method, params.post_id, nullptr /* blob_url_loader_factory */));
std::unique_ptr<NavigationEntryImpl> new_entry =
GetLastCommittedEntry()->CloneAndReplace(
@@ -1602,8 +1606,8 @@ bool NavigationControllerImpl::RendererDidNavigateAutoSubframe(
// (https://crbug.com/373041).
// TODO(creis): For now, restrict this check to HTTP(S) origins, because
// about:blank, file, and unique origins are more subtle to get right.
- // We'll abstract out the relevant checks from IsURLInPageNavigation and
- // share them here. See https://crbug.com/618104.
+ // We'll abstract out the relevant checks from IsURLSameDocumentNavigation
+ // and share them here. See https://crbug.com/618104.
const GURL& dest_top_url = GetEntryAtIndex(entry_index)->GetURL();
const GURL& current_top_url = GetLastCommittedEntry()->GetURL();
if (current_top_url.SchemeIsHTTPOrHTTPS() &&
@@ -1630,7 +1634,7 @@ bool NavigationControllerImpl::RendererDidNavigateAutoSubframe(
rfh->frame_tree_node(), params.item_sequence_number,
params.document_sequence_number, rfh->GetSiteInstance(), nullptr,
params.url, params.referrer, params.redirects, params.page_state,
- params.method, params.post_id);
+ params.method, params.post_id, nullptr /* blob_url_loader_factory */);
return send_commit_notification;
}
@@ -1845,6 +1849,156 @@ void NavigationControllerImpl::DeleteNavigationEntries(
delegate()->NotifyNavigationEntriesDeleted();
}
+void NavigationControllerImpl::DiscardPendingEntry(bool was_failure) {
+ // It is not safe to call DiscardPendingEntry while NavigateToEntry is in
+ // progress, since this will cause a use-after-free. (We only allow this
+ // when the tab is being destroyed for shutdown, since it won't return to
+ // NavigateToEntry in that case.) http://crbug.com/347742.
+ CHECK(!in_navigate_to_pending_entry_ || delegate_->IsBeingDestroyed());
+
+ if (was_failure && pending_entry_) {
+ failed_pending_entry_id_ = pending_entry_->GetUniqueID();
+ } else {
+ failed_pending_entry_id_ = 0;
+ }
+
+ if (pending_entry_) {
+ if (pending_entry_index_ == -1)
+ delete pending_entry_;
+ pending_entry_index_ = -1;
+ pending_entry_ = nullptr;
+ }
+}
+
+void NavigationControllerImpl::SetPendingNavigationSSLError(bool error) {
+ if (pending_entry_)
+ pending_entry_->set_ssl_error(error);
+}
+
+bool NavigationControllerImpl::StartHistoryNavigationInNewSubframe(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& default_url) {
+ NavigationEntryImpl* entry =
+ GetEntryWithUniqueID(render_frame_host->nav_entry_id());
+ if (!entry)
+ return false;
+
+ FrameNavigationEntry* frame_entry =
+ entry->GetFrameEntry(render_frame_host->frame_tree_node());
+ if (!frame_entry)
+ return false;
+
+ // Track how often history navigations load a different URL into a subframe
+ // than the frame's default URL.
+ bool restoring_different_url = frame_entry->url() != default_url;
+ UMA_HISTOGRAM_BOOLEAN("SessionRestore.RestoredSubframeURL",
+ restoring_different_url);
+ // If this frame's unique name uses a frame path, record the name length.
+ // If these names are long in practice, then a proposed plan to truncate
+ // unique names might affect restore behavior, since it is complex to deal
+ // with truncated names inside frame paths.
+ if (restoring_different_url) {
+ const std::string& unique_name =
+ render_frame_host->frame_tree_node()->unique_name();
+ const char kFramePathPrefix[] = "<!--framePath ";
+ if (base::StartsWith(unique_name, kFramePathPrefix,
+ base::CompareCase::SENSITIVE)) {
+ UMA_HISTOGRAM_COUNTS("SessionRestore.RestoreSubframeFramePathLength",
+ unique_name.size());
+ }
+ }
+
+ // TODO(clamy): Create a NavigationRequest here and pass it to Navigator for
+ // navigating.
+ return render_frame_host->frame_tree_node()->navigator()->NavigateToEntry(
+ render_frame_host->frame_tree_node(), *frame_entry, *entry,
+ ReloadType::NONE, false, true, false, nullptr,
+ nullptr /* navigation_ui_data */);
+}
+
+void NavigationControllerImpl::NavigateFromFrameProxy(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ bool is_renderer_initiated,
+ SiteInstance* source_site_instance,
+ const Referrer& referrer,
+ ui::PageTransition page_transition,
+ bool should_replace_current_entry,
+ const std::string& method,
+ scoped_refptr<network::ResourceRequestBody> post_body,
+ const std::string& extra_headers,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
+ FrameTreeNode* node = render_frame_host->frame_tree_node();
+ // Create a NavigationEntry for the transfer, without making it the pending
+ // entry. Subframe transfers should have a clone of the last committed entry
+ // with a FrameNavigationEntry for the target frame. Main frame transfers
+ // should have a new NavigationEntry.
+ // TODO(creis): Make this unnecessary by creating (and validating) the params
+ // directly, passing them to the destination RenderFrameHost. See
+ // https://crbug.com/536906.
+ std::unique_ptr<NavigationEntryImpl> entry;
+ if (!node->IsMainFrame()) {
+ // Subframe case: create FrameNavigationEntry.
+ if (GetLastCommittedEntry()) {
+ entry = GetLastCommittedEntry()->Clone();
+ entry->set_extra_headers(extra_headers);
+ // TODO(arthursonzogni): What about |is_renderer_initiated|?
+ // Renderer-initiated navigation that target a remote frame are currently
+ // classified as browser-initiated when this one has already navigated.
+ // See https://crbug.com/722251.
+ } else {
+ // If there's no last committed entry, create an entry for about:blank
+ // with a subframe entry for our destination.
+ // TODO(creis): Ensure this case can't exist in https://crbug.com/524208.
+ entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
+ GURL(url::kAboutBlankURL), referrer, page_transition,
+ is_renderer_initiated, extra_headers, browser_context_,
+ nullptr /* blob_url_loader_factory */));
+ }
+ entry->AddOrUpdateFrameEntry(
+ node, -1, -1, nullptr,
+ static_cast<SiteInstanceImpl*>(source_site_instance), url, referrer,
+ std::vector<GURL>(), PageState(), method, -1, blob_url_loader_factory);
+ } else {
+ // Main frame case.
+ entry = NavigationEntryImpl::FromNavigationEntry(CreateNavigationEntry(
+ url, referrer, page_transition, is_renderer_initiated, extra_headers,
+ browser_context_, blob_url_loader_factory));
+ entry->root_node()->frame_entry->set_source_site_instance(
+ static_cast<SiteInstanceImpl*>(source_site_instance));
+ entry->root_node()->frame_entry->set_method(method);
+ }
+
+ // Don't allow an entry replacement if there is no entry to replace.
+ // http://crbug.com/457149
+ if (should_replace_current_entry && GetEntryCount() > 0)
+ entry->set_should_replace_entry(true);
+ if (GetLastCommittedEntry() &&
+ GetLastCommittedEntry()->GetIsOverridingUserAgent()) {
+ entry->SetIsOverridingUserAgent(true);
+ }
+ // TODO(creis): Set user gesture and intent received timestamp on Android.
+
+ // We may not have successfully added the FrameNavigationEntry to |entry|
+ // above (per https://crbug.com/608402), in which case we create it from
+ // scratch. This works because we do not depend on |frame_entry| being inside
+ // |entry| during NavigateToEntry. This will go away when we shortcut this
+ // further in https://crbug.com/536906.
+ scoped_refptr<FrameNavigationEntry> frame_entry(entry->GetFrameEntry(node));
+ if (!frame_entry) {
+ frame_entry = new FrameNavigationEntry(
+ node->unique_name(), -1, -1, nullptr,
+ static_cast<SiteInstanceImpl*>(source_site_instance), url, referrer,
+ std::vector<GURL>(), PageState(), method, -1, blob_url_loader_factory);
+ }
+
+ // TODO(clamy): Create a NavigationRequest here and pass it to Navigator for
+ // navigating.
+ render_frame_host->frame_tree_node()->navigator()->NavigateToEntry(
+ node, *frame_entry, *entry.get(), ReloadType::NONE, false, false, false,
+ post_body, nullptr /* navigation_ui_data */);
+}
+
void NavigationControllerImpl::ClearAllScreenshots() {
screenshot_manager_->ClearAllScreenshots();
}
@@ -2299,32 +2453,6 @@ void NavigationControllerImpl::DiscardNonCommittedEntriesInternal() {
DiscardTransientEntry();
}
-void NavigationControllerImpl::DiscardPendingEntry(bool was_failure) {
- // It is not safe to call DiscardPendingEntry while NavigateToEntry is in
- // progress, since this will cause a use-after-free. (We only allow this
- // when the tab is being destroyed for shutdown, since it won't return to
- // NavigateToEntry in that case.) http://crbug.com/347742.
- CHECK(!in_navigate_to_pending_entry_ || delegate_->IsBeingDestroyed());
-
- if (was_failure && pending_entry_) {
- failed_pending_entry_id_ = pending_entry_->GetUniqueID();
- } else {
- failed_pending_entry_id_ = 0;
- }
-
- if (pending_entry_) {
- if (pending_entry_index_ == -1)
- delete pending_entry_;
- pending_entry_index_ = -1;
- pending_entry_ = nullptr;
- }
-}
-
-void NavigationControllerImpl::SetPendingNavigationSSLError(bool error) {
- if (pending_entry_)
- pending_entry_->set_ssl_error(error);
-}
-
void NavigationControllerImpl::DiscardTransientEntry() {
if (transient_entry_index_ == -1)
return;
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index d3be697cb0c..3f1f1ceff6d 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -93,6 +93,29 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
void DeleteNavigationEntries(
const DeletionPredicate& deletionPredicate) override;
+ // Starts a navigation in a newly created subframe as part of a history
+ // navigation. Returns true if the history navigation could start, false
+ // otherwise. If this returns false, the caller should do a regular
+ // navigation to |default_url| should be done instead.
+ bool StartHistoryNavigationInNewSubframe(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& default_url);
+
+ // Called when a document requests a navigation through a
+ // RenderFrameProxyHost.
+ void NavigateFromFrameProxy(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ bool is_renderer_initiated,
+ SiteInstance* source_site_instance,
+ const Referrer& referrer,
+ ui::PageTransition page_transition,
+ bool should_replace_current_entry,
+ const std::string& method,
+ scoped_refptr<network::ResourceRequestBody> post_body,
+ const std::string& extra_headers,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
+
void ClearAllScreenshots() override;
// Whether this is the initial navigation in an unmodified new tab. In this
@@ -138,7 +161,7 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
LoadCommittedDetails* details,
- bool is_navigation_within_page,
+ bool is_same_document_navigation,
NavigationHandleImpl* navigation_handle);
// Notifies us that we just became active. This is used by the WebContentsImpl
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 1462dab7844..bfe29504506 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -1430,79 +1430,73 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Verify that reloading a page with url anchor scrolls to correct position.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadWithUrlAnchor) {
- GURL url1(embedded_test_server()->GetURL(
- "/navigation_controller/reload-with-url-anchor.html#d2"));
- EXPECT_TRUE(NavigateToURL(shell(), url1));
+ GURL url(embedded_test_server()->GetURL(
+ "/navigation_controller/reload-with-url-anchor.html#center-element"));
+ EXPECT_TRUE(NavigateToURL(shell(), url));
- std::string script =
- "domAutomationController.send(document.getElementById('div').scrollTop)";
- double value = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), script, &value));
+ double window_scroll_y = 0;
+ std::string get_window_scroll_y =
+ "domAutomationController.send(window.scrollY);";
+ EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
+ &window_scroll_y));
- double expected = 100;
+ // The 'center-element' y-position is 2000px. 2000px is an arbitrary value.
+ double expected_window_scroll_y = 2000;
if (IsUseZoomForDSFEnabled()) {
float device_scale_factor = shell()
->web_contents()
->GetRenderWidgetHostView()
->GetDeviceScaleFactor();
- expected = floor(device_scale_factor * expected) / device_scale_factor;
+ expected_window_scroll_y =
+ floor(device_scale_factor * expected_window_scroll_y) /
+ device_scale_factor;
}
- EXPECT_FLOAT_EQ(expected, value);
+ EXPECT_FLOAT_EQ(expected_window_scroll_y, window_scroll_y);
// Reload.
ReloadBlockUntilNavigationsComplete(shell(), 1);
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), script, &value));
- EXPECT_FLOAT_EQ(expected, value);
+ EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
+ &window_scroll_y));
+ EXPECT_FLOAT_EQ(expected_window_scroll_y, window_scroll_y);
}
// Verify that reloading a page with url anchor and scroll scrolls to correct
// position.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
ReloadWithUrlAnchorAndScroll) {
- GURL url1(embedded_test_server()->GetURL(
- "/navigation_controller/reload-with-url-anchor.html#d2"));
- EXPECT_TRUE(NavigateToURL(shell(), url1));
+ GURL url(embedded_test_server()->GetURL(
+ "/navigation_controller/reload-with-url-anchor.html#center-element"));
+ EXPECT_TRUE(NavigateToURL(shell(), url));
- std::string script_scroll_down = "window.scroll(0, 10)";
+ // The 'center-element' y-position is 2000px. This script scrolls the view
+ // 100px below this element. 2000px and 100px are arbitrary values.
+ std::string script_scroll_down = "window.scroll(0, 2100)";
EXPECT_TRUE(ExecuteScript(shell(), script_scroll_down));
- std::string get_div_scroll_top =
- "domAutomationController.send(document.getElementById('div').scrollTop)";
std::string get_window_scroll_y =
"domAutomationController.send(window.scrollY)";
- double div_scroll_top = 0;
double window_scroll_y = 0;
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_div_scroll_top,
- &div_scroll_top));
EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
&window_scroll_y));
- double expected_div_scroll_top = 100;
- double expected_window_scroll_y = 10;
+ double expected_window_scroll_y = 2100;
if (IsUseZoomForDSFEnabled()) {
float device_scale_factor = shell()
->web_contents()
->GetRenderWidgetHostView()
->GetDeviceScaleFactor();
- expected_div_scroll_top =
- floor(device_scale_factor * expected_div_scroll_top) /
- device_scale_factor;
expected_window_scroll_y =
floor(device_scale_factor * expected_window_scroll_y) /
device_scale_factor;
}
- EXPECT_FLOAT_EQ(expected_div_scroll_top, div_scroll_top);
EXPECT_FLOAT_EQ(expected_window_scroll_y, window_scroll_y);
// Reload.
ReloadBlockUntilNavigationsComplete(shell(), 1);
- EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_div_scroll_top,
- &div_scroll_top));
EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), get_window_scroll_y,
&window_scroll_y));
- EXPECT_FLOAT_EQ(expected_div_scroll_top, div_scroll_top);
EXPECT_FLOAT_EQ(expected_window_scroll_y, window_scroll_y);
}
@@ -3845,9 +3839,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// it has the same FrameNavigationEntry structure.
std::unique_ptr<NavigationEntryImpl> restored_entry =
NavigationEntryImpl::FromNavigationEntry(
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
main_url_a, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
- std::string(), controller.GetBrowserContext()));
+ std::string(), controller.GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
EXPECT_EQ(0U, restored_entry->root_node()->children.size());
restored_entry->SetPageState(entry2->GetPageState());
@@ -3915,9 +3910,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// its default URL.
std::unique_ptr<NavigationEntryImpl> restored_entry =
NavigationEntryImpl::FromNavigationEntry(
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
main_url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
- std::string(), controller.GetBrowserContext()));
+ std::string(), controller.GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
restored_entry->SetPageState(PageState::CreateFromURL(main_url));
EXPECT_EQ(0U, restored_entry->root_node()->children.size());
@@ -4501,9 +4497,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, CloneNamedWindow) {
EXPECT_TRUE(NavigateToURL(shell(), url_2));
// Clone the tab and load the page.
- std::unique_ptr<WebContentsImpl> new_tab(
- static_cast<WebContentsImpl*>(shell()->web_contents()->Clone()));
- NavigationController& new_controller = new_tab->GetController();
+ std::unique_ptr<WebContents> new_tab = shell()->web_contents()->Clone();
+ WebContentsImpl* new_tab_impl = static_cast<WebContentsImpl*>(new_tab.get());
+ NavigationController& new_controller = new_tab_impl->GetController();
EXPECT_TRUE(new_controller.IsInitialNavigation());
EXPECT_TRUE(new_controller.NeedsReload());
{
@@ -4538,9 +4534,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url_1));
// Clone the tab and load the page.
- std::unique_ptr<WebContentsImpl> new_tab(
- static_cast<WebContentsImpl*>(shell()->web_contents()->Clone()));
- NavigationController& new_controller = new_tab->GetController();
+ std::unique_ptr<WebContents> new_tab = shell()->web_contents()->Clone();
+ WebContentsImpl* new_tab_impl = static_cast<WebContentsImpl*>(new_tab.get());
+ NavigationController& new_controller = new_tab_impl->GetController();
EXPECT_TRUE(new_controller.IsInitialNavigation());
EXPECT_TRUE(new_controller.NeedsReload());
{
@@ -4574,9 +4570,9 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url_2));
// Clone the tab but don't load last committed page.
- std::unique_ptr<WebContentsImpl> new_tab(
- static_cast<WebContentsImpl*>(shell()->web_contents()->Clone()));
- NavigationController& new_controller = new_tab->GetController();
+ std::unique_ptr<WebContents> new_tab = shell()->web_contents()->Clone();
+ WebContentsImpl* new_tab_impl = static_cast<WebContentsImpl*>(new_tab.get());
+ NavigationController& new_controller = new_tab_impl->GetController();
EXPECT_TRUE(new_controller.IsInitialNavigation());
EXPECT_TRUE(new_controller.NeedsReload());
@@ -4589,7 +4585,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// Make sure the new tab isn't still loading.
EXPECT_EQ(url_1, new_controller.GetLastCommittedEntry()->GetURL());
- EXPECT_FALSE(new_tab->IsLoading());
+ EXPECT_FALSE(new_tab_impl->IsLoading());
// Also check going back in the original tab after a renderer crash.
NavigationController& controller = shell()->web_contents()->GetController();
@@ -4897,9 +4893,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerOopifBrowserTest,
// 3. Create a NavigationEntry with the same PageState as |entry2|.
std::unique_ptr<NavigationEntryImpl> restored_entry =
NavigationEntryImpl::FromNavigationEntry(
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
main_url_a, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
- std::string(), controller.GetBrowserContext()));
+ std::string(), controller.GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
EXPECT_EQ(0U, restored_entry->root_node()->children.size());
restored_entry->SetPageState(entry2->GetPageState());
@@ -6281,10 +6278,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(url_1, root->current_url());
// Clone the tab without navigating it.
- std::unique_ptr<WebContentsImpl> new_tab(
- static_cast<WebContentsImpl*>(shell()->web_contents()->Clone()));
- NavigationController& new_controller = new_tab->GetController();
- FrameTreeNode* new_root = new_tab->GetFrameTree()->root();
+ std::unique_ptr<WebContents> new_tab = shell()->web_contents()->Clone();
+ WebContentsImpl* new_tab_impl = static_cast<WebContentsImpl*>(new_tab.get());
+ NavigationController& new_controller = new_tab_impl->GetController();
+ FrameTreeNode* new_root = new_tab_impl->GetFrameTree()->root();
EXPECT_TRUE(new_controller.IsInitialNavigation());
EXPECT_TRUE(new_controller.NeedsReload());
@@ -8140,39 +8137,4 @@ IN_PROC_BROWSER_TEST_F(ContentBrowserTest, DataURLSameDocumentNavigation) {
EXPECT_TRUE(capturer.is_same_document());
}
-IN_PROC_BROWSER_TEST_F(ContentBrowserTest, HideDownloadFromUnmodifiedNewTab) {
- GURL url("data:application/octet-stream,");
-
- const NavigationControllerImpl& controller =
- static_cast<const NavigationControllerImpl&>(
- shell()->web_contents()->GetController());
-
- {
- base::ScopedAllowBlockingForTesting allow_blocking;
- base::ScopedTempDir downloads_directory;
- ASSERT_TRUE(downloads_directory.CreateUniqueTempDir());
- DownloadManager* download_manager = BrowserContext::GetDownloadManager(
- shell()->web_contents()->GetBrowserContext());
- ShellDownloadManagerDelegate* download_delegate =
- static_cast<ShellDownloadManagerDelegate*>(
- download_manager->GetDelegate());
- download_delegate->SetDownloadBehaviorForTesting(
- downloads_directory.GetPath());
-
- DownloadTestObserverTerminal observer(
- download_manager, 1, DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
-
- OpenURLParams params(url, Referrer(), WindowOpenDisposition::CURRENT_TAB,
- ui::PAGE_TRANSITION_LINK, true);
- params.suggested_filename = std::string("foo");
-
- shell()->web_contents()->OpenURL(params);
- WaitForLoadStop(shell()->web_contents());
- observer.WaitForFinished();
- }
-
- EXPECT_FALSE(controller.GetPendingEntry());
- EXPECT_FALSE(controller.GetVisibleEntry());
-}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
index cfe018f6924..56e15a9b56f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -651,8 +651,6 @@ void CheckNavigationEntryMatchLoadParams(
EXPECT_EQ(should_override, entry->GetIsOverridingUserAgent());
}
EXPECT_EQ(load_params.post_data, entry->GetPostData());
- EXPECT_EQ(load_params.transferred_global_request_id,
- entry->transferred_global_request_id());
}
TEST_F(NavigationControllerTest, LoadURLWithParams) {
@@ -2758,7 +2756,7 @@ TEST_F(NavigationControllerTest, SameDocument_Replace) {
// window.location.replace("#a");
// window.location='http://foo3/';
// </script>
-TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
+TEST_F(NavigationControllerTest, ClientRedirectAfterSameDocumentNavigation) {
NavigationControllerImpl& controller = controller_impl();
// Load an initial page.
@@ -2777,7 +2775,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
navigation_entry_committed_counter_ = 0;
}
- // Navigate within the page using location.replace.
+ // Perform same-document navigation using location.replace.
{
const GURL url("http://foo2/#a");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
@@ -2921,17 +2919,19 @@ TEST_F(NavigationControllerTest, RestoreNavigate) {
GURL url("http://foo");
std::vector<std::unique_ptr<NavigationEntry>> entries;
std::unique_ptr<NavigationEntry> entry =
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false, std::string(),
- browser_context());
+ browser_context(), nullptr /* blob_url_loader_factory */);
entry->SetTitle(base::ASCIIToUTF16("Title"));
entry->SetPageState(PageState::CreateFromEncodedData("state"));
const base::Time timestamp = base::Time::Now();
entry->SetTimestamp(timestamp);
entries.push_back(std::move(entry));
- std::unique_ptr<WebContentsImpl> our_contents(static_cast<WebContentsImpl*>(
- WebContents::Create(WebContents::CreateParams(browser_context()))));
- NavigationControllerImpl& our_controller = our_contents->GetController();
+ std::unique_ptr<WebContents> our_contents =
+ WebContents::Create(WebContents::CreateParams(browser_context()));
+ WebContentsImpl* raw_our_contents =
+ static_cast<WebContentsImpl*>(our_contents.get());
+ NavigationControllerImpl& our_controller = raw_our_contents->GetController();
our_controller.Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -2963,7 +2963,7 @@ TEST_F(NavigationControllerTest, RestoreNavigate) {
params.method = "GET";
params.page_state = PageState::CreateFromURL(url);
TestRenderFrameHost* main_rfh =
- static_cast<TestRenderFrameHost*>(our_contents->GetMainFrame());
+ static_cast<TestRenderFrameHost*>(raw_our_contents->GetMainFrame());
main_rfh->PrepareForCommit();
main_rfh->SendNavigateWithParams(&params, false);
@@ -2990,15 +2990,17 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
GURL url("http://foo");
std::vector<std::unique_ptr<NavigationEntry>> entries;
std::unique_ptr<NavigationEntry> new_entry =
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false, std::string(),
- browser_context());
+ browser_context(), nullptr /* blob_url_loader_factory */);
new_entry->SetTitle(base::ASCIIToUTF16("Title"));
new_entry->SetPageState(PageState::CreateFromEncodedData("state"));
entries.push_back(std::move(new_entry));
- std::unique_ptr<WebContentsImpl> our_contents(static_cast<WebContentsImpl*>(
- WebContents::Create(WebContents::CreateParams(browser_context()))));
- NavigationControllerImpl& our_controller = our_contents->GetController();
+ std::unique_ptr<WebContents> our_contents =
+ WebContents::Create(WebContents::CreateParams(browser_context()));
+ WebContentsImpl* raw_our_contents =
+ static_cast<WebContentsImpl*>(our_contents.get());
+ NavigationControllerImpl& our_controller = raw_our_contents->GetController();
our_controller.Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -3043,7 +3045,7 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
params.method = "GET";
params.page_state = PageState::CreateFromURL(url);
TestRenderFrameHost* main_rfh =
- static_cast<TestRenderFrameHost*>(our_contents->GetMainFrame());
+ static_cast<TestRenderFrameHost*>(raw_our_contents->GetMainFrame());
main_rfh->PrepareForCommit();
main_rfh->SendNavigateWithParams(&params, false);
@@ -4052,7 +4054,7 @@ TEST_F(NavigationControllerTest, CopyStateFrom) {
contents()->CommitPendingNavigation();
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_controller.CopyStateFrom(controller, true);
@@ -4101,7 +4103,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune) {
EXPECT_EQ(instance1, instance2);
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_contents->ExpectSetHistoryOffsetAndLength(2, 3);
@@ -4139,7 +4141,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune2) {
contents()->CommitPendingNavigation();
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_contents->ExpectSetHistoryOffsetAndLength(1, 2);
@@ -4167,7 +4169,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPrune3) {
NavigateAndCommit(url2);
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_contents->NavigateAndCommit(url4);
@@ -4197,7 +4199,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneNotLast) {
NavigateAndCommit(url2);
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_contents->NavigateAndCommit(url4);
@@ -4231,7 +4233,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending) {
contents()->CommitPendingNavigation();
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_controller.LoadURL(
@@ -4265,7 +4267,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending2) {
NavigateAndCommit(url1);
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url2a);
// Simulate a client redirect, which has the same page ID as entry 2a.
@@ -4306,7 +4308,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneSourcePending) {
controller.GoBack();
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_contents->ExpectSetHistoryOffsetAndLength(2, 3);
@@ -4393,7 +4395,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntries) {
NavigateAndCommit(url3);
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url4);
other_contents->ExpectSetHistoryOffsetAndLength(2, 3);
@@ -4434,7 +4436,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneReplaceEntry) {
EXPECT_EQ(instance1, instance2);
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_contents->ExpectSetHistoryOffsetAndLength(1, 2);
@@ -4477,7 +4479,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneMaxEntriesReplaceEntry) {
NavigateAndCommit(url3);
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url4);
other_contents->ExpectSetHistoryOffsetAndLength(2, 3);
@@ -4511,15 +4513,16 @@ TEST_F(NavigationControllerTest, CopyRestoredStateAndNavigate) {
std::vector<std::unique_ptr<NavigationEntry>> entries;
for (size_t i = 0; i < arraysize(kRestoredUrls); ++i) {
std::unique_ptr<NavigationEntry> entry =
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
kRestoredUrls[i], Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
- std::string(), browser_context());
+ std::string(), browser_context(),
+ nullptr /* blob_url_loader_factory */);
entries.push_back(std::move(entry));
}
// Create a WebContents with restored entries.
std::unique_ptr<TestWebContents> source_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& source_controller =
source_contents->GetController();
source_controller.Restore(entries.size() - 1,
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index 039906ce78e..c434d64daa7 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -67,7 +67,8 @@ void RecursivelyGenerateFrameEntries(
nullptr, GURL(state.url_string.value_or(base::string16())),
Referrer(GURL(state.referrer.value_or(base::string16())),
state.referrer_policy),
- std::vector<GURL>(), PageState::CreateFromEncodedData(data), "GET", -1);
+ std::vector<GURL>(), PageState::CreateFromEncodedData(data), "GET", -1,
+ nullptr /* blob_url_loader_factory */);
// Don't pass the file list to subframes, since that would result in multiple
// copies of it ending up in the combined list in GetPageState (via
@@ -234,9 +235,13 @@ std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::FromNavigationEntry(
}
NavigationEntryImpl::NavigationEntryImpl()
- : NavigationEntryImpl(nullptr, GURL(), Referrer(), base::string16(),
- ui::PAGE_TRANSITION_LINK, false) {
-}
+ : NavigationEntryImpl(nullptr,
+ GURL(),
+ Referrer(),
+ base::string16(),
+ ui::PAGE_TRANSITION_LINK,
+ false,
+ nullptr) {}
NavigationEntryImpl::NavigationEntryImpl(
scoped_refptr<SiteInstanceImpl> instance,
@@ -244,19 +249,22 @@ NavigationEntryImpl::NavigationEntryImpl(
const Referrer& referrer,
const base::string16& title,
ui::PageTransition transition_type,
- bool is_renderer_initiated)
- : frame_tree_(new TreeNode(nullptr,
- new FrameNavigationEntry("",
- -1,
- -1,
- std::move(instance),
- nullptr,
- url,
- referrer,
- std::vector<GURL>(),
- PageState(),
- "GET",
- -1))),
+ bool is_renderer_initiated,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory)
+ : frame_tree_(new TreeNode(
+ nullptr,
+ new FrameNavigationEntry("",
+ -1,
+ -1,
+ std::move(instance),
+ nullptr,
+ url,
+ referrer,
+ std::vector<GURL>(),
+ PageState(),
+ "GET",
+ -1,
+ std::move(blob_url_loader_factory)))),
unique_id_(CreateUniqueEntryID()),
bindings_(kInvalidBindings),
page_type_(PAGE_TYPE_NORMAL),
@@ -654,7 +662,6 @@ std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::CloneAndReplace(
// ResetForCommit: reload_type_
copy->extra_data_ = extra_data_;
copy->replaced_entry_data_ = replaced_entry_data_;
- // ResetForCommit: suggested_filename_
return copy;
}
@@ -693,7 +700,9 @@ CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams(
navigation_start, method, post_body ? post_body : post_data_,
base::Optional<SourceLocation>(),
CSPDisposition::CHECK /* should_check_main_world_csp */,
- has_started_from_context_menu(), has_user_gesture(), suggested_filename_);
+ has_started_from_context_menu(), has_user_gesture(),
+ std::vector<ContentSecurityPolicy>() /* initiator_csp */,
+ CSPSource() /* initiator_self_source */);
}
RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams(
@@ -763,15 +772,16 @@ void NavigationEntryImpl::ResetForCommit(FrameNavigationEntry* frame_entry) {
set_frame_tree_node_id(-1);
set_reload_type(ReloadType::NONE);
- if (frame_entry)
+ if (frame_entry) {
frame_entry->set_source_site_instance(nullptr);
+ frame_entry->set_blob_url_loader_factory(nullptr);
+ }
#if defined(OS_ANDROID)
// Reset the time stamp so that the metrics are not reported if this entry is
// loaded again in the future.
set_intent_received_timestamp(base::TimeTicks());
#endif
- suggested_filename_.reset();
}
NavigationEntryImpl::TreeNode* NavigationEntryImpl::GetTreeNode(
@@ -803,7 +813,8 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry(
const std::vector<GURL>& redirect_chain,
const PageState& page_state,
const std::string& method,
- int64_t post_id) {
+ int64_t post_id,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
// If this is called for the main frame, the FrameNavigationEntry is
// guaranteed to exist, so just update it directly and return.
if (frame_tree_node->IsMainFrame()) {
@@ -817,7 +828,7 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry(
frame_tree_node->unique_name(), item_sequence_number,
document_sequence_number, site_instance,
std::move(source_site_instance), url, referrer, redirect_chain,
- page_state, method, post_id);
+ page_state, method, post_id, std::move(blob_url_loader_factory));
return;
}
@@ -845,7 +856,8 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry(
child->frame_entry->UpdateEntry(
unique_name, item_sequence_number, document_sequence_number,
site_instance, std::move(source_site_instance), url, referrer,
- redirect_chain, page_state, method, post_id);
+ redirect_chain, page_state, method, post_id,
+ std::move(blob_url_loader_factory));
return;
}
}
@@ -856,7 +868,8 @@ void NavigationEntryImpl::AddOrUpdateFrameEntry(
FrameNavigationEntry* frame_entry = new FrameNavigationEntry(
unique_name, item_sequence_number, document_sequence_number,
site_instance, std::move(source_site_instance), url, referrer,
- redirect_chain, page_state, method, post_id);
+ redirect_chain, page_state, method, post_id,
+ std::move(blob_url_loader_factory));
parent_node->children.push_back(
std::make_unique<NavigationEntryImpl::TreeNode>(parent_node,
frame_entry));
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index 5d711d1ea04..edfec89b1bc 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -85,12 +85,14 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
enum : int { kInvalidBindings = -1 };
NavigationEntryImpl();
- NavigationEntryImpl(scoped_refptr<SiteInstanceImpl> instance,
- const GURL& url,
- const Referrer& referrer,
- const base::string16& title,
- ui::PageTransition transition_type,
- bool is_renderer_initiated);
+ NavigationEntryImpl(
+ scoped_refptr<SiteInstanceImpl> instance,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& title,
+ ui::PageTransition transition_type,
+ bool is_renderer_initiated,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
~NavigationEntryImpl() override;
// NavigationEntry implementation:
@@ -233,7 +235,8 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
const std::vector<GURL>& redirect_chain,
const PageState& page_state,
const std::string& method,
- int64_t post_id);
+ int64_t post_id,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
// Returns the FrameNavigationEntry corresponding to |frame_tree_node|, if
// there is one in this NavigationEntry.
@@ -430,14 +433,6 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
replaced_entry_data_ = data;
}
- const base::Optional<std::string> suggested_filename() const {
- return suggested_filename_;
- }
- void set_suggested_filename(
- const base::Optional<std::string> suggested_filename) {
- suggested_filename_ = suggested_filename;
- }
-
private:
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
// Session/Tab restore save portions of this class so that it can be recreated
@@ -581,11 +576,6 @@ class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry {
// why the field is listed here.
base::Optional<ReplacedNavigationEntryData> replaced_entry_data_;
- // If this event was triggered by an anchor element with a download
- // attribute, |suggested_filename_| will contain the (possibly empty) value of
- // that attribute. Reset at commit and not persisted.
- base::Optional<std::string> suggested_filename_;
-
DISALLOW_COPY_AND_ASSIGN(NavigationEntryImpl);
};
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
index ce11139293a..c592771aa78 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -55,7 +55,8 @@ class NavigationEntryTest : public testing::Test {
entry2_.reset(new NavigationEntryImpl(
instance_, GURL("test:url"),
Referrer(GURL("from"), blink::kWebReferrerPolicyDefault),
- ASCIIToUTF16("title"), ui::PAGE_TRANSITION_TYPED, false));
+ ASCIIToUTF16("title"), ui::PAGE_TRANSITION_TYPED, false,
+ nullptr /* blob_url_loader_factory */));
}
void TearDown() override {}
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index 0c0c4cbb9ef..b23698013a0 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -13,7 +13,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/frame_host/ancestor_throttle.h"
-#include "content/browser/frame_host/data_url_navigation_throttle.h"
+#include "content/browser/frame_host/blocked_scheme_navigation_throttle.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/form_submission_throttle.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -22,6 +22,7 @@
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/navigator_delegate.h"
+#include "content/browser/frame_host/webui_navigation_throttle.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
@@ -117,7 +118,6 @@ std::unique_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
bool is_form_submission,
- const base::Optional<std::string>& suggested_filename,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const std::string& method,
net::HttpRequestHeaders request_headers,
@@ -132,10 +132,10 @@ std::unique_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
url, redirect_chain, frame_tree_node, is_renderer_initiated,
is_same_document, navigation_start, pending_nav_entry_id,
started_from_context_menu, should_check_main_world_csp,
- is_form_submission, suggested_filename, std::move(navigation_ui_data),
- method, std::move(request_headers), resource_request_body,
- sanitized_referrer, has_user_gesture, transition, is_external_protocol,
- request_context_type, mixed_content_context_type));
+ is_form_submission, std::move(navigation_ui_data), method,
+ std::move(request_headers), resource_request_body, sanitized_referrer,
+ has_user_gesture, transition, is_external_protocol, request_context_type,
+ mixed_content_context_type));
}
NavigationHandleImpl::NavigationHandleImpl(
@@ -149,7 +149,6 @@ NavigationHandleImpl::NavigationHandleImpl(
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
bool is_form_submission,
- const base::Optional<std::string>& suggested_filename,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const std::string& method,
net::HttpRequestHeaders request_headers,
@@ -191,7 +190,6 @@ NavigationHandleImpl::NavigationHandleImpl(
navigation_type_(NAVIGATION_TYPE_UNKNOWN),
should_check_main_world_csp_(should_check_main_world_csp),
expected_render_process_host_id_(ChildProcessHost::kInvalidUniqueID),
- suggested_filename_(suggested_filename),
is_transferring_(false),
is_form_submission_(is_form_submission),
should_replace_current_entry_(false),
@@ -382,12 +380,14 @@ net::Error NavigationHandleImpl::GetNetErrorCode() {
}
RenderFrameHostImpl* NavigationHandleImpl::GetRenderFrameHost() {
- // TODO(mkwst): Change this to check against 'READY_TO_COMMIT' once
- // ReadyToCommitNavigation is available whether or not PlzNavigate is
- // enabled. https://crbug.com/621856
- CHECK_GE(state_, WILL_PROCESS_RESPONSE)
- << "This accessor should only be called after a response has been "
- "delivered for processing.";
+ // Only allow the RenderFrameHost to be retrieved once it has been set for
+ // this navigation. This will happens either at WillProcessResponse time for
+ // regular navigations or at WillFailRequest time for error pages.
+ CHECK_GE(state_, WILL_FAIL_REQUEST)
+ << "This accessor should only be called after a RenderFrameHost has been "
+ "picked for this navigation.";
+ static_assert(WILL_FAIL_REQUEST < WILL_PROCESS_RESPONSE,
+ "WillFailRequest state should come before WillProcessResponse");
return render_frame_host_;
}
@@ -495,9 +495,11 @@ NavigationHandleImpl::CallWillRedirectRequestForTesting(
NavigationThrottle::ThrottleCheckResult
NavigationHandleImpl::CallWillFailRequestForTesting(
+ RenderFrameHost* render_frame_host,
base::Optional<net::SSLInfo> ssl_info) {
NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::DEFER;
- WillFailRequest(ssl_info, base::Bind(&UpdateThrottleCheckResult, &result));
+ WillFailRequest(static_cast<RenderFrameHostImpl*>(render_frame_host),
+ ssl_info, base::Bind(&UpdateThrottleCheckResult, &result));
// Reset the callback to ensure it will not be called later.
complete_callback_.Reset();
@@ -506,7 +508,7 @@ NavigationHandleImpl::CallWillFailRequestForTesting(
NavigationThrottle::ThrottleCheckResult
NavigationHandleImpl::CallWillProcessResponseForTesting(
- content::RenderFrameHost* render_frame_host,
+ RenderFrameHost* render_frame_host,
const std::string& raw_response_headers) {
scoped_refptr<net::HttpResponseHeaders> headers =
new net::HttpResponseHeaders(raw_response_headers);
@@ -601,11 +603,6 @@ bool NavigationHandleImpl::IsFormSubmission() {
return is_form_submission_;
}
-const base::Optional<std::string>&
-NavigationHandleImpl::GetSuggestedFilename() {
- return suggested_filename_;
-}
-
void NavigationHandleImpl::InitServiceWorkerHandle(
ServiceWorkerContextWrapper* service_worker_context) {
service_worker_handle_.reset(
@@ -732,6 +729,7 @@ void NavigationHandleImpl::WillRedirectRequest(
}
void NavigationHandleImpl::WillFailRequest(
+ RenderFrameHostImpl* render_frame_host,
base::Optional<net::SSLInfo> ssl_info,
const ThrottleChecksFinishedCallback& callback) {
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
@@ -739,6 +737,7 @@ void NavigationHandleImpl::WillFailRequest(
if (ssl_info.has_value())
ssl_info_ = ssl_info.value();
+ render_frame_host_ = render_frame_host;
complete_callback_ = callback;
state_ = WILL_FAIL_REQUEST;
@@ -793,16 +792,8 @@ void NavigationHandleImpl::WillProcessResponse(
// If the navigation is done processing the response, then it's ready to
// commit. Inform observers that the navigation is now ready to commit, unless
// it is not set to commit (204/205s/downloads).
- if (result.action() == NavigationThrottle::PROCEED && render_frame_host_) {
- CHECK(!suggested_filename_.has_value() ||
- !(url_.SchemeIsBlob() || url_.SchemeIsFileSystem() ||
- url_.SchemeIs(url::kAboutScheme) ||
- url_.SchemeIs(url::kDataScheme)))
- << "Blob, filesystem, data, and about URLs with a suggested filename "
- "should always result in a download, so we should never process a "
- "navigation response here.";
+ if (result.action() == NavigationThrottle::PROCEED && render_frame_host_)
ReadyToCommitNavigation(render_frame_host_, false);
- }
TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this,
"ProcessResponse", "result", result.action());
@@ -815,7 +806,18 @@ void NavigationHandleImpl::ReadyToCommitNavigation(
TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
"ReadyToCommitNavigation");
- DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
+ // If the NavigationHandle already has a RenderFrameHost set at
+ // WillProcessResponse time, we should not be changing it. One exception is
+ // errors originating from WillProcessResponse throttles, which might commit
+ // in a different RenderFrameHost. For example, a throttle might return
+ // CANCEL with an error code from WillProcessResponse, which will cancel the
+ // navigation and get here to commit the error page, with |render_frame_host|
+ // recomputed for the error page.
+ DCHECK(!render_frame_host_ || is_error ||
+ render_frame_host_ == render_frame_host)
+ << "Unsupported RenderFrameHost change from " << render_frame_host_
+ << " to " << render_frame_host << " with is_error=" << is_error;
+
render_frame_host_ = render_frame_host;
state_ = READY_TO_COMMIT;
ready_to_commit_time_ = base::TimeTicks::Now();
@@ -833,6 +835,17 @@ void NavigationHandleImpl::ReadyToCommitNavigation(
base::TimeDelta delta = ready_to_commit_time_ - navigation_start_;
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit", transition_, delta,
base::TimeDelta::FromSeconds(10));
+
+ if (IsInMainFrame()) {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.MainFrame",
+ transition_, delta,
+ base::TimeDelta::FromSeconds(10));
+ } else {
+ LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.Subframe",
+ transition_, delta,
+ base::TimeDelta::FromSeconds(10));
+ }
+
if (is_same_process_) {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit.SameProcess",
transition_, delta,
@@ -1277,9 +1290,14 @@ void NavigationHandleImpl::RegisterNavigationThrottles() {
throttles_ = GetDelegate()->CreateThrottlesForNavigation(this);
- // Check for renderer-inititated main frame navigations to data URLs. This is
- // done first as it may block the main frame navigation altogether.
- AddThrottle(DataUrlNavigationThrottle::CreateThrottleForNavigation(this));
+ // Enforce rules for WebUI navigations.
+ AddThrottle(WebUINavigationThrottle::CreateThrottleForNavigation(this));
+
+ // Check for renderer-inititated main frame navigations to blocked URL schemes
+ // (data, filesystem). This is done early as it may block the main frame
+ // navigation altogether.
+ AddThrottle(
+ BlockedSchemeNavigationThrottle::CreateThrottleForNavigation(this));
AddThrottle(AncestorThrottle::MaybeCreateThrottleFor(this));
AddThrottle(FormSubmissionThrottle::MaybeCreateThrottleFor(this));
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index e2a7a8bd975..f11fe8d88e0 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -66,7 +66,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
bool is_form_submission,
- const base::Optional<std::string>& suggested_filename,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const std::string& method = std::string(),
net::HttpRequestHeaders request_headers = net::HttpRequestHeaders(),
@@ -144,6 +143,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const GURL& new_referrer_url,
bool new_is_external_protocol) override;
NavigationThrottle::ThrottleCheckResult CallWillFailRequestForTesting(
+ RenderFrameHost* render_frame_host,
base::Optional<net::SSLInfo> ssl_info) override;
NavigationThrottle::ThrottleCheckResult CallWillProcessResponseForTesting(
RenderFrameHost* render_frame_host,
@@ -159,7 +159,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
const GlobalRequestID& GetGlobalRequestID() override;
bool IsDownload() override;
bool IsFormSubmission() override;
- const base::Optional<std::string>& GetSuggestedFilename() override;
// Resume and CancelDeferredNavigation must only be called by the
// NavigationThrottle that is currently deferring the navigation.
@@ -271,11 +270,13 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
RenderProcessHost* post_redirect_process,
const ThrottleChecksFinishedCallback& callback);
- // Called when the URLRequest will fail. |callback| will be called when all
- // throttles check have completed. This will allow the caller to explicitly
- // cancel the navigation (with a custom error code and/or custom error page
- // HTML) or let the failure proceed as normal.
- void WillFailRequest(base::Optional<net::SSLInfo> ssl_info,
+ // Called when the URLRequest will fail. |render_frame_host| corresponds to
+ // the RenderFrameHost in which the error page will load. |callback| will be
+ // called when all throttles check have completed. This will allow the caller
+ // to explicitly cancel the navigation (with a custom error code and/or
+ // custom error page HTML) or let the failure proceed as normal.
+ void WillFailRequest(RenderFrameHostImpl* render_frame_host,
+ base::Optional<net::SSLInfo> ssl_info,
const ThrottleChecksFinishedCallback& callback);
// Called when the URLRequest has delivered response headers and metadata.
@@ -381,7 +382,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool started_from_context_menu,
CSPDisposition should_check_main_world_csp,
bool is_form_submission,
- const base::Optional<std::string>& suggested_filename,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const std::string& method,
net::HttpRequestHeaders request_headers,
@@ -557,11 +557,6 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// in it.
int expected_render_process_host_id_;
- // If this navigation was triggered by an anchor element with a download
- // attribute, the |suggested_filename_| contains the attribute's (possibly
- // empty) value.
- base::Optional<std::string> suggested_filename_;
-
// Whether the navigation is in the middle of a transfer. Set to false when
// the DidStartProvisionalLoad is received from the new renderer.
bool is_transferring_;
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
index 1e6c0406cf9..fd806c769b3 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -13,6 +13,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/bindings_policy.h"
@@ -1654,8 +1655,8 @@ class PlzNavigateNavigationHandleImplBrowserTest : public ContentBrowserTest {
};
// Test to verify that error pages caused by NavigationThrottle blocking a
-// request from being made are properly committed in the original process
-// that requested the navigation.
+// request in the main frame from being made are properly committed in a
+// separate error page process.
IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
ErrorPageBlockedNavigation) {
SetupCrossSiteRedirector(embedded_test_server());
@@ -1680,8 +1681,8 @@ IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
NavigationThrottle::PROCEED);
{
- // A blocked, renderer-initiated navigation should commit an error page
- // in the process that originated the navigation.
+ // A blocked, renderer-initiated navigation in the main frame should commit
+ // an error page in a new process.
NavigationHandleObserver observer(shell()->web_contents(), blocked_url);
TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
EXPECT_TRUE(
@@ -1690,27 +1691,25 @@ IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
navigation_observer.Wait();
EXPECT_TRUE(observer.has_committed());
EXPECT_TRUE(observer.is_error());
- EXPECT_EQ(site_instance,
- shell()->web_contents()->GetMainFrame()->GetSiteInstance());
- }
-
- {
- // Reloading the blocked document from the renderer process should not
- // transfer processes.
- NavigationHandleObserver observer(shell()->web_contents(), blocked_url);
- TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
-
- EXPECT_TRUE(ExecuteScript(shell(), "location.reload()"));
- navigation_observer.Wait();
- EXPECT_TRUE(observer.has_committed());
- EXPECT_TRUE(observer.is_error());
- EXPECT_EQ(site_instance,
- shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
+ EXPECT_NE(site_instance,
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ EXPECT_EQ(kUnreachableWebDataURL, shell()
+ ->web_contents()
+ ->GetMainFrame()
+ ->GetSiteInstance()
+ ->GetSiteURL());
+ } else {
+ EXPECT_EQ(site_instance,
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ }
}
{
- // Reloading the blocked document from the browser process ends up
- // transferring processes in --site-per-process.
+ // Reloading the blocked document from the browser process still ends up
+ // in the error page process.
+ int process_id =
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
NavigationHandleObserver observer(shell()->web_contents(), blocked_url);
TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
@@ -1718,7 +1717,15 @@ IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
navigation_observer.Wait();
EXPECT_TRUE(observer.has_committed());
EXPECT_TRUE(observer.is_error());
- if (AreAllSitesIsolatedForTesting()) {
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
+ EXPECT_EQ(kUnreachableWebDataURL, shell()
+ ->web_contents()
+ ->GetMainFrame()
+ ->GetSiteInstance()
+ ->GetSiteURL());
+ EXPECT_EQ(process_id,
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID());
+ } else if (AreAllSitesIsolatedForTesting()) {
EXPECT_NE(site_instance,
shell()->web_contents()->GetMainFrame()->GetSiteInstance());
} else {
@@ -1761,6 +1768,48 @@ IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
EXPECT_TRUE(observer.is_error());
EXPECT_NE(site_instance,
shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
+ EXPECT_EQ(kUnreachableWebDataURL, shell()
+ ->web_contents()
+ ->GetMainFrame()
+ ->GetSiteInstance()
+ ->GetSiteURL());
+ }
+ }
+
+ installer.reset();
+
+ {
+ // A blocked subframe navigation should commit an error page in the same
+ // process.
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+ const std::string javascript =
+ "var i = document.createElement('iframe');"
+ "i.src = '" +
+ blocked_url.spec() +
+ "';"
+ "document.body.appendChild(i);";
+
+ installer = std::make_unique<TestNavigationThrottleInstaller>(
+ shell()->web_contents(), NavigationThrottle::BLOCK_REQUEST,
+ NavigationThrottle::PROCEED, NavigationThrottle::PROCEED,
+ NavigationThrottle::PROCEED);
+
+ content::RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ ASSERT_TRUE(content::ExecuteScript(rfh, javascript));
+ navigation_observer.Wait();
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1u, root->child_count());
+ FrameTreeNode* child = root->child_at(0u);
+
+ EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
+ child->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(kUnreachableWebDataURL,
+ child->current_frame_host()->GetSiteInstance()->GetSiteURL());
}
}
@@ -1795,6 +1844,13 @@ IN_PROC_BROWSER_TEST_F(PlzNavigateNavigationHandleImplBrowserTest,
EXPECT_TRUE(observer.is_error());
EXPECT_NE(site_instance,
shell()->web_contents()->GetMainFrame()->GetSiteInstance());
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) {
+ EXPECT_EQ(kUnreachableWebDataURL, shell()
+ ->web_contents()
+ ->GetMainFrame()
+ ->GetSiteInstance()
+ ->GetSiteURL());
+ }
}
}
@@ -1842,26 +1898,20 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
GURL url(embedded_test_server()->GetURL("/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), url));
- const struct {
- const GURL renderer_debug_url;
- const net::Error error_code;
- } kTestCases[] = {
- {GURL("javascript:window.alert('hello')"), net::ERR_ABORTED},
- {GURL(kChromeUIBadCastCrashURL), net::ERR_UNSAFE_REDIRECT},
- {GURL(kChromeUICrashURL), net::ERR_UNSAFE_REDIRECT},
- {GURL(kChromeUIDumpURL), net::ERR_UNSAFE_REDIRECT},
- {GURL(kChromeUIKillURL), net::ERR_UNSAFE_REDIRECT},
- {GURL(kChromeUIHangURL), net::ERR_UNSAFE_REDIRECT},
- {GURL(kChromeUIShorthangURL), net::ERR_UNSAFE_REDIRECT},
- {GURL(kChromeUIMemoryExhaustURL), net::ERR_UNSAFE_REDIRECT},
- };
+ const GURL kTestUrls[] = {GURL("javascript:window.alert('hello')"),
+ GURL(kChromeUIBadCastCrashURL),
+ GURL(kChromeUICrashURL),
+ GURL(kChromeUIDumpURL),
+ GURL(kChromeUIKillURL),
+ GURL(kChromeUIHangURL),
+ GURL(kChromeUIShorthangURL),
+ GURL(kChromeUIMemoryExhaustURL)};
- for (const auto& test_case : kTestCases) {
- SCOPED_TRACE(testing::Message()
- << "renderer_debug_url = " << test_case.renderer_debug_url);
+ for (const auto& test_url : kTestUrls) {
+ SCOPED_TRACE(testing::Message() << "renderer_debug_url = " << test_url);
- GURL redirecting_url = embedded_test_server()->GetURL(
- "/server-redirect?" + test_case.renderer_debug_url.spec());
+ GURL redirecting_url =
+ embedded_test_server()->GetURL("/server-redirect?" + test_url.spec());
NavigationHandleObserver observer(shell()->web_contents(), redirecting_url);
NavigationLogger logger(shell()->web_contents());
@@ -1869,7 +1919,7 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
// Try to navigate to the url. The navigation should be canceled and the
// NavigationHandle should have the right error code.
EXPECT_FALSE(NavigateToURL(shell(), redirecting_url));
- EXPECT_EQ(test_case.error_code, observer.net_error_code());
+ EXPECT_EQ(net::ERR_UNSAFE_REDIRECT, observer.net_error_code());
// Both WebContentsObserver::{DidStartNavigation, DidFinishNavigation}
// are called, but no WebContentsObserver::DidRedirectNavigation.
@@ -2147,8 +2197,8 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, StartToCommitMetrics) {
}
}
-// Verify that the SameProcess vs CrossProcess version of the
-// TimeToReadyToCommit metric is correctly logged.
+// Verify that the TimeToReadyToCommit metrics are correctly logged for
+// SameProcess vs CrossProcess as well as MainFrame vs Subframe cases.
IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
TimeToReadyToCommitMetrics) {
EXPECT_TRUE(
@@ -2161,6 +2211,8 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url));
base::HistogramTester::CountsMap expected_counts = {
+ {"Navigation.TimeToReadyToCommit.MainFrame", 1},
+ {"Navigation.TimeToReadyToCommit.MainFrame.NewNavigation", 1},
{"Navigation.TimeToReadyToCommit.NewNavigation", 1},
{"Navigation.TimeToReadyToCommit.SameProcess", 1},
{"Navigation.TimeToReadyToCommit.SameProcess.NewNavigation", 1}};
@@ -2176,6 +2228,8 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url));
base::HistogramTester::CountsMap expected_counts = {
+ {"Navigation.TimeToReadyToCommit.MainFrame", 1},
+ {"Navigation.TimeToReadyToCommit.MainFrame.NewNavigation", 1},
{"Navigation.TimeToReadyToCommit.NewNavigation", 1},
{"Navigation.TimeToReadyToCommit.CrossProcess", 1},
{"Navigation.TimeToReadyToCommit.CrossProcess.NewNavigation", 1}};
@@ -2183,6 +2237,36 @@ IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
histograms.GetTotalCountsForPrefix("Navigation.TimeToReadyToCommit."),
testing::ContainerEq(expected_counts));
}
+
+ // Add a new subframe.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_TRUE(ExecuteScript(
+ root, "document.body.appendChild(document.createElement('iframe'));"));
+
+ // Navigate subframe cross-site and ensure Subframe metrics are logged.
+ {
+ base::HistogramTester histograms;
+ GURL url(embedded_test_server()->GetURL("b.com", "/title3.html"));
+ NavigateFrameToURL(root->child_at(0), url);
+
+ std::string navigation_type =
+ AreAllSitesIsolatedForTesting() ? "CrossProcess" : "SameProcess";
+ base::HistogramTester::CountsMap expected_counts = {
+ {"Navigation.TimeToReadyToCommit.Subframe", 1},
+ {"Navigation.TimeToReadyToCommit.Subframe.NewNavigation", 1},
+ {"Navigation.TimeToReadyToCommit.NewNavigation", 1},
+ {base::StringPrintf("Navigation.TimeToReadyToCommit.%s",
+ navigation_type.c_str()),
+ 1},
+ {base::StringPrintf("Navigation.TimeToReadyToCommit.%s.NewNavigation",
+ navigation_type.c_str()),
+ 1}};
+ EXPECT_THAT(
+ histograms.GetTotalCountsForPrefix("Navigation.TimeToReadyToCommit."),
+ testing::ContainerEq(expected_counts));
+ }
}
IN_PROC_BROWSER_TEST_F(NavigationHandleImplDownloadBrowserTest, IsDownload) {
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
index 6d0602750d0..b09f5c258a7 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -146,7 +146,7 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
// It's safe to use base::Unretained since the NavigationHandle is owned by
// the NavigationHandleImplTest.
test_handle_->WillFailRequest(
- ssl_info,
+ main_test_rfh(), ssl_info,
base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult,
base::Unretained(this)));
}
@@ -258,7 +258,6 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
false, // started_from_context_menu
CSPDisposition::CHECK, // should_check_main_world_csp
false, // is_form_submission
- base::nullopt, // suggested_filename
nullptr, // navigation_ui_data
"GET", net::HttpRequestHeaders(),
nullptr, // resource_request_body
@@ -1136,4 +1135,42 @@ TEST_F(NavigationHandleImplTest, WillFailRequestSetsSSLInfo) {
EXPECT_EQ(connection_status, test_handle()->GetSSLInfo().connection_status);
}
+// Helper throttle which checks that it can access NavigationHandle's
+// RenderFrameHost in WillFailRequest() and then defers the failure.
+class GetRenderFrameHostOnFailureNavigationThrottle
+ : public NavigationThrottle {
+ public:
+ GetRenderFrameHostOnFailureNavigationThrottle(NavigationHandle* handle)
+ : NavigationThrottle(handle) {}
+ ~GetRenderFrameHostOnFailureNavigationThrottle() override {}
+
+ NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
+ EXPECT_TRUE(navigation_handle()->GetRenderFrameHost());
+ return NavigationThrottle::DEFER;
+ }
+
+ const char* GetNameForLogging() override {
+ return "GetRenderFrameHostOnFailureNavigationThrottle";
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GetRenderFrameHostOnFailureNavigationThrottle);
+};
+
+// Verify that the NavigationHandle::GetRenderFrameHost() can be retrieved by a
+// throttle in WillFailRequest(), as well as after deferring the failure. This
+// is allowed, since at that point the final RenderFrameHost will have already
+// been chosen. See https://crbug.com/817881.
+TEST_F(NavigationHandleImplTest, WillFailRequestCanAccessRenderFrameHost) {
+ test_handle()->RegisterThrottleForTesting(
+ std::make_unique<GetRenderFrameHostOnFailureNavigationThrottle>(
+ test_handle()));
+ SimulateWillStartRequest();
+ SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
+ EXPECT_EQ(NavigationHandleImpl::DEFERRING_FAILURE, state());
+ EXPECT_TRUE(test_handle()->GetRenderFrameHost());
+ Resume();
+ EXPECT_TRUE(test_handle()->GetRenderFrameHost());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 9d8ca86d315..ecc9736c95c 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -6,8 +6,10 @@
#include <utility>
+#include "base/metrics/field_trial_params.h"
#include "base/optional.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/chrome_appcache_service.h"
@@ -39,20 +41,20 @@
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/stream_handle.h"
#include "content/public/common/appcache_info.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/request_context_type.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/common/web_preferences.h"
-#include "mojo/common/values_struct_traits.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -62,6 +64,7 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
@@ -118,6 +121,12 @@ bool IsSecureFrame(FrameTreeNode* frame) {
return true;
}
+bool IsSecMetadataEnabled() {
+ return base::FeatureList::IsEnabled(features::kSecMetadata) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+}
+
// This should match blink::ResourceRequest::needsHTTPOrigin.
bool NeedsHTTPOrigin(net::HttpRequestHeaders* headers,
const std::string& method) {
@@ -149,11 +158,14 @@ void AddAdditionalRequestHeaders(
BrowserContext* browser_context,
const std::string& method,
const std::string user_agent_override,
+ bool has_user_gesture,
+ base::Optional<url::Origin> initiator_origin,
FrameTreeNode* frame_tree_node) {
if (!url.SchemeIsHTTPOrHTTPS())
return;
- if (!base::FeatureList::IsEnabled(features::kDataSaverHoldback)) {
+ if (!base::GetFieldTrialParamByFeatureAsBool(features::kDataSaverHoldback,
+ "holdback_web", false)) {
bool is_reload =
navigation_type == FrameMsg_Navigate_Type::RELOAD ||
navigation_type == FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE ||
@@ -179,6 +191,29 @@ void AddAdditionalRequestHeaders(
? GetContentClient()->GetUserAgent()
: user_agent_override);
+ // TODO(mkwst): Extract this logic out somewhere that can be shared between
+ // Blink and //content.
+ if (IsSecMetadataEnabled()) {
+ std::string site_value = "cross-site";
+ if (initiator_origin) {
+ url::Origin target_origin = url::Origin::Create(url);
+ if (initiator_origin->IsSameOriginWith(target_origin)) {
+ site_value = "same-origin";
+ } else if (net::registry_controlled_domains::SameDomainOrHost(
+ *initiator_origin, target_origin,
+ net::registry_controlled_domains::
+ INCLUDE_PRIVATE_REGISTRIES)) {
+ site_value = "same-site";
+ }
+ }
+ std::string value = base::StringPrintf(
+ "cause=%s, destination=document, target=%s, site=%s",
+ has_user_gesture ? "user-activated" : "forced",
+ frame_tree_node->IsMainFrame() ? "top-level" : "nested",
+ site_value.c_str());
+ headers->SetHeaderIfMissing("Sec-Metadata", value);
+ }
+
// Next, set the HTTP Origin if needed.
if (!NeedsHTTPOrigin(headers, method))
return;
@@ -301,6 +336,8 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
base::nullopt /* devtools_initiator_info */),
request_params, browser_initiated, false /* from_begin_navigation */,
&frame_entry, &entry, std::move(navigation_ui_data)));
+ navigation_request->blob_url_loader_factory_ =
+ frame_entry.blob_url_loader_factory();
return navigation_request;
}
@@ -438,7 +475,9 @@ NavigationRequest::NavigationRequest(
&headers, std::move(embedder_additional_headers), common_params_.url,
common_params_.navigation_type,
frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
- common_params.method, user_agent_override, frame_tree_node);
+ common_params.method, user_agent_override,
+ common_params_.has_user_gesture, begin_params_->initiator_origin,
+ frame_tree_node);
if (begin_params_->is_form_submission) {
if (browser_initiated && !request_params.post_content_type.empty()) {
@@ -465,13 +504,16 @@ NavigationRequest::NavigationRequest(
headers.SetHeader(kDoNotTrackHeader, "1");
begin_params_->headers = headers.ToString();
+
+ initiator_csp_context_.reset(new InitiatorCSPContext(
+ common_params_.initiator_csp, common_params_.initiator_self_source));
}
NavigationRequest::~NavigationRequest() {
TRACE_EVENT_ASYNC_END0("navigation", "NavigationRequest", this);
if (state_ == STARTED) {
- RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(*this,
- net::ERR_ABORTED);
+ RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(
+ *this, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
}
}
@@ -509,7 +551,7 @@ void NavigationRequest::BeginNavigation() {
// Don't create a NavigationHandle here to simulate what happened with the
// old navigation code path (i.e. doesn't fire onPageFinished notification
// for aborted loads).
- OnRequestFailed(false, net::ERR_ABORTED, base::nullopt);
+ OnRequestFailed(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
return;
}
#endif
@@ -518,14 +560,15 @@ void NavigationRequest::BeginNavigation() {
// gives CSP a chance to modify requests that NavigationThrottles would
// otherwise block. Similarly, the NavigationHandle is created afterwards, so
// that it gets the request URL after potentially being modified by CSP.
- if (CheckContentSecurityPolicyFrameSrc(false /* is redirect */) ==
- CONTENT_SECURITY_POLICY_CHECK_FAILED) {
+ net::Error net_error = CheckContentSecurityPolicy(
+ false /* is redirect */, false /* is_response_check */);
+ if (net_error != net::OK) {
// Create a navigation handle so that the correct error code can be set on
// it by OnRequestFailed().
CreateNavigationHandle();
- OnRequestFailedInternal(false, net::ERR_BLOCKED_BY_CLIENT, base::nullopt,
- false, base::nullopt);
-
+ OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
+ false /* skip_throttles */,
+ base::nullopt /* error_page_content */);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
return;
@@ -538,8 +581,9 @@ void NavigationRequest::BeginNavigation() {
// Create a navigation handle so that the correct error code can be set on
// it by OnRequestFailed().
CreateNavigationHandle();
- OnRequestFailedInternal(false, net::ERR_ABORTED, base::nullopt, false,
- base::nullopt);
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED),
+ false /* skip_throttles */, base::nullopt /* error_page_content */);
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -609,9 +653,8 @@ void NavigationRequest::CreateNavigationHandle() {
common_params_.navigation_start, nav_entry_id_,
common_params_.started_from_context_menu,
common_params_.should_check_main_world_csp,
- begin_params_->is_form_submission, common_params_.suggested_filename,
- std::move(navigation_ui_data_), common_params_.method,
- std::move(headers), common_params_.post_data,
+ begin_params_->is_form_submission, std::move(navigation_ui_data_),
+ common_params_.method, std::move(headers), common_params_.post_data,
Referrer::SanitizeForRequest(common_params_.url,
common_params_.referrer),
common_params_.has_user_gesture, common_params_.transition,
@@ -722,9 +765,7 @@ void NavigationRequest::OnRequestRedirected(
redirect_info.new_url)) {
DVLOG(1) << "Denied redirect for "
<< redirect_info.new_url.possibly_invalid_spec();
- // TODO(arthursonzogni): Consider switching to net::ERR_UNSAFE_REDIRECT
- // when PlzNavigate is launched.
- navigation_handle_->set_net_error_code(net::ERR_ABORTED);
+ navigation_handle_->set_net_error_code(net::ERR_UNSAFE_REDIRECT);
frame_tree_node_->ResetNavigationRequest(false, true);
return;
}
@@ -738,7 +779,7 @@ void NavigationRequest::OnRequestRedirected(
redirect_info.new_url)) {
DVLOG(1) << "Denied unauthorized redirect for "
<< redirect_info.new_url.possibly_invalid_spec();
- navigation_handle_->set_net_error_code(net::ERR_ABORTED);
+ navigation_handle_->set_net_error_code(net::ERR_UNSAFE_REDIRECT);
frame_tree_node_->ResetNavigationRequest(false, true);
return;
}
@@ -773,9 +814,10 @@ void NavigationRequest::OnRequestRedirected(
// Check Content Security Policy before the NavigationThrottles run. This
// gives CSP a chance to modify requests that NavigationThrottles would
// otherwise block.
- if (CheckContentSecurityPolicyFrameSrc(true /* is redirect */) ==
- CONTENT_SECURITY_POLICY_CHECK_FAILED) {
- OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT, base::nullopt);
+ net::Error net_error = CheckContentSecurityPolicy(
+ true /* is redirect */, false /* is_response_check */);
+ if (net_error != net::OK) {
+ OnRequestFailed(network::URLLoaderCompletionStatus(net_error));
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -786,7 +828,7 @@ void NavigationRequest::OnRequestRedirected(
CredentialedSubresourceCheckResult::BLOCK_REQUEST ||
CheckLegacyProtocolInSubresource() ==
LegacyProtocolInSubresourceCheckResult::BLOCK_REQUEST) {
- OnRequestFailed(false, net::ERR_ABORTED, base::nullopt);
+ OnRequestFailed(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -836,7 +878,6 @@ void NavigationRequest::OnRequestRedirected(
void NavigationRequest::OnResponseStarted(
const scoped_refptr<network::ResourceResponse>& response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- std::unique_ptr<StreamHandle> body,
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& request_id,
bool is_download,
@@ -856,8 +897,10 @@ void NavigationRequest::OnResponseStarted(
// Response that will not commit should be marked as aborted in the
// NavigationHandle.
- if (!response_should_be_rendered_)
+ if (!response_should_be_rendered_) {
navigation_handle_->set_net_error_code(net::ERR_ABORTED);
+ net_error_ = net::ERR_ABORTED;
+ }
// Update the service worker and AppCache params of the request params.
request_params_.service_worker_provider_id =
@@ -940,9 +983,9 @@ void NavigationRequest::OnResponseStarted(
if (navigation_data)
navigation_handle_->set_navigation_data(std::move(navigation_data));
- // Store the response and the StreamHandle until checks have been processed.
+ // Store the response and the URLLoaderClient endpoints until checks have been
+ // processed.
response_ = response;
- body_ = std::move(body);
url_loader_client_endpoints_ = std::move(url_loader_client_endpoints);
ssl_info_ = response->head.ssl_info.has_value() ? *response->head.ssl_info
: net::SSLInfo();
@@ -992,6 +1035,21 @@ void NavigationRequest::OnResponseStarted(
return;
}
+ // The CSP 'navigate-to' directive needs to know whether the response is a
+ // redirect or not in order to perform its checks. This is the reason
+ // why we need to check the CSP both on request and response.
+ net::Error net_error = CheckContentSecurityPolicy(
+ navigation_handle_->WasServerRedirect(), true /* is_response_check */);
+ if (net_error != net::OK) {
+ OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
+ false /* skip_throttles */,
+ base::nullopt /* error_page_content */);
+
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
+ // destroyed the NavigationRequest.
+ return;
+ }
+
// Check if the navigation should be allowed to proceed.
navigation_handle_->WillProcessResponse(
render_frame_host, response->head.headers.get(),
@@ -1003,70 +1061,68 @@ void NavigationRequest::OnResponseStarted(
}
void NavigationRequest::OnRequestFailed(
- bool has_stale_copy_in_cache,
- int net_error,
- const base::Optional<net::SSLInfo>& ssl_info) {
- RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(*this, net_error);
-
- NavigationRequest::OnRequestFailedInternal(has_stale_copy_in_cache, net_error,
- ssl_info, false, base::nullopt);
+ const network::URLLoaderCompletionStatus& status) {
+ NavigationRequest::OnRequestFailedInternal(
+ status, false /* skip_throttles */,
+ base::nullopt /* error_page_content */);
}
void NavigationRequest::OnRequestFailedInternal(
- bool has_stale_copy_in_cache,
- int net_error,
- const base::Optional<net::SSLInfo>& ssl_info,
+ const network::URLLoaderCompletionStatus& status,
bool skip_throttles,
const base::Optional<std::string>& error_page_content) {
DCHECK(state_ == STARTED || state_ == RESPONSE_STARTED);
- DCHECK(!(net_error == net::ERR_ABORTED && error_page_content.has_value()));
+ DCHECK(!(status.error_code == net::ERR_ABORTED &&
+ error_page_content.has_value()));
+
+ RenderFrameDevToolsAgentHost::OnNavigationRequestFailed(*this, status);
// TODO(https://crbug.com/757633): Check that ssl_info.has_value() if
// net_error is a certificate error.
TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationRequest", this,
- "OnRequestFailed", "error", net_error);
+ "OnRequestFailed", "error", status.error_code);
state_ = FAILED;
- if (navigation_handle_.get())
- navigation_handle_->set_net_error_code(static_cast<net::Error>(net_error));
-
- int expected_pending_entry_id = nav_entry_id_;
- bool is_download = false;
if (navigation_handle_.get()) {
- expected_pending_entry_id = navigation_handle_->pending_nav_entry_id();
- is_download = navigation_handle_->IsDownload();
+ navigation_handle_->set_net_error_code(
+ static_cast<net::Error>(status.error_code));
}
+ int expected_pending_entry_id =
+ navigation_handle_.get() ? navigation_handle_->pending_nav_entry_id()
+ : nav_entry_id_;
frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
- expected_pending_entry_id, is_download);
+ expected_pending_entry_id);
// If the request was canceled by the user do not show an error page.
- if (net_error == net::ERR_ABORTED) {
+ if (status.error_code == net::ERR_ABORTED) {
frame_tree_node_->ResetNavigationRequest(false, true);
return;
}
- // Decide whether to leave the error page in the original process.
- // * If this was a renderer-initiated navigation, and the request is blocked
- // because the initiating document wasn't allowed to make the request,
- // commit the error in the existing process. This is a strategy to to avoid
- // creating a process for the destination, which may belong to an origin
- // with a higher privilege level.
- // * Error pages resulting from errors like network outage, no network, or DNS
- // error can reasonably expect that a reload at a later point in time would
- // work. These should be allowed to transfer away from the current process:
- // they do belong to whichever process that will host the destination URL,
- // as a reload will end up committing in that process anyway.
- // * Error pages that arise during browser-initiated navigations to blocked
- // URLs should be allowed to transfer away from the current process, which
- // didn't request the navigation and may have a higher privilege level than
- // the blocked destination.
RenderFrameHostImpl* render_frame_host = nullptr;
- if (net_error == net::ERR_BLOCKED_BY_CLIENT && !browser_initiated()) {
- render_frame_host = frame_tree_node_->current_frame_host();
- } else {
+ if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame())) {
+ // Main frame error pages must be isolated from the source or destination
+ // process.
+ //
+ // Note: Since this navigation resulted in an error, clear the expected
+ // process for the original navigation since for main frames the error page
+ // will go into a new process.
+ // TODO(nasko): Investigate whether GetFrameHostForNavigation can properly
+ // account for clearing the expected process if it clears the speculative
+ // RenderFrameHost. See https://crbug.com/793127.
+ navigation_handle_->SetExpectedProcess(nullptr);
render_frame_host =
frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this);
+ } else {
+ if (ShouldKeepErrorPageInCurrentProcess(status.error_code)) {
+ render_frame_host = frame_tree_node_->current_frame_host();
+ } else {
+ render_frame_host =
+ frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this);
+ }
}
+
DCHECK(render_frame_host);
// Don't ask the renderer to commit an URL if the browser will kill it when
@@ -1076,8 +1132,8 @@ void NavigationRequest::OnRequestFailedInternal(
NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(render_frame_host,
common_params_.url);
- has_stale_copy_in_cache_ = has_stale_copy_in_cache;
- net_error_ = net_error;
+ has_stale_copy_in_cache_ = status.exists_in_cache;
+ net_error_ = status.error_code;
if (skip_throttles) {
// The NavigationHandle shouldn't be notified about renderer-debug URLs.
@@ -1086,11 +1142,32 @@ void NavigationRequest::OnRequestFailedInternal(
} else {
// Check if the navigation should be allowed to proceed.
navigation_handle_->WillFailRequest(
- ssl_info, base::Bind(&NavigationRequest::OnFailureChecksComplete,
- base::Unretained(this), render_frame_host));
+ render_frame_host, status.ssl_info,
+ base::Bind(&NavigationRequest::OnFailureChecksComplete,
+ base::Unretained(this), render_frame_host));
}
}
+bool NavigationRequest::ShouldKeepErrorPageInCurrentProcess(int net_error) {
+ // Decide whether to leave the error page in the original process.
+ // * If this was a renderer-initiated navigation, and the request is blocked
+ // because the initiating document wasn't allowed to make the request,
+ // commit the error in the existing process. This is a strategy to to
+ // avoid creating a process for the destination, which may belong to an
+ // origin with a higher privilege level.
+ // * Error pages resulting from errors like network outage, no network, or
+ // DNS error can reasonably expect that a reload at a later point in time
+ // would work. These should be allowed to transfer away from the current
+ // process: they do belong to whichever process that will host the
+ // destination URL, as a reload will end up committing in that process
+ // anyway.
+ // * Error pages that arise during browser-initiated navigations to blocked
+ // URLs should be allowed to transfer away from the current process, which
+ // didn't request the navigation and may have a higher privilege level
+ // than the blocked destination.
+ return net_error == net::ERR_BLOCKED_BY_CLIENT && !browser_initiated();
+}
+
void NavigationRequest::OnRequestStarted(base::TimeTicks timestamp) {
if (frame_tree_node_->IsMainFrame()) {
TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
@@ -1131,10 +1208,11 @@ void NavigationRequest::OnStartChecksComplete(
// PostTask to avoid that.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationRequest::OnRequestFailedInternal,
- weak_factory_.GetWeakPtr(), false,
- result.net_error_code(), base::nullopt, true,
- result.error_page_content()));
+ base::BindOnce(
+ &NavigationRequest::OnRequestFailedInternal,
+ weak_factory_.GetWeakPtr(),
+ network::URLLoaderCompletionStatus(result.net_error_code()),
+ true /* skip_throttles */, result.error_page_content()));
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -1197,12 +1275,28 @@ void NavigationRequest::OnStartChecksComplete(
!base_url.is_empty()
? base_url
: frame_tree_node_->frame_tree()->root()->current_url();
+
+ // Walk the ancestor chain to determine whether all frames are same-site. If
+ // not, the |site_for_cookies| is set to an empty URL.
+ //
// TODO(mkwst): This is incorrect. It ought to use the definition from
- // 'Document::firstPartyForCookies()' in Blink, which walks the ancestor tree
- // and verifies that all origins are PSL-matches (and special-cases extension
- // URLs).
+ // 'Document::SiteForCookies()' in Blink, which special-cases extension
+ // URLs and a few other sharp edges.
+ const FrameTreeNode* current = frame_tree_node_->parent();
+ bool ancestors_are_same_site = true;
+ while (current && ancestors_are_same_site) {
+ if (!net::registry_controlled_domains::SameDomainOrHost(
+ top_document_url, current->current_url(),
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+ ancestors_are_same_site = false;
+ }
+ current = current->parent();
+ }
const GURL& site_for_cookies =
- frame_tree_node_->IsMainFrame() ? common_params_.url : top_document_url;
+ ancestors_are_same_site
+ ? (frame_tree_node_->IsMainFrame() ? common_params_.url
+ : top_document_url)
+ : GURL::EmptyGURL();
bool parent_is_main_frame = !frame_tree_node_->parent()
? false
: frame_tree_node_->parent()->IsMainFrame();
@@ -1233,7 +1327,8 @@ void NavigationRequest::OnStartChecksComplete(
navigating_frame_host->GetVisibilityState() ==
blink::mojom::PageVisibilityState::kPrerender,
blob_url_loader_factory_ ? blob_url_loader_factory_->Clone()
- : nullptr),
+ : nullptr,
+ devtools_navigation_token()),
std::move(navigation_ui_data),
navigation_handle_->service_worker_handle(),
navigation_handle_->appcache_handle(), this);
@@ -1250,8 +1345,9 @@ void NavigationRequest::OnRedirectChecksComplete(
// TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE if needed.
DCHECK(result.action() == NavigationThrottle::CANCEL ||
result.net_error_code() == net::ERR_ABORTED);
- OnRequestFailedInternal(false, result.net_error_code(), base::nullopt, true,
- result.error_page_content());
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(result.net_error_code()),
+ true /* skip_throttles */, result.error_page_content());
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -1262,8 +1358,9 @@ void NavigationRequest::OnRedirectChecksComplete(
result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
DCHECK(result.net_error_code() == net::ERR_BLOCKED_BY_CLIENT ||
result.net_error_code() == net::ERR_BLOCKED_BY_ADMINISTRATOR);
- OnRequestFailedInternal(false, result.net_error_code(), base::nullopt, true,
- result.error_page_content());
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(result.net_error_code()),
+ true /* skip_throttles */, result.error_page_content());
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
return;
@@ -1279,15 +1376,33 @@ void NavigationRequest::OnFailureChecksComplete(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result.action() != NavigationThrottle::DEFER);
+ int old_net_error = net_error_;
net_error_ = result.net_error_code();
navigation_handle_->set_net_error_code(static_cast<net::Error>(net_error_));
- // TODO(crbug.com/774663): We may want to take result.action() into account..
- if (net::ERR_ABORTED == net_error_) {
+ // TODO(crbug.com/774663): We may want to take result.action() into account.
+ if (net::ERR_ABORTED == result.net_error_code()) {
frame_tree_node_->ResetNavigationRequest(false, true);
return;
}
+ // Ensure that WillFailRequest() isn't changing the error code in a way that
+ // switches the destination process for the error page - see
+ // https://crbug.com/817881. This is not a concern with error page
+ // isolation, where all errors will go into one process.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame())) {
+ CHECK_EQ(ShouldKeepErrorPageInCurrentProcess(old_net_error),
+ ShouldKeepErrorPageInCurrentProcess(net_error_))
+ << " Unsupported error code change in WillFailRequest(): from "
+ << net_error_ << " to " << result.net_error_code();
+ }
+
+ // Sanity check that we haven't changed the RenderFrameHost picked for the
+ // error page in OnRequestFailedInternal when running the WillFailRequest
+ // checks.
+ CHECK_EQ(navigation_handle_->GetRenderFrameHost(), render_frame_host);
+
CommitErrorPage(render_frame_host, result.error_page_content());
// DO NOT ADD CODE after this. The previous call to CommitErrorPage caused
// the destruction of the NavigationRequest.
@@ -1318,11 +1433,12 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
BrowserContext::GetDownloadManager(browser_context));
download_manager->InterceptNavigation(
std::move(resource_request), navigation_handle_->GetRedirectChain(),
- common_params_.suggested_filename, response_,
- std::move(url_loader_client_endpoints_), ssl_info_.cert_status,
- frame_tree_node_->frame_tree_node_id());
+ response_, std::move(url_loader_client_endpoints_),
+ ssl_info_.cert_status, frame_tree_node_->frame_tree_node_id());
- OnRequestFailed(false, net::ERR_ABORTED, base::nullopt);
+ OnRequestFailed(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
+ // destroyed the NavigationRequest.
return;
}
@@ -1330,19 +1446,15 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
// Note: There is no need to call ProceedWithResponse() when the Network
// Service is enabled. See https://crbug.com/791049.
if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- if (!IsNavigationMojoResponseEnabled()) {
- loader_->ProceedWithResponse();
+ // |url_loader_client_endpoints_| is always valid, except in some tests
+ // where the TestNavigationLoader is used.
+ if (url_loader_client_endpoints_) {
+ network::mojom::URLLoaderPtr url_loader(
+ std::move(url_loader_client_endpoints_->url_loader));
+ url_loader->ProceedWithResponse();
+ url_loader_client_endpoints_->url_loader = url_loader.PassInterface();
} else {
- // |url_loader_client_endpoints_| is always valid, except in some tests
- // where the TestNavigationLoader is used.
- if (url_loader_client_endpoints_) {
- network::mojom::URLLoaderPtr url_loader(
- std::move(url_loader_client_endpoints_->url_loader));
- url_loader->ProceedWithResponse();
- url_loader_client_endpoints_->url_loader = url_loader.PassInterface();
- } else {
- loader_->ProceedWithResponse();
- }
+ loader_->ProceedWithResponse();
}
}
}
@@ -1355,15 +1467,19 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
!response_should_be_rendered_) {
// TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
if (!response_should_be_rendered_) {
- OnRequestFailedInternal(false, net::ERR_ABORTED, base::nullopt, true,
- base::nullopt);
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
+ // destroyed the NavigationRequest.
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED),
+ true /* skip_throttles */, base::nullopt /* error_page_content */);
return;
}
DCHECK(result.action() == NavigationThrottle::CANCEL ||
result.net_error_code() == net::ERR_ABORTED);
- OnRequestFailedInternal(false, result.net_error_code(), base::nullopt, true,
- result.error_page_content());
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(result.net_error_code()),
+ true /* skip_throttles */, result.error_page_content());
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
@@ -1372,8 +1488,9 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
if (result.action() == NavigationThrottle::BLOCK_RESPONSE) {
DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, result.net_error_code());
- OnRequestFailedInternal(false, result.net_error_code(), base::nullopt, true,
- result.error_page_content());
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(result.net_error_code()),
+ true /* skip_throttles */, result.error_page_content());
// DO NOT ADD CODE after this. The previous call to OnRequestFailed has
// destroyed the NavigationRequest.
return;
@@ -1412,10 +1529,9 @@ void NavigationRequest::CommitNavigation() {
frame_tree_node_->TransferNavigationRequestOwnership(render_frame_host);
render_frame_host->CommitNavigation(
- response_.get(), std::move(url_loader_client_endpoints_),
- std::move(body_), common_params_, request_params_, is_view_source_,
- std::move(subresource_loader_params_), std::move(subresource_overrides_),
- devtools_navigation_token_);
+ response_.get(), std::move(url_loader_client_endpoints_), common_params_,
+ request_params_, is_view_source_, std::move(subresource_loader_params_),
+ std::move(subresource_overrides_), devtools_navigation_token_);
// Give SpareRenderProcessHostManager a heads-up about the most recently used
// BrowserContext. This is mostly needed to make sure the spare is warmed-up
@@ -1424,24 +1540,69 @@ void NavigationRequest::CommitNavigation() {
render_frame_host->GetSiteInstance()->GetBrowserContext());
}
-NavigationRequest::ContentSecurityPolicyCheckResult
-NavigationRequest::CheckContentSecurityPolicyFrameSrc(bool is_redirect) {
+bool NavigationRequest::IsAllowedByCSPDirective(
+ CSPContext* context,
+ CSPDirective::Name directive,
+ bool is_redirect,
+ bool is_response_check,
+ CSPContext::CheckCSPDisposition disposition) {
+ return context->IsAllowedByCsp(
+ directive, common_params_.url, is_redirect, is_response_check,
+ common_params_.source_location.value_or(SourceLocation()), disposition,
+ begin_params_->is_form_submission);
+}
+
+net::Error NavigationRequest::CheckCSPDirectives(
+ RenderFrameHostImpl* parent,
+ bool is_redirect,
+ bool is_response_check,
+ CSPContext::CheckCSPDisposition disposition) {
+ bool navigate_to_allowed = IsAllowedByCSPDirective(
+ initiator_csp_context_.get(), CSPDirective::NavigateTo, is_redirect,
+ is_response_check, disposition);
+
+ bool frame_src_allowed = true;
+ if (parent) {
+ frame_src_allowed =
+ IsAllowedByCSPDirective(parent, CSPDirective::FrameSrc, is_redirect,
+ is_response_check, disposition);
+ }
+
+ if (navigate_to_allowed && frame_src_allowed)
+ return net::OK;
+
+ // If 'frame-src' fails, ERR_BLOCKED_BY_CLIENT is used instead.
+ // If both checks fail, ERR_BLOCKED_BY_CLIENT is used to keep the existing
+ // behaviour before 'navigate-to' was introduced.
+ if (!frame_src_allowed)
+ return net::ERR_BLOCKED_BY_CLIENT;
+
+ // net::ERR_ABORTED is used to ensure that the navigation is cancelled
+ // when the 'navigate-to' directive check is failed. This is a better user
+ // experience as the user is not presented with an error page.
+ return net::ERR_ABORTED;
+}
+
+net::Error NavigationRequest::CheckContentSecurityPolicy(
+ bool is_redirect,
+ bool is_response_check) {
if (common_params_.url.SchemeIs(url::kAboutScheme))
- return CONTENT_SECURITY_POLICY_CHECK_PASSED;
+ return net::OK;
if (common_params_.should_check_main_world_csp ==
CSPDisposition::DO_NOT_CHECK) {
- return CONTENT_SECURITY_POLICY_CHECK_PASSED;
+ return net::OK;
}
- // The CSP frame-src directive only applies to subframes.
- if (frame_tree_node()->IsMainFrame())
- return CONTENT_SECURITY_POLICY_CHECK_PASSED;
-
FrameTreeNode* parent_ftn = frame_tree_node()->parent();
- DCHECK(parent_ftn);
- RenderFrameHostImpl* parent = parent_ftn->current_frame_host();
- DCHECK(parent);
+ RenderFrameHostImpl* parent =
+ parent_ftn ? parent_ftn->current_frame_host() : nullptr;
+
+ // TODO(andypaicu,https://crbug.com/837627): the current_frame_host is the
+ // wrong RenderFrameHost. We should be using the navigation initiator
+ // RenderFrameHost.
+ initiator_csp_context_->SetReportingRenderFrameHost(
+ frame_tree_node()->current_frame_host());
// CSP checking happens in three phases, per steps 3-5 of
// https://fetch.spec.whatwg.org/#main-fetch:
@@ -1454,36 +1615,27 @@ NavigationRequest::CheckContentSecurityPolicyFrameSrc(bool is_redirect) {
// This sequence of events allows site owners to learn about (via step 1) any
// requests that are upgraded in step 2.
- bool allowed = parent->IsAllowedByCsp(
- CSPDirective::FrameSrc, common_params_.url, is_redirect,
- common_params_.source_location.value_or(SourceLocation()),
- CSPContext::CHECK_REPORT_ONLY_CSP);
-
- // Checking report-only CSP should never return false because no requests are
- // blocked by report-only policies.
- DCHECK(allowed);
+ net::Error report_only_csp_status =
+ CheckCSPDirectives(parent, is_redirect, is_response_check,
+ CSPContext::CHECK_REPORT_ONLY_CSP);
// TODO(mkwst,estark): upgrade-insecure-requests does not work when following
// redirects. Trying to uprade the new URL on redirect here is fruitless: the
// redirect URL cannot be changed at this point. upgrade-insecure-requests
// needs to move to the net stack to resolve this. https://crbug.com/615885
- if (!is_redirect) {
- GURL new_url;
- if (parent->ShouldModifyRequestUrlForCsp(
- common_params_.url, true /* is subresource */, &new_url)) {
- common_params_.url = new_url;
- request_params_.original_url = new_url;
+ if (!is_redirect && !frame_tree_node()->IsMainFrame()) {
+ if (parent &&
+ parent->ShouldModifyRequestUrlForCsp(true /* is subresource */)) {
+ parent->ModifyRequestUrlForCsp(&common_params_.url);
+ request_params_.original_url = common_params_.url;
}
}
- if (parent->IsAllowedByCsp(
- CSPDirective::FrameSrc, common_params_.url, is_redirect,
- common_params_.source_location.value_or(SourceLocation()),
- CSPContext::CHECK_ENFORCED_CSP)) {
- return CONTENT_SECURITY_POLICY_CHECK_PASSED;
- }
-
- return CONTENT_SECURITY_POLICY_CHECK_FAILED;
+ net::Error enforced_csp_status = CheckCSPDirectives(
+ parent, is_redirect, is_response_check, CSPContext::CHECK_ENFORCED_CSP);
+ if (enforced_csp_status != net::OK)
+ return enforced_csp_status;
+ return report_only_csp_status;
}
NavigationRequest::CredentialedSubresourceCheckResult
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index 7582a5e3bc6..164401d6db4 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/initiator_csp_context.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/common/content_export.h"
#include "content/common/frame_message_enums.h"
@@ -24,6 +25,7 @@
namespace network {
class ResourceRequestBody;
+struct URLLoaderCompletionStatus;
}
namespace content {
@@ -36,10 +38,8 @@ class NavigationURLLoader;
class NavigationData;
class NavigationUIData;
class SiteInstanceImpl;
-class StreamHandle;
struct SubresourceLoaderParams;
-// PlzNavigate
// A UI thread object that owns a navigation request until it commits. It
// ensures the UI thread can start a navigation request in the
// ResourceDispatcherHost (that lives on the IO thread).
@@ -209,16 +209,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
mojom::TransferrableURLLoaderPtr transferrable_loader);
private:
- // This enum describes the result of a Content Security Policy (CSP) check for
- // the request.
- enum ContentSecurityPolicyCheckResult {
- // The request should be allowed to continue. PASSED could mean that the
- // request did not violate any CSP, or that it violated a report-only CSP.
- CONTENT_SECURITY_POLICY_CHECK_PASSED,
- // The request should be blocked because it violated an enforced CSP.
- CONTENT_SECURITY_POLICY_CHECK_FAILED,
- };
-
NavigationRequest(FrameTreeNode* frame_tree_node,
const CommonNavigationParams& common_params,
mojom::BeginNavigationParamsPtr begin_params,
@@ -236,28 +226,28 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
void OnResponseStarted(
const scoped_refptr<network::ResourceResponse>& response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- std::unique_ptr<StreamHandle> body,
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& request_id,
bool is_download,
bool is_stream,
base::Optional<SubresourceLoaderParams> subresource_loader_params)
override;
- void OnRequestFailed(bool has_stale_copy_in_cache,
- int net_error,
- const base::Optional<net::SSLInfo>& ssl_info) override;
+ void OnRequestFailed(
+ const network::URLLoaderCompletionStatus& status) override;
void OnRequestStarted(base::TimeTicks timestamp) override;
// A version of OnRequestFailed() that allows skipping throttles, to be used
// when a request failed due to a throttle result itself. |error_page_content|
// is only used when |skip_throttles| is true.
void OnRequestFailedInternal(
- bool has_stale_copy_in_cache,
- int net_error,
- const base::Optional<net::SSLInfo>& ssl_info,
+ const network::URLLoaderCompletionStatus& status,
bool skip_throttles,
const base::Optional<std::string>& error_page_content);
+ // Helper to determine whether an error page for the provided error code
+ // should stay in the current process.
+ bool ShouldKeepErrorPageInCurrentProcess(int net_error);
+
// Called when the NavigationThrottles have been checked by the
// NavigationHandle.
void OnStartChecksComplete(NavigationThrottle::ThrottleCheckResult result);
@@ -277,14 +267,32 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// be destroyed after this call.
void CommitNavigation();
+ // Checks if the specified CSP context's relevant CSP directive
+ // allows the navigation. This is called to perform the frame-src
+ // and navigate-to checks.
+ bool IsAllowedByCSPDirective(CSPContext* context,
+ CSPDirective::Name directive,
+ bool is_redirect,
+ bool is_response_check,
+ CSPContext::CheckCSPDisposition disposition);
+
+ // Checks if CSP allows the navigation. This will check the frame-src and
+ // navigate-to directives.
+ // Returns net::OK if the checks pass, and net::ERR_ABORTED or
+ // net::ERR_BLOCKED_BY_CLIENT depending on which checks fail.
+ net::Error CheckCSPDirectives(RenderFrameHostImpl* parent,
+ bool is_redirect,
+ bool is_response_check,
+ CSPContext::CheckCSPDisposition disposition);
+
// Check whether a request should be allowed to continue or should be blocked
// because it violates a CSP. This method can have two side effects:
// - If a CSP is configured to send reports and the request violates the CSP,
// a report will be sent.
// - The navigation request may be upgraded from HTTP to HTTPS if a CSP is
// configured to upgrade insecure requests.
- ContentSecurityPolicyCheckResult CheckContentSecurityPolicyFrameSrc(
- bool is_redirect);
+ net::Error CheckContentSecurityPolicy(bool is_redirect,
+ bool is_response_check);
// This enum describes the result of the credentialed subresource check for
// the request.
@@ -377,10 +385,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// Holds objects received from OnResponseStarted while the WillProcessResponse
// checks are performed by the NavigationHandle. Once the checks have been
// completed, these objects will be used to continue the navigation.
- // The URLLoaderClientEndpointsPtr is used when the Network Service or
- // NavigationMojoResponse is enabled. Otherwise the StreamHandle is used.
scoped_refptr<network::ResourceResponse> response_;
- std::unique_ptr<StreamHandle> body_;
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints_;
net::SSLInfo ssl_info_;
bool is_download_;
@@ -390,6 +395,8 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
bool has_stale_copy_in_cache_;
int net_error_;
+ std::unique_ptr<InitiatorCSPContext> initiator_csp_context_;
+
base::Closure on_start_checks_complete_closure_;
// Used in the network service world to pass the subressource loader params
@@ -397,7 +404,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
base::Optional<SubresourceLoaderParams> subresource_loader_params_;
// See comment on accessor.
- base::UnguessableToken devtools_navigation_token_;
+ const base::UnguessableToken devtools_navigation_token_;
base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>>
subresource_overrides_;
diff --git a/chromium/content/browser/frame_host/navigation_request_info.cc b/chromium/content/browser/frame_host/navigation_request_info.cc
index 4e918bf1e6d..51d8563db09 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.cc
+++ b/chromium/content/browser/frame_host/navigation_request_info.cc
@@ -4,7 +4,6 @@
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "mojo/common/values_struct_traits.h"
namespace content {
@@ -20,7 +19,8 @@ NavigationRequestInfo::NavigationRequestInfo(
bool report_raw_headers,
bool is_prerendering,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- blob_url_loader_factory)
+ blob_url_loader_factory,
+ const base::UnguessableToken& devtools_navigation_token)
: common_params(common_params),
begin_params(std::move(begin_params)),
site_for_cookies(site_for_cookies),
@@ -31,7 +31,8 @@ NavigationRequestInfo::NavigationRequestInfo(
is_for_guests_only(is_for_guests_only),
report_raw_headers(report_raw_headers),
is_prerendering(is_prerendering),
- blob_url_loader_factory(std::move(blob_url_loader_factory)) {}
+ blob_url_loader_factory(std::move(blob_url_loader_factory)),
+ devtools_navigation_token(devtools_navigation_token) {}
NavigationRequestInfo::NavigationRequestInfo(const NavigationRequestInfo& other)
: common_params(other.common_params),
@@ -43,7 +44,8 @@ NavigationRequestInfo::NavigationRequestInfo(const NavigationRequestInfo& other)
frame_tree_node_id(other.frame_tree_node_id),
is_for_guests_only(other.is_for_guests_only),
report_raw_headers(other.report_raw_headers),
- is_prerendering(other.is_prerendering) {}
+ is_prerendering(other.is_prerendering),
+ devtools_navigation_token(other.devtools_navigation_token) {}
NavigationRequestInfo::~NavigationRequestInfo() {}
diff --git a/chromium/content/browser/frame_host/navigation_request_info.h b/chromium/content/browser/frame_host/navigation_request_info.h
index 47dbca17b5c..304502f0a25 100644
--- a/chromium/content/browser/frame_host/navigation_request_info.h
+++ b/chromium/content/browser/frame_host/navigation_request_info.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "content/common/navigation_params.h"
#include "content/common/navigation_params.mojom.h"
@@ -22,18 +23,20 @@ namespace content {
// ResourceDispatcherHost. It is initialized on the UI thread, and then passed
// to the IO thread by a NavigationRequest object.
struct CONTENT_EXPORT NavigationRequestInfo {
- NavigationRequestInfo(const CommonNavigationParams& common_params,
- mojom::BeginNavigationParamsPtr begin_params,
- const GURL& site_for_cookies,
- bool is_main_frame,
- bool parent_is_main_frame,
- bool are_ancestors_secure,
- int frame_tree_node_id,
- bool is_for_guests_only,
- bool report_raw_headers,
- bool is_prerendering,
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- blob_url_loader_factory);
+ NavigationRequestInfo(
+ const CommonNavigationParams& common_params,
+ mojom::BeginNavigationParamsPtr begin_params,
+ const GURL& site_for_cookies,
+ bool is_main_frame,
+ bool parent_is_main_frame,
+ bool are_ancestors_secure,
+ int frame_tree_node_id,
+ bool is_for_guests_only,
+ bool report_raw_headers,
+ bool is_prerendering,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ blob_url_loader_factory,
+ const base::UnguessableToken& devtools_navigation_token);
NavigationRequestInfo(const NavigationRequestInfo& other);
~NavigationRequestInfo();
@@ -61,6 +64,8 @@ struct CONTENT_EXPORT NavigationRequestInfo {
// URLLoaderFactory to facilitate loading blob URLs.
std::unique_ptr<network::SharedURLLoaderFactoryInfo> blob_url_loader_factory;
+
+ const base::UnguessableToken devtools_navigation_token;
};
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index ff6457f3ae7..0876a3899ad 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -26,8 +26,22 @@ bool Navigator::NavigateToPendingEntry(
return false;
}
-bool Navigator::NavigateNewChildFrame(RenderFrameHostImpl* render_frame_host,
- const GURL& default_url) {
+bool Navigator::NavigateToEntry(
+ FrameTreeNode* frame_tree_node,
+ const FrameNavigationEntry& frame_entry,
+ const NavigationEntryImpl& entry,
+ ReloadType reload_type,
+ bool is_same_document_history_load,
+ bool is_history_navigation_in_new_child,
+ bool is_pending_entry,
+ const scoped_refptr<network::ResourceRequestBody>& post_body,
+ std::unique_ptr<NavigationUIData> navigation_ui_data) {
+ return false;
+}
+
+bool Navigator::StartHistoryNavigationInNewSubframe(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& default_url) {
return false;
}
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index 1ae19f9774e..5290287896d 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -101,16 +101,29 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
ReloadType reload_type,
bool is_same_document_history_load,
std::unique_ptr<NavigationUIData> navigation_ui_data);
+ // DEPRECATED. Callers should use NavigateToPendingEntry instead.
+ // TODO(clamy): This is only briefly exposed to facilitate a larger
+ // refactoring of NavigationController and will go away soon.
+ virtual bool NavigateToEntry(
+ FrameTreeNode* frame_tree_node,
+ const FrameNavigationEntry& frame_entry,
+ const NavigationEntryImpl& entry,
+ ReloadType reload_type,
+ bool is_same_document_history_load,
+ bool is_history_navigation_in_new_child,
+ bool is_pending_entry,
+ const scoped_refptr<network::ResourceRequestBody>& post_body,
+ std::unique_ptr<NavigationUIData> navigation_ui_data);
// Called on a newly created subframe during a history navigation. The browser
// process looks up the corresponding FrameNavigationEntry for the new frame
// navigates it in the correct process. Returns false if the
- // FrameNavigationEntry can't be found or the navigation fails. This is only
- // used in OOPIF-enabled modes.
+ // FrameNavigationEntry can't be found or the navigation fails.
// TODO(creis): Remove |default_url| once we have collected UMA stats on the
// cases that we use a different URL from history than the frame's src.
- virtual bool NavigateNewChildFrame(RenderFrameHostImpl* render_frame_host,
- const GURL& default_url);
+ virtual bool StartHistoryNavigationInNewSubframe(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& default_url);
// Navigation requests -------------------------------------------------------
@@ -129,25 +142,22 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
bool should_replace_current_entry,
bool user_gesture,
blink::WebTriggeringEventInfo triggering_event_info,
- const base::Optional<std::string>& suggested_filename) {}
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {}
- // The RenderFrameHostImpl wants to transfer the request to a new renderer.
- // |redirect_chain| contains any redirect URLs (excluding |url|) that happened
- // before the transfer. If |method| is "POST", then |post_body| needs to
- // specify the request body, otherwise |post_body| should be null.
- virtual void RequestTransferURL(
+ // Called when a document requests a navigation in another document through a
+ // RenderFrameProxy. If |method| is "POST", then |post_body| needs to specify
+ // the request body, otherwise |post_body| should be null.
+ virtual void NavigateFromFrameProxy(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
SiteInstance* source_site_instance,
- const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
- const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
const std::string& method,
scoped_refptr<network::ResourceRequestBody> post_body,
const std::string& extra_headers,
- const base::Optional<std::string>& suggested_filename) {}
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {}
// Called after receiving a BeforeUnloadACK IPC from the renderer. If
// |frame_tree_node| has a NavigationRequest waiting for the renderer
@@ -201,8 +211,7 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// With sufficiently bad interleaving of IPCs, this may no longer be the
// pending NavigationEntry, in which case the pending NavigationEntry will not
// be discarded.
- virtual void DiscardPendingEntryIfNeeded(int expected_pending_entry_id,
- bool is_download) {}
+ virtual void DiscardPendingEntryIfNeeded(int expected_pending_entry_id) {}
protected:
friend class base::RefCounted<Navigator>;
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index bb33fd3b868..e098e1bc69e 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -237,13 +237,11 @@ void NavigatorImpl::DidFailProvisionalLoadWithError(
}
// Discard the pending navigation entry if needed.
- int expected_pending_entry_id = 0;
- if (render_frame_host->GetNavigationHandle()) {
- expected_pending_entry_id =
- render_frame_host->GetNavigationHandle()->pending_nav_entry_id();
- DCHECK(!render_frame_host->GetNavigationHandle()->IsDownload());
- }
- DiscardPendingEntryIfNeeded(expected_pending_entry_id, false);
+ int expected_pending_entry_id =
+ render_frame_host->GetNavigationHandle()
+ ? render_frame_host->GetNavigationHandle()->pending_nav_entry_id()
+ : 0;
+ DiscardPendingEntryIfNeeded(expected_pending_entry_id);
}
void NavigatorImpl::DidFailLoadWithError(
@@ -393,42 +391,11 @@ bool NavigatorImpl::NavigateToPendingEntry(
std::move(navigation_ui_data));
}
-bool NavigatorImpl::NavigateNewChildFrame(
+bool NavigatorImpl::StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
const GURL& default_url) {
- NavigationEntryImpl* entry =
- controller_->GetEntryWithUniqueID(render_frame_host->nav_entry_id());
- if (!entry)
- return false;
-
- FrameNavigationEntry* frame_entry =
- entry->GetFrameEntry(render_frame_host->frame_tree_node());
- if (!frame_entry)
- return false;
-
- // Track how often history navigations load a different URL into a subframe
- // than the frame's default URL.
- bool restoring_different_url = frame_entry->url() != default_url;
- UMA_HISTOGRAM_BOOLEAN("SessionRestore.RestoredSubframeURL",
- restoring_different_url);
- // If this frame's unique name uses a frame path, record the name length.
- // If these names are long in practice, then a proposed plan to truncate
- // unique names might affect restore behavior, since it is complex to deal
- // with truncated names inside frame paths.
- if (restoring_different_url) {
- const std::string& unique_name =
- render_frame_host->frame_tree_node()->unique_name();
- const char kFramePathPrefix[] = "<!--framePath ";
- if (base::StartsWith(unique_name, kFramePathPrefix,
- base::CompareCase::SENSITIVE)) {
- UMA_HISTOGRAM_COUNTS("SessionRestore.RestoreSubframeFramePathLength",
- unique_name.size());
- }
- }
-
- return NavigateToEntry(render_frame_host->frame_tree_node(), *frame_entry,
- *entry, ReloadType::NONE, false, true, false, nullptr,
- nullptr /* navigation_ui_data */);
+ return controller_->StartHistoryNavigationInNewSubframe(render_frame_host,
+ default_url);
}
void NavigatorImpl::DidNavigate(
@@ -480,7 +447,8 @@ void NavigatorImpl::DidNavigate(
// run unload handlers. Those unload handlers should still see the old
// frame's origin. See https://crbug.com/825283.
frame_tree_node->render_manager()->DidNavigateFrame(
- render_frame_host, params.gesture == NavigationGestureUser);
+ render_frame_host, params.gesture == NavigationGestureUser,
+ is_same_document_navigation);
// Save the new page's origin and other properties, and replicate them to
// proxies, including the proxy created in DidNavigateFrame() to replace the
@@ -498,13 +466,12 @@ void NavigatorImpl::DidNavigate(
}
// Update the site of the SiteInstance if it doesn't have one yet, unless
- // assigning a site is not necessary for this URL or the commit was for an
- // error page. In that case, the SiteInstance can still be considered unused
- // until a navigation to a real page.
+ // assigning a site is not necessary for this URL. In that case, the
+ // SiteInstance can still be considered unused until a navigation to a real
+ // page.
SiteInstanceImpl* site_instance = render_frame_host->GetSiteInstance();
if (!site_instance->HasSite() &&
- SiteInstanceImpl::ShouldAssignSiteForURL(params.url) &&
- !params.url_is_unreachable) {
+ SiteInstanceImpl::ShouldAssignSiteForURL(params.url)) {
site_instance->SetSite(params.url);
}
@@ -589,7 +556,7 @@ void NavigatorImpl::RequestOpenURL(
bool should_replace_current_entry,
bool user_gesture,
blink::WebTriggeringEventInfo triggering_event_info,
- const base::Optional<std::string>& suggested_filename) {
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
// Note: This can be called for subframes (even when OOPIFs are not possible)
// if the disposition calls for a different window.
@@ -607,7 +574,7 @@ void NavigatorImpl::RequestOpenURL(
// redirects. http://crbug.com/311721.
std::vector<GURL> redirect_chain;
- // Note that unlike RequestTransferURL, this uses the navigating
+ // Note that unlike NavigateFromFrameProxy, this uses the navigating
// RenderFrameHost's current SiteInstance, as that's where this navigation
// originated.
GURL dest_url(url);
@@ -638,12 +605,11 @@ void NavigatorImpl::RequestOpenURL(
params.should_replace_current_entry = should_replace_current_entry;
params.user_gesture = user_gesture;
params.triggering_event_info = triggering_event_info;
- params.suggested_filename = suggested_filename;
// RequestOpenURL is used only for local frames, so we can get here only if
// the navigation is initiated by a frame in the same SiteInstance as this
// frame. Note that navigations on RenderFrameProxies do not use
- // RequestOpenURL and go through RequestTransferURL instead.
+ // RequestOpenURL and go through NavigateFromFrameProxy instead.
params.source_site_instance = current_site_instance;
params.source_render_frame_id = render_frame_host->GetRoutingID();
@@ -660,6 +626,8 @@ void NavigatorImpl::RequestOpenURL(
params.is_renderer_initiated = false;
}
+ params.blob_url_loader_factory = std::move(blob_url_loader_factory);
+
GetContentClient()->browser()->OverrideNavigationParams(
current_site_instance, &params.transition, &params.is_renderer_initiated,
&params.referrer);
@@ -668,19 +636,17 @@ void NavigatorImpl::RequestOpenURL(
delegate_->OpenURL(params);
}
-void NavigatorImpl::RequestTransferURL(
+void NavigatorImpl::NavigateFromFrameProxy(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
SiteInstance* source_site_instance,
- const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
- const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
const std::string& method,
scoped_refptr<network::ResourceRequestBody> post_body,
const std::string& extra_headers,
- const base::Optional<std::string>& suggested_filename) {
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
// |method != "POST"| should imply absence of |post_body|.
if (method != "POST" && post_body) {
NOTREACHED();
@@ -692,20 +658,18 @@ void NavigatorImpl::RequestTransferURL(
render_frame_host->frame_tree_node()->IsMainFrame()))
return;
- GURL dest_url(url);
Referrer referrer_to_use(referrer);
- FrameTreeNode* node = render_frame_host->frame_tree_node();
SiteInstance* current_site_instance = render_frame_host->GetSiteInstance();
// It is important to pass in the source_site_instance if it is available
// (such as when navigating a proxy). See https://crbug.com/656752.
if (!GetContentClient()->browser()->ShouldAllowOpenURL(
source_site_instance ? source_site_instance : current_site_instance,
url)) {
- // It is important to return here, rather than rewrite the dest_url to
+ // It is important to return here, rather than rewrite the url to
// about:blank. The latter won't actually have any effect when
// transferring, as NavigateToEntry will think that the transfer is to the
- // same RFH that started the navigation and let the existing navigation
- // (for the disallowed URL) proceed.
+ // same RFH that started the navigation and let the existing navigation (for
+ // the disallowed URL) proceed.
return;
}
@@ -727,76 +691,10 @@ void NavigatorImpl::RequestTransferURL(
current_site_instance, &page_transition, &is_renderer_initiated,
&referrer_to_use);
- // Create a NavigationEntry for the transfer, without making it the pending
- // entry. Subframe transfers should only be possible in OOPIF-enabled modes,
- // and should have a clone of the last committed entry with a
- // FrameNavigationEntry for the target frame. Main frame transfers should
- // have a new NavigationEntry.
- // TODO(creis): Make this unnecessary by creating (and validating) the params
- // directly, passing them to the destination RenderFrameHost. See
- // https://crbug.com/536906.
- std::unique_ptr<NavigationEntryImpl> entry;
- if (!node->IsMainFrame()) {
- // Subframe case: create FrameNavigationEntry.
- if (controller_->GetLastCommittedEntry()) {
- entry = controller_->GetLastCommittedEntry()->Clone();
- entry->set_extra_headers(extra_headers);
- // TODO(arthursonzogni): What about |is_renderer_initiated|?
- // Renderer-initiated navigation that target a remote frame are currently
- // classified as browser-initiated when this one has already navigated.
- // See https://crbug.com/722251.
- } else {
- // If there's no last committed entry, create an entry for about:blank
- // with a subframe entry for our destination.
- // TODO(creis): Ensure this case can't exist in https://crbug.com/524208.
- entry = NavigationEntryImpl::FromNavigationEntry(
- controller_->CreateNavigationEntry(
- GURL(url::kAboutBlankURL), referrer_to_use, page_transition,
- is_renderer_initiated, extra_headers,
- controller_->GetBrowserContext()));
- }
- entry->AddOrUpdateFrameEntry(
- node, -1, -1, nullptr,
- static_cast<SiteInstanceImpl*>(source_site_instance), dest_url,
- referrer_to_use, redirect_chain, PageState(), method, -1);
- } else {
- // Main frame case.
- entry = NavigationEntryImpl::FromNavigationEntry(
- controller_->CreateNavigationEntry(
- dest_url, referrer_to_use, page_transition, is_renderer_initiated,
- extra_headers, controller_->GetBrowserContext()));
- entry->root_node()->frame_entry->set_source_site_instance(
- static_cast<SiteInstanceImpl*>(source_site_instance));
- entry->root_node()->frame_entry->set_method(method);
- entry->SetRedirectChain(redirect_chain);
- }
- entry->set_suggested_filename(suggested_filename);
-
- // Don't allow an entry replacement if there is no entry to replace.
- // http://crbug.com/457149
- if (should_replace_current_entry && controller_->GetEntryCount() > 0)
- entry->set_should_replace_entry(true);
- if (controller_->GetLastCommittedEntry() &&
- controller_->GetLastCommittedEntry()->GetIsOverridingUserAgent()) {
- entry->SetIsOverridingUserAgent(true);
- }
- entry->set_transferred_global_request_id(transferred_global_request_id);
- // TODO(creis): Set user gesture and intent received timestamp on Android.
-
- // We may not have successfully added the FrameNavigationEntry to |entry|
- // above (per https://crbug.com/608402), in which case we create it from
- // scratch. This works because we do not depend on |frame_entry| being inside
- // |entry| during NavigateToEntry. This will go away when we shortcut this
- // further in https://crbug.com/536906.
- scoped_refptr<FrameNavigationEntry> frame_entry(entry->GetFrameEntry(node));
- if (!frame_entry) {
- frame_entry = new FrameNavigationEntry(
- node->unique_name(), -1, -1, nullptr,
- static_cast<SiteInstanceImpl*>(source_site_instance), dest_url,
- referrer_to_use, redirect_chain, PageState(), method, -1);
- }
- NavigateToEntry(node, *frame_entry, *entry.get(), ReloadType::NONE, false,
- false, false, post_body, nullptr /* navigation_ui_data */);
+ controller_->NavigateFromFrameProxy(
+ render_frame_host, url, is_renderer_initiated, source_site_instance,
+ referrer_to_use, page_transition, should_replace_current_entry, method,
+ post_body, extra_headers, std::move(blob_url_loader_factory));
}
void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node,
@@ -914,6 +812,22 @@ void NavigatorImpl::OnBeginNavigation(
std::move(blob_url_loader_factory)));
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
+ // This frame has already run beforeunload before it sent this IPC. See if
+ // any of its cross-process subframes also need to run beforeunload. If so,
+ // delay the navigation until receiving beforeunload ACKs from those frames.
+ DCHECK(!FrameMsg_Navigate_Type::IsSameDocument(
+ navigation_request->common_params().navigation_type));
+ bool should_dispatch_beforeunload =
+ frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(
+ true /* check_subframes_only */);
+ if (should_dispatch_beforeunload) {
+ frame_tree_node->navigation_request()->SetWaitingForRendererResponse();
+ frame_tree_node->current_frame_host()->DispatchBeforeUnload(
+ RenderFrameHostImpl::BeforeUnloadType::RENDERER_INITIATED_NAVIGATION,
+ FrameMsg_Navigate_Type::IsReload(common_params.navigation_type));
+ return;
+ }
+
// For main frames, NavigationHandle will be created after the call to
// |DidStartMainFrameNavigation|, so it receives the most up to date pending
// entry from the NavigationController.
@@ -986,15 +900,14 @@ void NavigatorImpl::LogBeforeUnloadTime(
}
}
-void NavigatorImpl::DiscardPendingEntryIfNeeded(int expected_pending_entry_id,
- bool is_download) {
+void NavigatorImpl::DiscardPendingEntryIfNeeded(int expected_pending_entry_id) {
// Racy conditions can cause a fail message to arrive after its corresponding
// pending entry has been replaced by another navigation. If
// |DiscardPendingEntry| is called in this case, then the completely valid
// entry for the new navigation would be discarded. See crbug.com/513742. To
// catch this case, the current pending entry is compared against the current
// navigation handle's entry id, which should correspond to the failed load.
- NavigationEntryImpl* pending_entry = controller_->GetPendingEntry();
+ NavigationEntry* pending_entry = controller_->GetPendingEntry();
bool pending_matches_fail_msg =
pending_entry &&
expected_pending_entry_id == pending_entry->GetUniqueID();
@@ -1015,13 +928,9 @@ void NavigatorImpl::DiscardPendingEntryIfNeeded(int expected_pending_entry_id,
// allow the view to clear the pending entry and typed URL if the user
// requests (e.g., hitting Escape with focus in the address bar).
//
- // Note that the pending entry does not need to be preserved for downloads,
- // since the user is unlikely to try again.
- //
// Note: don't touch the transient entry, since an interstitial may exist.
- bool should_preserve_entry = (controller_->IsUnmodifiedBlankTab() ||
- delegate_->ShouldPreserveAbortedURLs()) &&
- !is_download;
+ bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() ||
+ delegate_->ShouldPreserveAbortedURLs();
if (pending_entry != controller_->GetVisibleEntry() ||
!should_preserve_entry) {
controller_->DiscardPendingEntry(true);
@@ -1075,7 +984,8 @@ void NavigatorImpl::RequestNavigation(
FrameMsg_Navigate_Type::IsSameDocument(navigation_type);
bool should_dispatch_beforeunload =
!is_same_document && !is_history_navigation_in_new_child &&
- frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload();
+ frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload(
+ false /* check_subframes_only */);
std::unique_ptr<NavigationRequest> scoped_request =
NavigationRequest::CreateBrowserInitiated(
frame_tree_node, dest_url, dest_referrer, frame_entry, entry,
@@ -1095,7 +1005,8 @@ void NavigatorImpl::RequestNavigation(
if (should_dispatch_beforeunload) {
navigation_request->SetWaitingForRendererResponse();
frame_tree_node->current_frame_host()->DispatchBeforeUnload(
- true, reload_type != ReloadType::NONE);
+ RenderFrameHostImpl::BeforeUnloadType::BROWSER_INITIATED_NAVIGATION,
+ reload_type != ReloadType::NONE);
} else {
navigation_request->BeginNavigation();
// DO NOT USE |navigation_request| BEYOND THIS POINT. It might have been
@@ -1184,10 +1095,11 @@ void NavigatorImpl::DidStartMainFrameNavigation(
!renderer_provisional_load_to_pending_url) {
std::unique_ptr<NavigationEntryImpl> entry =
NavigationEntryImpl::FromNavigationEntry(
- controller_->CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
url, content::Referrer(), ui::PAGE_TRANSITION_LINK,
true /* is_renderer_initiated */, std::string(),
- controller_->GetBrowserContext()));
+ controller_->GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
entry->set_site_instance(site_instance);
// TODO(creis): If there's a pending entry already, find a safe way to
// update it instead of replacing it and copying over things like this.
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index b1bb76b4e7b..21557ba9c0c 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -63,33 +63,43 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
ReloadType reload_type,
bool is_same_document_history_load,
std::unique_ptr<NavigationUIData> navigation_ui_data) override;
- bool NavigateNewChildFrame(RenderFrameHostImpl* render_frame_host,
- const GURL& default_url) override;
- void RequestOpenURL(
+ bool NavigateToEntry(
+ FrameTreeNode* frame_tree_node,
+ const FrameNavigationEntry& frame_entry,
+ const NavigationEntryImpl& entry,
+ ReloadType reload_type,
+ bool is_same_document_history_load,
+ bool is_history_navigation_in_new_child,
+ bool is_pending_entry,
+ const scoped_refptr<network::ResourceRequestBody>& post_body,
+ std::unique_ptr<NavigationUIData> navigation_ui_data) override;
+ bool StartHistoryNavigationInNewSubframe(
RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- bool uses_post,
- const scoped_refptr<network::ResourceRequestBody>& body,
- const std::string& extra_headers,
- const Referrer& referrer,
- WindowOpenDisposition disposition,
- bool should_replace_current_entry,
- bool user_gesture,
- blink::WebTriggeringEventInfo triggering_event_info,
- const base::Optional<std::string>& suggested_filename) override;
- void RequestTransferURL(
+ const GURL& default_url) override;
+ void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ bool uses_post,
+ const scoped_refptr<network::ResourceRequestBody>& body,
+ const std::string& extra_headers,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ bool should_replace_current_entry,
+ bool user_gesture,
+ blink::WebTriggeringEventInfo triggering_event_info,
+ scoped_refptr<network::SharedURLLoaderFactory>
+ blob_url_loader_factory) override;
+ void NavigateFromFrameProxy(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
SiteInstance* source_site_instance,
- const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
- const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
const std::string& method,
scoped_refptr<network::ResourceRequestBody> post_body,
const std::string& extra_headers,
- const base::Optional<std::string>& suggested_filename) override;
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory)
+ override;
void OnBeforeUnloadACK(FrameTreeNode* frame_tree_node,
bool proceed,
const base::TimeTicks& proceed_time) override;
@@ -108,8 +118,7 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const base::TimeTicks& renderer_before_unload_end_time) override;
void CancelNavigation(FrameTreeNode* frame_tree_node,
bool inform_renderer) override;
- void DiscardPendingEntryIfNeeded(int expected_pending_entry_id,
- bool is_download) override;
+ void DiscardPendingEntryIfNeeded(int expected_pending_entry_id) override;
private:
// Holds data used to track browser side navigation metrics.
@@ -118,20 +127,6 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
friend class NavigatorTestWithBrowserSideNavigation;
~NavigatorImpl() override;
- // Navigates to the given entry, which might be the pending entry (if
- // |is_pending_entry| is true). Private because all callers should use either
- // NavigateToPendingEntry or NavigateToNewChildFrame.
- bool NavigateToEntry(
- FrameTreeNode* frame_tree_node,
- const FrameNavigationEntry& frame_entry,
- const NavigationEntryImpl& entry,
- ReloadType reload_type,
- bool is_same_document_history_load,
- bool is_history_navigation_in_new_child,
- bool is_pending_entry,
- const scoped_refptr<network::ResourceRequestBody>& post_body,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
-
// If needed, sends a BeforeUnload IPC to the renderer to ask it to execute
// the beforeUnload event. Otherwise, the navigation request will be started.
void RequestNavigation(
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index d5f6556da46..3f560d4d333 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -16,12 +16,10 @@
#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/streams/stream.h"
#include "content/common/frame.mojom.h"
#include "content/common/frame_messages.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/navigation_data.h"
-#include "content/public/browser/stream_handle.h"
#include "content/public/common/content_features.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
@@ -123,9 +121,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the current RenderFrameHost commit the navigation.
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
- GetLoaderForNavigationRequest(request)->CallOnResponseStarted(
- response, MakeEmptyStream(), nullptr);
- EXPECT_TRUE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ GetLoaderForNavigationRequest(request)->CallOnResponseStarted(response,
+ nullptr);
+ EXPECT_TRUE(main_test_rfh()->navigation_request());
EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_FALSE(node->navigation_request());
@@ -158,7 +156,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
FrameHostMsg_DidStopLoading(main_test_rfh()->GetRoutingID()));
// Start a renderer-initiated non-user-initiated navigation.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
auto navigation =
NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
navigation->SetTransition(ui::PageTransitionFromInt(
@@ -180,7 +178,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the current RenderFrameHost commit the navigation
navigation->ReadyToCommit();
- EXPECT_TRUE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(main_test_rfh()->navigation_request());
EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_FALSE(node->navigation_request());
@@ -208,7 +206,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
int32_t site_instance_id_1 = main_test_rfh()->GetSiteInstance()->GetId();
// Start a renderer-initiated navigation.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
auto navigation =
NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
navigation->Start();
@@ -233,11 +231,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
if (AreAllSitesIsolatedForTesting()) {
EXPECT_EQ(navigation->GetFinalRenderFrameHost(),
GetSpeculativeRenderFrameHost(node));
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
} else {
- EXPECT_TRUE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(main_test_rfh()->navigation_request());
}
EXPECT_FALSE(node->navigation_request());
- EXPECT_TRUE(process()->did_frame_commit_navigation());
// Commit the navigation.
navigation->Commit();
@@ -375,7 +373,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, NoContent) {
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
// Navigate to a different site.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
RequestNavigation(node, kUrl2);
main_test_rfh()->SendBeforeUnloadACK(true);
@@ -392,18 +390,18 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, NoContent) {
response->head.headers = new net::HttpResponseHeaders(
std::string(kNoContentHeaders, arraysize(kNoContentHeaders)));
GetLoaderForNavigationRequest(main_request)
- ->CallOnResponseStarted(response, MakeEmptyStream(), nullptr);
+ ->CallOnResponseStarted(response, nullptr);
// There should be no pending nor speculative RenderFrameHost; the navigation
// was aborted.
- EXPECT_FALSE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
EXPECT_FALSE(node->navigation_request());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
// Now, repeat the test with 205 Reset Content.
// Navigate to a different site again.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
RequestNavigation(node, kUrl2);
main_test_rfh()->SendBeforeUnloadACK(true);
@@ -417,17 +415,17 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, NoContent) {
response->head.headers = new net::HttpResponseHeaders(
std::string(kResetContentHeaders, arraysize(kResetContentHeaders)));
GetLoaderForNavigationRequest(main_request)
- ->CallOnResponseStarted(response, MakeEmptyStream(), nullptr);
+ ->CallOnResponseStarted(response, nullptr);
// There should be no pending nor speculative RenderFrameHost; the navigation
// was aborted.
- EXPECT_FALSE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
EXPECT_FALSE(node->navigation_request());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
-// PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
-// site navigation.
+// Test that a new RenderFrameHost is created when doing a cross site
+// navigation.
TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
const GURL kUrl1("http://www.chromium.org/");
const GURL kUrl2("http://www.google.com/");
@@ -437,7 +435,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
// Navigate to a different site.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
int entry_id = RequestNavigation(node, kUrl2);
NavigationRequest* main_request = node->navigation_request();
ASSERT_TRUE(main_request);
@@ -451,10 +449,10 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
GetLoaderForNavigationRequest(main_request)
- ->CallOnResponseStarted(response, MakeEmptyStream(), nullptr);
+ ->CallOnResponseStarted(response, nullptr);
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
- EXPECT_TRUE(speculative_rfh->GetProcess()->did_frame_commit_navigation());
- EXPECT_FALSE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(speculative_rfh->navigation_request());
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
speculative_rfh->SendNavigate(entry_id, true, kUrl2);
@@ -466,8 +464,8 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
-// PlzNavigate: Test that redirects are followed and the speculative
-// RenderFrameHost logic behaves as expected.
+// Test that redirects are followed and the speculative RenderFrameHost logic
+// behaves as expected.
TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
const GURL kUrl1("http://www.chromium.org/");
const GURL kUrl2("http://www.google.com/");
@@ -477,7 +475,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
// Navigate to a URL on the same site.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
int entry_id = RequestNavigation(node, kUrl1);
main_test_rfh()->SendBeforeUnloadACK(true);
NavigationRequest* main_request = node->navigation_request();
@@ -495,12 +493,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
GetLoaderForNavigationRequest(main_request)
- ->CallOnResponseStarted(response, MakeEmptyStream(), nullptr);
+ ->CallOnResponseStarted(response, nullptr);
TestRenderFrameHost* final_speculative_rfh =
GetSpeculativeRenderFrameHost(node);
EXPECT_TRUE(final_speculative_rfh);
- EXPECT_TRUE(
- final_speculative_rfh->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(final_speculative_rfh->navigation_request());
// Commit the navigation.
final_speculative_rfh->SendNavigate(entry_id, true, kUrl2);
@@ -513,8 +510,8 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, RedirectCrossSite) {
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
-// PlzNavigate: Test that a navigation is canceled if another browser-initiated
-// request has been issued in the meantime. Also confirms that the speculative
+// Test that a navigation is canceled if another browser-initiated request has
+// been issued in the meantime. Also confirms that the speculative
// RenderFrameHost is correctly updated in the process.
TEST_F(NavigatorTestWithBrowserSideNavigation,
BrowserInitiatedNavigationCancel) {
@@ -529,7 +526,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
// Request navigation to the 1st URL.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
RequestNavigation(node, kUrl1);
main_test_rfh()->SendBeforeUnloadACK(true);
NavigationRequest* request1 = node->navigation_request();
@@ -567,10 +564,10 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the RenderFrameHost commit the navigation.
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
- GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
- response, MakeEmptyStream(), nullptr);
- EXPECT_TRUE(speculative_rfh->GetProcess()->did_frame_commit_navigation());
- EXPECT_FALSE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(response,
+ nullptr);
+ EXPECT_TRUE(speculative_rfh->navigation_request());
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
// Commit the navigation.
speculative_rfh->SendNavigate(entry_id, true, kUrl2);
@@ -584,8 +581,8 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(site_instance_id_2, main_test_rfh()->GetSiteInstance()->GetId());
}
-// PlzNavigate: Test that a browser-initiated navigation is canceled if a
-// renderer-initiated user-initiated request has been issued in the meantime.
+// Test that a browser-initiated navigation is canceled if a renderer-initiated
+// user-initiated request has been issued in the meantime.
TEST_F(NavigatorTestWithBrowserSideNavigation,
RendererUserInitiatedNavigationCancel) {
const GURL kUrl0("http://www.wikipedia.org/");
@@ -598,7 +595,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Start a browser-initiated navigation to the 1st URL and receive its
// beforeUnload ACK.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
RequestNavigation(node, kUrl1);
main_test_rfh()->SendBeforeUnloadACK(true);
NavigationRequest* request1 = node->navigation_request();
@@ -639,11 +636,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the RenderFrameHost commit the navigation.
navigation->ReadyToCommit();
if (AreAllSitesIsolatedForTesting()) {
- EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)
- ->GetProcess()
- ->did_frame_commit_navigation());
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
} else {
- EXPECT_TRUE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(main_test_rfh()->navigation_request());
}
// Commit the navigation.
@@ -668,7 +663,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
// Start a renderer-initiated user-initiated navigation to the 1st URL.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
auto user_initiated_navigation =
NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
user_initiated_navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
@@ -708,11 +703,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the RenderFrameHost commit the navigation.
non_user_initiated_navigation->ReadyToCommit();
if (AreAllSitesIsolatedForTesting()) {
- EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)
- ->GetProcess()
- ->did_frame_commit_navigation());
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
} else {
- EXPECT_TRUE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(main_test_rfh()->navigation_request());
}
// Commit the navigation.
@@ -733,7 +726,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
FrameTreeNode* node = main_test_rfh()->frame_tree_node();
// Start a browser-initiated navigation to the 1st URL.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
int entry_id = RequestNavigation(node, kUrl1);
NavigationRequest* request1 = node->navigation_request();
ASSERT_TRUE(request1);
@@ -760,10 +753,10 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the RenderFrameHost commit the navigation.
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
- GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
- response, MakeEmptyStream(), nullptr);
- EXPECT_TRUE(speculative_rfh->GetProcess()->did_frame_commit_navigation());
- EXPECT_FALSE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(response,
+ nullptr);
+ EXPECT_TRUE(speculative_rfh->navigation_request());
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
// Commit the navigation.
speculative_rfh->SendNavigate(entry_id, true, kUrl1);
@@ -784,7 +777,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
int32_t site_instance_id_0 = main_test_rfh()->GetSiteInstance()->GetId();
// Start a renderer-initiated non-user-initiated navigation to the 1st URL.
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
auto navigation1 =
NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
navigation1->SetTransition(ui::PageTransitionFromInt(
@@ -828,11 +821,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Have the RenderFrameHost commit the navigation.
navigation2->ReadyToCommit();
if (AreAllSitesIsolatedForTesting()) {
- EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)
- ->GetProcess()
- ->did_frame_commit_navigation());
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
} else {
- EXPECT_TRUE(main_test_rfh()->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(main_test_rfh()->navigation_request());
}
// Commit the navigation.
@@ -890,7 +881,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Begin navigating to another site.
const GURL kUrl("http://google.com/");
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
int entry_id = RequestNavigation(node, kUrl);
TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
ASSERT_TRUE(speculative_rfh);
@@ -908,9 +899,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
GetLoaderForNavigationRequest(node->navigation_request())
- ->CallOnResponseStarted(response, MakeEmptyStream(), nullptr);
+ ->CallOnResponseStarted(response, nullptr);
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
- EXPECT_TRUE(speculative_rfh->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(speculative_rfh->navigation_request());
EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
// Invoke DidCommitProvisionalLoad.
@@ -931,7 +922,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Begin navigating to another site.
const GURL kUrl("http://google.com/");
- process()->set_did_frame_commit_navigation(false);
+ EXPECT_FALSE(main_test_rfh()->navigation_request());
int entry_id = RequestNavigation(node, kUrl);
TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
ASSERT_TRUE(speculative_rfh);
@@ -968,10 +959,10 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
scoped_refptr<network::ResourceResponse> response(
new network::ResourceResponse);
GetLoaderForNavigationRequest(main_request)
- ->CallOnResponseStarted(response, MakeEmptyStream(), nullptr);
+ ->CallOnResponseStarted(response, nullptr);
speculative_rfh = GetSpeculativeRenderFrameHost(node);
ASSERT_TRUE(speculative_rfh);
- EXPECT_TRUE(speculative_rfh->GetProcess()->did_frame_commit_navigation());
+ EXPECT_TRUE(speculative_rfh->navigation_request());
EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
EXPECT_TRUE(rfh_deleted_observer.deleted());
diff --git a/chromium/content/browser/frame_host/popup_menu_helper_mac.h b/chromium/content/browser/frame_host/popup_menu_helper_mac.h
index 2964f3cf3d5..03f039b0443 100644
--- a/chromium/content/browser/frame_host/popup_menu_helper_mac.h
+++ b/chromium/content/browser/frame_host/popup_menu_helper_mac.h
@@ -11,9 +11,9 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
#include "content/common/content_export.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/render_widget_host_observer.h"
#include "ui/gfx/geometry/rect.h"
#ifdef __OBJC__
@@ -33,7 +33,7 @@ class RenderFrameHostImpl;
class RenderWidgetHostViewMac;
struct MenuItem;
-class PopupMenuHelper : public NotificationObserver {
+class PopupMenuHelper : public RenderWidgetHostObserver {
public:
class Delegate {
public:
@@ -64,14 +64,14 @@ class PopupMenuHelper : public NotificationObserver {
virtual RenderWidgetHostViewMac* GetRenderWidgetHostView() const;
private:
- // NotificationObserver implementation:
- void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) override;
+ // RenderWidgetHostObserver implementation:
+ void RenderWidgetHostVisibilityChanged(RenderWidgetHost* widget_host,
+ bool became_visible) override;
+ void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override;
Delegate* delegate_; // Weak. Owns |this|.
- NotificationRegistrar notification_registrar_;
+ ScopedObserver<RenderWidgetHost, RenderWidgetHostObserver> observer_;
RenderFrameHostImpl* render_frame_host_;
WebMenuRunner* menu_runner_;
bool popup_was_hidden_;
diff --git a/chromium/content/browser/frame_host/popup_menu_helper_mac.mm b/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
index 8896a7ca776..85fab55ba45 100644
--- a/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
+++ b/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
@@ -6,7 +6,7 @@
#import "base/mac/scoped_nsobject.h"
#import "base/mac/scoped_sending_event.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#import "base/message_loop/message_pump_mac.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
@@ -15,9 +15,6 @@
#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "content/browser/renderer_host/webmenurunner_mac.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
#import "ui/base/cocoa/base_view.h"
namespace content {
@@ -31,18 +28,14 @@ bool g_allow_showing_popup_menus = true;
PopupMenuHelper::PopupMenuHelper(Delegate* delegate,
RenderFrameHost* render_frame_host)
: delegate_(delegate),
+ observer_(this),
render_frame_host_(static_cast<RenderFrameHostImpl*>(render_frame_host)),
menu_runner_(nil),
popup_was_hidden_(false),
weak_ptr_factory_(this) {
- notification_registrar_.Add(
- this, NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
- Source<RenderWidgetHost>(
- render_frame_host->GetRenderViewHost()->GetWidget()));
- notification_registrar_.Add(
- this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
- Source<RenderWidgetHost>(
- render_frame_host->GetRenderViewHost()->GetWidget()));
+ RenderWidgetHost* widget_host =
+ render_frame_host->GetRenderViewHost()->GetWidget();
+ observer_.Add(widget_host);
}
PopupMenuHelper::~PopupMenuHelper() {
@@ -85,8 +78,7 @@ void PopupMenuHelper::ShowPopupMenu(
{
// Make sure events can be pumped while the menu is up.
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
+ base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
// One of the events that could be pumped is |window.close()|.
// User-initiated event-tracking loops protect against this by
@@ -150,23 +142,16 @@ RenderWidgetHostViewMac* PopupMenuHelper::GetRenderWidgetHostView() const {
->GetView());
}
-void PopupMenuHelper::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK_EQ(Source<RenderWidgetHost>(source).ptr(),
- render_frame_host_->GetRenderViewHost()->GetWidget());
- switch (type) {
- case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: {
- render_frame_host_ = NULL;
- break;
- }
- case NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: {
- bool is_visible = *Details<bool>(details).ptr();
- if (!is_visible)
- Hide();
- break;
- }
- }
+void PopupMenuHelper::RenderWidgetHostVisibilityChanged(
+ RenderWidgetHost* widget_host,
+ bool became_visible) {
+ if (!became_visible)
+ Hide();
+}
+
+void PopupMenuHelper::RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) {
+ render_frame_host_ = nullptr;
+ observer_.Remove(widget_host);
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.cc b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
index 017610ae62c..390bcf09995 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -122,4 +122,8 @@ bool RenderFrameHostDelegate::IsBeingDestroyed() const {
return false;
}
+Visibility RenderFrameHostDelegate::GetVisibility() const {
+ return Visibility::HIDDEN;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.h b/chromium/content/browser/frame_host/render_frame_host_delegate.h
index 297accc301a..cd4a295dfa3 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -17,6 +17,7 @@
#include "content/common/content_export.h"
#include "content/common/frame_message_enums.h"
#include "content/public/browser/site_instance.h"
+#include "content/public/browser/visibility.h"
#include "content/public/common/javascript_dialog_type.h"
#include "content/public/common/media_stream_request.h"
#include "content/public/common/resource_load_info.mojom.h"
@@ -52,6 +53,10 @@ namespace url {
class Origin;
}
+namespace blink {
+struct WebFullscreenOptions;
+}
+
namespace content {
class FrameTreeNode;
class InterstitialPage;
@@ -218,7 +223,9 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// Notification that the frame wants to go into fullscreen mode.
// |origin| represents the origin of the frame that requests fullscreen.
- virtual void EnterFullscreenMode(const GURL& origin) {}
+ virtual void EnterFullscreenMode(const GURL& origin,
+ const blink::WebFullscreenOptions& options) {
+ }
// Notification that the frame wants to go out of fullscreen mode.
// |will_cause_resize| indicates whether the fullscreen change causes a
@@ -349,8 +356,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual void SubresourceResponseStarted(const GURL& url,
net::CertStatus cert_status) {}
- // Notifies that the render finished loading a subresource.
+ // Notifies that the render finished loading a subresource for the frame
+ // associated with |render_frame_host|.
virtual void ResourceLoadComplete(
+ RenderFrameHost* render_frame_host,
mojom::ResourceLoadInfoPtr resource_load_info) {}
// Request to print a frame that is in a different process than its parent.
@@ -363,9 +372,8 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual void UpdatePictureInPictureSurfaceId(const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) {}
- // Updates the Picture-in-Picture controller with a signal that
- // Picture-in-Picture mode has ended.
- virtual void ExitPictureInPicture() {}
+ // Returns the visibility of the delegate.
+ virtual Visibility GetVisibility() const;
protected:
virtual ~RenderFrameHostDelegate() {}
diff --git a/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc b/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc
index e4a6d38b68f..687bd02154e 100644
--- a/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_feature_policy_unittest.cc
@@ -30,7 +30,7 @@ class RenderFrameHostFeaturePolicyTest
static constexpr const char* kOrigin4 = "https://test.com";
static const blink::mojom::FeaturePolicyFeature kDefaultEnabledFeature =
- blink::mojom::FeaturePolicyFeature::kDocumentWrite;
+ blink::mojom::FeaturePolicyFeature::kDocumentStreamInsertion;
static const blink::mojom::FeaturePolicyFeature kDefaultSelfFeature =
blink::mojom::FeaturePolicyFeature::kGeolocation;
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.cc b/chromium/content/browser/frame_host/render_frame_host_impl.cc
index d938013c90b..cd755cbc3f2 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/containers/queue.h"
+#include "base/debug/alias.h"
#include "base/feature_list.h"
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
@@ -22,6 +23,7 @@
#include "base/numerics/safe_conversions.h"
#include "base/process/kill.h"
#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
@@ -30,16 +32,17 @@
#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/dedicated_worker/dedicated_worker_host.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/download/mhtml_generation_manager.h"
#include "content/browser/file_url_loader_factory.h"
+#include "content/browser/fileapi/file_system_url_loader_factory.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/input/input_injector_impl.h"
-#include "content/browser/frame_host/input/legacy_ipc_frame_input_handler.h"
#include "content/browser/frame_host/keep_alive_handle_factory.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
@@ -84,6 +87,7 @@
#include "content/browser/scoped_active_url.h"
#include "content/browser/shared_worker/shared_worker_connector_impl.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
+#include "content/browser/speech/speech_recognition_dispatcher_host.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/webauth/authenticator_impl.h"
#include "content/browser/webauth/scoped_virtual_authenticator_environment.h"
@@ -99,7 +103,6 @@
#include "content/common/frame_messages.h"
#include "content/common/frame_owner_properties.h"
#include "content/common/input/input_handler.mojom.h"
-#include "content/common/input_messages.h"
#include "content/common/inter_process_time_ticks_converter.h"
#include "content/common/navigation_params.h"
#include "content/common/navigation_subresource_loader_params.h"
@@ -108,7 +111,6 @@
#include "content/common/swapped_out_messages.h"
#include "content/common/url_loader_factory_bundle.mojom.h"
#include "content/common/widget.mojom.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
@@ -149,6 +151,7 @@
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/device/public/mojom/wake_lock_context.mojom.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/restricted_cookie_manager.h"
#include "services/resource_coordinator/public/cpp/frame_resource_coordinator.h"
@@ -156,10 +159,10 @@
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "storage/browser/blob/blob_storage_context.h"
-#include "storage/browser/blob/blob_url_loader_factory.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/platform/modules/webauth/virtual_authenticator.mojom.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_id_registry.h"
@@ -515,9 +518,10 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
render_frame_created_(false),
is_waiting_for_beforeunload_ack_(false),
unload_ack_is_for_navigation_(false),
+ beforeunload_timeout_delay_(base::TimeDelta::FromMilliseconds(
+ RenderViewHostImpl::kUnloadTimeoutMS)),
was_discarded_(false),
is_loading_(false),
- pending_commit_(false),
nav_entry_id_(0),
accessibility_reset_token_(0),
accessibility_reset_count_(0),
@@ -535,6 +539,8 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
active_sandbox_flags_(blink::WebSandboxFlags::kNone),
document_scoped_interface_provider_binding_(this),
keep_alive_timeout_(base::TimeDelta::FromSeconds(30)),
+ subframe_unload_timeout_(base::TimeDelta::FromMilliseconds(
+ RenderViewHostImpl::kUnloadTimeoutMS)),
weak_ptr_factory_(this) {
frame_tree_->AddRenderViewHostRef(render_view_host_);
GetProcess()->AddRoute(routing_id_, this);
@@ -631,10 +637,6 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
SetLastCommittedSiteUrl(GURL());
- GetProcess()->RemoveRoute(routing_id_);
- g_routing_id_frame_map.Get().erase(
- RenderFrameHostID(GetProcess()->GetID(), routing_id_));
-
if (overlay_routing_token_)
g_token_frame_map.Get().erase(*overlay_routing_token_);
@@ -658,8 +660,23 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
if (is_active() && render_frame_created_ &&
!will_render_view_clean_up_render_frame) {
Send(new FrameMsg_Delete(routing_id_));
+
+ // If this subframe has an unload handler, ensure that it has a chance to
+ // execute by delaying process cleanup. This will prevent the process from
+ // shutting down immediately in the case where this is the last active
+ // frame in the process. See https://crbug.com/852204.
+ if (!frame_tree_node_->IsMainFrame() &&
+ GetSuddenTerminationDisablerState(blink::kUnloadHandler)) {
+ RenderProcessHostImpl* process =
+ static_cast<RenderProcessHostImpl*>(GetProcess());
+ process->DelayProcessShutdownForUnload(subframe_unload_timeout_);
+ }
}
+ GetProcess()->RemoveRoute(routing_id_);
+ g_routing_id_frame_map.Get().erase(
+ RenderFrameHostID(GetProcess()->GetID(), routing_id_));
+
// Null out the swapout timer; in crash dumps this member will be null only if
// the dtor has run. (It may also be null in tests.)
swapout_event_monitor_timeout_.reset();
@@ -678,6 +695,17 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
frame_tree_->ReleaseRenderViewHostRef(render_view_host_);
ui::AXTreeIDRegistry::GetInstance()->RemoveAXTreeID(ax_tree_id_);
+
+ // If another frame is waiting for a beforeunload ACK from this frame,
+ // simulate it now.
+ RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
+ if (beforeunload_initiator && beforeunload_initiator != this) {
+ base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
+ beforeunload_initiator->ProcessBeforeUnloadACKFromFrame(
+ true /* proceed */, false /* treat_as_final_ack */, this,
+ true /* is_frame_being_destroyed */, approx_renderer_start_time,
+ base::TimeTicks::Now());
+ }
}
int RenderFrameHostImpl::GetRoutingID() {
@@ -737,8 +765,13 @@ const url::Origin& RenderFrameHostImpl::GetLastCommittedOrigin() {
void RenderFrameHostImpl::GetCanonicalUrlForSharing(
mojom::Frame::GetCanonicalUrlForSharingCallback callback) {
- DCHECK(frame_);
- frame_->GetCanonicalUrlForSharing(std::move(callback));
+ // TODO(https://crbug.com/859110): Remove this once frame_ can no longer be
+ // null.
+ if (IsRenderFrameLive()) {
+ frame_->GetCanonicalUrlForSharing(std::move(callback));
+ } else {
+ std::move(callback).Run(base::nullopt);
+ }
}
gfx::NativeView RenderFrameHostImpl::GetNativeView() {
@@ -983,7 +1016,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnAccessibilityChildFrameHitTestResult)
IPC_MESSAGE_HANDLER(AccessibilityHostMsg_SnapshotResponse,
OnAccessibilitySnapshotResponse)
- IPC_MESSAGE_HANDLER(FrameHostMsg_ToggleFullscreen, OnToggleFullscreen)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_EnterFullscreen, OnEnterFullscreen)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_ExitFullscreen, OnExitFullscreen)
IPC_MESSAGE_HANDLER(FrameHostMsg_SuddenTerminationDisablerChanged,
OnSuddenTerminationDisablerChanged)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading)
@@ -1000,6 +1034,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnSetHasReceivedUserGestureBeforeNavigation)
IPC_MESSAGE_HANDLER(FrameHostMsg_ScrollRectToVisibleInParentFrame,
OnScrollRectToVisibleInParentFrame)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_BubbleLogicalScrollInParentFrame,
+ OnBubbleLogicalScrollInParentFrame)
IPC_MESSAGE_HANDLER(FrameHostMsg_FrameDidCallFocus, OnFrameDidCallFocus)
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
@@ -1008,8 +1044,6 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(FrameHostMsg_RequestOverlayRoutingToken,
OnRequestOverlayRoutingToken)
IPC_MESSAGE_HANDLER(FrameHostMsg_ShowCreatedWindow, OnShowCreatedWindow)
- IPC_MESSAGE_HANDLER(FrameHostMsg_StreamHandleConsumed,
- OnStreamHandleConsumed)
IPC_END_MESSAGE_MAP()
// No further actions here, since we may have been deleted.
@@ -1115,11 +1149,6 @@ void RenderFrameHostImpl::RenderProcessGone(SiteInstanceImpl* site_instance) {
GetNavigationHandle()->set_net_error_code(net::ERR_ABORTED);
ResetLoadingState();
- // The renderer process is gone, so the |stream_handle_| will no longer be
- // used. It can be released.
- // TODO(clamy): Remove this when we switch to Mojo streams.
- stream_handle_.reset();
-
// Any future UpdateState or UpdateTitle messages from this or a recreated
// process should be ignored until the next commit.
set_nav_entry_id(0);
@@ -1186,8 +1215,6 @@ bool RenderFrameHostImpl::SchemeShouldBypassCSP(
}
mojom::FrameInputHandler* RenderFrameHostImpl::GetFrameInputHandler() {
- if (legacy_frame_input_handler_)
- return legacy_frame_input_handler_.get();
return frame_input_handler_.get();
}
@@ -1473,6 +1500,23 @@ void RenderFrameHostImpl::OnFrameFocused() {
void RenderFrameHostImpl::OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
GURL validated_url(params.url);
GetProcess()->FilterURL(false, &validated_url);
+
+ mojo::ScopedMessagePipeHandle blob_url_token_handle(params.blob_url_token);
+ blink::mojom::BlobURLTokenPtr blob_url_token(
+ blink::mojom::BlobURLTokenPtrInfo(std::move(blob_url_token_handle),
+ blink::mojom::BlobURLToken::Version_));
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
+ if (blob_url_token) {
+ if (!params.url.SchemeIsBlob()) {
+ bad_message::ReceivedBadMessage(
+ GetProcess(), bad_message::RFH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL);
+ return;
+ }
+ blob_url_loader_factory =
+ ChromeBlobStorageContext::URLLoaderFactoryForToken(
+ GetSiteInstance()->GetBrowserContext(), std::move(blob_url_token));
+ }
+
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRequestBody(
GetSiteInstance(), params.resource_request_body)) {
bad_message::ReceivedBadMessage(GetProcess(),
@@ -1484,9 +1528,10 @@ void RenderFrameHostImpl::OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
// Try to find a FrameNavigationEntry that matches this frame instead, based
// on the frame's unique name. If this can't be found, fall back to the
// default params using RequestOpenURL below.
- if (frame_tree_node_->navigator()->NavigateNewChildFrame(this,
- validated_url))
+ if (frame_tree_node_->navigator()->StartHistoryNavigationInNewSubframe(
+ this, validated_url)) {
return;
+ }
}
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url",
@@ -1496,7 +1541,7 @@ void RenderFrameHostImpl::OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
this, validated_url, params.uses_post, params.resource_request_body,
params.extra_headers, params.referrer, params.disposition,
params.should_replace_current_entry, params.user_gesture,
- params.triggering_event_info, params.suggested_filename);
+ params.triggering_event_info, std::move(blob_url_loader_factory));
}
void RenderFrameHostImpl::CancelInitialHistoryLoad() {
@@ -1610,7 +1655,8 @@ void RenderFrameHostImpl::DidCommitProvisionalLoad(
if (is_waiting_for_beforeunload_ack_ && unload_ack_is_for_navigation_ &&
!GetParent()) {
base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
- OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now());
+ ProcessBeforeUnloadACK(true /* proceed */, true /* treat_as_final_ack */,
+ approx_renderer_start_time, base::TimeTicks::Now());
}
// If we're waiting for an unload ack from this frame and we receive a commit
@@ -1822,6 +1868,16 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
bool proceed,
const base::TimeTicks& renderer_before_unload_start_time,
const base::TimeTicks& renderer_before_unload_end_time) {
+ ProcessBeforeUnloadACK(proceed, false /* treat_as_final_ack */,
+ renderer_before_unload_start_time,
+ renderer_before_unload_end_time);
+}
+
+void RenderFrameHostImpl::ProcessBeforeUnloadACK(
+ bool proceed,
+ bool treat_as_final_ack,
+ const base::TimeTicks& renderer_before_unload_start_time,
+ const base::TimeTicks& renderer_before_unload_end_time) {
TRACE_EVENT_ASYNC_END1("navigation", "RenderFrameHostImpl BeforeUnload", this,
"FrameTreeNode id",
frame_tree_node_->frame_tree_node_id());
@@ -1833,9 +1889,45 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
// happen when pending cross-site navigation is canceled by a second one just
// before DidCommitProvisionalLoad while current RVH is waiting for commit
// but second navigation is started from the beginning.
- if (!is_waiting_for_beforeunload_ack_) {
+ RenderFrameHostImpl* initiator = GetBeforeUnloadInitiator();
+ if (!initiator)
return;
+
+ // Continue processing the ACK in the frame that triggered beforeunload in
+ // this frame. This could be either this frame itself or an ancestor frame.
+ initiator->ProcessBeforeUnloadACKFromFrame(
+ proceed, treat_as_final_ack, this, false /* is_frame_being_destroyed */,
+ renderer_before_unload_start_time, renderer_before_unload_end_time);
+}
+
+RenderFrameHostImpl* RenderFrameHostImpl::GetBeforeUnloadInitiator() {
+ for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
+ if (frame->is_waiting_for_beforeunload_ack_)
+ return frame;
}
+ return nullptr;
+}
+
+void RenderFrameHostImpl::ProcessBeforeUnloadACKFromFrame(
+ bool proceed,
+ bool treat_as_final_ack,
+ RenderFrameHostImpl* frame,
+ bool is_frame_being_destroyed,
+ const base::TimeTicks& renderer_before_unload_start_time,
+ const base::TimeTicks& renderer_before_unload_end_time) {
+ // Check if we need to wait for more beforeunload ACKs. If |proceed| is
+ // false, we know the navigation or window close will be aborted, so we don't
+ // need to wait for beforeunload ACKs from any other frames.
+ // |treat_as_final_ack| also indicates that we shouldn't wait for any other
+ // ACKs (e.g., when a beforeunload timeout fires).
+ if (!proceed || treat_as_final_ack) {
+ beforeunload_pending_replies_.clear();
+ } else {
+ beforeunload_pending_replies_.erase(frame);
+ if (!beforeunload_pending_replies_.empty())
+ return;
+ }
+
DCHECK(!send_before_unload_start_time_.is_null());
// Sets a default value for before_unload_end_time so that the browser
@@ -1871,8 +1963,10 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
frame_tree_node_->navigator()->LogBeforeUnloadTime(
renderer_before_unload_start_time, renderer_before_unload_end_time);
}
+
// Resets beforeunload waiting state.
is_waiting_for_beforeunload_ack_ = false;
+ has_shown_beforeunload_dialog_ = false;
if (beforeunload_timeout_)
beforeunload_timeout_->Stop();
send_before_unload_start_time_ = base::TimeTicks();
@@ -1884,8 +1978,25 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
frame_tree_node_->navigator()->OnBeforeUnloadACK(frame_tree_node_, proceed,
before_unload_end_time);
} else {
- frame_tree_node_->render_manager()->OnBeforeUnloadACK(
- proceed, before_unload_end_time);
+ // We could reach this from a subframe destructor for |frame| while we're
+ // in the middle of closing the current tab. In that case, dispatch the
+ // ACK to prevent re-entrancy and a potential nested attempt to free the
+ // current frame. See https://crbug.com/866382.
+ base::OnceClosure task = base::BindOnce(
+ [](base::WeakPtr<RenderFrameHostImpl> self,
+ const base::TimeTicks& before_unload_end_time, bool proceed) {
+ if (!self)
+ return;
+ self->frame_tree_node()->render_manager()->OnBeforeUnloadACK(
+ proceed, before_unload_end_time);
+ },
+ weak_ptr_factory_.GetWeakPtr(), before_unload_end_time, proceed);
+ if (is_frame_being_destroyed) {
+ DCHECK(proceed);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
+ } else {
+ std::move(task).Run();
+ }
}
// If canceled, notify the delegate to cancel its pending navigation entry.
@@ -1923,6 +2034,7 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
SetRenderFrameCreated(false);
InvalidateMojoConnection();
document_scoped_interface_provider_binding_.Close();
+ SetLastCommittedUrl(GURL());
// Execute any pending AX tree snapshot callbacks with an empty response,
// since we're never going to get a response from this renderer.
@@ -1934,7 +2046,8 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
for (base::IDMap<std::unique_ptr<ExtractSmartClipDataCallback>>::iterator
iter(&smart_clip_callbacks_);
!iter.IsAtEnd(); iter.Advance()) {
- std::move(*iter.GetCurrentValue()).Run(base::string16(), base::string16());
+ std::move(*iter.GetCurrentValue())
+ .Run(base::string16(), base::string16(), gfx::Rect());
}
smart_clip_callbacks_.Clear();
#endif // defined(OS_ANDROID)
@@ -1994,6 +2107,11 @@ void RenderFrameHostImpl::DisableSwapOutTimerForTesting() {
swapout_event_monitor_timeout_.reset();
}
+void RenderFrameHostImpl::SetSubframeUnloadTimeoutForTesting(
+ const base::TimeDelta& timeout) {
+ subframe_unload_timeout_ = timeout;
+}
+
void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
if (!is_active())
return;
@@ -2059,8 +2177,10 @@ void RenderFrameHostImpl::RequestSmartClipExtract(
void RenderFrameHostImpl::OnSmartClipDataExtracted(int32_t callback_id,
const base::string16& text,
- const base::string16& html) {
- std::move(*smart_clip_callbacks_.Lookup(callback_id)).Run(text, html);
+ const base::string16& html,
+ const gfx::Rect& clip_rect) {
+ std::move(*smart_clip_callbacks_.Lookup(callback_id))
+ .Run(text, html, clip_rect);
smart_clip_callbacks_.Remove(callback_id);
}
#endif // defined(OS_ANDROID)
@@ -2111,6 +2231,30 @@ void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnRunBeforeUnloadConfirm",
"frame_tree_node", frame_tree_node_->frame_tree_node_id());
+ // Allow at most one attempt to show a beforeunload dialog per navigation.
+ RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
+ if (beforeunload_initiator) {
+ if (beforeunload_initiator->has_shown_beforeunload_dialog_) {
+ // TODO(alexmos): Pass enough data back to renderer to record histograms
+ // for Document.BeforeUnloadDialog and add the intervention console
+ // message to match renderer-side behavior in
+ // Document::DispatchBeforeUnloadEvent().
+ SendJavaScriptDialogReply(reply_msg, true /* success */,
+ base::string16());
+ return;
+ }
+ beforeunload_initiator->has_shown_beforeunload_dialog_ = true;
+ } else {
+ // TODO(alexmos): If a renderer-initiated beforeunload shows a dialog, it
+ // won't find a |beforeunload_initiator|. This can happen for a
+ // renderer-initiated navigation or window.close(). We should ensure that
+ // when the browser process later kicks off subframe unload handlers (if
+ // any), they won't be able to show additional dialogs. However, we can't
+ // just set |has_shown_beforeunload_dialog_| because we don't know which
+ // frame is navigating/closing here. Plumb enough information here to fix
+ // this.
+ }
+
// While a JS beforeunload dialog is showing, tabs in the same process
// shouldn't process input events.
GetProcess()->SetIgnoreInputEvents(true);
@@ -2215,26 +2359,6 @@ int RenderFrameHostImpl::GetEnabledBindings() const {
return enabled_bindings_;
}
-void RenderFrameHostImpl::BlockRequestsForFrame() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NotifyForEachFrameFromUI(
- this,
- base::BindRepeating(&ResourceDispatcherHostImpl::BlockRequestsForRoute));
-}
-
-void RenderFrameHostImpl::ResumeBlockedRequestsForFrame() {
- NotifyForEachFrameFromUI(
- this, base::BindRepeating(
- &ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
-}
-
-void RenderFrameHostImpl::CancelBlockedRequestsForFrame() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NotifyForEachFrameFromUI(
- this, base::BindRepeating(
- &ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute));
-}
-
void RenderFrameHostImpl::DisableBeforeUnloadHangMonitorForTesting() {
beforeunload_timeout_.reset();
}
@@ -2409,18 +2533,6 @@ void RenderFrameHostImpl::FrameSizeChanged(const gfx::Size& frame_size) {
frame_size_ = frame_size;
}
-void RenderFrameHostImpl::OnUpdatePictureInPictureSurfaceId(
- const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size) {
- if (delegate_)
- delegate_->UpdatePictureInPictureSurfaceId(surface_id, natural_size);
-}
-
-void RenderFrameHostImpl::OnExitPictureInPicture() {
- if (delegate_)
- delegate_->ExitPictureInPicture();
-}
-
void RenderFrameHostImpl::OnDidBlockFramebust(const GURL& url) {
delegate_->OnDidBlockFramebust(url);
}
@@ -2674,7 +2786,8 @@ void RenderFrameHostImpl::OnAccessibilitySnapshotResponse(
// TODO(alexmos): When the allowFullscreen flag is known in the browser
// process, use it to double-check that fullscreen can be entered here.
-void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
+void RenderFrameHostImpl::OnEnterFullscreen(
+ const blink::WebFullscreenOptions& options) {
// Entering fullscreen from a cross-process subframe also affects all
// renderers for ancestor frames, which will need to apply fullscreen CSS to
// appropriate ancestor <iframe> elements, fire fullscreenchange events, etc.
@@ -2686,29 +2799,24 @@ void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
// A-B-A-B hierarchy, if the bottom frame goes fullscreen, this only needs to
// notify its parent, and Blink-side logic will take care of applying
// necessary changes to the other two ancestors.
- if (enter_fullscreen) {
- std::set<SiteInstance*> notified_instances;
- notified_instances.insert(GetSiteInstance());
- for (FrameTreeNode* node = frame_tree_node_; node->parent();
- node = node->parent()) {
- SiteInstance* parent_site_instance =
- node->parent()->current_frame_host()->GetSiteInstance();
- if (ContainsKey(notified_instances, parent_site_instance))
- continue;
-
- RenderFrameProxyHost* child_proxy =
- node->render_manager()->GetRenderFrameProxyHost(parent_site_instance);
- child_proxy->Send(
- new FrameMsg_WillEnterFullscreen(child_proxy->GetRoutingID()));
- notified_instances.insert(parent_site_instance);
- }
+ std::set<SiteInstance*> notified_instances;
+ notified_instances.insert(GetSiteInstance());
+ for (FrameTreeNode* node = frame_tree_node_; node->parent();
+ node = node->parent()) {
+ SiteInstance* parent_site_instance =
+ node->parent()->current_frame_host()->GetSiteInstance();
+ if (ContainsKey(notified_instances, parent_site_instance))
+ continue;
+
+ RenderFrameProxyHost* child_proxy =
+ node->render_manager()->GetRenderFrameProxyHost(parent_site_instance);
+ child_proxy->Send(
+ new FrameMsg_WillEnterFullscreen(child_proxy->GetRoutingID()));
+ notified_instances.insert(parent_site_instance);
}
// TODO(alexmos): See if this can use the last committed origin instead.
- if (enter_fullscreen)
- delegate_->EnterFullscreenMode(GetLastCommittedURL().GetOrigin());
- else
- delegate_->ExitFullscreenMode(/* will_cause_resize */ true);
+ delegate_->EnterFullscreenMode(GetLastCommittedURL().GetOrigin(), options);
// The previous call might change the fullscreen state. We need to make sure
// the renderer is aware of that, which is done via the resize message.
@@ -2718,7 +2826,23 @@ void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
// sent in that case. We always send this to the main frame's widget, and if
// there are any OOPIF widgets, this will also trigger them to resize via
// frameRectsChanged.
- render_view_host_->GetWidget()->WasResized();
+ render_view_host_->GetWidget()->SynchronizeVisualProperties();
+}
+
+// TODO(alexmos): When the allowFullscreen flag is known in the browser
+// process, use it to double-check that fullscreen can be entered here.
+void RenderFrameHostImpl::OnExitFullscreen() {
+ delegate_->ExitFullscreenMode(/* will_cause_resize */ true);
+
+ // The previous call might change the fullscreen state. We need to make sure
+ // the renderer is aware of that, which is done via the resize message.
+ // Typically, this will be sent as part of the call on the |delegate_| above
+ // when resizing the native windows, but sometimes fullscreen can be entered
+ // without causing a resize, so we need to ensure that the resize message is
+ // sent in that case. We always send this to the main frame's widget, and if
+ // there are any OOPIF widgets, this will also trigger them to resize via
+ // frameRectsChanged.
+ render_view_host_->GetWidget()->SynchronizeVisualProperties();
}
// TODO(clamy): Remove this IPC now that it is only used for same-document
@@ -2840,6 +2964,25 @@ void RenderFrameHostImpl::OnScrollRectToVisibleInParentFrame(
proxy->ScrollRectToVisible(rect_to_scroll, params);
}
+void RenderFrameHostImpl::OnBubbleLogicalScrollInParentFrame(
+ blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity) {
+ if (!is_active())
+ return;
+
+ RenderFrameProxyHost* proxy =
+ frame_tree_node()->render_manager()->GetProxyToParent();
+ if (!proxy) {
+ // Only frames with an out-of-process parent frame should be sending this
+ // message.
+ bad_message::ReceivedBadMessage(GetProcess(),
+ bad_message::RFH_NO_PROXY_TO_PARENT);
+ return;
+ }
+
+ proxy->BubbleLogicalScroll(direction, granularity);
+}
+
void RenderFrameHostImpl::OnFrameDidCallFocus() {
delegate_->DidCallFocus();
}
@@ -2961,10 +3104,11 @@ void RenderFrameHostImpl::CreateNewWindow(
scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace;
if (base::FeatureList::IsEnabled(features::kMojoSessionStorage)) {
- // Any cloning should have already happened using the mojo
+ // Any cloning should / will happen using the
// SessionStorageNamespace::Clone in storage_partition_service.mojom.
- cloned_namespace = SessionStorageNamespaceImpl::Create(
- dom_storage_context, params->session_storage_namespace_id);
+ cloned_namespace = SessionStorageNamespaceImpl::CloneFrom(
+ dom_storage_context, params->session_storage_namespace_id,
+ params->clone_from_session_storage_namespace_id);
} else {
cloned_namespace = SessionStorageNamespaceImpl::CloneFrom(
dom_storage_context, params->session_storage_namespace_id,
@@ -3130,7 +3274,7 @@ void RenderFrameHostImpl::SubresourceResponseStarted(
void RenderFrameHostImpl::ResourceLoadComplete(
mojom::ResourceLoadInfoPtr resource_load_info) {
- delegate_->ResourceLoadComplete(std::move(resource_load_info));
+ delegate_->ResourceLoadComplete(this, std::move(resource_load_info));
}
namespace {
@@ -3223,30 +3367,29 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
registry_->AddInterface(base::BindRepeating(
&RenderFrameHostImpl::CreateWebSocket, base::Unretained(this)));
+ registry_->AddInterface(base::BindRepeating(
+ &RenderFrameHostImpl::CreateDedicatedWorkerHostFactory,
+ base::Unretained(this)));
+
registry_->AddInterface(base::Bind(&SharedWorkerConnectorImpl::Create,
process_->GetID(), routing_id_));
registry_->AddInterface<device::mojom::VRService>(base::Bind(
&WebvrServiceProvider::BindWebvrService, base::Unretained(this)));
- if (RenderFrameAudioInputStreamFactory::UseMojoFactories()) {
- registry_->AddInterface(
- base::BindRepeating(&RenderFrameHostImpl::CreateAudioInputStreamFactory,
- base::Unretained(this)));
- }
+ registry_->AddInterface(
+ base::BindRepeating(&RenderFrameHostImpl::CreateAudioInputStreamFactory,
+ base::Unretained(this)));
- if (RendererAudioOutputStreamFactoryContextImpl::UseMojoFactories()) {
- registry_->AddInterface(base::BindRepeating(
- &RenderFrameHostImpl::CreateAudioOutputStreamFactory,
- base::Unretained(this)));
- }
+ registry_->AddInterface(
+ base::BindRepeating(&RenderFrameHostImpl::CreateAudioOutputStreamFactory,
+ base::Unretained(this)));
if (resource_coordinator::IsResourceCoordinatorEnabled()) {
registry_->AddInterface(
base::Bind(&CreateFrameResourceCoordinator, base::Unretained(this)));
}
-#if BUILDFLAG(ENABLE_WEBRTC)
// BrowserMainLoop::GetInstance() may be null on unit tests.
if (BrowserMainLoop::GetInstance()) {
// BrowserMainLoop, which owns MediaStreamManager, is alive for the lifetime
@@ -3267,7 +3410,6 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
base::Unretained(this), base::Unretained(media_stream_manager)),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
}
-#endif
#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
registry_->AddInterface(base::Bind(&RemoterFactoryImpl::Bind,
@@ -3325,6 +3467,14 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
registry_->AddInterface(base::BindRepeating(
&QuotaDispatcherHost::CreateForFrame, GetProcess(), routing_id_));
+ registry_->AddInterface(
+ base::BindRepeating(
+ SpeechRecognitionDispatcherHost::Create, GetProcess()->GetID(),
+ routing_id_,
+ base::WrapRefCounted(
+ GetProcess()->GetStoragePartition()->GetURLRequestContext())),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
StoragePartitionImpl* storage_partition =
static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
@@ -3353,6 +3503,8 @@ void RenderFrameHostImpl::ResetWaitingState() {
is_waiting_for_beforeunload_ack_ = false;
if (beforeunload_timeout_)
beforeunload_timeout_->Stop();
+ has_shown_beforeunload_dialog_ = false;
+ beforeunload_pending_replies_.clear();
}
send_before_unload_start_time_ = base::TimeTicks();
render_view_host_->is_waiting_for_close_ack_ = false;
@@ -3407,11 +3559,11 @@ void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
base::Optional<SourceLocation>(),
CSPDisposition::CHECK /* should_check_main_world_csp */,
false /* started_from_context_menu */, false /* has_user_gesture */,
- base::nullopt /* suggested_filename */);
+ std::vector<ContentSecurityPolicy>() /* initiator_csp */,
+ CSPSource() /* initiator_self_source */);
CommitNavigation(nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
- std::unique_ptr<StreamHandle>(), common_params,
- RequestNavigationParams(), false, base::nullopt,
- base::nullopt /* subresource_overrides */,
+ common_params, RequestNavigationParams(), false,
+ base::nullopt, base::nullopt /* subresource_overrides */,
base::UnguessableToken::Create() /* not traced */);
}
@@ -3421,10 +3573,17 @@ void RenderFrameHostImpl::Stop() {
Send(new FrameMsg_Stop(routing_id_));
}
-void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation,
+void RenderFrameHostImpl::DispatchBeforeUnload(BeforeUnloadType type,
bool is_reload) {
+ bool for_navigation =
+ type == BeforeUnloadType::BROWSER_INITIATED_NAVIGATION ||
+ type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION;
DCHECK(for_navigation || !is_reload);
+ // Tab close should only dispatch beforeunload on main frames.
+ DCHECK(type != BeforeUnloadType::TAB_CLOSE ||
+ frame_tree_node_->IsMainFrame());
+
if (!for_navigation) {
// Cancel any pending navigations, to avoid their navigation commit/fail
// event from wiping out the is_waiting_for_beforeunload_ack_ state.
@@ -3437,12 +3596,27 @@ void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation,
frame_tree_node_->ResetNavigationRequest(false, true);
}
- // TODO(creis): Support beforeunload on subframes. For now just pretend that
- // the handler ran and allowed the navigation to proceed.
- if (!ShouldDispatchBeforeUnload()) {
+ // In renderer-initiated navigations, don't check for beforeunload in the
+ // navigating frame, as it has already run beforeunload before it sent the
+ // BeginNavigation IPC.
+ bool check_subframes_only =
+ type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION;
+ if (!ShouldDispatchBeforeUnload(check_subframes_only)) {
+ // When running beforeunload for navigations, ShouldDispatchBeforeUnload()
+ // is checked earlier and we would only get here if it had already returned
+ // true.
DCHECK(!for_navigation);
- frame_tree_node_->render_manager()->OnBeforeUnloadACK(
- true, base::TimeTicks::Now());
+
+ // Dispatch the ACK to prevent re-entrancy.
+ base::OnceClosure task = base::BindOnce(
+ [](base::WeakPtr<RenderFrameHostImpl> self) {
+ if (!self)
+ return;
+ self->frame_tree_node_->render_manager()->OnBeforeUnloadACK(
+ true, base::TimeTicks::Now());
+ },
+ weak_ptr_factory_.GetWeakPtr());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
return;
}
TRACE_EVENT_ASYNC_BEGIN1("navigation", "RenderFrameHostImpl BeforeUnload",
@@ -3472,23 +3646,126 @@ void RenderFrameHostImpl::DispatchBeforeUnload(bool for_navigation,
// reply from the dialog.
SimulateBeforeUnloadAck();
} else {
- if (beforeunload_timeout_) {
- beforeunload_timeout_->Start(
- TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS));
+ // Start a timer that will be shared by all frames that need to run
+ // beforeunload in the current frame's subtree.
+ if (beforeunload_timeout_)
+ beforeunload_timeout_->Start(beforeunload_timeout_delay_);
+
+ beforeunload_pending_replies_.clear();
+
+ // Run beforeunload in this frame and its cross-process descendant
+ // frames, in parallel.
+ CheckOrDispatchBeforeUnloadForSubtree(check_subframes_only,
+ true /* send_ipc */, is_reload);
+ }
+ }
+}
+
+bool RenderFrameHostImpl::CheckOrDispatchBeforeUnloadForSubtree(
+ bool subframes_only,
+ bool send_ipc,
+ bool is_reload) {
+ bool found_beforeunload = false;
+ for (FrameTreeNode* node :
+ frame_tree_node_->frame_tree()->SubtreeNodes(frame_tree_node_)) {
+ RenderFrameHostImpl* rfh = node->current_frame_host();
+
+ // If |subframes_only| is true, skip this frame and its same-site
+ // descendants. This happens for renderer-initiated navigations, where
+ // these frames have already run beforeunload.
+ if (subframes_only && rfh->GetSiteInstance() == GetSiteInstance())
+ continue;
+
+ // No need to run beforeunload if the RenderFrame isn't live.
+ if (!rfh->IsRenderFrameLive())
+ continue;
+
+ // Only run beforeunload in frames that have registered a beforeunload
+ // handler.
+ bool should_run_beforeunload =
+ rfh->GetSuddenTerminationDisablerState(blink::kBeforeUnloadHandler);
+ // TODO(alexmos): Many tests, as well as some DevTools cases, currently
+ // assume that beforeunload for a navigating/closing frame is always sent
+ // to the renderer. For now, keep this assumption by checking |rfh ==
+ // this|. In the future, this condition should be removed, and beforeunload
+ // should only be sent when a handler is registered. For subframes of a
+ // navigating/closing frame, this assumption was never present, so
+ // subframes are included only if they have registered a beforeunload
+ // handler.
+ if (rfh == this)
+ should_run_beforeunload = true;
+
+ if (!should_run_beforeunload)
+ continue;
+
+ // If we're only checking whether there's at least one frame with
+ // beforeunload, then we've just found one, so we can return now.
+ found_beforeunload = true;
+ if (!send_ipc)
+ return true;
+
+ // Otherwise, figure out whether we need to send the IPC, or whether this
+ // beforeunload was already triggered by an ancestor frame's IPC.
+
+ // Only send beforeunload to local roots, and let Blink handle any
+ // same-site frames under them. That is, if a frame has a beforeunload
+ // handler, ask its local root to run it. If we've already sent the message
+ // to that local root, skip this frame. For example, in A1(A2,A3), if A2
+ // and A3 contain beforeunload handlers, and all three frames are
+ // same-site, we ask A1 to run beforeunload for all three frames, and only
+ // ask it once.
+ while (!rfh->is_local_root() && rfh != this)
+ rfh = rfh->GetParent();
+ if (base::ContainsKey(beforeunload_pending_replies_, rfh))
+ continue;
+
+ // For a case like A(B(A)), it's not necessary to send an IPC for the
+ // innermost frame, as Blink will walk all same-site (local)
+ // descendants. Detect cases like this and skip them.
+ bool has_same_site_ancestor = false;
+ for (auto* added_rfh : beforeunload_pending_replies_) {
+ if (rfh->frame_tree_node()->IsDescendantOf(
+ added_rfh->frame_tree_node()) &&
+ rfh->GetSiteInstance() == added_rfh->GetSiteInstance()) {
+ has_same_site_ancestor = true;
+ break;
}
- Send(new FrameMsg_BeforeUnload(routing_id_, is_reload));
}
+ if (has_same_site_ancestor)
+ continue;
+
+ // Add |rfh| to the list of frames that need to receive beforeunload
+ // ACKs.
+ beforeunload_pending_replies_.insert(rfh);
+
+ rfh->Send(new FrameMsg_BeforeUnload(rfh->GetRoutingID(), is_reload));
}
+
+ return found_beforeunload;
}
void RenderFrameHostImpl::SimulateBeforeUnloadAck() {
DCHECK(is_waiting_for_beforeunload_ack_);
base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
- OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now());
+
+ // Dispatch the ACK to prevent re-entrancy.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RenderFrameHostImpl::ProcessBeforeUnloadACK,
+ weak_ptr_factory_.GetWeakPtr(), true /* proceed */,
+ true /* treat_as_final_ack */, approx_renderer_start_time,
+ base::TimeTicks::Now()));
}
-bool RenderFrameHostImpl::ShouldDispatchBeforeUnload() {
- return IsRenderFrameLive();
+bool RenderFrameHostImpl::ShouldDispatchBeforeUnload(
+ bool check_subframes_only) {
+ return CheckOrDispatchBeforeUnloadForSubtree(
+ check_subframes_only, false /* send_ipc */, false /* is_reload */);
+}
+
+void RenderFrameHostImpl::SetBeforeUnloadTimeoutDelayForTesting(
+ const base::TimeDelta& timeout) {
+ beforeunload_timeout_delay_ = timeout;
}
void RenderFrameHostImpl::UpdateOpener() {
@@ -3537,8 +3814,7 @@ void RenderFrameHostImpl::JavaScriptDialogClosed(
for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
if (frame->is_waiting_for_beforeunload_ack_ &&
frame->beforeunload_timeout_) {
- frame->beforeunload_timeout_->Start(
- TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS));
+ frame->beforeunload_timeout_->Start(beforeunload_timeout_delay_);
}
}
}
@@ -3555,7 +3831,6 @@ void RenderFrameHostImpl::SendJavaScriptDialogReply(
void RenderFrameHostImpl::CommitNavigation(
network::ResourceResponse* response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- std::unique_ptr<StreamHandle> body,
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
bool is_view_source,
@@ -3568,7 +3843,7 @@ void RenderFrameHostImpl::CommitNavigation(
common_params.url.possibly_invalid_spec());
DCHECK(!IsRendererDebugURL(common_params.url));
DCHECK(
- (response && (url_loader_client_endpoints || body)) ||
+ (response && url_loader_client_endpoints) ||
common_params.url.SchemeIs(url::kDataScheme) ||
FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type) ||
!IsURLHandledByNetworkStack(common_params.url));
@@ -3589,7 +3864,6 @@ void RenderFrameHostImpl::CommitNavigation(
render_view_host()->Send(new FrameMsg_EnableViewSourceMode(routing_id_));
}
- const GURL body_url = body.get() ? body->GetURL() : GURL();
const network::ResourceResponseHead head =
response ? response->head : network::ResourceResponseHead();
const bool is_same_document =
@@ -3600,6 +3874,7 @@ void RenderFrameHostImpl::CommitNavigation(
(!is_same_document || is_first_navigation)) {
subresource_loader_factories =
std::make_unique<URLLoaderFactoryBundleInfo>();
+ BrowserContext* browser_context = GetSiteInstance()->GetBrowserContext();
// NOTE: On Network Service navigations, we want to ensure that a frame is
// given everything it will need to load any accessible subresources. We
// however only do this for cross-document navigations, because the
@@ -3607,7 +3882,7 @@ void RenderFrameHostImpl::CommitNavigation(
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
StoragePartitionImpl* storage_partition =
static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
- GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
+ browser_context, GetSiteInstance()));
if (subresource_loader_params &&
subresource_loader_params->loader_factory_info.is_valid()) {
// If the caller has supplied a default URLLoaderFactory override (for
@@ -3655,7 +3930,7 @@ void RenderFrameHostImpl::CommitNavigation(
if (common_params.url.SchemeIsFile()) {
// Only file resources can load file subresources
auto file_factory = std::make_unique<FileURLLoaderFactory>(
- GetProcess()->GetBrowserContext()->GetPath(),
+ browser_context->GetPath(),
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
@@ -3663,10 +3938,26 @@ void RenderFrameHostImpl::CommitNavigation(
std::move(file_factory));
}
+ StoragePartition* partition =
+ BrowserContext::GetStoragePartition(browser_context, GetSiteInstance());
+ std::string storage_domain;
+ if (site_instance_) {
+ std::string partition_name;
+ bool in_memory;
+ GetContentClient()->browser()->GetStoragePartitionConfigForSite(
+ browser_context, site_instance_->GetSiteURL(), true, &storage_domain,
+ &partition_name, &in_memory);
+ }
+ non_network_url_loader_factories_.emplace(
+ url::kFileSystemScheme,
+ content::CreateFileSystemURLLoaderFactory(
+ this, /*is_navigation=*/false, partition->GetFileSystemContext(),
+ storage_domain));
+
GetContentClient()
->browser()
->RegisterNonNetworkSubresourceURLLoaderFactories(
- this, common_params.url, &non_network_url_loader_factories_);
+ process_->GetID(), routing_id_, &non_network_url_loader_factories_);
for (auto& factory : non_network_url_loader_factories_) {
network::mojom::URLLoaderFactoryPtrInfo factory_proxy_info;
@@ -3675,20 +3966,14 @@ void RenderFrameHostImpl::CommitNavigation(
this, false /* is_navigation */, &factory_request);
// Keep DevTools proxy lasy, i.e. closest to the network.
RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
- this, false, &factory_request);
+ this, false /* is_navigation */, false /* is_download */,
+ &factory_request);
factory.second->Clone(std::move(factory_request));
subresource_loader_factories->factories_info().emplace(
factory.first, std::move(factory_proxy_info));
}
}
- // Pass the controller service worker info if we have one.
- mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info;
- if (subresource_loader_params) {
- controller_service_worker_info =
- std::move(subresource_loader_params->controller_service_worker_info);
- }
-
// It is imperative that cross-document navigations always provide a set of
// subresource ULFs when the Network Service is enabled.
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
@@ -3705,22 +3990,44 @@ void RenderFrameHostImpl::CommitNavigation(
->GetNavigationId(),
common_params.should_replace_current_entry));
} else {
+ // Pass the controller service worker info if we have one.
+ mojom::ControllerServiceWorkerInfoPtr controller;
+ blink::mojom::ServiceWorkerObjectAssociatedPtrInfo remote_object;
+ blink::mojom::ServiceWorkerState sent_state;
+ if (subresource_loader_params &&
+ subresource_loader_params->controller_service_worker_info) {
+ controller =
+ std::move(subresource_loader_params->controller_service_worker_info);
+ if (controller->object_info) {
+ controller->object_info->request = mojo::MakeRequest(&remote_object);
+ sent_state = controller->object_info->state;
+ }
+ }
+
GetNavigationControl()->CommitNavigation(
- head, body_url, common_params, request_params,
+ head, common_params, request_params,
std::move(url_loader_client_endpoints),
std::move(subresource_loader_factories),
- std::move(subresource_overrides),
- std::move(controller_service_worker_info), devtools_navigation_token);
+ std::move(subresource_overrides), std::move(controller),
+ devtools_navigation_token);
+
+ // |remote_object| is an associated interface ptr, so calls can't be made on
+ // it until its request endpoint is sent. Now that the request endpoint was
+ // sent, it can be used, so add it to ServiceWorkerHandle.
+ if (remote_object.is_valid()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &ServiceWorkerHandle::AddRemoteObjectPtrAndUpdateState,
+ subresource_loader_params->controller_service_worker_handle,
+ std::move(remote_object), sent_state));
+ }
// If a network request was made, update the Previews state.
if (IsURLHandledByNetworkStack(common_params.url))
last_navigation_previews_state_ = common_params.previews_state;
-
- // Released in OnStreamHandleConsumed().
- stream_handle_ = std::move(body);
}
- pending_commit_ = true;
is_loading_ = true;
}
@@ -3802,11 +4109,7 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
remote_interfaces_.reset(new service_manager::InterfaceProvider);
remote_interfaces_->Bind(std::move(remote_interfaces));
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- remote_interfaces_->GetInterface(&frame_input_handler_);
- } else {
- legacy_frame_input_handler_.reset(new LegacyIPCFrameInputHandler(this));
- }
+ remote_interfaces_->GetInterface(&frame_input_handler_);
}
void RenderFrameHostImpl::InvalidateMojoConnection() {
@@ -3933,6 +4236,13 @@ RenderFrameHostImpl::GetMojoImageDownloader() {
return mojo_image_downloader_;
}
+const blink::mojom::FindInPageAssociatedPtr&
+RenderFrameHostImpl::GetFindInPage() {
+ if (!find_in_page_)
+ GetRemoteAssociatedInterfaces()->GetInterface(&find_in_page_);
+ return find_in_page_;
+}
+
resource_coordinator::FrameResourceCoordinator*
RenderFrameHostImpl::GetFrameResourceCoordinator() {
if (frame_resource_coordinator_)
@@ -3989,6 +4299,26 @@ bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
return GetContentClient()->browser()->CanCommitURL(GetProcess(), url);
}
+void RenderFrameHostImpl::BlockRequestsForFrame() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NotifyForEachFrameFromUI(
+ this,
+ base::BindRepeating(&ResourceDispatcherHostImpl::BlockRequestsForRoute));
+}
+
+void RenderFrameHostImpl::ResumeBlockedRequestsForFrame() {
+ NotifyForEachFrameFromUI(
+ this, base::BindRepeating(
+ &ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
+}
+
+void RenderFrameHostImpl::CancelBlockedRequestsForFrame() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NotifyForEachFrameFromUI(
+ this, base::BindRepeating(
+ &ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute));
+}
+
bool RenderFrameHostImpl::IsSameSiteInstance(
RenderFrameHostImpl* other_render_frame_host) {
// As a sanity check, make sure the frame belongs to the same BrowserContext.
@@ -4229,21 +4559,30 @@ void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
void RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
network::mojom::URLLoaderFactoryRequest default_factory_request) {
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = GetProcess()->GetID();
+ // TODO(lukasza): https://crbug.com/792546: Start using CORB.
+ params->is_corb_enabled = false;
+ network::mojom::URLLoaderFactoryParamsPtr params_for_error_monitoring =
+ params->Clone();
+
auto* context = GetSiteInstance()->GetBrowserContext();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
this, false /* is_navigation */, &default_factory_request);
// Keep DevTools proxy lasy, i.e. closest to the network.
RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
- this, false, &default_factory_request);
+ this, false /* is_navigation */, false /* is_download */,
+ &default_factory_request);
StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetStoragePartition(context, GetSiteInstance()));
if (g_create_network_factory_callback_for_test.Get().is_null()) {
storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(default_factory_request), GetProcess()->GetID());
+ std::move(default_factory_request), std::move(params));
} else {
network::mojom::URLLoaderFactoryPtr original_factory;
storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
- mojo::MakeRequest(&original_factory), GetProcess()->GetID());
+ mojo::MakeRequest(&original_factory), std::move(params));
g_create_network_factory_callback_for_test.Get().Run(
std::move(default_factory_request), GetProcess()->GetID(),
original_factory.PassInterface());
@@ -4254,7 +4593,7 @@ void RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
if (IsOutOfProcessNetworkService()) {
storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
mojo::MakeRequest(&network_service_connection_error_handler_holder_),
- GetProcess()->GetID());
+ std::move(params_for_error_monitoring));
network_service_connection_error_handler_holder_
.set_connection_error_handler(base::BindOnce(
&RenderFrameHostImpl::UpdateSubresourceLoaderFactories,
@@ -4440,28 +4779,43 @@ void RenderFrameHostImpl::CreateAudioInputStreamFactory(
mojom::RendererAudioInputStreamFactoryRequest request) {
BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
DCHECK(browser_main_loop);
- audio_input_stream_factory_ =
- RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
- base::BindRepeating(&AudioInputDelegateImpl::Create,
- media::AudioManager::Get(),
- AudioMirroringManager::GetInstance(),
- browser_main_loop->user_input_monitor(),
- GetProcess()->GetID(), GetRoutingID()),
- browser_main_loop->media_stream_manager(), GetProcess()->GetID(),
- GetRoutingID(), std::move(request));
+ if (base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams)) {
+ scoped_refptr<AudioInputDeviceManager> aidm =
+ browser_main_loop->media_stream_manager()->audio_input_device_manager();
+ audio_service_audio_input_stream_factory_.emplace(std::move(request),
+ std::move(aidm), this);
+ } else {
+ in_content_audio_input_stream_factory_ =
+ RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
+ base::BindRepeating(&AudioInputDelegateImpl::Create,
+ browser_main_loop->audio_manager(),
+ AudioMirroringManager::GetInstance(),
+ browser_main_loop->user_input_monitor(),
+ GetProcess()->GetID(), GetRoutingID()),
+ browser_main_loop->media_stream_manager(), GetProcess()->GetID(),
+ GetRoutingID(), std::move(request));
+ }
}
void RenderFrameHostImpl::CreateAudioOutputStreamFactory(
mojom::RendererAudioOutputStreamFactoryRequest request) {
- RendererAudioOutputStreamFactoryContext* factory_context =
- GetProcess()->GetRendererAudioOutputStreamFactoryContext();
- DCHECK(factory_context);
- audio_output_stream_factory_ =
- RenderFrameAudioOutputStreamFactoryHandle::CreateFactory(
- factory_context, GetRoutingID(), std::move(request));
+ if (base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams)) {
+ media::AudioSystem* audio_system =
+ BrowserMainLoop::GetInstance()->audio_system();
+ MediaStreamManager* media_stream_manager =
+ BrowserMainLoop::GetInstance()->media_stream_manager();
+ audio_service_audio_output_stream_factory_.emplace(
+ this, audio_system, media_stream_manager, std::move(request));
+ } else {
+ RendererAudioOutputStreamFactoryContext* factory_context =
+ GetProcess()->GetRendererAudioOutputStreamFactoryContext();
+ DCHECK(factory_context);
+ in_content_audio_output_stream_factory_ =
+ RenderFrameAudioOutputStreamFactoryHandle::CreateFactory(
+ factory_context, GetRoutingID(), std::move(request));
+ }
}
-#if BUILDFLAG(ENABLE_WEBRTC)
void RenderFrameHostImpl::CreateMediaStreamDispatcherHost(
MediaStreamManager* media_stream_manager,
mojom::MediaStreamDispatcherHostRequest request) {
@@ -4472,7 +4826,6 @@ void RenderFrameHostImpl::CreateMediaStreamDispatcherHost(
}
media_stream_dispatcher_host_->BindRequest(std::move(request));
}
-#endif
void RenderFrameHostImpl::BindMediaInterfaceFactoryRequest(
media::mojom::InterfaceFactoryRequest request) {
@@ -4485,21 +4838,18 @@ void RenderFrameHostImpl::BindMediaInterfaceFactoryRequest(
void RenderFrameHostImpl::CreateWebSocket(
network::mojom::WebSocketRequest request) {
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- auto* context = GetSiteInstance()->GetBrowserContext();
- auto* storage_partition = static_cast<StoragePartitionImpl*>(
- BrowserContext::GetStoragePartition(context, GetSiteInstance()));
- storage_partition->GetNetworkContext()->CreateWebSocket(
- std::move(request), process_->GetID(), routing_id_,
- last_committed_origin_);
- } else {
- // This is to support usage of WebSockets in cases in which there is an
- // associated RenderFrame. This is important for showing the correct
- // security state of the page and also honoring user override of bad
- // certificates.
- WebSocketManager::CreateWebSocketForFrame(process_->GetID(), routing_id_,
- std::move(request));
- }
+ // This is to support usage of WebSockets in cases in which there is an
+ // associated RenderFrame. This is important for showing the correct security
+ // state of the page and also honoring user override of bad certificates.
+ WebSocketManager::CreateWebSocket(process_->GetID(), routing_id_,
+ last_committed_origin_, std::move(request));
+}
+
+void RenderFrameHostImpl::CreateDedicatedWorkerHostFactory(
+ blink::mojom::DedicatedWorkerFactoryRequest request) {
+ content::CreateDedicatedWorkerHostFactory(process_->GetID(), routing_id_,
+ last_committed_origin_,
+ std::move(request));
}
void RenderFrameHostImpl::OnMediaInterfaceFactoryConnectionError() {
@@ -4602,7 +4952,6 @@ RenderFrameHostImpl::TakeNavigationHandleForSameDocumentCommit(
false, // started_from_context_menu
CSPDisposition::CHECK, // should_check_main_world_csp
false, // is_form_submission
- base::nullopt, // suggested_filename
nullptr); // navigation_ui_data
}
@@ -4664,7 +5013,6 @@ RenderFrameHostImpl::TakeNavigationHandleForCommit(
false, // started_from_context_menu
CSPDisposition::CHECK, // should_check_main_world_csp
false, // is_form_submission
- base::nullopt, // suggested_filename
nullptr); // navigation_ui_data
}
@@ -4701,11 +5049,6 @@ void RenderFrameHostImpl::SetLastCommittedSiteUrl(const GURL& url) {
}
}
-void RenderFrameHostImpl::OnStreamHandleConsumed(const GURL& stream_url) {
- if (stream_handle_ && stream_handle_->GetURL() == stream_url)
- stream_handle_.reset();
-}
-
#if defined(OS_ANDROID)
class RenderFrameHostImpl::JavaInterfaceProvider
@@ -4911,7 +5254,6 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
is_loading_ = true;
frame_tree_node()->DidStartLoading(true, was_loading);
}
- pending_commit_ = false;
}
if (navigation_request_)
@@ -4933,7 +5275,6 @@ bool RenderFrameHostImpl::DidCommitNavigationInternal(
frame_tree_node()->navigator()->DidNavigate(this, *validated_params,
std::move(navigation_handle),
is_same_document_navigation);
-
return true;
}
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.h b/chromium/content/browser/frame_host/render_frame_host_impl.h
index 5b85cfa21b9..e5c6b19d148 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -31,6 +31,8 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/bad_message.h"
#include "content/browser/loader/global_routing_id.h"
+#include "content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h"
+#include "content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.h"
#include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
#include "content/browser/site_instance_impl.h"
@@ -61,11 +63,14 @@
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+#include "third_party/blink/public/platform/dedicated_worker_factory.mojom.h"
#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
#include "third_party/blink/public/platform/modules/webauth/authenticator.mojom.h"
#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
+#include "third_party/blink/public/platform/web_scroll_types.h"
#include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
#include "third_party/blink/public/web/commit_result.mojom.h"
#include "third_party/blink/public/web/web_text_direction.h"
@@ -98,6 +103,7 @@ class ListValue;
namespace blink {
struct FramePolicy;
+struct WebFullscreenOptions;
struct WebScrollIntoViewParams;
}
@@ -114,7 +120,6 @@ namespace content {
class AssociatedInterfaceProviderImpl;
class AssociatedInterfaceRegistryImpl;
class AuthenticatorImpl;
-class LegacyIPCFrameInputHandler;
class FrameTree;
class FrameTreeNode;
class GeolocationServiceImpl;
@@ -133,7 +138,6 @@ class RenderWidgetHostImpl;
class RenderWidgetHostView;
class RenderWidgetHostViewBase;
class SensorProviderProxyImpl;
-class StreamHandle;
class TimeoutMonitor;
class WebBluetoothServiceImpl;
struct CommonNavigationParams;
@@ -144,9 +148,7 @@ struct RequestNavigationParams;
struct ResourceTimingInfo;
struct SubresourceLoaderParams;
-#if BUILDFLAG(ENABLE_WEBRTC)
class MediaStreamDispatcherHost;
-#endif
class CONTENT_EXPORT RenderFrameHostImpl
: public RenderFrameHost,
@@ -232,8 +234,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
int max_length) override;
void AllowBindings(int binding_flags) override;
int GetEnabledBindings() const override;
- void BlockRequestsForFrame() override;
- void ResumeBlockedRequestsForFrame() override;
void DisableBeforeUnloadHangMonitorForTesting() override;
bool IsBeforeUnloadHangMonitorDisabledForTesting() override;
bool GetSuddenTerminationDisablerState(
@@ -419,8 +419,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
// active RenderFrames, but not until WasSwappedOut is called.
void SwapOut(RenderFrameProxyHost* proxy, bool is_loading);
- // Whether an ongoing navigation is waiting for a BeforeUnload ACK from the
- // RenderFrame.
+ // Whether an ongoing navigation in this frame is waiting for a BeforeUnload
+ // ACK either from this RenderFrame or from one of its subframes.
bool is_waiting_for_beforeunload_ack() const {
return is_waiting_for_beforeunload_ack_;
}
@@ -442,20 +442,32 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Stop the load in progress.
void Stop();
- // Runs the beforeunload handler for this frame. |for_navigation| indicates
- // whether this call is for the current frame during a navigation. False means
- // we're closing the entire tab. |is_reload| indicates whether the navigation
- // is a reload of the page or not. If |for_navigation| is false, |is_reload|
- // should be false as well.
- void DispatchBeforeUnload(bool for_navigation, bool is_reload);
+ enum class BeforeUnloadType {
+ BROWSER_INITIATED_NAVIGATION,
+ RENDERER_INITIATED_NAVIGATION,
+ TAB_CLOSE
+ };
+
+ // Runs the beforeunload handler for this frame and its subframes. |type|
+ // indicates whether this call is for a navigation or tab close. |is_reload|
+ // indicates whether the navigation is a reload of the page. If |type|
+ // corresponds to tab close and not a navigation, |is_reload| should be
+ // false.
+ void DispatchBeforeUnload(BeforeUnloadType type, bool is_reload);
// Simulate beforeunload ack on behalf of renderer if it's unrenresponsive.
void SimulateBeforeUnloadAck();
// Returns true if a call to DispatchBeforeUnload will actually send the
- // BeforeUnload IPC. This is the case if the current renderer is live and this
- // frame is the main frame.
- bool ShouldDispatchBeforeUnload();
+ // BeforeUnload IPC. This can be called on a main frame or subframe. If
+ // |check_subframes_only| is false, it covers handlers for the frame
+ // itself and all its descendants. If |check_subframes_only| is true, it
+ // only checks the frame's descendants but not the frame itself.
+ bool ShouldDispatchBeforeUnload(bool check_subframes_only);
+
+ // Allow tests to override how long to wait for beforeunload ACKs to arrive
+ // before timing out.
+ void SetBeforeUnloadTimeoutDelayForTesting(const base::TimeDelta& timeout);
// Update the frame's opener in the renderer process in response to the
// opener being modified (e.g., with window.open or being set to null) in
@@ -484,15 +496,16 @@ class CONTENT_EXPORT RenderFrameHostImpl
#if defined(OS_ANDROID)
// Samsung Galaxy Note-specific "smart clip" stylus text getter.
- using ExtractSmartClipDataCallback =
- base::OnceCallback<void(const base::string16&, const base::string16&)>;
+ using ExtractSmartClipDataCallback = base::OnceCallback<
+ void(const base::string16&, const base::string16&, const gfx::Rect&)>;
void RequestSmartClipExtract(ExtractSmartClipDataCallback callback,
gfx::Rect rect);
void OnSmartClipDataExtracted(int32_t callback_id,
const base::string16& text,
- const base::string16& html);
+ const base::string16& html,
+ const gfx::Rect& clip_rect);
#endif // defined(OS_ANDROID)
// Request a one-time snapshot of the accessibility tree without changing
@@ -563,7 +576,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CommitNavigation(
network::ResourceResponse* response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- std::unique_ptr<StreamHandle> body,
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
bool is_view_source,
@@ -619,6 +631,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Returns the Mojo ImageDownloader service.
const content::mojom::ImageDownloaderPtr& GetMojoImageDownloader();
+ // Returns pointer to renderer side FindInPage associated with this frame.
+ const blink::mojom::FindInPageAssociatedPtr& GetFindInPage();
+
resource_coordinator::FrameResourceCoordinator* GetFrameResourceCoordinator()
override;
@@ -653,6 +668,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
return has_focused_editable_element_;
}
+ // Note: The methods for blocking / resuming / cancelling requests per
+ // RenderFrameHost are deprecated and will not work in the network service,
+ // please avoid using them.
+ //
+ // Causes all new requests for the root RenderFrameHost and its children to
+ // be blocked (not being started) until ResumeBlockedRequestsForFrame is
+ // called.
+ void BlockRequestsForFrame();
+
+ // Resumes any blocked request for the specified root RenderFrameHost and
+ // child frame hosts.
+ void ResumeBlockedRequestsForFrame();
+
// Cancels any blocked request for the frame and its subframes.
void CancelBlockedRequestsForFrame();
@@ -682,10 +710,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
service_manager::mojom::InterfaceProviderRequest
interface_provider_request);
- const StreamHandle* stream_handle_for_testing() const {
- return stream_handle_.get();
- }
-
// Exposed so that tests can swap out the implementation and intercept calls.
mojo::AssociatedBinding<mojom::FrameHost>& frame_host_binding_for_testing() {
return frame_host_associated_binding_;
@@ -717,6 +741,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
// running renderer, or in case of Network Service connection errors.
void UpdateSubresourceLoaderFactories();
+ // Allow tests to override the timeout used to keep subframe processes alive
+ // for unload handler processing.
+ void SetSubframeUnloadTimeoutForTesting(const base::TimeDelta& timeout);
+
protected:
friend class RenderFrameHostFactory;
@@ -740,6 +768,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
friend class TestRenderFrameHost;
friend class TestRenderViewHost;
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBeforeUnloadBrowserTest,
+ SubframeShowsDialogWhenMainFrameNavigates);
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBeforeUnloadBrowserTest,
+ TimerNotRestartedBySecondDialog);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
CreateRenderViewAfterProcessKillAndClosedProxy);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, DontSelectInvalidFiles);
@@ -766,6 +798,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
ContextMenuAfterCrossProcessNavigation);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
ActiveSandboxFlagsRetainedAfterSwapOut);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ LastCommittedURLRetainedAfterSwapOut);
FRIEND_TEST_ALL_PREFIXES(SecurityExploitBrowserTest,
AttemptDuplicateRenderViewHost);
@@ -845,7 +879,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnAccessibilitySnapshotResponse(
int callback_id,
const AXContentTreeUpdate& snapshot);
- void OnToggleFullscreen(bool enter_fullscreen);
+ void OnEnterFullscreen(const blink::WebFullscreenOptions& options);
+ void OnExitFullscreen();
void OnSuddenTerminationDisablerChanged(
bool present,
blink::WebSuddenTerminationDisablerType disabler_type);
@@ -867,6 +902,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
void OnScrollRectToVisibleInParentFrame(
const gfx::Rect& rect_to_scroll,
const blink::WebScrollIntoViewParams& params);
+ void OnBubbleLogicalScrollInParentFrame(
+ blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity);
void OnFrameDidCallFocus();
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
@@ -917,10 +955,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CancelInitialHistoryLoad() override;
void UpdateEncoding(const std::string& encoding) override;
void FrameSizeChanged(const gfx::Size& frame_size) override;
- void OnUpdatePictureInPictureSurfaceId(
- const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size) override;
- void OnExitPictureInPicture() override;
// Registers Mojo interfaces that this frame host makes available.
void RegisterMojoInterfaces();
@@ -1019,17 +1053,18 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CreateAudioOutputStreamFactory(
mojom::RendererAudioOutputStreamFactoryRequest request);
-#if BUILDFLAG(ENABLE_WEBRTC)
void CreateMediaStreamDispatcherHost(
MediaStreamManager* media_stream_manager,
mojom::MediaStreamDispatcherHostRequest request);
-#endif
void BindMediaInterfaceFactoryRequest(
media::mojom::InterfaceFactoryRequest request);
void CreateWebSocket(network::mojom::WebSocketRequest request);
+ void CreateDedicatedWorkerHostFactory(
+ blink::mojom::DedicatedWorkerFactoryRequest request);
+
// Callback for connection error on the media::mojom::InterfaceFactory client.
void OnMediaInterfaceFactoryConnectionError();
@@ -1066,6 +1101,50 @@ class CONTENT_EXPORT RenderFrameHostImpl
std::unique_ptr<NavigationHandleImpl> TakeNavigationHandleForCommit(
const FrameHostMsg_DidCommitProvisionalLoad_Params& params);
+ // Helper to process the beforeunload ACK. |proceed| indicates whether the
+ // navigation or tab close should be allowed to proceed. If
+ // |treat_as_final_ack| is true, the frame should stop waiting for any
+ // further ACKs from subframes. ACKs received from the renderer set
+ // |treat_as_final_ack| to false, whereas a beforeunload timeout sets it to
+ // true.
+ void ProcessBeforeUnloadACK(
+ bool proceed,
+ bool treat_as_final_ack,
+ const base::TimeTicks& renderer_before_unload_start_time,
+ const base::TimeTicks& renderer_before_unload_end_time);
+
+ // Find the frame that triggered the beforeunload handler to run in this
+ // frame, which might be the frame itself or its ancestor. This will
+ // return the frame that is navigating, or the main frame if beforeunload was
+ // triggered by closing the current tab. It will return null if no
+ // beforeunload is currently in progress.
+ RenderFrameHostImpl* GetBeforeUnloadInitiator();
+
+ // Called when a particular frame finishes running a beforeunload handler,
+ // possibly as part of processing beforeunload for an ancestor frame. In
+ // that case, this is called on the ancestor frame that is navigating or
+ // closing, and |frame| indicates which beforeunload ACK is received. If a
+ // beforeunload timeout occurred, |treat_as_final_ack| is set to true.
+ // |is_frame_being_destroyed| is set to true if this was called as part of
+ // destroying |frame|.
+ void ProcessBeforeUnloadACKFromFrame(
+ bool proceed,
+ bool treat_as_final_ack,
+ RenderFrameHostImpl* frame,
+ bool is_frame_being_destroyed,
+ const base::TimeTicks& renderer_before_unload_start_time,
+ const base::TimeTicks& renderer_before_unload_end_time);
+
+ // Helper function to check whether the current frame and its subframes need
+ // to run beforeunload and, if |send_ipc| is true, send all the necessary
+ // IPCs for this frame's subtree. If |send_ipc| is false, this only checks
+ // whether beforeunload is needed and returns the answer. |subframes_only|
+ // indicates whether to only check subframes of the current frame, and skip
+ // the current frame itself.
+ bool CheckOrDispatchBeforeUnloadForSubtree(bool subframes_only,
+ bool send_ipc,
+ bool is_reload);
+
// Called by |beforeunload_timeout_| when the beforeunload timeout fires.
void BeforeUnloadTimeout();
@@ -1081,9 +1160,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// based on its parent frame.
void ResetFeaturePolicy();
- // Called when the frame has consumed the StreamHandle and it can be released.
- void OnStreamHandleConsumed(const GURL& stream_url);
-
// TODO(ekaramad): One major purpose behind the API is to traverse the frame
// tree top-down to visit the RenderWidgetHostViews of interest in the most
// efficient way. We might want to revisit this API, remove it from RFHImpl,
@@ -1206,7 +1282,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
// RenderFrameHost owns its RenderViewHost.
RenderWidgetHostImpl* render_widget_host_;
- int routing_id_;
+ const int routing_id_;
// Boolean indicating whether this RenderFrameHost is being actively used or
// is waiting for FrameHostMsg_SwapOut_ACK and thus pending deletion.
@@ -1240,6 +1316,25 @@ class CONTENT_EXPORT RenderFrameHostImpl
// to OnBeforeUnloadACK(), or until the timeout triggers.
std::unique_ptr<TimeoutMonitor> beforeunload_timeout_;
+ // The delay to use for the beforeunload timeout monitor above.
+ base::TimeDelta beforeunload_timeout_delay_;
+
+ // When this frame is asked to execute beforeunload, this maintains a list of
+ // frames that need to receive beforeunload ACKs. This may include this
+ // frame and/or its descendant frames. This excludes frames that don't have
+ // beforeunload handlers defined.
+ //
+ // TODO(alexmos): For now, this always includes the navigating frame. Make
+ // this include the navigating frame only if it has a beforeunload handler
+ // defined.
+ std::set<RenderFrameHostImpl*> beforeunload_pending_replies_;
+
+ // During beforeunload, keeps track whether a dialog has already been shown.
+ // Used to enforce at most one dialog per navigation. This is tracked on the
+ // frame that is being navigated, and not on any of its subframes that might
+ // have triggered a dialog.
+ bool has_shown_beforeunload_dialog_ = false;
+
// Returns whether the tab was previously discarded.
// This is passed to RequestNavigationParams in NavigationRequest.
bool was_discarded_;
@@ -1248,10 +1343,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// document or not.
bool is_loading_;
- // Used to track whether a commit is expected in this frame. Only used in
- // tests.
- bool pending_commit_;
-
// The unique ID of the latest NavigationEntry that this RenderFrameHost is
// showing. This may change even when this frame hasn't committed a page,
// such as for a new subframe navigation in a different frame. Tracking this
@@ -1318,10 +1409,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// already exists it will still be used.
bool no_create_browser_accessibility_manager_for_testing_;
- // Owns the stream used in navigations to store the body of the response once
- // it has started.
- std::unique_ptr<StreamHandle> stream_handle_;
-
// Context shared for each mojom::PermissionService instance created for this
// RFH.
std::unique_ptr<PermissionServiceContext> permission_service_context_;
@@ -1329,6 +1416,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Holder of Mojo connection with ImageDownloader service in RenderFrame.
content::mojom::ImageDownloaderPtr mojo_image_downloader_;
+ // Holder of Mojo connection with FindInPage service in Blink.
+ blink::mojom::FindInPageAssociatedPtr find_in_page_;
+
// Holds the interface wrapper to the Global Resource Coordinator service.
std::unique_ptr<resource_coordinator::FrameResourceCoordinator>
frame_resource_coordinator_;
@@ -1413,13 +1503,22 @@ class CONTENT_EXPORT RenderFrameHostImpl
// |FrameHostMsg_TextSurroundingSelectionResponse| message comes.
TextSurroundingSelectionCallback text_surrounding_selection_callback_;
- UniqueAudioInputStreamFactoryPtr audio_input_stream_factory_;
- UniqueAudioOutputStreamFactoryPtr audio_output_stream_factory_;
+ // We switch between |audio_service_audio_output_stream_factory_| and
+ // |in_content_audio_output_stream_factory_| based on
+ // features::kAudioServiceAudioStreams status.
+ base::Optional<RenderFrameAudioOutputStreamFactory>
+ audio_service_audio_output_stream_factory_;
+ UniqueAudioOutputStreamFactoryPtr in_content_audio_output_stream_factory_;
+
+ // We switch between |audio_service_audio_input_stream_factory_| and
+ // |in_content_audio_input_stream_factory_| based on
+ // features::kAudioServiceAudioStreams status.
+ base::Optional<RenderFrameAudioInputStreamFactory>
+ audio_service_audio_input_stream_factory_;
+ UniqueAudioInputStreamFactoryPtr in_content_audio_input_stream_factory_;
-#if BUILDFLAG(ENABLE_WEBRTC)
std::unique_ptr<MediaStreamDispatcherHost, BrowserThread::DeleteOnIOThread>
media_stream_dispatcher_host_;
-#endif
// Hosts media::mojom::InterfaceFactory for the RenderFrame and forwards
// media::mojom::InterfaceFactory calls to the remote "media" service.
@@ -1510,11 +1609,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
viz::mojom::InputTargetClient* input_target_client_ = nullptr;
mojom::FrameInputHandlerPtr frame_input_handler_;
- std::unique_ptr<LegacyIPCFrameInputHandler> legacy_frame_input_handler_;
std::unique_ptr<KeepAliveHandleFactory> keep_alive_handle_factory_;
base::TimeDelta keep_alive_timeout_;
+ base::TimeDelta subframe_unload_timeout_;
+
// For observing Network Service connection errors only. Will trigger
// |OnNetworkServiceConnectionError()| and push updated factories to
// |RenderFrame|.
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index f4b891346d8..cd82082fbb7 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -12,9 +12,11 @@
#include "base/test/bind_test_util.h"
#include "base/test/histogram_tester.h"
#include "base/test/mock_callback.h"
+#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/interface_provider_filtering.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/javascript_dialog_manager.h"
@@ -30,6 +32,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/did_commit_provisional_load_interceptor.h"
#include "content/test/frame_host_test_interface.mojom.h"
#include "content/test/test_content_browser_client.h"
@@ -204,6 +207,8 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
DialogClosedCallback& callback() { return callback_; }
+ int num_beforeunload_dialogs_seen() { return num_beforeunload_dialogs_seen_; }
+
// WebContentsDelegate
JavaScriptDialogManager* GetJavaScriptDialogManager(
@@ -225,6 +230,7 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
RenderFrameHost* render_frame_host,
bool is_reload,
DialogClosedCallback callback) override {
+ ++num_beforeunload_dialogs_seen_;
callback_ = std::move(callback);
message_loop_runner_->Quit();
}
@@ -257,6 +263,9 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager,
// The number of times NavigationStateChanged has been called.
int url_invalidate_count_;
+ // The total number of beforeunload dialogs seen by this dialog manager.
+ int num_beforeunload_dialogs_seen_ = 0;
+
DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
};
@@ -416,6 +425,485 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
wc->SetJavaScriptDialogManagerForTesting(nullptr);
}
+// Helper class for beforunload tests. Sets up a custom dialog manager for the
+// main WebContents and provides helpers to register and test beforeunload
+// handlers.
+//
+// TODO(alexmos): Refactor other beforeunload tests in this file to use this
+// class.
+class RenderFrameHostImplBeforeUnloadBrowserTest
+ : public RenderFrameHostImplBrowserTest {
+ public:
+ RenderFrameHostImplBeforeUnloadBrowserTest() {}
+
+ WebContentsImpl* web_contents() {
+ return static_cast<WebContentsImpl*>(shell()->web_contents());
+ }
+
+ TestJavaScriptDialogManager* dialog_manager() {
+ return dialog_manager_.get();
+ }
+
+ void CloseDialogAndProceed() {
+ std::move(dialog_manager()->callback())
+ .Run(true /* navigation should proceed */, base::string16());
+ }
+
+ void CloseDialogAndCancel() {
+ std::move(dialog_manager()->callback())
+ .Run(false /* navigation should proceed */, base::string16());
+ }
+
+ // Installs a beforeunload handler in the given frame.
+ // |before_unload_options| specify whether the handler should send a "ping"
+ // message through domAutomationController, and/or whether it should trigger
+ // the modal beforeunload confirmation dialog.
+ enum BeforeUnloadOptions {
+ SHOW_DIALOG = 1,
+ SEND_PING = 2,
+ };
+ void InstallBeforeUnloadHandler(FrameTreeNode* ftn,
+ int before_unload_options) {
+ std::string script = "window.onbeforeunload = () => { ";
+ if (before_unload_options & SEND_PING)
+ script += "domAutomationController.send('ping'); ";
+ if (before_unload_options & SHOW_DIALOG)
+ script += "return 'x'; ";
+ script += " }";
+ EXPECT_TRUE(ExecuteScript(ftn, script));
+ }
+
+ int RetrievePingsFromMessageQueue(DOMMessageQueue* msg_queue) {
+ int num_pings = 0;
+ std::string message;
+ while (msg_queue->PopMessage(&message)) {
+ base::TrimString(message, "\"", &message);
+ // Only count messages from beforeunload. For example, an ExecuteScript
+ // sends its own message to DOMMessageQueue, which we need to ignore.
+ if (message == "ping")
+ ++num_pings;
+ }
+ return num_pings;
+ }
+
+ protected:
+ void SetUpOnMainThread() override {
+ RenderFrameHostImplBrowserTest::SetUpOnMainThread();
+ dialog_manager_.reset(new TestJavaScriptDialogManager);
+ web_contents()->SetDelegate(dialog_manager_.get());
+ }
+
+ void TearDownOnMainThread() override {
+ web_contents()->SetDelegate(nullptr);
+ web_contents()->SetJavaScriptDialogManagerForTesting(nullptr);
+ RenderFrameHostImplBrowserTest::TearDownOnMainThread();
+ }
+
+ private:
+ std::unique_ptr<TestJavaScriptDialogManager> dialog_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostImplBeforeUnloadBrowserTest);
+};
+
+// Check that when a frame performs a browser-initiated navigation, its
+// cross-site subframe is able to execute a beforeunload handler and put up a
+// dialog to cancel or allow the navigation. This matters especially in
+// --site-per-process mode; see https://crbug.com/853021.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ SubframeShowsDialogWhenMainFrameNavigates) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler in the first iframe.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root->child_at(0), SHOW_DIALOG);
+
+ // Disable beforeunload timer to prevent flakiness.
+ PrepContentsForBeforeUnloadTest(web_contents());
+
+ // Navigate cross-site and wait for the beforeunload dialog to be shown from
+ // the subframe.
+ GURL cross_site_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ shell()->LoadURL(cross_site_url);
+ dialog_manager()->Wait();
+
+ // Only the main frame should be marked as waiting for beforeunload ACK as
+ // the frame being navigated.
+ RenderFrameHostImpl* main_frame = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* child = root->child_at(0)->current_frame_host();
+ EXPECT_TRUE(main_frame->is_waiting_for_beforeunload_ack());
+ EXPECT_FALSE(child->is_waiting_for_beforeunload_ack());
+
+ // Sanity check that the main frame is waiting for subframe's beforeunload
+ // ACK.
+ EXPECT_EQ(main_frame, child->GetBeforeUnloadInitiator());
+ EXPECT_EQ(main_frame, main_frame->GetBeforeUnloadInitiator());
+ EXPECT_EQ(1u, main_frame->beforeunload_pending_replies_.size());
+
+ // In --site-per-process mode, the beforeunload ACK should come back from the
+ // child RFH. Without --site-per-process, it will come from the main frame
+ // RFH, which processes beforeunload for both main frame and child frame,
+ // since they are in the same process.
+ RenderFrameHostImpl* frame_that_sent_beforeunload_ipc =
+ AreAllSitesIsolatedForTesting() ? child : main_frame;
+ EXPECT_TRUE(main_frame->beforeunload_pending_replies_.count(
+ frame_that_sent_beforeunload_ipc));
+
+ // Answer the dialog with "cancel" to stay on current page.
+ CloseDialogAndCancel();
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ EXPECT_EQ(main_url, web_contents()->GetLastCommittedURL());
+
+ // Verify beforeunload state has been cleared.
+ EXPECT_FALSE(main_frame->is_waiting_for_beforeunload_ack());
+ EXPECT_FALSE(child->is_waiting_for_beforeunload_ack());
+ EXPECT_EQ(nullptr, main_frame->GetBeforeUnloadInitiator());
+ EXPECT_EQ(nullptr, child->GetBeforeUnloadInitiator());
+ EXPECT_EQ(0u, main_frame->beforeunload_pending_replies_.size());
+
+ // Try navigating again. The dialog should come up again.
+ shell()->LoadURL(cross_site_url);
+ dialog_manager()->Wait();
+ EXPECT_TRUE(main_frame->is_waiting_for_beforeunload_ack());
+
+ // Now answer the dialog and allow the navigation to proceed. Disable
+ // SwapOut ACK on the old frame so that it sticks around in pending delete
+ // state, since the test later verifies that it has received the beforeunload
+ // ACK.
+ TestFrameNavigationObserver commit_observer(root);
+ main_frame->DisableSwapOutTimerForTesting();
+ CloseDialogAndProceed();
+ commit_observer.WaitForCommit();
+ EXPECT_EQ(cross_site_url, web_contents()->GetLastCommittedURL());
+ EXPECT_FALSE(
+ web_contents()->GetMainFrame()->is_waiting_for_beforeunload_ack());
+
+ // The navigation that succeeded was a browser-initiated, main frame
+ // navigation, so it swapped RenderFrameHosts. |main_frame| should now be
+ // pending deletion and waiting for swapout ACK, but it should not be waiting
+ // for the beforeunload ACK.
+ EXPECT_FALSE(main_frame->is_active());
+ EXPECT_FALSE(main_frame->is_waiting_for_beforeunload_ack());
+ EXPECT_EQ(0u, main_frame->beforeunload_pending_replies_.size());
+ EXPECT_EQ(nullptr, main_frame->GetBeforeUnloadInitiator());
+}
+
+// Check that when a frame with multiple cross-site subframes navigates, all
+// the subframes execute their beforeunload handlers, but at most one
+// beforeunload dialog is allowed per navigation.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ MultipleSubframes) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c),b,c(d),c,d)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler in five of eight frames to send a ping via
+ // domAutomationController and request a beforeunload dialog.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root, SEND_PING | SHOW_DIALOG);
+ InstallBeforeUnloadHandler(root->child_at(0)->child_at(0),
+ SEND_PING | SHOW_DIALOG);
+ InstallBeforeUnloadHandler(root->child_at(1), SEND_PING | SHOW_DIALOG);
+ InstallBeforeUnloadHandler(root->child_at(2), SEND_PING | SHOW_DIALOG);
+ InstallBeforeUnloadHandler(root->child_at(2)->child_at(0),
+ SEND_PING | SHOW_DIALOG);
+
+ // Disable beforeunload timer to prevent flakiness.
+ PrepContentsForBeforeUnloadTest(web_contents());
+
+ // Navigate main frame cross-site and wait for the beforeunload dialog to be
+ // shown from one of the frames.
+ DOMMessageQueue msg_queue;
+ GURL cross_site_url(embedded_test_server()->GetURL("e.com", "/title1.html"));
+ shell()->LoadURL(cross_site_url);
+ dialog_manager()->Wait();
+
+ // Answer the dialog and allow the navigation to proceed.
+ CloseDialogAndProceed();
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ EXPECT_EQ(cross_site_url, web_contents()->GetLastCommittedURL());
+
+ // We should've received five beforeunload pings.
+ EXPECT_EQ(5, RetrievePingsFromMessageQueue(&msg_queue));
+
+ // No more beforeunload dialogs shouldn't been shown, due to a policy of at
+ // most one dialog per navigation.
+ EXPECT_EQ(1, dialog_manager()->num_beforeunload_dialogs_seen());
+}
+
+// Similar to the test above, but test scenarios where the subframes with
+// beforeunload handlers aren't local roots.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ NonLocalRootSubframes) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(b),c(c))"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler in two of five frames to send a ping via
+ // domAutomationController and request a beforeunload dialog.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root->child_at(0), SEND_PING | SHOW_DIALOG);
+ InstallBeforeUnloadHandler(root->child_at(0)->child_at(0),
+ SEND_PING | SHOW_DIALOG);
+
+ // Disable beforeunload timer to prevent flakiness.
+ PrepContentsForBeforeUnloadTest(web_contents());
+
+ // Navigate and wait for the beforeunload dialog to be shown from one of the
+ // frames.
+ DOMMessageQueue msg_queue;
+ GURL cross_site_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ shell()->LoadURL(cross_site_url);
+ dialog_manager()->Wait();
+
+ // Answer the dialog and allow the navigation to proceed.
+ CloseDialogAndProceed();
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ EXPECT_EQ(cross_site_url, web_contents()->GetLastCommittedURL());
+
+ // We should've received two beforeunload pings.
+ EXPECT_EQ(2, RetrievePingsFromMessageQueue(&msg_queue));
+
+ // No more beforeunload dialogs shouldn't been shown, due to a policy of at
+ // most one dialog per navigation.
+ EXPECT_EQ(1, dialog_manager()->num_beforeunload_dialogs_seen());
+}
+
+// Test that cross-site subframes run the beforeunload handler when the main
+// frame performs a renderer-initiated navigation.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ RendererInitiatedNavigation) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a,b,c)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler in both a.com frames to send a ping via
+ // domAutomationController.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root, SEND_PING);
+ InstallBeforeUnloadHandler(root->child_at(0), SEND_PING);
+
+ // Install a beforeunload handler in the b.com frame to put up a dialog.
+ InstallBeforeUnloadHandler(root->child_at(1), SHOW_DIALOG);
+
+ // Disable beforeunload timer to prevent flakiness.
+ PrepContentsForBeforeUnloadTest(web_contents());
+
+ // Start a same-site renderer-initiated navigation. The beforeunload dialog
+ // from the b.com frame should be shown. The other two a.com frames should
+ // send pings from their beforeunload handlers.
+ DOMMessageQueue msg_queue;
+ GURL new_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ TestNavigationManager navigation_manager(web_contents(), new_url);
+ EXPECT_TRUE(ExecuteScript(root, "location.href = '" + new_url.spec() + "';"));
+ dialog_manager()->Wait();
+
+ // Answer the dialog and allow the navigation to proceed. Note that at this
+ // point, without site isolation, the navigation hasn't started yet, as the
+ // navigating frame is still processing beforeunload for all its descendant
+ // local frames. With site isolation, the a.com frames have finished
+ // beforeunload, and the browser process has received OnBeginNavigation, but
+ // the navigation is paused until the b.com subframe process finishes running
+ // beforeunload.
+ CloseDialogAndProceed();
+
+ // Wait for navigation to end.
+ navigation_manager.WaitForNavigationFinished();
+ EXPECT_EQ(new_url, web_contents()->GetLastCommittedURL());
+
+ // We should have received two pings from two a.com frames. If we receive
+ // more, that probably means we ran beforeunload an extra time in the a.com
+ // frames.
+ EXPECT_EQ(2, RetrievePingsFromMessageQueue(&msg_queue));
+ EXPECT_EQ(1, dialog_manager()->num_beforeunload_dialogs_seen());
+}
+
+// Similar to the test above, but check a navigation in a subframe rather than
+// the main frame.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ RendererInitiatedNavigationInSubframe) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c),c)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler to send a ping in all frames.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root, SEND_PING);
+ InstallBeforeUnloadHandler(root->child_at(0), SEND_PING);
+ InstallBeforeUnloadHandler(root->child_at(0)->child_at(0), SEND_PING);
+ InstallBeforeUnloadHandler(root->child_at(1), SEND_PING);
+
+ // Disable beforeunload timer to prevent flakiness.
+ PrepContentsForBeforeUnloadTest(web_contents());
+
+ // Start a renderer-initiated navigation in the middle frame.
+ DOMMessageQueue msg_queue;
+ GURL new_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ TestNavigationManager navigation_manager(web_contents(), new_url);
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
+ "location.href = '" + new_url.spec() + "';"));
+ navigation_manager.WaitForNavigationFinished();
+ EXPECT_EQ(new_url,
+ root->child_at(0)->current_frame_host()->GetLastCommittedURL());
+
+ // We should have received two pings from the b.com frame and its child.
+ // Other frames' beforeunload handlers shouldn't have run.
+ EXPECT_EQ(2, RetrievePingsFromMessageQueue(&msg_queue));
+
+ // We shouldn't have seen any beforeunload dialogs.
+ EXPECT_EQ(0, dialog_manager()->num_beforeunload_dialogs_seen());
+}
+
+// Ensure that when a beforeunload handler deletes a subframe which is also
+// running beforeunload, the navigation can still proceed.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ DetachSubframe) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler in root frame to delete the subframe.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ std::string script =
+ "window.onbeforeunload = () => { "
+ " document.body.removeChild(document.querySelector('iframe'));"
+ "}";
+ EXPECT_TRUE(ExecuteScript(root, script));
+
+ // Install a beforeunload handler which never finishes in subframe.
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
+ "window.onbeforeunload = () => { while (1) ; }"));
+
+ // Disable beforeunload timer to prevent flakiness.
+ PrepContentsForBeforeUnloadTest(web_contents());
+
+ // Navigate main frame and ensure that it doesn't time out. When the main
+ // frame detaches the subframe, the RFHI destruction should unblock the
+ // navigation from waiting on the subframe's beforeunload ACK.
+ GURL new_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), new_url));
+}
+
+// Ensure that A(B(A)) cases work sanely with beforeunload handlers.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ RendererInitiatedNavigationInABAB) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(a(b)))"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler to send a ping in all frames.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root, SEND_PING);
+ InstallBeforeUnloadHandler(root->child_at(0), SEND_PING);
+ InstallBeforeUnloadHandler(root->child_at(0)->child_at(0), SEND_PING);
+ InstallBeforeUnloadHandler(root->child_at(0)->child_at(0)->child_at(0),
+ SEND_PING);
+
+ // Disable beforeunload timer to prevent flakiness.
+ PrepContentsForBeforeUnloadTest(web_contents());
+
+ // Navigate the main frame.
+ DOMMessageQueue msg_queue;
+ GURL new_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), new_url));
+
+ // We should have received four pings.
+ EXPECT_EQ(4, RetrievePingsFromMessageQueue(&msg_queue));
+
+ // We shouldn't have seen any beforeunload dialogs.
+ EXPECT_EQ(0, dialog_manager()->num_beforeunload_dialogs_seen());
+}
+
+// Ensure that the beforeunload timeout works properly when
+// beforeunload handlers from subframes time out.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ TimeoutInSubframe) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Install a beforeunload handler to send a ping in main frame.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root, SEND_PING);
+
+ // Install a beforeunload handler which never finishes in subframe.
+ EXPECT_TRUE(ExecuteScript(root->child_at(0),
+ "window.onbeforeunload = () => { while (1) ; }"));
+
+ // Navigate the main frame. We should eventually time out on the subframe
+ // beforeunload handler and complete the navigation.
+ GURL new_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), new_url));
+}
+
+// Ensure that the beforeunload timeout isn't restarted when a frame attempts
+// to show a beforeunload dialog and fails because the dialog is already being
+// shown by another frame. See https://crbug.com/865223.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBeforeUnloadBrowserTest,
+ TimerNotRestartedBySecondDialog) {
+ // This test exercises a scenario that's only possible with
+ // --site-per-process.
+ if (!AreAllSitesIsolatedForTesting())
+ return;
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ RenderFrameHostImpl* main_frame = web_contents()->GetMainFrame();
+
+ // Install a beforeunload handler to show a dialog in both frames.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ InstallBeforeUnloadHandler(root, SHOW_DIALOG);
+ InstallBeforeUnloadHandler(root->child_at(0), SHOW_DIALOG);
+
+ // Extend the beforeunload timeout to prevent flakiness. This test can't use
+ // PrepContentsForBeforeUnloadTest(), as that clears the timer altogether,
+ // and this test needs the timer to be valid, to see whether it gets paused
+ // and not restarted correctly.
+ main_frame->SetBeforeUnloadTimeoutDelayForTesting(
+ base::TimeDelta::FromSeconds(30));
+
+ // Start a navigation in the main frame.
+ GURL new_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ shell()->LoadURL(new_url);
+
+ // We should have two pending beforeunload ACKs at this point, and the
+ // beforeunload timer should be running.
+ EXPECT_EQ(2u, main_frame->beforeunload_pending_replies_.size());
+ EXPECT_TRUE(main_frame->beforeunload_timeout_->IsRunning());
+
+ // Wait for the dialog from one of the frames. Note that either frame could
+ // be the first to trigger the dialog.
+ dialog_manager()->Wait();
+
+ // The dialog should've canceled the timer.
+ EXPECT_FALSE(main_frame->beforeunload_timeout_->IsRunning());
+
+ // Don't close the dialog and allow the second beforeunload to come in and
+ // attempt to show a dialog. This should fail due to the intervention of at
+ // most one dialog per navigation and respond to the renderer with the
+ // confirmation to proceed, which should trigger a beforeunload ACK
+ // from the second frame. Wait for that beforeunload ACK. After it's
+ // received, there will be one ACK remaining for the frame that's currently
+ // showing the dialog.
+ while (main_frame->beforeunload_pending_replies_.size() > 1) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+ run_loop.Run();
+ }
+
+ // Ensure that the beforeunload timer hasn't been restarted, since the first
+ // beforeunload dialog is still up at this point.
+ EXPECT_FALSE(main_frame->beforeunload_timeout_->IsRunning());
+
+ // Cancel the dialog and make sure we stay on the old page.
+ CloseDialogAndCancel();
+ EXPECT_TRUE(WaitForLoadStop(web_contents()));
+ EXPECT_EQ(main_url, web_contents()->GetLastCommittedURL());
+}
+
namespace {
// A helper to execute some script in a frame just before it is deleted, such
@@ -506,79 +994,6 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
EXPECT_EQ("null", result_of_window_open);
}
-// After a navigation, the StreamHandle must be released.
-IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, StreamHandleReleased) {
- if (IsNavigationMojoResponseEnabled() ||
- base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- // This test is specific to the delivery of the main resource in a blob url.
- // This mechanism is not sued when NavigationMojoResponse or NetworkService
- // are enabled.
- return;
- }
- EXPECT_TRUE(NavigateToURL(shell(), GetTestUrl("", "title1.html")));
- WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHostImpl* main_frame =
- static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
- EXPECT_EQ(nullptr, main_frame->stream_handle_for_testing());
-}
-
-namespace {
-class DropStreamHandleConsumedFilter : public BrowserMessageFilter {
- public:
- DropStreamHandleConsumedFilter() : BrowserMessageFilter(FrameMsgStart) {}
-
- protected:
- ~DropStreamHandleConsumedFilter() override {}
-
- private:
- // BrowserMessageFilter:
- bool OnMessageReceived(const IPC::Message& message) override {
- return message.type() == FrameHostMsg_StreamHandleConsumed::ID;
- }
-
- DISALLOW_COPY_AND_ASSIGN(DropStreamHandleConsumedFilter);
-};
-} // namespace
-
-// After a renderer crash, the StreamHandle must be released.
-IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
- StreamHandleReleasedOnRendererCrash) {
- // Disable this test when the |stream_handle_| is not used.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) ||
- IsNavigationMojoResponseEnabled()) {
- return;
- }
-
- GURL url_1(embedded_test_server()->GetURL("a.com", "/title1.html"));
- GURL url_2(embedded_test_server()->GetURL("a.com", "/title2.html"));
-
- EXPECT_TRUE(NavigateToURL(shell(), url_1));
-
- // Set up a filter to make sure that the browser is not notified that its
- // |stream_handle_| has been consumed.
- WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderFrameHostImpl* main_frame =
- static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
- scoped_refptr<DropStreamHandleConsumedFilter> filter =
- new DropStreamHandleConsumedFilter();
- main_frame->GetProcess()->AddFilter(filter.get());
-
- EXPECT_TRUE(NavigateToURL(shell(), url_2));
-
- // Check that the |stream_handle_| hasn't been released yet.
- EXPECT_NE(nullptr, main_frame->stream_handle_for_testing());
-
- // Make the renderer crash.
- RenderProcessHost* renderer_process = main_frame->GetProcess();
- RenderProcessHostWatcher crash_observer(
- renderer_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
- renderer_process->Shutdown(0);
- crash_observer.Wait();
-
- // The |stream_handle_| must have been released now.
- EXPECT_EQ(nullptr, main_frame->stream_handle_for_testing());
-}
-
namespace {
void PostRequestMonitor(int* post_counter,
const net::test_server::HttpRequest& request) {
@@ -1315,8 +1730,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
const GURL kUrl3(embedded_test_server()->GetURL("/title3.html"));
const GURL kUrl4(embedded_test_server()->GetURL("/empty.html"));
- // The 31-bit hash of the string "content::mojom::BrowserTarget".
- const int32_t kHashOfContentMojomBrowserTarget = 0x1CA01D37;
+ // The 31-bit hash of the string "content.mojom:BrowserTarget".
+ const int32_t kHashOfContentMojomBrowserTarget = 0x1730feb8;
// Client ends of the fake interface provider requests injected for the first
// and second navigations.
@@ -1348,9 +1763,9 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
// Simulate two interface requests corresponding to the first navigation
// arrived after the second navigation was committed, hence were dropped.
- interface_provider_1->GetInterface("content::mojom::BrowserTarget",
+ interface_provider_1->GetInterface("content.mojom.BrowserTarget",
CreateDisconnectedMessagePipeHandle());
- interface_provider_1->GetInterface("content::mojom::BrowserTarget",
+ interface_provider_1->GetInterface("content.mojom.BrowserTarget",
CreateDisconnectedMessagePipeHandle());
// RFHI destroys the DroppedInterfaceRequestLogger from navigation `n` on
@@ -1368,7 +1783,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
}
// Simulate one interface request dropped for the second URL.
- interface_provider_2->GetInterface("content::mojom::BrowserTarget",
+ interface_provider_2->GetInterface("content.mojom.BrowserTarget",
CreateDisconnectedMessagePipeHandle());
// A final navigation should record the sample from the second URL.
@@ -1384,9 +1799,9 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
// Both the DroppedInterfaceRequestLogger for the first and second URLs are
// destroyed -- even more interfacerequests should not cause any crashes.
- interface_provider_1->GetInterface("content::mojom::BrowserTarget",
+ interface_provider_1->GetInterface("content.mojom.BrowserTarget",
CreateDisconnectedMessagePipeHandle());
- interface_provider_2->GetInterface("content::mojom::BrowserTarget",
+ interface_provider_2->GetInterface("content.mojom.BrowserTarget",
CreateDisconnectedMessagePipeHandle());
// The interface connections should be broken.
@@ -1394,4 +1809,25 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
wait_until_connection_error_loop_2.Run();
}
+// Regression test for https://crbug.com/852350
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ GetCanonicalUrlAfterRendererCrash) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), GetTestUrl("render_frame_host", "beforeunload.html")));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHostImpl* main_frame =
+ static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
+
+ // Make the renderer crash.
+ RenderProcessHost* renderer_process = main_frame->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ renderer_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ renderer_process->Shutdown(0);
+ crash_observer.Wait();
+
+ main_frame->GetCanonicalUrlForSharing(base::DoNothing());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.cc b/chromium/content/browser/frame_host/render_frame_host_manager.cc
index d7875ac0c04..b682235b0f8 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -225,17 +225,22 @@ void RenderFrameHostManager::OnBeforeUnloadACK(
void RenderFrameHostManager::DidNavigateFrame(
RenderFrameHostImpl* render_frame_host,
- bool was_caused_by_user_gesture) {
- CommitPendingIfNecessary(render_frame_host, was_caused_by_user_gesture);
+ bool was_caused_by_user_gesture,
+ bool is_same_document_navigation) {
+ CommitPendingIfNecessary(render_frame_host, was_caused_by_user_gesture,
+ is_same_document_navigation);
// Make sure any dynamic changes to this frame's sandbox flags and feature
- // policy that were made prior to navigation take effect.
- CommitPendingFramePolicy();
+ // policy that were made prior to navigation take effect. This should only
+ // happen for cross-document navigations.
+ if (!is_same_document_navigation)
+ CommitPendingFramePolicy();
}
void RenderFrameHostManager::CommitPendingIfNecessary(
RenderFrameHostImpl* render_frame_host,
- bool was_caused_by_user_gesture) {
+ bool was_caused_by_user_gesture,
+ bool is_same_document_navigation) {
if (!speculative_render_frame_host_) {
// There's no speculative RenderFrameHost so it must be that the current
// renderer process completed a navigation.
@@ -267,11 +272,15 @@ void RenderFrameHostManager::CommitPendingIfNecessary(
if (render_frame_host_->pending_web_ui())
CommitPendingWebUI();
- // A navigation in the original page has taken place. Cancel the speculative
- // one. Only do it for user gesture originated navigations to prevent page
- // doing any shenanigans to prevent user from navigating. See
- // https://code.google.com/p/chromium/issues/detail?id=75195
- if (was_caused_by_user_gesture) {
+ // A navigation in the original process has taken place. This should
+ // cancel the ongoing cross-process navigation if the commit is
+ // cross-document and has a user gesture (since the user might have clicked
+ // on a new link while waiting for a slow navigation), but it should not
+ // cancel it for same-document navigations (which might happen as
+ // bookkeeping) or when there is no user gesture (which might abusively try
+ // to prevent the user from leaving). See https://crbug.com/825677 and
+ // https://crbug.com/75195 for examples.
+ if (!is_same_document_navigation && was_caused_by_user_gesture) {
frame_tree_node_->ResetNavigationRequest(false, true);
CleanUpNavigation();
}
@@ -514,12 +523,9 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// already updated its state properly, and doesn't need to be notified.
if (speculative_render_frame_host_->GetNavigationHandle() &&
request.from_begin_navigation()) {
- DCHECK(!speculative_render_frame_host_->GetNavigationHandle()
- ->IsDownload());
frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
speculative_render_frame_host_->GetNavigationHandle()
- ->pending_nav_entry_id(),
- false /* is_download */);
+ ->pending_nav_entry_id());
}
DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
}
@@ -556,12 +562,9 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
if (speculative_render_frame_host_ &&
speculative_render_frame_host_->GetNavigationHandle() &&
request.from_begin_navigation()) {
- DCHECK(!speculative_render_frame_host_->GetNavigationHandle()
- ->IsDownload());
frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
speculative_render_frame_host_->GetNavigationHandle()
- ->pending_nav_entry_id(),
- false /* is_download */);
+ ->pending_nav_entry_id());
}
// If a previous speculative RenderFrameHost didn't exist or if its
@@ -965,6 +968,7 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
SiteInstance* dest_instance,
SiteInstance* candidate_instance,
ui::PageTransition transition,
+ bool is_failure,
bool dest_is_restore,
bool dest_is_view_source_mode,
bool was_server_redirect) {
@@ -1024,7 +1028,7 @@ RenderFrameHostManager::GetSiteInstanceForNavigation(
if (ShouldTransitionCrossSite() || force_swap) {
new_instance_descriptor = DetermineSiteInstanceForURL(
dest_url, source_instance, current_instance, dest_instance, transition,
- dest_is_restore, dest_is_view_source_mode, force_swap,
+ is_failure, dest_is_restore, dest_is_view_source_mode, force_swap,
was_server_redirect);
}
@@ -1100,6 +1104,7 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
SiteInstance* current_instance,
SiteInstance* dest_instance,
ui::PageTransition transition,
+ bool is_failure,
bool dest_is_restore,
bool dest_is_view_source_mode,
bool force_browsing_instance_swap,
@@ -1126,20 +1131,16 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
return SiteInstanceDescriptor(browser_context, dest_url,
SiteInstanceRelation::UNRELATED);
- // (UGLY) HEURISTIC, process-per-site only:
- //
- // If this navigation is generated, then it probably corresponds to a search
- // query. Given that search results typically lead to users navigating to
- // other sites, we don't really want to use the search engine hostname to
- // determine the site instance for this navigation.
- //
- // NOTE: This can be removed once we have a way to transition between
- // RenderViews in response to a link click.
- //
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kProcessPerSite) &&
- ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_GENERATED)) {
- return SiteInstanceDescriptor(current_instance_impl);
+ // If error page navigations should be isolated, ensure a dedicated
+ // SiteInstance is used for them.
+ if (is_failure && SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ frame_tree_node_->IsMainFrame())) {
+ // Keep the error page in the same BrowsingInstance, such that in the case
+ // of transient network errors, a subsequent successful load of the same
+ // document will not result in broken scripting relationships between
+ // windows.
+ return SiteInstanceDescriptor(browser_context, GURL(kUnreachableWebDataURL),
+ SiteInstanceRelation::RELATED);
}
if (!frame_tree_node_->IsMainFrame()) {
@@ -1918,13 +1919,16 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
// marked as renderer-initiated are created by receiving a BeginNavigation
// IPC, and will then proceed in the same renderer. In site-per-process
// mode, it is possible for renderer-intiated navigations to be allowed to
- // go cross-process. Check it first.
+ // go cross-process. Main frame navigations resulting in an error are also
+ // expected to change process. Check it first.
bool can_renderer_initiate_transfer =
- render_frame_host_->IsRenderFrameLive() &&
- IsURLHandledByNetworkStack(request.common_params().url) &&
- IsRendererTransferNeededForNavigation(render_frame_host_.get(),
- request.common_params().url);
-
+ (request.state() == NavigationRequest::FAILED &&
+ SiteIsolationPolicy::IsErrorPageIsolationEnabled(
+ true /* in_main_frame */)) ||
+ (render_frame_host_->IsRenderFrameLive() &&
+ IsURLHandledByNetworkStack(request.common_params().url) &&
+ IsRendererTransferNeededForNavigation(render_frame_host_.get(),
+ request.common_params().url));
no_renderer_swap_allowed |=
request.from_begin_navigation() && !can_renderer_initiate_transfer;
} else {
@@ -1951,6 +1955,7 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
request.common_params().url, request.source_site_instance(),
request.dest_site_instance(), candidate_site_instance,
request.common_params().transition,
+ request.state() == NavigationRequest::FAILED,
request.restore_type() != RestoreType::NONE, request.is_view_source(),
was_server_redirect);
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.h b/chromium/content/browser/frame_host/render_frame_host_manager.h
index a6f58d99c33..e53920fc916 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -283,7 +283,8 @@ class CONTENT_EXPORT RenderFrameHostManager
// Called when a renderer's frame navigates.
void DidNavigateFrame(RenderFrameHostImpl* render_frame_host,
- bool was_caused_by_user_gesture);
+ bool was_caused_by_user_gesture,
+ bool is_same_document_navigation);
// Called when this frame's opener is changed to the frame specified by
// |opener_routing_id| in |source_site_instance|'s process. This change
@@ -569,6 +570,7 @@ class CONTENT_EXPORT RenderFrameHostManager
SiteInstance* dest_instance,
SiteInstance* candidate_instance,
ui::PageTransition transition,
+ bool is_failure,
bool dest_is_restore,
bool dest_is_view_source_mode,
bool was_server_redirect);
@@ -593,6 +595,7 @@ class CONTENT_EXPORT RenderFrameHostManager
SiteInstance* current_instance,
SiteInstance* dest_instance,
ui::PageTransition transition,
+ bool is_failure,
bool dest_is_restore,
bool dest_is_view_source_mode,
bool force_browsing_instance_swap,
@@ -691,7 +694,9 @@ class CONTENT_EXPORT RenderFrameHostManager
// Helper to call CommitPending() in all necessary cases.
void CommitPendingIfNecessary(RenderFrameHostImpl* render_frame_host,
- bool was_caused_by_user_gesture);
+ bool was_caused_by_user_gesture,
+ bool is_same_document_navigation);
+
// Commits any pending sandbox flag or feature policy updates when the
// renderer's frame navigates.
void CommitPendingFramePolicy();
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index 2a64b912f49..0828c4263a3 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -30,11 +30,11 @@
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/content_constants_internal.h"
-#include "content/common/input_messages.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
+#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_message_handler.h"
@@ -47,15 +47,19 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
+#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/request_handler_util.h"
+#include "net/test/url_request/url_request_failed_job.h"
+#include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
using base::ASCIIToUTF16;
@@ -173,6 +177,21 @@ class RenderFrameHostManagerTest : public ContentBrowserTest {
ASSERT_TRUE(embedded_test_server()->Start());
}
+ std::unique_ptr<content::URLLoaderInterceptor> SetupRequestFailForURL(
+ const GURL& url) {
+ return std::make_unique<content::URLLoaderInterceptor>(base::BindRepeating(
+ [](const GURL& url,
+ content::URLLoaderInterceptor::RequestParams* params) {
+ if (params->url_request.url != url)
+ return false;
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::ERR_DNS_TIMED_OUT;
+ params->client->OnComplete(status);
+ return true;
+ },
+ url));
+ }
+
// Returns a URL on foo.com with the given path.
GURL GetCrossSiteURL(const std::string& path) {
GURL cross_site_url(embedded_test_server()->GetURL(path));
@@ -1402,6 +1421,15 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerSpoofingTest,
embedded_test_server()->GetURL("/click-nocontent-link.html"));
WebContents* orig_contents = shell()->web_contents();
+ // Change the link to be cross-site.
+ GURL target_url = embedded_test_server()->GetURL("foo.com", "/nocontent");
+ ExecuteScript(
+ orig_contents,
+ base::StringPrintf(
+ "document.getElementById('nocontent_targeted_link').href = '%s';",
+ target_url.spec().c_str())
+ .c_str());
+
// Click a /nocontent link that opens in a new window but never commits.
ShellAddedObserver new_shell_observer;
ExecuteScript(orig_contents, "clickNoContentTargetedLink();");
@@ -1410,8 +1438,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerSpoofingTest,
Shell* new_shell = new_shell_observer.GetShell();
WebContents* contents = new_shell->web_contents();
- // Make sure the new window has started the provisional load, so the
- // associated navigation controller will have a visible entry.
+ // Make sure the new window has started the navigation, so the associated
+ // navigation controller will have a visible entry.
{
VisibleEntryWaiter waiter(contents);
waiter.Wait();
@@ -1420,8 +1448,65 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerSpoofingTest,
// Ensure the destination URL is visible, because it is considered the
// initial navigation.
EXPECT_TRUE(contents->GetController().IsInitialNavigation());
- EXPECT_EQ("/nocontent",
- contents->GetController().GetVisibleEntry()->GetURL().path());
+ EXPECT_EQ(target_url, contents->GetController().GetVisibleEntry()->GetURL());
+
+ // Now modify the contents of the new window from the opener. This will also
+ // modify the title of the document to give us something to listen for.
+ base::string16 expected_title = ASCIIToUTF16("Modified Title");
+ TitleWatcher title_watcher(orig_contents, expected_title);
+ ExecuteScript(orig_contents, "modifyNewWindow();");
+ ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ // At this point, we should no longer be showing the destination URL.
+ // The visible entry should be null, resulting in about:blank in the address
+ // bar.
+ EXPECT_FALSE(contents->GetController().GetVisibleEntry());
+}
+
+// Same as ShowLoadingURLUntilSpoof, but reloads the new popup before modifying
+// it, to test https://crbug.com/847718. The reload should not cause the
+// visible entry to stick around after the modification, even though it is
+// triggered in the browser process.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerSpoofingTest,
+ ShowLoadingURLUntilSpoofAfterReload) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Load a page that can open a URL that won't commit in a new window.
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("/click-nocontent-link.html"));
+ WebContents* orig_contents = shell()->web_contents();
+
+ // Change the link to be cross-site.
+ GURL target_url = embedded_test_server()->GetURL("foo.com", "/nocontent");
+ ExecuteScript(
+ orig_contents,
+ base::StringPrintf(
+ "document.getElementById('nocontent_targeted_link').href = '%s';",
+ target_url.spec().c_str())
+ .c_str());
+
+ // Click a /nocontent link that opens in a new window but never commits.
+ ShellAddedObserver new_shell_observer;
+ ExecuteScript(orig_contents, "clickNoContentTargetedLink();");
+
+ // Wait for the window to open.
+ Shell* new_shell = new_shell_observer.GetShell();
+ WebContents* contents = new_shell->web_contents();
+
+ // Make sure the new window has started the navigation, so the associated
+ // navigation controller will have a visible entry.
+ {
+ VisibleEntryWaiter waiter(contents);
+ waiter.Wait();
+ }
+
+ // Ensure the destination URL is visible, because it is considered the
+ // initial navigation.
+ EXPECT_TRUE(contents->GetController().IsInitialNavigation());
+ EXPECT_EQ(target_url, contents->GetController().GetVisibleEntry()->GetURL());
+
+ // Reload the popup before modifying it. See https://crbug.com/847718.
+ contents->GetController().Reload(ReloadType::NORMAL, false);
// Now modify the contents of the new window from the opener. This will also
// modify the title of the document to give us something to listen for.
@@ -2391,7 +2476,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, DontSelectInvalidFiles) {
// Use a file path with an invalid encoding, such that it can't be converted
// to a WebString (on all platforms but Windows).
base::FilePath file;
- EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file));
file = file.Append(FILE_PATH_LITERAL("foo\337bar"));
// Navigate and try to get page to reference this file in its PageState.
@@ -2449,7 +2534,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
RestoreFileAccessForHistoryNavigation) {
StartServer();
base::FilePath file;
- EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file));
file = file.AppendASCII("bar");
// Navigate to url and get it to reference a file in its PageState.
@@ -2511,7 +2596,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
RestoreSubframeFileAccessForHistoryNavigation) {
StartServer();
base::FilePath file;
- EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file));
file = file.AppendASCII("bar");
// Navigate to url and get it to reference a file in its PageState.
@@ -2592,9 +2677,10 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// https://crbug.com/620261.
std::unique_ptr<NavigationEntryImpl> cloned_entry =
NavigationEntryImpl::FromNavigationEntry(
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
url1, Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
- std::string(), shell()->web_contents()->GetBrowserContext()));
+ std::string(), shell()->web_contents()->GetBrowserContext(),
+ nullptr /* blob_url_loader_factory */));
prev_entry = shell()->web_contents()->GetController().GetEntryAtIndex(0);
cloned_entry->SetPageState(prev_entry->GetPageState());
const std::vector<base::FilePath>& cloned_files =
@@ -3982,4 +4068,408 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
}
}
+// Test to verify that navigations in the main frame, which result in an error
+// page, properly commit the error page in its own dedicated process.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationInMainFrame) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+
+ // Start with a successful navigation to a document.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ scoped_refptr<SiteInstance> success_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+
+ // Browser-initiated navigation to an error page should result in changing the
+ // SiteInstance and process.
+ {
+ NavigationHandleObserver observer(shell()->web_contents(), error_url);
+ EXPECT_FALSE(NavigateToURL(shell(), error_url));
+ EXPECT_TRUE(observer.is_error());
+ EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.net_error_code());
+
+ scoped_refptr<SiteInstance> error_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_NE(success_site_instance, error_site_instance);
+ EXPECT_TRUE(success_site_instance->IsRelatedSiteInstance(
+ error_site_instance.get()));
+ EXPECT_NE(success_site_instance->GetProcess()->GetID(),
+ error_site_instance->GetProcess()->GetID());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+
+ // Verify that the error page process is locked to origin
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ EXPECT_EQ(
+ GURL(kUnreachableWebDataURL),
+ policy->GetOriginLock(error_site_instance->GetProcess()->GetID()));
+ }
+
+ // Navigate successfully again to a document, then perform a
+ // renderer-initiated navigation and verify it behaves the same way.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ success_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+
+ {
+ NavigationHandleObserver observer(shell()->web_contents(), error_url);
+ TestFrameNavigationObserver frame_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "location.href = '" + error_url.spec() + "';"));
+ frame_observer.Wait();
+ EXPECT_TRUE(observer.is_error());
+ EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.net_error_code());
+
+ scoped_refptr<SiteInstance> error_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_NE(success_site_instance, error_site_instance);
+ EXPECT_TRUE(success_site_instance->IsRelatedSiteInstance(
+ error_site_instance.get()));
+ EXPECT_NE(success_site_instance->GetProcess()->GetID(),
+ error_site_instance->GetProcess()->GetID());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+ }
+}
+
+// Test to verify that navigations in subframes, which result in an error
+// page, commit the error page in the same process and not in the dedicated
+// error page process.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationInChildFrame) {
+ StartEmbeddedServer();
+ GURL url(embedded_test_server()->GetURL("/page_with_iframe.html"));
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+
+ // Start with a successful navigation to a document.
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+
+ FrameTreeNode* root = web_contents->GetFrameTree()->root();
+ FrameTreeNode* child = root->child_at(0);
+
+ scoped_refptr<SiteInstance> success_site_instance =
+ child->current_frame_host()->GetSiteInstance();
+
+ NavigationHandleObserver observer(web_contents, error_url);
+ TestFrameNavigationObserver frame_observer(child);
+ EXPECT_TRUE(
+ ExecuteScript(child, "location.href = '" + error_url.spec() + "';"));
+ frame_observer.Wait();
+
+ EXPECT_TRUE(observer.is_error());
+ EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.net_error_code());
+
+ scoped_refptr<SiteInstance> error_site_instance =
+ child->current_frame_host()->GetSiteInstance();
+ EXPECT_EQ(success_site_instance, error_site_instance);
+ EXPECT_NE(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+}
+
+// Test to verify that navigations in new window, which result in an error
+// page, commit the error page in the dedicated error page process and not in
+// the one for the destination site.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationInNewWindow) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+
+ // Start with a successful navigation to a document.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ scoped_refptr<SiteInstance> main_site_instance =
+ root->current_frame_host()->GetSiteInstance();
+
+ Shell* new_shell = OpenPopup(shell(), error_url, "foo");
+ EXPECT_TRUE(new_shell);
+
+ scoped_refptr<SiteInstance> error_site_instance =
+ new_shell->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_NE(main_site_instance, error_site_instance);
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+}
+
+// Test to verify that windows that are not part of the same
+// BrowsingInstance end up using the same error page process, even though
+// their SiteInstances are not related.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ErrorPageNavigationInUnrelatedWindows) {
+ // This test is only valid if error page isolation is enabled.
+ if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true))
+ return;
+
+ StartEmbeddedServer();
+ GURL error_url(embedded_test_server()->GetURL("/empty.html"));
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
+ SetupRequestFailForURL(error_url);
+
+ // Navigate the main window to an error page and verify.
+ {
+ NavigationHandleObserver observer(shell()->web_contents(), error_url);
+ EXPECT_FALSE(NavigateToURL(shell(), error_url));
+ scoped_refptr<SiteInstance> error_site_instance =
+ shell()->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_TRUE(observer.is_error());
+ EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.net_error_code());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+ }
+
+ // Creat a new, unrelated, window, navigate it to an error page and
+ // verify.
+ Shell* new_shell = CreateBrowser();
+ {
+ NavigationHandleObserver observer(new_shell->web_contents(), error_url);
+ EXPECT_FALSE(NavigateToURL(new_shell, error_url));
+ scoped_refptr<SiteInstance> error_site_instance =
+ new_shell->web_contents()->GetMainFrame()->GetSiteInstance();
+ EXPECT_TRUE(observer.is_error());
+ EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.net_error_code());
+ EXPECT_EQ(GURL(kUnreachableWebDataURL), error_site_instance->GetSiteURL());
+ }
+
+ // Verify the two SiteInstanes are not related, but they end up using the
+ // same underlying RenderProcessHost.
+ EXPECT_FALSE(
+ shell()->web_contents()->GetSiteInstance()->IsRelatedSiteInstance(
+ new_shell->web_contents()->GetSiteInstance()));
+ EXPECT_EQ(shell()->web_contents()->GetSiteInstance()->GetProcess(),
+ new_shell->web_contents()->GetSiteInstance()->GetProcess());
+}
+
+// Helper class to simplify testing of unload handlers. It allows waiting for
+// particular HTTP requests to be made to the embedded_test_server(); the tests
+// use this to wait for termination pings (e.g., navigator.sendBeacon()) made
+// from unload handlers.
+class RenderFrameHostManagerUnloadBrowserTest
+ : public RenderFrameHostManagerTest {
+ public:
+ RenderFrameHostManagerUnloadBrowserTest() {}
+
+ // Starts monitoring requests made to the embedded_http_server() looking for
+ // one made to |url|. To be used together with WaitForMonitoredRequest().
+ void StartMonitoringRequestsFor(const GURL& url) {
+ request_url_ = url;
+ saw_request_url_ = false;
+ }
+
+ // Waits for a request to a URL set earlier via StartMonitoringRequestsFor().
+ // Returns right away if that request was already made.
+ void WaitForMonitoredRequest() {
+ if (saw_request_url_)
+ return;
+
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ run_loop_.reset();
+ }
+
+ // Returns the body of the monitored request if it was a POST.
+ const std::string& GetRequestContent() { return request_content_; }
+
+ // Adds an unload handler to |rfh| and verifies that the unload state
+ // bookkeeping on |rfh| is updated properly.
+ void AddUnloadHandler(RenderFrameHostImpl* rfh, const std::string& script) {
+ EXPECT_FALSE(rfh->GetSuddenTerminationDisablerState(blink::kUnloadHandler));
+ EXPECT_TRUE(ExecuteScript(
+ rfh, base::StringPrintf("window.onunload = function(e) { %s }",
+ script.c_str())));
+ EXPECT_TRUE(rfh->GetSuddenTerminationDisablerState(blink::kUnloadHandler));
+ }
+
+ // Extend the timeout for keeping the subframe process alive for unload
+ // processing to prevent any test flakiness. This is the time that the ping
+ // request will have to make it from the renderer to the test server.
+ void ExtendSubframeUnloadTimeoutForTerminationPing(RenderFrameHostImpl* rfh) {
+ rfh->SetSubframeUnloadTimeoutForTesting(base::TimeDelta::FromSeconds(30));
+ }
+
+ protected:
+ void SetUpOnMainThread() override {
+ // Request interceptor needs to be installed before the test server is
+ // started.
+ embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
+ &RenderFrameHostManagerUnloadBrowserTest::MonitorResourceRequest,
+ base::Unretained(this)));
+
+ RenderFrameHostManagerTest::SetUpOnMainThread();
+
+ StartEmbeddedServer();
+ }
+
+ private:
+ void MonitorResourceRequest(const net::test_server::HttpRequest& request) {
+ // |request.GetURL()| gives us the URL after it's already resolved to
+ // 127.0.0.1, so reconstruct the requested host via the Host header (which
+ // includes host+port).
+ GURL requested_url = request.GetURL();
+ auto it = request.headers.find("Host");
+ if (it != request.headers.end())
+ requested_url = GURL("http://" + it->second + request.relative_url);
+
+ if (!saw_request_url_ && request_url_ == requested_url) {
+ saw_request_url_ = true;
+ request_content_ = request.content;
+ if (run_loop_)
+ run_loop_->Quit();
+ }
+ }
+
+ GURL request_url_;
+ std::string request_content_;
+ bool saw_request_url_ = false;
+ std::unique_ptr<base::RunLoop> run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManagerUnloadBrowserTest);
+};
+
+// Ensure that after a main frame with a cross-site iframe is itself navigated
+// cross-site, the unload handler in the iframe can use navigator.sendBeacon()
+// to do a termination ping. See https://crbug.com/852204, where this was
+// broken with site isolation if the iframe was in its own process.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
+ SubframeTerminationPing_SendBeacon) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ RenderFrameHostImpl* child_rfh = root->child_at(0)->current_frame_host();
+
+ // Add a subframe unload handler to do a termination ping via sendBeacon.
+ GURL ping_url(embedded_test_server()->GetURL("b.com", "/empty.html"));
+ AddUnloadHandler(child_rfh,
+ base::StringPrintf("navigator.sendBeacon('%s', 'ping');",
+ ping_url.spec().c_str()));
+ ExtendSubframeUnloadTimeoutForTerminationPing(child_rfh);
+
+ // Navigate the main frame to c.com and wait for the ping.
+ StartMonitoringRequestsFor(ping_url);
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), c_url));
+ // Test succeeds if this doesn't time out while waiting for |ping_url|.
+ WaitForMonitoredRequest();
+ EXPECT_EQ("ping", GetRequestContent());
+}
+
+// Ensure that after a main frame with a cross-site iframe is itself navigated
+// cross-site, the unload handler in the iframe can use an image load to do a
+// termination ping. See https://crbug.com/852204, where this was broken with
+// site isolation if the iframe was in its own process.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
+ SubframeTerminationPing_Image) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ RenderFrameHostImpl* child_rfh = root->child_at(0)->current_frame_host();
+
+ // Add a subframe unload handler to do a termination ping by loading an
+ // image.
+ GURL ping_url(embedded_test_server()->GetURL("b.com", "/blank.jpg"));
+ AddUnloadHandler(child_rfh,
+ base::StringPrintf("var img = document.createElement('img');"
+ "img.src = '%s';"
+ "document.body.appendChild(img);",
+ ping_url.spec().c_str()));
+ ExtendSubframeUnloadTimeoutForTerminationPing(child_rfh);
+
+ // Navigate the main frame to c.com and wait for the ping.
+ StartMonitoringRequestsFor(ping_url);
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), c_url));
+ // Test succeeds if this doesn't time out while waiting for |ping_url|.
+ WaitForMonitoredRequest();
+}
+
+// Ensure that when closing a window containing a page with a cross-site
+// iframe, the iframe still runs its unload handler and can do a sendBeacon
+// termination ping.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
+ SubframeTerminationPingWhenWindowCloses) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Open a popup window with a page containing a cross-site iframe.
+ GURL popup_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(c)"));
+ Shell* popup = OpenPopup(root, popup_url, "popup");
+ WebContentsImpl* popup_contents =
+ static_cast<WebContentsImpl*>(popup->web_contents());
+ EXPECT_TRUE(WaitForLoadStop(popup_contents));
+ EXPECT_EQ(popup_url, popup_contents->GetLastCommittedURL());
+
+ FrameTreeNode* popup_root = popup_contents->GetFrameTree()->root();
+ RenderFrameHostImpl* child_rfh =
+ popup_root->child_at(0)->current_frame_host();
+
+ // In the popup, add a subframe unload handler to do a termination ping via
+ // sendBeacon.
+ GURL ping_url(embedded_test_server()->GetURL("c.com", "/empty.html"));
+ AddUnloadHandler(child_rfh,
+ base::StringPrintf("navigator.sendBeacon('%s', 'ping');",
+ ping_url.spec().c_str()));
+ ExtendSubframeUnloadTimeoutForTerminationPing(child_rfh);
+
+ // Close the popup and wait for the ping.
+ StartMonitoringRequestsFor(ping_url);
+ popup->Close();
+ // Test succeeds if this doesn't time out while waiting for |ping_url|.
+ WaitForMonitoredRequest();
+ EXPECT_EQ("ping", GetRequestContent());
+}
+
+// Ensure that after a main frame with a cross-site iframe is navigated
+// cross-site, and the iframe had an unload handler which never finishes, the
+// iframe's process eventually exits.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerUnloadBrowserTest,
+ SubframeProcessGoesAwayAfterUnloadTimeout) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ RenderFrameHostImpl* child_rfh = root->child_at(0)->current_frame_host();
+
+ // Add an unload handler which never finishes to b.com subframe.
+ AddUnloadHandler(child_rfh, "while(1);");
+
+ // Navigate the main frame to c.com and wait for the subframe process to
+ // shut down. This should happen when the subframe unload timeout happens,
+ // roughly in one second. Note that depending on whether site isolation is
+ // enabled, the subframe process may or may not be the same as the old main
+ // frame process, but it should shut down regardless.
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ RenderProcessHostWatcher process_exit_observer(
+ child_rfh->GetProcess(),
+ RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ EXPECT_TRUE(NavigateToURL(shell(), c_url));
+ process_exit_observer.Wait();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
index 754c2d88c63..e1c1162d38b 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -11,6 +11,7 @@
#include <utility>
#include <vector>
+#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/macros.h"
@@ -31,12 +32,10 @@
#include "content/common/frame_owner_properties.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
+#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
@@ -50,7 +49,6 @@
#include "content/public/test/browser_side_navigation_test_utils.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/test_notification_tracker.h"
#include "content/public/test/test_utils.h"
#include "content/test/mock_widget_input_handler.h"
#include "content/test/test_content_browser_client.h"
@@ -317,7 +315,6 @@ class PluginFaviconMessageObserver : public WebContentsObserver {
class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
public:
void SetUp() override {
- mojo_feature_list_.InitAndEnableFeature(features::kMojoInputMessages);
RenderViewHostImplTestHarness::SetUp();
WebUIControllerFactory::RegisterFactory(&factory_);
}
@@ -464,7 +461,6 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
TestRenderFrameHost* frame_host = static_cast<TestRenderFrameHost*>(
manager->GetFrameHostForNavigation(*navigation_request));
CHECK(frame_host);
- frame_host->set_pending_commit(true);
return frame_host;
}
@@ -497,7 +493,6 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
RenderFrameHostManager*)>& commit_lambda);
private:
- base::test::ScopedFeatureList mojo_feature_list_;
RenderFrameHostManagerTestWebUIControllerFactory factory_;
};
@@ -767,19 +762,19 @@ TEST_F(RenderFrameHostManagerTest, ActiveFrameCountWhileSwappingInAndOut) {
class RenderViewHostDestroyer : public WebContentsObserver {
public:
RenderViewHostDestroyer(RenderViewHost* render_view_host,
- WebContents* web_contents)
+ std::unique_ptr<WebContents> web_contents)
: WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)),
render_view_host_(render_view_host),
- web_contents_(web_contents) {}
+ web_contents_(std::move(web_contents)) {}
void RenderViewDeleted(RenderViewHost* render_view_host) override {
if (render_view_host == render_view_host_)
- delete web_contents_;
+ web_contents_.reset();
}
private:
RenderViewHost* render_view_host_;
- WebContents* web_contents_;
+ std::unique_ptr<WebContents> web_contents_;
DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestroyer);
};
@@ -801,11 +796,11 @@ TEST_F(RenderFrameHostManagerTest,
// Create one more tab and navigate to kUrl1. web_contents is not
// wrapped as scoped_ptr since it intentionally deleted by destroyer
// below as part of this test.
- TestWebContents* web_contents =
+ std::unique_ptr<TestWebContents> web_contents =
TestWebContents::Create(browser_context(), ntp_rfh->GetSiteInstance());
web_contents->NavigateAndCommit(kUrl1);
RenderViewHostDestroyer destroyer(ntp_rfh->GetRenderViewHost(),
- web_contents);
+ std::move(web_contents));
// This causes the first tab to navigate to kUrl2, which destroys
// the ntp_rfh in ShutdownRenderViewHostsInSiteInstance(). When
@@ -919,7 +914,8 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
nullptr /* instance */, kUrl1, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
host = NavigateToEntry(manager, entry1);
// The RenderFrameHost created in Init will be reused.
@@ -927,7 +923,8 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
EXPECT_FALSE(GetPendingFrameHost(manager));
// Commit.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Commit to SiteInstance should be delayed until RenderFrame commit.
EXPECT_TRUE(host == manager->current_frame_host());
ASSERT_TRUE(host);
@@ -938,11 +935,11 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
// 2) Navigate to next site. -------------------------
const GURL kUrl2("http://www.google.com/foo");
- NavigationEntryImpl entry2(nullptr /* instance */, kUrl2,
- Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- true /* is_renderer_init */);
+ NavigationEntryImpl entry2(
+ nullptr /* instance */, kUrl2,
+ Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ true /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
host = NavigateToEntry(manager, entry2);
// The RenderFrameHost created in Init will be reused.
@@ -950,21 +947,23 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
EXPECT_FALSE(GetPendingFrameHost(manager));
// Commit.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_TRUE(host == manager->current_frame_host());
ASSERT_TRUE(host);
EXPECT_TRUE(host->GetSiteInstance()->HasSite());
+ ASSERT_TRUE(manager->GetRenderWidgetHostView()->GetBackgroundColor());
EXPECT_EQ(SK_ColorRED,
- manager->GetRenderWidgetHostView()->background_color());
+ *manager->GetRenderWidgetHostView()->GetBackgroundColor());
// 3) Cross-site navigate to next site. --------------
const GURL kUrl3("http://webkit.org/");
- NavigationEntryImpl entry3(nullptr /* instance */, kUrl3,
- Referrer(kUrl2, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entry3(
+ nullptr /* instance */, kUrl3,
+ Referrer(kUrl2, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
host = NavigateToEntry(manager, entry3);
// A new RenderFrameHost should be created.
@@ -974,7 +973,9 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
change_observer.Reset();
// Commit.
- manager->DidNavigateFrame(GetPendingFrameHost(manager), true);
+ manager->DidNavigateFrame(GetPendingFrameHost(manager),
+ true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_TRUE(host == manager->current_frame_host());
ASSERT_TRUE(host);
EXPECT_TRUE(host->GetSiteInstance()->HasSite());
@@ -984,8 +985,9 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
// We should observe RVH changed event.
EXPECT_TRUE(change_observer.DidHostChange());
+ ASSERT_TRUE(manager->GetRenderWidgetHostView()->GetBackgroundColor());
EXPECT_EQ(SK_ColorRED,
- manager->GetRenderWidgetHostView()->background_color());
+ *manager->GetRenderWidgetHostView()->GetBackgroundColor());
}
// Tests WebUI creation.
@@ -1006,7 +1008,8 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
const GURL kUrl("chrome://foo");
NavigationEntryImpl entry(
nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host = NavigateToEntry(manager, entry);
// We commit the pending RenderFrameHost immediately because the previous
@@ -1032,7 +1035,8 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
EXPECT_TRUE(manager->current_frame_host()->web_ui());
// Commit.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_TRUE(host->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
}
@@ -1060,7 +1064,8 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
const GURL kUrl1("chrome://foo");
NavigationEntryImpl entry1(
nullptr /* instance */, kUrl1, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host1 = NavigateToEntry(manager1, entry1);
// We should have a pending navigation to the WebUI RenderViewHost.
@@ -1070,7 +1075,8 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
EXPECT_TRUE(host1->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
// Commit and ensure we still have bindings.
- manager1->DidNavigateFrame(host1, true);
+ manager1->DidNavigateFrame(host1, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
SiteInstance* webui_instance = host1->GetSiteInstance();
EXPECT_EQ(host1, manager1->current_frame_host());
EXPECT_TRUE(host1->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
@@ -1090,7 +1096,8 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
const GURL kUrl2("chrome://foo/bar");
NavigationEntryImpl entry2(
nullptr /* instance */, kUrl2, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK, true /* is_renderer_init */);
+ ui::PAGE_TRANSITION_LINK, true /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host2 = NavigateToEntry(manager2, entry2);
// No cross-process transition happens because we are already in the right
@@ -1100,7 +1107,8 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
EXPECT_FALSE(host2->web_ui());
EXPECT_TRUE(host2->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
- manager2->DidNavigateFrame(host2, true);
+ manager2->DidNavigateFrame(host2, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
}
// Tests that a WebUI is correctly reused between chrome:// pages.
@@ -1508,7 +1516,8 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
nullptr /* instance */, kUrl1, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
host = NavigateToEntry(manager, entry1);
// The RenderFrameHost created in Init will be reused.
@@ -1517,7 +1526,8 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
EXPECT_EQ(manager->current_frame_host()->GetSiteInstance(), instance);
// Commit.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Commit to SiteInstance should be delayed until RenderFrame commit.
EXPECT_EQ(host, manager->current_frame_host());
ASSERT_TRUE(host);
@@ -1526,11 +1536,11 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
// 2) Navigate to a different domain. -------------------------
// Guests stay in the same process on navigation.
const GURL kUrl2("http://www.chromium.org");
- NavigationEntryImpl entry2(nullptr /* instance */, kUrl2,
- Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- true /* is_renderer_init */);
+ NavigationEntryImpl entry2(
+ nullptr /* instance */, kUrl2,
+ Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ true /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
host = NavigateToEntry(manager, entry2);
// The RenderFrameHost created in Init will be reused.
@@ -1538,17 +1548,35 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
EXPECT_FALSE(manager->speculative_frame_host());
// Commit.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(host, manager->current_frame_host());
ASSERT_TRUE(host);
EXPECT_EQ(host->GetSiteInstance(), instance);
}
+namespace {
+
+class WidgetDestructionObserver : public RenderWidgetHostObserver {
+ public:
+ explicit WidgetDestructionObserver(base::OnceClosure closure)
+ : closure_(std::move(closure)) {}
+
+ void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override {
+ std::move(closure_).Run();
+ }
+
+ private:
+ base::OnceClosure closure_;
+
+ DISALLOW_COPY_AND_ASSIGN(WidgetDestructionObserver);
+};
+
+} // namespace
+
// Test that we cancel a pending RVH if we close the tab while it's pending.
// http://crbug.com/294697.
TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
- TestNotificationTracker notifications;
-
scoped_refptr<SiteInstance> instance =
SiteInstance::Create(browser_context());
@@ -1564,7 +1592,8 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
nullptr /* instance */, kUrl1, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host = NavigateToEntry(manager, entry1);
// The RenderFrameHost created in Init will be reused.
@@ -1575,7 +1604,8 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
EXPECT_TRUE(change_observer.DidHostChange());
// Commit.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Commit to SiteInstance should be delayed until RenderFrame commits.
EXPECT_EQ(host, manager->current_frame_host());
@@ -1586,7 +1616,8 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
const GURL kUrl2("http://www.example.com");
NavigationEntryImpl entry2(
nullptr /* instance */, kUrl2, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host2 = NavigateToEntry(manager, entry2);
// A new RenderFrameHost should be created.
@@ -1597,13 +1628,13 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
EXPECT_EQ(host2, GetPendingFrameHost(manager));
// 3) Close the tab. -------------------------
- notifications.ListenFor(
- NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
- Source<RenderWidgetHost>(host2->render_view_host()->GetWidget()));
+ base::RunLoop run_loop;
+ WidgetDestructionObserver observer(run_loop.QuitClosure());
+ host2->render_view_host()->GetWidget()->AddObserver(&observer);
+
manager->OnBeforeUnloadACK(true, base::TimeTicks());
- EXPECT_TRUE(
- notifications.Check1AndReset(NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED));
+ run_loop.Run();
EXPECT_FALSE(GetPendingFrameHost(manager));
EXPECT_EQ(host, manager->current_frame_host());
}
@@ -1861,7 +1892,8 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation, DetachPendingChild) {
// 1) The first navigation.
NavigationEntryImpl entryA(
nullptr /* instance */, kUrlA, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host1 = NavigateToEntry(iframe1, entryA);
// The RenderFrameHost created in Init will be reused.
@@ -1869,18 +1901,19 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation, DetachPendingChild) {
EXPECT_FALSE(GetPendingFrameHost(iframe1));
// Commit.
- iframe1->DidNavigateFrame(host1, true);
+ iframe1->DidNavigateFrame(host1, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Commit to SiteInstance should be delayed until RenderFrame commit.
EXPECT_TRUE(host1 == iframe1->current_frame_host());
ASSERT_TRUE(host1);
EXPECT_TRUE(host1->GetSiteInstance()->HasSite());
// 2) Cross-site navigate both frames to next site.
- NavigationEntryImpl entryB(nullptr /* instance */, kUrlB,
- Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entryB(
+ nullptr /* instance */, kUrlB,
+ Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
host1 = NavigateToEntry(iframe1, entryB);
RenderFrameHostImpl* host2 = NavigateToEntry(iframe2, entryB);
@@ -1989,13 +2022,14 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
FrameOwnerProperties());
RenderFrameHostManager* iframe =
contents()->GetFrameTree()->root()->child_at(0)->render_manager();
- NavigationEntryImpl entry(nullptr /* instance */, kUrl2,
- Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entry(
+ nullptr /* instance */, kUrl2,
+ Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* cross_site = NavigateToEntry(iframe, entry);
- iframe->DidNavigateFrame(cross_site, true);
+ iframe->DidNavigateFrame(cross_site, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// A proxy to the iframe should now exist in the SiteInstance of the main
// frames.
@@ -2047,7 +2081,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
NavigationEntryImpl webui_entry(
nullptr /* instance */, kWebUIUrl, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
- false /* is_renderer_init */);
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
RenderFrameHostManager* main_rfhm = contents()->GetRenderManagerForTesting();
RenderFrameHostImpl* webui_rfh = NavigateToEntry(main_rfhm, webui_entry);
EXPECT_EQ(webui_rfh, GetPendingFrameHost(main_rfhm));
@@ -2059,7 +2093,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
NavigationEntryImpl subframe_entry(
nullptr /* instance */, kSubframeUrl, Referrer(),
base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* bar_rfh = NavigateToEntry(subframe_rfhm, subframe_entry);
EXPECT_FALSE(bar_rfh->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
}
@@ -2307,27 +2341,30 @@ TEST_F(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
RenderFrameHostManager* child3 = root->child_at(2)->render_manager();
// Navigate first two subframes to B.
- NavigationEntryImpl entryB(nullptr /* instance */, kUrlB,
- Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entryB(
+ nullptr /* instance */, kUrlB,
+ Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
TestRenderFrameHost* host1 =
static_cast<TestRenderFrameHost*>(NavigateToEntry(child1, entryB));
TestRenderFrameHost* host2 =
static_cast<TestRenderFrameHost*>(NavigateToEntry(child2, entryB));
- child1->DidNavigateFrame(host1, true);
- child2->DidNavigateFrame(host2, true);
+ child1->DidNavigateFrame(host1, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
+ child2->DidNavigateFrame(host2, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Navigate the third subframe to C.
- NavigationEntryImpl entryC(nullptr /* instance */, kUrlC,
- Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entryC(
+ nullptr /* instance */, kUrlC,
+ Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
TestRenderFrameHost* host3 =
static_cast<TestRenderFrameHost*>(NavigateToEntry(child3, entryC));
- child3->DidNavigateFrame(host3, true);
+ child3->DidNavigateFrame(host3, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Make sure the first two subframes and the third subframe are placed in
// distinct processes.
@@ -2398,28 +2435,30 @@ TEST_F(RenderFrameHostManagerTest,
RenderFrameHostManager* child = root->child_at(0)->render_manager();
// Navigate subframe to B.
- NavigationEntryImpl entryB(nullptr /* instance */, kUrlB,
- Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entryB(
+ nullptr /* instance */, kUrlB,
+ Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
TestRenderFrameHost* hostB =
static_cast<TestRenderFrameHost*>(NavigateToEntry(child, entryB));
- child->DidNavigateFrame(hostB, true);
+ child->DidNavigateFrame(hostB, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Ensure that the main page is focused.
main_test_rfh()->GetView()->Focus();
EXPECT_TRUE(main_test_rfh()->GetView()->HasFocus());
// Navigate the subframe to C.
- NavigationEntryImpl entryC(nullptr /* instance */, kUrlC,
- Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entryC(
+ nullptr /* instance */, kUrlC,
+ Referrer(kUrlA, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
TestRenderFrameHost* hostC =
static_cast<TestRenderFrameHost*>(NavigateToEntry(child, entryC));
- child->DidNavigateFrame(hostC, true);
+ child->DidNavigateFrame(hostC, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// The main frame should now have a proxy for C.
RenderFrameProxyHost* proxy =
@@ -2448,9 +2487,9 @@ TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
// Setup a restored entry.
std::vector<std::unique_ptr<NavigationEntry>> entries;
std::unique_ptr<NavigationEntry> new_entry =
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
kInitUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, false, std::string(),
- browser_context());
+ browser_context(), nullptr /* blob_url_loader_factory */);
entries.push_back(std::move(new_entry));
controller.Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -2462,10 +2501,10 @@ TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
EXPECT_FALSE(initial_host->web_ui());
// Navigation request to an entry from a previous browsing session.
- NavigationEntryImpl entry(nullptr /* instance */, kInitUrl,
- Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_RELOAD,
- false /* is_renderer_init */);
+ NavigationEntryImpl entry(
+ nullptr /* instance */, kInitUrl, Referrer(),
+ base::string16() /* title */, ui::PAGE_TRANSITION_RELOAD,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
entry.set_restore_type(RestoreType::LAST_SESSION_EXITED_CLEANLY);
NavigateToEntry(manager, entry);
@@ -2483,7 +2522,8 @@ TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
EXPECT_FALSE(current_host->web_ui());
// The RenderFrameHost committed.
- manager->DidNavigateFrame(current_host, true);
+ manager->DidNavigateFrame(current_host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(current_host, manager->current_frame_host());
EXPECT_EQ(web_ui, current_host->web_ui());
EXPECT_FALSE(current_host->pending_web_ui());
@@ -2519,7 +2559,8 @@ void RenderFrameHostManagerTest::BaseSimultaneousNavigationWithOneWebUI(
const GURL kUrl("http://google.com");
NavigationEntryImpl entry(
nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host2 = NavigateToEntry(manager, entry);
ASSERT_TRUE(host2);
@@ -2549,7 +2590,8 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithOneWebUI1) {
RenderFrameHostImpl* host1, RenderFrameHostImpl* host2, WebUIImpl* web_ui,
RenderFrameHostManager* manager) {
// The current RenderFrameHost commits; its WebUI should still be in place.
- manager->DidNavigateFrame(host1, true);
+ manager->DidNavigateFrame(host1, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(host1, manager->current_frame_host());
EXPECT_EQ(web_ui, host1->web_ui());
EXPECT_FALSE(host1->pending_web_ui());
@@ -2567,7 +2609,8 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithOneWebUI2) {
RenderFrameHostImpl* host1, RenderFrameHostImpl* host2, WebUIImpl* web_ui,
RenderFrameHostManager* manager) {
// The new RenderFrameHost commits; there should be no active WebUI.
- manager->DidNavigateFrame(host2, true);
+ manager->DidNavigateFrame(host2, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(host2, manager->current_frame_host());
EXPECT_FALSE(host2->web_ui());
EXPECT_FALSE(host2->pending_web_ui());
@@ -2610,7 +2653,8 @@ void RenderFrameHostManagerTest::BaseSimultaneousNavigationWithTwoWebUIs(
const GURL kUrl("chrome://bar/");
NavigationEntryImpl entry(
nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */);
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
RenderFrameHostImpl* host2 = NavigateToEntry(manager, entry);
ASSERT_TRUE(host2);
@@ -2642,7 +2686,8 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs1) {
RenderFrameHostImpl* host1, RenderFrameHostImpl* host2,
WebUIImpl* web_ui1, WebUIImpl* web_ui2, RenderFrameHostManager* manager) {
// The current RenderFrameHost commits; its WebUI should still be active.
- manager->DidNavigateFrame(host1, true);
+ manager->DidNavigateFrame(host1, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(host1, manager->current_frame_host());
EXPECT_EQ(web_ui1, host1->web_ui());
EXPECT_FALSE(host1->pending_web_ui());
@@ -2660,7 +2705,8 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs2) {
RenderFrameHostImpl* host1, RenderFrameHostImpl* host2,
WebUIImpl* web_ui1, WebUIImpl* web_ui2, RenderFrameHostManager* manager) {
// The new RenderFrameHost commits; its WebUI should now be active.
- manager->DidNavigateFrame(host2, true);
+ manager->DidNavigateFrame(host2, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(host2, manager->current_frame_host());
EXPECT_EQ(web_ui2, host2->web_ui());
EXPECT_FALSE(host2->pending_web_ui());
@@ -2754,10 +2800,10 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// Navigation request.
const GURL kUrl("chrome://foo");
- NavigationEntryImpl entry(nullptr /* instance */, kUrl,
- Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED,
- false /* is_renderer_init */);
+ NavigationEntryImpl entry(
+ nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get();
std::unique_ptr<NavigationRequest> navigation_request =
NavigationRequest::CreateBrowserInitiated(
@@ -2792,7 +2838,8 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
EXPECT_FALSE(GetPendingFrameHost(manager));
// The RenderFrameHost committed.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(host, manager->current_frame_host());
EXPECT_FALSE(GetPendingFrameHost(manager));
EXPECT_EQ(web_ui, host->web_ui());
@@ -2815,10 +2862,10 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// Navigation request. No change in the returned WebUI type.
const GURL kUrl("chrome://foo/bar");
- NavigationEntryImpl entry(nullptr /* instance */, kUrl,
- Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED,
- false /* is_renderer_init */);
+ NavigationEntryImpl entry(
+ nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get();
std::unique_ptr<NavigationRequest> navigation_request =
NavigationRequest::CreateBrowserInitiated(
@@ -2845,7 +2892,8 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
EXPECT_FALSE(GetPendingFrameHost(manager));
// The RenderFrameHost committed.
- manager->DidNavigateFrame(host, true);
+ manager->DidNavigateFrame(host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(web_ui, host->web_ui());
EXPECT_FALSE(manager->GetNavigatingWebUI());
EXPECT_FALSE(host->pending_web_ui());
@@ -2873,10 +2921,10 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
// Navigation request.
const GURL kUrl("chrome://bar");
- NavigationEntryImpl entry(nullptr /* instance */, kUrl,
- Referrer(), base::string16() /* title */,
- ui::PAGE_TRANSITION_TYPED,
- false /* is_renderer_init */);
+ NavigationEntryImpl entry(
+ nullptr /* instance */, kUrl, Referrer(), base::string16() /* title */,
+ ui::PAGE_TRANSITION_TYPED, false /* is_renderer_init */,
+ nullptr /* blob_url_loader_factory */);
FrameNavigationEntry* frame_entry = entry.root_node()->frame_entry.get();
std::unique_ptr<NavigationRequest> navigation_request =
NavigationRequest::CreateBrowserInitiated(
@@ -2912,7 +2960,9 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
EXPECT_FALSE(speculative_host->pending_web_ui());
// The RenderFrameHost committed.
- manager->DidNavigateFrame(speculative_host, true);
+ manager->DidNavigateFrame(speculative_host,
+ true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
EXPECT_EQ(speculative_host, manager->current_frame_host());
EXPECT_EQ(next_web_ui, manager->current_frame_host()->web_ui());
EXPECT_FALSE(GetPendingFrameHost(manager));
@@ -2942,14 +2992,15 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
RenderFrameHostManager* child = root->child_at(0)->render_manager();
// Navigate subframe to kUrl2.
- NavigationEntryImpl entry1(nullptr /* instance */, kUrl2,
- Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
- base::string16() /* title */,
- ui::PAGE_TRANSITION_LINK,
- false /* is_renderer_init */);
+ NavigationEntryImpl entry1(
+ nullptr /* instance */, kUrl2,
+ Referrer(kUrl1, blink::kWebReferrerPolicyDefault),
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
+ false /* is_renderer_init */, nullptr /* blob_url_loader_factory */);
TestRenderFrameHost* child_host =
static_cast<TestRenderFrameHost*>(NavigateToEntry(child, entry1));
- child->DidNavigateFrame(child_host, true);
+ child->DidNavigateFrame(child_host, true /* was_caused_by_user_gesture */,
+ false /* is_same_document_navigation */);
// Verify that parent and child are in different processes.
EXPECT_NE(child_host->GetProcess(), main_test_rfh()->GetProcess());
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.cc b/chromium/content/browser/frame_host/render_frame_message_filter.cc
index 80fd7cf8957..91bf248a67a 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -13,6 +13,7 @@
#include "base/debug/alias.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
+#include "base/syslog_logging.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "components/download/public/common/download_url_parameters.h"
@@ -96,9 +97,13 @@ void CreateChildFrameOnUI(
}
}
+// |blob_data_handle| is only here for the legacy code path. With network
+// service enabled |blob_url_token| should be provided and will be used instead
+// to download the correct blob.
void DownloadUrlOnUIThread(
std::unique_ptr<download::DownloadUrlParameters> parameters,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle) {
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ blink::mojom::BlobURLTokenPtrInfo blob_url_token) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* render_process_host =
@@ -107,11 +112,21 @@ void DownloadUrlOnUIThread(
return;
BrowserContext* browser_context = render_process_host->GetBrowserContext();
+
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
+ if (blob_url_token) {
+ blob_url_loader_factory =
+ ChromeBlobStorageContext::URLLoaderFactoryForToken(
+ browser_context,
+ blink::mojom::BlobURLTokenPtr(std::move(blob_url_token)));
+ }
+
DownloadManager* download_manager =
BrowserContext::GetDownloadManager(browser_context);
parameters->set_download_source(download::DownloadSource::FROM_RENDERER);
download_manager->DownloadUrl(std::move(parameters),
- std::move(blob_data_handle));
+ std::move(blob_data_handle),
+ std::move(blob_url_loader_factory));
}
// Common functionality for converting a sync renderer message to a callback
@@ -296,13 +311,15 @@ void RenderFrameMessageFilter::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
-void RenderFrameMessageFilter::DownloadUrl(int render_view_id,
- int render_frame_id,
- const GURL& url,
- const Referrer& referrer,
- const url::Origin& initiator,
- const base::string16& suggested_name,
- const bool use_prompt) const {
+void RenderFrameMessageFilter::DownloadUrl(
+ int render_view_id,
+ int render_frame_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const url::Origin& initiator,
+ const base::string16& suggested_name,
+ const bool use_prompt,
+ blink::mojom::BlobURLTokenPtrInfo blob_url_token) const {
if (!resource_context_)
return;
@@ -343,6 +360,10 @@ void RenderFrameMessageFilter::DownloadUrl(int render_view_id,
Referrer::ReferrerPolicyForUrlRequest(referrer.policy));
parameters->set_initiator(initiator);
+ // If network service is enabled we should always have a |blob_url_token|,
+ // which will be used to download the correct blob. But in the legacy
+ // non-network service code path we still need to look up the BlobDataHandle
+ // for the URL here, to make sure the correct blob ends up getting downloaded.
std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
if (url.SchemeIsBlob()) {
ChromeBlobStorageContext* blob_context =
@@ -355,7 +376,7 @@ void RenderFrameMessageFilter::DownloadUrl(int render_view_id,
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&DownloadUrlOnUIThread, std::move(parameters),
- std::move(blob_data_handle)));
+ std::move(blob_data_handle), std::move(blob_url_token)));
}
void RenderFrameMessageFilter::OnCreateChildFrame(
@@ -414,9 +435,18 @@ void RenderFrameMessageFilter::CheckPolicyForCookies(
void RenderFrameMessageFilter::OnDownloadUrl(
const FrameHostMsg_DownloadUrl_Params& params) {
+ mojo::ScopedMessagePipeHandle blob_url_token_handle(params.blob_url_token);
+ blink::mojom::BlobURLTokenPtrInfo blob_url_token(
+ std::move(blob_url_token_handle), blink::mojom::BlobURLToken::Version_);
+ if (blob_url_token && !params.url.SchemeIsBlob()) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::RFMF_BLOB_URL_TOKEN_FOR_NON_BLOB_URL);
+ return;
+ }
+
DownloadUrl(params.render_view_id, params.render_frame_id, params.url,
params.referrer, params.initiator_origin, params.suggested_name,
- false);
+ false, std::move(blob_url_token));
}
void RenderFrameMessageFilter::OnSaveImageFromDataURL(
@@ -432,7 +462,7 @@ void RenderFrameMessageFilter::OnSaveImageFromDataURL(
return;
DownloadUrl(render_view_id, render_frame_id, data_url, Referrer(),
- url::Origin(), base::string16(), true);
+ url::Origin(), base::string16(), true, nullptr);
}
void RenderFrameMessageFilter::OnAre3DAPIsBlocked(int render_frame_id,
@@ -461,8 +491,11 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
if (!policy->CanAccessDataForOrigin(render_process_id_, url)) {
- bad_message::ReceivedBadMessage(this,
- bad_message::RFMF_SET_COOKIE_BAD_ORIGIN);
+ bad_message::BadMessageReason reason =
+ bad_message::RFMF_SET_COOKIE_BAD_ORIGIN;
+ SYSLOG(WARNING) << "Killing renderer: illegal cookie write. Reason: "
+ << reason;
+ bad_message::ReceivedBadMessage(this, reason);
return;
}
@@ -502,8 +535,11 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
if (!policy->CanAccessDataForOrigin(render_process_id_, url)) {
- bad_message::ReceivedBadMessage(this,
- bad_message::RFMF_GET_COOKIES_BAD_ORIGIN);
+ bad_message::BadMessageReason reason =
+ bad_message::RFMF_GET_COOKIES_BAD_ORIGIN;
+ SYSLOG(WARNING) << "Killing renderer: illegal cookie read. Reason: "
+ << reason;
+ bad_message::ReceivedBadMessage(this, reason);
std::move(callback).Run(std::string());
return;
}
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.h b/chromium/content/browser/frame_host/render_frame_message_filter.h
index 871e11f6127..7f3ab224bd1 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -18,6 +18,7 @@
#include "net/cookies/canonical_cookie.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/network/public/mojom/network_service.mojom.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
#include "third_party/blink/public/web/web_tree_scope_type.h"
#include "url/origin.h"
@@ -76,13 +77,15 @@ class CONTENT_EXPORT RenderFrameMessageFilter
friend class TestSaveImageFromDataURL;
// This method will be overridden by TestSaveImageFromDataURL class for test.
- virtual void DownloadUrl(int render_view_id,
- int render_frame_id,
- const GURL& url,
- const Referrer& referrer,
- const url::Origin& initiator,
- const base::string16& suggested_name,
- const bool use_prompt) const;
+ virtual void DownloadUrl(
+ int render_view_id,
+ int render_frame_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const url::Origin& initiator,
+ const base::string16& suggested_name,
+ const bool use_prompt,
+ blink::mojom::BlobURLTokenPtrInfo blob_url_token) const;
private:
friend class BrowserThread;
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.cc b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
index b44b0fd799e..838bc1e20c3 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "content/browser/bad_message.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/frame_tree.h"
@@ -246,6 +247,12 @@ void RenderFrameProxyHost::ScrollRectToVisible(
Send(new FrameMsg_ScrollRectToVisible(routing_id_, rect_to_scroll, params));
}
+void RenderFrameProxyHost::BubbleLogicalScroll(
+ blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity) {
+ Send(new FrameMsg_BubbleLogicalScroll(routing_id_, direction, granularity));
+}
+
void RenderFrameProxyHost::SetDestructionCallback(
DestructionCallback destruction_callback) {
destruction_callback_ = std::move(destruction_callback);
@@ -275,6 +282,22 @@ void RenderFrameProxyHost::OnOpenURL(
GURL validated_url(params.url);
GetProcess()->FilterURL(false, &validated_url);
+ mojo::ScopedMessagePipeHandle blob_url_token_handle(params.blob_url_token);
+ blink::mojom::BlobURLTokenPtr blob_url_token(
+ blink::mojom::BlobURLTokenPtrInfo(std::move(blob_url_token_handle),
+ blink::mojom::BlobURLToken::Version_));
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
+ if (blob_url_token) {
+ if (!params.url.SchemeIsBlob()) {
+ bad_message::ReceivedBadMessage(
+ GetProcess(), bad_message::RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL);
+ return;
+ }
+ blob_url_loader_factory =
+ ChromeBlobStorageContext::URLLoaderFactoryForToken(
+ GetSiteInstance()->GetBrowserContext(), std::move(blob_url_token));
+ }
+
// Verify that we are in the same BrowsingInstance as the current
// RenderFrameHost.
RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();
@@ -300,12 +323,13 @@ void RenderFrameProxyHost::OnOpenURL(
// RequestTransferURL method once both RenderFrameProxyHost and
// RenderFrameHostImpl call RequestOpenURL from their OnOpenURL handlers.
// See also https://crbug.com/647772.
- frame_tree_node_->navigator()->RequestTransferURL(
- current_rfh, validated_url, site_instance_.get(), std::vector<GURL>(),
- params.referrer, ui::PAGE_TRANSITION_LINK, GlobalRequestID(),
- params.should_replace_current_entry, params.uses_post ? "POST" : "GET",
- params.resource_request_body, params.extra_headers,
- params.suggested_filename);
+ // TODO(clamy): The transition should probably be changed for POST navigations
+ // to PAGE_TRANSITION_FORM_SUBMIT. See https://crbug.com/829827.
+ frame_tree_node_->navigator()->NavigateFromFrameProxy(
+ current_rfh, validated_url, site_instance_.get(), params.referrer,
+ ui::PAGE_TRANSITION_LINK, params.should_replace_current_entry,
+ params.uses_post ? "POST" : "GET", params.resource_request_body,
+ params.extra_headers, std::move(blob_url_loader_factory));
}
void RenderFrameProxyHost::OnCheckCompleted() {
@@ -340,6 +364,23 @@ void RenderFrameProxyHost::OnRouteMessageEvent(
if (!source_rfh) {
new_params.source_routing_id = MSG_ROUTING_NONE;
} else {
+ // https://crbug.com/822958: If the postMessage is going to a descendant
+ // frame, ensure that any pending visual properties such as size are sent
+ // to the target frame before the postMessage, as sites might implicitly
+ // be relying on this ordering.
+ bool target_is_descendant_of_source = false;
+ for (FrameTreeNode* node = target_rfh->frame_tree_node(); node;
+ node = node->parent()) {
+ if (node == source_rfh->frame_tree_node()) {
+ target_is_descendant_of_source = true;
+ break;
+ }
+ }
+ if (target_is_descendant_of_source) {
+ target_rfh->GetRenderWidgetHost()
+ ->SynchronizeVisualPropertiesIgnoringPendingAck();
+ }
+
// Ensure that we have a swapped-out RVH and proxy for the source frame
// in the target SiteInstance. If it doesn't exist, create it on demand
// and also create its opener chain, since that will also be accessible
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.h b/chromium/content/browser/frame_host/render_frame_proxy_host.h
index 17869ebf616..76590d42945 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.h
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.h
@@ -15,6 +15,7 @@
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "third_party/blink/public/platform/web_focus_type.h"
+#include "third_party/blink/public/platform/web_scroll_types.h"
struct FrameHostMsg_OpenURL_Params;
struct FrameMsg_PostMessage_Params;
@@ -131,6 +132,11 @@ class RenderFrameProxyHost
void ScrollRectToVisible(const gfx::Rect& rect_to_scroll,
const blink::WebScrollIntoViewParams& params);
+ // Continues to bubble a logical scroll from the frame's process. Bubbling
+ // continues from the frame owner element in the parent process.
+ void BubbleLogicalScroll(blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity);
+
void set_render_frame_proxy_created(bool created) {
render_frame_proxy_created_ = created;
}
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
index 839017d8fee..a0bc38e7f05 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -10,7 +10,6 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
@@ -97,6 +96,10 @@ RenderWidgetHostViewBase* RenderWidgetHostViewGuest::GetRootView(
return rwhv;
}
+RenderWidgetHostViewBase* RenderWidgetHostViewGuest::GetParentView() {
+ return GetOwnerRenderWidgetHostView();
+}
+
RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
RenderWidgetHost* widget_host,
BrowserPluginGuest* guest,
@@ -246,8 +249,11 @@ gfx::Rect RenderWidgetHostViewGuest::GetBoundsInRootWindow() {
gfx::PointF RenderWidgetHostViewGuest::TransformPointToRootCoordSpaceF(
const gfx::PointF& point) {
- if (!guest_ || !last_received_local_surface_id_.is_valid())
+ // LocalSurfaceId is not needed in Viz hit-test.
+ if (!guest_ ||
+ (!use_viz_hit_test_ && !last_received_local_surface_id_.is_valid())) {
return point;
+ }
RenderWidgetHostViewBase* root_rwhv = GetRootView(this);
if (!root_rwhv)
@@ -266,7 +272,7 @@ gfx::PointF RenderWidgetHostViewGuest::TransformPointToRootCoordSpaceF(
return transformed_point;
}
-bool RenderWidgetHostViewGuest::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewGuest::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
@@ -371,6 +377,13 @@ void RenderWidgetHostViewGuest::SendSurfaceInfoToEmbedderImpl(
guest_->SetChildFrameSurface(surface_info);
}
+void RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata) {
+ if (guest_)
+ guest_->DidUpdateVisualProperties(metadata);
+ host()->SynchronizeVisualProperties();
+}
+
void RenderWidgetHostViewGuest::OnAttached() {
RegisterFrameSinkId();
#if defined(USE_AURA)
@@ -548,6 +561,13 @@ void RenderWidgetHostViewGuest::UnlockMouse() {
platform_view_->UnlockMouse();
}
+viz::FrameSinkId RenderWidgetHostViewGuest::GetRootFrameSinkId() {
+ RenderWidgetHostViewBase* root_rwhv = GetRootView(this);
+ if (root_rwhv)
+ return root_rwhv->GetRootFrameSinkId();
+ return viz::FrameSinkId();
+}
+
viz::LocalSurfaceId RenderWidgetHostViewGuest::GetLocalSurfaceId() const {
if (guest_)
return guest_->local_surface_id();
@@ -605,8 +625,7 @@ void RenderWidgetHostViewGuest::MaybeSendSyntheticTapGesture(
GetOwnerRenderWidgetHostView()->GetBoundsInRootWindow().origin();
blink::WebGestureEvent gesture_tap_event(
blink::WebGestureEvent::kGestureTapDown,
- blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()),
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow(),
blink::kWebGestureDeviceTouchscreen);
gesture_tap_event.SetPositionInWidget(
blink::WebFloatPoint(position.x + offset.x(), position.y + offset.y()));
@@ -689,16 +708,12 @@ void RenderWidgetHostViewGuest::DisableAutoResize(const gfx::Size& new_size) {
guest_->DisableAutoResize();
}
-viz::ScopedSurfaceIdAllocator RenderWidgetHostViewGuest::ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
- // TODO(cblume): This doesn't currently suppress allocation.
- // It maintains existing behavior while using the suppression style.
- // This will be addressed in a follow-up patch.
- // See https://crbug.com/805073
- base::OnceCallback<void()> allocation_task =
- base::BindOnce(&BrowserPluginGuest::ResizeDueToAutoResize, guest_,
- new_size, sequence_number);
+viz::ScopedSurfaceIdAllocator
+RenderWidgetHostViewGuest::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
+ base::OnceCallback<void()> allocation_task = base::BindOnce(
+ &RenderWidgetHostViewGuest::OnDidUpdateVisualPropertiesComplete,
+ weak_ptr_factory_.GetWeakPtr(), metadata);
return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
}
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest.h b/chromium/content/browser/frame_host/render_widget_host_view_guest.h
index 374694e7faf..1e2687b945e 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest.h
@@ -62,6 +62,9 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
// Called when this RenderWidgetHostViewGuest is attached.
void OnAttached();
+ // RenderWidgetHostViewChildFrame implementation.
+ RenderWidgetHostViewBase* GetParentView() override;
+
// RenderWidgetHostView implementation.
bool OnMessageReceived(const IPC::Message& msg) override;
void InitAsChild(gfx::NativeView parent_view) override;
@@ -82,9 +85,10 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
GetTouchSelectionControllerClientManager() override;
gfx::PointF TransformPointToRootCoordSpaceF(
const gfx::PointF& point) override;
- bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
- const viz::SurfaceId& original_surface,
- gfx::PointF* transformed_point) override;
+ bool TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point) override;
gfx::PointF TransformRootPointToViewCoordSpace(
const gfx::PointF& point) override;
@@ -121,6 +125,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
void DidStopFlinging() override;
bool LockMouse() override;
void UnlockMouse() override;
+ viz::FrameSinkId GetRootFrameSinkId() override;
viz::LocalSurfaceId GetLocalSurfaceId() const override;
void DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
@@ -151,9 +156,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
const gfx::Size& max_size) override;
void DisableAutoResize(const gfx::Size& new_size) override;
- viz::ScopedSurfaceIdAllocator ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) override;
+ viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) override;
private:
friend class RenderWidgetHostView;
@@ -161,6 +165,9 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
void SendSurfaceInfoToEmbedderImpl(
const viz::SurfaceInfo& surface_info) override;
+ void OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata);
+
RenderWidgetHostViewGuest(
RenderWidgetHost* widget,
BrowserPluginGuest* guest,
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index 90579b1591c..8c69857ab3f 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -12,6 +12,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
@@ -147,8 +148,7 @@ class RenderWidgetHostViewGuestSurfaceTest
browser_context_.reset(new TestBrowserContext);
MockRenderProcessHost* process_host =
new MockRenderProcessHost(browser_context_.get());
- web_contents_.reset(
- TestWebContents::Create(browser_context_.get(), nullptr));
+ web_contents_ = TestWebContents::Create(browser_context_.get(), nullptr);
// We don't own the BPG, the WebContents does.
browser_plugin_guest_ = new TestBrowserPluginGuest(
web_contents_.get(), &browser_plugin_guest_delegate_);
@@ -199,7 +199,6 @@ class RenderWidgetHostViewGuestSurfaceTest
}
protected:
- ScopedMockRenderProcessHostFactory rph_factory_;
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<BrowserContext> browser_context_;
MockRenderWidgetHostDelegate delegate_;
@@ -237,9 +236,12 @@ viz::CompositorFrame CreateDelegatedFrame(float scale_factor,
} // anonymous namespace
TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
+ // https://crbug.com/844469
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ base::FeatureList::IsEnabled(features::kMash)) {
return;
+ }
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
@@ -254,7 +256,7 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
browser_plugin_guest_->set_attached(true);
view_->SubmitCompositorFrame(
local_surface_id,
- CreateDelegatedFrame(scale_factor, view_size, view_rect), nullptr);
+ CreateDelegatedFrame(scale_factor, view_size, view_rect), base::nullopt);
viz::SurfaceId id = GetSurfaceId();
@@ -278,7 +280,7 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
view_->SubmitCompositorFrame(
local_surface_id,
- CreateDelegatedFrame(scale_factor, view_size, view_rect), nullptr);
+ CreateDelegatedFrame(scale_factor, view_size, view_rect), base::nullopt);
// Since we have not changed the frame size and scale factor, the same surface
// id must be used.
diff --git a/chromium/content/browser/frame_host/webui_navigation_browsertest.cc b/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
new file mode 100644
index 00000000000..23f8a793303
--- /dev/null
+++ b/chromium/content/browser/frame_host/webui_navigation_browsertest.cc
@@ -0,0 +1,238 @@
+// 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/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace content {
+
+class WebUINavigationBrowserTest : public ContentBrowserTest {
+ public:
+ WebUINavigationBrowserTest() {}
+
+ protected:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebUINavigationBrowserTest);
+};
+
+// Verify that a chrome: scheme document cannot add iframes with web content.
+// See https://crbug.com/683418.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ WebFrameInChromeSchemeDisallowed) {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // TODO(nasko): Replace this URL with one with a custom WebUI object that
+ // doesn't have restrictive CSP, so the test can successfully add an
+ // iframe and test the actual throttle blocking. Currently the CSP policy
+ // will just block the navigation prior to the throttle being even
+ // invoked. See http://crbug.com/776900.
+ GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIBlobInternalsHost));
+ EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
+ EXPECT_EQ(chrome_url, root->current_frame_host()->GetLastCommittedURL());
+
+ {
+ GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+ std::string script = base::StringPrintf(
+ "var frame = document.createElement('iframe');\n"
+ "frame.src = '%s';\n"
+ "document.body.appendChild(frame);\n",
+ web_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
+ }
+
+ // Verify data: URLs are also not allowed.
+ {
+ GURL data_url("data:text/html,foo");
+ std::string script = base::StringPrintf(
+ "var frame = document.createElement('iframe');\n"
+ "frame.src = '%s';\n"
+ "document.body.appendChild(frame);\n",
+ data_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
+ }
+
+ // Verify that an iframe with "about:blank" URL is actually allowed. Not
+ // sure why this would be useful, but from a security perspective it can
+ // only host content coming from the parent document, so it effectively
+ // has the same security context.
+ {
+ GURL about_blank_url("about:blank");
+ std::string script = base::StringPrintf(
+ "var frame = document.createElement('iframe');\n"
+ "frame.src = '%s';\n"
+ "document.body.appendChild(frame);\n",
+ about_blank_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
+ }
+}
+
+// Verify that no web content can be loaded in a process that has WebUI
+// bindings, regardless of what scheme the content was loaded from.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ WebFrameInWebUIProcessDisallowed) {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ GURL data_url("data:text/html,a data url document");
+ EXPECT_TRUE(NavigateToURL(shell(), data_url));
+ EXPECT_EQ(data_url, root->current_frame_host()->GetLastCommittedURL());
+ EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ root->current_frame_host()->GetProcess()->GetID()));
+
+ // Grant WebUI bindings to the process. This will ensure that if there is
+ // a mistake in the navigation logic and a process gets somehow WebUI
+ // bindings, it cannot include web content regardless of the scheme of the
+ // document.
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
+ root->current_frame_host()->GetProcess()->GetID());
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ root->current_frame_host()->GetProcess()->GetID()));
+ {
+ GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+ std::string script = base::StringPrintf(
+ "var frame = document.createElement('iframe');\n"
+ "frame.src = '%s';\n"
+ "document.body.appendChild(frame);\n",
+ web_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_EQ(1U, root->child_count());
+ EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
+ }
+}
+
+// Verify that a WebUI document in the main frame is allowed to navigate to
+// web content and it properly does cross-process navigation.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, WebUIMainFrameToWebAllowed) {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
+ RenderFrameHost* webui_rfh = root->current_frame_host();
+ scoped_refptr<SiteInstance> webui_site_instance =
+ webui_rfh->GetSiteInstance();
+
+ EXPECT_EQ(chrome_url, webui_rfh->GetLastCommittedURL());
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ webui_rfh->GetProcess()->GetID()));
+
+ GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+ std::string script =
+ base::StringPrintf("location.href = '%s';", web_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
+ EXPECT_EQ(web_url, root->current_frame_host()->GetLastCommittedURL());
+ EXPECT_NE(webui_site_instance, root->current_frame_host()->GetSiteInstance());
+ EXPECT_FALSE(webui_site_instance->IsRelatedSiteInstance(
+ root->current_frame_host()->GetSiteInstance()));
+}
+
+// Verify that a WebUI document in a subframe is allowed to target a new
+// window and navigate it to web content.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+ WebUISubframeNewWindowToWebAllowed) {
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // TODO(nasko): Replace this URL with one with a custom WebUI object that
+ // doesn't have restrictive CSP, so the test can successfully add an
+ // iframe which gets WebUI bindings in the renderer process.
+ GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIBlobInternalsHost));
+ EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
+ RenderFrameHost* webui_rfh = root->current_frame_host();
+ scoped_refptr<SiteInstance> webui_site_instance =
+ webui_rfh->GetSiteInstance();
+
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
+ webui_rfh->GetProcess()->GetID());
+
+ EXPECT_EQ(chrome_url, webui_rfh->GetLastCommittedURL());
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ webui_rfh->GetProcess()->GetID()));
+
+ // Create a subframe with a WebUI document in it.
+ {
+ std::string script = base::StringPrintf(
+ "var frame = document.createElement('iframe');\n"
+ "frame.src = '%s';\n"
+ "document.body.appendChild(frame);\n",
+ chrome_url.spec().c_str());
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell(), script));
+ navigation_observer.Wait();
+
+ EXPECT_EQ(1U, root->child_count());
+ EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
+ }
+
+ // Add a link that targets a new window and click it.
+ GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+ std::string script = base::StringPrintf(
+ "var a = document.createElement('a');"
+ "a.href = '%s'; a.target = '_blank'; a.click()",
+ web_url.spec().c_str());
+
+ ShellAddedObserver new_shell_observer;
+ EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+
+ EXPECT_EQ(web_url, new_shell->web_contents()->GetLastCommittedURL());
+
+ // TODO(nasko): Verify the SiteInstance is different once
+ // https://crbug.com/776900 is fixed.
+ // Without a WebUI object which requires WebUI bindings, the RenderFrame is
+ // not notified that it has WebUI bindings. This in turn causes link clicks
+ // to use the BeginNavigation path, where otherwise the WebUI bindings will
+ // cause the OpenURL path to be taken. When using BeginNavigation, the
+ // navigation is committed same process, since it is renderer initiated.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/webui_navigation_throttle.cc b/chromium/content/browser/frame_host/webui_navigation_throttle.cc
new file mode 100644
index 00000000000..625b1cb19fe
--- /dev/null
+++ b/chromium/content/browser/frame_host/webui_navigation_throttle.cc
@@ -0,0 +1,59 @@
+// Copyright 2017 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/frame_host/webui_navigation_throttle.h"
+
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/common/url_constants.h"
+
+namespace content {
+
+WebUINavigationThrottle::WebUINavigationThrottle(
+ NavigationHandle* navigation_handle)
+ : NavigationThrottle(navigation_handle) {}
+
+WebUINavigationThrottle::~WebUINavigationThrottle() {}
+
+NavigationThrottle::ThrottleCheckResult
+WebUINavigationThrottle::WillStartRequest() {
+ // Allow only chrome: scheme documents to be navigated to.
+ if (navigation_handle()->GetURL().SchemeIs(kChromeUIScheme))
+ return PROCEED;
+
+ return BLOCK_REQUEST;
+}
+
+const char* WebUINavigationThrottle::GetNameForLogging() {
+ return "WebUINavigationThrottle";
+}
+
+// static
+std::unique_ptr<NavigationThrottle>
+WebUINavigationThrottle::CreateThrottleForNavigation(
+ NavigationHandle* navigation_handle) {
+ // Create the throttle only for subframe navigations.
+ if (navigation_handle->IsInMainFrame())
+ return nullptr;
+
+ RenderFrameHostImpl* parent =
+ static_cast<NavigationHandleImpl*>(navigation_handle)
+ ->frame_tree_node()
+ ->parent()
+ ->current_frame_host();
+
+ // Create a throttle only for navigations where the parent frame is either
+ // at a chrome:// URL or is in a process with WebUI bindings.
+ if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ parent->GetProcess()->GetID()) ||
+ parent->GetLastCommittedURL().SchemeIs(kChromeUIScheme)) {
+ return std::make_unique<WebUINavigationThrottle>(navigation_handle);
+ }
+
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/webui_navigation_throttle.h b/chromium/content/browser/frame_host/webui_navigation_throttle.h
new file mode 100644
index 00000000000..b47aa830487
--- /dev/null
+++ b/chromium/content/browser/frame_host/webui_navigation_throttle.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 CONTENT_BROWSER_FRAME_HOST_WEBUI_NAVIGATION_THROTTLE_H_
+#define CONTENT_BROWSER_FRAME_HOST_WEBUI_NAVIGATION_THROTTLE_H_
+
+#include "content/public/browser/navigation_throttle.h"
+
+namespace content {
+
+// This NavigationThrottle class is used to check for subframe navigations to
+// web content in WebUI processes and/or chrome:// documents. When the
+// parent frame is at a chrome:// URL or is in a process with WebUI
+// bindings, subframes are only allowed to navigate to chrome:// URLs.
+// Note: There are WebUI documents that live on non-chrome: schemes and do
+// not have WebUI bindings. Those are not covered by this restriction.
+//
+// This is an important security property to uphold, because by default
+// WebUI documents have high privileges and if malicious web content is
+// loaded in their process, it can be used as an easy step towards a sandbox
+// escape.
+//
+// Note: Navigations in the main frame are allowed, as those will result in a
+// process change with BrowsingInstance change and drop of privileges.
+// Subframes are resticted because they must be in the same BrowsingInstance
+// and would have the ability to communicate with the parent document.
+class WebUINavigationThrottle : public NavigationThrottle {
+ public:
+ static std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
+ NavigationHandle* navigation_handle);
+
+ explicit WebUINavigationThrottle(NavigationHandle* navigation_handle);
+ ~WebUINavigationThrottle() override;
+
+ // NavigationThrottle methods
+ ThrottleCheckResult WillStartRequest() override;
+ const char* GetNameForLogging() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebUINavigationThrottle);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_WEBUI_NAVIGATION_THROTTLE_H_
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index 7af07718719..db3b6606770 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -5,8 +5,9 @@
#include "content/browser/gpu/compositor_util.h"
#include <stddef.h>
-#include <memory>
+#include <algorithm>
+#include <memory>
#include <utility>
#include "base/command_line.h"
@@ -25,7 +26,9 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
+#include "gpu/config/gpu_blacklist.h"
+#include "gpu/config/gpu_driver_bug_list.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_switches.h"
@@ -42,12 +45,15 @@ const int kMaxRasterThreads = 4;
const int kMinMSAASampleCount = 0;
+enum class GpuFeatureInfoType { kCurrent, kForHardwareGpu };
+
struct GpuFeatureData {
std::string name;
gpu::GpuFeatureStatus status;
bool disabled;
std::string disabled_description;
bool fallback_to_software;
+ bool needs_gpu_access;
};
bool IsForceGpuRasterizationEnabled() {
@@ -55,117 +61,279 @@ bool IsForceGpuRasterizationEnabled() {
return command_line->HasSwitch(switches::kForceGpuRasterization);
}
-gpu::GpuFeatureStatus SafeGetFeatureStatus(GpuDataManagerImpl* manager,
- gpu::GpuFeatureType feature) {
- if (!manager->IsGpuFeatureInfoAvailable()) {
+gpu::GpuFeatureStatus SafeGetFeatureStatus(
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ gpu::GpuFeatureType feature) {
+ if (!gpu_feature_info.IsInitialized()) {
// The GPU process probably crashed during startup, but we can't
// assert this as the test bots are slow, and recording the crash
// is racy. Be robust and just say that all features are disabled.
return gpu::kGpuFeatureStatusDisabled;
}
- return manager->GetFeatureStatus(feature);
+ DCHECK(feature >= 0 && feature < gpu::NUMBER_OF_GPU_FEATURE_TYPES);
+ return gpu_feature_info.status_values[feature];
}
-gpu::GpuFeatureStatus GetGpuCompositingStatus() {
+gpu::GpuFeatureStatus GetGpuCompositingStatus(
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ GpuFeatureInfoType type) {
gpu::GpuFeatureStatus status = SafeGetFeatureStatus(
- GpuDataManagerImpl::GetInstance(), gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING);
+ gpu_feature_info, gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING);
#if defined(USE_AURA) || defined(OS_MACOSX)
- if (status == gpu::kGpuFeatureStatusEnabled &&
+ if (type == GpuFeatureInfoType::kCurrent &&
+ status == gpu::kGpuFeatureStatusEnabled &&
ImageTransportFactory::GetInstance()->IsGpuCompositingDisabled()) {
+ // We only adjust the status for kCurrent, because compositing status
+ // affects other feature status, and we want to preserve the kHardwareGpu
+ // feature status and don't want them to be modified by the current
+ // compositing status.
status = gpu::kGpuFeatureStatusDisabled;
}
#endif
return status;
}
-const GpuFeatureData GetGpuFeatureData(size_t index, bool* eof) {
+const GpuFeatureData GetGpuFeatureData(
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ GpuFeatureInfoType type,
+ size_t index,
+ bool* eof) {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
- GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
const GpuFeatureData kGpuFeatureData[] = {
{"2d_canvas",
- SafeGetFeatureStatus(manager,
+ SafeGetFeatureStatus(gpu_feature_info,
gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
"Accelerated 2D canvas is unavailable: either disabled via blacklist or"
" the command line.",
- true},
- {"gpu_compositing", GetGpuCompositingStatus(),
+ true, true},
+ {"gpu_compositing", GetGpuCompositingStatus(gpu_feature_info, type),
command_line.HasSwitch(switches::kDisableGpuCompositing),
- "Gpu compositing has been disabled, either via blacklist, about:flags"
- " or the command line. The browser will fall back to software "
- "compositing"
- " and hardware acceleration will be unavailable.",
- true},
+ "Gpu compositing has been disabled, either via blacklist, about:flags "
+ "or the command line. The browser will fall back to software "
+ "compositing and hardware acceleration will be unavailable.",
+ true, true},
{"webgl",
- SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL),
+ SafeGetFeatureStatus(gpu_feature_info,
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL),
command_line.HasSwitch(switches::kDisableWebGL),
- "WebGL has been disabled via blacklist or the command line.", false},
- {"flash_3d", SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_FLASH3D),
+ "WebGL has been disabled via blacklist or the command line.", false,
+ true},
+ {"flash_3d",
+ SafeGetFeatureStatus(gpu_feature_info, gpu::GPU_FEATURE_TYPE_FLASH3D),
command_line.HasSwitch(switches::kDisableFlash3d),
"Using 3d in flash has been disabled, either via blacklist, about:flags "
- "or"
- " the command line.",
- true},
+ "or the command line.",
+ true, true},
{"flash_stage3d",
- SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
+ SafeGetFeatureStatus(gpu_feature_info,
+ gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
command_line.HasSwitch(switches::kDisableFlashStage3d),
- "Using Stage3d in Flash has been disabled, either via blacklist,"
- " about:flags or the command line.",
- true},
+ "Using Stage3d in Flash has been disabled, either via blacklist, "
+ "about:flags or the command line.",
+ true, true},
{"flash_stage3d_baseline",
- SafeGetFeatureStatus(manager,
+ SafeGetFeatureStatus(gpu_feature_info,
gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE),
command_line.HasSwitch(switches::kDisableFlashStage3d),
- "Using Stage3d Baseline profile in Flash has been disabled, either"
- " via blacklist, about:flags or the command line.",
+ "Using Stage3d Baseline profile in Flash has been disabled, either via "
+ "blacklist, about:flags or the command line.",
+ true, true},
+ {"protected_video_decode",
+ SafeGetFeatureStatus(gpu_feature_info,
+ gpu::GPU_FEATURE_TYPE_PROTECTED_VIDEO_DECODE),
+ false, "Protected video decode has been disabled, via blacklist.", false,
true},
{"video_decode",
- SafeGetFeatureStatus(manager,
+ SafeGetFeatureStatus(gpu_feature_info,
gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
- "Accelerated video decode has been disabled, either via blacklist,"
- " about:flags or the command line.",
- true},
+ "Accelerated video decode has been disabled, either via blacklist, "
+ "about:flags or the command line.",
+ true, true},
{"rasterization",
- SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION),
+ SafeGetFeatureStatus(gpu_feature_info,
+ gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION),
(command_line.HasSwitch(switches::kDisableGpuRasterization) &&
!IsForceGpuRasterizationEnabled()),
- "Accelerated rasterization has been disabled, either via blacklist,"
- " about:flags or the command line.",
- true},
+ "Accelerated rasterization has been disabled, either via blacklist, "
+ "about:flags or the command line.",
+ true, true},
{"multiple_raster_threads", gpu::kGpuFeatureStatusEnabled,
NumberOfRendererRasterThreads() == 1, "Raster is using a single thread.",
- false},
+ false, true},
{"native_gpu_memory_buffers", gpu::kGpuFeatureStatusEnabled,
!gpu::AreNativeGpuMemoryBuffersEnabled(),
- "Native GpuMemoryBuffers have been disabled, either via about:flags"
- " or command line.",
- true},
+ "Native GpuMemoryBuffers have been disabled, either via about:flags or "
+ "command line.",
+ true, true},
{"surface_synchronization", gpu::kGpuFeatureStatusEnabled,
!features::IsSurfaceSynchronizationEnabled(),
"Surface synchronization has been disabled by Finch trial or command "
"line.",
- false},
+ false, false},
{"webgl2",
- SafeGetFeatureStatus(manager, gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2),
+ SafeGetFeatureStatus(gpu_feature_info,
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2),
(command_line.HasSwitch(switches::kDisableWebGL) ||
command_line.HasSwitch(switches::kDisableWebGL2)),
- "WebGL2 has been disabled via blacklist or the command line.", false},
+ "WebGL2 has been disabled via blacklist or the command line.", false,
+ true},
{"viz_display_compositor", gpu::kGpuFeatureStatusEnabled,
!base::FeatureList::IsEnabled(features::kVizDisplayCompositor),
- "Viz service display compositor is not enabled by default.", false},
- {"checker_imaging", gpu::kGpuFeatureStatusEnabled,
- !IsCheckerImagingEnabled(),
- "Checker-imaging has been disabled via finch trial or the command line.",
+ "Viz service display compositor is not enabled by default.", false,
false},
+ {"skia_renderer", gpu::kGpuFeatureStatusEnabled,
+ !features::IsUsingSkiaRenderer(),
+ "Skia renderer is not used by default.", false, false},
+ {"skia_deferred_display_list", gpu::kGpuFeatureStatusEnabled,
+ !features::IsUsingSkiaDeferredDisplayList(),
+ "Skia deferred display list is not used by default.", false, false},
};
DCHECK(index < arraysize(kGpuFeatureData));
*eof = (index == arraysize(kGpuFeatureData) - 1);
return kGpuFeatureData[index];
}
+std::unique_ptr<base::DictionaryValue> GetFeatureStatusImpl(
+ GpuFeatureInfoType type) {
+ GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+ std::string gpu_access_blocked_reason;
+ bool gpu_access_blocked =
+ !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
+ const gpu::GpuFeatureInfo gpu_feature_info =
+ type == GpuFeatureInfoType::kCurrent
+ ? manager->GetGpuFeatureInfo()
+ : manager->GetGpuFeatureInfoForHardwareGpu();
+
+ auto feature_status_dict = std::make_unique<base::DictionaryValue>();
+
+ bool eof = false;
+ for (size_t i = 0; !eof; ++i) {
+ const GpuFeatureData gpu_feature_data =
+ GetGpuFeatureData(gpu_feature_info, type, i, &eof);
+ std::string status;
+ if (gpu_feature_data.disabled || gpu_access_blocked ||
+ gpu_feature_data.status == gpu::kGpuFeatureStatusDisabled) {
+ status = "disabled";
+ if (gpu_feature_data.fallback_to_software)
+ status += "_software";
+ else
+ status += "_off";
+ } else if (gpu_feature_data.status == gpu::kGpuFeatureStatusBlacklisted) {
+ status = "unavailable_off";
+ } else if (gpu_feature_data.status == gpu::kGpuFeatureStatusSoftware) {
+ status = "unavailable_software";
+ } else {
+ status = "enabled";
+ if ((gpu_feature_data.name == "webgl" ||
+ gpu_feature_data.name == "webgl2") &&
+ (GetGpuCompositingStatus(gpu_feature_info, type) !=
+ gpu::kGpuFeatureStatusEnabled))
+ status += "_readback";
+ if (gpu_feature_data.name == "rasterization") {
+ if (IsForceGpuRasterizationEnabled())
+ status += "_force";
+ }
+ if (gpu_feature_data.name == "multiple_raster_threads") {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kNumRasterThreads))
+ status += "_force";
+ status += "_on";
+ }
+ if (gpu_feature_data.name == "surface_synchronization") {
+ if (features::IsSurfaceSynchronizationEnabled())
+ status += "_on";
+ }
+ if (gpu_feature_data.name == "viz_display_compositor") {
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
+ status += "_on";
+ }
+ if (gpu_feature_data.name == "skia_renderer") {
+ if (features::IsUsingSkiaRenderer())
+ status += "_on";
+ }
+ if (gpu_feature_data.name == "skia_deferred_display_list") {
+ if (features::IsUsingSkiaDeferredDisplayList())
+ status += "_on";
+ }
+ }
+ feature_status_dict->SetString(gpu_feature_data.name, status);
+ }
+ return feature_status_dict;
+}
+
+std::unique_ptr<base::ListValue> GetProblemsImpl(GpuFeatureInfoType type) {
+ GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+ std::string gpu_access_blocked_reason;
+ bool gpu_access_blocked =
+ !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
+ const gpu::GpuFeatureInfo gpu_feature_info =
+ type == GpuFeatureInfoType::kCurrent
+ ? manager->GetGpuFeatureInfo()
+ : manager->GetGpuFeatureInfoForHardwareGpu();
+
+ auto problem_list = std::make_unique<base::ListValue>();
+ if (!gpu_feature_info.applied_gpu_blacklist_entries.empty()) {
+ std::unique_ptr<gpu::GpuBlacklist> blacklist(gpu::GpuBlacklist::Create());
+ blacklist->GetReasons(problem_list.get(), "disabledFeatures",
+ gpu_feature_info.applied_gpu_blacklist_entries);
+ }
+ if (!gpu_feature_info.applied_gpu_driver_bug_list_entries.empty()) {
+ std::unique_ptr<gpu::GpuDriverBugList> bug_list(
+ gpu::GpuDriverBugList::Create());
+ bug_list->GetReasons(problem_list.get(), "workarounds",
+ gpu_feature_info.applied_gpu_driver_bug_list_entries);
+ }
+
+ if (gpu_access_blocked) {
+ auto problem = std::make_unique<base::DictionaryValue>();
+ problem->SetString("description", "GPU process was unable to boot: " +
+ gpu_access_blocked_reason);
+ problem->Set("crBugs", std::make_unique<base::ListValue>());
+ auto disabled_features = std::make_unique<base::ListValue>();
+ disabled_features->AppendString("all");
+ problem->Set("affectedGpuSettings", std::move(disabled_features));
+ problem->SetString("tag", "disabledFeatures");
+ problem_list->Insert(0, std::move(problem));
+ }
+
+ bool eof = false;
+ for (size_t i = 0; !eof; ++i) {
+ const GpuFeatureData gpu_feature_data =
+ GetGpuFeatureData(gpu_feature_info, type, i, &eof);
+ if (gpu_feature_data.disabled) {
+ auto problem = std::make_unique<base::DictionaryValue>();
+ problem->SetString("description", gpu_feature_data.disabled_description);
+ problem->Set("crBugs", std::make_unique<base::ListValue>());
+ auto disabled_features = std::make_unique<base::ListValue>();
+ disabled_features->AppendString(gpu_feature_data.name);
+ problem->Set("affectedGpuSettings", std::move(disabled_features));
+ problem->SetString("tag", "disabledFeatures");
+ problem_list->Append(std::move(problem));
+ }
+ }
+ return problem_list;
+}
+
+std::vector<std::string> GetDriverBugWorkaroundsImpl(GpuFeatureInfoType type) {
+ GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+ const gpu::GpuFeatureInfo gpu_feature_info =
+ type == GpuFeatureInfoType::kCurrent
+ ? manager->GetGpuFeatureInfo()
+ : manager->GetGpuFeatureInfoForHardwareGpu();
+
+ std::vector<std::string> workarounds;
+ for (auto workaround : gpu_feature_info.enabled_gpu_driver_bug_workarounds) {
+ workarounds.push_back(gpu::GpuDriverBugWorkaroundTypeToString(
+ static_cast<gpu::GpuDriverBugWorkaroundType>(workaround)));
+ }
+ return workarounds;
+}
+
} // namespace
int NumberOfRendererRasterThreads() {
@@ -278,140 +446,28 @@ bool IsMainFrameBeforeActivationEnabled() {
return true;
}
-bool IsCheckerImagingEnabled() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- cc::switches::kDisableCheckerImaging))
- return false;
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- cc::switches::kEnableCheckerImaging))
- return true;
-
- if (base::FeatureList::IsEnabled(features::kCheckerImaging))
- return true;
-
- return false;
-}
-
std::unique_ptr<base::DictionaryValue> GetFeatureStatus() {
- GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
- std::string gpu_access_blocked_reason;
- bool gpu_access_blocked =
- !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
-
- auto feature_status_dict = std::make_unique<base::DictionaryValue>();
-
- bool eof = false;
- for (size_t i = 0; !eof; ++i) {
- const GpuFeatureData gpu_feature_data = GetGpuFeatureData(i, &eof);
- std::string status;
- if (gpu_feature_data.disabled || gpu_access_blocked ||
- gpu_feature_data.status == gpu::kGpuFeatureStatusDisabled) {
- status = "disabled";
- if (gpu_feature_data.fallback_to_software)
- status += "_software";
- else
- status += "_off";
- } else if (gpu_feature_data.status == gpu::kGpuFeatureStatusBlacklisted) {
- status = "unavailable_off";
- } else if (gpu_feature_data.status == gpu::kGpuFeatureStatusSoftware) {
- status = "unavailable_software";
- } else {
- status = "enabled";
- if ((gpu_feature_data.name == "webgl" ||
- gpu_feature_data.name == "webgl2") &&
- (manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING) !=
- gpu::kGpuFeatureStatusEnabled))
- status += "_readback";
- if (gpu_feature_data.name == "rasterization") {
- if (IsForceGpuRasterizationEnabled())
- status += "_force";
- }
- if (gpu_feature_data.name == "multiple_raster_threads") {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kNumRasterThreads))
- status += "_force";
- status += "_on";
- }
- if (gpu_feature_data.name == "checker_imaging") {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(cc::switches::kEnableCheckerImaging))
- status += "_force";
- status += "_on";
- }
- if (gpu_feature_data.name == "surface_synchronization") {
- if (features::IsSurfaceSynchronizationEnabled())
- status += "_on";
- }
- if (gpu_feature_data.name == "viz_display_compositor") {
- if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor))
- status += "_on";
- }
- }
- feature_status_dict->SetString(gpu_feature_data.name, status);
- }
- return feature_status_dict;
+ return GetFeatureStatusImpl(GpuFeatureInfoType::kCurrent);
}
std::unique_ptr<base::ListValue> GetProblems() {
- GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
- std::string gpu_access_blocked_reason;
- bool gpu_access_blocked =
- !manager->GpuAccessAllowed(&gpu_access_blocked_reason);
-
- auto problem_list = std::make_unique<base::ListValue>();
- manager->GetBlacklistReasons(problem_list.get());
+ return GetProblemsImpl(GpuFeatureInfoType::kCurrent);
+}
- if (gpu_access_blocked) {
- auto problem = std::make_unique<base::DictionaryValue>();
- problem->SetString("description",
- "GPU process was unable to boot: " + gpu_access_blocked_reason);
- problem->Set("crBugs", std::make_unique<base::ListValue>());
- auto disabled_features = std::make_unique<base::ListValue>();
- disabled_features->AppendString("all");
- problem->Set("affectedGpuSettings", std::move(disabled_features));
- problem->SetString("tag", "disabledFeatures");
- problem_list->Insert(0, std::move(problem));
- }
+std::vector<std::string> GetDriverBugWorkarounds() {
+ return GetDriverBugWorkaroundsImpl(GpuFeatureInfoType::kCurrent);
+}
- bool eof = false;
- for (size_t i = 0; !eof; ++i) {
- const GpuFeatureData gpu_feature_data = GetGpuFeatureData(i, &eof);
- if (gpu_feature_data.disabled) {
- auto problem = std::make_unique<base::DictionaryValue>();
- problem->SetString("description", gpu_feature_data.disabled_description);
- problem->Set("crBugs", std::make_unique<base::ListValue>());
- auto disabled_features = std::make_unique<base::ListValue>();
- disabled_features->AppendString(gpu_feature_data.name);
- problem->Set("affectedGpuSettings", std::move(disabled_features));
- problem->SetString("tag", "disabledFeatures");
- problem_list->Append(std::move(problem));
- }
- }
- return problem_list;
+std::unique_ptr<base::DictionaryValue> GetFeatureStatusForHardwareGpu() {
+ return GetFeatureStatusImpl(GpuFeatureInfoType::kForHardwareGpu);
}
-std::vector<std::string> GetDriverBugWorkarounds() {
- return GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds();
+std::unique_ptr<base::ListValue> GetProblemsForHardwareGpu() {
+ return GetProblemsImpl(GpuFeatureInfoType::kForHardwareGpu);
}
-std::vector<gfx::BufferUsageAndFormat>
-CreateBufferUsageAndFormatExceptionList() {
- std::vector<gfx::BufferUsageAndFormat> usage_format_list;
- for (int usage_idx = 0; usage_idx <= static_cast<int>(gfx::BufferUsage::LAST);
- ++usage_idx) {
- gfx::BufferUsage usage = static_cast<gfx::BufferUsage>(usage_idx);
- for (int format_idx = 0;
- format_idx <= static_cast<int>(gfx::BufferFormat::LAST);
- ++format_idx) {
- gfx::BufferFormat format = static_cast<gfx::BufferFormat>(format_idx);
- if (gpu::GetImageNeedsPlatformSpecificTextureTarget(format, usage))
- usage_format_list.push_back(gfx::BufferUsageAndFormat(usage, format));
- }
- }
- return usage_format_list;
+std::vector<std::string> GetDriverBugWorkaroundsForHardwareGpu() {
+ return GetDriverBugWorkaroundsImpl(GpuFeatureInfoType::kForHardwareGpu);
}
} // namespace content
diff --git a/chromium/content/browser/gpu/compositor_util.h b/chromium/content/browser/gpu/compositor_util.h
index d31715e3dd7..e9ed20977ea 100644
--- a/chromium/content/browser/gpu/compositor_util.h
+++ b/chromium/content/browser/gpu/compositor_util.h
@@ -6,11 +6,11 @@
#define CONTENT_BROWSER_GPU_COMPOSITOR_UTIL_H_
#include <memory>
+#include <string>
#include <vector>
#include "base/values.h"
#include "content/common/content_export.h"
-#include "ui/gfx/buffer_types.h"
namespace content {
@@ -37,9 +37,6 @@ CONTENT_EXPORT int NumberOfRendererRasterThreads();
// Returns true if main thread can be pipelined with activation.
CONTENT_EXPORT bool IsMainFrameBeforeActivationEnabled();
-// Returns true if images can be decode asynchronously from rasterization.
-CONTENT_EXPORT bool IsCheckerImagingEnabled();
-
// Returns true if image animations should run in the compositor.
CONTENT_EXPORT bool IsCompositorImageAnimationEnabled();
@@ -47,10 +44,10 @@ CONTENT_EXPORT std::unique_ptr<base::DictionaryValue> GetFeatureStatus();
CONTENT_EXPORT std::unique_ptr<base::ListValue> GetProblems();
CONTENT_EXPORT std::vector<std::string> GetDriverBugWorkarounds();
-// Populate a list of buffer usage/format for which a per platform specific
-// texture target must be used instead of GL_TEXTURE_2D.
-CONTENT_EXPORT std::vector<gfx::BufferUsageAndFormat>
-CreateBufferUsageAndFormatExceptionList();
+CONTENT_EXPORT std::unique_ptr<base::DictionaryValue>
+GetFeatureStatusForHardwareGpu();
+CONTENT_EXPORT std::unique_ptr<base::ListValue> GetProblemsForHardwareGpu();
+CONTENT_EXPORT std::vector<std::string> GetDriverBugWorkaroundsForHardwareGpu();
} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_client.cc b/chromium/content/browser/gpu/gpu_client_impl.cc
index 541bdd0c9bc..a591794d329 100644
--- a/chromium/content/browser/gpu/gpu_client.cc
+++ b/chromium/content/browser/gpu/gpu_client_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/gpu/gpu_client.h"
+#include "content/browser/gpu/gpu_client_impl.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -14,41 +14,60 @@
namespace content {
-GpuClient::GpuClient(int render_process_id)
+// static
+std::unique_ptr<GpuClient, BrowserThread::DeleteOnIOThread> GpuClient::Create(
+ ui::mojom::GpuRequest request,
+ ConnectionErrorHandlerClosure connection_error_handler) {
+ std::unique_ptr<GpuClientImpl, BrowserThread::DeleteOnIOThread> gpu_client(
+ new GpuClientImpl(ChildProcessHostImpl::GenerateChildProcessUniqueId()));
+ gpu_client->SetConnectionErrorHandler(std::move(connection_error_handler));
+ gpu_client->Add(std::move(request));
+ return gpu_client;
+}
+
+GpuClientImpl::GpuClientImpl(int render_process_id)
: render_process_id_(render_process_id), weak_factory_(this) {
bindings_.set_connection_error_handler(
- base::Bind(&GpuClient::OnError, base::Unretained(this)));
+ base::Bind(&GpuClientImpl::OnError, base::Unretained(this),
+ ErrorReason::kConnectionLost));
}
-GpuClient::~GpuClient() {
+GpuClientImpl::~GpuClientImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
bindings_.CloseAllBindings();
- OnError();
+ OnError(ErrorReason::kInDestructor);
}
-void GpuClient::Add(ui::mojom::GpuRequest request) {
+void GpuClientImpl::Add(ui::mojom::GpuRequest request) {
bindings_.AddBinding(this, std::move(request));
}
-void GpuClient::OnError() {
+void GpuClientImpl::OnError(ErrorReason reason) {
ClearCallback();
- if (!bindings_.empty())
- return;
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
- BrowserGpuMemoryBufferManager::current();
- if (gpu_memory_buffer_manager)
- gpu_memory_buffer_manager->ProcessRemoved(render_process_id_);
+ if (bindings_.empty()) {
+ BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
+ BrowserGpuMemoryBufferManager::current();
+ if (gpu_memory_buffer_manager)
+ gpu_memory_buffer_manager->ProcessRemoved(render_process_id_);
+ }
+ if (reason == ErrorReason::kConnectionLost && connection_error_handler_)
+ std::move(connection_error_handler_).Run(this);
}
-void GpuClient::PreEstablishGpuChannel() {
+void GpuClientImpl::PreEstablishGpuChannel() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&GpuClient::EstablishGpuChannel, base::Unretained(this),
- EstablishGpuChannelCallback()));
+ base::BindOnce(&GpuClientImpl::EstablishGpuChannel,
+ base::Unretained(this), EstablishGpuChannelCallback()));
+}
+
+void GpuClientImpl::SetConnectionErrorHandler(
+ ConnectionErrorHandlerClosure connection_error_handler) {
+ connection_error_handler_ = std::move(connection_error_handler);
}
-void GpuClient::OnEstablishGpuChannel(
+void GpuClientImpl::OnEstablishGpuChannel(
mojo::ScopedMessagePipeHandle channel_handle,
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
@@ -79,13 +98,13 @@ void GpuClient::OnEstablishGpuChannel(
}
}
-void GpuClient::OnCreateGpuMemoryBuffer(
+void GpuClientImpl::OnCreateGpuMemoryBuffer(
CreateGpuMemoryBufferCallback callback,
const gfx::GpuMemoryBufferHandle& handle) {
std::move(callback).Run(handle);
}
-void GpuClient::ClearCallback() {
+void GpuClientImpl::ClearCallback() {
if (!callback_)
return;
EstablishGpuChannelCallback callback = std::move(callback_);
@@ -94,7 +113,7 @@ void GpuClient::ClearCallback() {
DCHECK(!callback_);
}
-void GpuClient::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
+void GpuClientImpl::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// At most one channel should be requested. So clear previous request first.
ClearCallback();
@@ -131,18 +150,18 @@ void GpuClient::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
render_process_id_),
preempts, allow_view_command_buffers, allow_real_time_streams,
- base::Bind(&GpuClient::OnEstablishGpuChannel,
+ base::Bind(&GpuClientImpl::OnEstablishGpuChannel,
weak_factory_.GetWeakPtr()));
}
-void GpuClient::CreateJpegDecodeAccelerator(
+void GpuClientImpl::CreateJpegDecodeAccelerator(
media::mojom::JpegDecodeAcceleratorRequest jda_request) {
GpuProcessHost* host = GpuProcessHost::Get();
if (host)
host->gpu_service()->CreateJpegDecodeAccelerator(std::move(jda_request));
}
-void GpuClient::CreateVideoEncodeAcceleratorProvider(
+void GpuClientImpl::CreateVideoEncodeAcceleratorProvider(
media::mojom::VideoEncodeAcceleratorProviderRequest vea_provider_request) {
GpuProcessHost* host = GpuProcessHost::Get();
if (!host)
@@ -151,7 +170,7 @@ void GpuClient::CreateVideoEncodeAcceleratorProvider(
std::move(vea_provider_request));
}
-void GpuClient::CreateGpuMemoryBuffer(
+void GpuClientImpl::CreateGpuMemoryBuffer(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
gfx::BufferFormat format,
@@ -169,12 +188,12 @@ void GpuClient::CreateGpuMemoryBuffer(
BrowserGpuMemoryBufferManager::current()
->AllocateGpuMemoryBufferForChildProcess(
id, size, format, usage, render_process_id_,
- base::BindOnce(&GpuClient::OnCreateGpuMemoryBuffer,
+ base::BindOnce(&GpuClientImpl::OnCreateGpuMemoryBuffer,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
-void GpuClient::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- const gpu::SyncToken& sync_token) {
+void GpuClientImpl::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
+ const gpu::SyncToken& sync_token) {
DCHECK(BrowserGpuMemoryBufferManager::current());
BrowserGpuMemoryBufferManager::current()->ChildProcessDeletedGpuMemoryBuffer(
diff --git a/chromium/content/browser/gpu/gpu_client.h b/chromium/content/browser/gpu/gpu_client_impl.h
index 89d0d9cdf6c..03e29bf4b5f 100644
--- a/chromium/content/browser/gpu/gpu_client.h
+++ b/chromium/content/browser/gpu/gpu_client_impl.h
@@ -2,27 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_GPU_GPU_CLIENT_H_
-#define CONTENT_BROWSER_GPU_GPU_CLIENT_H_
+#ifndef CONTENT_BROWSER_GPU_GPU_CLIENT_IMPL_H_
+#define CONTENT_BROWSER_GPU_GPU_CLIENT_IMPL_H_
+#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/gpu_client.h"
#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/ui/public/interfaces/gpu.mojom.h"
namespace content {
-class GpuClient : public ui::mojom::Gpu {
+class GpuClientImpl : public ui::mojom::Gpu, public GpuClient {
public:
- explicit GpuClient(int render_process_id);
- ~GpuClient() override;
+ explicit GpuClientImpl(int render_process_id);
+ ~GpuClientImpl() override;
void Add(ui::mojom::GpuRequest request);
void PreEstablishGpuChannel();
+ void SetConnectionErrorHandler(
+ ConnectionErrorHandlerClosure connection_error_handler);
+
private:
- void OnError();
+ enum class ErrorReason {
+ // OnError() is being called from the destructor.
+ kInDestructor,
+ // OnError() is being called because the connection was lost.
+ kConnectionLost
+ };
+ void OnError(ErrorReason reason);
void OnEstablishGpuChannel(mojo::ScopedMessagePipeHandle channel_handle,
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
@@ -54,11 +64,12 @@ class GpuClient : public ui::mojom::Gpu {
mojo::ScopedMessagePipeHandle channel_handle_;
gpu::GPUInfo gpu_info_;
gpu::GpuFeatureInfo gpu_feature_info_;
- base::WeakPtrFactory<GpuClient> weak_factory_;
+ ConnectionErrorHandlerClosure connection_error_handler_;
+ base::WeakPtrFactory<GpuClientImpl> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(GpuClient);
+ DISALLOW_COPY_AND_ASSIGN(GpuClientImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_GPU_GPU_CLIENT_H_
+#endif // CONTENT_BROWSER_GPU_GPU_CLIENT_IMPL_H_
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index 13f75be6f01..3c8b665a48a 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -94,12 +94,6 @@ bool GpuDataManagerImpl::HardwareAccelerationEnabled() const {
return private_->HardwareAccelerationEnabled();
}
-void GpuDataManagerImpl::GetDisabledExtensions(
- std::string* disabled_extensions) const {
- base::AutoLock auto_lock(lock_);
- private_->GetDisabledExtensions(disabled_extensions);
-}
-
void GpuDataManagerImpl::RequestGpuSupportedRuntimeVersion() const {
base::AutoLock auto_lock(lock_);
private_->RequestGpuSupportedRuntimeVersion();
@@ -110,21 +104,20 @@ bool GpuDataManagerImpl::GpuProcessStartAllowed() const {
return private_->GpuProcessStartAllowed();
}
-void GpuDataManagerImpl::GetDisabledWebGLExtensions(
- std::string* disabled_webgl_extensions) const {
- base::AutoLock auto_lock(lock_);
- private_->GetDisabledWebGLExtensions(disabled_webgl_extensions);
-}
-
-void GpuDataManagerImpl::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
+void GpuDataManagerImpl::UpdateGpuInfo(
+ const gpu::GPUInfo& gpu_info,
+ const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu) {
base::AutoLock auto_lock(lock_);
- private_->UpdateGpuInfo(gpu_info);
+ private_->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
}
void GpuDataManagerImpl::UpdateGpuFeatureInfo(
- const gpu::GpuFeatureInfo& gpu_feature_info) {
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu) {
base::AutoLock auto_lock(lock_);
- private_->UpdateGpuFeatureInfo(gpu_feature_info);
+ private_->UpdateGpuFeatureInfo(gpu_feature_info,
+ gpu_feature_info_for_hardware_gpu);
}
gpu::GpuFeatureInfo GpuDataManagerImpl::GetGpuFeatureInfo() const {
@@ -132,26 +125,27 @@ gpu::GpuFeatureInfo GpuDataManagerImpl::GetGpuFeatureInfo() const {
return private_->GetGpuFeatureInfo();
}
-void GpuDataManagerImpl::AppendGpuCommandLine(
- base::CommandLine* command_line) const {
+gpu::GPUInfo GpuDataManagerImpl::GetGPUInfoForHardwareGpu() const {
base::AutoLock auto_lock(lock_);
- private_->AppendGpuCommandLine(command_line);
+ return private_->GetGPUInfoForHardwareGpu();
}
-void GpuDataManagerImpl::UpdateGpuPreferences(
- gpu::GpuPreferences* gpu_preferences) const {
+gpu::GpuFeatureInfo GpuDataManagerImpl::GetGpuFeatureInfoForHardwareGpu()
+ const {
base::AutoLock auto_lock(lock_);
- private_->UpdateGpuPreferences(gpu_preferences);
+ return private_->GetGpuFeatureInfoForHardwareGpu();
}
-void GpuDataManagerImpl::GetBlacklistReasons(base::ListValue* reasons) const {
+void GpuDataManagerImpl::AppendGpuCommandLine(
+ base::CommandLine* command_line) const {
base::AutoLock auto_lock(lock_);
- private_->GetBlacklistReasons(reasons);
+ private_->AppendGpuCommandLine(command_line);
}
-std::vector<std::string> GpuDataManagerImpl::GetDriverBugWorkarounds() const {
+void GpuDataManagerImpl::UpdateGpuPreferences(
+ gpu::GpuPreferences* gpu_preferences) const {
base::AutoLock auto_lock(lock_);
- return private_->GetDriverBugWorkarounds();
+ private_->UpdateGpuPreferences(gpu_preferences);
}
void GpuDataManagerImpl::AddLogMessage(int level,
@@ -218,6 +212,11 @@ void GpuDataManagerImpl::OnGpuProcessInitFailure() {
private_->OnGpuProcessInitFailure();
}
+bool GpuDataManagerImpl::IsGpuProcessUsingHardwareGpu() const {
+ base::AutoLock auto_lock(lock_);
+ return private_->IsGpuProcessUsingHardwareGpu();
+}
+
GpuDataManagerImpl::GpuDataManagerImpl()
: private_(GpuDataManagerImplPrivate::Create(this)) {
}
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index b77578834a6..06210a34e80 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -81,41 +81,36 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
void RemoveObserver(GpuDataManagerObserver* observer) override;
void DisableHardwareAcceleration() override;
bool HardwareAccelerationEnabled() const override;
- void GetDisabledExtensions(std::string* disabled_extensions) const override;
void RequestGpuSupportedRuntimeVersion() const;
bool GpuProcessStartAllowed() const;
- void GetDisabledWebGLExtensions(std::string* disabled_webgl_extensions) const;
-
bool IsGpuFeatureInfoAvailable() const;
gpu::GpuFeatureStatus GetFeatureStatus(gpu::GpuFeatureType feature) const;
// Only update if the current GPUInfo is not finalized. If blacklist is
// loaded, run through blacklist and update blacklisted features.
- void UpdateGpuInfo(const gpu::GPUInfo& gpu_info);
+ void UpdateGpuInfo(
+ const gpu::GPUInfo& gpu_info,
+ const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu);
// Update the GPU feature info. This updates the blacklist and enabled status
// of GPU rasterization. In the future this will be used for more features.
- void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info);
+ void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu);
gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
+ gpu::GPUInfo GetGPUInfoForHardwareGpu() const;
+ gpu::GpuFeatureInfo GetGpuFeatureInfoForHardwareGpu() const;
+
// Insert switches into gpu process command line: kUseGL, etc.
void AppendGpuCommandLine(base::CommandLine* command_line) const;
// Update GpuPreferences based on blacklisting decisions.
void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences) const;
- // Returns the reasons for the latest run of blacklisting decisions.
- // For the structure of returned value, see documentation for
- // GpuBlacklist::GetBlacklistedReasons().
- void GetBlacklistReasons(base::ListValue* reasons) const;
-
- // Returns the workarounds that are applied to the current system as
- // a vector of strings.
- std::vector<std::string> GetDriverBugWorkarounds() const;
-
void AddLogMessage(int level,
const std::string& header,
const std::string& message);
@@ -160,6 +155,10 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
void BlockSwiftShader();
bool SwiftShaderAllowed() const;
+ // Returns false if the latest GPUInfo gl_renderer is from SwiftShader or
+ // Disabled (in the viz case).
+ bool IsGpuProcessUsingHardwareGpu() const;
+
private:
friend class GpuDataManagerImplPrivate;
friend class GpuDataManagerImplPrivateTest;
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
index 657b6381461..e3b41337158 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -16,6 +16,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "base/version.h"
@@ -23,7 +24,6 @@
#include "cc/base/switches.h"
#include "components/viz/common/features.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
-#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager_observer.h"
@@ -44,6 +44,7 @@
#include "gpu/config/software_rendering_list_autogen.h"
#include "gpu/ipc/common/gpu_preferences_util.h"
#include "gpu/ipc/common/memory_stats.h"
+#include "gpu/ipc/host/gpu_memory_buffer_support.h"
#include "gpu/ipc/host/shader_disk_cache.h"
#include "media/media_buildflags.h"
#include "ui/base/ui_base_switches.h"
@@ -194,7 +195,7 @@ void DisplayReconfigCallback(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags,
void* gpu_data_manager) {
if (flags == kCGDisplayBeginConfigurationFlag)
- return; // This call contains no information about the display change
+ return; // This call contains no information about the display change
GpuDataManagerImpl* manager =
reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
@@ -254,12 +255,13 @@ void UpdateGpuInfoOnIO(const gpu::GPUInfo& gpu_info) {
base::BindOnce(
[](const gpu::GPUInfo& gpu_info) {
TRACE_EVENT0("test_gpu", "OnGraphicsInfoCollected");
- GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
+ GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info,
+ base::nullopt);
},
gpu_info));
}
-} // namespace anonymous
+} // anonymous namespace
void GpuDataManagerImplPrivate::BlacklistWebGLForTesting() {
// This function is for testing only, so disable histograms.
@@ -272,7 +274,7 @@ void GpuDataManagerImplPrivate::BlacklistWebGLForTesting() {
else
gpu_feature_info.status_values[ii] = gpu::kGpuFeatureStatusEnabled;
}
- UpdateGpuFeatureInfo(gpu_feature_info);
+ UpdateGpuFeatureInfo(gpu_feature_info, base::nullopt);
NotifyGpuInfoUpdate();
}
@@ -280,6 +282,10 @@ gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const {
return gpu_info_;
}
+gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfoForHardwareGpu() const {
+ return gpu_info_for_hardware_gpu_;
+}
+
bool GpuDataManagerImplPrivate::GpuAccessAllowed(
std::string* reason) const {
bool swiftshader_available = false;
@@ -327,6 +333,8 @@ void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
return;
if (!GpuAccessAllowed(nullptr))
return;
+ if (in_process_gpu_)
+ return;
complete_gpu_info_already_requested_ = true;
@@ -346,12 +354,15 @@ void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
void GpuDataManagerImplPrivate::RequestGpuSupportedRuntimeVersion() {
#if defined(OS_WIN)
+ if (in_process_gpu_)
+ return;
base::OnceClosure task = base::BindOnce([]() {
GpuProcessHost* host = GpuProcessHost::Get(
GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED, true /* force_create */);
if (!host)
return;
- host->gpu_service()->GetGpuSupportedRuntimeVersion();
+ host->gpu_service()->GetGpuSupportedRuntimeVersion(
+ base::BindOnce(&UpdateGpuInfoOnIO));
});
BrowserThread::PostDelayedTask(BrowserThread::IO, FROM_HERE, std::move(task),
@@ -420,15 +431,38 @@ void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) {
timestamps_of_gpu_resets_.clear();
}
-void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
+void GpuDataManagerImplPrivate::UpdateGpuInfo(
+ const gpu::GPUInfo& gpu_info,
+ const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu) {
bool sandboxed = gpu_info_.sandboxed;
+#if defined(OS_WIN)
+ uint32_t d3d12_feature_level = gpu_info_.d3d12_feature_level;
+ uint32_t vulkan_version = gpu_info_.vulkan_version;
+#endif
gpu_info_ = gpu_info;
+ if (!gpu_info_for_hardware_gpu_.IsInitialized()) {
+ if (!!gpu_info_for_hardware_gpu) {
+ DCHECK(gpu_info_for_hardware_gpu->IsInitialized());
+ gpu_info_for_hardware_gpu_ = gpu_info_for_hardware_gpu.value();
+ } else {
+ gpu_info_for_hardware_gpu_ = gpu_info;
+ }
+ }
#if defined(OS_WIN)
// On Windows, complete GPUInfo is collected through an unsandboxed
// GPU process. If the regular GPU process is sandboxed, it should
// not be overwritten.
if (sandboxed)
gpu_info_.sandboxed = true;
+
+ if (d3d12_feature_level) {
+ gpu_info_.d3d12_feature_level = d3d12_feature_level;
+ gpu_info_.supports_dx12 = true;
+ }
+ if (vulkan_version) {
+ gpu_info_.vulkan_version = vulkan_version;
+ gpu_info_.supports_vulkan = true;
+ }
#else
(void)sandboxed;
#endif // OS_WIN
@@ -443,8 +477,19 @@ void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
}
void GpuDataManagerImplPrivate::UpdateGpuFeatureInfo(
- const gpu::GpuFeatureInfo& gpu_feature_info) {
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu) {
gpu_feature_info_ = gpu_feature_info;
+ if (!gpu_feature_info_for_hardware_gpu_.IsInitialized()) {
+ if (gpu_feature_info_for_hardware_gpu.has_value()) {
+ DCHECK(gpu_feature_info_for_hardware_gpu->IsInitialized());
+ gpu_feature_info_for_hardware_gpu_ =
+ gpu_feature_info_for_hardware_gpu.value();
+ } else {
+ gpu_feature_info_for_hardware_gpu_ = gpu_feature_info;
+ }
+ }
if (update_histograms_) {
UpdateFeatureStats(gpu_feature_info);
UpdateDriverBugListStats(gpu_feature_info);
@@ -455,6 +500,11 @@ gpu::GpuFeatureInfo GpuDataManagerImplPrivate::GetGpuFeatureInfo() const {
return gpu_feature_info_;
}
+gpu::GpuFeatureInfo GpuDataManagerImplPrivate::GetGpuFeatureInfoForHardwareGpu()
+ const {
+ return gpu_feature_info_for_hardware_gpu_;
+}
+
void GpuDataManagerImplPrivate::AppendGpuCommandLine(
base::CommandLine* command_line) const {
DCHECK(command_line);
@@ -469,6 +519,8 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
std::string use_gl;
if (card_disabled_ && SwiftShaderAllowed()) {
use_gl = gl::kGLImplementationSwiftShaderForWebGLName;
+ } else if (card_disabled_) {
+ use_gl = gl::kGLImplementationDisabledName;
} else {
use_gl = browser_command_line->GetSwitchValueASCII(switches::kUseGL);
}
@@ -486,12 +538,6 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
command_line->AppendSwitch(switches::kOverrideUseSoftwareGLForTests);
}
#endif // !OS_MACOSX
-
-#if defined(USE_OZONE)
- if (browser_command_line->HasSwitch(switches::kEnableDrmAtomic)) {
- command_line->AppendSwitch(switches::kEnableDrmAtomic);
- }
-#endif
}
void GpuDataManagerImplPrivate::UpdateGpuPreferences(
@@ -513,7 +559,7 @@ void GpuDataManagerImplPrivate::UpdateGpuPreferences(
gpu::ShaderDiskCache::CacheSizeBytes();
gpu_preferences->texture_target_exception_list =
- CreateBufferUsageAndFormatExceptionList();
+ gpu::CreateBufferUsageAndFormatExceptionList();
}
void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
@@ -542,38 +588,16 @@ bool GpuDataManagerImplPrivate::SwiftShaderAllowed() const {
}
void GpuDataManagerImplPrivate::OnGpuBlocked() {
+ base::Optional<gpu::GpuFeatureInfo> gpu_feature_info_for_hardware_gpu;
+ if (gpu_feature_info_.IsInitialized())
+ gpu_feature_info_for_hardware_gpu = gpu_feature_info_;
gpu::GpuFeatureInfo gpu_feature_info = gpu::ComputeGpuFeatureInfoWithNoGpu();
- UpdateGpuFeatureInfo(gpu_feature_info);
+ UpdateGpuFeatureInfo(gpu_feature_info, gpu_feature_info_for_hardware_gpu);
// Some observers might be waiting.
NotifyGpuInfoUpdate();
}
-void GpuDataManagerImplPrivate::GetBlacklistReasons(
- base::ListValue* reasons) const {
- if (!gpu_feature_info_.applied_gpu_blacklist_entries.empty()) {
- std::unique_ptr<gpu::GpuBlacklist> blacklist(gpu::GpuBlacklist::Create());
- blacklist->GetReasons(reasons, "disabledFeatures",
- gpu_feature_info_.applied_gpu_blacklist_entries);
- }
- if (!gpu_feature_info_.applied_gpu_driver_bug_list_entries.empty()) {
- std::unique_ptr<gpu::GpuDriverBugList> bug_list(
- gpu::GpuDriverBugList::Create());
- bug_list->GetReasons(reasons, "workarounds",
- gpu_feature_info_.applied_gpu_driver_bug_list_entries);
- }
-}
-
-std::vector<std::string>
-GpuDataManagerImplPrivate::GetDriverBugWorkarounds() const {
- std::vector<std::string> workarounds;
- for (auto workaround : gpu_feature_info_.enabled_gpu_driver_bug_workarounds) {
- workarounds.push_back(gpu::GpuDriverBugWorkaroundTypeToString(
- static_cast<gpu::GpuDriverBugWorkaroundType>(workaround)));
- }
- return workarounds;
-}
-
void GpuDataManagerImplPrivate::AddLogMessage(
int level, const std::string& header, const std::string& message) {
// Some clients emit many log messages. This has been observed to consume GBs
@@ -660,18 +684,6 @@ bool GpuDataManagerImplPrivate::UpdateActiveGpu(uint32_t vendor_id,
return true;
}
-void GpuDataManagerImplPrivate::GetDisabledExtensions(
- std::string* disabled_extensions) const {
- DCHECK(disabled_extensions);
- *disabled_extensions = gpu_feature_info_.disabled_extensions;
-}
-
-void GpuDataManagerImplPrivate::GetDisabledWebGLExtensions(
- std::string* disabled_webgl_extensions) const {
- DCHECK(disabled_webgl_extensions);
- *disabled_webgl_extensions = gpu_feature_info_.disabled_webgl_extensions;
-}
-
void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) {
BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now());
@@ -735,6 +747,15 @@ void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::OnGpuInfoUpdate);
}
+bool GpuDataManagerImplPrivate::IsGpuProcessUsingHardwareGpu() const {
+ if (base::StartsWith(gpu_info_.gl_renderer, "Google SwiftShader",
+ base::CompareCase::SENSITIVE))
+ return false;
+ if (gpu_info_.gl_renderer == "Disabled")
+ return false;
+ return true;
+}
+
std::string GpuDataManagerImplPrivate::GetDomainFromURL(
const GURL& url) const {
// For the moment, we just use the host, or its IP address, as the
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
index 08b4cae2f11..a84efd1a461 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -41,6 +41,7 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void BlacklistWebGLForTesting();
gpu::GPUInfo GetGPUInfo() const;
+ gpu::GPUInfo GetGPUInfoForHardwareGpu() const;
bool GpuAccessAllowed(std::string* reason) const;
bool GpuProcessStartAllowed() const;
void RequestCompleteGpuInfoIfNeeded();
@@ -59,18 +60,19 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void BlockSwiftShader();
bool SwiftShaderAllowed() const;
- void UpdateGpuInfo(const gpu::GPUInfo& gpu_info);
- void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info);
+ void UpdateGpuInfo(
+ const gpu::GPUInfo& gpu_info,
+ const base::Optional<gpu::GPUInfo>& optional_gpu_info_for_hardware_gpu);
+ void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu);
gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
+ gpu::GpuFeatureInfo GetGpuFeatureInfoForHardwareGpu() const;
void AppendGpuCommandLine(base::CommandLine* command_line) const;
void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences) const;
- void GetBlacklistReasons(base::ListValue* reasons) const;
-
- std::vector<std::string> GetDriverBugWorkarounds() const;
-
void AddLogMessage(int level,
const std::string& header,
const std::string& message);
@@ -81,9 +83,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void HandleGpuSwitch();
- void GetDisabledExtensions(std::string* disabled_extensions) const;
- void GetDisabledWebGLExtensions(std::string* disabled_webgl_extensions) const;
-
void BlockDomainFrom3DAPIs(
const GURL& url, GpuDataManagerImpl::DomainGuilt guilt);
bool Are3DAPIsBlocked(const GURL& top_origin_url,
@@ -105,6 +104,8 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// Notify all observers whenever there is a GPU info update.
void NotifyGpuInfoUpdate();
+ bool IsGpuProcessUsingHardwareGpu() const;
+
virtual ~GpuDataManagerImplPrivate();
private:
@@ -171,11 +172,14 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
bool complete_gpu_info_already_requested_;
- // Eventually |blacklisted_features_| should be folded in to this.
gpu::GpuFeatureInfo gpu_feature_info_;
-
gpu::GPUInfo gpu_info_;
+ // What we would have gotten if we haven't fallen back to SwiftShader or
+ // pure software (in the viz case).
+ gpu::GpuFeatureInfo gpu_feature_info_for_hardware_gpu_;
+ gpu::GPUInfo gpu_info_for_hardware_gpu_;
+
const scoped_refptr<GpuDataManagerObserverList> observer_list_;
// Contains the 1000 most recent log messages.
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
index 252ca41c2b6..a105555d01f 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
@@ -140,7 +140,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) {
EXPECT_FALSE(observer.gpu_info_updated());
gpu::GPUInfo gpu_info;
- manager->UpdateGpuInfo(gpu_info);
+ manager->UpdateGpuInfo(gpu_info, base::nullopt);
{
base::RunLoop run_loop;
run_loop.RunUntilIdle();
diff --git a/chromium/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h b/chromium/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
index 41bda617020..16551fd1890 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
@@ -46,13 +46,14 @@ const GpuControlList::GLStrings kGLStringsForEntry5Exception0 = {
nullptr, ".*GeForce.*", nullptr, nullptr,
};
-const int kFeatureListForEntry6[9] = {
+const int kFeatureListForEntry6[10] = {
GPU_FEATURE_TYPE_FLASH_STAGE3D,
GPU_FEATURE_TYPE_GPU_COMPOSITING,
GPU_FEATURE_TYPE_GPU_RASTERIZATION,
GPU_FEATURE_TYPE_FLASH3D,
GPU_FEATURE_TYPE_ACCELERATED_WEBGL2,
GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
+ GPU_FEATURE_TYPE_PROTECTED_VIDEO_DECODE,
GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE,
GPU_FEATURE_TYPE_ACCELERATED_WEBGL,
GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE,
diff --git a/chromium/content/browser/gpu/gpu_data_manager_testing_autogen.cc b/chromium/content/browser/gpu/gpu_data_manager_testing_autogen.cc
index 43b1d394874..adb983a9cce 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_testing_autogen.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_testing_autogen.cc
@@ -19,14 +19,14 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
{
1, // id
"GpuDataManagerImplPrivateTest.GpuSideBlacklisting.0",
- arraysize(kFeatureListForEntry1), // features size
- kFeatureListForEntry1, // features
- 0, // DisabledExtensions size
- nullptr, // DisabledExtensions
- 0, // DisabledWebGLExtensions size
- nullptr, // DisabledWebGLExtensions
- 0, // CrBugs size
- nullptr, // CrBugs
+ base::size(kFeatureListForEntry1), // features size
+ kFeatureListForEntry1, // features
+ 0, // DisabledExtensions size
+ nullptr, // DisabledExtensions
+ 0, // DisabledWebGLExtensions size
+ nullptr, // DisabledWebGLExtensions
+ 0, // CrBugs size
+ nullptr, // CrBugs
{
GpuControlList::kOsAny, // os_type
{GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical,
@@ -39,6 +39,8 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
nullptr, // driver info
nullptr, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
0, // exceptions count
@@ -47,14 +49,14 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
{
2, // id
"GpuDataManagerImplPrivateTest.GpuSideBlacklisting.1",
- arraysize(kFeatureListForEntry2), // features size
- kFeatureListForEntry2, // features
- 0, // DisabledExtensions size
- nullptr, // DisabledExtensions
- 0, // DisabledWebGLExtensions size
- nullptr, // DisabledWebGLExtensions
- 0, // CrBugs size
- nullptr, // CrBugs
+ base::size(kFeatureListForEntry2), // features size
+ kFeatureListForEntry2, // features
+ 0, // DisabledExtensions size
+ nullptr, // DisabledExtensions
+ 0, // DisabledWebGLExtensions size
+ nullptr, // DisabledWebGLExtensions
+ 0, // CrBugs size
+ nullptr, // CrBugs
{
GpuControlList::kOsAny, // os_type
{GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical,
@@ -67,6 +69,8 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
nullptr, // driver info
&kGLStringsForEntry2, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
0, // exceptions count
@@ -75,14 +79,14 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
{
3, // id
"GpuDataManagerImplPrivateTest.GpuSideBlacklistingWebGL.0",
- arraysize(kFeatureListForEntry3), // features size
- kFeatureListForEntry3, // features
- 0, // DisabledExtensions size
- nullptr, // DisabledExtensions
- 0, // DisabledWebGLExtensions size
- nullptr, // DisabledWebGLExtensions
- 0, // CrBugs size
- nullptr, // CrBugs
+ base::size(kFeatureListForEntry3), // features size
+ kFeatureListForEntry3, // features
+ 0, // DisabledExtensions size
+ nullptr, // DisabledExtensions
+ 0, // DisabledWebGLExtensions size
+ nullptr, // DisabledWebGLExtensions
+ 0, // CrBugs size
+ nullptr, // CrBugs
{
GpuControlList::kOsAny, // os_type
{GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical,
@@ -95,6 +99,8 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
nullptr, // driver info
nullptr, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
0, // exceptions count
@@ -103,14 +109,14 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
{
4, // id
"GpuDataManagerImplPrivateTest.GpuSideBlacklistingWebGL.1",
- arraysize(kFeatureListForEntry4), // features size
- kFeatureListForEntry4, // features
- 0, // DisabledExtensions size
- nullptr, // DisabledExtensions
- 0, // DisabledWebGLExtensions size
- nullptr, // DisabledWebGLExtensions
- 0, // CrBugs size
- nullptr, // CrBugs
+ base::size(kFeatureListForEntry4), // features size
+ kFeatureListForEntry4, // features
+ 0, // DisabledExtensions size
+ nullptr, // DisabledExtensions
+ 0, // DisabledWebGLExtensions size
+ nullptr, // DisabledWebGLExtensions
+ 0, // CrBugs size
+ nullptr, // CrBugs
{
GpuControlList::kOsAny, // os_type
{GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical,
@@ -123,6 +129,8 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
nullptr, // driver info
&kGLStringsForEntry4, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
0, // exceptions count
@@ -131,14 +139,14 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
{
5, // id
"GpuDataManagerImplPrivateTest.GpuSideException",
- arraysize(kFeatureListForEntry5), // features size
- kFeatureListForEntry5, // features
- 0, // DisabledExtensions size
- nullptr, // DisabledExtensions
- 0, // DisabledWebGLExtensions size
- nullptr, // DisabledWebGLExtensions
- 0, // CrBugs size
- nullptr, // CrBugs
+ base::size(kFeatureListForEntry5), // features size
+ kFeatureListForEntry5, // features
+ 0, // DisabledExtensions size
+ nullptr, // DisabledExtensions
+ 0, // DisabledWebGLExtensions size
+ nullptr, // DisabledWebGLExtensions
+ 0, // CrBugs size
+ nullptr, // CrBugs
{
GpuControlList::kOsAny, // os_type
{GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical,
@@ -151,22 +159,24 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
nullptr, // driver info
nullptr, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
- arraysize(kExceptionsForEntry5), // exceptions count
- kExceptionsForEntry5, // exceptions
+ base::size(kExceptionsForEntry5), // exceptions count
+ kExceptionsForEntry5, // exceptions
},
{
6, // id
"GpuDataManagerImplPrivateTest.BlacklistAllFeatures",
- arraysize(kFeatureListForEntry6), // features size
- kFeatureListForEntry6, // features
- 0, // DisabledExtensions size
- nullptr, // DisabledExtensions
- 0, // DisabledWebGLExtensions size
- nullptr, // DisabledWebGLExtensions
- 0, // CrBugs size
- nullptr, // CrBugs
+ base::size(kFeatureListForEntry6), // features size
+ kFeatureListForEntry6, // features
+ 0, // DisabledExtensions size
+ nullptr, // DisabledExtensions
+ 0, // DisabledWebGLExtensions size
+ nullptr, // DisabledWebGLExtensions
+ 0, // CrBugs size
+ nullptr, // CrBugs
{
GpuControlList::kOsAny, // os_type
{GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical,
@@ -179,6 +189,8 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
nullptr, // driver info
nullptr, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
0, // exceptions count
@@ -187,14 +199,14 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
{
7, // id
"GpuDataManagerImplPrivateTest.UpdateActiveGpu",
- arraysize(kFeatureListForEntry7), // features size
- kFeatureListForEntry7, // features
- 0, // DisabledExtensions size
- nullptr, // DisabledExtensions
- 0, // DisabledWebGLExtensions size
- nullptr, // DisabledWebGLExtensions
- 0, // CrBugs size
- nullptr, // CrBugs
+ base::size(kFeatureListForEntry7), // features size
+ kFeatureListForEntry7, // features
+ 0, // DisabledExtensions size
+ nullptr, // DisabledExtensions
+ 0, // DisabledWebGLExtensions size
+ nullptr, // DisabledWebGLExtensions
+ 0, // CrBugs size
+ nullptr, // CrBugs
{
GpuControlList::kOsAny, // os_type
{GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical,
@@ -207,6 +219,8 @@ const GpuControlList::Entry kGpuDataManagerTestingEntries[] = {
nullptr, // driver info
nullptr, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
0, // exceptions count
diff --git a/chromium/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h b/chromium/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h
index 12a2a5491da..9c282eee67a 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h
@@ -25,6 +25,8 @@ const GpuControlList::Conditions kExceptionsForEntry5[1] = {
nullptr, // driver info
&kGLStringsForEntry5Exception0, // GL strings
nullptr, // machine model info
+ 0, // gpu_series size
+ nullptr, // gpu_series
nullptr, // more conditions
},
};
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 210eb5fe2da..54537e236ac 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -110,6 +110,27 @@ std::unique_ptr<base::ListValue> DxDiagNodeToList(const gpu::DxDiagNode& node) {
}
return list;
}
+
+std::string D3dFeaturelevelToString(uint32_t d3d_feature_level) {
+ if (d3d_feature_level == 0) {
+ return "Not supported";
+ } else {
+ return base::StringPrintf("D3D %d.%d", (d3d_feature_level >> 12) & 0xF,
+ (d3d_feature_level >> 8) & 0xF);
+ }
+}
+
+std::string VulkanVersionToString(uint32_t vulkan_version) {
+ if (vulkan_version == 0) {
+ return "Not supported";
+ } else {
+ // Vulkan version number VK_MAKE_VERSION(major, minor, patch)
+ // (((major) << 22) | ((minor) << 12) | (patch))
+ return base::StringPrintf(
+ "Vulkan API %d.%d.%d", (vulkan_version >> 22) & 0x3FF,
+ (vulkan_version >> 12) & 0x3FF, vulkan_version & 0xFFF);
+ }
+}
#endif
std::string GPUDeviceToString(const gpu::GPUInfo::GPUDevice& gpu) {
@@ -123,8 +144,9 @@ std::string GPUDeviceToString(const gpu::GPUInfo::GPUDevice& gpu) {
vendor.c_str(), device.c_str(), gpu.active ? " *ACTIVE*" : "");
}
-std::unique_ptr<base::DictionaryValue> GpuInfoAsDictionaryValue() {
- gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+std::unique_ptr<base::ListValue> BasicGpuInfoAsListValue(
+ const gpu::GPUInfo& gpu_info,
+ const gpu::GpuFeatureInfo& gpu_feature_info) {
auto basic_info = std::make_unique<base::ListValue>();
basic_info->Append(NewDescriptionValuePair(
"Initialization time",
@@ -177,21 +199,14 @@ std::unique_ptr<base::DictionaryValue> GpuInfoAsDictionaryValue() {
}
basic_info->Append(NewDescriptionValuePair(
- "DX12", std::make_unique<base::Value>(gpu_info.supports_dx12)));
-
- basic_info->Append(NewDescriptionValuePair(
- "Vulkan", std::make_unique<base::Value>(gpu_info.supports_vulkan)));
+ "Driver D3D12 feature level",
+ D3dFeaturelevelToString(gpu_info.d3d12_feature_level)));
+ basic_info->Append(
+ NewDescriptionValuePair("Driver Vulkan API version",
+ VulkanVersionToString(gpu_info.vulkan_version)));
#endif
- std::string disabled_extensions;
- GpuDataManagerImpl::GetInstance()->GetDisabledExtensions(
- &disabled_extensions);
-
- std::string disabled_webgl_extensions;
- GpuDataManagerImpl::GetInstance()->GetDisabledWebGLExtensions(
- &disabled_webgl_extensions);
-
basic_info->Append(
NewDescriptionValuePair("Driver vendor", gpu_info.driver_vendor));
basic_info->Append(NewDescriptionValuePair("Driver version",
@@ -216,10 +231,10 @@ std::unique_ptr<base::DictionaryValue> GpuInfoAsDictionaryValue() {
gpu_info.gl_version));
basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS",
gpu_info.gl_extensions));
- basic_info->Append(NewDescriptionValuePair("Disabled Extensions",
- disabled_extensions));
- basic_info->Append(NewDescriptionValuePair("Disabled WebGL Extensions",
- disabled_webgl_extensions));
+ basic_info->Append(NewDescriptionValuePair(
+ "Disabled Extensions", gpu_feature_info.disabled_extensions));
+ basic_info->Append(NewDescriptionValuePair(
+ "Disabled WebGL Extensions", gpu_feature_info.disabled_webgl_extensions));
basic_info->Append(NewDescriptionValuePair("Window system binding vendor",
gpu_info.gl_ws_vendor));
basic_info->Append(NewDescriptionValuePair("Window system binding version",
@@ -256,8 +271,25 @@ std::unique_ptr<base::DictionaryValue> GpuInfoAsDictionaryValue() {
"GPU process crash count",
std::make_unique<base::Value>(GpuProcessHost::GetGpuCrashCount())));
+#if defined(USE_X11)
+ basic_info->Append(NewDescriptionValuePair(
+ "System visual ID", base::NumberToString(gpu_info.system_visual)));
+ basic_info->Append(NewDescriptionValuePair(
+ "RGBA visual ID", base::NumberToString(gpu_info.rgba_visual)));
+#endif
+
+ return basic_info;
+}
+
+std::unique_ptr<base::DictionaryValue> GpuInfoAsDictionaryValue() {
auto info = std::make_unique<base::DictionaryValue>();
+ const gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+ const gpu::GpuFeatureInfo gpu_feature_info =
+ GpuDataManagerImpl::GetInstance()->GetGpuFeatureInfo();
+ auto basic_info = BasicGpuInfoAsListValue(gpu_info, gpu_feature_info);
+ info->Set("basicInfo", std::move(basic_info));
+
#if defined(OS_WIN)
auto dx_info = std::make_unique<base::Value>();
if (gpu_info.dx_diagnostics.children.size())
@@ -265,14 +297,6 @@ std::unique_ptr<base::DictionaryValue> GpuInfoAsDictionaryValue() {
info->Set("diagnostics", std::move(dx_info));
#endif
-#if defined(USE_X11)
- basic_info->Append(NewDescriptionValuePair(
- "System visual ID", base::NumberToString(gpu_info.system_visual)));
- basic_info->Append(NewDescriptionValuePair(
- "RGBA visual ID", base::NumberToString(gpu_info.rgba_visual)));
-#endif
-
- info->Set("basic_info", std::move(basic_info));
return info;
}
@@ -284,6 +308,8 @@ const char* BufferUsageToString(gfx::BufferUsage usage) {
return "SCANOUT";
case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
return "SCANOUT_CAMERA_READ_WRITE";
+ case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE:
+ return "CAMERA_AND_CPU_READ_WRITE";
case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
return "SCANOUT_CPU_READ_WRITE";
case gfx::BufferUsage::SCANOUT_VDA_WRITE:
@@ -603,18 +629,41 @@ std::unique_ptr<base::ListValue> GpuMessageHandler::OnRequestLogMessages(
void GpuMessageHandler::OnGpuInfoUpdate() {
// Get GPU Info.
- std::unique_ptr<base::DictionaryValue> gpu_info_val(
- GpuInfoAsDictionaryValue());
+ const gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+ auto gpu_info_val = GpuInfoAsDictionaryValue();
// Add in blacklisting features
auto feature_status = std::make_unique<base::DictionaryValue>();
feature_status->Set("featureStatus", GetFeatureStatus());
feature_status->Set("problems", GetProblems());
auto workarounds = std::make_unique<base::ListValue>();
- for (const std::string& workaround : GetDriverBugWorkarounds())
+ for (const auto& workaround : GetDriverBugWorkarounds())
workarounds->AppendString(workaround);
feature_status->Set("workarounds", std::move(workarounds));
gpu_info_val->Set("featureStatus", std::move(feature_status));
+ if (!GpuDataManagerImpl::GetInstance()->IsGpuProcessUsingHardwareGpu()) {
+ auto feature_status_for_hardware_gpu =
+ std::make_unique<base::DictionaryValue>();
+ feature_status_for_hardware_gpu->Set("featureStatus",
+ GetFeatureStatusForHardwareGpu());
+ feature_status_for_hardware_gpu->Set("problems",
+ GetProblemsForHardwareGpu());
+ auto workarounds_for_hardware_gpu = std::make_unique<base::ListValue>();
+ for (const auto& workaround : GetDriverBugWorkaroundsForHardwareGpu())
+ workarounds_for_hardware_gpu->AppendString(workaround);
+ feature_status_for_hardware_gpu->Set(
+ "workarounds", std::move(workarounds_for_hardware_gpu));
+ gpu_info_val->Set("featureStatusForHardwareGpu",
+ std::move(feature_status_for_hardware_gpu));
+ const gpu::GPUInfo gpu_info_for_hardware_gpu =
+ GpuDataManagerImpl::GetInstance()->GetGPUInfoForHardwareGpu();
+ const gpu::GpuFeatureInfo gpu_feature_info_for_hardware_gpu =
+ GpuDataManagerImpl::GetInstance()->GetGpuFeatureInfoForHardwareGpu();
+ auto gpu_info_for_hardware_gpu_val = BasicGpuInfoAsListValue(
+ gpu_info_for_hardware_gpu, gpu_feature_info_for_hardware_gpu);
+ gpu_info_val->Set("basicInfoForHardwareGpu",
+ std::move(gpu_info_for_hardware_gpu_val));
+ }
gpu_info_val->Set("compositorInfo", CompositorInfo());
gpu_info_val->Set("gpuMemoryBufferInfo", GpuMemoryBufferInfo());
gpu_info_val->Set("displayInfo", getDisplayInfo());
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index c68ef4f4382..72708d0f0c7 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -51,7 +51,6 @@
#include "content/public/common/connection_filter.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_channel_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_manager_connection.h"
@@ -117,11 +116,64 @@ int GpuProcessHost::display_compositor_recent_crash_count_ = 0;
namespace {
+// This matches base::TerminationStatus.
+// These values are persisted to logs. Entries (except MAX_ENUM) should not be
+// renumbered and numeric values should never be reused. Should also avoid
+// OS-defines in this enum to keep the values consistent on all platforms.
+enum class GpuTerminationStatus {
+ NORMAL_TERMINATION = 0,
+ ABNORMAL_TERMINATION = 1,
+ PROCESS_WAS_KILLED = 2,
+ PROCESS_CRASHED = 3,
+ STILL_RUNNING = 4,
+ PROCESS_WAS_KILLED_BY_OOM = 5,
+ OOM_PROTECTED = 6,
+ LAUNCH_FAILED = 7,
+ OOM = 8,
+ MAX_ENUM = 9,
+};
+
+GpuTerminationStatus ConvertToGpuTerminationStatus(
+ base::TerminationStatus status) {
+ switch (status) {
+ case base::TERMINATION_STATUS_NORMAL_TERMINATION:
+ return GpuTerminationStatus::NORMAL_TERMINATION;
+ case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
+ return GpuTerminationStatus::ABNORMAL_TERMINATION;
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
+ return GpuTerminationStatus::PROCESS_WAS_KILLED;
+ case base::TERMINATION_STATUS_PROCESS_CRASHED:
+ return GpuTerminationStatus::PROCESS_CRASHED;
+ case base::TERMINATION_STATUS_STILL_RUNNING:
+ return GpuTerminationStatus::STILL_RUNNING;
+#if defined(OS_CHROMEOS)
+ case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
+ return GpuTerminationStatus::PROCESS_WAS_KILLED_BY_OOM;
+#endif
+#if defined(OS_ANDROID)
+ case base::TERMINATION_STATUS_OOM_PROTECTED:
+ return GpuTerminationStatus::OOM_PROTECTED;
+#endif
+ case base::TERMINATION_STATUS_LAUNCH_FAILED:
+ return GpuTerminationStatus::LAUNCH_FAILED;
+ case base::TERMINATION_STATUS_OOM:
+ return GpuTerminationStatus::OOM;
+ case base::TERMINATION_STATUS_MAX_ENUM:
+ NOTREACHED();
+ return GpuTerminationStatus::MAX_ENUM;
+ // Do not add default.
+ }
+ NOTREACHED();
+ return GpuTerminationStatus::ABNORMAL_TERMINATION;
+}
+
// Command-line switches to propagate to the GPU process.
static const char* const kSwitchNames[] = {
service_manager::switches::kDisableSeccompFilterSandbox,
service_manager::switches::kGpuSandboxAllowSysVShm,
service_manager::switches::kGpuSandboxFailuresFatal,
+ service_manager::switches::kDisableGpuSandbox,
+ service_manager::switches::kNoSandbox,
#if defined(OS_WIN)
service_manager::switches::kAddGpuAppContainerCaps,
service_manager::switches::kDisableGpuAppContainer,
@@ -130,18 +182,14 @@ static const char* const kSwitchNames[] = {
#endif // defined(OS_WIN)
switches::kDisableBreakpad,
switches::kDisableGpuRasterization,
- switches::kDisableGpuSandbox,
switches::kDisableGLExtensions,
switches::kDisableLogging,
switches::kDisableShaderNameHashing,
-#if BUILDFLAG(ENABLE_WEBRTC)
switches::kDisableWebRtcHWEncoding,
-#endif
#if defined(OS_WIN)
switches::kEnableAcceleratedVpxDecode,
#endif
switches::kEnableGpuRasterization,
- switches::kEnableHeapProfiling,
switches::kEnableLogging,
switches::kEnableOOPRasterization,
switches::kEnableVizDevTools,
@@ -149,7 +197,6 @@ static const char* const kSwitchNames[] = {
switches::kLoggingLevel,
switches::kEnableLowEndDeviceMode,
switches::kDisableLowEndDeviceMode,
- switches::kNoSandbox,
switches::kRunAllCompositorStagesBeforeDraw,
switches::kTestGLLib,
switches::kTraceToConsole,
@@ -158,10 +205,10 @@ static const char* const kSwitchNames[] = {
switches::kV,
switches::kVModule,
#if defined(OS_MACOSX)
+ service_manager::switches::kEnableSandboxLogging,
switches::kDisableAVFoundationOverlays,
switches::kDisableMacOverlays,
switches::kDisableRemoteCoreAnimation,
- switches::kEnableSandboxLogging,
switches::kShowMacOverlayBorders,
#endif
#if defined(USE_OZONE)
@@ -343,7 +390,7 @@ class GpuSandboxedProcessLauncherDelegate
service_manager::SandboxType GetSandboxType() override {
#if defined(OS_WIN)
- if (cmd_line_.HasSwitch(switches::kDisableGpuSandbox)) {
+ if (cmd_line_.HasSwitch(service_manager::switches::kDisableGpuSandbox)) {
DVLOG(1) << "GPU sandbox is disabled";
return service_manager::SANDBOX_TYPE_NO_SANDBOX;
}
@@ -395,7 +442,7 @@ void BindDiscardableMemoryRequestOnUI(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(USE_AURA)
- if (features::IsMusEnabled()) {
+ if (features::IsMashEnabled()) {
ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
ui::mojom::kServiceName, std::move(request));
return;
@@ -532,6 +579,16 @@ void GpuProcessHost::CallOnIO(
void GpuProcessHost::BindInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
+ if (interface_name ==
+ discardable_memory::mojom::DiscardableSharedMemoryManager::Name_) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &BindDiscardableMemoryRequestOnUI,
+ discardable_memory::mojom::DiscardableSharedMemoryManagerRequest(
+ std::move(interface_pipe))));
+ return;
+ }
process_->child_connection()->BindInterface(interface_name,
std::move(interface_pipe));
}
@@ -631,23 +688,22 @@ GpuProcessHost::~GpuProcessHost() {
std::string message;
bool block_offscreen_contexts = true;
if (!in_process_ && process_launched_) {
- int exit_code;
- base::TerminationStatus status = process_->GetTerminationStatus(
- false /* known_dead */, &exit_code);
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus",
- status,
- base::TERMINATION_STATUS_MAX_ENUM);
-
- if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
- status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
- status == base::TERMINATION_STATUS_PROCESS_CRASHED) {
+ ChildProcessTerminationInfo info =
+ process_->GetTerminationInfo(false /* known_dead */);
+ UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessTerminationStatus2",
+ ConvertToGpuTerminationStatus(info.status),
+ GpuTerminationStatus::MAX_ENUM);
+
+ if (info.status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
+ info.status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
+ info.status == base::TERMINATION_STATUS_PROCESS_CRASHED) {
// Windows always returns PROCESS_CRASHED on abnormal termination, as it
// doesn't have a way to distinguish the two.
base::UmaHistogramSparse("GPU.GPUProcessExitCode",
- std::max(0, std::min(100, exit_code)));
+ std::max(0, std::min(100, info.exit_code)));
}
- switch (status) {
+ switch (info.status) {
case base::TERMINATION_STATUS_NORMAL_TERMINATION:
// Don't block offscreen contexts (and force page reload for webgl)
// if this was an intentional shutdown or the OOM killer on Android
@@ -660,9 +716,8 @@ GpuProcessHost::~GpuProcessHost() {
message = "The GPU process exited normally. Everything is okay.";
break;
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
- message = base::StringPrintf(
- "The GPU process exited with code %d.",
- exit_code);
+ message = base::StringPrintf("The GPU process exited with code %d.",
+ info.exit_code);
break;
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
message = "You killed the GPU process! Why?";
@@ -1025,13 +1080,18 @@ void GpuProcessHost::OnProcessCrashed(int exit_code) {
}
SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
RecordProcessCrash();
- GpuDataManagerImpl::GetInstance()->ProcessCrashed(
- process_->GetTerminationStatus(true /* known_dead */, nullptr));
+
+ ChildProcessTerminationInfo info =
+ process_->GetTerminationInfo(true /* known_dead */);
+ GpuDataManagerImpl::GetInstance()->ProcessCrashed(info.status);
}
void GpuProcessHost::DidInitialize(
const gpu::GPUInfo& gpu_info,
- const gpu::GpuFeatureInfo& gpu_feature_info) {
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu) {
UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", true);
status_ = SUCCESS;
@@ -1047,8 +1107,9 @@ void GpuProcessHost::DidInitialize(
GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
// Update GpuFeatureInfo first, because UpdateGpuInfo() will notify all
// listeners.
- gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info);
- gpu_data_manager->UpdateGpuInfo(gpu_info);
+ gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info,
+ gpu_feature_info_for_hardware_gpu);
+ gpu_data_manager->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
RunRequestGPUInfoCallbacks(gpu_data_manager->GetGPUInfo());
}
@@ -1233,7 +1294,7 @@ bool GpuProcessHost::LaunchGpuProcess() {
#endif // defined(OS_WIN)
if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
- cmd_line->AppendSwitch(switches::kDisableGpuSandbox);
+ cmd_line->AppendSwitch(service_manager::switches::kDisableGpuSandbox);
// TODO(penghuang): Replace all GPU related switches with GpuPreferences.
// https://crbug.com/590825
@@ -1245,6 +1306,9 @@ bool GpuProcessHost::LaunchGpuProcess() {
browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost,
switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches);
+ if (browser_command_line.HasSwitch(switches::kDisableFrameRateLimit))
+ cmd_line->AppendSwitch(switches::kDisableGpuVsync);
+
std::vector<const char*> gpu_workarounds;
gpu::GpuDriverBugList::AppendAllWorkarounds(&gpu_workarounds);
cmd_line->CopySwitchesFrom(browser_command_line, gpu_workarounds.data(),
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index 51b57b61eb4..e08bcf72fc1 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -84,7 +84,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
BufferCreationStatus status)>;
using RequestGPUInfoCallback = base::Callback<void(const gpu::GPUInfo&)>;
- using RequestHDRStatusCallback = base::Callback<void(bool)>;
+ using RequestHDRStatusCallback = base::RepeatingCallback<void(bool)>;
static int GetGpuCrashCount();
@@ -203,8 +203,12 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void OnProcessCrashed(int exit_code) override;
// viz::mojom::GpuHost:
- void DidInitialize(const gpu::GPUInfo& gpu_info,
- const gpu::GpuFeatureInfo& gpu_feature_info) override;
+ void DidInitialize(
+ const gpu::GPUInfo& gpu_info,
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu) override;
void DidFailInitialize() override;
void DidCreateContextSuccessfully() override;
void DidCreateOffscreenContext(const GURL& url) override;
diff --git a/chromium/content/browser/histogram_internals_request_job.cc b/chromium/content/browser/histogram_internals_request_job.cc
deleted file mode 100644
index 3bb2bcf977e..00000000000
--- a/chromium/content/browser/histogram_internals_request_job.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/histogram_internals_request_job.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/statistics_recorder.h"
-#include "content/browser/histogram_synchronizer.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/escape.h"
-#include "net/base/net_errors.h"
-#include "net/url_request/url_request.h"
-#include "url/gurl.h"
-
-namespace content {
-
-HistogramInternalsRequestJob::HistogramInternalsRequestJob(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate)
- : net::URLRequestSimpleJob(request, network_delegate),
- url_(request->url()),
- weak_factory_(this) {}
-
-HistogramInternalsRequestJob::~HistogramInternalsRequestJob() {}
-
-std::string HistogramInternalsRequestJob::GenerateHTML(const GURL& url) {
- const std::string& spec = url.possibly_invalid_spec();
- const url::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
- // + 1 to skip the slash at the beginning of the path.
- int offset = parsed.CountCharactersBefore(url::Parsed::PATH, false) + 1;
-
- std::string path;
- if (offset < static_cast<int>(spec.size()))
- path = spec.substr(offset);
-
- HistogramSynchronizer::FetchHistograms();
-
- std::string unescaped_query;
- std::string unescaped_title("About Histograms");
- if (!path.empty()) {
- unescaped_query = net::UnescapeURLComponent(path,
- net::UnescapeRule::NORMAL);
- unescaped_title += " - " + unescaped_query;
- }
-
- std::string data;
- data.append("<!DOCTYPE html>\n<html>\n<head>\n");
- data.append(
- "<meta http-equiv=\"Content-Security-Policy\" "
- "content=\"object-src 'none'; script-src 'none'\">");
- data.append("<title>");
- data.append(net::EscapeForHTML(unescaped_title));
- data.append("</title>\n");
- data.append("</head><body>");
-
- // Display any stats for which we sent off requests the last time.
- data.append(
- "<p>Stats accumulated since browser startup. Reload to refresh.</p>\n");
-
- base::StatisticsRecorder::WriteHTMLGraph(unescaped_query, &data);
- return data;
-}
-
-void HistogramInternalsRequestJob::Start() {
- // First import histograms from all providers and then start the URL fetch
- // job. It's not possible to call URLRequestSimpleJob::Start through Bind,
- // it ends up re-calling this method, so a small helper method is used.
- content::BrowserThread::PostTaskAndReply(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(&base::StatisticsRecorder::ImportProvidedHistograms),
- base::BindOnce(&HistogramInternalsRequestJob::StartUrlRequest,
- weak_factory_.GetWeakPtr()));
-}
-
-int HistogramInternalsRequestJob::GetData(
- std::string* mime_type,
- std::string* charset,
- std::string* data,
- const net::CompletionCallback& callback) const {
- mime_type->assign("text/html");
- charset->assign("UTF8");
-
- *data = GenerateHTML(url_);
- return net::OK;
-}
-
-void HistogramInternalsRequestJob::StartUrlRequest() {
- URLRequestSimpleJob::Start();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/histogram_internals_request_job.h b/chromium/content/browser/histogram_internals_request_job.h
deleted file mode 100644
index 1dd090233db..00000000000
--- a/chromium/content/browser/histogram_internals_request_job.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_HISTOGRAM_INTERNALS_REQUEST_JOB_H_
-#define CONTENT_BROWSER_HISTOGRAM_INTERNALS_REQUEST_JOB_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "net/url_request/url_request_simple_job.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class HistogramInternalsRequestJob : public net::URLRequestSimpleJob {
- public:
- HistogramInternalsRequestJob(net::URLRequest* request,
- net::NetworkDelegate* network_delegate);
-
- // net::URLRequestSimpleJob:
- void Start() override;
- int GetData(std::string* mime_type,
- std::string* charset,
- std::string* data,
- const net::CompletionCallback& callback) const override;
-
- // Generates the HTML for chrome://histograms. If |url| has a path, it's used
- // to display a single histogram.
- // base::StatisticsRecorder::ImportProvidedHistograms must have been called
- // on the UI thread first.
- static std::string GenerateHTML(const GURL& url);
-
- private:
- ~HistogramInternalsRequestJob() override;
-
- // Starts the real URL request.
- void StartUrlRequest();
-
- // The URL that was requested, which might have a path component to a specific
- // histogram.
- GURL url_;
-
- base::WeakPtrFactory<HistogramInternalsRequestJob> weak_factory_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(HistogramInternalsRequestJob);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_HISTOGRAM_INTERNALS_REQUEST_JOB_H_
diff --git a/chromium/content/browser/histogram_internals_url_loader.cc b/chromium/content/browser/histogram_internals_url_loader.cc
deleted file mode 100644
index 63cbaa16931..00000000000
--- a/chromium/content/browser/histogram_internals_url_loader.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2017 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/histogram_internals_url_loader.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/statistics_recorder.h"
-#include "content/browser/histogram_internals_request_job.h"
-#include "mojo/public/cpp/system/data_pipe_utils.h"
-
-namespace content {
-
-void StartHistogramInternalsURLLoader(
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client) {
- scoped_refptr<net::HttpResponseHeaders> headers(
- new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
- network::ResourceResponseHead resource_response;
- resource_response.headers = headers;
- resource_response.mime_type = "text/html";
- client->OnReceiveResponse(resource_response, nullptr);
-
- base::StatisticsRecorder::ImportProvidedHistograms();
- std::string data = HistogramInternalsRequestJob::GenerateHTML(request.url);
- mojo::DataPipe data_pipe(data.size());
- CHECK(mojo::BlockingCopyFromString(data, data_pipe.producer_handle));
-
- client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
- network::URLLoaderCompletionStatus status(net::OK);
- status.encoded_data_length = data.size();
- status.encoded_body_length = data.size();
- client->OnComplete(status);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/histogram_internals_url_loader.h b/chromium/content/browser/histogram_internals_url_loader.h
deleted file mode 100644
index d8a6f9fc668..00000000000
--- a/chromium/content/browser/histogram_internals_url_loader.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 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_HISTOGRAM_INTERNALS_URL_LOADER_H_
-#define CONTENT_BROWSER_HISTOGRAM_INTERNALS_URL_LOADER_H_
-
-#include "services/network/public/mojom/url_loader.mojom.h"
-
-namespace content {
-
-// Creates the data for chrome://histograms.
-void StartHistogramInternalsURLLoader(
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client);
-} // namespace content
-
-#endif // CONTENT_BROWSER_HISTOGRAM_INTERNALS_URL_LOADER_H_
diff --git a/chromium/content/browser/histograms_internals_ui.cc b/chromium/content/browser/histograms_internals_ui.cc
new file mode 100644
index 00000000000..e338b28cb7a
--- /dev/null
+++ b/chromium/content/browser/histograms_internals_ui.cc
@@ -0,0 +1,113 @@
+// 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/histograms_internals_ui.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/values.h"
+#include "content/browser/histogram_synchronizer.h"
+#include "content/grit/content_resources.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/browser/web_ui_message_handler.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/url_constants.h"
+
+namespace content {
+namespace {
+
+const char kHistogramsUIJs[] = "histograms_internals.js";
+const char kHistogramsUIRequestHistograms[] = "requestHistograms";
+
+WebUIDataSource* CreateHistogramsHTMLSource() {
+ WebUIDataSource* source = WebUIDataSource::Create(kChromeUIHistogramHost);
+
+ source->AddResourcePath(kHistogramsUIJs, IDR_HISTOGRAMS_INTERNALS_JS);
+ source->SetDefaultResource(IDR_HISTOGRAMS_INTERNALS_HTML);
+ source->UseGzip();
+ return source;
+}
+
+// This class receives javascript messages from the renderer.
+// Note that the WebUI infrastructure runs on the UI thread, therefore all of
+// this class's methods are expected to run on the UI thread.
+class HistogramsMessageHandler : public WebUIMessageHandler {
+ public:
+ HistogramsMessageHandler();
+ ~HistogramsMessageHandler() override;
+
+ // WebUIMessageHandler:
+ void RegisterMessages() override;
+
+ private:
+ void HandleRequestHistograms(const base::ListValue* args);
+
+ DISALLOW_COPY_AND_ASSIGN(HistogramsMessageHandler);
+};
+
+HistogramsMessageHandler::HistogramsMessageHandler() {}
+
+HistogramsMessageHandler::~HistogramsMessageHandler() {}
+
+void HistogramsMessageHandler::HandleRequestHistograms(
+ const base::ListValue* args) {
+ base::StatisticsRecorder::ImportProvidedHistograms();
+ HistogramSynchronizer::FetchHistograms();
+
+ AllowJavascript();
+ std::string callback_id;
+ args->GetString(0, &callback_id);
+ std::string query;
+ args->GetString(1, &query);
+
+ base::ListValue histograms_list;
+ for (base::HistogramBase* histogram : base::StatisticsRecorder::WithName(
+ base::StatisticsRecorder::GetHistograms(), query)) {
+ // TODO(crbug.com/809820): Return the histogram object as a DictionaryValue
+ // for better UI that is built client side.
+ std::string ascii_output;
+ histogram->WriteHTMLGraph(&ascii_output);
+ ascii_output += "<br><hr><br>";
+ histograms_list.GetList().emplace_back(std::move(ascii_output));
+ }
+
+ ResolveJavascriptCallback(base::Value(callback_id),
+ std::move(histograms_list));
+}
+
+void HistogramsMessageHandler::RegisterMessages() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // We can use base::Unretained() here, as both the callback and this class are
+ // owned by HistogramsInternalsUI.
+ web_ui()->RegisterMessageCallback(
+ kHistogramsUIRequestHistograms,
+ base::BindRepeating(&HistogramsMessageHandler::HandleRequestHistograms,
+ base::Unretained(this)));
+}
+
+} // namespace
+
+HistogramsInternalsUI::HistogramsInternalsUI(WebUI* web_ui)
+ : WebUIController(web_ui) {
+ web_ui->AddMessageHandler(std::make_unique<HistogramsMessageHandler>());
+
+ // Set up the chrome://histograms/ source.
+ BrowserContext* browser_context =
+ web_ui->GetWebContents()->GetBrowserContext();
+ WebUIDataSource::Add(browser_context, CreateHistogramsHTMLSource());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/histograms_internals_ui.h b/chromium/content/browser/histograms_internals_ui.h
new file mode 100644
index 00000000000..40fdd056801
--- /dev/null
+++ b/chromium/content/browser/histograms_internals_ui.h
@@ -0,0 +1,25 @@
+// 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_HISTOGRAMS_INTERNALS_UI_H_
+#define CONTENT_BROWSER_HISTOGRAMS_INTERNALS_UI_H_
+
+#include "base/macros.h"
+#include "content/public/browser/web_ui_controller.h"
+
+namespace content {
+
+// Handles serving the chrome://histograms HTML, JS, CSS as well as internal
+// page requests.
+class HistogramsInternalsUI : public WebUIController {
+ public:
+ explicit HistogramsInternalsUI(WebUI* web_ui);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HistogramsInternalsUI);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_HISTOGRAMS_INTERNALS_UI_H_
diff --git a/chromium/content/browser/hyphenation/hyphenation_impl.h b/chromium/content/browser/hyphenation/hyphenation_impl.h
index 05014dd9f85..1679aa2f946 100644
--- a/chromium/content/browser/hyphenation/hyphenation_impl.h
+++ b/chromium/content/browser/hyphenation/hyphenation_impl.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_HYPHENATION_HYPHENATION_IMPL_H_
#include "base/macros.h"
+#include "base/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "third_party/blink/public/platform/modules/hyphenation/hyphenation.mojom.h"
diff --git a/chromium/content/browser/indexed_db/OWNERS b/chromium/content/browser/indexed_db/OWNERS
index 11e923cac27..5a42cf0e75b 100644
--- a/chromium/content/browser/indexed_db/OWNERS
+++ b/chromium/content/browser/indexed_db/OWNERS
@@ -2,8 +2,5 @@ jsbell@chromium.org
cmumford@chromium.org
dmurph@chromium.org
-# Secondary: only if other OWNERS are unavailable and something is urgent.
-michaeln@chromium.org
-
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>IndexedDB
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
index 774da43bac0..6dde8e246d8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -42,6 +42,7 @@
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request_context.h"
@@ -585,9 +586,12 @@ IndexedDBBackingStore::IndexedDBBackingStore(
db_(std::move(db)),
comparator_(std::move(comparator)),
active_blob_registry_(this),
- committing_transaction_count_(0) {}
+ committing_transaction_count_(0) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+}
IndexedDBBackingStore::~IndexedDBBackingStore() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!blob_path_.empty() && !child_process_ids_granted_.empty()) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -643,6 +647,8 @@ Status IndexedDBBackingStore::DestroyBackingStore(const FilePath& path_base,
Status IndexedDBBackingStore::AnyDatabaseContainsBlobs(
LevelDBTransaction* transaction,
bool* blobs_exist) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
Status status = leveldb::Status::OK();
std::vector<base::string16> names;
IndexedDBMetadataCoding metadata_coding;
@@ -688,6 +694,8 @@ Status IndexedDBBackingStore::AnyDatabaseContainsBlobs(
}
WARN_UNUSED_RESULT Status IndexedDBBackingStore::SetUpMetadata() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
const IndexedDBDataFormatVersion latest_known_data_version =
IndexedDBDataFormatVersion::GetCurrent();
const std::string schema_version_key = SchemaVersionKey::Encode();
@@ -766,9 +774,6 @@ WARN_UNUSED_RESULT Status IndexedDBBackingStore::SetUpMetadata() {
//
// In order to prevent corrupt databases, when upgrading from 2 to 3 this
// will consider any v2 databases with BlobEntryKey entries as corrupt.
- // Unfortunately this will blow away a lot of data for third party
- // customers, so first we will only upgrade the non-corrupt v2 databases
- // (and leave the corrupt v2 ones for one release).
// https://crbug.com/756447, https://crbug.com/829125,
// https://crbug.com/829141
db_schema_version = 3;
@@ -780,10 +785,13 @@ WARN_UNUSED_RESULT Status IndexedDBBackingStore::SetUpMetadata() {
}
indexed_db::ReportV2Schema(has_blobs, origin_);
if (has_blobs) {
- // TODO(dmurph): Treat this as corruption.
- // https://crbug.com/829141
INTERNAL_CONSISTENCY_ERROR(UPGRADING_SCHEMA_CORRUPTED_BLOBS);
- // return InternalInconsistencyStatus();
+ // Put database wiping behind a flag so we can use finch to stop this
+ // behavior if first-party customers have problems.
+ if (base::FeatureList::IsEnabled(
+ features::kWipeCorruptV2IDBDatabases)) {
+ return InternalInconsistencyStatus();
+ }
} else {
PutInt(transaction.get(), schema_version_key, db_schema_version);
}
@@ -830,6 +838,8 @@ WARN_UNUSED_RESULT Status IndexedDBBackingStore::SetUpMetadata() {
leveldb::Status IndexedDBBackingStore::GetCompleteMetadata(
std::vector<IndexedDBDatabaseMetadata>* output) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
IndexedDBMetadataCoding metadata_coding;
leveldb::Status status = leveldb::Status::OK();
std::vector<base::string16> names;
@@ -855,6 +865,7 @@ leveldb::Status IndexedDBBackingStore::GetCompleteMetadata(
return status;
}
+// static
bool IndexedDBBackingStore::ReadCorruptionInfo(const FilePath& path_base,
const Origin& origin,
std::string* message) {
@@ -877,8 +888,7 @@ bool IndexedDBBackingStore::ReadCorruptionInfo(const FilePath& path_base,
bool success = false;
if (file.IsValid()) {
std::string input_js(file_size, '\0');
- if (file_size ==
- file.Read(0, base::string_as_array(&input_js), file_size)) {
+ if (file_size == file.Read(0, base::data(input_js), file_size)) {
base::JSONReader reader;
std::unique_ptr<base::DictionaryValue> val(
base::DictionaryValue::From(reader.ReadToValue(input_js)));
@@ -893,6 +903,7 @@ bool IndexedDBBackingStore::ReadCorruptionInfo(const FilePath& path_base,
return success;
}
+// static
bool IndexedDBBackingStore::RecordCorruptionInfo(const FilePath& path_base,
const Origin& origin,
const std::string& message) {
@@ -1132,6 +1143,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
}
void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
if (!child_process_ids_granted_.count(child_process_id)) {
child_process_ids_granted_.insert(child_process_id);
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
@@ -1140,6 +1153,8 @@ void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) {
}
Status IndexedDBBackingStore::DeleteDatabase(const base::string16& name) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
std::unique_ptr<LevelDBDirectTransaction> transaction =
LevelDBDirectTransaction::Create(db_.get());
@@ -1205,7 +1220,10 @@ Status IndexedDBBackingStore::DeleteDatabase(const base::string16& name) {
return s;
}
-void IndexedDBBackingStore::Compact() { db_->CompactAll(); }
+void IndexedDBBackingStore::Compact() {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+ db_->CompactAll();
+}
Status IndexedDBBackingStore::GetRecord(
IndexedDBBackingStore::Transaction* transaction,
@@ -1213,6 +1231,8 @@ Status IndexedDBBackingStore::GetRecord(
int64_t object_store_id,
const IndexedDBKey& key,
IndexedDBValue* record) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
IDB_TRACE("IndexedDBBackingStore::GetRecord");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return InvalidDBKeyStatus();
@@ -1248,6 +1268,20 @@ Status IndexedDBBackingStore::GetRecord(
return transaction->GetBlobInfoForRecord(database_id, leveldb_key, record);
}
+int64_t IndexedDBBackingStore::GetInMemoryBlobSize() const {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+ int64_t total_size = 0;
+ for (const auto& kvp : incognito_blob_map_) {
+ for (const IndexedDBBlobInfo& blob_info : kvp.second->blob_info()) {
+ if (!blob_info.is_file()) {
+ total_size += blob_info.size();
+ }
+ }
+ }
+ return total_size;
+}
+
Status IndexedDBBackingStore::PutRecord(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
@@ -1256,6 +1290,8 @@ Status IndexedDBBackingStore::PutRecord(
IndexedDBValue* value,
std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles,
RecordIdentifier* record_identifier) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
IDB_TRACE("IndexedDBBackingStore::PutRecord");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return InvalidDBKeyStatus();
@@ -1301,6 +1337,8 @@ Status IndexedDBBackingStore::ClearObjectStore(
IndexedDBBackingStore::Transaction* transaction,
int64_t database_id,
int64_t object_store_id) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return InvalidDBKeyStatus();
@@ -1321,6 +1359,8 @@ Status IndexedDBBackingStore::DeleteRecord(
int64_t database_id,
int64_t object_store_id,
const RecordIdentifier& record_identifier) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
return InvalidDBKeyStatus();
@@ -1345,6 +1385,8 @@ Status IndexedDBBackingStore::DeleteRange(
int64_t database_id,
int64_t object_store_id,
const IndexedDBKeyRange& key_range) {
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
Status s;
std::unique_ptr<IndexedDBBackingStore::Cursor> start_cursor =
OpenObjectStoreCursor(transaction, database_id, object_store_id,
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
index bb43ef02033..4ec52518ce4 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -573,6 +573,8 @@ class CONTENT_EXPORT IndexedDBBackingStore
// Returns true if a blob cleanup job is pending on journal_cleaning_timer_.
bool IsBlobCleanupPending();
+ int64_t GetInMemoryBlobSize() const;
+
#if DCHECK_IS_ON()
int NumBlobFilesDeletedForTesting() { return num_blob_files_deleted_; }
int NumAggregatedJournalCleaningRequestsForTesting() const {
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index c7eb42be40b..e976df908b2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -591,6 +591,9 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, PutGetConsistencyWithBlobs) {
// Finish up transaction 3, verifying blob deletes.
EXPECT_TRUE(state->transaction3->CommitPhaseTwo().ok());
EXPECT_TRUE(test->CheckBlobRemovals());
+
+ // Clean up Transactions, etc on the IDB thread.
+ *state = TestState();
},
base::Unretained(this), base::Unretained(&state)));
RunAllTasksUntilIdle();
@@ -716,6 +719,9 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
backing_store->removals()[0]);
EXPECT_EQ(backing_store->writes()[2].key(),
backing_store->removals()[1]);
+
+ // Clean up Transactions, etc on the IDB thread.
+ *state = TestState();
},
base::Unretained(backing_store()), base::Unretained(&state)));
RunAllTasksUntilIdle();
@@ -837,6 +843,9 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
// Verify blob removals.
EXPECT_EQ(0UL, backing_store->removals().size());
+
+ // Clean up Transactions, etc on the IDB thread.
+ *state = TestState();
},
base::Unretained(backing_store()), base::Unretained(&state)));
RunAllTasksUntilIdle();
@@ -919,6 +928,9 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, BlobJournalInterleavedTransactions) {
EXPECT_TRUE(state->transaction2->CommitPhaseTwo().ok());
EXPECT_EQ(0U, test->backing_store()->removals().size());
+
+ // Clean up Transactions, etc on the IDB thread.
+ *state = TestState();
},
base::Unretained(this), base::Unretained(&state)));
RunAllTasksUntilIdle();
@@ -1022,7 +1034,7 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
idb_context_->TaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
- [](IndexedDBBackingStoreTestWithBlobs* test) {
+ [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) {
EXPECT_TRUE(test->backing_store()->IsBlobCleanupPending());
#if DCHECK_IS_ON()
EXPECT_EQ(3,
@@ -1040,8 +1052,11 @@ TEST_F(IndexedDBBackingStoreTestWithBlobs, LiveBlobJournal) {
test->backing_store()->NumBlobFilesDeletedForTesting());
#endif
EXPECT_FALSE(test->backing_store()->IsBlobCleanupPending());
+
+ // Clean up Transactions, etc on the IDB thread.
+ *state = TestState();
},
- base::Unretained(this)));
+ base::Unretained(this), base::Unretained(&state)));
RunAllTasksUntilIdle();
}
@@ -1559,5 +1574,120 @@ TEST_F(IndexedDBBackingStoreTest, SchemaUpgradeWithoutBlobsSurvives) {
RunAllTasksUntilIdle();
}
+// Our v2->v3 schema migration code forgot to bump the on-disk version number.
+// This test covers migrating a v3 database mislabeled as v2 to a properly
+// labeled v3 database. When the mislabeled database has blob entries, we must
+// treat it as corrupt and delete it.
+// https://crbug.com/756447, https://crbug.com/829125, https://crbug.com/829141
+TEST_F(IndexedDBBackingStoreTestWithBlobs, SchemaUpgradeWithBlobsCorrupt) {
+ struct TestState {
+ int64_t database_id;
+ const int64_t object_store_id = 99;
+ std::unique_ptr<IndexedDBBackingStore::Transaction> transaction1;
+ scoped_refptr<TestCallback> callback1;
+ std::unique_ptr<IndexedDBBackingStore::Transaction> transaction3;
+ scoped_refptr<TestCallback> callback3;
+ } state;
+
+ // The database metadata needs to be written so the blob entry keys can
+ // be detected.
+ idb_context_->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](IndexedDBBackingStore* backing_store, TestState* state) {
+ const base::string16 database_name(ASCIIToUTF16("db1"));
+ const int64_t version = 9;
+
+ const base::string16 object_store_name(
+ ASCIIToUTF16("object_store1"));
+ const bool auto_increment = true;
+ const IndexedDBKeyPath object_store_key_path(
+ ASCIIToUTF16("object_store_key"));
+
+ IndexedDBMetadataCoding metadata_coding;
+
+ {
+ IndexedDBDatabaseMetadata database;
+ leveldb::Status s = metadata_coding.CreateDatabase(
+ backing_store->db(), backing_store->origin_identifier(),
+ database_name, version, &database);
+ EXPECT_TRUE(s.ok());
+ EXPECT_GT(database.id, 0);
+ state->database_id = database.id;
+
+ IndexedDBBackingStore::Transaction transaction(backing_store);
+ transaction.Begin();
+
+ IndexedDBObjectStoreMetadata object_store;
+ s = metadata_coding.CreateObjectStore(
+ transaction.transaction(), database.id,
+ state->object_store_id, object_store_name,
+ object_store_key_path, auto_increment, &object_store);
+ EXPECT_TRUE(s.ok());
+
+ scoped_refptr<TestCallback> callback(
+ base::MakeRefCounted<TestCallback>());
+ EXPECT_TRUE(transaction.CommitPhaseOne(callback).ok());
+ EXPECT_TRUE(callback->called);
+ EXPECT_TRUE(callback->succeeded);
+ EXPECT_TRUE(transaction.CommitPhaseTwo().ok());
+ }
+ },
+ base::Unretained(backing_store()), base::Unretained(&state)));
+ RunAllTasksUntilIdle();
+
+ idb_context_->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) {
+ // Initiate transaction1 - writing blobs.
+ state->transaction1 =
+ std::make_unique<IndexedDBBackingStore::Transaction>(
+ test->backing_store());
+ state->transaction1->Begin();
+ std::vector<std::unique_ptr<storage::BlobDataHandle>> handles;
+ IndexedDBBackingStore::RecordIdentifier record;
+ EXPECT_TRUE(test->backing_store()
+ ->PutRecord(state->transaction1.get(),
+ state->database_id,
+ state->object_store_id, test->key3_,
+ &test->value3_, &handles, &record)
+ .ok());
+ state->callback1 = base::MakeRefCounted<TestCallback>();
+ EXPECT_TRUE(
+ state->transaction1->CommitPhaseOne(state->callback1).ok());
+ },
+ base::Unretained(this), base::Unretained(&state)));
+ RunAllTasksUntilIdle();
+
+ idb_context_->TaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](IndexedDBBackingStoreTestWithBlobs* test, TestState* state) {
+ // Finish up transaction1, verifying blob writes.
+ EXPECT_TRUE(state->callback1->called);
+ EXPECT_TRUE(state->callback1->succeeded);
+ EXPECT_TRUE(test->CheckBlobWrites());
+ EXPECT_TRUE(state->transaction1->CommitPhaseTwo().ok());
+
+ // Set the schema to 2, which was before blob support.
+ scoped_refptr<LevelDBTransaction> transaction =
+ IndexedDBClassFactory::Get()->CreateLevelDBTransaction(
+ test->backing_store()->db());
+ const std::string schema_version_key = SchemaVersionKey::Encode();
+ indexed_db::PutInt(transaction.get(), schema_version_key, 2);
+ ASSERT_TRUE(transaction->Commit().ok());
+ },
+ base::Unretained(this), base::Unretained(&state)));
+ RunAllTasksUntilIdle();
+
+ DestroyFactoryAndBackingStore();
+ CreateFactoryAndBackingStore();
+
+ // The factory returns a null backing store pointer when there is a corrupt
+ // database.
+ EXPECT_EQ(nullptr, backing_store());
+}
+
} // namespace indexed_db_backing_store_unittest
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
index d242a9db6a8..d582605c949 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -177,13 +177,15 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
info->SetString("url", origin.Serialize());
info->SetString("size", ui::FormatBytes(GetOriginDiskUsage(origin)));
info->SetDouble("last_modified", GetOriginLastModified(origin).ToJsTime());
+
+ auto paths = std::make_unique<base::ListValue>();
if (!is_incognito()) {
- std::unique_ptr<base::ListValue> paths(
- std::make_unique<base::ListValue>());
for (const base::FilePath& path : GetStoragePaths(origin))
paths->AppendString(path.value());
- info->Set("paths", std::move(paths));
+ } else {
+ paths->AppendString("N/A");
}
+ info->Set("paths", std::move(paths));
info->SetDouble("connection_count", GetConnectionCount(origin));
// This ends up being O(n^2) since we iterate over all open databases
@@ -292,15 +294,25 @@ int IndexedDBContextImpl::GetOriginBlobFileCount(const Origin& origin) {
int64_t IndexedDBContextImpl::GetOriginDiskUsage(const Origin& origin) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
- if (data_path_.empty() || !HasOrigin(origin))
+ if (!HasOrigin(origin))
return 0;
+
EnsureDiskUsageCacheInitialized(origin);
return origin_size_map_[origin];
}
base::Time IndexedDBContextImpl::GetOriginLastModified(const Origin& origin) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
- if (data_path_.empty() || !HasOrigin(origin))
+ if (!HasOrigin(origin))
+ return base::Time();
+
+ if (is_incognito()) {
+ if (!factory_)
+ return base::Time();
+ return factory_->GetLastModified(origin);
+ }
+
+ if (data_path_.empty())
return base::Time();
base::FilePath idb_directory = GetLevelDBPath(origin);
base::File::Info file_info;
@@ -395,7 +407,7 @@ void IndexedDBContextImpl::ForceClose(const Origin origin,
size_t IndexedDBContextImpl::GetConnectionCount(const Origin& origin) {
DCHECK(TaskRunner()->RunsTasksInCurrentSequence());
- if (data_path_.empty() || !HasOrigin(origin))
+ if (!HasOrigin(origin))
return 0;
if (!factory_.get())
@@ -555,8 +567,12 @@ base::FilePath IndexedDBContextImpl::GetLevelDBPath(
}
int64_t IndexedDBContextImpl::ReadUsageFromDisk(const Origin& origin) const {
- if (data_path_.empty())
- return 0;
+ if (is_incognito()) {
+ if (!factory_)
+ return 0;
+ return factory_->GetInMemoryDBSize(origin);
+ }
+
int64_t total_size = 0;
for (const base::FilePath& path : GetStoragePaths(origin))
total_size += base::ComputeDirectorySize(path);
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 52deffba26f..034a34e0465 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -160,8 +160,7 @@ void IndexedDBDispatcherHost::AddCursorBinding(
void IndexedDBDispatcherHost::RenderProcessExited(
RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {
+ const ChildProcessTerminationInfo& info) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
index 71ccfbd1d07..dc177044771 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -73,8 +73,7 @@ class CONTENT_EXPORT IndexedDBDispatcherHost
// Called by UI thread. Used to kill outstanding bindings and weak pointers
// in callbacks.
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override;
+ const ChildProcessTerminationInfo& info) override;
private:
class IDBSequenceHelper;
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index 694251f2e31..c4edb3f5d3f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -96,6 +96,10 @@ class CONTENT_EXPORT IndexedDBFactory
virtual size_t GetConnectionCount(const url::Origin& origin) const = 0;
+ virtual int64_t GetInMemoryDBSize(const url::Origin& origin) const = 0;
+
+ virtual base::Time GetLastModified(const url::Origin& origin) const = 0;
+
virtual void NotifyIndexedDBContentChanged(
const url::Origin& origin,
const base::string16& database_name,
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
index eea4df4c465..f063f01ae1d 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -78,6 +78,32 @@ base::Time GenerateNextGlobalSweepTime(base::Time now) {
return now + base::TimeDelta::FromMilliseconds(rand_millis);
}
+leveldb::Status GetDBSizeFromEnv(leveldb::Env* env,
+ const std::string& path,
+ int64_t* total_size_out) {
+ *total_size_out = 0;
+ // Root path should be /, but in MemEnv, a path name is not tailed with '/'
+ DCHECK_EQ(path.back(), '/');
+ const std::string path_without_slash = path.substr(0, path.length() - 1);
+
+ // This assumes that leveldb will not put a subdirectory into the directory
+ std::vector<std::string> file_names;
+ leveldb::Status s = env->GetChildren(path_without_slash, &file_names);
+ if (!s.ok())
+ return s;
+
+ for (std::string& file_name : file_names) {
+ file_name.insert(0, path);
+ uint64_t file_size;
+ s = env->GetFileSize(file_name, &file_size);
+ if (!s.ok())
+ return s;
+ else
+ *total_size_out += static_cast<int64_t>(file_size);
+ }
+ return s;
+}
+
} // namespace
const base::Feature kIDBTombstoneStatistics{"IDBTombstoneStatistics",
@@ -353,10 +379,13 @@ void IndexedDBFactoryImpl::GetDatabaseNames(
OpenBackingStore(origin, data_directory, request_context_getter,
&data_loss_info, &disk_full, &s);
if (!backing_store.get()) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionUnknownError,
- "Internal error opening backing store for "
- "indexedDB.webkitGetDatabaseNames."));
+ IndexedDBDatabaseError error(
+ blink::kWebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16("Internal error opening backing store for "
+ "indexedDB.webkitGetDatabaseNames."));
+ callbacks->OnError(error);
+ if (s.IsCorruption())
+ HandleBackingStoreCorruption(origin, error);
return;
}
@@ -715,6 +744,29 @@ size_t IndexedDBFactoryImpl::GetConnectionCount(const Origin& origin) const {
return count;
}
+int64_t IndexedDBFactoryImpl::GetInMemoryDBSize(const Origin& origin) const {
+ const auto& it = backing_store_map_.find(origin);
+ DCHECK(it != backing_store_map_.end());
+
+ const scoped_refptr<IndexedDBBackingStore>& backing_store = it->second;
+ int64_t level_db_size = 0;
+ leveldb::Status s =
+ GetDBSizeFromEnv(backing_store->db()->env(), "/", &level_db_size);
+ if (!s.ok())
+ LOG(ERROR) << "Failed to GetDBSizeFromEnv: " << s.ToString();
+
+ return backing_store->GetInMemoryBlobSize() + level_db_size;
+}
+
+base::Time IndexedDBFactoryImpl::GetLastModified(
+ const url::Origin& origin) const {
+ const auto& it = backing_store_map_.find(origin);
+ DCHECK(it != backing_store_map_.end());
+
+ const scoped_refptr<IndexedDBBackingStore>& backing_store = it->second;
+ return backing_store->db()->LastModified();
+}
+
void IndexedDBFactoryImpl::NotifyIndexedDBContentChanged(
const url::Origin& origin,
const base::string16& database_name,
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
index cb730b49a1c..4ae17600381 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -107,6 +107,10 @@ class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
const base::string16& database_name,
const base::string16& object_store_name) override;
+ int64_t GetInMemoryDBSize(const url::Origin& origin) const override;
+
+ base::Time GetLastModified(const url::Origin& origin) const override;
+
protected:
~IndexedDBFactoryImpl() override;
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
index 3c68fcd7cba..46b713fb53a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -5,6 +5,7 @@
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "base/files/file_path.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "net/url_request/url_request_context_getter.h"
namespace content {
@@ -16,7 +17,7 @@ IndexedDBFakeBackingStore::IndexedDBFakeBackingStore()
scoped_refptr<net::URLRequestContextGetter>(),
std::unique_ptr<LevelDBDatabase>(),
std::unique_ptr<LevelDBComparator>(),
- nullptr /* task_runner */) {}
+ base::SequencedTaskRunnerHandle::Get().get()) {}
IndexedDBFakeBackingStore::IndexedDBFakeBackingStore(
IndexedDBFactory* factory,
base::SequencedTaskRunner* task_runner)
diff --git a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
index 48bf8b22774..616d0b0f0d5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -41,7 +41,7 @@ namespace {
bool AllowWhitelistedPaths(const std::vector<base::FilePath>& allowed_paths,
const base::FilePath& candidate_path) {
for (const base::FilePath& allowed_path : allowed_paths) {
- if (allowed_path.IsParent(candidate_path))
+ if (candidate_path == allowed_path || allowed_path.IsParent(candidate_path))
return true;
}
return false;
diff --git a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
index d8ffcc5a04b..138b8d149ca 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc
@@ -38,7 +38,7 @@ ACTION_P2(RunClosureThenReturn, closure, ret) {
class MockPreCloseTask : public PreCloseTask {
public:
MockPreCloseTask() {}
- ~MockPreCloseTask() {}
+ ~MockPreCloseTask() override {}
MOCK_METHOD1(SetMetadata,
void(std::vector<IndexedDBDatabaseMetadata> const* metadata));
diff --git a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
index e0d69eac84f..d53addc85b2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
@@ -15,6 +15,7 @@
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "content/browser/indexed_db/leveldb/mock_level_db.h"
#include "content/common/indexed_db/indexed_db_metadata.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/env_chromium.h"
@@ -242,6 +243,9 @@ class IndexedDBTombstoneSweeperTest : public testing::TestWithParam<Mode> {
// Used to verify recorded data.
base::HistogramTester histogram_tester_;
+
+ private:
+ TestBrowserThreadBundle thread_bundle_;
};
TEST_P(IndexedDBTombstoneSweeperTest, EmptyDB) {
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index 20a4218d2b2..761cc63bb32 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -23,6 +23,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
+#include "base/time/default_clock.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "build/build_config.h"
@@ -39,6 +40,7 @@
#include "third_party/leveldatabase/src/include/leveldb/slice.h"
using base::StringPiece;
+using leveldb_env::DBTracker;
namespace content {
@@ -238,7 +240,7 @@ LevelDBSnapshot::~LevelDBSnapshot() {
}
LevelDBDatabase::LevelDBDatabase(size_t max_open_iterators)
- : iterator_lru_(max_open_iterators) {
+ : clock_(new base::DefaultClock()), iterator_lru_(max_open_iterators) {
DCHECK(max_open_iterators);
}
@@ -334,7 +336,7 @@ std::unique_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
std::unique_ptr<ComparatorAdapter> comparator_adapter(
std::make_unique<ComparatorAdapter>(comparator));
std::unique_ptr<leveldb::Env> in_memory_env(
- leveldb_chrome::NewMemEnv(LevelDBEnv::Get()));
+ leveldb_chrome::NewMemEnv("indexed-db", LevelDBEnv::Get()));
std::unique_ptr<leveldb::DB> db;
std::unique_ptr<const leveldb::FilterPolicy> filter_policy;
@@ -375,6 +377,7 @@ leveldb::Status LevelDBDatabase::Put(const StringPiece& key,
else
UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.PutTime",
base::TimeTicks::Now() - begin_time);
+ last_modified_ = clock_->Now();
return s;
}
@@ -386,6 +389,7 @@ leveldb::Status LevelDBDatabase::Remove(const StringPiece& key) {
db_->Delete(write_options, leveldb_env::MakeSlice(key));
if (!s.IsNotFound())
LOG(ERROR) << "LevelDB remove failed: " << s.ToString();
+ last_modified_ = clock_->Now();
return s;
}
@@ -426,6 +430,7 @@ leveldb::Status LevelDBDatabase::Write(const LevelDBWriteBatch& write_batch) {
UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.WriteTime",
base::TimeTicks::Now() - begin_time);
}
+ last_modified_ = clock_->Now();
return s;
}
@@ -479,30 +484,49 @@ bool LevelDBDatabase::OnMemoryDump(
return false;
// All leveldb databases are already dumped by leveldb_env::DBTracker. Add
// an edge to the existing database.
- auto* tracker_dump =
+ auto* db_tracker_dump =
leveldb_env::DBTracker::GetOrCreateAllocatorDump(pmd, db_.get());
- if (!tracker_dump)
+ if (!db_tracker_dump)
return true;
- auto* dump = pmd->CreateAllocatorDump(
- base::StringPrintf("site_storage/index_db/0x%" PRIXPTR,
+ auto* db_dump = pmd->CreateAllocatorDump(
+ base::StringPrintf("site_storage/index_db/db_0x%" PRIXPTR,
reinterpret_cast<uintptr_t>(db_.get())));
- dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
- base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- tracker_dump->GetSizeInternal());
- pmd->AddOwnershipEdge(dump->guid(), tracker_dump->guid());
+ db_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ db_tracker_dump->GetSizeInternal());
+ pmd->AddOwnershipEdge(db_dump->guid(), db_tracker_dump->guid());
+
+ if (env_ && leveldb_chrome::IsMemEnv(env_.get())) {
+ // All leveldb env's are already dumped by leveldb_env::DBTracker. Add
+ // an edge to the existing env.
+ auto* env_tracker_dump =
+ DBTracker::GetOrCreateAllocatorDump(pmd, env_.get());
+ auto* env_dump = pmd->CreateAllocatorDump(
+ base::StringPrintf("site_storage/index_db/memenv_0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(env_.get())));
+ env_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ env_tracker_dump->GetSizeInternal());
+ pmd->AddOwnershipEdge(env_dump->guid(), env_tracker_dump->guid());
+ }
- // Dumps in BACKGROUND mode cannot have strings or edges in order to minimize
- // trace size and instrumentation overhead.
+ // Dumps in BACKGROUND mode can only have whitelisted strings (and there are
+ // currently none) so return early.
if (args.level_of_detail ==
base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
return true;
}
- dump->AddString("file_name", "", file_name_for_tracing);
+ db_dump->AddString("file_name", "", file_name_for_tracing);
+
return true;
}
+void LevelDBDatabase::SetClockForTesting(std::unique_ptr<base::Clock> clock) {
+ clock_ = std::move(clock);
+}
+
std::unique_ptr<leveldb::Iterator> LevelDBDatabase::CreateLevelDBIterator(
const leveldb::Snapshot* snapshot) {
leveldb::ReadOptions read_options;
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
index 46118ce1d3a..56bf775112a 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
+#include "base/time/clock.h"
#include "base/trace_event/memory_dump_provider.h"
#include "content/common/content_export.h"
#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
@@ -100,6 +101,10 @@ class CONTENT_EXPORT LevelDBDatabase
base::trace_event::ProcessMemoryDump* pmd) override;
leveldb::DB* db() { return db_.get(); }
+ leveldb::Env* env() { return env_.get(); }
+ base::Time LastModified() const { return last_modified_; }
+
+ void SetClockForTesting(std::unique_ptr<base::Clock> clock);
protected:
explicit LevelDBDatabase(size_t max_open_iterators);
@@ -125,6 +130,8 @@ class CONTENT_EXPORT LevelDBDatabase
std::unique_ptr<leveldb::DB> db_;
std::unique_ptr<const leveldb::FilterPolicy> filter_policy_;
const LevelDBComparator* comparator_;
+ base::Time last_modified_;
+ std::unique_ptr<base::Clock> clock_;
struct DetachIteratorOnDestruct {
DetachIteratorOnDestruct() {}
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
index a922b1bc020..ea75c483f6f 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
@@ -12,9 +12,11 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string_piece.h"
+#include "base/test/simple_test_clock.h"
#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "content/browser/indexed_db/leveldb/leveldb_env.h"
+#include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
@@ -110,5 +112,42 @@ TEST(LevelDB, Locking) {
EXPECT_TRUE(status.ok());
}
+TEST(LevelDBDatabaseTest, LastModified) {
+ const std::string key("key");
+ const std::string value("value");
+ std::string put_value;
+ SimpleComparator comparator;
+ auto test_clock = std::make_unique<base::SimpleTestClock>();
+ base::SimpleTestClock* clock_ptr = test_clock.get();
+ clock_ptr->Advance(base::TimeDelta::FromHours(2));
+ std::unique_ptr<LevelDBDatabase> leveldb =
+ LevelDBDatabase::OpenInMemory(&comparator);
+ ASSERT_TRUE(leveldb);
+ leveldb->SetClockForTesting(std::move(test_clock));
+ // Calling |Put| sets time modified.
+ put_value = value;
+ base::Time now_time = clock_ptr->Now();
+ leveldb::Status status = leveldb->Put(key, &put_value);
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ(now_time, leveldb->LastModified());
+
+ // Calling |Remove| sets time modified.
+ clock_ptr->Advance(base::TimeDelta::FromSeconds(200));
+ now_time = clock_ptr->Now();
+ status = leveldb->Remove(key);
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ(now_time, leveldb->LastModified());
+
+ // Calling |Write| sets time modified
+ clock_ptr->Advance(base::TimeDelta::FromMinutes(15));
+ now_time = clock_ptr->Now();
+ auto batch = LevelDBWriteBatch::Create();
+ batch->Put(key, value);
+ batch->Remove(key);
+ status = leveldb->Write(*batch);
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ(now_time, leveldb->LastModified());
+}
+
} // namespace leveldb_unittest
} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_write_batch.h b/chromium/content/browser/indexed_db/leveldb/leveldb_write_batch.h
index c1c6e65d6b0..4893c563b28 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_write_batch.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_write_batch.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
namespace leveldb {
class WriteBatch;
@@ -17,7 +18,7 @@ namespace content {
// Wrapper around leveldb::WriteBatch.
// This class holds a collection of updates to apply atomically to a database.
-class LevelDBWriteBatch {
+class CONTENT_EXPORT LevelDBWriteBatch {
public:
static std::unique_ptr<LevelDBWriteBatch> Create();
~LevelDBWriteBatch();
diff --git a/chromium/content/browser/indexed_db/leveldb/mock_level_db.h b/chromium/content/browser/indexed_db/leveldb/mock_level_db.h
index ca1484191cc..01e9be12c51 100644
--- a/chromium/content/browser/indexed_db/leveldb/mock_level_db.h
+++ b/chromium/content/browser/indexed_db/leveldb/mock_level_db.h
@@ -13,7 +13,7 @@ namespace leveldb {
class MockIterator : public Iterator {
public:
MockIterator();
- ~MockIterator();
+ ~MockIterator() override;
MOCK_CONST_METHOD0(Valid, bool());
@@ -32,7 +32,7 @@ class MockIterator : public Iterator {
class MockLevelDB : public DB {
public:
MockLevelDB();
- ~MockLevelDB();
+ ~MockLevelDB() override;
MOCK_METHOD3(Put,
Status(const WriteOptions& options,
diff --git a/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h b/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h
index 5da41919c7c..b01f6e19956 100644
--- a/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h
+++ b/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h
@@ -14,7 +14,7 @@ namespace content {
class MockLevelDBFactory : public LevelDBFactory {
public:
MockLevelDBFactory();
- ~MockLevelDBFactory();
+ ~MockLevelDBFactory() override;
MOCK_METHOD4(OpenLevelDB,
leveldb::Status(const base::FilePath& file_name,
const LevelDBComparator* comparator,
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
index 9a2ee226cf4..6a3022197a0 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -35,12 +35,11 @@ class MockIndexedDBFactory : public IndexedDBFactory {
const url::Origin& origin,
const base::FilePath& data_directory));
// Googlemock can't deal with move-only types, so *Proxy() is a workaround.
- virtual void Open(
- const base::string16& name,
- std::unique_ptr<IndexedDBPendingConnection> connection,
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- const url::Origin& origin,
- const base::FilePath& data_directory) {
+ void Open(const base::string16& name,
+ std::unique_ptr<IndexedDBPendingConnection> connection,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ const url::Origin& origin,
+ const base::FilePath& data_directory) override {
OpenProxy(name, connection.get(), request_context_getter, origin,
data_directory);
}
@@ -55,18 +54,18 @@ class MockIndexedDBFactory : public IndexedDBFactory {
MOCK_METHOD2(AbortTransactionsAndCompactDatabaseProxy,
void(base::OnceCallback<void(leveldb::Status)>* callback,
const url::Origin& origin));
- virtual void AbortTransactionsAndCompactDatabase(
+ void AbortTransactionsAndCompactDatabase(
base::OnceCallback<void(leveldb::Status)> callback,
- const url::Origin& origin) {
+ const url::Origin& origin) override {
base::OnceCallback<void(leveldb::Status)>* callback_ref = &callback;
AbortTransactionsAndCompactDatabaseProxy(callback_ref, origin);
}
MOCK_METHOD2(AbortTransactionsForDatabaseProxy,
void(base::OnceCallback<void(leveldb::Status)>* callback,
const url::Origin& origin));
- virtual void AbortTransactionsForDatabase(
+ void AbortTransactionsForDatabase(
base::OnceCallback<void(leveldb::Status)> callback,
- const url::Origin& origin) {
+ const url::Origin& origin) override {
base::OnceCallback<void(leveldb::Status)>* callback_ref = &callback;
AbortTransactionsForDatabaseProxy(callback_ref, origin);
}
@@ -87,6 +86,10 @@ class MockIndexedDBFactory : public IndexedDBFactory {
MOCK_CONST_METHOD1(GetConnectionCount, size_t(const url::Origin& origin));
+ MOCK_CONST_METHOD1(GetInMemoryDBSize, int64_t(const url::Origin& origin));
+
+ MOCK_CONST_METHOD1(GetLastModified, base::Time(const url::Origin& origin));
+
MOCK_METHOD2(ReportOutstandingBlobs,
void(const url::Origin& origin, bool blobs_outstanding));
@@ -97,7 +100,7 @@ class MockIndexedDBFactory : public IndexedDBFactory {
const base::string16& object_store_name));
protected:
- virtual ~MockIndexedDBFactory();
+ ~MockIndexedDBFactory() override;
MOCK_METHOD6(
OpenBackingStore,
diff --git a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h
index c4d939ee6c9..ca8fb743097 100644
--- a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h
@@ -18,7 +18,7 @@ namespace content {
class MockMojoIndexedDBCallbacks : public ::indexed_db::mojom::Callbacks {
public:
explicit MockMojoIndexedDBCallbacks();
- ~MockMojoIndexedDBCallbacks();
+ ~MockMojoIndexedDBCallbacks() override;
::indexed_db::mojom::CallbacksAssociatedPtrInfo CreateInterfacePtrAndBind();
diff --git a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h
index 94562099bf7..cff98884f15 100644
--- a/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h
@@ -18,7 +18,7 @@ class MockMojoIndexedDBDatabaseCallbacks
: public ::indexed_db::mojom::DatabaseCallbacks {
public:
MockMojoIndexedDBDatabaseCallbacks();
- ~MockMojoIndexedDBDatabaseCallbacks();
+ ~MockMojoIndexedDBDatabaseCallbacks() override;
::indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo
CreateInterfacePtrAndBind();
diff --git a/chromium/content/browser/initiator_csp_context.cc b/chromium/content/browser/initiator_csp_context.cc
new file mode 100644
index 00000000000..a29e02d4e97
--- /dev/null
+++ b/chromium/content/browser/initiator_csp_context.cc
@@ -0,0 +1,55 @@
+// 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/initiator_csp_context.h"
+
+namespace content {
+
+InitiatorCSPContext::InitiatorCSPContext(
+ const std::vector<ContentSecurityPolicy>& policies,
+ base::Optional<CSPSource>& self_source)
+ : reporting_render_frame_host_impl_(nullptr) {
+ for (const auto& policy : policies)
+ AddContentSecurityPolicy(policy);
+
+ if (self_source.has_value())
+ SetSelf(self_source.value());
+}
+
+void InitiatorCSPContext::SetReportingRenderFrameHost(
+ RenderFrameHostImpl* rfh) {
+ reporting_render_frame_host_impl_ = rfh;
+}
+
+void InitiatorCSPContext::ReportContentSecurityPolicyViolation(
+ const CSPViolationParams& violation_params) {
+ if (reporting_render_frame_host_impl_) {
+ reporting_render_frame_host_impl_->ReportContentSecurityPolicyViolation(
+ violation_params);
+ }
+}
+
+bool InitiatorCSPContext::SchemeShouldBypassCSP(
+ const base::StringPiece& scheme) {
+ // TODO(andypaicu): RenderFrameHostImpl::SchemeShouldBypassCSP could be
+ // static except for the fact that it's virtual. It's weird to use
+ // the reporting RFH to do this check but overall harmless.
+ if (reporting_render_frame_host_impl_)
+ return reporting_render_frame_host_impl_->SchemeShouldBypassCSP(scheme);
+
+ return false;
+}
+
+void InitiatorCSPContext::SanitizeDataForUseInCspViolation(
+ bool is_redirect,
+ CSPDirective::Name directive,
+ GURL* blocked_url,
+ SourceLocation* source_location) const {
+ if (reporting_render_frame_host_impl_) {
+ reporting_render_frame_host_impl_->SanitizeDataForUseInCspViolation(
+ is_redirect, directive, blocked_url, source_location);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/initiator_csp_context.h b/chromium/content/browser/initiator_csp_context.h
new file mode 100644
index 00000000000..e370eee3b60
--- /dev/null
+++ b/chromium/content/browser/initiator_csp_context.h
@@ -0,0 +1,42 @@
+// 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_INITIATOR_CSP_CONTEXT_H_
+#define CONTENT_BROWSER_INITIATOR_CSP_CONTEXT_H_
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/common/content_security_policy/csp_context.h"
+#include "content/common/navigation_params.h"
+
+namespace content {
+
+// This is a CSP context that represents the document that initiated a
+// navigation. The reason we can't just use the initiating RenderFrameHost is
+// because it might already be destroyed when the CSP are checked in the
+// navigating RenderFrameHost. This uses the policies
+// passed through the CommonNavigationParams. The
+// relevant CSP directives of the navigation initiator are currently
+// `navigate-to` and `form-action` (in the case of form submissions).
+class InitiatorCSPContext : public CSPContext {
+ public:
+ InitiatorCSPContext(const std::vector<ContentSecurityPolicy>& policies,
+ base::Optional<CSPSource>& self_source);
+
+ void ReportContentSecurityPolicyViolation(
+ const CSPViolationParams& violation_params) override;
+ bool SchemeShouldBypassCSP(const base::StringPiece& scheme) override;
+ void SetReportingRenderFrameHost(RenderFrameHostImpl* rfh);
+ void SanitizeDataForUseInCspViolation(
+ bool is_redirect,
+ CSPDirective::Name directive,
+ GURL* blocked_url,
+ SourceLocation* source_location) const override;
+
+ private:
+ RenderFrameHostImpl* reporting_render_frame_host_impl_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INITIATOR_CSP_CONTEXT_H_
diff --git a/chromium/content/browser/isolated_origin_browsertest.cc b/chromium/content/browser/isolated_origin_browsertest.cc
index eae2d0c881d..417972f21b9 100644
--- a/chromium/content/browser/isolated_origin_browsertest.cc
+++ b/chromium/content/browser/isolated_origin_browsertest.cc
@@ -6,7 +6,9 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/storage_partition_impl.h"
@@ -18,6 +20,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
@@ -26,6 +29,7 @@
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/network/public/cpp/features.h"
#include "url/gurl.h"
namespace content {
@@ -1019,8 +1023,7 @@ class StoragePartitonInterceptor
// Ensure this object is cleaned up when the process goes away, since it
// is not owned by anyone else.
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override {
+ const ChildProcessTerminationInfo& info) override {
host->RemoveObserver(this);
delete this;
}
@@ -1174,6 +1177,111 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginLongListTest, Test) {
EXPECT_NE(subframe1->GetSiteInstance(), subframe2->GetSiteInstance());
}
+// Check that navigating a subframe to an isolated origin error page puts the
+// subframe into an OOPIF and its own SiteInstance. Also check that a
+// non-isolated error page in a subframe ends up in the correct SiteInstance.
+IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, SubframeErrorPages) {
+ GURL top_url(
+ embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html"));
+ GURL isolated_url(
+ embedded_test_server()->GetURL("isolated.foo.com", "/close-socket"));
+ GURL regular_url(embedded_test_server()->GetURL("a.com", "/close-socket"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), top_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ EXPECT_EQ(2u, root->child_count());
+
+ FrameTreeNode* child1 = root->child_at(0);
+ FrameTreeNode* child2 = root->child_at(1);
+
+ {
+ TestFrameNavigationObserver observer(child1);
+ NavigationHandleObserver handle_observer(web_contents(), isolated_url);
+ EXPECT_TRUE(ExecuteScript(
+ child1, "location.href = '" + isolated_url.spec() + "';"));
+ observer.Wait();
+ EXPECT_EQ(child1->current_url(), isolated_url);
+ EXPECT_TRUE(handle_observer.is_error());
+
+ EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+ child1->current_frame_host()->GetSiteInstance());
+ EXPECT_EQ(GURL(isolated_url.GetOrigin()),
+ child1->current_frame_host()->GetSiteInstance()->GetSiteURL());
+ }
+
+ {
+ TestFrameNavigationObserver observer(child2);
+ NavigationHandleObserver handle_observer(web_contents(), regular_url);
+ EXPECT_TRUE(
+ ExecuteScript(child2, "location.href = '" + regular_url.spec() + "';"));
+ observer.Wait();
+ EXPECT_EQ(child2->current_url(), regular_url);
+ EXPECT_TRUE(handle_observer.is_error());
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+ child2->current_frame_host()->GetSiteInstance());
+ EXPECT_EQ(SiteInstance::GetSiteForURL(web_contents()->GetBrowserContext(),
+ regular_url),
+ child2->current_frame_host()->GetSiteInstance()->GetSiteURL());
+ } else {
+ EXPECT_EQ(root->current_frame_host()->GetSiteInstance(),
+ child2->current_frame_host()->GetSiteInstance());
+ }
+ EXPECT_NE(GURL(kUnreachableWebDataURL),
+ child2->current_frame_host()->GetSiteInstance()->GetSiteURL());
+ }
+}
+
+class IsolatedOriginTestWithMojoBlobURLs : public IsolatedOriginTest {
+ public:
+ IsolatedOriginTestWithMojoBlobURLs() {
+ // Enabling NetworkService implies enabling MojoBlobURLs.
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kNetworkService);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+// Times out on android, and crashes on mac due to its dependency on network
+// service.
+#define MAYBE_NavigateToBlobURL DISABLED_NavigateToBlobURL
+#else
+#define MAYBE_NavigateToBlobURL NavigateToBlobURL
+#endif
+
+IN_PROC_BROWSER_TEST_F(IsolatedOriginTestWithMojoBlobURLs,
+ MAYBE_NavigateToBlobURL) {
+ GURL top_url(
+ embedded_test_server()->GetURL("www.foo.com", "/page_with_iframe.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), top_url));
+
+ GURL isolated_url(embedded_test_server()->GetURL("isolated.foo.com",
+ "/page_with_iframe.html"));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* child = root->child_at(0);
+
+ NavigateIframeToURL(web_contents(), "test_iframe", isolated_url);
+ EXPECT_EQ(child->current_url(), isolated_url);
+ EXPECT_TRUE(child->current_frame_host()->IsCrossProcessSubframe());
+
+ // Now navigate the child frame to a Blob URL.
+ TestNavigationObserver load_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents()->GetMainFrame(),
+ "const b = new Blob(['foo']);\n"
+ "const u = URL.createObjectURL(b);\n"
+ "frames[0].location = u;\n"
+ "URL.revokeObjectURL(u);"));
+ load_observer.Wait();
+ EXPECT_TRUE(base::StartsWith(child->current_url().spec(),
+ "blob:http://www.foo.com",
+ base::CompareCase::SENSITIVE));
+ EXPECT_TRUE(load_observer.last_navigation_succeeded());
+}
+
// Ensure that --disable-site-isolation-trials disables field trials.
class IsolatedOriginTrialOverrideTest : public IsolatedOriginFieldTrialTest {
public:
diff --git a/chromium/content/browser/keyboard_lock/keyboard_lock_metrics.h b/chromium/content/browser/keyboard_lock/keyboard_lock_metrics.h
new file mode 100644
index 00000000000..9761b1915ef
--- /dev/null
+++ b/chromium/content/browser/keyboard_lock/keyboard_lock_metrics.h
@@ -0,0 +1,26 @@
+// 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_KEYBOARD_LOCK_KEYBOARD_LOCK_METRICS_H_
+#define CONTENT_BROWSER_KEYBOARD_LOCK_KEYBOARD_LOCK_METRICS_H_
+
+namespace content {
+
+// These values must stay in sync with tools/metrics/histograms.xml.
+// Enum values should never be renumbered or reused as they are stored and can
+// be used for multi-release queries. Insert any new values before |kCount| and
+// increment the count.
+enum class KeyboardLockMethods {
+ kRequestAllKeys = 0,
+ kRequestSomeKeys = 1,
+ kCancelLock = 2,
+ kCount = 3
+};
+
+constexpr char kKeyboardLockMethodCalledHistogramName[] =
+ "Blink.KeyboardLock.MethodCalled";
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_KEYBOARD_LOCK_KEYBOARD_LOCK_METRICS_H_
diff --git a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
index d8bafd5dff6..a0b9c10d77b 100644
--- a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
+++ b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.cc
@@ -14,31 +14,24 @@
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/keyboard_lock/keyboard_lock_metrics.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host.h"
+#include "content/public/common/console_message_level.h"
#include "content/public/common/content_features.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
+using blink::mojom::GetKeyboardLayoutMapResult;
using blink::mojom::KeyboardLockRequestResult;
namespace content {
namespace {
-// These values must stay in sync with tools/metrics/histograms.xml.
-// Enum values should never be renumbered or reused as they are stored and can
-// be used for multi-release queries. Insert any new values before |kCount| and
-// increment the count.
-enum class KeyboardLockMethods {
- kRequestAllKeys = 0,
- kRequestSomeKeys = 1,
- kCancelLock = 2,
- kCount = 3
-};
-
void LogKeyboardLockMethodCalled(KeyboardLockMethods method) {
- UMA_HISTOGRAM_ENUMERATION("Blink.KeyboardLock.MethodCalled", method,
+ UMA_HISTOGRAM_ENUMERATION(kKeyboardLockMethodCalledHistogramName, method,
KeyboardLockMethods::kCount);
}
@@ -86,30 +79,36 @@ void KeyboardLockServiceImpl::RequestKeyboardLock(
// Per base::flat_set usage notes, the proper way to init a flat_set is
// inserting into a vector and using that to init the flat_set.
- std::vector<int> native_key_codes;
- const int invalid_key_code = ui::KeycodeConverter::InvalidNativeKeycode();
+ std::vector<ui::DomCode> dom_codes;
for (const std::string& code : key_codes) {
- int native_key_code = ui::KeycodeConverter::CodeStringToNativeKeycode(code);
- if (native_key_code != invalid_key_code)
- native_key_codes.push_back(native_key_code);
+ ui::DomCode dom_code = ui::KeycodeConverter::CodeStringToDomCode(code);
+ if (dom_code != ui::DomCode::NONE) {
+ dom_codes.push_back(dom_code);
+ } else {
+ render_frame_host_->AddMessageToConsole(
+ ConsoleMessageLevel::CONSOLE_MESSAGE_LEVEL_WARNING,
+ "Invalid DOMString passed into keyboard.lock(): '" + code + "'");
+ }
}
// If we are provided with a vector containing only invalid keycodes, then
// exit without enabling keyboard lock. An empty vector is treated as
// 'capture all keys' which is not what the caller intended.
- if (!key_codes.empty() && native_key_codes.empty()) {
+ if (!key_codes.empty() && dom_codes.empty()) {
std::move(callback).Run(KeyboardLockRequestResult::kNoValidKeyCodesError);
return;
}
- base::Optional<base::flat_set<int>> key_code_set;
- if (!native_key_codes.empty())
- key_code_set = std::move(native_key_codes);
-
- render_frame_host_->GetRenderWidgetHost()->RequestKeyboardLock(
- std::move(key_code_set));
+ base::Optional<base::flat_set<ui::DomCode>> dom_code_set;
+ if (!dom_codes.empty())
+ dom_code_set = std::move(dom_codes);
- std::move(callback).Run(KeyboardLockRequestResult::kSuccess);
+ if (render_frame_host_->GetRenderWidgetHost()->RequestKeyboardLock(
+ std::move(dom_code_set))) {
+ std::move(callback).Run(KeyboardLockRequestResult::kSuccess);
+ } else {
+ std::move(callback).Run(KeyboardLockRequestResult::kRequestFailedError);
+ }
}
void KeyboardLockServiceImpl::CancelKeyboardLock() {
@@ -119,4 +118,14 @@ void KeyboardLockServiceImpl::CancelKeyboardLock() {
render_frame_host_->GetRenderWidgetHost()->CancelKeyboardLock();
}
+void KeyboardLockServiceImpl::GetKeyboardLayoutMap(
+ GetKeyboardLayoutMapCallback callback) {
+ auto response = GetKeyboardLayoutMapResult::New();
+ response->status = blink::mojom::GetKeyboardLayoutMapStatus::kSuccess;
+ response->layout_map =
+ render_frame_host_->GetRenderWidgetHost()->GetKeyboardLayoutMap();
+
+ std::move(callback).Run(std::move(response));
+}
+
} // namespace content
diff --git a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
index aafcbd92317..19c2f994758 100644
--- a/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
+++ b/chromium/content/browser/keyboard_lock/keyboard_lock_service_impl.h
@@ -31,6 +31,7 @@ class CONTENT_EXPORT KeyboardLockServiceImpl
void RequestKeyboardLock(const std::vector<std::string>& key_codes,
RequestKeyboardLockCallback callback) override;
void CancelKeyboardLock() override;
+ void GetKeyboardLayoutMap(GetKeyboardLayoutMapCallback callback) override;
private:
RenderFrameHostImpl* const render_frame_host_;
diff --git a/chromium/content/browser/keyboard_lock_browsertest.cc b/chromium/content/browser/keyboard_lock_browsertest.cc
index 1279c21f547..2a4739de4af 100644
--- a/chromium/content/browser/keyboard_lock_browsertest.cc
+++ b/chromium/content/browser/keyboard_lock_browsertest.cc
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <vector>
+#include "content/browser/keyboard_lock_browsertest.h"
+
+#include <string>
#include "base/macros.h"
+#include "base/metrics/histogram_base.h"
+#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
+#include "components/network_session_configurator/common/network_switches.h"
+#include "content/browser/keyboard_lock/keyboard_lock_metrics.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_features.h"
@@ -16,7 +22,13 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/web/web_fullscreen_options.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/native_widget_types.h"
#ifdef USE_AURA
@@ -28,14 +40,31 @@ namespace content {
namespace {
-// TODO(joedow): Enable tests on additional platforms as they are implemented.
-#if defined(OS_WIN)
-#define MAYBE_RUN(test_name) test_name
-#else
-#define MAYBE_RUN(test_name) DISABLED_##test_name
-#endif
+constexpr char kFullscreenFramePath[] = "/fullscreen_frame.html";
+
+constexpr char kHelloFramePath[] = "/hello.html";
+
+constexpr char kInputFieldFramePath[] = "/page_with_input_field.html";
+
+// Set up a DOM structure which contains three inner iframes for testing:
+// - Same domain iframe w/ fullscreen attribute.
+// - Cross domain iframe.
+// - Cross domain iframe w/ fullscreen attribute.
+constexpr char kCrossSiteFramePath[] =
+ "/cross_site_iframe_factory.html"
+ "?a(a{allowfullscreen}(),b(),c{allowfullscreen}())";
+
+constexpr char kCrossSiteTopLevelDomain[] = "a.com";
+
+constexpr char kChildIframeName_0[] = "child-0";
+
+constexpr char kChildIframeName_1[] = "child-1";
+
+constexpr char kChildIframeName_2[] = "child-2";
-constexpr char kFullscreenFrameName[] = "/fullscreen_frame.html";
+constexpr char kCrossSiteChildDomain1[] = "b.com";
+
+constexpr char kCrossSiteChildDomain2[] = "c.com";
constexpr char kKeyboardLockMethodExistanceCheck[] =
"window.domAutomationController.send("
@@ -69,9 +98,31 @@ constexpr char kKeyboardLockMethodCallWithSomeInvalidKeys[] =
constexpr char kKeyboardUnlockMethodCall[] = "navigator.keyboard.unlock()";
-bool g_window_has_focus = false;
+constexpr char kFocusInputFieldScript[] =
+ "function onInput(e) {"
+ " domAutomationController.send(getInputFieldText());"
+ "}"
+ "inputField = document.getElementById('text-field');"
+ "inputField.addEventListener('input', onInput, false);";
+
+void SimulateKeyPress(WebContents* web_contents,
+ const std::string& code_string,
+ const std::string& expected_result) {
+ DOMMessageQueue msg_queue;
+ std::string reply;
+ ui::DomKey dom_key = ui::KeycodeConverter::KeyStringToDomKey(code_string);
+ ui::DomCode dom_code = ui::KeycodeConverter::CodeStringToDomCode(code_string);
+ SimulateKeyPress(web_contents, dom_key, dom_code,
+ ui::DomCodeToUsLayoutKeyboardCode(dom_code), false, false,
+ false, false);
+ ASSERT_TRUE(msg_queue.WaitForMessage(&reply));
+ ASSERT_EQ("\"" + expected_result + "\"", reply);
+}
#if defined(USE_AURA)
+
+bool g_window_has_focus = false;
+
class TestRenderWidgetHostView : public RenderWidgetHostViewAura {
public:
TestRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack)
@@ -88,13 +139,6 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewAura {
}
};
-void InstallCreateHooksForKeyboardLockBrowserTests() {
- WebContentsViewAura::InstallCreateHookForTests(
- [](RenderWidgetHost* host,
- bool is_guest_view_hack) -> RenderWidgetHostViewAura* {
- return new TestRenderWidgetHostView(host, is_guest_view_hack);
- });
-}
#endif // USE_AURA
class FakeKeyboardLockWebContentsDelegate : public WebContentsDelegate {
@@ -103,8 +147,10 @@ class FakeKeyboardLockWebContentsDelegate : public WebContentsDelegate {
~FakeKeyboardLockWebContentsDelegate() override {}
// WebContentsDelegate overrides.
- void EnterFullscreenModeForTab(WebContents* web_contents,
- const GURL& origin) override;
+ void EnterFullscreenModeForTab(
+ WebContents* web_contents,
+ const GURL& origin,
+ const blink::WebFullscreenOptions& options) override;
void ExitFullscreenModeForTab(WebContents* web_contents) override;
bool IsFullscreenForTabOrPending(
const WebContents* web_contents) const override;
@@ -121,7 +167,8 @@ class FakeKeyboardLockWebContentsDelegate : public WebContentsDelegate {
void FakeKeyboardLockWebContentsDelegate::EnterFullscreenModeForTab(
WebContents* web_contents,
- const GURL& origin) {
+ const GURL& origin,
+ const blink::WebFullscreenOptions& options) {
is_fullscreen_ = true;
if (keyboard_lock_requested_)
web_contents->GotResponseToKeyboardLockRequest(/*allowed=*/true);
@@ -154,6 +201,22 @@ void FakeKeyboardLockWebContentsDelegate::CancelKeyboardLockRequest(
} // namespace
+#if defined(USE_AURA)
+
+void SetWindowFocusForKeyboardLockBrowserTests(bool is_focused) {
+ g_window_has_focus = is_focused;
+}
+
+void InstallCreateHooksForKeyboardLockBrowserTests() {
+ WebContentsViewAura::InstallCreateHookForTests(
+ [](RenderWidgetHost* host,
+ bool is_guest_view_hack) -> RenderWidgetHostViewAura* {
+ return new TestRenderWidgetHostView(host, is_guest_view_hack);
+ });
+}
+
+#endif // USE_AURA
+
class KeyboardLockBrowserTest : public ContentBrowserTest {
public:
KeyboardLockBrowserTest();
@@ -169,11 +232,11 @@ class KeyboardLockBrowserTest : public ContentBrowserTest {
// Helper methods for common tasks.
bool KeyboardLockApiExists();
- void NavigateToTestURL();
+ void NavigateToTestURL(const GURL& gurl);
void RequestKeyboardLock(const base::Location& from_here,
bool lock_all_keys = true);
void CancelKeyboardLock(const base::Location& from_here);
- void EnterFullscreen(const base::Location& from_here);
+ void EnterFullscreen(const base::Location& from_here, const GURL& gurl);
void ExitFullscreen(const base::Location& from_here);
void FocusContent(const base::Location& from_here);
void BlurContent(const base::Location& from_here);
@@ -186,13 +249,22 @@ class KeyboardLockBrowserTest : public ContentBrowserTest {
net::EmbeddedTestServer* https_test_server() { return &https_test_server_; }
GURL https_fullscreen_frame() {
- return https_test_server()->GetURL(kFullscreenFrameName);
+ return https_test_server()->GetURL(kFullscreenFramePath);
+ }
+
+ GURL https_cross_site_frame() {
+ return https_test_server()->GetURL(kCrossSiteTopLevelDomain,
+ kCrossSiteFramePath);
}
base::test::ScopedFeatureList* feature_list() {
return &scoped_feature_list_;
}
+ WebContentsDelegate* web_contents_delegate() {
+ return &web_contents_delegate_;
+ }
+
private:
base::test::ScopedFeatureList scoped_feature_list_;
net::EmbeddedTestServer https_test_server_;
@@ -206,17 +278,18 @@ KeyboardLockBrowserTest::~KeyboardLockBrowserTest() = default;
void KeyboardLockBrowserTest::SetUp() {
// Assume we have focus to start with.
- g_window_has_focus = true;
-#if defined(USE_AURA)
+ SetWindowFocusForKeyboardLockBrowserTests(true);
InstallCreateHooksForKeyboardLockBrowserTests();
-#endif
SetUpFeatureList();
ContentBrowserTest::SetUp();
}
void KeyboardLockBrowserTest::SetUpCommandLine(
base::CommandLine* command_line) {
- IsolateAllSitesForTesting(command_line);
+ // Ignore cert errors so that the sign-in URL can be loaded from a site other
+ // than localhost (the EmbeddedTestServer serves a certificate that is valid
+ // for localhost).
+ command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
}
void KeyboardLockBrowserTest::SetUpOnMainThread() {
@@ -225,6 +298,8 @@ void KeyboardLockBrowserTest::SetUpOnMainThread() {
// KeyboardLock requires a secure context (HTTPS).
https_test_server()->AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("content/test/data")));
+ host_resolver()->AddRule("*", "127.0.0.1");
+ SetupCrossSiteRedirector(https_test_server());
ASSERT_TRUE(https_test_server()->Start());
}
@@ -239,8 +314,8 @@ bool KeyboardLockBrowserTest::KeyboardLockApiExists() {
return api_exists;
}
-void KeyboardLockBrowserTest::NavigateToTestURL() {
- ASSERT_TRUE(NavigateToURL(shell(), https_fullscreen_frame()));
+void KeyboardLockBrowserTest::NavigateToTestURL(const GURL& gurl) {
+ ASSERT_TRUE(NavigateToURL(shell(), gurl));
ASSERT_TRUE(KeyboardLockApiExists());
@@ -253,9 +328,9 @@ void KeyboardLockBrowserTest::RequestKeyboardLock(
const base::Location& from_here,
bool lock_all_keys /*=true*/) {
bool result;
- // keyboardLock() is an async call which requires a promise handling dance.
+ // keyboard.lock() is an async call which requires a promise handling dance.
ASSERT_TRUE(ExecuteScriptAndExtractBool(
- web_contents(),
+ web_contents()->GetMainFrame(),
lock_all_keys ? kKeyboardLockMethodCallWithAllKeys
: kKeyboardLockMethodCallWithSomeKeys,
&result))
@@ -271,8 +346,9 @@ void KeyboardLockBrowserTest::RequestKeyboardLock(
void KeyboardLockBrowserTest::CancelKeyboardLock(
const base::Location& from_here) {
- // keyboardUnlock() is a synchronous call.
- ASSERT_TRUE(ExecuteScript(web_contents(), kKeyboardUnlockMethodCall));
+ // keyboard.unlock() is a synchronous call.
+ ASSERT_TRUE(
+ ExecuteScript(web_contents()->GetMainFrame(), kKeyboardUnlockMethodCall));
ASSERT_EQ(nullptr, web_contents()->GetKeyboardLockWidget())
<< "Location: " << from_here.ToString();
@@ -280,8 +356,9 @@ void KeyboardLockBrowserTest::CancelKeyboardLock(
VerifyKeyboardLockState(from_here);
}
-void KeyboardLockBrowserTest::EnterFullscreen(const base::Location& from_here) {
- web_contents()->EnterFullscreenMode(https_fullscreen_frame());
+void KeyboardLockBrowserTest::EnterFullscreen(const base::Location& from_here,
+ const GURL& gurl) {
+ web_contents()->EnterFullscreenMode(gurl, blink::WebFullscreenOptions());
ASSERT_TRUE(web_contents()->IsFullscreenForCurrentTab())
<< "Location: " << from_here.ToString();
@@ -299,7 +376,7 @@ void KeyboardLockBrowserTest::ExitFullscreen(const base::Location& from_here) {
}
void KeyboardLockBrowserTest::FocusContent(const base::Location& from_here) {
- g_window_has_focus = true;
+ SetWindowFocusForKeyboardLockBrowserTests(true);
RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
web_contents()->GetRenderWidgetHostView()->GetRenderWidgetHost());
host->GotFocus();
@@ -312,7 +389,7 @@ void KeyboardLockBrowserTest::FocusContent(const base::Location& from_here) {
}
void KeyboardLockBrowserTest::BlurContent(const base::Location& from_here) {
- g_window_has_focus = false;
+ SetWindowFocusForKeyboardLockBrowserTests(false);
RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
web_contents()->GetRenderWidgetHostView()->GetRenderWidgetHost());
host->SetActive(false);
@@ -355,44 +432,63 @@ void KeyboardLockDisabledBrowserTest::SetUpFeatureList() {
feature_list()->InitAndDisableFeature(features::kKeyboardLockAPI);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, MAYBE_RUN(SingleLockCall)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, SingleLockCall) {
+ NavigateToTestURL(https_fullscreen_frame());
+ base::HistogramTester uma;
RequestKeyboardLock(FROM_HERE);
// Don't explicitly call CancelKeyboardLock().
+
+ uma.ExpectTotalCount(kKeyboardLockMethodCalledHistogramName, 1);
+ uma.ExpectBucketCount(kKeyboardLockMethodCalledHistogramName,
+ static_cast<int>(KeyboardLockMethods::kRequestAllKeys),
+ 1);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(SingleLockCallForSomeKeys)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, SingleLockCallForSomeKeys) {
+ NavigateToTestURL(https_fullscreen_frame());
+ base::HistogramTester uma;
RequestKeyboardLock(FROM_HERE, /*lock_all_keys=*/false);
// Don't explicitly call CancelKeyboardLock().
+
+ uma.ExpectTotalCount(kKeyboardLockMethodCalledHistogramName, 1);
+ uma.ExpectBucketCount(kKeyboardLockMethodCalledHistogramName,
+ static_cast<int>(KeyboardLockMethods::kRequestSomeKeys),
+ 1);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(SingleLockWithCancelCall)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, SingleLockWithCancelCall) {
+ NavigateToTestURL(https_fullscreen_frame());
+ base::HistogramTester uma;
RequestKeyboardLock(FROM_HERE);
CancelKeyboardLock(FROM_HERE);
+
+ uma.ExpectTotalCount(kKeyboardLockMethodCalledHistogramName, 2);
+ uma.ExpectBucketCount(kKeyboardLockMethodCalledHistogramName,
+ static_cast<int>(KeyboardLockMethods::kRequestAllKeys),
+ 1);
+ uma.ExpectBucketCount(kKeyboardLockMethodCalledHistogramName,
+ static_cast<int>(KeyboardLockMethods::kCancelLock), 1);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockCalledBeforeFullscreen)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, LockCalledBeforeFullscreen) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
RequestKeyboardLock(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockCalledAfterFullscreen)) {
- NavigateToTestURL();
- EnterFullscreen(FROM_HERE);
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, LockCalledAfterFullscreen) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
+ EnterFullscreen(FROM_HERE, url_for_test);
RequestKeyboardLock(FROM_HERE);
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockAndCancelCyclingNoActivation)) {
- NavigateToTestURL();
+ LockAndCancelCyclingNoActivation) {
+ NavigateToTestURL(https_fullscreen_frame());
+ base::HistogramTester uma;
RequestKeyboardLock(FROM_HERE);
CancelKeyboardLock(FROM_HERE);
RequestKeyboardLock(FROM_HERE, /*lock_all_keys=*/false);
@@ -401,13 +497,24 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
CancelKeyboardLock(FROM_HERE);
RequestKeyboardLock(FROM_HERE);
CancelKeyboardLock(FROM_HERE);
+
+ uma.ExpectTotalCount(kKeyboardLockMethodCalledHistogramName, 8);
+ uma.ExpectBucketCount(kKeyboardLockMethodCalledHistogramName,
+ static_cast<int>(KeyboardLockMethods::kRequestAllKeys),
+ 3);
+ uma.ExpectBucketCount(kKeyboardLockMethodCalledHistogramName,
+ static_cast<int>(KeyboardLockMethods::kRequestSomeKeys),
+ 1);
+ uma.ExpectBucketCount(kKeyboardLockMethodCalledHistogramName,
+ static_cast<int>(KeyboardLockMethods::kCancelLock), 4);
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockAndCancelCyclingInFullscreen)) {
- NavigateToTestURL();
+ LockAndCancelCyclingInFullscreen) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
RequestKeyboardLock(FROM_HERE);
CancelKeyboardLock(FROM_HERE);
@@ -421,34 +528,34 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
CancelKeyboardLock(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, MAYBE_RUN(CancelInFullscreen)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, CancelInFullscreen) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
RequestKeyboardLock(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
CancelKeyboardLock(FROM_HERE);
ExitFullscreen(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(EnterAndExitFullscreenCycling)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, EnterAndExitFullscreenCycling) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
RequestKeyboardLock(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
ExitFullscreen(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
ExitFullscreen(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
ExitFullscreen(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
ExitFullscreen(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(GainAndLoseFocusInWindowMode)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, GainAndLoseFocusInWindowMode) {
+ NavigateToTestURL(https_fullscreen_frame());
RequestKeyboardLock(FROM_HERE);
@@ -458,28 +565,29 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
BlurContent(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(EnterFullscreenWithoutFocus)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, EnterFullscreenWithoutFocus) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
RequestKeyboardLock(FROM_HERE);
BlurContent(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
ExitFullscreen(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
FocusContent(FROM_HERE);
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(GainAndLoseFocusCyclingInFullscreen)) {
- NavigateToTestURL();
+ GainAndLoseFocusCyclingInFullscreen) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
RequestKeyboardLock(FROM_HERE);
BlurContent(FROM_HERE);
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
FocusContent(FROM_HERE);
BlurContent(FROM_HERE);
@@ -493,23 +601,22 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
ExitFullscreen(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, MAYBE_RUN(CancelWithoutLock)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, CancelWithoutLock) {
+ NavigateToTestURL(https_fullscreen_frame());
CancelKeyboardLock(FROM_HERE);
CancelKeyboardLock(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, MAYBE_RUN(MultipleLockCalls)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, MultipleLockCalls) {
+ NavigateToTestURL(https_fullscreen_frame());
RequestKeyboardLock(FROM_HERE);
RequestKeyboardLock(FROM_HERE);
RequestKeyboardLock(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(MultipleCancelCalls)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, MultipleCancelCalls) {
+ NavigateToTestURL(https_fullscreen_frame());
RequestKeyboardLock(FROM_HERE);
@@ -518,9 +625,9 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
CancelKeyboardLock(FROM_HERE);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockCallWithAllInvalidKeys)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, LockCallWithAllInvalidKeys) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
bool result;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
@@ -528,14 +635,14 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
ASSERT_TRUE(result);
// If no valid Keys are passed in, then KeyboardLock will not be requested.
- ASSERT_EQ(nullptr, web_contents()->GetKeyboardLockWidget());
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockCallWithSomeInvalidKeys)) {
- NavigateToTestURL();
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, LockCallWithSomeInvalidKeys) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
bool result;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
@@ -543,63 +650,308 @@ IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
ASSERT_TRUE(result);
// If some valid Keys are passed in, then KeyboardLock will be requested.
- ASSERT_NE(nullptr, web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
- EnterFullscreen(FROM_HERE);
+ EnterFullscreen(FROM_HERE, url_for_test);
}
IN_PROC_BROWSER_TEST_F(KeyboardLockDisabledBrowserTest,
- MAYBE_RUN(NoKeyboardLockWhenDisabled)) {
+ NoKeyboardLockWhenDisabled) {
ASSERT_TRUE(NavigateToURL(shell(), https_fullscreen_frame()));
- ASSERT_FALSE(KeyboardLockApiExists());
+ ASSERT_TRUE(KeyboardLockApiExists());
+
+ // KeyboardLockServiceImpl returns success from the RequestKeyboardLock()
+ // call when the Chrome side of the feature is disabled. This prevents
+ // problems running the WebKit layout tests.
+ bool result = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(web_contents()->GetMainFrame(),
+ kKeyboardLockMethodCallWithAllKeys,
+ &result));
+ ASSERT_TRUE(result);
+
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
+}
+
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
+ KeyboardLockNotAllowedForSameOriginIFrame) {
+ NavigateToTestURL(https_cross_site_frame());
+
+ // The first child has the same origin as the top-level domain.
+ RenderFrameHost* child_frame = ChildFrameAt(web_contents()->GetMainFrame(),
+ /*child_index=*/0);
+ ASSERT_TRUE(child_frame);
+
+ bool api_exists = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ child_frame, kKeyboardLockMethodExistanceCheck, &api_exists));
+ ASSERT_TRUE(api_exists);
+
+ bool result = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ child_frame, kKeyboardLockMethodCallWithAllKeys, &result));
+ ASSERT_FALSE(result);
+
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(KeyboardLockNotAllowedForIFrame)) {
- // TODO(joedow): IMPLEMENT.
+ KeyboardLockNotAllowedForCrossOriginIFrame) {
+ NavigateToTestURL(https_cross_site_frame());
+
+ // The second child has a different origin as the top-level domain.
+ RenderFrameHost* child_frame = ChildFrameAt(web_contents()->GetMainFrame(),
+ /*child_index=*/1);
+ ASSERT_TRUE(child_frame);
+
+ bool api_exists = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ child_frame, kKeyboardLockMethodExistanceCheck, &api_exists));
+ ASSERT_TRUE(api_exists);
+
+ bool result = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ child_frame, kKeyboardLockMethodCallWithAllKeys, &result));
+ ASSERT_FALSE(result);
+
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(KeyboardUnlockedWhenNavigatingAway)) {
- // TODO(joedow): IMPLEMENT.
+ KeyboardUnlockedWhenNavigatingToSameUrl) {
+ GURL url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(url_for_test);
+ EnterFullscreen(FROM_HERE, url_for_test);
+ RequestKeyboardLock(FROM_HERE);
+
+ // Navigate to the same URL which will reset the keyboard lock state.
+ NavigateToTestURL(url_for_test);
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
+
+ // Entering fullscreen on the new page should not engage keyboard lock.
+ EnterFullscreen(FROM_HERE, url_for_test);
+ ASSERT_FALSE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(CrossOriginIFrameDoesNotReceiveInput)) {
- // TODO(joedow): Added per code review feedback.
- // Steps: Main frame initiates keyboard lock and goes fullscreen. Is input
- // delivered to cross-origin iFrame?
+ KeyboardUnlockedWhenNavigatingAway) {
+ GURL first_url_for_test = https_fullscreen_frame();
+ NavigateToTestURL(first_url_for_test);
+ EnterFullscreen(FROM_HERE, first_url_for_test);
+ RequestKeyboardLock(FROM_HERE);
+
+ // Navigate to a new URL which will reset the keyboard lock state.
+ GURL second_url_for_test = https_cross_site_frame();
+ NavigateToTestURL(second_url_for_test);
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
+
+ // Entering fullscreen on the new page should not engage keyboard lock.
+ EnterFullscreen(FROM_HERE, second_url_for_test);
+ ASSERT_FALSE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(CrossOriginIFrameRequestsFullscreen)) {
- // TODO(joedow): Added per code review feedback.
- // Steps: Main frame requests keyboard lock, cross-origin iFrame goes
- // fullscreen. Should KeyboardLock be triggered in that case (presumably no).
+ KeyboardRemainsLockedWhenIframeNavigates) {
+ NavigateToTestURL(https_cross_site_frame());
+ EnterFullscreen(FROM_HERE, https_cross_site_frame());
+ RequestKeyboardLock(FROM_HERE);
+
+ ASSERT_TRUE(NavigateIframeToURL(
+ web_contents(), kChildIframeName_0,
+ https_test_server()->GetURL(kCrossSiteTopLevelDomain, kHelloFramePath)));
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ ASSERT_TRUE(NavigateIframeToURL(
+ web_contents(), kChildIframeName_1,
+ https_test_server()->GetURL(kCrossSiteChildDomain1, kHelloFramePath)));
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ ASSERT_TRUE(NavigateIframeToURL(
+ web_contents(), kChildIframeName_2,
+ https_test_server()->GetURL(kCrossSiteChildDomain2, kHelloFramePath)));
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ ASSERT_TRUE(
+ NavigateIframeToURL(web_contents(), kChildIframeName_0,
+ https_test_server()->GetURL(kCrossSiteChildDomain2,
+ kInputFieldFramePath)));
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ ASSERT_TRUE(
+ NavigateIframeToURL(web_contents(), kChildIframeName_1,
+ https_test_server()->GetURL(kCrossSiteTopLevelDomain,
+ kInputFieldFramePath)));
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ ASSERT_TRUE(
+ NavigateIframeToURL(web_contents(), kChildIframeName_2,
+ https_test_server()->GetURL(kCrossSiteChildDomain1,
+ kInputFieldFramePath)));
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockRequestWhileIFrameIsFullscreen)) {
- // TODO(joedow): Added per code review feedback.
- // Steps: 1. Load a page with a cross-site iframe: call main frame "A" and the
- // subframe "B"
- // 2. B goes fullscreen.
- // 3. A initiates keyboard lock.
+ CrossOriginIFrameReceivesInputWhenFocused) {
+ NavigateToTestURL(https_cross_site_frame());
+ EnterFullscreen(FROM_HERE, https_cross_site_frame());
+ RequestKeyboardLock(FROM_HERE);
+
+ GURL iframe_url =
+ https_test_server()->GetURL(kCrossSiteChildDomain1, kInputFieldFramePath);
+ ASSERT_TRUE(
+ NavigateIframeToURL(web_contents(), kChildIframeName_1, iframe_url));
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ RenderFrameHost* main_frame = web_contents()->GetMainFrame();
+ RenderFrameHost* child = ChildFrameAt(main_frame, 1);
+ ASSERT_TRUE(child);
+
+ ASSERT_EQ(main_frame, web_contents()->GetFocusedFrame());
+
+ std::string result;
+ ASSERT_TRUE(ExecuteScript(child, kFocusInputFieldScript));
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ child, "window.focus(); focusInputField();", &result));
+ ASSERT_EQ("input-focus", result);
+ ASSERT_EQ(child, web_contents()->GetFocusedFrame());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ SimulateKeyPress(web_contents(), "KeyB", "B");
+ SimulateKeyPress(web_contents(), "KeyL", "BL");
+ SimulateKeyPress(web_contents(), "KeyA", "BLA");
+ SimulateKeyPress(web_contents(), "KeyR", "BLAR");
+ SimulateKeyPress(web_contents(), "KeyG", "BLARG");
+ SimulateKeyPress(web_contents(), "KeyH", "BLARGH");
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+}
+
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
+ LockRequestBeforeCrossOriginIFrameIsFullscreen) {
+ // If the main frame trusts the child frame by granting it the allowfullscreen
+ // permission, then we will allow keyboard lock to be activated when the child
+ // frame activates fullscreen.
+ NavigateToTestURL(https_cross_site_frame());
+ RequestKeyboardLock(FROM_HERE);
+ ASSERT_TRUE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_FALSE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+
+ RenderFrameHost* main_frame = web_contents()->GetMainFrame();
+ RenderFrameHost* child = ChildFrameAt(main_frame, 2);
+ ASSERT_TRUE(child);
+
+ // The third child is cross-domain and has the allowfullscreen attribute set.
+ ASSERT_TRUE(
+ NavigateIframeToURL(web_contents(), kChildIframeName_2,
+ https_test_server()->GetURL(kCrossSiteChildDomain2,
+ kFullscreenFramePath)));
+ ASSERT_TRUE(ExecuteScript(child, "activateFullscreen()"));
+
+ ASSERT_EQ(main_frame->GetView()->GetRenderWidgetHost(),
+ web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+}
+
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
+ LockRequestWhileCrossOriginIFrameIsFullscreen) {
+ // If the main frame trusts the child frame by granting it the allowfullscreen
+ // permission, then we will allow keyboard lock to be activated when the child
+ // frame activates fullscreen.
+ NavigateToTestURL(https_cross_site_frame());
+
+ RenderFrameHost* main_frame = web_contents()->GetMainFrame();
+ RenderFrameHost* child = ChildFrameAt(main_frame, 2);
+ ASSERT_TRUE(child);
+
+ // The third child is cross-domain and has the allowfullscreen attribute set.
+ ASSERT_TRUE(
+ NavigateIframeToURL(web_contents(), kChildIframeName_2,
+ https_test_server()->GetURL(kCrossSiteChildDomain2,
+ kFullscreenFramePath)));
+ ASSERT_TRUE(ExecuteScript(child, "activateFullscreen()"));
+
+ RequestKeyboardLock(FROM_HERE);
+
+ ASSERT_EQ(main_frame->GetView()->GetRenderWidgetHost(),
+ web_contents()->GetKeyboardLockWidget());
+ ASSERT_TRUE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
+}
+
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
+ LockRequestFailsFromInnerWebContents) {
+ NavigateToTestURL(https_cross_site_frame());
+
+ // The first child is a same-origin iframe.
+ RenderFrameHost* main_frame = web_contents()->GetMainFrame();
+ RenderFrameHost* child = ChildFrameAt(main_frame, 0);
+ ASSERT_TRUE(child);
+
+ WebContents* inner_contents = CreateAndAttachInnerContents(child);
+ inner_contents->SetDelegate(web_contents_delegate());
+
+ ASSERT_TRUE(
+ NavigateToURLFromRenderer(inner_contents, https_fullscreen_frame()));
+
+ bool api_exists = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ inner_contents, kKeyboardLockMethodExistanceCheck, &api_exists));
+ ASSERT_TRUE(api_exists);
+
+ bool result = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ inner_contents, kKeyboardLockMethodCallWithAllKeys, &result));
+ ASSERT_FALSE(result);
+
+ // Verify neither inner nor outer WebContents have a pending lock request.
+ WebContentsImpl* inner_contents_impl =
+ static_cast<WebContentsImpl*>(inner_contents);
+ ASSERT_FALSE(inner_contents_impl->GetKeyboardLockWidget());
+ ASSERT_FALSE(
+ inner_contents_impl->GetRenderWidgetHostView()->IsKeyboardLocked());
+ ASSERT_FALSE(web_contents()->GetKeyboardLockWidget());
+ ASSERT_FALSE(web_contents()->GetRenderWidgetHostView()->IsKeyboardLocked());
}
IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
- MAYBE_RUN(LockRequestFailsFromInnerWebContents)) {
+ SubsequentLockCallSupersedesPreviousCall) {
// TODO(joedow): Added per code review feedback.
- // Steps: Try requesting KeyboardLock from with an inner WebContents context.
- // See: CreateAndAttachInnerContents() helper method in
- // https://cs.chromium.org/chromium/src/content/public/test/test_utils.h
+ // Steps: 1. Request all keys, verify keys are locked
+ // 2. Request subset of keys, verify the subset of keys are locked, but
+ // non-requested keys are no longer locked
+ // 3. Request all keys again, verify keys are now locked
}
-IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, MAYBE_RUN(HistogramTest)) {
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
+ BrowserShortcutsHandledCorrectly) {
// TODO(joedow): Added per code review feedback.
- // Steps: Call the API methods and verify the histogram data is accurate using
- // base::HistogramTester. Alternatively, this could be integrated with the
- // test fixture as well. window_open_apitest.cc (line 317()) is an example.
+ // Steps: 1. Request keyboard lock for all keys
+ // 2. Simulate browser shortcut (Ctrl+T)
+ // 3. Verify new tab is not created
+ // 4. Unlock keyboard
+ // 5. Simulate browser shortcut (Ctrl+T)
+ // 6. Verify new tab was created
+}
+
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest,
+ InnerContentsFullscreenBehavior) {
+ // TODO(joedow): Added per code review feedback. Need to define the behavior
+ // for KeyboardLock when an attached InnerWebContents goes fullscreen.
+ // Steps: 1. Request keyboard lock for all keys
+ // 2. InnerWebContents request fullscreen
+ // 3. Verify KeyboardLock behavior (should match iframe behavior)
+}
+
+IN_PROC_BROWSER_TEST_F(KeyboardLockBrowserTest, InnerContentsInputBehavior) {
+ // TODO(joedow): Added per code review feedback. Need to define the behavior
+ // for KeyboardLock when an attached InnerWebContents goes fullscreen.
+ // Steps: 1. Request keyboard lock for all keys
+ // 2. Main frame goes fullscreen
+ // 3. Inner web contents is focused
+ // 4. Verify input behavior (should match iframe behavior)
}
} // namespace content
diff --git a/chromium/content/browser/keyboard_lock_browsertest.h b/chromium/content/browser/keyboard_lock_browsertest.h
new file mode 100644
index 00000000000..5e5237bf33d
--- /dev/null
+++ b/chromium/content/browser/keyboard_lock_browsertest.h
@@ -0,0 +1,16 @@
+// 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_KEYBOARD_LOCK_BROWSERTEST_H_
+#define CONTENT_BROWSER_KEYBOARD_LOCK_BROWSERTEST_H_
+
+namespace content {
+
+void SetWindowFocusForKeyboardLockBrowserTests(bool is_focused);
+
+void InstallCreateHooksForKeyboardLockBrowserTests();
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_KEYBOARD_LOCK_BROWSERTEST_H_
diff --git a/chromium/content/browser/keyboard_lock_browsertest_mac.mm b/chromium/content/browser/keyboard_lock_browsertest_mac.mm
new file mode 100644
index 00000000000..c08c372c7b4
--- /dev/null
+++ b/chromium/content/browser/keyboard_lock_browsertest_mac.mm
@@ -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.
+
+#include "content/browser/keyboard_lock_browsertest.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#include "content/browser/web_contents/web_contents_view_mac.h"
+
+namespace content {
+
+namespace {
+
+bool g_window_has_focus = false;
+
+class TestRenderWidgetHostView : public RenderWidgetHostViewMac {
+ public:
+ TestRenderWidgetHostView(RenderWidgetHost* host, bool is_guest_view_hack)
+ : RenderWidgetHostViewMac(host, is_guest_view_hack) {}
+ ~TestRenderWidgetHostView() override {}
+
+ bool HasFocus() const override { return g_window_has_focus; }
+};
+}
+
+void SetWindowFocusForKeyboardLockBrowserTests(bool is_focused) {
+ g_window_has_focus = is_focused;
+}
+
+void InstallCreateHooksForKeyboardLockBrowserTests() {
+ WebContentsViewMac::InstallCreateHookForTests(
+ [](RenderWidgetHost* host,
+ bool is_guest_view_hack) -> RenderWidgetHostViewMac* {
+ return new TestRenderWidgetHostView(host, is_guest_view_hack);
+ });
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/browser/leveldb_wrapper_impl.cc b/chromium/content/browser/leveldb_wrapper_impl.cc
index c17743445aa..d3c5c994d71 100644
--- a/chromium/content/browser/leveldb_wrapper_impl.cc
+++ b/chromium/content/browser/leveldb_wrapper_impl.cc
@@ -826,11 +826,13 @@ void LevelDBWrapperImpl::CommitChanges() {
}
void LevelDBWrapperImpl::OnCommitComplete(DatabaseError error) {
+ has_committed_data_ = true;
--commit_batches_in_flight_;
StartCommitTimer();
- if (error != DatabaseError::OK)
+ if (error != DatabaseError::OK) {
SetCacheMode(CacheMode::KEYS_AND_VALUES);
+ }
// Call before |DidCommit| as delegate can destroy this object.
UnloadMapIfPossible();
@@ -845,9 +847,11 @@ void LevelDBWrapperImpl::UnloadMapIfPossible() {
// * There are pending tasks waiting on the key-value map being loaded, or
// * There is no database connection.
// * We have commit batches in-flight.
+ // * We haven't committed data yet.
if (cache_mode_ != CacheMode::KEYS_ONLY_WHEN_POSSIBLE ||
map_state_ != MapState::LOADED_KEYS_AND_VALUES ||
- has_pending_load_tasks() || !database_ || commit_batches_in_flight_ > 0) {
+ has_pending_load_tasks() || !database_ || commit_batches_in_flight_ > 0 ||
+ !has_committed_data_) {
return;
}
diff --git a/chromium/content/browser/leveldb_wrapper_impl.h b/chromium/content/browser/leveldb_wrapper_impl.h
index e120d20acfa..79075941452 100644
--- a/chromium/content/browser/leveldb_wrapper_impl.h
+++ b/chromium/content/browser/leveldb_wrapper_impl.h
@@ -331,6 +331,7 @@ class CONTENT_EXPORT LevelDBWrapperImpl : public mojom::LevelDBWrapper {
RateLimiter data_rate_limiter_;
RateLimiter commit_rate_limiter_;
int commit_batches_in_flight_ = 0;
+ bool has_committed_data_ = false;
std::unique_ptr<CommitBatch> commit_batch_;
base::WeakPtrFactory<LevelDBWrapperImpl> weak_ptr_factory_;
diff --git a/chromium/content/browser/leveldb_wrapper_impl_unittest.cc b/chromium/content/browser/leveldb_wrapper_impl_unittest.cc
index 5e63e99a0f7..ac80a72e4c4 100644
--- a/chromium/content/browser/leveldb_wrapper_impl_unittest.cc
+++ b/chromium/content/browser/leveldb_wrapper_impl_unittest.cc
@@ -17,6 +17,7 @@
#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/fake_leveldb_database.h"
+#include "content/test/leveldb_wrapper_test_util.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -24,8 +25,10 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
-
namespace {
+using test::MakeSuccessCallback;
+using test::MakeGetAllCallback;
+using test::GetAllCallback;
using CacheMode = LevelDBWrapperImpl::CacheMode;
using DatabaseError = leveldb::mojom::DatabaseError;
@@ -87,32 +90,6 @@ class IncrementalBarrier {
DISALLOW_COPY_AND_ASSIGN(IncrementalBarrier);
};
-class GetAllCallback : public mojom::LevelDBWrapperGetAllCallback {
- public:
- static mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo CreateAndBind(
- bool* result,
- base::OnceClosure callback) {
- mojom::LevelDBWrapperGetAllCallbackAssociatedPtr ptr;
- auto request = mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr);
- mojo::MakeStrongAssociatedBinding(
- base::WrapUnique(new GetAllCallback(result, std::move(callback))),
- std::move(request));
- return ptr.PassInterface();
- }
-
- private:
- GetAllCallback(bool* result, base::OnceClosure callback)
- : result_(result), callback_(std::move(callback)) {}
- void Complete(bool success) override {
- *result_ = success;
- if (callback_)
- std::move(callback_).Run();
- }
-
- bool* result_;
- base::OnceClosure callback_;
-};
-
class MockDelegate : public LevelDBWrapperImpl::Delegate {
public:
MockDelegate() {}
@@ -167,33 +144,6 @@ base::OnceCallback<void(bool, const std::vector<uint8_t>&)> MakeGetCallback(
value_out);
}
-void GetAllDataCallback(leveldb::mojom::DatabaseError* status_out,
- std::vector<mojom::KeyValuePtr>* data_out,
- leveldb::mojom::DatabaseError status,
- std::vector<mojom::KeyValuePtr> data) {
- *status_out = status;
- *data_out = std::move(data);
-}
-
-base::OnceCallback<void(leveldb::mojom::DatabaseError status,
- std::vector<mojom::KeyValuePtr> data)>
-MakeGetAllCallback(leveldb::mojom::DatabaseError* status_out,
- std::vector<mojom::KeyValuePtr>* data_out) {
- return base::BindOnce(&GetAllDataCallback, status_out, data_out);
-}
-
-void SuccessCallback(base::OnceClosure callback,
- bool* success_out,
- bool success) {
- *success_out = success;
- std::move(callback).Run();
-}
-
-base::OnceCallback<void(bool)> MakeSuccessCallback(base::OnceClosure callback,
- bool* success_out) {
- return base::BindOnce(&SuccessCallback, std::move(callback), success_out);
-}
-
LevelDBWrapperImpl::Options GetDefaultTestingOptions(CacheMode cache_mode) {
LevelDBWrapperImpl::Options options;
options.max_size = kTestSizeLimit;
@@ -261,6 +211,8 @@ class LevelDBWrapperImplTest : public testing::Test,
mojom::LevelDBWrapper* wrapper() { return level_db_wrapper_ptr_.get(); }
LevelDBWrapperImpl* wrapper_impl() { return level_db_wrapper_.get(); }
+ void FlushWrapperBinding() { level_db_wrapper_ptr_.FlushForTesting(); }
+
bool GetSync(mojom::LevelDBWrapper* wrapper,
const std::vector<uint8_t>& key,
std::vector<uint8_t>* result) {
@@ -271,38 +223,15 @@ class LevelDBWrapperImplTest : public testing::Test,
return success;
}
- bool PutSync(mojom::LevelDBWrapper* wrapper,
- const std::vector<uint8_t>& key,
- const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
- std::string source = kTestSource) {
- bool success = false;
- base::RunLoop loop;
- wrapper->Put(key, value, client_old_value, source,
- MakeSuccessCallback(loop.QuitClosure(), &success));
- loop.Run();
- return success;
- }
-
bool DeleteSync(
mojom::LevelDBWrapper* wrapper,
const std::vector<uint8_t>& key,
const base::Optional<std::vector<uint8_t>>& client_old_value) {
- bool success = false;
- base::RunLoop loop;
- wrapper->Delete(key, client_old_value, test_source_,
- MakeSuccessCallback(loop.QuitClosure(), &success));
- loop.Run();
- return success;
+ return test::DeleteSync(wrapper, key, client_old_value, test_source_);
}
bool DeleteAllSync(mojom::LevelDBWrapper* wrapper) {
- bool success = false;
- base::RunLoop loop;
- wrapper->DeleteAll(test_source_,
- MakeSuccessCallback(loop.QuitClosure(), &success));
- loop.Run();
- return success;
+ return test::DeleteAllSync(wrapper, test_source_);
}
bool GetSync(const std::vector<uint8_t>& key, std::vector<uint8_t>* result) {
@@ -313,7 +242,7 @@ class LevelDBWrapperImplTest : public testing::Test,
const std::vector<uint8_t>& value,
const base::Optional<std::vector<uint8_t>>& client_old_value,
std::string source = kTestSource) {
- return PutSync(wrapper(), key, value, client_old_value, source);
+ return test::PutSync(wrapper(), key, value, client_old_value, source);
}
bool DeleteSync(
@@ -326,20 +255,9 @@ class LevelDBWrapperImplTest : public testing::Test,
std::string GetSyncStrUsingGetAll(LevelDBWrapperImpl* wrapper_impl,
const std::string& key) {
- leveldb::mojom::DatabaseError status;
std::vector<mojom::KeyValuePtr> data;
- bool done = false;
-
- base::RunLoop loop;
- // Testing the 'Sync' mojo version is a big headache involving 3 threads, so
- // just test the async version.
- wrapper_impl->GetAll(
- GetAllCallback::CreateAndBind(&done, loop.QuitClosure()),
- MakeGetAllCallback(&status, &data));
- loop.Run();
-
- if (!done)
- return "";
+ leveldb::mojom::DatabaseError status =
+ test::GetAllSyncOnDedicatedPipe(wrapper_impl, &data);
if (status != leveldb::mojom::DatabaseError::OK)
return "";
@@ -499,6 +417,7 @@ TEST_F(LevelDBWrapperImplTest, PutLoadsValuesAfterCacheModeUpgrade) {
// Do a put to load the key-only cache.
EXPECT_TRUE(PutSync(key, value1, base::nullopt));
+ BlockingCommit();
EXPECT_EQ(LevelDBWrapperImpl::MapState::LOADED_KEYS_ONLY,
wrapper_impl()->map_state_);
@@ -516,20 +435,12 @@ TEST_F(LevelDBWrapperImplTest, PutLoadsValuesAfterCacheModeUpgrade) {
TEST_P(LevelDBWrapperImplParamTest, GetAll) {
wrapper_impl()->SetCacheModeForTesting(GetParam());
- DatabaseError status;
+
std::vector<mojom::KeyValuePtr> data;
- bool result = false;
+ leveldb::mojom::DatabaseError status = test::GetAllSync(wrapper(), &data);
- base::RunLoop loop;
- // Testing the 'Sync' mojo version is a big headache involving 3 threads, so
- // just test the async version.
- wrapper_impl()->GetAll(
- GetAllCallback::CreateAndBind(&result, loop.QuitClosure()),
- MakeGetAllCallback(&status, &data));
- loop.Run();
EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status);
EXPECT_EQ(2u, data.size());
- EXPECT_TRUE(result);
}
TEST_P(LevelDBWrapperImplParamTest, CommitPutToDB) {
@@ -829,17 +740,8 @@ TEST_P(LevelDBWrapperImplParamTest, FixUpData) {
changes.push_back(std::make_pair(test_prefix_bytes_, ToBytes("bla")));
delegate()->set_mock_changes(std::move(changes));
- leveldb::mojom::DatabaseError status;
std::vector<mojom::KeyValuePtr> data;
- bool result = false;
-
- base::RunLoop loop;
- // Testing the 'Sync' mojo version is a big headache involving 3 threads, so
- // just test the async version.
- wrapper_impl()->GetAll(
- GetAllCallback::CreateAndBind(&result, loop.QuitClosure()),
- MakeGetAllCallback(&status, &data));
- loop.Run();
+ leveldb::mojom::DatabaseError status = test::GetAllSync(wrapper(), &data);
EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status);
ASSERT_EQ(2u, data.size());
@@ -895,12 +797,26 @@ TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) {
wrapper_impl()->SetCacheModeForTesting(GetParam());
std::vector<uint8_t> key = test_key2_bytes_;
std::vector<uint8_t> value = ToBytes("foo");
- std::vector<uint8_t> value2 = ToBytes("foobar");
+ std::vector<uint8_t> value2 = ToBytes("foo2");
+ std::vector<uint8_t> value3 = ToBytes("foobar");
// The initial map always has values, so a nullopt is fine for the old value.
ASSERT_TRUE(PutSync(key, value, base::nullopt));
ASSERT_TRUE(wrapper_impl()->commit_batch_);
+ // Wrapper stays in CacheMode::KEYS_AND_VALUES until the first commit has
+ // succeeded.
+ EXPECT_TRUE(wrapper_impl()->commit_batch_->changed_values.empty());
+ auto* changes = &wrapper_impl()->commit_batch_->changed_keys;
+ ASSERT_EQ(1u, changes->size());
+ EXPECT_EQ(key, *changes->begin());
+
+ BlockingCommit();
+
+ ASSERT_TRUE(PutSync(key, value2, value));
+ ASSERT_TRUE(wrapper_impl()->commit_batch_);
+
+ // Commit has occured, so the map type will diverge based on the cache mode.
if (GetParam() == CacheMode::KEYS_AND_VALUES) {
EXPECT_TRUE(wrapper_impl()->commit_batch_->changed_values.empty());
auto* changes = &wrapper_impl()->commit_batch_->changed_keys;
@@ -912,19 +828,19 @@ TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) {
ASSERT_EQ(1u, changes->size());
auto it = changes->begin();
EXPECT_EQ(key, it->first);
- EXPECT_EQ(value, it->second);
+ EXPECT_EQ(value2, it->second);
}
BlockingCommit();
- EXPECT_EQ("foo", get_mock_data(test_prefix_ + test_key2_));
+ EXPECT_EQ("foo2", get_mock_data(test_prefix_ + test_key2_));
if (GetParam() == CacheMode::KEYS_AND_VALUES)
EXPECT_EQ(2u, wrapper_impl()->keys_values_map_.size());
else
EXPECT_EQ(2u, wrapper_impl()->keys_only_map_.size());
- ASSERT_TRUE(PutSync(key, value, value));
+ ASSERT_TRUE(PutSync(key, value2, value2));
EXPECT_FALSE(wrapper_impl()->commit_batch_);
- ASSERT_TRUE(PutSync(key, value2, value));
+ ASSERT_TRUE(PutSync(key, value3, value2));
ASSERT_TRUE(wrapper_impl()->commit_batch_);
if (GetParam() == CacheMode::KEYS_AND_VALUES) {
@@ -937,7 +853,7 @@ TEST_P(LevelDBWrapperImplParamTest, CommitOnDifferentCacheModes) {
EXPECT_EQ(1u, changes->size());
auto it = changes->find(key);
ASSERT_NE(it, changes->end());
- EXPECT_EQ(value2, it->second);
+ EXPECT_EQ(value3, it->second);
}
clear_mock_data();
@@ -969,14 +885,14 @@ TEST_F(LevelDBWrapperImplTest, GetAllWhenCacheOnlyKeys) {
{
IncrementalBarrier barrier(loop.QuitClosure());
- wrapper_impl()->Put(key, value, value2, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_result1));
+ wrapper()->Put(key, value, value2, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_result1));
- wrapper_impl()->GetAll(
- GetAllCallback::CreateAndBind(&result, barrier.Get()),
- MakeGetAllCallback(&status, &data));
- wrapper_impl()->Put(key, value2, value, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_result2));
+ wrapper()->GetAll(GetAllCallback::CreateAndBind(&result, barrier.Get()),
+ MakeGetAllCallback(&status, &data));
+ wrapper()->Put(key, value2, value, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_result2));
+ FlushWrapperBinding();
}
// GetAll triggers a commit when it's switching map types.
@@ -1037,21 +953,22 @@ TEST_F(LevelDBWrapperImplTest, GetAllAfterSetCacheMode) {
{
IncrementalBarrier barrier(loop.QuitClosure());
- wrapper_impl()->Put(key, value, value2, test_source_,
- MakeSuccessCallback(barrier.Get(), &put_success));
+ wrapper()->Put(key, value, value2, test_source_,
+ MakeSuccessCallback(barrier.Get(), &put_success));
// Put task triggers database upgrade, so there are no more changes
// to commit.
+ FlushWrapperBinding();
EXPECT_FALSE(wrapper_impl()->has_changes_to_commit());
EXPECT_TRUE(wrapper_impl()->has_pending_load_tasks());
- wrapper_impl()->GetAll(
+ wrapper()->GetAll(
GetAllCallback::CreateAndBind(&get_all_success, barrier.Get()),
MakeGetAllCallback(&status, &data));
// This Delete() should not affect the value returned by GetAll().
- wrapper_impl()->Delete(key, value, test_source_,
- MakeSuccessCallback(barrier.Get(), &delete_success));
+ wrapper()->Delete(key, value, test_source_,
+ MakeSuccessCallback(barrier.Get(), &delete_success));
}
loop.Run();
diff --git a/chromium/content/browser/linux_ipc_browsertest.cc b/chromium/content/browser/linux_ipc_browsertest.cc
index 0654dff6924..7be05896fec 100644
--- a/chromium/content/browser/linux_ipc_browsertest.cc
+++ b/chromium/content/browser/linux_ipc_browsertest.cc
@@ -13,6 +13,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "services/service_manager/sandbox/switches.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,8 +33,8 @@ class LinuxIPCBrowserTest : public ContentBrowserTest,
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
if (GetParam() == "no-zygote") {
+ command_line->AppendSwitch(service_manager::switches::kNoSandbox);
command_line->AppendSwitch(switches::kNoZygote);
- command_line->AppendSwitch(switches::kNoSandbox);
}
}
diff --git a/chromium/content/browser/loader/cors_file_origin_browsertest.cc b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
index 5bd57848cbc..af3ed282f18 100644
--- a/chromium/content/browser/loader/cors_file_origin_browsertest.cc
+++ b/chromium/content/browser/loader/cors_file_origin_browsertest.cc
@@ -89,7 +89,7 @@ class CORSFileOriginBrowserTest : public ContentBrowserTest {
base::AutoLock lock(lock_);
// Need to obtain the path on the main thread.
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_data_loader_path_));
+ ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_data_loader_path_));
test_data_loader_path_ =
test_data_loader_path_.Append(FILE_PATH_LITERAL("loader"));
diff --git a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
index 0f195de5327..494ecda070c 100644
--- a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -599,7 +599,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
// Make sure the test covers all the safelisted headers known to the product
// code.
for (const std::string& safelisted_header :
- CrossSiteDocumentResourceHandler::GetCorsSafelistedHeadersForTesting()) {
+ network::CrossOriginReadBlocking::GetCorsSafelistedHeadersForTesting()) {
EXPECT_TRUE(
interceptor.response_head().headers->HasHeader(safelisted_header));
@@ -806,9 +806,12 @@ class CrossSiteDocumentBlockingKillSwitchTest
: public CrossSiteDocumentBlockingTest {
public:
CrossSiteDocumentBlockingKillSwitchTest() {
- // Simulate flipping the kill switch.
- scoped_feature_list_.InitAndDisableFeature(
- features::kCrossSiteDocumentBlockingIfIsolating);
+ // Simulate flipping both of the kill switches.
+ std::vector<base::Feature> disabled_features = {
+ features::kCrossSiteDocumentBlockingAlways,
+ features::kCrossSiteDocumentBlockingIfIsolating,
+ };
+ scoped_feature_list_.InitWithFeatures({}, disabled_features);
}
~CrossSiteDocumentBlockingKillSwitchTest() override {}
@@ -891,13 +894,10 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingDisableVsFeatureTest,
EXPECT_FALSE(was_blocked);
}
-// Without any Site Isolation (in the base test class), there should be no
-// document blocking.
+// Even without any Site Isolation, document blocking should be turned on by
+// default.
IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingBaseTest,
- DontBlockDocumentsByDefault) {
- if (AreAllSitesIsolatedForTesting())
- return;
-
+ BlockDocumentsByDefault) {
// Load a page that issues illegal cross-site document requests to bar.com.
GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -905,7 +905,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingBaseTest,
bool was_blocked;
ASSERT_TRUE(ExecuteScriptAndExtractBool(
shell(), "sendRequest(\"valid.html\");", &was_blocked));
- EXPECT_FALSE(was_blocked);
+ EXPECT_TRUE(was_blocked);
}
// Test class to verify that documents are blocked for isolated origins as well.
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler.cc b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
index a6aedd72e8a..9924a53b147 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.cc
@@ -7,8 +7,6 @@
#include <string.h>
#include <algorithm>
-#include <string>
-#include <unordered_set>
#include <utility>
#include "base/bind.h"
@@ -35,112 +33,11 @@
#include "services/metrics/public/cpp/ukm_recorder.h"
using MimeType = network::CrossOriginReadBlocking::MimeType;
-using SniffingResult = network::CrossOriginReadBlocking::SniffingResult;
namespace content {
-// An interface to enable incremental content sniffing. These are instantiated
-// for each each request; thus they can be stateful.
-class CrossSiteDocumentResourceHandler::ConfirmationSniffer {
- public:
- virtual ~ConfirmationSniffer() = default;
-
- // Called after data is read from the network. |sniffing_buffer| contains the
- // entire response body delivered thus far. To support streaming,
- // |new_data_offset| gives the offset into |sniffing_buffer| at which new data
- // was appended since the last read.
- virtual void OnDataAvailable(base::StringPiece sniffing_buffer,
- size_t new_data_offset) = 0;
-
- // Returns true if the return value of IsConfirmedContentType() might change
- // with the addition of more data. Returns false if a final decision is
- // available.
- virtual bool WantsMoreData() const = 0;
-
- // Returns true if the data has been confirmed to be of the CORB-protected
- // content type that this sniffer is intended to detect.
- virtual bool IsConfirmedContentType() const = 0;
-
- // Called when this sniffer's decision was used to block a response. This will
- // only be invoked when an earlier call to IsConfirmedContentType() returned
- // true.
- virtual void LogBlockedResponse(ResourceType resource_type) const {}
-};
-
namespace {
-void LogCrossSiteDocumentAction(
- CrossSiteDocumentResourceHandler::Action action) {
- UMA_HISTOGRAM_ENUMERATION("SiteIsolation.XSD.Browser.Action", action,
- CrossSiteDocumentResourceHandler::Action::kCount);
-}
-
-// A ConfirmationSniffer that wraps one of the sniffing functions from
-// network::CrossOriginReadBlocking.
-class SimpleConfirmationSniffer
- : public CrossSiteDocumentResourceHandler::ConfirmationSniffer {
- public:
- // The function pointer type corresponding to one of the available sniffing
- // functions from network::CrossOriginReadBlocking.
- using SnifferFunction =
- decltype(&network::CrossOriginReadBlocking::SniffForHTML);
-
- explicit SimpleConfirmationSniffer(SnifferFunction sniffer_function)
- : sniffer_function_(sniffer_function) {}
- ~SimpleConfirmationSniffer() override = default;
-
- void OnDataAvailable(base::StringPiece sniffing_buffer,
- size_t new_data_offset) final {
- DCHECK_LE(new_data_offset, sniffing_buffer.length());
- if (new_data_offset == sniffing_buffer.length()) {
- // No new data -- do nothing. This happens at end-of-stream.
- return;
- }
- // The sniffing functions don't support streaming, so with each new chunk of
- // data, call the sniffer on the whole buffer.
- last_sniff_result_ = (*sniffer_function_)(sniffing_buffer);
- }
-
- bool WantsMoreData() const final {
- // kNo and kYes results are final, meaning that sniffing can stop once they
- // occur. A kMaybe result corresponds to an indeterminate state, that could
- // change to kYes or kNo with more data.
- return last_sniff_result_ == SniffingResult::kMaybe;
- }
-
- bool IsConfirmedContentType() const final {
- // Only confirm the mime type if an affirmative pattern (e.g. an HTML tag,
- // if using the HTML sniffer) was detected.
- //
- // Note that if the stream ends (or net::kMaxBytesToSniff has been reached)
- // and |last_sniff_result_| is kMaybe, the response is allowed to go
- // through.
- return last_sniff_result_ == SniffingResult::kYes;
- }
-
- private:
- // The function that actually knows how to sniff for a content type.
- SnifferFunction sniffer_function_;
-
- // Result of sniffing the data available thus far.
- SniffingResult last_sniff_result_ = SniffingResult::kMaybe;
-};
-
-// A ConfirmationSniffer for parser breakers (fetch-only resources). This logs
-// to an UMA histogram whenever it is the reason for a response being blocked.
-class FetchOnlyResourceSniffer : public SimpleConfirmationSniffer {
- public:
- FetchOnlyResourceSniffer()
- : SimpleConfirmationSniffer(
- &network::CrossOriginReadBlocking::SniffForFetchOnlyResource) {}
-
- void LogBlockedResponse(ResourceType resource_type) const final {
- UMA_HISTOGRAM_ENUMERATION(
- "SiteIsolation.XSD.Browser.BlockedForParserBreaker", resource_type,
- content::RESOURCE_TYPE_LAST_TYPE);
- }
-};
-
// An IOBuffer to enable writing into a existing IOBuffer at a given offset.
class LocalIoBufferWithOffset : public net::WrappedIOBuffer {
public:
@@ -153,60 +50,6 @@ class LocalIoBufferWithOffset : public net::WrappedIOBuffer {
scoped_refptr<net::IOBuffer> buf_;
};
-// Headers from
-// https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name.
-//
-// Note that XSDB doesn't block responses allowed through CORS - this means
-// that the list of allowed headers below doesn't have to consider header
-// names listed in the Access-Control-Expose-Headers header.
-const char* const kCorsSafelistedHeaders[] = {
- "cache-control", "content-language", "content-type",
- "expires", "last-modified", "pragma",
-};
-
-// Removes headers that should be blocked in cross-origin case.
-// See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name.
-void SanitizeResponseHeaders(
- const scoped_refptr<net::HttpResponseHeaders>& headers) {
- DCHECK(headers);
- std::unordered_set<std::string> names_of_headers_to_remove;
-
- size_t it = 0;
- std::string name;
- std::string value;
- while (headers->EnumerateHeaderLines(&it, &name, &value)) {
- // Don't remove CORS headers - doing so would lead to incorrect error
- // messages for CORS-blocked responses (e.g. Blink would say "[...] No
- // 'Access-Control-Allow-Origin' header is present [...]" instead of saying
- // something like "[...] Access-Control-Allow-Origin' header has a value
- // 'http://www2.localhost:8000' that is not equal to the supplied origin
- // [...]").
- if (base::StartsWith(name, "Access-Control-",
- base::CompareCase::INSENSITIVE_ASCII)) {
- continue;
- }
-
- // Remove all other headers (but note the final exclusion below).
- names_of_headers_to_remove.insert(base::ToLowerASCII(name));
- }
-
- // Exclude from removals headers from
- // https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name.
- for (const char* header : kCorsSafelistedHeaders)
- names_of_headers_to_remove.erase(header);
-
- headers->RemoveHeaders(names_of_headers_to_remove);
-}
-
-// Sanitizes/strips metadata of a response we decided to block.
-void SanitizeResourceResponse(
- const scoped_refptr<network::ResourceResponse>& response) {
- DCHECK(response);
- response->head.content_length = 0;
- if (response->head.headers)
- SanitizeResponseHeaders(response->head.headers);
-}
-
} // namespace
// static
@@ -235,35 +78,20 @@ void CrossSiteDocumentResourceHandler::LogBlockedResponseOnUIThread(
.Record(recorder);
}
-// static
void CrossSiteDocumentResourceHandler::LogBlockedResponse(
ResourceRequestInfoImpl* resource_request_info,
- bool needed_sniffing,
- MimeType canonical_mime_type,
- int http_response_code,
- int64_t content_length) {
+ int http_response_code) {
DCHECK(resource_request_info);
- DCHECK_NE(network::CrossOriginReadBlocking::MimeType::kInvalid,
- canonical_mime_type);
-
- LogCrossSiteDocumentAction(
- needed_sniffing
- ? CrossSiteDocumentResourceHandler::Action::kBlockedAfterSniffing
- : CrossSiteDocumentResourceHandler::Action::kBlockedWithoutSniffing);
-
- UMA_HISTOGRAM_BOOLEAN(
- "SiteIsolation.XSD.Browser.Blocked.ContentLength.WasAvailable",
- content_length >= 0);
- if (content_length >= 0) {
- UMA_HISTOGRAM_COUNTS_10000(
- "SiteIsolation.XSD.Browser.Blocked.ContentLength.ValueIfAvailable",
- content_length);
- }
+ DCHECK(analyzer_);
+ DCHECK_NE(network::CrossOriginReadBlocking::MimeType::kInvalidMimeType,
+ analyzer_->canonical_mime_type());
+
+ analyzer_->LogBlockedResponse();
ResourceType resource_type = resource_request_info->GetResourceType();
UMA_HISTOGRAM_ENUMERATION("SiteIsolation.XSD.Browser.Blocked", resource_type,
content::RESOURCE_TYPE_LAST_TYPE);
- switch (canonical_mime_type) {
+ switch (analyzer_->canonical_mime_type()) {
case MimeType::kHtml:
UMA_HISTOGRAM_ENUMERATION("SiteIsolation.XSD.Browser.Blocked.HTML",
resource_type,
@@ -292,6 +120,11 @@ void CrossSiteDocumentResourceHandler::LogBlockedResponse(
default:
NOTREACHED();
}
+ if (analyzer_->found_parser_breaker()) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "SiteIsolation.XSD.Browser.BlockedForParserBreaker", resource_type,
+ content::RESOURCE_TYPE_LAST_TYPE);
+ }
// The last committed URL is only available on the UI thread - we need to hop
// onto the UI thread to log an UKM event. Note that this is racey - by the
@@ -303,8 +136,8 @@ void CrossSiteDocumentResourceHandler::LogBlockedResponse(
base::BindOnce(
&CrossSiteDocumentResourceHandler::LogBlockedResponseOnUIThread,
resource_request_info->GetWebContentsGetterForRequest(),
- needed_sniffing, canonical_mime_type, resource_type,
- http_response_code, content_length));
+ analyzer_->needs_sniffing(), analyzer_->canonical_mime_type(),
+ resource_type, http_response_code, analyzer_->content_length()));
}
// ResourceController that runs a closure on Resume(), and forwards failures
@@ -378,19 +211,18 @@ CrossSiteDocumentResourceHandler::~CrossSiteDocumentResourceHandler() {}
void CrossSiteDocumentResourceHandler::OnResponseStarted(
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) {
- content_length_ = response->head.content_length;
has_response_started_ = true;
http_response_code_ =
response->head.headers ? response->head.headers->response_code() : 0;
- LogCrossSiteDocumentAction(
- CrossSiteDocumentResourceHandler::Action::kResponseStarted);
+ network::CrossOriginReadBlocking::LogAction(
+ network::CrossOriginReadBlocking::Action::kResponseStarted);
- should_block_based_on_headers_ = ShouldBlockBasedOnHeaders(response);
+ should_block_based_on_headers_ = ShouldBlockBasedOnHeaders(*response);
// If blocking is possible, postpone forwarding |response| to the
// |next_handler_|, until we have made the allow-vs-block decision
- // (which might need more time depending on |needs_sniffing_|).
+ // (which might need more time depending on the sniffing needs).
if (should_block_based_on_headers_) {
pending_response_start_ = response;
controller->Resume();
@@ -527,7 +359,7 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
// handler's buffer and resume the response without blocking.
bool confirmed_blockable = false;
ResourceRequestInfoImpl* info = GetRequestInfo();
- if (!needs_sniffing_) {
+ if (!analyzer_->needs_sniffing()) {
// If sniffing is impossible (e.g., because this is a range request), or
// if sniffing is disabled due to a nosniff header AND the server returned
// a protected mime type, then we have enough information to block
@@ -553,29 +385,12 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
std::min(local_buffer_bytes_read_, net::kMaxBytesToSniff);
base::StringPiece data(local_buffer_->data(), bytes_to_sniff);
- for (size_t i = 0; i < sniffers_.size();) {
- sniffers_[i]->OnDataAvailable(data, new_data_offset);
-
- if (!more_data_possible || !sniffers_[i]->WantsMoreData()) {
- if (sniffers_[i]->IsConfirmedContentType()) {
- // We're done sniffing; this response is CORB-protected.
- confirmed_blockable = true;
- sniffers_[i]->LogBlockedResponse(info->GetResourceType());
- break;
- }
-
- // This response is CORB-exempt as far as this sniffer is concerned;
- // remove it from the list.
- sniffers_.erase(sniffers_.begin() + i);
- } else {
- i++;
- }
- }
+ // If we have some new data, ask the |analyzer_| to sniff it.
+ analyzer_->SniffResponseBody(data, new_data_offset);
- // When there are no sniffers left, the response is allowed.
- const bool confirmed_allowed = sniffers_.empty();
+ const bool confirmed_allowed = analyzer_->should_allow();
+ confirmed_blockable = analyzer_->should_block();
DCHECK(!(confirmed_blockable && confirmed_allowed));
- DCHECK(confirmed_blockable || confirmed_allowed || more_data_possible);
// If sniffing didn't yield a conclusive response, and we haven't read too
// many bytes yet or hit the end of the stream, buffer up some more data.
@@ -585,11 +400,6 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
}
}
- if (needs_sniffing_) {
- UMA_HISTOGRAM_COUNTS("SiteIsolation.XSD.Browser.BytesReadForSniffing",
- local_buffer_bytes_read_);
- }
-
// At this point we have already made a block-vs-allow decision and we know
// that we can wake the |next_handler_| and let it catch-up with our
// processing of the response. The first step will always be calling
@@ -615,13 +425,13 @@ void CrossSiteDocumentResourceHandler::OnReadCompleted(
: "null",
"url", request()->url().spec());
- LogBlockedResponse(info, needs_sniffing_, canonical_mime_type_,
- http_response_code_, content_length_);
+ LogBlockedResponse(info, http_response_code_);
// Block the response and throw away the data. Report zero bytes read.
blocked_read_completed_ = true;
info->set_blocked_cross_site_document(true);
- SanitizeResourceResponse(pending_response_start_);
+ network::CrossOriginReadBlocking::SanitizeBlockedResponse(
+ pending_response_start_);
// Pass an empty/blocked body onto the next handler. size of the two
// buffers is the same (see OnWillRead). After the next statement,
@@ -716,25 +526,20 @@ void CrossSiteDocumentResourceHandler::OnResponseCompleted(
} else {
// Only report XSDB status for successful (i.e. non-aborted,
// non-errored-out) requests.
- if (status.is_success()) {
- LogCrossSiteDocumentAction(
- needs_sniffing_
- ? CrossSiteDocumentResourceHandler::Action::kAllowedAfterSniffing
- : CrossSiteDocumentResourceHandler::Action::
- kAllowedWithoutSniffing);
- }
+ if (status.is_success())
+ analyzer_->LogAllowedResponse();
next_handler_->OnResponseCompleted(status, std::move(controller));
}
}
bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
- network::ResourceResponse* response) {
- // The checks in this method are ordered to rule out blocking in most cases as
- // quickly as possible. Checks that are likely to lead to returning false or
- // that are inexpensive should be near the top.
- const GURL& url = request()->url();
- url::Origin target_origin = url::Origin::Create(url);
+ const network::ResourceResponse& response) {
+ analyzer_ =
+ std::make_unique<network::CrossOriginReadBlocking::ResponseAnalyzer>(
+ *request(), response);
+ if (analyzer_->should_allow())
+ return false;
// Check if the response's site needs to have its documents protected. By
// default, this will usually return false.
@@ -744,38 +549,22 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
switch (SiteIsolationPolicy::IsCrossSiteDocumentBlockingEnabled()) {
case SiteIsolationPolicy::XSDB_ENABLED_UNCONDITIONALLY:
break;
- case SiteIsolationPolicy::XSDB_ENABLED_IF_ISOLATED:
+ case SiteIsolationPolicy::XSDB_ENABLED_IF_ISOLATED: {
+ url::Origin target_origin = url::Origin::Create(request()->url());
if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites() &&
!ChildProcessSecurityPolicyImpl::GetInstance()->IsIsolatedOrigin(
target_origin)) {
return false;
}
break;
+ }
case SiteIsolationPolicy::XSDB_DISABLED:
return false;
}
- // Treat a missing initiator as an empty origin to be safe, though we don't
- // expect this to happen. Unfortunately, this requires a copy.
- url::Origin initiator;
- if (request()->initiator().has_value())
- initiator = request()->initiator().value();
-
- // Don't block same-origin documents.
- if (initiator.IsSameOriginWith(target_origin))
- return false;
-
- // Only block documents from HTTP(S) schemes. Checking the scheme of
- // |target_origin| ensures that we also protect content of blob: and
- // filesystem: URLs if their nested origins have a HTTP(S) scheme.
- if (!network::CrossOriginReadBlocking::IsBlockableScheme(
- target_origin.GetURL()))
- return false;
-
- // Allow requests from file:// URLs for now.
- // TODO(creis): Limit this to when the allow_universal_access_from_file_urls
- // preference is set. See https://crbug.com/789781.
- if (initiator.scheme() == url::kFileScheme)
+ // Only block if this is a request made from a renderer process.
+ const ResourceRequestInfoImpl* info = GetRequestInfo();
+ if (!info || info->GetChildID() == -1)
return false;
// Give embedder a chance to skip document blocking for this response.
@@ -783,44 +572,9 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
GetContentClient()
->browser()
->GetInitatorSchemeBypassingDocumentBlocking();
- if (initiator_scheme_exception &&
- initiator.scheme() == initiator_scheme_exception) {
- return false;
- }
-
- // Only block if this is a request made from a renderer process.
- const ResourceRequestInfoImpl* info = GetRequestInfo();
- if (!info || info->GetChildID() == -1)
+ if (initiator_scheme_exception && request()->initiator().has_value() &&
+ request()->initiator()->scheme() == initiator_scheme_exception) {
return false;
-
- // Allow the response through if it has valid CORS headers.
- std::string cors_header;
- response->head.headers->GetNormalizedHeader("access-control-allow-origin",
- &cors_header);
- if (network::CrossOriginReadBlocking::IsValidCorsHeaderSet(initiator,
- cors_header)) {
- return false;
- }
-
- // Requests from foo.example.com will consult foo.example.com's service worker
- // first (if one has been registered). The service worker can handle requests
- // initiated by foo.example.com even if they are cross-origin (e.g. requests
- // for bar.example.com). This is okay and should not be blocked by XSDB,
- // unless the initiator opted out of CORS / opted into receiving an opaque
- // response. See also https://crbug.com/803672.
- if (response->head.was_fetched_via_service_worker) {
- switch (response->head.response_type_via_service_worker) {
- case network::mojom::FetchResponseType::kBasic:
- case network::mojom::FetchResponseType::kCORS:
- case network::mojom::FetchResponseType::kDefault:
- case network::mojom::FetchResponseType::kError:
- // Non-opaque responses shouldn't be blocked.
- return false;
- case network::mojom::FetchResponseType::kOpaque:
- case network::mojom::FetchResponseType::kOpaqueRedirect:
- // Opaque responses are eligible for blocking. Continue on...
- break;
- }
}
// Don't block plugin requests with universal access (e.g., Flash). Such
@@ -833,111 +587,7 @@ bool CrossSiteDocumentResourceHandler::ShouldBlockBasedOnHeaders(
return false;
}
- // We intend to block the response at this point. However, we will usually
- // sniff the contents to confirm the MIME type, to avoid blocking incorrectly
- // labeled JavaScript, JSONP, etc files.
- //
- // Note: if there is a nosniff header, it means we should honor the response
- // mime type without trying to confirm it.
- std::string nosniff_header;
- response->head.headers->GetNormalizedHeader("x-content-type-options",
- &nosniff_header);
- bool has_nosniff_header =
- base::LowerCaseEqualsASCII(nosniff_header, "nosniff");
-
- // CORB should look directly at the Content-Type header if one has been
- // received from the network. Ignoring |response->head.mime_type| helps avoid
- // breaking legitimate websites (which might happen more often when blocking
- // would be based on the mime type sniffed by MimeSniffingResourceHandler).
- //
- // TODO(nick): What if the mime type is omitted? Should that be treated the
- // same as text/plain? https://crbug.com/795971
- std::string mime_type;
- if (response->head.headers)
- response->head.headers->GetMimeType(&mime_type);
- // Canonicalize the MIME type. Note that even if it doesn't claim to be a
- // blockable type (i.e., HTML, XML, JSON, or plain text), it may still fail
- // the checks during the SniffForFetchOnlyResource() phase.
- canonical_mime_type_ =
- network::CrossOriginReadBlocking::GetCanonicalMimeType(mime_type);
-
- // If this is a partial response, sniffing is not possible, so allow the
- // response if it's not a protected mime type.
- std::string range_header;
- response->head.headers->GetNormalizedHeader("content-range", &range_header);
- if (!range_header.empty()) {
- needs_sniffing_ = false;
- switch (canonical_mime_type_) {
- case MimeType::kOthers:
- case MimeType::kPlain: // See also https://crbug.com/801709
- return false;
- case MimeType::kHtml:
- case MimeType::kJson:
- case MimeType::kXml:
- return true;
- case MimeType::kMax:
- NOTREACHED();
- return true;
- }
- }
-
- // We need to sniff unprotected mime types (e.g. for parser breakers), and
- // unless the nosniff header is set, we also need to sniff protected mime
- // types to verify that they're not mislabeled.
- needs_sniffing_ =
- (canonical_mime_type_ == MimeType::kOthers) || !has_nosniff_header;
-
- // Stylesheets shouldn't be sniffed for JSON parser breakers - see
- // https://crbug.com/809259.
- if (response->head.mime_type.empty() ||
- base::LowerCaseEqualsASCII(response->head.mime_type, "text/css")) {
- return false;
- }
-
- // Create one or more |sniffers_| to confirm that the body is actually the
- // MIME type advertised in the Content-Type header.
- if (needs_sniffing_) {
- // When the MIME type is "text/plain", create sniffers for HTML, XML and
- // JSON. If any of these sniffers match, the response will be blocked.
- const bool use_all = canonical_mime_type_ == MimeType::kPlain;
-
- // HTML sniffer.
- if (use_all || canonical_mime_type_ == MimeType::kHtml) {
- sniffers_.push_back(std::make_unique<SimpleConfirmationSniffer>(
- &network::CrossOriginReadBlocking::SniffForHTML));
- }
-
- // XML sniffer.
- if (use_all || canonical_mime_type_ == MimeType::kXml) {
- sniffers_.push_back(std::make_unique<SimpleConfirmationSniffer>(
- &network::CrossOriginReadBlocking::SniffForXML));
- }
-
- // JSON sniffer.
- if (use_all || canonical_mime_type_ == MimeType::kJson) {
- sniffers_.push_back(std::make_unique<SimpleConfirmationSniffer>(
- &network::CrossOriginReadBlocking::SniffForJSON));
- }
-
- // Parser-breaker sniffer.
- //
- // Because these prefixes are an XSSI-defeating mechanism, CORB considers
- // them distinctive enough to be worth blocking no matter the Content-Type
- // header. So this sniffer is created unconditionally.
- //
- // For MimeType::kOthers, this will be the only sniffer that's active.
- sniffers_.push_back(std::make_unique<FetchOnlyResourceSniffer>());
- }
-
return true;
}
-// static
-std::vector<std::string>
-CrossSiteDocumentResourceHandler::GetCorsSafelistedHeadersForTesting() {
- return std::vector<std::string>(
- kCorsSafelistedHeaders,
- kCorsSafelistedHeaders + arraysize(kCorsSafelistedHeaders));
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler.h b/chromium/content/browser/loader/cross_site_document_resource_handler.h
index ba0c4d4484b..447c6ed2699 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_LOADER_CROSS_SITE_DOCUMENT_RESOURCE_HANDLER_H_
#include <memory>
+#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -55,30 +56,6 @@ namespace content {
class CONTENT_EXPORT CrossSiteDocumentResourceHandler
: public LayeredResourceHandler {
public:
- class ConfirmationSniffer;
-
- // This enum backs a histogram, so do not change the order of entries or
- // remove entries. Put new entries before |kCount| and update enums.xml (see
- // the SiteIsolationResponseAction enum).
- enum class Action {
- // Logged at OnResponseStarted.
- kResponseStarted = 0,
-
- // Logged when a response is blocked without requiring sniffing.
- kBlockedWithoutSniffing = 1,
-
- // Logged when a response is blocked as a result of sniffing the content.
- kBlockedAfterSniffing = 2,
-
- // Logged when a response is allowed without requiring sniffing.
- kAllowedWithoutSniffing = 3,
-
- // Logged when a response is allowed as a result of sniffing the content.
- kAllowedAfterSniffing = 4,
-
- kCount
- };
-
CrossSiteDocumentResourceHandler(
std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request,
@@ -98,14 +75,6 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
- // Returns explicitly named headers from
- // https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name.
- //
- // Note that XSDB doesn't block responses allowed through CORS - this means
- // that the list of allowed headers below doesn't have to consider header
- // names listed in the Access-Control-Expose-Headers header.
- static std::vector<std::string> GetCorsSafelistedHeadersForTesting();
-
private:
FRIEND_TEST_ALL_PREFIXES(CrossSiteDocumentResourceHandlerTest,
ResponseBlocking);
@@ -120,7 +89,7 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
// Computes whether this response contains a cross-site document that needs to
// be blocked from the renderer process. This is a first approximation based
// on the headers, and may be revised after some of the data is sniffed.
- bool ShouldBlockBasedOnHeaders(network::ResourceResponse* response);
+ bool ShouldBlockBasedOnHeaders(const network::ResourceResponse& response);
// Once the downstream handler has allocated the buffer for OnWillRead
// (possibly after deferring), this sets up sniffing into a local buffer.
@@ -140,12 +109,8 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
ResourceType resource_type,
int http_response_code,
int64_t content_length);
- static void LogBlockedResponse(
- ResourceRequestInfoImpl* resource_request_info,
- bool needed_sniffing,
- network::CrossOriginReadBlocking::MimeType canonical_mime_type,
- int http_response_code,
- int64_t content_length);
+ void LogBlockedResponse(ResourceRequestInfoImpl* resource_request_info,
+ int http_response_code);
// WeakPtrFactory for |next_handler_|.
base::WeakPtrFactory<ResourceHandler> weak_next_handler_;
@@ -169,10 +134,9 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
// The size of |next_handler_buffer_|.
int next_handler_buffer_size_ = 0;
- // A canonicalization of the specified MIME type, to determine if blocking the
- // response is needed, as well as which type of sniffing to perform.
- network::CrossOriginReadBlocking::MimeType canonical_mime_type_ =
- network::CrossOriginReadBlocking::MimeType::kInvalid;
+ // The helper class that encapsulates the logic for deciding whether to block
+ // the response or not.
+ std::unique_ptr<network::CrossOriginReadBlocking::ResponseAnalyzer> analyzer_;
// Indicates whether this request was made by a plugin and was not using CORS.
// Such requests are exempt from blocking, while other plugin requests must be
@@ -190,12 +154,6 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
// should only be read afterwards.
bool should_block_based_on_headers_ = false;
- // Whether the response data should be sniffed before blocking it, to avoid
- // blocking mislabeled responses (e.g., JSONP labeled as HTML). This is
- // usually true when |should_block_based_on_headers_| is set, unless there is
- // a nosniff header or range request.
- bool needs_sniffing_ = false;
-
// Whether this response will be allowed through despite being flagged for
// blocking (via |should_block_based_on_headers_), because sniffing determined
// it was incorrectly labeled and might be needed for compatibility (e.g.,
@@ -210,12 +168,6 @@ class CONTENT_EXPORT CrossSiteDocumentResourceHandler
// resource request.
int http_response_code_ = 0;
- // Content length if available. -1 if not available.
- int64_t content_length_ = -1;
-
- // The sniffers to be used.
- std::vector<std::unique_ptr<ConfirmationSniffer>> sniffers_;
-
base::WeakPtrFactory<CrossSiteDocumentResourceHandler> weak_this_;
DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentResourceHandler);
diff --git a/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc b/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
index e69ddb4d243..7f66b566c8b 100644
--- a/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/cross_site_document_resource_handler_unittest.cc
@@ -208,7 +208,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
@@ -224,7 +224,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
@@ -240,7 +240,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/json", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
@@ -272,7 +272,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kAllowInitiatorOrigin, // cors_response
@@ -288,7 +288,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
"application/rss+xml", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kAllowAny, // cors_response
@@ -304,7 +304,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
"text/json", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kAllowNull, // cors_response
@@ -320,7 +320,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
@@ -336,7 +336,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
@@ -352,8 +352,8 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
- false, // include_no_sniff_header
+ MimeType::kHtml, // canonical_mime_type
+ true, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
{"<html><head>this should sniff as HTML"}, // packets
@@ -368,8 +368,8 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
- false, // include_no_sniff_header
+ MimeType::kInvalidMimeType, // canonical_mime_type
+ true, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kAllowInitiatorOrigin, // cors_response
{"<html><head>this should sniff as HTML"}, // first_chunk
@@ -384,7 +384,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kInclude, // cors_request
"application/javascript", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
true, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kAllowAny, // cors_response
@@ -628,7 +628,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
@@ -644,7 +644,7 @@ const TestScenario kScenarios[] = {
"http://www.a.com/", // initiator_origin
OriginHeader::kOmit, // cors_request
"text/html", // response_mime_type
- MimeType::kInvalid, // canonical_mime_type
+ MimeType::kInvalidMimeType, // canonical_mime_type
false, // include_no_sniff_header
false, // simulate_range_response
AccessControlAllowOriginHeader::kOmit, // cors_response
@@ -1334,7 +1334,7 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, ResponseBlocking) {
// Verify MIME type was classified correctly.
ASSERT_TRUE(document_blocker_->has_response_started_);
EXPECT_EQ(scenario.canonical_mime_type,
- document_blocker_->canonical_mime_type_);
+ document_blocker_->analyzer_->canonical_mime_type());
// Verify that we will sniff content into a different buffer if sniffing is
// needed. Note that the different buffer is used even for blocking cases
@@ -1342,7 +1342,7 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, ResponseBlocking) {
// handler doesn't look at the data in that case, but there's no way to verify
// it in the test.
bool expected_to_sniff = scenario.verdict_packet >= 0;
- ASSERT_EQ(expected_to_sniff, document_blocker_->needs_sniffing_);
+ ASSERT_EQ(expected_to_sniff, document_blocker_->analyzer_->needs_sniffing());
// Verify that we correctly decide whether to block based on headers. Note
// that this includes cases that will later be allowed after sniffing.
@@ -1518,27 +1518,27 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, ResponseBlocking) {
case MimeType::kOthers:
bucket = "Others";
break;
- case MimeType::kInvalid:
+ case MimeType::kInvalidMimeType:
DCHECK_EQ(Verdict::kAllow, scenario.verdict);
DCHECK_EQ(-1, scenario.verdict_packet);
bucket = "No blocking = no bucket";
break;
}
int start_action = static_cast<int>(
- CrossSiteDocumentResourceHandler::Action::kResponseStarted);
+ network::CrossOriginReadBlocking::Action::kResponseStarted);
int end_action = -1;
if (should_be_blocked && expected_to_sniff) {
end_action = static_cast<int>(
- CrossSiteDocumentResourceHandler::Action::kBlockedAfterSniffing);
+ network::CrossOriginReadBlocking::Action::kBlockedAfterSniffing);
} else if (should_be_blocked && !expected_to_sniff) {
end_action = static_cast<int>(
- CrossSiteDocumentResourceHandler::Action::kBlockedWithoutSniffing);
+ network::CrossOriginReadBlocking::Action::kBlockedWithoutSniffing);
} else if (!should_be_blocked && expected_to_sniff) {
end_action = static_cast<int>(
- CrossSiteDocumentResourceHandler::Action::kAllowedAfterSniffing);
+ network::CrossOriginReadBlocking::Action::kAllowedAfterSniffing);
} else if (!should_be_blocked && !expected_to_sniff) {
end_action = static_cast<int>(
- CrossSiteDocumentResourceHandler::Action::kAllowedWithoutSniffing);
+ network::CrossOriginReadBlocking::Action::kAllowedWithoutSniffing);
} else {
NOTREACHED();
}
@@ -1629,7 +1629,7 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, OnWillReadDefer) {
// it in the test.
bool expected_to_sniff =
(scenario.verdict_packet != kVerdictPacketForHeadersBasedVerdict);
- ASSERT_EQ(expected_to_sniff, document_blocker_->needs_sniffing_);
+ ASSERT_EQ(expected_to_sniff, document_blocker_->analyzer_->needs_sniffing());
// Cause the TestResourceHandler to defer when OnWillRead is called, to make
// sure the test scenarios still work when the downstream handler's buffer
@@ -1811,9 +1811,9 @@ TEST_P(CrossSiteDocumentResourceHandlerTest, MimeSnifferInterop) {
// CrossSiteDocumentResourceHandler's behavior.
ASSERT_TRUE(document_blocker_->has_response_started_);
EXPECT_EQ(scenario.canonical_mime_type,
- document_blocker_->canonical_mime_type_);
- EXPECT_EQ(expected_to_sniff, document_blocker_->needs_sniffing_);
- EXPECT_EQ(expected_to_block_based_on_headers,
+ document_blocker_->analyzer_->canonical_mime_type());
+ EXPECT_EQ(expected_to_sniff, document_blocker_->analyzer_->needs_sniffing());
+ ASSERT_EQ(expected_to_block_based_on_headers,
document_blocker_->should_block_based_on_headers_);
// Ensure that all or none of the data arrived.
diff --git a/chromium/content/browser/loader/data_pipe_to_source_stream_unittest.cc b/chromium/content/browser/loader/data_pipe_to_source_stream_unittest.cc
index aaeeb65dc69..17439b760f7 100644
--- a/chromium/content/browser/loader/data_pipe_to_source_stream_unittest.cc
+++ b/chromium/content/browser/loader/data_pipe_to_source_stream_unittest.cc
@@ -49,8 +49,8 @@ class DataPipeToSourceStreamTest
void Init(base::StringPiece message) {
message_ = message;
const MojoCreateDataPipeOptions data_pipe_options{
- sizeof(MojoCreateDataPipeOptions),
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, GetParam().pipe_capacity};
+ sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1,
+ GetParam().pipe_capacity};
mojo::ScopedDataPipeConsumerHandle consumer_end;
CHECK_EQ(MOJO_RESULT_OK,
mojo::CreateDataPipe(&data_pipe_options, &producer_end_,
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/loader_browsertest.cc
index 78188404651..450919d3c3b 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/loader_browsertest.cc
@@ -34,6 +34,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
+#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_network_delegate.h"
@@ -57,10 +58,10 @@ using testing::Not;
namespace content {
-class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
- public DownloadManager::Observer {
+class LoaderBrowserTest : public ContentBrowserTest,
+ public DownloadManager::Observer {
public:
- ResourceDispatcherHostBrowserTest() : got_downloads_(false) {}
+ LoaderBrowserTest() : got_downloads_(false) {}
protected:
void SetUpOnMainThread() override {
@@ -114,7 +115,7 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
// Test title for content created by javascript window.open().
// See http://crbug.com/5988
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DynamicTitle1) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/dynamic1.html"));
@@ -127,7 +128,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) {
// Test title for content created by javascript window.open().
// See http://crbug.com/5988
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DynamicTitle2) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/dynamic2.html"));
@@ -138,8 +139,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) {
<< "Actual title: " << title;
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- SniffHTMLWithNoContentType) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SniffHTMLWithNoContentType) {
// Covered by URLLoaderTest.SniffMimeType.
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
@@ -149,8 +149,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
"Content Sniffer Test 0");
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- RespectNoSniffDirective) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, RespectNoSniffDirective) {
// Covered by URLLoaderTest.RespectNoSniff.
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
@@ -159,8 +158,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
"mock.http/nosniff-test.html");
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- DoNotSniffHTMLFromTextPlain) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DoNotSniffHTMLFromTextPlain) {
// Covered by URLLoaderTest.DoNotSniffHTMLFromTextPlain.
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
@@ -170,8 +168,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
"mock.http/content-sniffer-test1.html");
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- DoNotSniffHTMLFromImageGIF) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DoNotSniffHTMLFromImageGIF) {
// Covered by URLLoaderTest.DoNotSniffHTMLFromImageGIF.
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
@@ -181,22 +178,20 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
"mock.http/content-sniffer-test2.html");
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- SniffNoContentTypeNoData) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SniffNoContentTypeNoData) {
// Make sure no downloads start.
BrowserContext::GetDownloadManager(
shell()->web_contents()->GetBrowserContext())
->AddObserver(this);
- CheckTitleTest(
- net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test3.html"),
- "Content Sniffer Test 3");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/content-sniffer-test3.html"));
+ CheckTitleTest(url, "Content Sniffer Test 3");
EXPECT_EQ(1u, Shell::windows().size());
ASSERT_FALSE(got_downloads());
}
// Make sure file URLs are not sniffed as HTML when they don't end in HTML.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- DoNotSniffHTMLFromFileUrl) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DoNotSniffHTMLFromFileUrl) {
base::FilePath path =
GetTestFilePath(nullptr, "content-sniffer-test5.not-html");
GURL file_url = net::FilePathToFileURL(path);
@@ -205,22 +200,20 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
CheckTitleTest(file_url, path.BaseName().MaybeAsASCII());
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- ContentDispositionEmpty) {
- CheckTitleTest(
- net::URLRequestMockHTTPJob::GetMockUrl("content-disposition-empty.html"),
- "success");
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, ContentDispositionEmpty) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/content-disposition-empty.html"));
+ CheckTitleTest(url, "success");
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- ContentDispositionInline) {
- CheckTitleTest(
- net::URLRequestMockHTTPJob::GetMockUrl("content-disposition-inline.html"),
- "success");
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, ContentDispositionInline) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/content-disposition-inline.html"));
+ CheckTitleTest(url, "success");
}
// Test for bug #1091358.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SyncXMLHttpRequest) {
ASSERT_TRUE(embedded_test_server()->Start());
NavigateToURL(shell(),
embedded_test_server()->GetURL("/sync_xmlhttprequest.html"));
@@ -234,8 +227,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, SyncXMLHttpRequest) {
}
// If this flakes, use http://crbug.com/62776.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- SyncXMLHttpRequest_Disallowed) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SyncXMLHttpRequest_Disallowed) {
ASSERT_TRUE(embedded_test_server()->Start());
NavigateToURL(shell(), embedded_test_server()->GetURL(
"/sync_xmlhttprequest_disallowed.html"));
@@ -257,7 +249,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
#else
#define MAYBE_SyncXMLHttpRequest_DuringUnload SyncXMLHttpRequest_DuringUnload
#endif
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
MAYBE_SyncXMLHttpRequest_DuringUnload) {
ASSERT_TRUE(embedded_test_server()->Start());
BrowserContext::GetDownloadManager(
@@ -278,8 +270,9 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
namespace {
-// Responses with a HungResponse for the specified URL to hang on the request,
-// and cancells all requests from specifield |child_id|.
+// Responds with a HungResponse for the specified URL to hang on the request.
+// If the network service is enabled, crashes the process. If it's disabled,
+// cancels all requests from specifield |child_id|.
std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
const std::string& relative_url,
int child_id,
@@ -287,11 +280,17 @@ std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
if (request.relative_url != relative_url)
return nullptr;
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ResourceDispatcherHostImpl::CancelRequestsForProcess,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- child_id));
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce(SimulateNetworkServiceCrash));
+ } else {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&ResourceDispatcherHostImpl::CancelRequestsForProcess,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ child_id));
+ }
return std::make_unique<net::test_server::HungResponse>();
}
@@ -301,8 +300,7 @@ std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
// Tests the case where the request is cancelled by a layer above the
// URLRequest, which passes the error on ResourceLoader teardown, rather than in
// response to call to AsyncResourceHandler::OnResponseComplete.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- SyncXMLHttpRequest_Cancelled) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SyncXMLHttpRequest_Cancelled) {
embedded_test_server()->RegisterRequestHandler(base::Bind(
&CancelOnRequest, "/hung",
shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
@@ -324,8 +322,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// Flaky everywhere. http://crbug.com/130404
// Tests that onunload is run for cross-site requests. (Bug 1114994)
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- DISABLED_CrossSiteOnunloadCookie) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DISABLED_CrossSiteOnunloadCookie) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/onunload_cookie.html");
@@ -344,7 +341,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// If this flakes, use http://crbug.com/130404
// Tests that onunload is run for cross-site requests to URLs that complete
// without network loads (e.g., about:blank, data URLs).
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
DISABLED_CrossSiteImmediateLoadOnunloadCookie) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -379,8 +376,7 @@ std::unique_ptr<net::test_server::HttpResponse> NoContentResponseHandler(
// Tests that the unload handler is not run for 204 responses.
// If this flakes use http://crbug.com/80596.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- CrossSiteNoUnloadOn204) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, CrossSiteNoUnloadOn204) {
const char kNoContentPath[] = "/nocontent";
embedded_test_server()->RegisterRequestHandler(
base::Bind(&NoContentResponseHandler, kNoContentPath));
@@ -411,8 +407,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
#else
#define MAYBE_CrossSiteAfterCrash CrossSiteAfterCrash
#endif
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- MAYBE_CrossSiteAfterCrash) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, MAYBE_CrossSiteAfterCrash) {
// Make sure we have a live process before trying to kill it.
NavigateToURL(shell(), GURL("about:blank"));
@@ -426,31 +421,30 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// Navigate to a new cross-site page. The browser should not wait around for
// the old renderer's on{before}unload handlers to run.
- CheckTitleTest(
- net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test0.html"),
- "Content Sniffer Test 0");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(embedded_test_server()->GetURL("/content-sniffer-test0.html"));
+ CheckTitleTest(url, "Content Sniffer Test 0");
}
// Tests that cross-site navigations work when the new page does not go through
// the BufferedEventHandler (e.g., non-http{s} URLs). (Bug 1225872)
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- CrossSiteNavigationNonBuffered) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, CrossSiteNavigationNonBuffered) {
// Start with an HTTP page.
- CheckTitleTest(
- net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test0.html"),
- "Content Sniffer Test 0");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url1(embedded_test_server()->GetURL("/content-sniffer-test0.html"));
+ CheckTitleTest(url1, "Content Sniffer Test 0");
// Now load a file:// page, which does not use the BufferedEventHandler.
// Make sure that the page loads and displays a title, and doesn't get stuck.
- GURL url = GetTestUrl("", "title2.html");
- CheckTitleTest(url, "Title Of Awesomeness");
+ GURL url2 = GetTestUrl("", "title2.html");
+ CheckTitleTest(url2, "Title Of Awesomeness");
}
// Flaky everywhere. http://crbug.com/130404
// Tests that a cross-site navigation to an error page (resulting in the link
// doctor page) still runs the onunload handler and can support navigations
// away from the link doctor page. (Bug 1235537)
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
DISABLED_CrossSiteNavigationErrorPage) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -492,8 +486,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- CrossSiteNavigationErrorPage2) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, CrossSiteNavigationErrorPage2) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/title2.html"));
@@ -516,25 +509,30 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
shell()->web_contents()->GetTitle());
}
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- CrossOriginRedirectBlocked) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, CrossOriginRedirectBlocked) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url(
+ embedded_test_server()->GetURL("/cross-origin-redirect-blocked.html"));
// We expect the following URL requests from this test:
- // 1- http://mock.http/cross-origin-redirect-blocked.html
- // 2- http://mock.http/redirect-to-title2.html
- // 3- http://mock.http/title2.html
+ // 1- navigation to http://127.0.0.1:[port]/cross-origin-redirect-blocked.html
+ // 2- XHR to
+ // http://127.0.0.1:[port]/server-redirect-302?http://a.com:[port]/title2.html
+ // 3- above XHR is redirected to http://a.com:[port]/title2.html which should
+ // be blocked
+ // 4- When the page notices the above request is blocked, it issues an XHR to
+ // http://127.0.0.1:[port]/title2.html
+ // 5- When the above XHR succeed, the page navigates to
+ // http://127.0.0.1:[port]/title3.html
//
- // If the redirect in #2 were not blocked, we'd also see a request
- // for http://mock.http:4000/title2.html, and the title would be different.
- CheckTitleTest(net::URLRequestMockHTTPJob::GetMockUrl(
- "cross-origin-redirect-blocked.html"),
- "Title Of More Awesomeness");
+ // If the redirect in #3 were not blocked, we'd instead see a navigation
+ // to http://a.com[port]/title2.html, and the title would be different.
+ CheckTitleTest(url, "Title Of More Awesomeness");
}
// Tests that ResourceRequestInfoImpl is updated correctly on failed
// requests, to prevent calling Read on a request that has already failed.
// See bug 40250.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- CrossSiteFailedRequest) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, CrossSiteFailedRequest) {
// Visit another URL first to trigger a cross-site navigation.
NavigateToURL(shell(), GetTestUrl("", "simple_page.html"));
@@ -564,7 +562,7 @@ std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
// Test that we update the cookie policy URLs correctly when transferring
// navigations.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, CookiePolicy) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, CookiePolicy) {
embedded_test_server()->RegisterRequestHandler(
base::Bind(&HandleRedirectRequest, "/redirect?"));
ASSERT_TRUE(embedded_test_server()->Start());
@@ -607,8 +605,7 @@ class PageTransitionResourceDispatcherHostDelegate
// Test that ui::PAGE_TRANSITION_CLIENT_REDIRECT is correctly set
// when encountering a meta refresh tag.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- PageTransitionClientRedirect) {
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, PageTransitionClientRedirect) {
// TODO(crbug.com/818445): Fix the flakiness on Network Service.
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
@@ -723,10 +720,9 @@ class PreviewsStateResourceDispatcherHostDelegate
} // namespace
-class PreviewsStateResourceDispatcherHostBrowserTest
- : public ContentBrowserTest {
+class PreviewsStateBrowserTest : public ContentBrowserTest {
public:
- ~PreviewsStateResourceDispatcherHostBrowserTest() override {}
+ ~PreviewsStateBrowserTest() override {}
protected:
void SetUpOnMainThread() override {
@@ -767,8 +763,7 @@ class PreviewsStateResourceDispatcherHostBrowserTest
};
// Test that navigating calls GetPreviewsState with SERVER_LOFI_ON.
-IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
- ShouldEnableLoFiModeOn) {
+IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest, ShouldEnableLoFiModeOn) {
// Navigate with ShouldEnableLoFiMode returning true.
Reset(SERVER_LOFI_ON);
NavigateToURLBlockUntilNavigationsComplete(
@@ -777,8 +772,7 @@ IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
}
// Test that navigating calls GetPreviewsState returning PREVIEWS_OFF.
-IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
- ShouldEnableLoFiModeOff) {
+IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest, ShouldEnableLoFiModeOff) {
// Navigate with GetPreviewsState returning false.
NavigateToURLBlockUntilNavigationsComplete(
shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
@@ -787,8 +781,7 @@ IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
// Test that reloading calls GetPreviewsState again and changes the Previews
// state.
-IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
- ShouldEnableLoFiModeReload) {
+IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest, ShouldEnableLoFiModeReload) {
// Navigate with GetPreviewsState returning PREVIEWS_OFF.
NavigateToURLBlockUntilNavigationsComplete(
shell(), embedded_test_server()->GetURL("/page_with_iframe.html"), 1);
@@ -802,7 +795,7 @@ IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
// Test that navigating backwards calls GetPreviewsState again and changes
// the Previews state.
-IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
+IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest,
ShouldEnableLoFiModeNavigateBackThenForward) {
// Navigate with GetPreviewsState returning false.
NavigateToURLBlockUntilNavigationsComplete(
@@ -822,7 +815,7 @@ IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
// Test that reloading with Lo-Fi disabled doesn't call ShouldEnableLoFiMode and
// already has LOFI_OFF.
-IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
+IN_PROC_BROWSER_TEST_F(PreviewsStateBrowserTest,
ShouldEnableLoFiModeReloadDisableLoFi) {
// Navigate with GetPreviewsState returning SERVER_LOFI_ON.
Reset(SERVER_LOFI_ON);
@@ -841,18 +834,18 @@ IN_PROC_BROWSER_TEST_F(PreviewsStateResourceDispatcherHostBrowserTest,
namespace {
-struct RequestDataForDelegate {
+struct RequestData {
const GURL url;
const GURL first_party;
const base::Optional<url::Origin> initiator;
const int load_flags;
const std::string referrer;
- RequestDataForDelegate(const GURL& url,
- const GURL& first_party,
- const base::Optional<url::Origin>& initiator,
- int load_flags,
- const std::string& referrer)
+ RequestData(const GURL& url,
+ const GURL& first_party,
+ const base::Optional<url::Origin>& initiator,
+ int load_flags,
+ const std::string& referrer)
: url(url),
first_party(first_party),
initiator(initiator),
@@ -860,102 +853,91 @@ struct RequestDataForDelegate {
referrer(referrer) {}
};
-// Captures calls to 'RequestBeginning' and records the URL, first-party for
-// cookies, initiator, load flags, and referrer.
-class RequestDataResourceDispatcherHostDelegate
- : public ResourceDispatcherHostDelegate {
- public:
- RequestDataResourceDispatcherHostDelegate() {}
-
- const std::vector<std::unique_ptr<RequestDataForDelegate>>& data() {
- return requests_;
- }
-
- // ResourceDispatcherHostDelegate implementation:
- void RequestBeginning(
- net::URLRequest* request,
- ResourceContext* resource_context,
- AppCacheService* appcache_service,
- ResourceType resource_type,
- std::vector<std::unique_ptr<ResourceThrottle>>* throttles) override {
- requests_.push_back(std::make_unique<RequestDataForDelegate>(
- request->url(), request->site_for_cookies(), request->initiator(),
- request->load_flags(), request->referrer()));
- }
-
- void SetDelegate() { ResourceDispatcherHost::Get()->SetDelegate(this); }
-
- private:
- std::vector<std::unique_ptr<RequestDataForDelegate>> requests_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestDataResourceDispatcherHostDelegate);
-};
-
const GURL kURLWithUniqueOrigin("data:,");
} // namespace
-class RequestDataResourceDispatcherHostBrowserTest : public ContentBrowserTest {
+class RequestDataBrowserTest : public ContentBrowserTest {
public:
- ~RequestDataResourceDispatcherHostBrowserTest() override {}
+ RequestDataBrowserTest()
+ : interceptor_(std::make_unique<content::URLLoaderInterceptor>(
+ base::BindRepeating(&RequestDataBrowserTest::OnRequest,
+ base::Unretained(this)))) {}
+ ~RequestDataBrowserTest() override {}
+
+ std::vector<RequestData> data() {
+ base::AutoLock auto_lock(requests_lock_);
+ auto copy = requests_;
+ return copy;
+ }
- protected:
+ private:
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
ASSERT_TRUE(embedded_test_server()->Start());
- delegate_.reset(new RequestDataResourceDispatcherHostDelegate());
-
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&RequestDataResourceDispatcherHostDelegate::SetDelegate,
- base::Unretained(delegate_.get())));
host_resolver()->AddRule("*", "127.0.0.1");
}
- protected:
- std::unique_ptr<RequestDataResourceDispatcherHostDelegate> delegate_;
+ void TearDownOnMainThread() override { interceptor_.reset(); }
+
+ bool OnRequest(URLLoaderInterceptor::RequestParams* params) {
+ RequestCreated(RequestData(
+ params->url_request.url, params->url_request.site_for_cookies,
+ params->url_request.request_initiator, params->url_request.load_flags,
+ params->url_request.referrer.spec()));
+ return false;
+ }
+
+ void RequestCreated(RequestData data) {
+ base::AutoLock auto_lock(requests_lock_);
+ requests_.push_back(data);
+ }
+
+ base::Lock requests_lock_;
+ std::vector<RequestData> requests_;
+ std::unique_ptr<URLLoaderInterceptor> interceptor_;
};
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest, Basic) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, Basic) {
GURL top_url(embedded_test_server()->GetURL("/page_with_subresources.html"));
url::Origin top_origin = url::Origin::Create(top_url);
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
- EXPECT_EQ(8u, delegate_->data().size());
+ auto requests = data();
+ EXPECT_EQ(8u, requests.size());
// All resources loaded directly by the top-level document should have a
// |first_party| and |initiator| that match the URL of the top-level document.
// The top-level document itself doesn't have an |initiator|.
- const RequestDataForDelegate* first_request = delegate_->data()[0].get();
+ const RequestData* first_request = &requests[0];
EXPECT_EQ(top_url, first_request->first_party);
EXPECT_FALSE(first_request->initiator.has_value());
- for (size_t i = 1; i < delegate_->data().size(); i++) {
- const RequestDataForDelegate* request = delegate_->data()[i].get();
+ for (size_t i = 1; i < requests.size(); i++) {
+ const RequestData* request = &requests[i];
EXPECT_EQ(top_url, request->first_party);
ASSERT_TRUE(request->initiator.has_value());
EXPECT_EQ(top_origin, request->initiator);
}
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- LinkRelPrefetch) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, LinkRelPrefetch) {
GURL top_url(embedded_test_server()->GetURL("/link_rel_prefetch.html"));
url::Origin top_origin = url::Origin::Create(top_url);
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
- EXPECT_EQ(2u, delegate_->data().size());
- auto* request = delegate_->data()[1].get();
+ auto requests = data();
+ EXPECT_EQ(2u, requests.size());
+ auto* request = &requests[1];
EXPECT_EQ(top_origin, request->initiator);
EXPECT_EQ(top_url, request->referrer);
EXPECT_TRUE(request->load_flags & net::LOAD_PREFETCH);
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- LinkRelPrefetchReferrerPolicy) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, LinkRelPrefetchReferrerPolicy) {
GURL top_url(embedded_test_server()->GetURL(
"/link_rel_prefetch_referrer_policy.html"));
GURL img_url(embedded_test_server()->GetURL("/image.jpg"));
@@ -963,9 +945,10 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
- EXPECT_EQ(2u, delegate_->data().size());
- auto* main_frame_request = delegate_->data()[0].get();
- auto* image_request = delegate_->data()[1].get();
+ auto requests = data();
+ EXPECT_EQ(2u, requests.size());
+ auto* main_frame_request = &requests[0];
+ auto* image_request = &requests[1];
// Check the main frame request.
EXPECT_EQ(top_url, main_frame_request->url);
@@ -980,8 +963,7 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
EXPECT_TRUE(image_request->load_flags & net::LOAD_PREFETCH);
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- BasicCrossSite) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, BasicCrossSite) {
GURL top_url(embedded_test_server()->GetURL(
"a.com", "/nested_page_with_subresources.html"));
GURL nested_url(embedded_test_server()->GetURL(
@@ -991,32 +973,32 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
- EXPECT_EQ(9u, delegate_->data().size());
+ auto requests = data();
+ EXPECT_EQ(9u, requests.size());
// The first items loaded are the top-level and nested documents. These should
// both have a |first_party| that match the URL of the top-level document.
// The top-level document has no initiator and the nested frame is initiated
// by the top-level document.
- EXPECT_EQ(top_url, delegate_->data()[0]->url);
- EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
- EXPECT_FALSE(delegate_->data()[0]->initiator.has_value());
+ EXPECT_EQ(top_url, requests[0].url);
+ EXPECT_EQ(top_url, requests[0].first_party);
+ EXPECT_FALSE(requests[0].initiator.has_value());
- EXPECT_EQ(nested_url, delegate_->data()[1]->url);
- EXPECT_EQ(top_url, delegate_->data()[1]->first_party);
- EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+ EXPECT_EQ(nested_url, requests[1].url);
+ EXPECT_EQ(top_url, requests[1].first_party);
+ EXPECT_EQ(top_origin, requests[1].initiator);
// The remaining items are loaded as subresources in the nested document, and
// should have a unique first-party, and an initiator that matches the
// document in which they're embedded.
- for (size_t i = 2; i < delegate_->data().size(); i++) {
- SCOPED_TRACE(delegate_->data()[i]->url);
- EXPECT_EQ(kURLWithUniqueOrigin, delegate_->data()[i]->first_party);
- EXPECT_EQ(nested_origin, delegate_->data()[i]->initiator);
+ for (size_t i = 2; i < requests.size(); i++) {
+ SCOPED_TRACE(requests[i].url);
+ EXPECT_EQ(kURLWithUniqueOrigin, requests[i].first_party);
+ EXPECT_EQ(nested_origin, requests[i].initiator);
}
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- SameOriginNested) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, SameOriginNested) {
GURL top_url(embedded_test_server()->GetURL("/page_with_iframe.html"));
GURL image_url(embedded_test_server()->GetURL("/image.jpg"));
GURL nested_url(embedded_test_server()->GetURL("/title1.html"));
@@ -1024,30 +1006,30 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
- EXPECT_EQ(3u, delegate_->data().size());
+ auto requests = data();
+ EXPECT_EQ(3u, requests.size());
// User-initiated top-level navigations have a first-party that matches the
// URL to which they navigate. The navigation was initiated outside of a
// document, so there is no |initiator|.
- EXPECT_EQ(top_url, delegate_->data()[0]->url);
- EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
- EXPECT_FALSE(delegate_->data()[0]->initiator.has_value());
+ EXPECT_EQ(top_url, requests[0].url);
+ EXPECT_EQ(top_url, requests[0].first_party);
+ EXPECT_FALSE(requests[0].initiator.has_value());
// Subresource requests have a first-party and initiator that matches the
// document in which they're embedded.
- EXPECT_EQ(image_url, delegate_->data()[1]->url);
- EXPECT_EQ(top_url, delegate_->data()[1]->first_party);
- EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+ EXPECT_EQ(image_url, requests[1].url);
+ EXPECT_EQ(top_url, requests[1].first_party);
+ EXPECT_EQ(top_origin, requests[1].initiator);
// Same-origin nested frames have a first-party and initiator that matches
// the document in which they're embedded.
- EXPECT_EQ(nested_url, delegate_->data()[2]->url);
- EXPECT_EQ(top_url, delegate_->data()[2]->first_party);
- EXPECT_EQ(top_origin, delegate_->data()[2]->initiator);
+ EXPECT_EQ(nested_url, requests[2].url);
+ EXPECT_EQ(top_url, requests[2].first_party);
+ EXPECT_EQ(top_origin, requests[2].initiator);
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- SameOriginAuxiliary) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, SameOriginAuxiliary) {
GURL top_url(embedded_test_server()->GetURL("/simple_links.html"));
GURL auxiliary_url(embedded_test_server()->GetURL("/title2.html"));
url::Origin top_origin = url::Origin::Create(top_url);
@@ -1064,24 +1046,24 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
Shell* new_shell = new_shell_observer.GetShell();
WaitForLoadStop(new_shell->web_contents());
- EXPECT_EQ(2u, delegate_->data().size());
+ auto requests = data();
+ EXPECT_EQ(2u, requests.size());
// User-initiated top-level navigations have a first-party that matches the
// URL to which they navigate, even if they fail to load. The navigation was
// initiated outside of a document, so there is no |initiator|.
- EXPECT_EQ(top_url, delegate_->data()[0]->url);
- EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
- EXPECT_FALSE(delegate_->data()[0]->initiator.has_value());
+ EXPECT_EQ(top_url, requests[0].url);
+ EXPECT_EQ(top_url, requests[0].first_party);
+ EXPECT_FALSE(requests[0].initiator.has_value());
// Auxiliary navigations have a first-party that matches the URL to which they
// navigate, and an initiator that matches the document that triggered them.
- EXPECT_EQ(auxiliary_url, delegate_->data()[1]->url);
- EXPECT_EQ(auxiliary_url, delegate_->data()[1]->first_party);
- EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+ EXPECT_EQ(auxiliary_url, requests[1].url);
+ EXPECT_EQ(auxiliary_url, requests[1].first_party);
+ EXPECT_EQ(top_origin, requests[1].initiator);
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- CrossOriginAuxiliary) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, CrossOriginAuxiliary) {
GURL top_url(embedded_test_server()->GetURL("/simple_links.html"));
GURL auxiliary_url(embedded_test_server()->GetURL("foo.com", "/title2.html"));
url::Origin top_origin = url::Origin::Create(top_url);
@@ -1106,24 +1088,24 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
Shell* new_shell = new_shell_observer.GetShell();
WaitForLoadStop(new_shell->web_contents());
- EXPECT_EQ(2u, delegate_->data().size());
+ auto requests = data();
+ EXPECT_EQ(2u, requests.size());
// User-initiated top-level navigations have a first-party that matches the
// URL to which they navigate, even if they fail to load. The navigation was
// initiated outside of a document, so there is no initiator.
- EXPECT_EQ(top_url, delegate_->data()[0]->url);
- EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
- EXPECT_FALSE(delegate_->data()[0]->initiator.has_value());
+ EXPECT_EQ(top_url, requests[0].url);
+ EXPECT_EQ(top_url, requests[0].first_party);
+ EXPECT_FALSE(requests[0].initiator.has_value());
// Auxiliary navigations have a first-party that matches the URL to which they
// navigate, and an initiator that matches the document that triggered them.
- EXPECT_EQ(auxiliary_url, delegate_->data()[1]->url);
- EXPECT_EQ(auxiliary_url, delegate_->data()[1]->first_party);
- EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+ EXPECT_EQ(auxiliary_url, requests[1].url);
+ EXPECT_EQ(auxiliary_url, requests[1].first_party);
+ EXPECT_EQ(top_origin, requests[1].initiator);
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- FailedNavigation) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, FailedNavigation) {
// Navigating to this URL will fail, as we haven't taught the host resolver
// about 'a.com'.
GURL top_url(embedded_test_server()->GetURL("a.com", "/simple_page.html"));
@@ -1131,18 +1113,18 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
- EXPECT_EQ(1u, delegate_->data().size());
+ auto requests = data();
+ EXPECT_EQ(1u, requests.size());
// User-initiated top-level navigations have a first-party that matches the
// URL to which they navigate, even if they fail to load. The navigation was
// initiated outside of a document, so there is no initiator.
- EXPECT_EQ(top_url, delegate_->data()[0]->url);
- EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
- EXPECT_FALSE(delegate_->data()[0]->initiator.has_value());
+ EXPECT_EQ(top_url, requests[0].url);
+ EXPECT_EQ(top_url, requests[0].first_party);
+ EXPECT_FALSE(requests[0].initiator.has_value());
}
-IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
- CrossOriginNested) {
+IN_PROC_BROWSER_TEST_F(RequestDataBrowserTest, CrossOriginNested) {
GURL top_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
GURL top_js_url(
@@ -1156,34 +1138,35 @@ IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
- EXPECT_EQ(4u, delegate_->data().size());
+ auto requests = data();
+ EXPECT_EQ(4u, requests.size());
// User-initiated top-level navigations have a |first-party|. The navigation
// was initiated outside of a document, so there are no initiator.
- EXPECT_EQ(top_url, delegate_->data()[0]->url);
- EXPECT_EQ(top_url, delegate_->data()[0]->first_party);
- EXPECT_FALSE(delegate_->data()[0]->initiator.has_value());
+ EXPECT_EQ(top_url, requests[0].url);
+ EXPECT_EQ(top_url, requests[0].first_party);
+ EXPECT_FALSE(requests[0].initiator.has_value());
- EXPECT_EQ(top_js_url, delegate_->data()[1]->url);
- EXPECT_EQ(top_url, delegate_->data()[1]->first_party);
- EXPECT_EQ(top_origin, delegate_->data()[1]->initiator);
+ EXPECT_EQ(top_js_url, requests[1].url);
+ EXPECT_EQ(top_url, requests[1].first_party);
+ EXPECT_EQ(top_origin, requests[1].initiator);
// Cross-origin frames have a first-party and initiator that matches the URL
// in which they're embedded.
- EXPECT_EQ(nested_url, delegate_->data()[2]->url);
- EXPECT_EQ(top_url, delegate_->data()[2]->first_party);
- EXPECT_EQ(top_origin, delegate_->data()[2]->initiator);
+ EXPECT_EQ(nested_url, requests[2].url);
+ EXPECT_EQ(top_url, requests[2].first_party);
+ EXPECT_EQ(top_origin, requests[2].initiator);
// Cross-origin subresource requests have a unique first-party, and an
// initiator that matches the document in which they're embedded.
- EXPECT_EQ(nested_js_url, delegate_->data()[3]->url);
- EXPECT_EQ(kURLWithUniqueOrigin, delegate_->data()[3]->first_party);
- EXPECT_EQ(nested_origin, delegate_->data()[3]->initiator);
+ EXPECT_EQ(nested_js_url, requests[3].url);
+ EXPECT_EQ(kURLWithUniqueOrigin, requests[3].first_party);
+ EXPECT_EQ(nested_origin, requests[3].initiator);
}
// Regression test for https://crbug.com/648608. An attacker could trivially
// bypass cookies SameSite=Strict protections by navigating a new window twice.
-IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
CookieSameSiteStrictOpenNewNamedWindowTwice) {
ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
index 577f62b57ff..bed70acf54d 100644
--- a/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_sniffing_resource_handler.cc
@@ -23,6 +23,7 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/stream_resource_handler.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/browser/web_package/web_package_request_handler.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/plugin_service.h"
@@ -41,6 +42,7 @@
#include "services/network/loader_util.h"
#include "services/network/public/cpp/resource_response.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
#include "url/origin.h"
namespace content {
@@ -457,11 +459,10 @@ bool MimeSniffingResourceHandler::MaybeStartInterception() {
if (!must_download) {
if (blink::IsSupportedMimeType(mime_type))
return true;
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange) &&
- WebPackageRequestHandler::IsSupportedMimeType(mime_type)) {
+ if (signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(
+ request()->url(), response_->head)) {
return true;
}
-
bool handled_by_plugin;
if (!CheckForPluginHandler(&handled_by_plugin))
return false;
@@ -557,23 +558,11 @@ bool MimeSniffingResourceHandler::MustDownload() {
must_download_is_set_ = true;
- bool is_cross_origin =
- (request()->initiator().has_value() &&
- !request()->url_chain().back().SchemeIsBlob() &&
- !request()->url_chain().back().SchemeIsFileSystem() &&
- !request()->url_chain().back().SchemeIs(url::kAboutScheme) &&
- !request()->url_chain().back().SchemeIs(url::kDataScheme) &&
- request()->initiator()->GetURL() !=
- request()->url_chain().back().GetOrigin());
-
std::string disposition;
request()->GetResponseHeaderByName("content-disposition", &disposition);
if (!disposition.empty() &&
net::HttpContentDisposition(disposition, std::string()).is_attachment()) {
must_download_ = true;
- } else if (GetRequestInfo()->suggested_filename().has_value() &&
- !is_cross_origin) {
- must_download_ = true;
} else if (GetContentClient()->browser()->ShouldForceDownloadResource(
request()->url(), response_->head.mime_type)) {
must_download_ = true;
@@ -592,11 +581,6 @@ bool MimeSniffingResourceHandler::MustDownload() {
must_download_ = false;
}
- if (GetRequestInfo()->suggested_filename().has_value() && !must_download_) {
- download::RecordDownloadCount(
- download::CROSS_ORIGIN_DOWNLOAD_WITHOUT_CONTENT_DISPOSITION);
- }
-
return must_download_;
}
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.cc b/chromium/content/browser/loader/mojo_async_resource_handler.cc
index 601641fd9f0..08d0708f93c 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.cc
@@ -12,9 +12,9 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "content/browser/loader/downloaded_temp_file_impl.h"
-#include "content/browser/loader/navigation_metrics.h"
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
@@ -40,9 +40,24 @@ constexpr size_t kMinAllocationSize = 2 * net::kMaxBytesToSniff;
constexpr size_t kMaxChunkSize = 32 * 1024;
-void NotReached(network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client) {
- NOTREACHED();
+// Records histograms for the time spent between several events in the
+// MojoAsyncResourceHandler for a navigation.
+// - |response_started| is when the response's headers and metadata are
+// available. Loading is paused at this time.
+// - |proceed_with_response| is when loading is resumed.
+// - |first_read_completed| is when the first part of the body has been read.
+void RecordNavigationResourceHandlerMetrics(
+ base::TimeTicks response_started,
+ base::TimeTicks proceed_with_response,
+ base::TimeTicks first_read_completed) {
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.ResourceHandler."
+ "ResponseStartedUntilProceedWithResponse",
+ proceed_with_response - response_started);
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.ResourceHandler."
+ "ProceedWithResponseUntilFirstReadCompleted",
+ first_read_completed - proceed_with_response);
}
} // namespace
@@ -120,13 +135,6 @@ MojoAsyncResourceHandler::MojoAsyncResourceHandler(
// the callback will never be called after |this| is destroyed.
binding_.set_connection_error_with_reason_handler(base::BindOnce(
&MojoAsyncResourceHandler::Cancel, base::Unretained(this)));
-
- if (IsResourceTypeFrame(resource_type)) {
- GetRequestInfo()->set_on_transfer(base::Bind(
- &MojoAsyncResourceHandler::OnTransfer, weak_factory_.GetWeakPtr()));
- } else {
- GetRequestInfo()->set_on_transfer(base::Bind(&NotReached));
- }
}
MojoAsyncResourceHandler::~MojoAsyncResourceHandler() {
@@ -256,7 +264,7 @@ void MojoAsyncResourceHandler::OnWillRead(
first_call = true;
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
- options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
options.element_num_bytes = 1;
options.capacity_num_bytes = g_allocation_size;
mojo::ScopedDataPipeProducerHandle producer;
@@ -381,7 +389,11 @@ void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
CalculateRecentlyReceivedBytes());
}
-void MojoAsyncResourceHandler::FollowRedirect() {
+void MojoAsyncResourceHandler::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
+ "headers was not supported "
+ "yet. crbug.com/845683";
if (!request()->status().is_success()) {
DVLOG(1) << "FollowRedirect for invalid request";
return;
@@ -492,6 +504,20 @@ void MojoAsyncResourceHandler::OnResponseCompleted(
net::NetErrorDetails details;
request()->PopulateNetErrorDetails(&details);
loader_status.extended_error_code = details.quic_connection_error;
+ } else if (error_code == net::ERR_BLOCKED_BY_CLIENT ||
+ error_code == net::ERR_BLOCKED_BY_RESPONSE) {
+ ResourceRequestInfoImpl* resource_request_info =
+ ResourceRequestInfoImpl::ForRequest(request());
+ auto maybe_reason =
+ resource_request_info->GetResourceRequestBlockedReason();
+ // Ideally, every blocked by client / blocked by response error
+ // would be annotated with a blocked reason, but we can't guarantee it
+ // here, so sometimes we won't populate extended_error_code which
+ // corresonds ResourceRequestBlockedReason::kOther.
+ if (maybe_reason) {
+ loader_status.extended_error_code =
+ static_cast<int>(maybe_reason.value());
+ }
}
loader_status.exists_in_cache = request()->response_info().was_cached;
loader_status.completion_time = base::TimeTicks::Now();
@@ -637,16 +663,6 @@ MojoAsyncResourceHandler::CreateUploadProgressTracker(
from_here, std::move(callback), request());
}
-void MojoAsyncResourceHandler::OnTransfer(
- network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client) {
- binding_.Unbind();
- binding_.Bind(std::move(mojo_request));
- binding_.set_connection_error_with_reason_handler(base::BindOnce(
- &MojoAsyncResourceHandler::Cancel, base::Unretained(this)));
- url_loader_client_ = std::move(url_loader_client);
-}
-
void MojoAsyncResourceHandler::SendUploadProgress(
const net::UploadProgress& progress) {
url_loader_client_->OnUploadProgress(
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler.h b/chromium/content/browser/loader/mojo_async_resource_handler.h
index 029ea5d1472..c612b2f72e2 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler.h
+++ b/chromium/content/browser/loader/mojo_async_resource_handler.h
@@ -85,7 +85,8 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
void OnDataDownloaded(int bytes_downloaded) override;
// network::mojom::URLLoader implementation:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
@@ -130,8 +131,6 @@ class CONTENT_EXPORT MojoAsyncResourceHandler
const base::Location& from_here,
network::UploadProgressTracker::UploadProgressReportCallback callback);
- void OnTransfer(network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client);
void SendUploadProgress(const net::UploadProgress& progress);
void OnUploadProgressACK();
static void InitializeResourceBufferConstants();
diff --git a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
index b71fba4bfb3..f6ca9da8125 100644
--- a/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -105,14 +105,6 @@ class TestResourceDispatcherHostDelegate final
TestResourceDispatcherHostDelegate() = default;
~TestResourceDispatcherHostDelegate() override = default;
- bool ShouldBeginRequest(const std::string& method,
- const GURL& url,
- ResourceType resource_type,
- ResourceContext* resource_context) override {
- ADD_FAILURE() << "ShouldBeginRequest should not be called.";
- return false;
- }
-
void RequestBeginning(
net::URLRequest* request,
ResourceContext* resource_context,
@@ -1219,7 +1211,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
mock_loader_->status());
- handler_->FollowRedirect();
+ handler_->FollowRedirect(base::nullopt);
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
url_loader_client_.ClearHasReceivedRedirect();
@@ -1240,7 +1232,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
ASSERT_EQ(MockResourceLoader::Status::CALLBACK_PENDING,
mock_loader_->status());
- handler_->FollowRedirect();
+ handler_->FollowRedirect(base::nullopt);
ASSERT_EQ(MockResourceLoader::Status::IDLE, mock_loader_->status());
// Give the final response.
@@ -1264,7 +1256,7 @@ TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest, RedirectHandling) {
// redirect, despite the fact that no redirect has been received yet.
TEST_P(MojoAsyncResourceHandlerWithAllocationSizeTest,
MalformedFollowRedirectRequest) {
- handler_->FollowRedirect();
+ handler_->FollowRedirect(base::nullopt);
EXPECT_TRUE(handler_->has_received_bad_message());
}
diff --git a/chromium/content/browser/loader/navigation_loader_util.cc b/chromium/content/browser/loader/navigation_loader_util.cc
new file mode 100644
index 00000000000..96a7879b520
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_loader_util.cc
@@ -0,0 +1,58 @@
+// 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/loader/navigation_loader_util.h"
+
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+#include "net/http/http_content_disposition.h"
+#include "net/http/http_response_headers.h"
+#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+namespace navigation_loader_util {
+
+bool MustDownload(const GURL& url,
+ net::HttpResponseHeaders* headers,
+ const std::string& mime_type) {
+ if (headers) {
+ std::string disposition;
+ if (headers->GetNormalizedHeader("content-disposition", &disposition) &&
+ !disposition.empty() &&
+ net::HttpContentDisposition(disposition, std::string())
+ .is_attachment()) {
+ return true;
+ }
+ if (GetContentClient()->browser()->ShouldForceDownloadResource(url,
+ mime_type))
+ return true;
+ if (mime_type == "multipart/related" || mime_type == "message/rfc822") {
+ // TODO(https://crbug.com/790734): retrieve the new NavigationUIData from
+ // the request and and pass it to AllowRenderingMhtmlOverHttp().
+ return !GetContentClient()->browser()->AllowRenderingMhtmlOverHttp(
+ nullptr);
+ }
+ // TODO(qinmin): Check whether this is special-case user script that needs
+ // to be downloaded.
+ }
+
+ return false;
+}
+
+bool IsDownload(const GURL& url,
+ net::HttpResponseHeaders* headers,
+ const std::string& mime_type) {
+ if (MustDownload(url, headers, mime_type))
+ return true;
+
+ if (blink::IsSupportedMimeType(mime_type))
+ return false;
+
+ return !headers || headers->response_code() / 100 == 2;
+}
+
+} // namespace navigation_loader_util
+} // namespace content
diff --git a/chromium/content/browser/loader/navigation_loader_util.h b/chromium/content/browser/loader/navigation_loader_util.h
new file mode 100644
index 00000000000..d5741554aff
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_loader_util.h
@@ -0,0 +1,34 @@
+// 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_LOADER_NAVIGATION_LOADER_UTIL_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_UTIL_H_
+
+#include "base/optional.h"
+
+#include <string>
+
+class GURL;
+namespace net {
+class HttpResponseHeaders;
+}
+
+namespace content {
+namespace navigation_loader_util {
+
+// Returns true if the given response must be downloaded because of the headers.
+bool MustDownload(const GURL& url,
+ net::HttpResponseHeaders* headers,
+ const std::string& mime_type);
+
+// Determines whether given response would result in a download.
+// Note this doesn't handle the case when a plugin exists for the |mime_type|.
+bool IsDownload(const GURL& url,
+ net::HttpResponseHeaders* headers,
+ const std::string& mime_type);
+
+} // namespace navigation_loader_util
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_UTIL_H_
diff --git a/chromium/content/browser/loader/navigation_metrics.cc b/chromium/content/browser/loader/navigation_metrics.cc
deleted file mode 100644
index 265efe3ade5..00000000000
--- a/chromium/content/browser/loader/navigation_metrics.cc
+++ /dev/null
@@ -1,25 +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/loader/navigation_metrics.h"
-
-#include "base/metrics/histogram_macros.h"
-
-namespace content {
-
-void RecordNavigationResourceHandlerMetrics(
- base::TimeTicks response_started,
- base::TimeTicks proceed_with_response,
- base::TimeTicks first_read_completed) {
- UMA_HISTOGRAM_TIMES(
- "Navigation.ResourceHandler."
- "ResponseStartedUntilProceedWithResponse",
- proceed_with_response - response_started);
- UMA_HISTOGRAM_TIMES(
- "Navigation.ResourceHandler."
- "ProceedWithResponseUntilFirstReadCompleted",
- first_read_completed - proceed_with_response);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/navigation_metrics.h b/chromium/content/browser/loader/navigation_metrics.h
deleted file mode 100644
index dfdd1d370ab..00000000000
--- a/chromium/content/browser/loader/navigation_metrics.h
+++ /dev/null
@@ -1,32 +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_LOADER_NAVIGATION_METRICS_H
-#define CONTENT_BROWSER_LOADER_NAVIGATION_METRICS_H
-
-#include "base/time/time.h"
-
-namespace content {
-
-// Records histograms for the time spent between several events in the
-// ResourceHandler dedicated to navigations.
-// - |response_started| is when the response's headers and metadata are
-// available. Loading is paused at this time.
-// - |proceed_with_response| is when loading is resumed.
-// - |first_read_completed| is when the first part of the body has been read.
-//
-// Depending on whether NavigationMojoResponse is enabled or not, these times
-// are either recorded by the MojoAsyncResourceHandler or the
-// NavigationResourceHandler.
-//
-// TODO(arthursonzogni): Move this function in MojoAsyncResourceHandler once
-// NavigationResourceHandler has been deleted.
-void RecordNavigationResourceHandlerMetrics(
- base::TimeTicks response_started,
- base::TimeTicks proceed_with_response,
- base::TimeTicks first_read_completed);
-
-} // namespace content.
-
-#endif // CONTENT_BROWSER_LOADER_NAVIGATION_METRICS_H
diff --git a/chromium/content/browser/loader/navigation_resource_handler.cc b/chromium/content/browser/loader/navigation_resource_handler.cc
deleted file mode 100644
index e0ee350c523..00000000000
--- a/chromium/content/browser/loader/navigation_resource_handler.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2014 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/loader/navigation_resource_handler.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/optional.h"
-#include "content/browser/loader/navigation_metrics.h"
-#include "content/browser/loader/navigation_url_loader_impl_core.h"
-#include "content/browser/loader/resource_controller.h"
-#include "content/browser/loader/resource_loader.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/resource_context_impl.h"
-#include "content/browser/streams/stream.h"
-#include "content/browser/streams/stream_context.h"
-#include "content/public/browser/navigation_data.h"
-#include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/stream_handle.h"
-#include "net/base/net_errors.h"
-#include "net/http/transport_security_state.h"
-#include "net/ssl/ssl_info.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "services/network/public/cpp/resource_response.h"
-#include "url/gurl.h"
-
-namespace content {
-
-NavigationResourceHandler::NavigationResourceHandler(
- net::URLRequest* request,
- std::unique_ptr<ResourceHandler> next_handler,
- NavigationURLLoaderImplCore* core,
- ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate,
- std::unique_ptr<StreamHandle> stream_handle)
- : LayeredResourceHandler(request, std::move(next_handler)),
- core_(core),
- stream_handle_(std::move(stream_handle)),
- resource_dispatcher_host_delegate_(resource_dispatcher_host_delegate) {
- core_->set_resource_handler(this);
-}
-
-NavigationResourceHandler::~NavigationResourceHandler() {
- if (core_) {
- core_->NotifyRequestFailed(false, net::ERR_ABORTED, base::nullopt);
- DetachFromCore();
- }
-}
-
-void NavigationResourceHandler::Cancel() {
- if (core_) {
- DetachFromCore();
- if (has_controller()) {
- LayeredResourceHandler::Cancel();
- } else {
- OutOfBandCancel(net::ERR_ABORTED, true /* tell_renderer */);
- }
- }
-}
-
-void NavigationResourceHandler::FollowRedirect() {
- DCHECK(response_);
- DCHECK(redirect_info_);
- DCHECK(has_controller());
- next_handler_->OnRequestRedirected(*redirect_info_, response_.get(),
- ReleaseController());
- response_ = nullptr;
- redirect_info_ = nullptr;
-}
-
-void NavigationResourceHandler::ProceedWithResponse() {
- DCHECK(response_);
- DCHECK(has_controller());
-
- time_proceed_with_response_ = base::TimeTicks::Now();
-
- // Detach from the loader; at this point, the request is now owned by the
- // StreamHandle sent in OnResponseStarted.
- DetachFromCore();
- next_handler_->OnResponseStarted(response_.get(), ReleaseController());
- response_ = nullptr;
-}
-
-void NavigationResourceHandler::OnRequestRedirected(
- const net::RedirectInfo& redirect_info,
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) {
- DCHECK(!has_controller());
-
- // The UI thread already cancelled the navigation. Do not proceed.
- if (!core_) {
- controller->Cancel();
- return;
- }
-
- response->head.encoded_data_length = request()->GetTotalReceivedBytes();
- core_->NotifyRequestRedirected(redirect_info, response);
-
- HoldController(std::move(controller));
- response_ = response;
- redirect_info_ = std::make_unique<net::RedirectInfo>(redirect_info);
-}
-
-void NavigationResourceHandler::OnResponseStarted(
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) {
- DCHECK(!has_controller());
-
- time_response_started_ = base::TimeTicks::Now();
-
- // The UI thread already cancelled the navigation. Do not proceed.
- if (!core_) {
- controller->Cancel();
- return;
- }
-
- ResourceRequestInfoImpl* info = GetRequestInfo();
-
- response->head.encoded_data_length = request()->raw_header_size();
- if (request()->ssl_info().cert)
- response->head.ssl_info = request()->ssl_info();
-
- std::unique_ptr<NavigationData> cloned_data;
- if (resource_dispatcher_host_delegate_) {
- // Ask the embedder for a NavigationData instance.
- NavigationData* navigation_data =
- resource_dispatcher_host_delegate_->GetNavigationData(request());
-
- // Clone the embedder's NavigationData before moving it to the UI thread.
- if (navigation_data)
- cloned_data = navigation_data->Clone();
- }
-
- core_->NotifyResponseStarted(
- response, std::move(stream_handle_), std::move(cloned_data),
- info->GetGlobalRequestID(), info->IsDownload(), info->is_stream());
- HoldController(std::move(controller));
- response_ = response;
-}
-
-void NavigationResourceHandler::OnReadCompleted(
- int bytes_read,
- std::unique_ptr<ResourceController> controller) {
- if (!has_completed_one_read_) {
- has_completed_one_read_ = true;
- base::TimeTicks time_first_read_completed = base::TimeTicks::Now();
- RecordNavigationResourceHandlerMetrics(time_response_started_,
- time_proceed_with_response_,
- time_first_read_completed);
- }
- next_handler_->OnReadCompleted(bytes_read, std::move(controller));
-}
-
-void NavigationResourceHandler::OnResponseCompleted(
- const net::URLRequestStatus& status,
- std::unique_ptr<ResourceController> controller) {
- if (core_) {
- int net_error = status.error();
- DCHECK_NE(net::OK, net_error);
-
- base::Optional<net::SSLInfo> ssl_info;
- if (net::IsCertStatusError(request()->ssl_info().cert_status)) {
- ssl_info = request()->ssl_info();
- }
-
- core_->NotifyRequestFailed(request()->response_info().was_cached, net_error,
- ssl_info);
- DetachFromCore();
- }
- next_handler_->OnResponseCompleted(status, std::move(controller));
-}
-
-void NavigationResourceHandler::DetachFromCore() {
- DCHECK(core_);
- core_->set_resource_handler(nullptr);
- core_ = nullptr;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/navigation_resource_handler.h b/chromium/content/browser/loader/navigation_resource_handler.h
deleted file mode 100644
index 8f6bf5f1d10..00000000000
--- a/chromium/content/browser/loader/navigation_resource_handler.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2014 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_LOADER_NAVIGATION_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_HANDLER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
-#include "content/browser/loader/layered_resource_handler.h"
-#include "content/public/browser/stream_handle.h"
-
-namespace content {
-class NavigationURLLoaderImplCore;
-class ResourceController;
-class ResourceDispatcherHostDelegate;
-
-// PlzNavigate: The ResourceHandler used with NavigationURLLoaderImplCore to
-// control the flow of navigation requests.
-class NavigationResourceHandler : public LayeredResourceHandler {
- public:
- NavigationResourceHandler(
- net::URLRequest* request,
- std::unique_ptr<ResourceHandler> next_handler,
- NavigationURLLoaderImplCore* core,
- ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate,
- std::unique_ptr<StreamHandle> stream_handle);
- ~NavigationResourceHandler() override;
-
- // Called by the loader the cancel the request.
- void Cancel();
-
- // Called to the loader to resume a paused redirect.
- void FollowRedirect();
-
- // Called to proceed with the response.
- void ProceedWithResponse();
-
- // LayeredResourceHandler implementation.
- void OnRequestRedirected(
- const net::RedirectInfo& redirect_info,
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) override;
- void OnResponseStarted(
- network::ResourceResponse* response,
- std::unique_ptr<ResourceController> controller) override;
- void OnReadCompleted(int bytes_read,
- std::unique_ptr<ResourceController> controller) override;
- void OnResponseCompleted(
- const net::URLRequestStatus& status,
- std::unique_ptr<ResourceController> controller) override;
-
- private:
- // Clears |core_| and its reference to the resource handler. After calling
- // this, the lifetime of the request is no longer managed by the
- // NavigationURLLoader.
- void DetachFromCore();
-
- // Used to buffer the response and redirect info while waiting for UI thread
- // checks to execute.
- scoped_refptr<network::ResourceResponse> response_;
- std::unique_ptr<net::RedirectInfo> redirect_info_;
-
- // Used for UMA histograms.
- bool has_completed_one_read_ = false;
- base::TimeTicks time_response_started_;
- base::TimeTicks time_proceed_with_response_;
-
- // NavigationResourceHandler has joint ownership of the
- // NavigationURLLoaderImplCore with the NavigationURLLoaderImpl.
- scoped_refptr<NavigationURLLoaderImplCore> core_;
- std::unique_ptr<StreamHandle> stream_handle_;
- ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(NavigationResourceHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader.cc b/chromium/content/browser/loader/navigation_url_loader.cc
index 7222ef1fa7c..c3709f8fa70 100644
--- a/chromium/content/browser/loader/navigation_url_loader.cc
+++ b/chromium/content/browser/loader/navigation_url_loader.cc
@@ -11,7 +11,6 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader_factory.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
-#include "content/browser/loader/navigation_url_loader_network_service.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "services/network/public/cpp/features.h"
@@ -33,17 +32,10 @@ std::unique_ptr<NavigationURLLoader> NavigationURLLoader::Create(
resource_context, storage_partition, std::move(request_info),
std::move(navigation_ui_data), service_worker_handle, delegate);
}
- if (IsNavigationMojoResponseEnabled()) {
- return std::make_unique<NavigationURLLoaderNetworkService>(
- resource_context, storage_partition, std::move(request_info),
- std::move(navigation_ui_data), service_worker_handle, appcache_handle,
- delegate, std::vector<std::unique_ptr<NavigationLoaderInterceptor>>());
- } else {
- return std::make_unique<NavigationURLLoaderImpl>(
- resource_context, storage_partition, std::move(request_info),
- std::move(navigation_ui_data), service_worker_handle, appcache_handle,
- delegate);
- }
+ return std::make_unique<NavigationURLLoaderImpl>(
+ resource_context, storage_partition, std::move(request_info),
+ std::move(navigation_ui_data), service_worker_handle, appcache_handle,
+ delegate, std::vector<std::unique_ptr<NavigationLoaderInterceptor>>());
}
void NavigationURLLoader::SetFactoryForTesting(
diff --git a/chromium/content/browser/loader/navigation_url_loader_delegate.h b/chromium/content/browser/loader/navigation_url_loader_delegate.h
index d7f694a942f..c7d238283e1 100644
--- a/chromium/content/browser/loader/navigation_url_loader_delegate.h
+++ b/chromium/content/browser/loader/navigation_url_loader_delegate.h
@@ -15,21 +15,20 @@
namespace net {
struct RedirectInfo;
-class SSLInfo;
}
namespace network {
struct ResourceResponse;
+struct URLLoaderCompletionStatus;
}
namespace content {
class NavigationData;
-class StreamHandle;
struct GlobalRequestID;
struct SubresourceLoaderParams;
-// PlzNavigate: The delegate interface to NavigationURLLoader.
+// The delegate interface to NavigationURLLoader.
class CONTENT_EXPORT NavigationURLLoaderDelegate {
public:
// Called when the request is redirected. Call FollowRedirect to continue
@@ -39,11 +38,9 @@ class CONTENT_EXPORT NavigationURLLoaderDelegate {
const scoped_refptr<network::ResourceResponse>& response) = 0;
// Called when the request receives its response. No further calls will be
- // made to the delegate. The response body is returned as a stream in
- // |body_stream|. |navigation_data| is passed to the NavigationHandle.
- // If the Network Service or NavigationMojoResponse is enabled, then the
- // |url_loader_client_endpoints| will be used, otherwise |body_stream|. Only
- // one of these will ever be non-null.
+ // made to the delegate. The response body can be retrieved by implementing an
+ // URLLoaderClient and binding the |url_loader_client_endpoints|.
+ // |navigation_data| is passed to the NavigationHandle.
// |subresource_loader_params| is used in the network service only for passing
// necessary info to create a custom subresource loader in the renderer
// process if the navigated context is controlled by a request interceptor
@@ -51,24 +48,20 @@ class CONTENT_EXPORT NavigationURLLoaderDelegate {
virtual void OnResponseStarted(
const scoped_refptr<network::ResourceResponse>& response,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- std::unique_ptr<StreamHandle> body_stream,
std::unique_ptr<NavigationData> navigation_data,
const GlobalRequestID& request_id,
bool is_download,
bool is_stream,
base::Optional<SubresourceLoaderParams> subresource_loader_params) = 0;
- // Called if the request fails before receving a response. |net_error| is a
- // network error code for the failure. |has_stale_copy_in_cache| is true if
- // there is a stale copy of the unreachable page in cache. |ssl_info| is the
- // SSL info for the request. If |net_error| is a certificate error and the
- // navigation request was for the main frame, the caller must pass a value
- // for |ssl_info|. If |net_error| is not a certificate error, |ssl_info| is
- // ignored.
+ // Called if the request fails before receving a response. Specific
+ // fields which are used: |status.error_code| holds the error code
+ // for the failure; |status.extended_error_code| holds details if
+ // available; |status.exists_in_cache| indicates a stale cache
+ // entry; |status.ssl_info| is available when |status.error_code| is
+ // a certificate error.
virtual void OnRequestFailed(
- bool has_stale_copy_in_cache,
- int net_error,
- const base::Optional<net::SSLInfo>& ssl_info) = 0;
+ const network::URLLoaderCompletionStatus& status) = 0;
// Called after the network request has begun on the IO thread at time
// |timestamp|. This is just a thread hop but is used to compare timing
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 687e6a6aff9..3dc15070498 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -1,128 +1,1412 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2017 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/loader/navigation_url_loader_impl.h"
-#include <utility>
+#include <memory>
#include "base/bind.h"
-#include "base/location.h"
-#include "base/optional.h"
+#include "base/bind_helpers.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/task_scheduler/post_task.h"
#include "base/trace_event/trace_event.h"
+#include "components/download/public/common/download_stats.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
-#include "content/browser/appcache/appcache_navigation_handle_core.h"
+#include "content/browser/appcache/appcache_request_handler.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/file_url_loader_factory.h"
+#include "content/browser/fileapi/file_system_url_loader_factory.h"
+#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
+#include "content/browser/loader/navigation_loader_util.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
-#include "content/browser/loader/navigation_url_loader_impl_core.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/resource_context_impl.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
+#include "content/browser/service_worker/service_worker_request_handler.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/browser/url_loader_factory_getter.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/browser/web_package/web_package_request_handler.h"
+#include "content/browser/webui/url_data_manager_backend.h"
+#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
#include "content/common/navigation_subresource_loader_params.h"
+#include "content/common/service_worker/service_worker_utils.h"
+#include "content/common/throttling_url_loader.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/navigation_ui_data.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/stream_handle.h"
+#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/ssl_status.h"
+#include "content/public/browser/url_loader_request_interceptor.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/referrer.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
+#include "content/public/common/webplugininfo.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_content_disposition.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/redirect_util.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "ppapi/buildflags/buildflags.h"
+#include "services/network/loader_util.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/request_context_frame_type.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "third_party/blink/public/common/mime_util/mime_util.h"
namespace content {
+namespace {
+
+class NavigationLoaderInterceptorBrowserContainer
+ : public NavigationLoaderInterceptor {
+ public:
+ explicit NavigationLoaderInterceptorBrowserContainer(
+ std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor)
+ : browser_interceptor_(std::move(browser_interceptor)) {}
+
+ ~NavigationLoaderInterceptorBrowserContainer() override = default;
+
+ void MaybeCreateLoader(const network::ResourceRequest& resource_request,
+ ResourceContext* resource_context,
+ LoaderCallback callback) override {
+ browser_interceptor_->MaybeCreateLoader(resource_request, resource_context,
+ std::move(callback));
+ }
+
+ private:
+ std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor_;
+};
+
+// Only used on the IO thread.
+base::LazyInstance<NavigationURLLoaderImpl::BeginNavigationInterceptor>::Leaky
+ g_interceptor = LAZY_INSTANCE_INITIALIZER;
+
+// Returns true if interception by NavigationLoaderInterceptors is enabled.
+// Both ServiceWorkerServicification and SignedExchange require the loader
+// interception. So even if NetworkService is not enabled, returns true when one
+// of them is enabled.
+bool IsLoaderInterceptionEnabled() {
+ return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+ ServiceWorkerUtils::IsServicificationEnabled() ||
+ signed_exchange_utils::IsSignedExchangeHandlingEnabled();
+}
+
+// Request ID for browser initiated requests. We start at -2 on the same lines
+// as ResourceDispatcherHostImpl.
+int g_next_request_id = -2;
+GlobalRequestID MakeGlobalRequestID() {
+ return GlobalRequestID(-1, g_next_request_id--);
+}
+
+size_t GetCertificateChainsSizeInKB(const net::SSLInfo& ssl_info) {
+ base::Pickle cert_pickle;
+ ssl_info.cert->Persist(&cert_pickle);
+ base::Pickle unverified_cert_pickle;
+ ssl_info.unverified_cert->Persist(&unverified_cert_pickle);
+ return (cert_pickle.size() + unverified_cert_pickle.size()) / 1000;
+}
+
+WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ if (!frame_tree_node)
+ return nullptr;
+
+ return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
+}
+
+const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
+ net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
+ semantics {
+ sender: "Navigation URL Loader"
+ description:
+ "This request is issued by a main frame navigation to fetch the "
+ "content of the page that is being navigated to."
+ trigger:
+ "Navigating Chrome (by clicking on a link, bookmark, history item, "
+ "using session restore, etc)."
+ data:
+ "Arbitrary site-controlled data can be included in the URL, HTTP "
+ "headers, and request body. Requests may include cookies and "
+ "site-specific credentials."
+ destination: WEBSITE
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "user"
+ setting: "This feature cannot be disabled."
+ chrome_policy {
+ URLBlacklist {
+ URLBlacklist: { entries: '*' }
+ }
+ }
+ chrome_policy {
+ URLWhitelist {
+ URLWhitelist { }
+ }
+ }
+ }
+ comments:
+ "Chrome would be unable to navigate to websites without this type of "
+ "request. Using either URLBlacklist or URLWhitelist policies (or a "
+ "combination of both) limits the scope of these requests."
+ )");
+
+std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
+ NavigationRequestInfo* request_info,
+ int frame_tree_node_id,
+ bool allow_download) {
+ // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here.
+ auto new_request = std::make_unique<network::ResourceRequest>();
+
+ new_request->method = request_info->common_params.method;
+ new_request->url = request_info->common_params.url;
+ new_request->site_for_cookies = request_info->site_for_cookies;
+
+ net::RequestPriority net_priority = net::HIGHEST;
+ if (!request_info->is_main_frame &&
+ base::FeatureList::IsEnabled(features::kLowPriorityIframes)) {
+ net_priority = net::LOWEST;
+ }
+ new_request->priority = net_priority;
+
+ new_request->render_frame_id = frame_tree_node_id;
+
+ // The code below to set fields like request_initiator, referrer, etc has
+ // been copied from ResourceDispatcherHostImpl. We did not refactor the
+ // common code into a function, because RDHI uses accessor functions on the
+ // URLRequest class to set these fields. whereas we use ResourceRequest here.
+ new_request->request_initiator = request_info->begin_params->initiator_origin;
+ new_request->referrer = request_info->common_params.referrer.url;
+ new_request->referrer_policy = Referrer::ReferrerPolicyForUrlRequest(
+ request_info->common_params.referrer.policy);
+ new_request->headers.AddHeadersFromString(
+ request_info->begin_params->headers);
+
+ std::string accept_value = network::kFrameAcceptHeader;
+ // TODO(https://crbug.com/840704): Decide whether the Accept header should
+ // advertise the state of kSignedHTTPExchangeOriginTrial before starting the
+ // Origin-Trial.
+ if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
+ DCHECK(!accept_value.empty());
+ accept_value.append(kAcceptHeaderSignedExchangeSuffix);
+ }
+
+ new_request->headers.SetHeader(network::kAcceptHeader, accept_value);
+
+ new_request->resource_type = request_info->is_main_frame
+ ? RESOURCE_TYPE_MAIN_FRAME
+ : RESOURCE_TYPE_SUB_FRAME;
+ if (request_info->is_main_frame)
+ new_request->update_first_party_url_on_redirect = true;
+
+ int load_flags = request_info->begin_params->load_flags;
+ if (request_info->is_main_frame)
+ load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED;
+
+ // Sync loads should have maximum priority and should be the only
+ // requests that have the ignore limits flag set.
+ DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));
+
+ new_request->load_flags = load_flags;
+
+ new_request->request_body = request_info->common_params.post_data.get();
+ new_request->report_raw_headers = request_info->report_raw_headers;
+ new_request->allow_download = allow_download;
+ new_request->enable_load_timing = true;
+
+ new_request->fetch_request_mode = network::mojom::FetchRequestMode::kNavigate;
+ new_request->fetch_credentials_mode =
+ network::mojom::FetchCredentialsMode::kInclude;
+ new_request->fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
+ new_request->fetch_request_context_type =
+ request_info->begin_params->request_context_type;
+ return new_request;
+}
+
+// Used only when NetworkService is disabled but IsLoaderInterceptionEnabled()
+// is true.
+std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
+ const NavigationRequestInfo& previous_request_info,
+ const network::ResourceRequest& updated_resource_request) {
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK(IsLoaderInterceptionEnabled());
+
+ CommonNavigationParams new_common_params =
+ previous_request_info.common_params;
+ new_common_params.url = updated_resource_request.url;
+ new_common_params.referrer =
+ Referrer(updated_resource_request.url,
+ Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
+ updated_resource_request.referrer_policy));
+ new_common_params.method = updated_resource_request.method;
+ new_common_params.post_data = updated_resource_request.request_body;
+ // TODO(shimazu): Set correct base url and history url for a data URL.
+
+ mojom::BeginNavigationParamsPtr new_begin_params =
+ previous_request_info.begin_params.Clone();
+ new_begin_params->headers = updated_resource_request.headers.ToString();
+
+ return std::make_unique<NavigationRequestInfo>(
+ std::move(new_common_params), std::move(new_begin_params),
+ updated_resource_request.site_for_cookies,
+ previous_request_info.is_main_frame,
+ previous_request_info.parent_is_main_frame,
+ previous_request_info.are_ancestors_secure,
+ previous_request_info.frame_tree_node_id,
+ previous_request_info.is_for_guests_only,
+ previous_request_info.report_raw_headers,
+ previous_request_info.is_prerendering,
+ nullptr /* blob_url_loader_factory */,
+ previous_request_info.devtools_navigation_token);
+}
+
+// Called for requests that we don't have a URLLoaderFactory for.
+void UnknownSchemeCallback(bool handled_externally,
+ network::mojom::URLLoaderRequest request,
+ network::mojom::URLLoaderClientPtr client) {
+ client->OnComplete(network::URLLoaderCompletionStatus(
+ handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
+}
+
+} // namespace
+
+// Kept around during the lifetime of the navigation request, and is
+// responsible for dispatching a ResourceRequest to the appropriate
+// URLLoader. In order to get the right URLLoader it builds a vector
+// of NavigationLoaderInterceptors and successively calls MaybeCreateLoader
+// on each until the request is successfully handled. The same sequence
+// may be performed multiple times when redirects happen.
+// TODO(michaeln): Expose this class and add more unittests.
+class NavigationURLLoaderImpl::URLLoaderRequestController
+ : public network::mojom::URLLoaderClient {
+ public:
+ URLLoaderRequestController(
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+ initial_interceptors,
+ std::unique_ptr<network::ResourceRequest> resource_request,
+ ResourceContext* resource_context,
+ scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter,
+ const GURL& url,
+ network::mojom::URLLoaderFactoryRequest proxied_factory_request,
+ network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
+ std::set<std::string> known_schemes,
+ const base::WeakPtr<NavigationURLLoaderImpl>& owner)
+ : interceptors_(std::move(initial_interceptors)),
+ resource_request_(std::move(resource_request)),
+ resource_context_(resource_context),
+ default_url_loader_factory_getter_(default_url_loader_factory_getter),
+ url_(url),
+ owner_(owner),
+ response_loader_binding_(this),
+ proxied_factory_request_(std::move(proxied_factory_request)),
+ proxied_factory_info_(std::move(proxied_factory_info)),
+ known_schemes_(std::move(known_schemes)),
+ weak_factory_(this) {}
+
+ ~URLLoaderRequestController() override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ }
+
+ static uint32_t GetURLLoaderOptions(bool is_main_frame) {
+ uint32_t options = network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
+ if (is_main_frame)
+ options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
+
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ options |= network::mojom::kURLLoadOptionSniffMimeType;
+ } else {
+ // TODO(arthursonzogni): This is a temporary option. Remove this as soon
+ // as the InterceptingResourceHandler is removed.
+ // See https://crbug.com/791049.
+ options |= network::mojom::kURLLoadOptionPauseOnResponseStarted;
+ }
+
+ return options;
+ }
+
+ SingleRequestURLLoaderFactory::RequestHandler
+ CreateDefaultRequestHandlerForNonNetworkService(
+ net::URLRequestContextGetter* url_request_context_getter,
+ storage::FileSystemContext* upload_file_system_context,
+ ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
+ AppCacheNavigationHandleCore* appcache_handle_core) const {
+ return base::BindOnce(
+ &URLLoaderRequestController::CreateNonNetworkServiceURLLoader,
+ weak_factory_.GetWeakPtr(),
+ base::Unretained(url_request_context_getter),
+ base::Unretained(upload_file_system_context),
+ std::make_unique<NavigationRequestInfo>(*request_info_),
+ base::Unretained(service_worker_navigation_handle_core),
+ base::Unretained(appcache_handle_core));
+ }
+
+ void CreateNonNetworkServiceURLLoader(
+ net::URLRequestContextGetter* url_request_context_getter,
+ storage::FileSystemContext* upload_file_system_context,
+ std::unique_ptr<NavigationRequestInfo> request_info,
+ ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
+ AppCacheNavigationHandleCore* appcache_handle_core,
+ network::mojom::URLLoaderRequest url_loader,
+ network::mojom::URLLoaderClientPtr url_loader_client) {
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ default_loader_used_ = true;
+ if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
+ DCHECK(!default_url_loader_factory_getter_);
+ // It is safe to pass the callback of CreateURLLoaderThrottles with the
+ // unretained |this|, because the passed callback will be used by a
+ // SignedExchangeHandler which is indirectly owned by |this| until its
+ // header is verified and parsed, that's where the getter is used.
+ interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
+ url::Origin::Create(request_info->common_params.url),
+ request_info->common_params.url,
+ GetURLLoaderOptions(request_info->is_main_frame),
+ request_info->frame_tree_node_id,
+ request_info->devtools_navigation_token,
+ request_info->report_raw_headers,
+ base::MakeRefCounted<
+ SignedExchangeURLLoaderFactoryForNonNetworkService>(
+ resource_context_, url_request_context_getter),
+ base::BindRepeating(
+ &URLLoaderRequestController::CreateURLLoaderThrottles,
+ base::Unretained(this)),
+ url_request_context_getter));
+ }
+
+ uint32_t options = GetURLLoaderOptions(request_info->is_main_frame);
+
+ bool intercepted = false;
+ if (g_interceptor.Get()) {
+ intercepted = g_interceptor.Get().Run(
+ &url_loader, frame_tree_node_id_, 0 /* request_id */, options,
+ *resource_request_.get(), &url_loader_client,
+ net::MutableNetworkTrafficAnnotationTag(
+ kNavigationUrlLoaderTrafficAnnotation));
+ }
+
+ // The ResourceDispatcherHostImpl can be null in unit tests.
+ if (!intercepted && ResourceDispatcherHostImpl::Get()) {
+ ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
+ resource_context_, url_request_context_getter->GetURLRequestContext(),
+ upload_file_system_context, *request_info,
+ std::move(navigation_ui_data_), std::move(url_loader_client),
+ std::move(url_loader), service_worker_navigation_handle_core,
+ appcache_handle_core, options, &global_request_id_);
+ }
+
+ // TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
+ // create a URLLoader. When it doesn't, do not send OnRequestStarted().
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted, owner_,
+ base::TimeTicks::Now()));
+ }
+
+ // TODO(arthursonzogni): See if this could eventually be unified with Start().
+ void StartWithoutNetworkService(
+ net::URLRequestContextGetter* url_request_context_getter,
+ storage::FileSystemContext* upload_file_system_context,
+ ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
+ AppCacheNavigationHandleCore* appcache_handle_core,
+ std::unique_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationUIData> navigation_ui_data) {
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!started_);
+ started_ = true;
+ request_info_ = std::move(request_info);
+ frame_tree_node_id_ = request_info_->frame_tree_node_id;
+ web_contents_getter_ = base::BindRepeating(
+ &GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
+ navigation_ui_data_ = std::move(navigation_ui_data);
+ default_request_handler_factory_ = base::BindRepeating(
+ &URLLoaderRequestController::
+ CreateDefaultRequestHandlerForNonNetworkService,
+ // base::Unretained(this) is safe since
+ // |default_request_handler_factory_| could be called only from |this|.
+ base::Unretained(this), base::Unretained(url_request_context_getter),
+ base::Unretained(upload_file_system_context),
+ base::Unretained(service_worker_navigation_handle_core),
+ base::Unretained(appcache_handle_core));
+
+ // If S13nServiceWorker is disabled, just use
+ // |default_request_handler_factory_| and return. The non network service
+ // request handling goes through ResourceDispatcherHost which has legacy
+ // hooks for service worker (ServiceWorkerRequestInterceptor), so no service
+ // worker interception is needed here.
+ if (!ServiceWorkerUtils::IsServicificationEnabled() ||
+ !service_worker_navigation_handle_core) {
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ default_request_handler_factory_.Run()),
+ CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(),
+ this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
+
+ // Otherwise, if S13nServiceWorker is enabled, create an interceptor so
+ // S13nServiceWorker has a chance to intercept the request.
+ std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
+ CreateServiceWorkerInterceptor(*request_info_,
+ service_worker_navigation_handle_core);
+ // If an interceptor is not created for some reasons (e.g. the origin is not
+ // secure), we no longer have to go through the rest of the network service
+ // code.
+ if (!service_worker_interceptor) {
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ default_request_handler_factory_.Run()),
+ CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(),
+ this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
+
+ interceptors_.push_back(std::move(service_worker_interceptor));
+
+ // TODO(shimazu): Make sure we have a consistent global id for the
+ // navigation request.
+ global_request_id_ = MakeGlobalRequestID();
+ Restart();
+ }
+
+ void Start(
+ net::URLRequestContextGetter* url_request_context_getter,
+ ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
+ AppCacheNavigationHandleCore* appcache_handle_core,
+ std::unique_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
+ int frame_tree_node_id,
+ std::unique_ptr<service_manager::Connector> connector) {
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!started_);
+ global_request_id_ = MakeGlobalRequestID();
+ frame_tree_node_id_ = frame_tree_node_id;
+ started_ = true;
+ web_contents_getter_ =
+ base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
+ navigation_ui_data_ = std::move(navigation_ui_data);
+
+ if (resource_request_->request_body) {
+ GetBodyBlobDataHandles(resource_request_->request_body.get(),
+ resource_context_, &blob_handles_);
+ }
+
+ // Requests to WebUI scheme won't get redirected to/from other schemes
+ // or be intercepted, so we just let it go here.
+ if (factory_for_webui.is_valid()) {
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(factory_for_webui)),
+ CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+ kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
+
+ // Requests to Blob scheme won't get redirected to/from other schemes
+ // or be intercepted, so we just let it go here.
+ if (request_info->common_params.url.SchemeIsBlob() &&
+ request_info->blob_url_loader_factory) {
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ network::SharedURLLoaderFactory::Create(
+ std::move(request_info->blob_url_loader_factory)),
+ CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+ kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
+
+ if (service_worker_navigation_handle_core) {
+ std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
+ CreateServiceWorkerInterceptor(*request_info,
+ service_worker_navigation_handle_core);
+ if (service_worker_interceptor)
+ interceptors_.push_back(std::move(service_worker_interceptor));
+ }
+
+ if (appcache_handle_core) {
+ std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
+ AppCacheRequestHandler::InitializeForNavigationNetworkService(
+ *resource_request_, appcache_handle_core,
+ default_url_loader_factory_getter_.get());
+ if (appcache_interceptor)
+ interceptors_.push_back(std::move(appcache_interceptor));
+ }
+
+ if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
+ // It is safe to pass the callback of CreateURLLoaderThrottles with the
+ // unretained |this|, because the passed callback will be used by a
+ // SignedExchangeHandler which is indirectly owned by |this| until its
+ // header is verified and parsed, that's where the getter is used.
+ interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
+ url::Origin::Create(request_info->common_params.url),
+ request_info->common_params.url,
+ GetURLLoaderOptions(request_info->is_main_frame),
+ request_info->frame_tree_node_id,
+ request_info->devtools_navigation_token,
+ request_info->report_raw_headers,
+ default_url_loader_factory_getter_->GetNetworkFactory(),
+ base::BindRepeating(
+ &URLLoaderRequestController::CreateURLLoaderThrottles,
+ base::Unretained(this)),
+ url_request_context_getter));
+ }
+
+ std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
+ browser_interceptors = GetContentClient()
+ ->browser()
+ ->WillCreateURLLoaderRequestInterceptors(
+ navigation_ui_data_.get(),
+ request_info->frame_tree_node_id);
+ if (!browser_interceptors.empty()) {
+ for (auto& browser_interceptor : browser_interceptors) {
+ interceptors_.push_back(
+ std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
+ std::move(browser_interceptor)));
+ }
+ }
+
+ Restart();
+ }
+
+ // This could be called multiple times to follow a chain of redirects.
+ void Restart() {
+ DCHECK(IsLoaderInterceptionEnabled());
+ // Clear |url_loader_| if it's not the default one (network). This allows
+ // the restarted request to use a new loader, instead of, e.g., reusing the
+ // AppCache or service worker loader. For an optimization, we keep and reuse
+ // the default url loader if the all |interceptors_| doesn't handle the
+ // redirected request.
+ if (!default_loader_used_)
+ url_loader_.reset();
+ interceptor_index_ = 0;
+ received_response_ = false;
+ MaybeStartLoader(nullptr /* interceptor */,
+ {} /* single_request_handler */);
+ }
+
+ // |interceptor| is non-null if this is called by one of the interceptors
+ // (via a LoaderCallback).
+ // |single_request_handler| is the RequestHandler given by the |interceptor|,
+ // non-null if the interceptor wants to handle the request.
+ void MaybeStartLoader(
+ NavigationLoaderInterceptor* interceptor,
+ SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
+ DCHECK(IsLoaderInterceptionEnabled());
+ if (single_request_handler) {
+ // |interceptor| wants to handle the request with
+ // |single_request_handler|.
+ DCHECK(interceptor);
+ default_loader_used_ = false;
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ std::move(single_request_handler)),
+ CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id? */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+ kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+
+ subresource_loader_params_ =
+ interceptor->MaybeCreateSubresourceLoaderParams();
+
+ return;
+ }
+
+ // Before falling back to the next interceptor, see if |interceptor| still
+ // wants to give additional info to the frame for subresource loading. In
+ // that case we will just fall back to the default loader (i.e. won't go on
+ // to the next interceptors) but send the subresource_loader_params to the
+ // child process. This is necessary for correctness in the cases where, e.g.
+ // there's a controlling ServiceWorker that doesn't handle main resource
+ // loading, but may still want to control the page and/or handle subresource
+ // loading. In that case we want to skip AppCache.
+ if (interceptor) {
+ subresource_loader_params_ =
+ interceptor->MaybeCreateSubresourceLoaderParams();
+
+ // If non-null |subresource_loader_params_| is returned, make sure
+ // we skip the next interceptors.
+ if (subresource_loader_params_)
+ interceptor_index_ = interceptors_.size();
+ }
+
+ // See if the next interceptor wants to handle the request.
+ if (interceptor_index_ < interceptors_.size()) {
+ auto* next_interceptor = interceptors_[interceptor_index_++].get();
+ next_interceptor->MaybeCreateLoader(
+ *resource_request_, resource_context_,
+ base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
+ base::Unretained(this), next_interceptor));
+ return;
+ }
+
+ // If we already have the default |url_loader_| we must come here after
+ // a redirect. No interceptors wanted to intercept the redirected request,
+ // so let it just follow the redirect.
+ if (url_loader_) {
+ DCHECK(!redirect_info_.new_url.is_empty());
+ url_loader_->FollowRedirect();
+ return;
+ }
+
+ // TODO(https://crbug.com/796425): We temporarily wrap raw
+ // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
+ // further refactor the factory getters to avoid this.
+ scoped_refptr<network::SharedURLLoaderFactory> factory;
+ DCHECK_EQ(interceptors_.size(), interceptor_index_);
+
+ // If NetworkService is not enabled (which means we come here because one of
+ // the loader interceptors is enabled), use the default request handler
+ // instead of going through the NetworkService path.
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ DCHECK(!interceptors_.empty());
+ DCHECK(default_request_handler_factory_);
+ default_loader_used_ = true;
+ // Update |request_info_| when following a redirect.
+ if (url_chain_.size() > 0) {
+ request_info_ = CreateNavigationRequestInfoForRedirect(
+ *request_info_, *resource_request_);
+ }
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ default_request_handler_factory_.Run()),
+ CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id */,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(),
+ this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
+
+ if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
+ factory =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ default_url_loader_factory_getter_->GetBlobFactory());
+ } else if (!IsURLHandledByNetworkService(resource_request_->url) &&
+ !resource_request_->url.SchemeIs(url::kDataScheme)) {
+ if (known_schemes_.find(resource_request_->url.scheme()) ==
+ known_schemes_.end()) {
+ bool handled = GetContentClient()->browser()->HandleExternalProtocol(
+ resource_request_->url, web_contents_getter_,
+ ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
+ resource_request_->resource_type == RESOURCE_TYPE_MAIN_FRAME,
+ static_cast<ui::PageTransition>(resource_request_->transition_type),
+ resource_request_->has_user_gesture);
+ factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ base::BindOnce(UnknownSchemeCallback, handled));
+ } else {
+ network::mojom::URLLoaderFactoryPtr& non_network_factory =
+ non_network_url_loader_factories_[resource_request_->url.scheme()];
+ if (!non_network_factory.is_bound()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NavigationURLLoaderImpl ::
+ BindNonNetworkURLLoaderFactoryRequest,
+ owner_, frame_tree_node_id_,
+ resource_request_->url,
+ mojo::MakeRequest(&non_network_factory)));
+ }
+ factory =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ non_network_factory.get());
+ }
+ } else {
+ default_loader_used_ = true;
+
+ // NOTE: We only support embedders proxying network-service-bound requests
+ // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
+ // or AppCache). Hence this code is only reachable when one of the above
+ // interceptors isn't used and the URL is either a data URL or has a
+ // scheme which is handled by the network service. We explicitly avoid
+ // proxying the data URL case here.
+ if (proxied_factory_request_.is_pending() &&
+ !resource_request_->url.SchemeIs(url::kDataScheme)) {
+ DCHECK(proxied_factory_info_.is_valid());
+ // We don't worry about reconnection since it's a single navigation.
+ default_url_loader_factory_getter_->CloneNetworkFactory(
+ std::move(proxied_factory_request_));
+ factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(proxied_factory_info_));
+ } else {
+ factory = default_url_loader_factory_getter_->GetNetworkFactory();
+ }
+ }
+ url_chain_.push_back(resource_request_->url);
+ uint32_t options = GetURLLoaderOptions(resource_request_->resource_type ==
+ RESOURCE_TYPE_MAIN_FRAME);
+ url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
+ factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
+ 0 /* request_id? */, options, resource_request_.get(), this,
+ kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ }
+
+ void FollowRedirect() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!redirect_info_.new_url.is_empty());
+
+ if (!IsLoaderInterceptionEnabled()) {
+ url_loader_->FollowRedirect();
+ return;
+ }
+
+ // Update |resource_request_| and call Restart to give our |interceptors_| a
+ // chance at handling the new location. If no interceptor wants to take
+ // over, we'll use the existing url_loader to follow the redirect, see
+ // MaybeStartLoader.
+ // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
+ // there likely remains more to be done.
+ // a. For subframe navigations, the Origin header may need to be modified
+ // differently?
+ // b. How should redirect_info_.referred_token_binding_host be handled?
+
+ bool should_clear_upload = false;
+ net::RedirectUtil::UpdateHttpRequest(
+ resource_request_->url, resource_request_->method, redirect_info_,
+ &resource_request_->headers, &should_clear_upload);
+ if (should_clear_upload) {
+ // The request body is no longer applicable.
+ resource_request_->request_body = nullptr;
+ blob_handles_.clear();
+ }
+
+ resource_request_->url = redirect_info_.new_url;
+ resource_request_->method = redirect_info_.new_method;
+ resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
+ resource_request_->referrer = GURL(redirect_info_.new_referrer);
+ resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
+ url_chain_.push_back(redirect_info_.new_url);
+
+ Restart();
+ }
+
+ base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
+ return std::move(subresource_loader_params_);
+ }
+
+ private:
+ // network::mojom::URLLoaderClient implementation:
+ void OnReceiveResponse(
+ const network::ResourceResponseHead& head,
+ network::mojom::DownloadedTempFilePtr downloaded_file) override {
+ received_response_ = true;
+
+ // If the default loader (network) was used to handle the URL load request
+ // we need to see if the interceptors want to potentially create a new
+ // loader for the response. e.g. AppCache.
+ if (MaybeCreateLoaderForResponse(head))
+ return;
+
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
+
+ // Currently only plugin handlers may intercept the response. Don't treat
+ // the response as download if it has been handled by plugins.
+ bool response_intercepted = false;
+ if (url_loader_) {
+ url_loader_client_endpoints = url_loader_->Unbind();
+ response_intercepted = url_loader_->response_intercepted();
+ } else {
+ url_loader_client_endpoints =
+ network::mojom::URLLoaderClientEndpoints::New(
+ response_url_loader_.PassInterface(),
+ response_loader_binding_.Unbind());
+ }
+
+ bool is_download;
+ bool is_stream;
+ std::unique_ptr<NavigationData> cloned_navigation_data;
+ if (IsLoaderInterceptionEnabled()) {
+ bool must_download = navigation_loader_util::MustDownload(
+ url_, head.headers.get(), head.mime_type);
+ bool known_mime_type = blink::IsSupportedMimeType(head.mime_type);
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ if (!response_intercepted && !must_download && !known_mime_type) {
+ CheckPluginAndContinueOnReceiveResponse(
+ head, std::move(downloaded_file),
+ std::move(url_loader_client_endpoints),
+ std::vector<WebPluginInfo>());
+ return;
+ }
+#endif
+
+ is_download =
+ !response_intercepted && (must_download || !known_mime_type);
+ is_stream = false;
+ } else {
+ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
+ net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
+
+ // The |url_request| maybe have been removed from the resource dispatcher
+ // host during the time it took for OnReceiveResponse() to be received.
+ if (url_request) {
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(url_request);
+ is_download = !response_intercepted && info->IsDownload();
+ is_stream = info->is_stream();
+ if (rdh->delegate()) {
+ NavigationData* navigation_data =
+ rdh->delegate()->GetNavigationData(url_request);
+
+ // Clone the embedder's NavigationData before moving it to the UI
+ // thread.
+ if (navigation_data)
+ cloned_navigation_data = navigation_data->Clone();
+ }
+
+ // This is similar to what is done in
+ // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams().
+ // It takes the matching ControllerServiceWorkerInfo (if any) associated
+ // with the request. It will be sent to the renderer process and used to
+ // intercept requests.
+ // TODO(arthursonzogni): This is needed only for the
+ // non-S13nServiceWorker case. The S13nServiceWorker case is still not
+ // supported without the NetworkService. This block needs to be updated
+ // once support for it will be added.
+ ServiceWorkerProviderHost* sw_provider_host =
+ ServiceWorkerRequestHandler::GetProviderHost(url_request);
+ if (sw_provider_host && sw_provider_host->controller()) {
+ subresource_loader_params_ = SubresourceLoaderParams();
+ subresource_loader_params_->controller_service_worker_info =
+ mojom::ControllerServiceWorkerInfo::New();
+ base::WeakPtr<ServiceWorkerHandle> sw_handle =
+ sw_provider_host->GetOrCreateServiceWorkerHandle(
+ sw_provider_host->controller());
+ if (sw_handle) {
+ subresource_loader_params_->controller_service_worker_handle =
+ sw_handle;
+ subresource_loader_params_->controller_service_worker_info
+ ->object_info = sw_handle->CreateIncompleteObjectInfo();
+ }
+ }
+ } else {
+ is_download = is_stream = false;
+ }
+ }
+
+ CallOnReceivedResponse(head, std::move(downloaded_file),
+ std::move(url_loader_client_endpoints),
+ std::move(cloned_navigation_data), is_download,
+ is_stream);
+ }
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ void CheckPluginAndContinueOnReceiveResponse(
+ const network::ResourceResponseHead& head,
+ network::mojom::DownloadedTempFilePtr downloaded_file,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ const std::vector<WebPluginInfo>& plugins) {
+ bool stale;
+ WebPluginInfo plugin;
+ // It's ok to pass -1 for the render process and frame ID since that's
+ // only used for plugin overridding. We don't actually care if we get an
+ // overridden plugin or not, since all we care about is the presence of a
+ // plugin. Note that this is what the MimeSniffingResourceHandler code
+ // path does as well for navigations.
+ bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
+ -1 /* render_process_id */, -1 /* render_frame_id */, resource_context_,
+ resource_request_->url, url::Origin(), head.mime_type,
+ false /* allow_wildcard */, &stale, &plugin, nullptr);
+
+ if (stale) {
+ // Refresh the plugins asynchronously.
+ PluginService::GetInstance()->GetPlugins(base::BindOnce(
+ &URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
+ weak_factory_.GetWeakPtr(), head, std::move(downloaded_file),
+ std::move(url_loader_client_endpoints)));
+ return;
+ }
+
+ bool is_download =
+ !has_plugin &&
+ (!head.headers || head.headers->response_code() / 100 == 2);
+
+ CallOnReceivedResponse(head, std::move(downloaded_file),
+ std::move(url_loader_client_endpoints), nullptr,
+ is_download, false /* is_stream */);
+ }
+#endif
+
+ void CallOnReceivedResponse(
+ const network::ResourceResponseHead& head,
+ network::mojom::DownloadedTempFilePtr downloaded_file,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ std::unique_ptr<NavigationData> cloned_navigation_data,
+ bool is_download,
+ bool is_stream) {
+ scoped_refptr<network::ResourceResponse> response(
+ new network::ResourceResponse());
+ response->head = head;
+
+ // Make a copy of the ResourceResponse before it is passed to another
+ // thread.
+ //
+ // TODO(davidben): This copy could be avoided if ResourceResponse weren't
+ // reference counted and the loader stack passed unique ownership of the
+ // response. https://crbug.com/416050
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NavigationURLLoaderImpl::OnReceiveResponse, owner_,
+ response->DeepCopy(),
+ std::move(url_loader_client_endpoints),
+ std::move(cloned_navigation_data), global_request_id_,
+ is_download, is_stream, std::move(downloaded_file)));
+ }
+
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& head) override {
+ if (--redirect_limit_ == 0) {
+ OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
+ return;
+ }
+
+ // Store the redirect_info for later use in FollowRedirect where we give
+ // our interceptors_ a chance to intercept the request for the new location.
+ redirect_info_ = redirect_info;
+
+ scoped_refptr<network::ResourceResponse> response(
+ new network::ResourceResponse());
+ response->head = head;
+ url_ = redirect_info.new_url;
+
+ // Make a copy of the ResourceResponse before it is passed to another
+ // thread.
+ //
+ // TODO(davidben): This copy could be avoided if ResourceResponse weren't
+ // reference counted and the loader stack passed unique ownership of the
+ // response. https://crbug.com/416050
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NavigationURLLoaderImpl::OnReceiveRedirect, owner_,
+ redirect_info, response->DeepCopy()));
+ }
+
+ void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) override {}
+ void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
+
+ void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
+ // Not reached. At this point, the loader and client endpoints must have
+ // been unbound and forwarded to the renderer.
+ CHECK(false);
+ }
+
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
+ status.ssl_info.has_value());
+ if (status.ssl_info.has_value()) {
+ UMA_HISTOGRAM_MEMORY_KB(
+ "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
+ GetCertificateChainsSizeInKB(status.ssl_info.value()));
+ }
+
+ if (status.error_code != net::OK && !received_response_) {
+ // If the default loader (network) was used to handle the URL load
+ // request we need to see if the interceptors want to potentially create a
+ // new loader for the response. e.g. AppCache.
+ if (MaybeCreateLoaderForResponse(network::ResourceResponseHead()))
+ return;
+ }
+ status_ = status;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status));
+ }
+
+ // Returns true if an interceptor wants to handle the response, i.e. return a
+ // different response. For e.g. AppCache may have fallback content.
+ bool MaybeCreateLoaderForResponse(
+ const network::ResourceResponseHead& response) {
+ if (!IsLoaderInterceptionEnabled())
+ return false;
+
+ if (!default_loader_used_)
+ return false;
+
+ for (auto& interceptor : interceptors_) {
+ network::mojom::URLLoaderClientRequest response_client_request;
+ if (interceptor->MaybeCreateLoaderForResponse(
+ response, &response_url_loader_, &response_client_request,
+ url_loader_.get())) {
+ response_loader_binding_.Bind(std::move(response_client_request));
+ default_loader_used_ = false;
+ url_loader_.reset();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ std::vector<std::unique_ptr<content::URLLoaderThrottle>>
+ CreateURLLoaderThrottles() {
+ return GetContentClient()->browser()->CreateURLLoaderThrottles(
+ *resource_request_, resource_context_, web_contents_getter_,
+ navigation_ui_data_.get(), frame_tree_node_id_);
+ }
+
+ std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
+ const NavigationRequestInfo& request_info,
+ ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core)
+ const {
+ const ResourceType resource_type = request_info.is_main_frame
+ ? RESOURCE_TYPE_MAIN_FRAME
+ : RESOURCE_TYPE_SUB_FRAME;
+ network::mojom::RequestContextFrameType frame_type =
+ request_info.is_main_frame
+ ? network::mojom::RequestContextFrameType::kTopLevel
+ : network::mojom::RequestContextFrameType::kNested;
+ storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
+ GetChromeBlobStorageContextForResourceContext(resource_context_));
+ return ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
+ *resource_request_, resource_context_,
+ service_worker_navigation_handle_core, blob_storage_context,
+ request_info.begin_params->skip_service_worker, resource_type,
+ request_info.begin_params->request_context_type, frame_type,
+ request_info.are_ancestors_secure, request_info.common_params.post_data,
+ web_contents_getter_);
+ }
+
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
+ size_t interceptor_index_ = 0;
+
+ std::unique_ptr<network::ResourceRequest> resource_request_;
+ // Non-NetworkService: |request_info_| is updated along with
+ // |resource_request_| on redirects.
+ std::unique_ptr<NavigationRequestInfo> request_info_;
+ int frame_tree_node_id_ = 0;
+ GlobalRequestID global_request_id_;
+ net::RedirectInfo redirect_info_;
+ int redirect_limit_ = net::URLRequest::kMaxRedirects;
+ ResourceContext* resource_context_;
+ base::Callback<WebContents*()> web_contents_getter_;
+ std::unique_ptr<NavigationUIData> navigation_ui_data_;
+ scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
+
+ std::unique_ptr<ThrottlingURLLoader> url_loader_;
+
+ BlobHandles blob_handles_;
+ std::vector<GURL> url_chain_;
+
+ // Current URL that is being navigated, updated after redirection.
+ GURL url_;
+
+ // Currently used by the AppCache loader to pass its factory to the
+ // renderer which enables it to handle subresources.
+ base::Optional<SubresourceLoaderParams> subresource_loader_params_;
+
+ // This is referenced only on the UI thread.
+ base::WeakPtr<NavigationURLLoaderImpl> owner_;
+
+ // Set to true if the default URLLoader (network service) was used for the
+ // current navigation.
+ bool default_loader_used_ = false;
+
+ // URLLoaderClient binding for loaders created for responses received from the
+ // network loader.
+ mojo::Binding<network::mojom::URLLoaderClient> response_loader_binding_;
+
+ // URLLoader instance for response loaders, i.e loaders created for handing
+ // responses received from the network URLLoader.
+ network::mojom::URLLoaderPtr response_url_loader_;
+
+ // Set to true if we receive a valid response from a URLLoader, i.e.
+ // URLLoaderClient::OnReceivedResponse() is called.
+ bool received_response_ = false;
+
+ bool started_ = false;
+
+ // Lazily initialized and used in the case of non-network resource
+ // navigations. Keyed by URL scheme.
+ std::map<std::string, network::mojom::URLLoaderFactoryPtr>
+ non_network_url_loader_factories_;
+
+ // Non-NetworkService:
+ // Generator of a request handler for sending request to the network. This
+ // captures all of parameters to create a
+ // SingleRequestURLLoaderFactory::RequestHandler. Used only when
+ // NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
+ base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler()>
+ default_request_handler_factory_;
+
+ // The completion status if it has been received. This is needed to handle
+ // the case that the response is intercepted by download, and OnComplete() is
+ // already called while we are transferring the |url_loader_| and response
+ // body to download code.
+ base::Optional<network::URLLoaderCompletionStatus> status_;
+
+ // Before creating this URLLoaderRequestController on UI thread, the embedder
+ // may have elected to proxy the URLLoaderFactory request, in which case these
+ // fields will contain input (info) and output (request) endpoints for the
+ // proxy. If this controller is handling a request for which proxying is
+ // supported, requests will be plumbed through these endpoints.
+ //
+ // Note that these are only used for requests that go to the Network Service.
+ network::mojom::URLLoaderFactoryRequest proxied_factory_request_;
+ network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info_;
+
+ // The schemes that this loader can use. For anything else we'll try external
+ // protocol handlers.
+ std::set<std::string> known_schemes_;
+
+ mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
+};
+
+// TODO(https://crbug.com/790734): pass |navigation_ui_data| along with the
+// request so that it could be modified.
NavigationURLLoaderImpl::NavigationURLLoaderImpl(
ResourceContext* resource_context,
StoragePartition* storage_partition,
std::unique_ptr<NavigationRequestInfo> request_info,
std::unique_ptr<NavigationUIData> navigation_ui_data,
- ServiceWorkerNavigationHandle* service_worker_handle,
+ ServiceWorkerNavigationHandle* service_worker_navigation_handle,
AppCacheNavigationHandle* appcache_handle,
- NavigationURLLoaderDelegate* delegate)
- : delegate_(delegate), weak_factory_(this) {
+ NavigationURLLoaderDelegate* delegate,
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+ initial_interceptors)
+ : delegate_(delegate),
+ allow_download_(request_info->common_params.allow_download),
+ weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ int frame_tree_node_id = request_info->frame_tree_node_id;
- core_ = new NavigationURLLoaderImplCore(weak_factory_.GetWeakPtr());
-
- // TODO(carlosk): extend this trace to support non-PlzNavigate navigations.
- // For the trace below we're using the NavigationURLLoaderImplCore as the
- // async trace id, |navigation_start| as the timestamp and reporting the
- // FrameTreeNode id as a parameter.
TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
- "navigation", "Navigation timeToResponseStarted", core_.get(),
+ "navigation", "Navigation timeToResponseStarted", this,
request_info->common_params.navigation_start, "FrameTreeNode id",
- request_info->frame_tree_node_id);
- ServiceWorkerNavigationHandleCore* service_worker_handle_core =
- service_worker_handle ? service_worker_handle->core() : nullptr;
+ frame_tree_node_id);
+
+ ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core =
+ service_worker_navigation_handle
+ ? service_worker_navigation_handle->core()
+ : nullptr;
+
AppCacheNavigationHandleCore* appcache_handle_core =
appcache_handle ? appcache_handle->core() : nullptr;
+
+ std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
+ request_info.get(), frame_tree_node_id, allow_download_);
+
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ DCHECK(!request_controller_);
+ request_controller_ = std::make_unique<URLLoaderRequestController>(
+ /* initial_interceptors = */
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
+ std::move(new_request), resource_context,
+ /* default_url_factory_getter = */ nullptr,
+ request_info->common_params.url,
+ /* proxied_url_loader_factory_request */ nullptr,
+ /* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
+ weak_factory_.GetWeakPtr());
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &URLLoaderRequestController::StartWithoutNetworkService,
+ base::Unretained(request_controller_.get()),
+ base::RetainedRef(storage_partition->GetURLRequestContext()),
+ base::Unretained(storage_partition->GetFileSystemContext()),
+ base::Unretained(service_worker_navigation_handle_core),
+ base::Unretained(appcache_handle_core), std::move(request_info),
+ std::move(navigation_ui_data)));
+ return;
+ }
+
+ // Check if a web UI scheme wants to handle this request.
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
+ const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
+ std::string scheme = new_request->url.scheme();
+ if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
+ factory_for_webui = CreateWebUIURLLoaderBinding(
+ frame_tree_node->current_frame_host(), scheme)
+ .PassInterface();
+ }
+
+ network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
+ network::mojom::URLLoaderFactoryRequest proxied_factory_request;
+ auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
+ if (frame_tree_node) {
+ // |frame_tree_node| may be null in some unit test environments.
+ GetContentClient()
+ ->browser()
+ ->RegisterNonNetworkNavigationURLLoaderFactories(
+ frame_tree_node_id, &non_network_url_loader_factories_);
+
+ // The embedder may want to proxy all network-bound URLLoaderFactory
+ // requests that it can. If it elects to do so, we'll pass its proxy
+ // endpoints off to the URLLoaderRequestController where wthey will be
+ // connected if the request type supports proxying.
+ network::mojom::URLLoaderFactoryPtrInfo factory_info;
+ auto factory_request = mojo::MakeRequest(&factory_info);
+ bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
+ frame_tree_node->current_frame_host(), true /* is_navigation */,
+ &factory_request);
+ if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
+ frame_tree_node->current_frame_host(), true, false,
+ &factory_request)) {
+ use_proxy = true;
+ }
+ if (use_proxy) {
+ proxied_factory_request = std::move(factory_request);
+ proxied_factory_info = std::move(factory_info);
+ }
+
+ const std::string storage_domain;
+ non_network_url_loader_factories_[url::kFileSystemScheme] =
+ CreateFileSystemURLLoaderFactory(frame_tree_node->current_frame_host(),
+ /*is_navigation=*/true,
+ partition->GetFileSystemContext(),
+ storage_domain);
+ }
+
+ non_network_url_loader_factories_[url::kFileScheme] =
+ std::make_unique<FileURLLoaderFactory>(
+ partition->browser_context()->GetPath(),
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+ std::set<std::string> known_schemes;
+ for (auto& iter : non_network_url_loader_factories_)
+ known_schemes.insert(iter.first);
+
+ DCHECK(!request_controller_);
+ request_controller_ = std::make_unique<URLLoaderRequestController>(
+ std::move(initial_interceptors), std::move(new_request), resource_context,
+ partition->url_loader_factory_getter(), request_info->common_params.url,
+ std::move(proxied_factory_request), std::move(proxied_factory_info),
+ std::move(known_schemes), weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
- &NavigationURLLoaderImplCore::Start, core_, resource_context,
- base::Unretained(storage_partition->GetURLRequestContext()),
- base::Unretained(storage_partition->GetFileSystemContext()),
- service_worker_handle_core, appcache_handle_core,
- std::move(request_info), std::move(navigation_ui_data)));
+ &URLLoaderRequestController::Start,
+ base::Unretained(request_controller_.get()),
+ base::RetainedRef(storage_partition->GetURLRequestContext()),
+ service_worker_navigation_handle_core, appcache_handle_core,
+ std::move(request_info), std::move(navigation_ui_data),
+ std::move(factory_for_webui), frame_tree_node_id,
+ ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
}
NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderImplCore::CancelRequestIfNeeded,
- core_));
+ BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
+ request_controller_.release());
}
void NavigationURLLoaderImpl::FollowRedirect() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderImplCore::FollowRedirect, core_));
+ base::BindOnce(&URLLoaderRequestController::FollowRedirect,
+ base::Unretained(request_controller_.get())));
}
-void NavigationURLLoaderImpl::ProceedWithResponse() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void NavigationURLLoaderImpl::ProceedWithResponse() {}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderImplCore::ProceedWithResponse, core_));
+void NavigationURLLoaderImpl::OnReceiveResponse(
+ scoped_refptr<network::ResourceResponse> response,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ std::unique_ptr<NavigationData> navigation_data,
+ const GlobalRequestID& global_request_id,
+ bool is_download,
+ bool is_stream,
+ network::mojom::DownloadedTempFilePtr downloaded_file) {
+ TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
+ "&NavigationURLLoaderImpl", this, "success", true);
+
+ // TODO(scottmg): This needs to do more of what
+ // NavigationResourceHandler::OnResponseStarted() does.
+
+ delegate_->OnResponseStarted(
+ std::move(response), std::move(url_loader_client_endpoints),
+ std::move(navigation_data), global_request_id,
+ allow_download_ && is_download, is_stream,
+ request_controller_->TakeSubresourceLoaderParams());
}
-void NavigationURLLoaderImpl::NotifyRequestRedirected(
+void NavigationURLLoaderImpl::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
- const scoped_refptr<network::ResourceResponse>& response) {
+ scoped_refptr<network::ResourceResponse> response) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- delegate_->OnRequestRedirected(redirect_info, response);
+ delegate_->OnRequestRedirected(redirect_info, std::move(response));
}
-void NavigationURLLoaderImpl::NotifyResponseStarted(
- const scoped_refptr<network::ResourceResponse>& response,
- std::unique_ptr<StreamHandle> body,
- std::unique_ptr<NavigationData> navigation_data,
- const GlobalRequestID& request_id,
- bool is_download,
- bool is_stream) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void NavigationURLLoaderImpl::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ if (status.error_code == net::OK)
+ return;
- delegate_->OnResponseStarted(
- response, network::mojom::URLLoaderClientEndpointsPtr(), std::move(body),
- std::move(navigation_data), request_id, is_download, is_stream,
- base::nullopt);
-}
+ TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
+ "&NavigationURLLoaderImpl", this, "success", false);
-void NavigationURLLoaderImpl::NotifyRequestFailed(
- bool in_cache,
- int net_error,
- base::Optional<net::SSLInfo> ssl_info) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ delegate_->OnRequestFailed(status);
+}
- delegate_->OnRequestFailed(in_cache, net_error, ssl_info);
+void NavigationURLLoaderImpl::SetBeginNavigationInterceptorForTesting(
+ const BeginNavigationInterceptor& interceptor) {
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
+ BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+ g_interceptor.Get() = interceptor;
}
-void NavigationURLLoaderImpl::NotifyRequestStarted(base::TimeTicks timestamp) {
+void NavigationURLLoaderImpl::OnRequestStarted(base::TimeTicks timestamp) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
delegate_->OnRequestStarted(timestamp);
}
+void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryRequest(
+ int frame_tree_node_id,
+ const GURL& url,
+ network::mojom::URLLoaderFactoryRequest factory) {
+ auto it = non_network_url_loader_factories_.find(url.scheme());
+ if (it == non_network_url_loader_factories_.end()) {
+ DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec();
+ return;
+ }
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ GetContentClient()->browser()->WillCreateURLLoaderFactory(
+ frame_tree_node->current_frame_host(), true /* is_navigation */,
+ &factory);
+ it->second->Clone(std::move(factory));
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index 7060fce6580..67c1d5bb8f7 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -1,86 +1,100 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2017 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_LOADER_NAVIGATION_URL_LOADER_IMPL_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_H_
-#include <memory>
-
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/loader/navigation_url_loader.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/ssl_status.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace net {
struct RedirectInfo;
-class SSLInfo;
-}
-
-namespace network {
-struct ResourceResponse;
}
namespace content {
-class AppCacheNavigationHandle;
-class NavigationURLLoaderImplCore;
class NavigationData;
-class ServiceWorkerNavigationHandle;
-class StreamHandle;
+class ResourceContext;
+class StoragePartition;
+class NavigationLoaderInterceptor;
struct GlobalRequestID;
-class NavigationURLLoaderImpl : public NavigationURLLoader {
+class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
public:
// The caller is responsible for ensuring that |delegate| outlives the loader.
- NavigationURLLoaderImpl(ResourceContext* resource_context,
- StoragePartition* storage_partition,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data,
- ServiceWorkerNavigationHandle* service_worker_handle,
- AppCacheNavigationHandle* appcache_handle,
- NavigationURLLoaderDelegate* delegate);
+ // Note |initial_interceptors| is there for test purposes only.
+ NavigationURLLoaderImpl(
+ ResourceContext* resource_context,
+ StoragePartition* storage_partition,
+ std::unique_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationUIData> navigation_ui_data,
+ ServiceWorkerNavigationHandle* service_worker_handle,
+ AppCacheNavigationHandle* appcache_handle,
+ NavigationURLLoaderDelegate* delegate,
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+ initial_interceptors);
~NavigationURLLoaderImpl() override;
- // NavigationURLLoader implementation.
+ // NavigationURLLoader implementation:
void FollowRedirect() override;
void ProceedWithResponse() override;
- private:
- friend class NavigationURLLoaderImplCore;
-
- // Notifies the delegate of a redirect.
- void NotifyRequestRedirected(
- const net::RedirectInfo& redirect_info,
- const scoped_refptr<network::ResourceResponse>& response);
-
- // Notifies the delegate that the response has started.
- void NotifyResponseStarted(
- const scoped_refptr<network::ResourceResponse>& response,
- std::unique_ptr<StreamHandle> body,
+ void OnReceiveResponse(
+ scoped_refptr<network::ResourceResponse> response,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
std::unique_ptr<NavigationData> navigation_data,
- const GlobalRequestID& request_id,
+ const GlobalRequestID& global_request_id,
bool is_download,
- bool is_stream);
+ bool is_stream,
+ network::mojom::DownloadedTempFilePtr downloaded_file);
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ scoped_refptr<network::ResourceResponse> response);
+ void OnComplete(const network::URLLoaderCompletionStatus& status);
+
+ // Overrides loading of frame requests when the network service is disabled.
+ // If the callback returns true, the frame request was intercepted. Otherwise
+ // it should be loaded normally through ResourceDispatcherHost. Passing an
+ // empty callback will restore the default behavior.
+ // This method must be called either on the IO thread or before threads start.
+ // This callback is run on the IO thread.
+ using BeginNavigationInterceptor = base::RepeatingCallback<bool(
+ network::mojom::URLLoaderRequest* request,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ network::mojom::URLLoaderClientPtr* client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)>;
+ static void SetBeginNavigationInterceptorForTesting(
+ const BeginNavigationInterceptor& interceptor);
- // Notifies the delegate the the request has failed. If |net_error| is a
- // certificate error, the caller must pass valid values for |ssl_info| and
- // |fatal_cert_error|. If |net_error| is not a certificate error, |ssl_info|
- // is ignored.
- void NotifyRequestFailed(bool in_cache,
- int net_error,
- base::Optional<net::SSLInfo> ssl_info);
+ private:
+ class URLLoaderRequestController;
+ void OnRequestStarted(base::TimeTicks timestamp);
- // Notifies the delegate the begin navigation request was handled and a
- // potential first network request is about to be made.
- void NotifyRequestStarted(base::TimeTicks timestamp);
+ void BindNonNetworkURLLoaderFactoryRequest(
+ int frame_tree_node_id,
+ const GURL& url,
+ network::mojom::URLLoaderFactoryRequest factory);
NavigationURLLoaderDelegate* delegate_;
- // |core_| is owned by this and the NavigationResourceHandler.
- scoped_refptr<NavigationURLLoaderImplCore> core_;
+ // Lives on the IO thread.
+ std::unique_ptr<URLLoaderRequestController> request_controller_;
+
+ bool allow_download_;
+
+ // Factories to handle navigation requests for non-network resources.
+ ContentBrowserClient::NonNetworkURLLoaderFactoryMap
+ non_network_url_loader_factories_;
base::WeakPtrFactory<NavigationURLLoaderImpl> weak_factory_;
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
deleted file mode 100644
index c4683b44905..00000000000
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2014 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/loader/navigation_url_loader_impl_core.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/time/time.h"
-#include "content/browser/frame_host/navigation_request_info.h"
-#include "content/browser/loader/navigation_resource_handler.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
-#include "content/common/navigation_params.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/navigation_data.h"
-#include "content/public/browser/navigation_ui_data.h"
-#include "content/public/browser/ssl_status.h"
-#include "content/public/browser/stream_handle.h"
-#include "net/base/net_errors.h"
-#include "net/url_request/redirect_info.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/public/cpp/resource_response.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "storage/browser/fileapi/file_system_context.h"
-
-namespace content {
-
-NavigationURLLoaderImplCore::NavigationURLLoaderImplCore(
- const base::WeakPtr<NavigationURLLoaderImpl>& loader)
- : loader_(loader), resource_handler_(nullptr), weak_factory_(this) {
- // This object is created on the UI thread but otherwise is accessed and
- // deleted on the IO thread.
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-NavigationURLLoaderImplCore::~NavigationURLLoaderImplCore() {}
-
-void NavigationURLLoaderImplCore::Start(
- ResourceContext* resource_context,
- net::URLRequestContextGetter* url_request_context_getter,
- storage::FileSystemContext* upload_file_system_context,
- ServiceWorkerNavigationHandleCore* service_worker_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- base::WeakPtr<NavigationURLLoaderImplCore> weak_this =
- weak_factory_.GetWeakPtr();
-
- uint32_t options = network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
- if (request_info->is_main_frame)
- options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
-
- // The ResourceDispatcherHostImpl can be null in unit tests.
- if (ResourceDispatcherHostImpl::Get()) {
- GlobalRequestID global_request_id; // unused.
- ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
- resource_context, url_request_context_getter->GetURLRequestContext(),
- upload_file_system_context, *request_info,
- std::move(navigation_ui_data), this,
- network::mojom::URLLoaderClientPtr(),
- network::mojom::URLLoaderRequest(), service_worker_handle_core,
- appcache_handle_core, options, &global_request_id);
- }
-
- // Careful, |this| could be destroyed at this point. Don't notify start if
- // that's the case (i.e. the request failed).
- if (!weak_this)
- return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestStarted, loader_,
- base::TimeTicks::Now()));
-}
-
-void NavigationURLLoaderImplCore::FollowRedirect() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (resource_handler_)
- resource_handler_->FollowRedirect();
-}
-
-void NavigationURLLoaderImplCore::ProceedWithResponse() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (resource_handler_)
- resource_handler_->ProceedWithResponse();
-}
-
-void NavigationURLLoaderImplCore::CancelRequestIfNeeded() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (resource_handler_)
- resource_handler_->Cancel();
-}
-
-void NavigationURLLoaderImplCore::NotifyRequestRedirected(
- const net::RedirectInfo& redirect_info,
- network::ResourceResponse* response) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
-
- // Make a copy of the ResourceResponse before it is passed to another thread.
- //
- // TODO(davidben): This copy could be avoided if ResourceResponse weren't
- // reference counted and the loader stack passed unique ownership of the
- // response. https://crbug.com/416050
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestRedirected, loader_,
- redirect_info, response->DeepCopy()));
-
- // TODO(carlosk): extend this trace to support non-PlzNavigate navigations.
- // For the trace below we're using the NavigationURLLoaderImplCore as the
- // async trace id and reporting the new redirect URL as a parameter.
- TRACE_EVENT_ASYNC_BEGIN2("navigation", "Navigation redirectDelay", this,
- "&NavigationURLLoaderImplCore", this, "New URL",
- redirect_info.new_url.spec());
-}
-
-void NavigationURLLoaderImplCore::NotifyResponseStarted(
- network::ResourceResponse* response,
- std::unique_ptr<StreamHandle> body,
- std::unique_ptr<NavigationData> navigation_data,
- const GlobalRequestID& request_id,
- bool is_download,
- bool is_stream) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
- TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
- "&NavigationURLLoaderImplCore", this, "success", true);
-
- // If, by the time the task reaches the UI thread, |loader_| has already been
- // destroyed, NotifyResponseStarted will not run. |body| will be destructed
- // and the request released at that point.
-
- // Make a copy of the ResourceResponse before it is passed to another thread.
- //
- // TODO(davidben): This copy could be avoided if ResourceResponse weren't
- // reference counted and the loader stack passed unique ownership of the
- // response. https://crbug.com/416050
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderImpl::NotifyResponseStarted, loader_,
- response->DeepCopy(), std::move(body),
- std::move(navigation_data), request_id, is_download,
- is_stream));
-}
-
-void NavigationURLLoaderImplCore::NotifyRequestFailed(
- bool in_cache,
- int net_error,
- const base::Optional<net::SSLInfo>& ssl_info) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
- TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
- "&NavigationURLLoaderImplCore", this, "success",
- false);
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestFailed, loader_,
- in_cache, net_error, ssl_info));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.h b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
deleted file mode 100644
index 5b3bad89726..00000000000
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2014 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_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
-#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/loader/navigation_url_loader_impl.h"
-
-namespace net {
-class URLRequestContextGetter;
-struct RedirectInfo;
-}
-
-namespace storage {
-class FileSystemContext;
-}
-
-namespace network {
-struct ResourceResponse;
-}
-
-namespace content {
-
-class AppCacheNavigationHandleCore;
-class NavigationResourceHandler;
-class NavigationData;
-class ResourceContext;
-class ServiceWorkerNavigationHandleCore;
-class StreamHandle;
-struct GlobalRequestID;
-
-// The IO-thread counterpart to the NavigationURLLoaderImpl. It lives on the IO
-// thread and is owned by the UI-thread NavigationURLLoaderImpl and the
-// IO-thread NavigationResourceHandler.
-// NavigationURLLoaderImplCore interacts with the ResourceDispatcherHost stack
-// and forwards signals back to the loader on the UI thread.
-class NavigationURLLoaderImplCore
- : public base::RefCountedThreadSafe<NavigationURLLoaderImplCore> {
- public:
- // Creates a new NavigationURLLoaderImplCore that forwards signals back to
- // |loader| on the UI thread.
- explicit NavigationURLLoaderImplCore(
- const base::WeakPtr<NavigationURLLoaderImpl>& loader);
-
- // Starts the request.
- void Start(ResourceContext* resource_context,
- net::URLRequestContextGetter* url_request_context_getter,
- storage::FileSystemContext* upload_file_system_context,
- ServiceWorkerNavigationHandleCore* service_worker_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data);
-
- // Follows the current pending redirect.
- void FollowRedirect();
-
- // Proceeds with processing the response.
- void ProceedWithResponse();
-
- // Cancels the request on the IO thread if this NavigationURLLoaderImplCore is
- // still attached to the NavigationResourceHandler.
- void CancelRequestIfNeeded();
-
- void set_resource_handler(NavigationResourceHandler* resource_handler) {
- resource_handler_ = resource_handler;
- }
-
- // Notifies |loader_| on the UI thread that the request was redirected.
- void NotifyRequestRedirected(const net::RedirectInfo& redirect_info,
- network::ResourceResponse* response);
-
- // Notifies |loader_| on the UI thread that the response started.
- void NotifyResponseStarted(network::ResourceResponse* response,
- std::unique_ptr<StreamHandle> body,
- std::unique_ptr<NavigationData> navigation_data,
- const GlobalRequestID& request_id,
- bool is_download,
- bool is_stream);
-
- // Notifies |loader_| on the UI thread that the request failed.
- void NotifyRequestFailed(bool in_cache,
- int net_error,
- const base::Optional<net::SSLInfo>& ssl_info);
-
- private:
- friend class base::RefCountedThreadSafe<NavigationURLLoaderImplCore>;
- virtual ~NavigationURLLoaderImplCore();
-
- base::WeakPtr<NavigationURLLoaderImpl> loader_;
- NavigationResourceHandler* resource_handler_;
-
- base::WeakPtrFactory<NavigationURLLoaderImplCore> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderImplCore);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader_network_service_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
index b6e28afd3be..4cafe900bb2 100644
--- a/chromium/content/browser/loader/navigation_url_loader_network_service_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -2,10 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/loader/navigation_url_loader_network_service.h"
+#include "content/browser/loader/navigation_url_loader_impl.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
+#include "base/unguessable_token.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader.h"
@@ -15,6 +21,7 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_ui_data.h"
+#include "content/public/browser/plugin_service.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -27,6 +34,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
+#include "ppapi/buildflags/buildflags.h"
#include "services/network/public/cpp/features.h"
#include "services/network/resource_scheduler_client.h"
#include "services/network/url_loader.h"
@@ -47,20 +55,18 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
net::URLRequestContextBuilder context_builder;
context_builder.set_proxy_resolution_service(
net::ProxyResolutionService::CreateDirect());
- context_ =
- new network::NetworkURLRequestContextGetter(context_builder.Build());
+ context_ = context_builder.Build();
constexpr int child_id = 4;
constexpr int route_id = 8;
resource_scheduler_client_ =
base::MakeRefCounted<network::ResourceSchedulerClient>(
child_id, route_id, &resource_scheduler_,
- context_->GetURLRequestContext()->network_quality_estimator());
+ context_->network_quality_estimator());
}
~TestNavigationLoaderInterceptor() override {
url_loader_ = nullptr;
resource_scheduler_client_ = nullptr;
- context_->NotifyContextShuttingDown();
}
void MaybeCreateLoader(const network::ResourceRequest& resource_request,
@@ -75,14 +81,18 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
network::mojom::URLLoaderRequest request,
network::mojom::URLLoaderClientPtr client) {
*most_recent_resource_request_ = resource_request;
+ static network::mojom::URLLoaderFactoryParams params;
+ params.process_id = network::mojom::kBrowserProcessId;
+ params.is_corb_enabled = false;
url_loader_ = std::make_unique<network::URLLoader>(
- context_, nullptr, base::BindOnce([](network::URLLoader*) {
- // Ignore self-deletion requests, for simplicity.
- }),
+ context_.get(), nullptr,
+ base::BindOnce(&TestNavigationLoaderInterceptor::DeleteURLLoader,
+ base::Unretained(this)),
std::move(request), 0 /* options */, resource_request,
false /* report_raw_headers */, std::move(client),
- TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* process_id */, 0, /* request_id */
- resource_scheduler_client_, nullptr);
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, 0, /* request_id */
+ resource_scheduler_client_, nullptr,
+ nullptr /* network_usage_accumulator */);
}
bool MaybeCreateLoaderForResponse(
@@ -94,19 +104,24 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
}
private:
+ void DeleteURLLoader(network::URLLoader* url_loader) {
+ DCHECK_EQ(url_loader_.get(), url_loader);
+ url_loader_.reset();
+ }
+
base::Optional<network::ResourceRequest>*
most_recent_resource_request_; // NOT OWNED.
network::ResourceScheduler resource_scheduler_;
- scoped_refptr<network::NetworkURLRequestContextGetter> context_;
+ std::unique_ptr<net::URLRequestContext> context_;
scoped_refptr<network::ResourceSchedulerClient> resource_scheduler_client_;
std::unique_ptr<network::URLLoader> url_loader_;
};
} // namespace
-class NavigationURLLoaderNetworkServiceTest : public testing::Test {
+class NavigationURLLoaderImplTest : public testing::Test {
public:
- NavigationURLLoaderNetworkServiceTest()
+ NavigationURLLoaderImplTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
feature_list_.InitAndEnableFeature(network::features::kNetworkService);
@@ -123,9 +138,13 @@ class NavigationURLLoaderNetworkServiceTest : public testing::Test {
browser_context_.reset(new TestBrowserContext);
http_test_server_.AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("content/test/data")));
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ PluginService::GetInstance()->Init();
+#endif
}
- ~NavigationURLLoaderNetworkServiceTest() override {
+ ~NavigationURLLoaderImplTest() override {
ServiceManagerConnection::DestroyForProcess();
}
@@ -157,13 +176,14 @@ class NavigationURLLoaderNetworkServiceTest : public testing::Test {
false /* parent_is_main_frame */, false /* are_ancestors_secure */,
-1 /* frame_tree_node_id */, false /* is_for_guests_only */,
false /* report_raw_headers */, false /* is_prerenering */,
- nullptr /* blob_url_loader_factory */));
+ nullptr /* blob_url_loader_factory */,
+ base::UnguessableToken::Create() /* devtools_navigation_token */));
std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors;
most_recent_resource_request_ = base::nullopt;
interceptors.push_back(std::make_unique<TestNavigationLoaderInterceptor>(
&most_recent_resource_request_));
- return std::make_unique<NavigationURLLoaderNetworkService>(
+ return std::make_unique<NavigationURLLoaderImpl>(
browser_context_->GetResourceContext(),
BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
std::move(request_info), nullptr /* navigation_ui_data */,
@@ -245,7 +265,7 @@ class NavigationURLLoaderNetworkServiceTest : public testing::Test {
base::Optional<network::ResourceRequest> most_recent_resource_request_;
};
-TEST_F(NavigationURLLoaderNetworkServiceTest, RequestPriority) {
+TEST_F(NavigationURLLoaderImplTest, RequestPriority) {
ASSERT_TRUE(http_test_server_.Start());
const GURL url = http_test_server_.GetURL("/redirect301-to-echo");
@@ -255,7 +275,7 @@ TEST_F(NavigationURLLoaderNetworkServiceTest, RequestPriority) {
NavigateAndReturnRequestPriority(url, false /* is_main_frame */));
}
-TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect301Tests) {
+TEST_F(NavigationURLLoaderImplTest, Redirect301Tests) {
ASSERT_TRUE(http_test_server_.Start());
const GURL url = http_test_server_.GetURL("/redirect301-to-echo");
@@ -269,7 +289,7 @@ TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect301Tests) {
true);
}
-TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect302Tests) {
+TEST_F(NavigationURLLoaderImplTest, Redirect302Tests) {
ASSERT_TRUE(http_test_server_.Start());
const GURL url = http_test_server_.GetURL("/redirect302-to-echo");
@@ -283,7 +303,7 @@ TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect302Tests) {
true);
}
-TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect303Tests) {
+TEST_F(NavigationURLLoaderImplTest, Redirect303Tests) {
ASSERT_TRUE(http_test_server_.Start());
const GURL url = http_test_server_.GetURL("/redirect303-to-echo");
@@ -297,7 +317,7 @@ TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect303Tests) {
true);
}
-TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect307Tests) {
+TEST_F(NavigationURLLoaderImplTest, Redirect307Tests) {
ASSERT_TRUE(http_test_server_.Start());
const GURL url = http_test_server_.GetURL("/redirect307-to-echo");
@@ -311,7 +331,7 @@ TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect307Tests) {
true);
}
-TEST_F(NavigationURLLoaderNetworkServiceTest, Redirect308Tests) {
+TEST_F(NavigationURLLoaderImplTest, Redirect308Tests) {
ASSERT_TRUE(http_test_server_.Start());
const GURL url = http_test_server_.GetURL("/redirect308-to-echo");
diff --git a/chromium/content/browser/loader/navigation_url_loader_network_service.cc b/chromium/content/browser/loader/navigation_url_loader_network_service.cc
deleted file mode 100644
index 4b7db1b992e..00000000000
--- a/chromium/content/browser/loader/navigation_url_loader_network_service.cc
+++ /dev/null
@@ -1,1344 +0,0 @@
-// Copyright 2017 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/loader/navigation_url_loader_network_service.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/feature_list.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/trace_event/trace_event.h"
-#include "components/download/public/common/download_stats.h"
-#include "content/browser/appcache/appcache_navigation_handle.h"
-#include "content/browser/appcache/appcache_request_handler.h"
-#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/devtools/render_frame_devtools_agent_host.h"
-#include "content/browser/file_url_loader_factory.h"
-#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/frame_host/navigation_request_info.h"
-#include "content/browser/loader/navigation_loader_interceptor.h"
-#include "content/browser/loader/navigation_resource_handler.h"
-#include "content/browser/loader/navigation_url_loader_delegate.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/resource_context_impl.h"
-#include "content/browser/service_worker/service_worker_navigation_handle.h"
-#include "content/browser/service_worker/service_worker_navigation_handle_core.h"
-#include "content/browser/service_worker/service_worker_request_handler.h"
-#include "content/browser/storage_partition_impl.h"
-#include "content/browser/url_loader_factory_getter.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/web_package/signed_exchange_consts.h"
-#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
-#include "content/browser/web_package/web_package_request_handler.h"
-#include "content/browser/webui/url_data_manager_backend.h"
-#include "content/browser/webui/web_ui_url_loader_factory_internal.h"
-#include "content/common/navigation_subresource_loader_params.h"
-#include "content/common/service_worker/service_worker_utils.h"
-#include "content/common/throttling_url_loader.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/navigation_data.h"
-#include "content/public/browser/navigation_ui_data.h"
-#include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/ssl_status.h"
-#include "content/public/browser/stream_handle.h"
-#include "content/public/common/browser_side_navigation_policy.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/referrer.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/common/url_utils.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
-#include "mojo/common/values_struct_traits.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_content_disposition.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/redirect_util.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/loader_util.h"
-#include "services/network/public/cpp/features.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "third_party/blink/public/common/mime_util/mime_util.h"
-
-namespace content {
-
-namespace {
-
-// Returns true if interception by NavigationLoaderInterceptors is enabled.
-bool IsLoaderInterceptionEnabled() {
- return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
- base::FeatureList::IsEnabled(features::kSignedHTTPExchange) ||
- ServiceWorkerUtils::IsServicificationEnabled();
-}
-
-// Request ID for browser initiated requests. We start at -2 on the same lines
-// as ResourceDispatcherHostImpl.
-int g_next_request_id = -2;
-GlobalRequestID MakeGlobalRequestID() {
- return GlobalRequestID(-1, g_next_request_id--);
-}
-
-size_t GetCertificateChainsSizeInKB(const net::SSLInfo& ssl_info) {
- base::Pickle cert_pickle;
- ssl_info.cert->Persist(&cert_pickle);
- base::Pickle unverified_cert_pickle;
- ssl_info.unverified_cert->Persist(&unverified_cert_pickle);
- return (cert_pickle.size() + unverified_cert_pickle.size()) / 1000;
-}
-
-WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id);
- if (!frame_tree_node)
- return nullptr;
-
- return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
-}
-
-const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
- net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
- semantics {
- sender: "Navigation URL Loader"
- description:
- "This request is issued by a main frame navigation to fetch the "
- "content of the page that is being navigated to."
- trigger:
- "Navigating Chrome (by clicking on a link, bookmark, history item, "
- "using session restore, etc)."
- data:
- "Arbitrary site-controlled data can be included in the URL, HTTP "
- "headers, and request body. Requests may include cookies and "
- "site-specific credentials."
- destination: WEBSITE
- }
- policy {
- cookies_allowed: YES
- cookies_store: "user"
- setting: "This feature cannot be disabled."
- chrome_policy {
- URLBlacklist {
- URLBlacklist: { entries: '*' }
- }
- }
- chrome_policy {
- URLWhitelist {
- URLWhitelist { }
- }
- }
- }
- comments:
- "Chrome would be unable to navigate to websites without this type of "
- "request. Using either URLBlacklist or URLWhitelist policies (or a "
- "combination of both) limits the scope of these requests."
- )");
-
-// TODO(arthursonzogni): IsDownload can't be determined only by the response's
-// headers. The response's body might contain information to guess it.
-// See MimeSniffingResourceHandler.
-bool IsDownload(const network::ResourceResponse& response,
- const GURL& url,
- const std::vector<GURL>& url_chain,
- const base::Optional<url::Origin>& initiator_origin,
- const base::Optional<std::string>& suggested_filename) {
- if (response.head.headers) {
- GURL url_chain_back = url_chain.empty() ? url : url_chain.back();
- bool is_cross_origin =
- (initiator_origin.has_value() && !url_chain_back.SchemeIsBlob() &&
- !url_chain_back.SchemeIsFileSystem() &&
- !url_chain_back.SchemeIs(url::kAboutScheme) &&
- !url_chain_back.SchemeIs(url::kDataScheme) &&
- initiator_origin->GetURL() != url_chain_back.GetOrigin());
-
- std::string disposition;
- if (response.head.headers->GetNormalizedHeader("content-disposition",
- &disposition) &&
- !disposition.empty() &&
- net::HttpContentDisposition(disposition, std::string())
- .is_attachment()) {
- return true;
- } else if (suggested_filename.has_value() && !is_cross_origin) {
- return true;
- } else if (GetContentClient()->browser()->ShouldForceDownloadResource(
- url, response.head.mime_type)) {
- return true;
- } else if (response.head.mime_type == "multipart/related" ||
- response.head.mime_type == "message/rfc822") {
- // TODO(https://crbug.com/790734): retrieve the new NavigationUIData from
- // the request and and pass it to AllowRenderingMhtmlOverHttp().
- return !GetContentClient()->browser()->AllowRenderingMhtmlOverHttp(
- nullptr);
- }
- // TODO(qinmin): Check whether this is special-case user script that needs
- // to be downloaded.
- }
-
- if (blink::IsSupportedMimeType(response.head.mime_type))
- return false;
-
- // TODO(qinmin): Check whether there is a plugin handler.
-
- if (suggested_filename.has_value()) {
- download::RecordDownloadCount(
- download::CROSS_ORIGIN_DOWNLOAD_WITHOUT_CONTENT_DISPOSITION);
- }
-
- return (!response.head.headers ||
- response.head.headers->response_code() / 100 == 2);
-}
-
-std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
- NavigationRequestInfo* request_info,
- int frame_tree_node_id,
- bool allow_download) {
- // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here.
- auto new_request = std::make_unique<network::ResourceRequest>();
-
- new_request->method = request_info->common_params.method;
- new_request->url = request_info->common_params.url;
- new_request->site_for_cookies = request_info->site_for_cookies;
-
- net::RequestPriority net_priority = net::HIGHEST;
- if (!request_info->is_main_frame &&
- base::FeatureList::IsEnabled(features::kLowPriorityIframes)) {
- net_priority = net::LOWEST;
- }
- new_request->priority = net_priority;
-
- new_request->render_frame_id = frame_tree_node_id;
-
- // The code below to set fields like request_initiator, referrer, etc has
- // been copied from ResourceDispatcherHostImpl. We did not refactor the
- // common code into a function, because RDHI uses accessor functions on the
- // URLRequest class to set these fields. whereas we use ResourceRequest here.
- new_request->request_initiator = request_info->begin_params->initiator_origin;
- new_request->referrer = request_info->common_params.referrer.url;
- new_request->referrer_policy = Referrer::ReferrerPolicyForUrlRequest(
- request_info->common_params.referrer.policy);
- new_request->headers.AddHeadersFromString(
- request_info->begin_params->headers);
-
- std::string accept_value = network::kFrameAcceptHeader;
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange)) {
- DCHECK(!accept_value.empty());
- accept_value.append(kAcceptHeaderSignedExchangeSuffix);
- }
-
- new_request->headers.SetHeader(network::kAcceptHeader, accept_value);
-
- new_request->resource_type = request_info->is_main_frame
- ? RESOURCE_TYPE_MAIN_FRAME
- : RESOURCE_TYPE_SUB_FRAME;
- if (request_info->is_main_frame)
- new_request->update_first_party_url_on_redirect = true;
-
- int load_flags = request_info->begin_params->load_flags;
- if (request_info->is_main_frame)
- load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED;
-
- // Sync loads should have maximum priority and should be the only
- // requests that have the ignore limits flag set.
- DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));
-
- new_request->load_flags = load_flags;
-
- new_request->request_body = request_info->common_params.post_data.get();
- new_request->report_raw_headers = request_info->report_raw_headers;
- new_request->allow_download = allow_download;
- new_request->enable_load_timing = true;
-
- new_request->fetch_request_mode = network::mojom::FetchRequestMode::kNavigate;
- new_request->fetch_credentials_mode =
- network::mojom::FetchCredentialsMode::kInclude;
- new_request->fetch_redirect_mode = network::mojom::FetchRedirectMode::kManual;
- new_request->fetch_request_context_type =
- request_info->begin_params->request_context_type;
- return new_request;
-}
-
-// Used only when NetworkService is disabled but IsLoaderInterceptionEnabled()
-// is true.
-std::unique_ptr<NavigationRequestInfo> CreateNavigationRequestInfoForRedirect(
- const NavigationRequestInfo& previous_request_info,
- const network::ResourceRequest& updated_resource_request) {
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- DCHECK(IsLoaderInterceptionEnabled());
-
- CommonNavigationParams new_common_params =
- previous_request_info.common_params;
- new_common_params.url = updated_resource_request.url;
- new_common_params.referrer =
- Referrer(updated_resource_request.url,
- Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
- updated_resource_request.referrer_policy));
- new_common_params.method = updated_resource_request.method;
- new_common_params.post_data = updated_resource_request.request_body;
- // TODO(shimazu): Set correct base url and history url for a data URL.
-
- mojom::BeginNavigationParamsPtr new_begin_params =
- previous_request_info.begin_params.Clone();
- new_begin_params->headers = updated_resource_request.headers.ToString();
-
- return std::make_unique<NavigationRequestInfo>(
- std::move(new_common_params), std::move(new_begin_params),
- updated_resource_request.site_for_cookies,
- previous_request_info.is_main_frame,
- previous_request_info.parent_is_main_frame,
- previous_request_info.are_ancestors_secure,
- previous_request_info.frame_tree_node_id,
- previous_request_info.is_for_guests_only,
- previous_request_info.report_raw_headers,
- previous_request_info.is_prerendering,
- nullptr /* blob_url_loader_factory */);
-}
-
-// Called for requests that we don't have a URLLoaderFactory for.
-void UnknownSchemeCallback(bool handled_externally,
- network::mojom::URLLoaderRequest request,
- network::mojom::URLLoaderClientPtr client) {
- client->OnComplete(network::URLLoaderCompletionStatus(
- handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
-}
-
-} // namespace
-
-// Kept around during the lifetime of the navigation request, and is
-// responsible for dispatching a ResourceRequest to the appropriate
-// URLLoader. In order to get the right URLLoader it builds a vector
-// of NavigationLoaderInterceptors and successively calls MaybeCreateLoader
-// on each until the request is successfully handled. The same sequence
-// may be performed multiple times when redirects happen.
-// TODO(michaeln): Expose this class and add more unittests.
-class NavigationURLLoaderNetworkService::URLLoaderRequestController
- : public network::mojom::URLLoaderClient {
- public:
- URLLoaderRequestController(
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
- initial_interceptors,
- std::unique_ptr<network::ResourceRequest> resource_request,
- ResourceContext* resource_context,
- scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter,
- const GURL& url,
- base::Optional<url::Origin> initiator_origin,
- base::Optional<std::string> suggested_filename,
- network::mojom::URLLoaderFactoryRequest proxied_factory_request,
- network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
- std::set<std::string> known_schemes,
- const base::WeakPtr<NavigationURLLoaderNetworkService>& owner)
- : interceptors_(std::move(initial_interceptors)),
- resource_request_(std::move(resource_request)),
- resource_context_(resource_context),
- default_url_loader_factory_getter_(default_url_loader_factory_getter),
- url_(url),
- initiator_origin_(initiator_origin),
- suggested_filename_(suggested_filename),
- owner_(owner),
- response_loader_binding_(this),
- proxied_factory_request_(std::move(proxied_factory_request)),
- proxied_factory_info_(std::move(proxied_factory_info)),
- known_schemes_(std::move(known_schemes)),
- weak_factory_(this) {}
-
- ~URLLoaderRequestController() override {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- }
-
- static uint32_t GetURLLoaderOptions(bool is_main_frame) {
- uint32_t options = network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
- if (is_main_frame)
- options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
-
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- options |= network::mojom::kURLLoadOptionSniffMimeType;
- } else {
- // TODO(arthursonzogni): This is a temporary option. Remove this as soon
- // as the InterceptingResourceHandler is removed.
- // See https://crbug.com/791049.
- options |= network::mojom::kURLLoadOptionPauseOnResponseStarted;
- }
-
- return options;
- }
-
- SingleRequestURLLoaderFactory::RequestHandler
- CreateDefaultRequestHandlerForNonNetworkService(
- net::URLRequestContextGetter* url_request_context_getter,
- storage::FileSystemContext* upload_file_system_context,
- ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core) const {
- return base::BindOnce(
- &URLLoaderRequestController::CreateNonNetworkServiceURLLoader,
- weak_factory_.GetWeakPtr(),
- base::Unretained(url_request_context_getter),
- base::Unretained(upload_file_system_context),
- std::make_unique<NavigationRequestInfo>(*request_info_),
- base::Unretained(service_worker_navigation_handle_core),
- base::Unretained(appcache_handle_core));
- }
-
- void CreateNonNetworkServiceURLLoader(
- net::URLRequestContextGetter* url_request_context_getter,
- storage::FileSystemContext* upload_file_system_context,
- std::unique_ptr<NavigationRequestInfo> request_info,
- ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core,
- network::mojom::URLLoaderRequest url_loader,
- network::mojom::URLLoaderClientPtr url_loader_client) {
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- default_loader_used_ = true;
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange)) {
- DCHECK(!default_url_loader_factory_getter_);
- // It is safe to pass the callback of CreateURLLoaderThrottles with the
- // unretained |this|, because the passed callback will be used by a
- // SignedExchangeHandler which is indirectly owned by |this| until its
- // header is verified and parsed, that's where the getter is used.
- interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
- url::Origin::Create(request_info->common_params.url),
- GetURLLoaderOptions(request_info->is_main_frame),
- request_info->frame_tree_node_id,
- base::MakeRefCounted<
- SignedExchangeURLLoaderFactoryForNonNetworkService>(
- resource_context_, url_request_context_getter),
- base::BindRepeating(
- &URLLoaderRequestController::CreateURLLoaderThrottles,
- base::Unretained(this)),
- url_request_context_getter));
- }
-
- // The ResourceDispatcherHostImpl can be null in unit tests.
- if (ResourceDispatcherHostImpl::Get()) {
- ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
- resource_context_, url_request_context_getter->GetURLRequestContext(),
- upload_file_system_context, *request_info,
- std::move(navigation_ui_data_), nullptr, std::move(url_loader_client),
- std::move(url_loader), service_worker_navigation_handle_core,
- appcache_handle_core,
- GetURLLoaderOptions(request_info->is_main_frame),
- &global_request_id_);
- }
-
- // TODO(arthursonzogni): Detect when the ResourceDispatcherHost didn't
- // create a URLLoader. When it doesn't, do not send OnRequestStarted().
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderNetworkService::OnRequestStarted,
- owner_, base::TimeTicks::Now()));
- }
-
- // TODO(arthursonzogni): See if this could eventually be unified with Start().
- void StartWithoutNetworkService(
- net::URLRequestContextGetter* url_request_context_getter,
- storage::FileSystemContext* upload_file_system_context,
- ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data) {
- DCHECK(IsNavigationMojoResponseEnabled());
- DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!started_);
- started_ = true;
- request_info_ = std::move(request_info);
- frame_tree_node_id_ = request_info_->frame_tree_node_id;
- web_contents_getter_ = base::BindRepeating(
- &GetWebContentsFromFrameTreeNodeID, frame_tree_node_id_);
- navigation_ui_data_ = std::move(navigation_ui_data);
- default_request_handler_factory_ = base::BindRepeating(
- &URLLoaderRequestController::
- CreateDefaultRequestHandlerForNonNetworkService,
- // base::Unretained(this) is safe since
- // |default_request_handler_factory_| could be called only from |this|.
- base::Unretained(this), base::Unretained(url_request_context_getter),
- base::Unretained(upload_file_system_context),
- base::Unretained(service_worker_navigation_handle_core),
- base::Unretained(appcache_handle_core));
-
- // If S13nServiceWorker is disabled, just use
- // |default_request_handler_factory_| and return. The non network service
- // request handling goes through ResourceDispatcherHost which has legacy
- // hooks for service worker (ServiceWorkerRequestInterceptor), so no service
- // worker interception is needed here.
- if (!ServiceWorkerUtils::IsServicificationEnabled() ||
- !service_worker_navigation_handle_core) {
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
- CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(),
- this /* client */, kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
- }
-
- // Otherwise, if S13nServiceWorker is enabled, create an interceptor so
- // S13nServiceWorker has a chance to intercept the request.
- std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
- CreateServiceWorkerInterceptor(*request_info_,
- service_worker_navigation_handle_core);
- // If an interceptor is not created for some reasons (e.g. the origin is not
- // secure), we no longer have to go through the rest of the network service
- // code.
- if (!service_worker_interceptor) {
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
- CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(),
- this /* client */, kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
- }
-
- interceptors_.push_back(std::move(service_worker_interceptor));
-
- // TODO(shimazu): Make sure we have a consistent global id for the
- // navigation request.
- global_request_id_ = MakeGlobalRequestID();
- Restart();
- }
-
- void Start(
- net::URLRequestContextGetter* url_request_context_getter,
- ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
- AppCacheNavigationHandleCore* appcache_handle_core,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data,
- network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
- int frame_tree_node_id,
- std::unique_ptr<service_manager::Connector> connector) {
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!started_);
- global_request_id_ = MakeGlobalRequestID();
- frame_tree_node_id_ = frame_tree_node_id;
- started_ = true;
- web_contents_getter_ =
- base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id);
- navigation_ui_data_ = std::move(navigation_ui_data);
-
- if (resource_request_->request_body) {
- GetBodyBlobDataHandles(resource_request_->request_body.get(),
- resource_context_, &blob_handles_);
- }
-
- // Requests to WebUI scheme won't get redirected to/from other schemes
- // or be intercepted, so we just let it go here.
- if (factory_for_webui.is_valid()) {
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
- std::move(factory_for_webui)),
- CreateURLLoaderThrottles(), 0 /* routing_id */, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
- }
-
- // Requests to Blob scheme won't get redirected to/from other schemes
- // or be intercepted, so we just let it go here.
- if (request_info->common_params.url.SchemeIsBlob() &&
- request_info->blob_url_loader_factory) {
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- network::SharedURLLoaderFactory::Create(
- std::move(request_info->blob_url_loader_factory)),
- GetContentClient()->browser()->CreateURLLoaderThrottles(
- *resource_request_, resource_context_, web_contents_getter_,
- navigation_ui_data_.get(), frame_tree_node_id_),
- 0 /* routing_id */, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
- }
-
- if (service_worker_navigation_handle_core) {
- std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
- CreateServiceWorkerInterceptor(*request_info,
- service_worker_navigation_handle_core);
- if (service_worker_interceptor)
- interceptors_.push_back(std::move(service_worker_interceptor));
- }
-
- if (appcache_handle_core) {
- std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
- AppCacheRequestHandler::InitializeForNavigationNetworkService(
- *resource_request_, appcache_handle_core,
- default_url_loader_factory_getter_.get());
- if (appcache_interceptor)
- interceptors_.push_back(std::move(appcache_interceptor));
- }
-
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange)) {
- // It is safe to pass the callback of CreateURLLoaderThrottles with the
- // unretained |this|, because the passed callback will be used by a
- // SignedExchangeHandler which is indirectly owned by |this| until its
- // header is verified and parsed, that's where the getter is used.
- interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
- url::Origin::Create(request_info->common_params.url),
- GetURLLoaderOptions(request_info->is_main_frame),
- request_info->frame_tree_node_id,
- default_url_loader_factory_getter_->GetNetworkFactory(),
- base::BindRepeating(
- &URLLoaderRequestController::CreateURLLoaderThrottles,
- base::Unretained(this)),
- url_request_context_getter));
- }
-
- Restart();
- }
-
- // This could be called multiple times to follow a chain of redirects.
- void Restart() {
- DCHECK(IsLoaderInterceptionEnabled());
- // Clear |url_loader_| if it's not the default one (network). This allows
- // the restarted request to use a new loader, instead of, e.g., reusing the
- // AppCache or service worker loader. For an optimization, we keep and reuse
- // the default url loader if the all |interceptors_| doesn't handle the
- // redirected request.
- if (!default_loader_used_)
- url_loader_.reset();
- interceptor_index_ = 0;
- received_response_ = false;
- MaybeStartLoader(nullptr /* interceptor */,
- {} /* single_request_handler */);
- }
-
- // |interceptor| is non-null if this is called by one of the interceptors
- // (via a LoaderCallback).
- // |single_request_handler| is the RequestHandler given by the |interceptor|,
- // non-null if the interceptor wants to handle the request.
- void MaybeStartLoader(
- NavigationLoaderInterceptor* interceptor,
- SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
- DCHECK(IsLoaderInterceptionEnabled());
- if (single_request_handler) {
- // |interceptor| wants to handle the request with
- // |single_request_handler|.
- DCHECK(interceptor);
- default_loader_used_ = false;
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- std::move(single_request_handler)),
- CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id? */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
-
- subresource_loader_params_ =
- interceptor->MaybeCreateSubresourceLoaderParams();
-
- return;
- }
-
- // Before falling back to the next interceptor, see if |interceptor| still
- // wants to give additional info to the frame for subresource loading. In
- // that case we will just fall back to the default loader (i.e. won't go on
- // to the next interceptors) but send the subresource_loader_params to the
- // child process. This is necessary for correctness in the cases where, e.g.
- // there's a controlling ServiceWorker that doesn't handle main resource
- // loading, but may still want to control the page and/or handle subresource
- // loading. In that case we want to skip AppCache.
- if (interceptor) {
- subresource_loader_params_ =
- interceptor->MaybeCreateSubresourceLoaderParams();
-
- // If non-null |subresource_loader_params_| is returned, make sure
- // we skip the next interceptors.
- if (subresource_loader_params_)
- interceptor_index_ = interceptors_.size();
- }
-
- // See if the next interceptor wants to handle the request.
- if (interceptor_index_ < interceptors_.size()) {
- auto* next_interceptor = interceptors_[interceptor_index_++].get();
- next_interceptor->MaybeCreateLoader(
- *resource_request_, resource_context_,
- base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
- base::Unretained(this), next_interceptor));
- return;
- }
-
- // If we already have the default |url_loader_| we must come here after
- // a redirect. No interceptors wanted to intercept the redirected request,
- // so let it just follow the redirect.
- if (url_loader_) {
- DCHECK(!redirect_info_.new_url.is_empty());
- url_loader_->FollowRedirect();
- return;
- }
-
- // TODO(https://crbug.com/796425): We temporarily wrap raw
- // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
- // further refactor the factory getters to avoid this.
- scoped_refptr<network::SharedURLLoaderFactory> factory;
- DCHECK_EQ(interceptors_.size(), interceptor_index_);
-
- // If NetworkService is not enabled (which means we come here because one of
- // the loader interceptors is enabled), use the default request handler
- // instead of going through the NetworkService path.
- if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- DCHECK(!interceptors_.empty());
- DCHECK(default_request_handler_factory_);
- default_loader_used_ = true;
- // Update |request_info_| when following a redirect.
- if (url_chain_.size() > 0) {
- request_info_ = CreateNavigationRequestInfoForRedirect(
- *request_info_, *resource_request_);
- }
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- default_request_handler_factory_.Run()),
- CreateURLLoaderThrottles(), frame_tree_node_id_, 0 /* request_id */,
- network::mojom::kURLLoadOptionNone, resource_request_.get(),
- this /* client */, kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
- }
-
- if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
- factory = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
- default_url_loader_factory_getter_->GetBlobFactory());
- } else if (!IsURLHandledByNetworkService(resource_request_->url) &&
- !resource_request_->url.SchemeIs(url::kDataScheme)) {
- if (known_schemes_.find(resource_request_->url.scheme()) ==
- known_schemes_.end()) {
- bool handled = GetContentClient()->browser()->HandleExternalProtocol(
- resource_request_->url, web_contents_getter_,
- ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
- resource_request_->resource_type == RESOURCE_TYPE_MAIN_FRAME,
- static_cast<ui::PageTransition>(resource_request_->transition_type),
- resource_request_->has_user_gesture);
- factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- base::BindOnce(UnknownSchemeCallback, handled));
- } else {
- network::mojom::URLLoaderFactoryPtr& non_network_factory =
- non_network_url_loader_factories_[resource_request_->url.scheme()];
- if (!non_network_factory.is_bound()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderNetworkService ::
- BindNonNetworkURLLoaderFactoryRequest,
- owner_, frame_tree_node_id_,
- resource_request_->url,
- mojo::MakeRequest(&non_network_factory)));
- }
- factory = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
- non_network_factory.get());
- }
- } else {
- default_loader_used_ = true;
-
- // NOTE: We only support embedders proxying network-service-bound requests
- // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
- // or AppCache). Hence this code is only reachable when one of the above
- // interceptors isn't used and the URL is either a data URL or has a
- // scheme which is handled by the network service. We explicitly avoid
- // proxying the data URL case here.
- if (proxied_factory_request_.is_pending() &&
- !resource_request_->url.SchemeIs(url::kDataScheme)) {
- DCHECK(proxied_factory_info_.is_valid());
- // We don't worry about reconnection since it's a single navigation.
- default_url_loader_factory_getter_->CloneNetworkFactory(
- std::move(proxied_factory_request_));
- factory = base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
- std::move(proxied_factory_info_));
- } else {
- factory = default_url_loader_factory_getter_->GetNetworkFactory();
- }
- }
- url_chain_.push_back(resource_request_->url);
- uint32_t options = GetURLLoaderOptions(resource_request_->resource_type ==
- RESOURCE_TYPE_MAIN_FRAME);
- url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
- factory, CreateURLLoaderThrottles(), frame_tree_node_id_,
- 0 /* request_id? */, options, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- }
-
- void FollowRedirect() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!redirect_info_.new_url.is_empty());
-
- if (!IsLoaderInterceptionEnabled()) {
- url_loader_->FollowRedirect();
- return;
- }
-
- // Update |resource_request_| and call Restart to give our |interceptors_| a
- // chance at handling the new location. If no interceptor wants to take
- // over, we'll use the existing url_loader to follow the redirect, see
- // MaybeStartLoader.
- // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
- // there likely remains more to be done.
- // a. For subframe navigations, the Origin header may need to be modified
- // differently?
- // b. How should redirect_info_.referred_token_binding_host be handled?
-
- bool should_clear_upload = false;
- net::RedirectUtil::UpdateHttpRequest(
- resource_request_->url, resource_request_->method, redirect_info_,
- &resource_request_->headers, &should_clear_upload);
- if (should_clear_upload) {
- // The request body is no longer applicable.
- resource_request_->request_body = nullptr;
- blob_handles_.clear();
- }
-
- resource_request_->url = redirect_info_.new_url;
- resource_request_->method = redirect_info_.new_method;
- resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
- resource_request_->referrer = GURL(redirect_info_.new_referrer);
- resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
- url_chain_.push_back(redirect_info_.new_url);
-
- Restart();
- }
-
- base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
- return std::move(subresource_loader_params_);
- }
-
- private:
- // network::mojom::URLLoaderClient implementation:
- void OnReceiveResponse(
- const network::ResourceResponseHead& head,
- network::mojom::DownloadedTempFilePtr downloaded_file) override {
- received_response_ = true;
-
- // If the default loader (network) was used to handle the URL load request
- // we need to see if the interceptors want to potentially create a new
- // loader for the response. e.g. AppCache.
- if (MaybeCreateLoaderForResponse(head))
- return;
-
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
-
- // Currently only plugin handlers may intercept the response. Don't treat
- // the response as download if it has been handled by plugins.
- bool response_intercepted = false;
- if (url_loader_) {
- url_loader_client_endpoints = url_loader_->Unbind();
- response_intercepted = url_loader_->response_intercepted();
- } else {
- url_loader_client_endpoints =
- network::mojom::URLLoaderClientEndpoints::New(
- response_url_loader_.PassInterface(),
- response_loader_binding_.Unbind());
- }
-
- scoped_refptr<network::ResourceResponse> response(
- new network::ResourceResponse());
- response->head = head;
-
- bool is_download;
- bool is_stream;
- std::unique_ptr<NavigationData> cloned_navigation_data;
- if (IsLoaderInterceptionEnabled()) {
- is_download = !response_intercepted &&
- IsDownload(*response.get(), url_, url_chain_,
- initiator_origin_, suggested_filename_);
- is_stream = false;
- } else {
- ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
- net::URLRequest* url_request = rdh->GetURLRequest(global_request_id_);
-
- // The |url_request| maybe have been removed from the resource dispatcher
- // host during the time it took for OnReceiveResponse() to be received. In
- // this case, it means the request has been canceled.
- // See https://crbug.com/828156.
- if (!url_request) {
- OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
- return;
- }
-
- ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(url_request);
- is_download = !response_intercepted && info->IsDownload();
- is_stream = info->is_stream();
- if (rdh->delegate()) {
- NavigationData* navigation_data =
- rdh->delegate()->GetNavigationData(url_request);
-
- // Clone the embedder's NavigationData before moving it to the UI
- // thread.
- if (navigation_data)
- cloned_navigation_data = navigation_data->Clone();
- }
-
- // This is similar to what is done in
- // ServiceWorkerControlleeHandler::MaybeCreateSubresourceLoaderParams().
- // It takes the matching ControllerServiceWorkerInfo (if any) associated
- // with the request. It will be sent to the renderer process and used to
- // intercept requests.
- // TODO(arthursonzogni): This is needed only for the non-S13nServiceWorker
- // case. The S13nServiceWorker case is still not supported without the
- // NetworkService. This block needs to be updated once support for it will
- // be added.
- ServiceWorkerProviderHost* sw_provider_host =
- ServiceWorkerRequestHandler::GetProviderHost(url_request);
- if (sw_provider_host && sw_provider_host->controller()) {
- subresource_loader_params_ = SubresourceLoaderParams();
- subresource_loader_params_->controller_service_worker_info =
- mojom::ControllerServiceWorkerInfo::New();
- subresource_loader_params_->controller_service_worker_info
- ->object_info = sw_provider_host->GetOrCreateServiceWorkerHandle(
- sw_provider_host->controller());
- }
- }
-
- // Make a copy of the ResourceResponse before it is passed to another
- // thread.
- //
- // TODO(davidben): This copy could be avoided if ResourceResponse weren't
- // reference counted and the loader stack passed unique ownership of the
- // response. https://crbug.com/416050
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderNetworkService::OnReceiveResponse,
- owner_, response->DeepCopy(),
- std::move(url_loader_client_endpoints),
- std::move(cloned_navigation_data), global_request_id_,
- is_download, is_stream, std::move(downloaded_file)));
- }
-
- void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& head) override {
- if (--redirect_limit_ == 0) {
- OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_TOO_MANY_REDIRECTS));
- return;
- }
-
- // Store the redirect_info for later use in FollowRedirect where we give
- // our interceptors_ a chance to intercept the request for the new location.
- redirect_info_ = redirect_info;
-
- scoped_refptr<network::ResourceResponse> response(
- new network::ResourceResponse());
- response->head = head;
- url_ = redirect_info.new_url;
-
- // Make a copy of the ResourceResponse before it is passed to another
- // thread.
- //
- // TODO(davidben): This copy could be avoided if ResourceResponse weren't
- // reference counted and the loader stack passed unique ownership of the
- // response. https://crbug.com/416050
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderNetworkService::OnReceiveRedirect,
- owner_, redirect_info, response->DeepCopy()));
- }
-
- void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
- void OnUploadProgress(int64_t current_position,
- int64_t total_size,
- OnUploadProgressCallback callback) override {}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
- void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
-
- void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle) override {
- // Not reached. At this point, the loader and client endpoints must have
- // been unbound and forwarded to the renderer.
- CHECK(false);
- }
-
- void OnComplete(const network::URLLoaderCompletionStatus& status) override {
- UMA_HISTOGRAM_BOOLEAN(
- "Navigation.URLLoaderNetworkService.OnCompleteHadSSLInfo",
- status.ssl_info.has_value());
- if (status.ssl_info.has_value()) {
- UMA_HISTOGRAM_MEMORY_KB(
- "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
- GetCertificateChainsSizeInKB(status.ssl_info.value()));
- }
-
- if (status.error_code != net::OK && !received_response_) {
- // If the default loader (network) was used to handle the URL load
- // request we need to see if the interceptors want to potentially create a
- // new loader for the response. e.g. AppCache.
- if (MaybeCreateLoaderForResponse(network::ResourceResponseHead()))
- return;
- }
- status_ = status;
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&NavigationURLLoaderNetworkService::OnComplete, owner_,
- status));
- }
-
- // Returns true if an interceptor wants to handle the response, i.e. return a
- // different response. For e.g. AppCache may have fallback content.
- bool MaybeCreateLoaderForResponse(
- const network::ResourceResponseHead& response) {
- if (!IsLoaderInterceptionEnabled())
- return false;
-
- if (!default_loader_used_)
- return false;
-
- for (auto& interceptor : interceptors_) {
- network::mojom::URLLoaderClientRequest response_client_request;
- if (interceptor->MaybeCreateLoaderForResponse(
- response, &response_url_loader_, &response_client_request,
- url_loader_.get())) {
- response_loader_binding_.Bind(std::move(response_client_request));
- default_loader_used_ = false;
- url_loader_.reset();
- return true;
- }
- }
- return false;
- }
-
- std::vector<std::unique_ptr<content::URLLoaderThrottle>>
- CreateURLLoaderThrottles() {
- return GetContentClient()->browser()->CreateURLLoaderThrottles(
- *resource_request_, resource_context_, web_contents_getter_,
- navigation_ui_data_.get(), frame_tree_node_id_);
- }
-
- std::unique_ptr<NavigationLoaderInterceptor> CreateServiceWorkerInterceptor(
- const NavigationRequestInfo& request_info,
- ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core)
- const {
- const ResourceType resource_type = request_info.is_main_frame
- ? RESOURCE_TYPE_MAIN_FRAME
- : RESOURCE_TYPE_SUB_FRAME;
- network::mojom::RequestContextFrameType frame_type =
- request_info.is_main_frame
- ? network::mojom::RequestContextFrameType::kTopLevel
- : network::mojom::RequestContextFrameType::kNested;
- storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
- GetChromeBlobStorageContextForResourceContext(resource_context_));
- return ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
- *resource_request_, resource_context_,
- service_worker_navigation_handle_core, blob_storage_context,
- request_info.begin_params->skip_service_worker, resource_type,
- request_info.begin_params->request_context_type, frame_type,
- request_info.are_ancestors_secure, request_info.common_params.post_data,
- web_contents_getter_);
- }
-
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
- size_t interceptor_index_ = 0;
-
- std::unique_ptr<network::ResourceRequest> resource_request_;
- // Non-NetworkService: |request_info_| is updated along with
- // |resource_request_| on redirects.
- std::unique_ptr<NavigationRequestInfo> request_info_;
- int frame_tree_node_id_ = 0;
- GlobalRequestID global_request_id_;
- net::RedirectInfo redirect_info_;
- int redirect_limit_ = net::URLRequest::kMaxRedirects;
- ResourceContext* resource_context_;
- base::Callback<WebContents*()> web_contents_getter_;
- std::unique_ptr<NavigationUIData> navigation_ui_data_;
- scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
-
- std::unique_ptr<ThrottlingURLLoader> url_loader_;
-
- BlobHandles blob_handles_;
- std::vector<GURL> url_chain_;
-
- // Current URL that is being navigated, updated after redirection.
- GURL url_;
-
- base::Optional<url::Origin> initiator_origin_;
-
- // If this request was triggered by an anchor tag with a download attribute,
- // the |suggested_filename_| will be the (possibly empty) value of said
- // attribute.
- base::Optional<std::string> suggested_filename_;
-
- // Currently used by the AppCache loader to pass its factory to the
- // renderer which enables it to handle subresources.
- base::Optional<SubresourceLoaderParams> subresource_loader_params_;
-
- // This is referenced only on the UI thread.
- base::WeakPtr<NavigationURLLoaderNetworkService> owner_;
-
- // Set to true if the default URLLoader (network service) was used for the
- // current navigation.
- bool default_loader_used_ = false;
-
- // URLLoaderClient binding for loaders created for responses received from the
- // network loader.
- mojo::Binding<network::mojom::URLLoaderClient> response_loader_binding_;
-
- // URLLoader instance for response loaders, i.e loaders created for handing
- // responses received from the network URLLoader.
- network::mojom::URLLoaderPtr response_url_loader_;
-
- // Set to true if we receive a valid response from a URLLoader, i.e.
- // URLLoaderClient::OnReceivedResponse() is called.
- bool received_response_ = false;
-
- bool started_ = false;
-
- // Lazily initialized and used in the case of non-network resource
- // navigations. Keyed by URL scheme.
- std::map<std::string, network::mojom::URLLoaderFactoryPtr>
- non_network_url_loader_factories_;
-
- // Non-NetworkService:
- // Generator of a request handler for sending request to the network. This
- // captures all of parameters to create a
- // SingleRequestURLLoaderFactory::RequestHandler. Used only when
- // NetworkService is disabled but IsLoaderInterceptionEnabled() is true.
- base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler()>
- default_request_handler_factory_;
-
- // The completion status if it has been received. This is needed to handle
- // the case that the response is intercepted by download, and OnComplete() is
- // already called while we are transferring the |url_loader_| and response
- // body to download code.
- base::Optional<network::URLLoaderCompletionStatus> status_;
-
- // Before creating this URLLoaderRequestController on UI thread, the embedder
- // may have elected to proxy the URLLoaderFactory request, in which case these
- // fields will contain input (info) and output (request) endpoints for the
- // proxy. If this controller is handling a request for which proxying is
- // supported, requests will be plumbed through these endpoints.
- //
- // Note that these are only used for requests that go to the Network Service.
- network::mojom::URLLoaderFactoryRequest proxied_factory_request_;
- network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info_;
-
- // The schemes that this loader can use. For anything else we'll try external
- // protocol handlers.
- std::set<std::string> known_schemes_;
-
- mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
-};
-
-// TODO(https://crbug.com/790734): pass |navigation_ui_data| along with the
-// request so that it could be modified.
-NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService(
- ResourceContext* resource_context,
- StoragePartition* storage_partition,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data,
- ServiceWorkerNavigationHandle* service_worker_navigation_handle,
- AppCacheNavigationHandle* appcache_handle,
- NavigationURLLoaderDelegate* delegate,
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
- initial_interceptors)
- : delegate_(delegate),
- allow_download_(request_info->common_params.allow_download),
- weak_factory_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- int frame_tree_node_id = request_info->frame_tree_node_id;
-
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
- "navigation", "Navigation timeToResponseStarted", this,
- request_info->common_params.navigation_start, "FrameTreeNode id",
- frame_tree_node_id);
-
- ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core =
- service_worker_navigation_handle
- ? service_worker_navigation_handle->core()
- : nullptr;
-
- AppCacheNavigationHandleCore* appcache_handle_core =
- appcache_handle ? appcache_handle->core() : nullptr;
-
- std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
- request_info.get(), frame_tree_node_id, allow_download_);
-
- if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- DCHECK(!request_controller_);
- request_controller_ = std::make_unique<URLLoaderRequestController>(
- /* initial_interceptors = */
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
- std::move(new_request), resource_context,
- /* default_url_factory_getter = */ nullptr,
- request_info->common_params.url,
- request_info->begin_params->initiator_origin,
- request_info->common_params.suggested_filename,
- /* proxied_url_loader_factory_request */ nullptr,
- /* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
- weak_factory_.GetWeakPtr());
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &URLLoaderRequestController::StartWithoutNetworkService,
- base::Unretained(request_controller_.get()),
- base::RetainedRef(storage_partition->GetURLRequestContext()),
- base::Unretained(storage_partition->GetFileSystemContext()),
- base::Unretained(service_worker_navigation_handle_core),
- base::Unretained(appcache_handle_core), std::move(request_info),
- std::move(navigation_ui_data)));
- return;
- }
-
- // Check if a web UI scheme wants to handle this request.
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id);
- network::mojom::URLLoaderFactoryPtrInfo factory_for_webui;
- const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
- std::string scheme = new_request->url.scheme();
- if (std::find(schemes.begin(), schemes.end(), scheme) != schemes.end()) {
- factory_for_webui = CreateWebUIURLLoaderBinding(
- frame_tree_node->current_frame_host(), scheme)
- .PassInterface();
- }
-
- network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
- network::mojom::URLLoaderFactoryRequest proxied_factory_request;
- if (frame_tree_node) {
- // |frame_tree_node| may be null in some unit test environments.
- GetContentClient()
- ->browser()
- ->RegisterNonNetworkNavigationURLLoaderFactories(
- frame_tree_node->current_frame_host(),
- &non_network_url_loader_factories_);
-
- // The embedder may want to proxy all network-bound URLLoaderFactory
- // requests that it can. If it elects to do so, we'll pass its proxy
- // endpoints off to the URLLoaderRequestController where wthey will be
- // connected if the request type supports proxying.
- network::mojom::URLLoaderFactoryPtrInfo factory_info;
- auto factory_request = mojo::MakeRequest(&factory_info);
- bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
- frame_tree_node->current_frame_host(), true /* is_navigation */,
- &factory_request);
- if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
- frame_tree_node->current_frame_host(), true, &factory_request)) {
- use_proxy = true;
- }
- if (use_proxy) {
- proxied_factory_request = std::move(factory_request);
- proxied_factory_info = std::move(factory_info);
- }
- }
-
- auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
- non_network_url_loader_factories_[url::kFileScheme] =
- std::make_unique<FileURLLoaderFactory>(
- partition->browser_context()->GetPath(),
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
- std::set<std::string> known_schemes;
- for (auto& iter : non_network_url_loader_factories_)
- known_schemes.insert(iter.first);
-
- DCHECK(!request_controller_);
- request_controller_ = std::make_unique<URLLoaderRequestController>(
- std::move(initial_interceptors), std::move(new_request), resource_context,
- partition->url_loader_factory_getter(), request_info->common_params.url,
- request_info->begin_params->initiator_origin,
- request_info->common_params.suggested_filename,
- std::move(proxied_factory_request), std::move(proxied_factory_info),
- std::move(known_schemes), weak_factory_.GetWeakPtr());
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &URLLoaderRequestController::Start,
- base::Unretained(request_controller_.get()),
- base::RetainedRef(storage_partition->GetURLRequestContext()),
- service_worker_navigation_handle_core, appcache_handle_core,
- std::move(request_info), std::move(navigation_ui_data),
- std::move(factory_for_webui), frame_tree_node_id,
- ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
-}
-
-NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {
- BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
- request_controller_.release());
-}
-
-void NavigationURLLoaderNetworkService::FollowRedirect() {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&URLLoaderRequestController::FollowRedirect,
- base::Unretained(request_controller_.get())));
-}
-
-void NavigationURLLoaderNetworkService::ProceedWithResponse() {}
-
-void NavigationURLLoaderNetworkService::OnReceiveResponse(
- scoped_refptr<network::ResourceResponse> response,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- std::unique_ptr<NavigationData> navigation_data,
- const GlobalRequestID& global_request_id,
- bool is_download,
- bool is_stream,
- network::mojom::DownloadedTempFilePtr downloaded_file) {
- TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
- "&NavigationURLLoaderNetworkService", this, "success",
- true);
-
- // TODO(scottmg): This needs to do more of what
- // NavigationResourceHandler::OnResponseStarted() does.
-
- delegate_->OnResponseStarted(
- std::move(response), std::move(url_loader_client_endpoints), nullptr,
- std::move(navigation_data), global_request_id,
- allow_download_ && is_download, is_stream,
- request_controller_->TakeSubresourceLoaderParams());
-}
-
-void NavigationURLLoaderNetworkService::OnReceiveRedirect(
- const net::RedirectInfo& redirect_info,
- scoped_refptr<network::ResourceResponse> response) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- delegate_->OnRequestRedirected(redirect_info, std::move(response));
-}
-
-void NavigationURLLoaderNetworkService::OnComplete(
- const network::URLLoaderCompletionStatus& status) {
- if (status.error_code == net::OK)
- return;
-
- TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
- "&NavigationURLLoaderNetworkService", this, "success",
- false);
-
- delegate_->OnRequestFailed(status.exists_in_cache, status.error_code,
- status.ssl_info);
-}
-
-void NavigationURLLoaderNetworkService::OnRequestStarted(
- base::TimeTicks timestamp) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- delegate_->OnRequestStarted(timestamp);
-}
-
-void NavigationURLLoaderNetworkService::BindNonNetworkURLLoaderFactoryRequest(
- int frame_tree_node_id,
- const GURL& url,
- network::mojom::URLLoaderFactoryRequest factory) {
- auto it = non_network_url_loader_factories_.find(url.scheme());
- if (it == non_network_url_loader_factories_.end()) {
- DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec();
- return;
- }
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id);
- GetContentClient()->browser()->WillCreateURLLoaderFactory(
- frame_tree_node->current_frame_host(), true /* is_navigation */,
- &factory);
- it->second->Clone(std::move(factory));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_network_service.h b/chromium/content/browser/loader/navigation_url_loader_network_service.h
deleted file mode 100644
index 7a3ee671914..00000000000
--- a/chromium/content/browser/loader/navigation_url_loader_network_service.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2017 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_LOADER_NAVIGATION_URL_LOADER_NETWORK_SERVICE_H_
-#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_NETWORK_SERVICE_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "base/time/time.h"
-#include "content/browser/loader/navigation_url_loader.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/ssl_status.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-
-namespace net {
-struct RedirectInfo;
-}
-
-namespace content {
-
-class NavigationData;
-class NavigationPostDataHandler;
-class ResourceContext;
-class StoragePartition;
-class NavigationLoaderInterceptor;
-struct GlobalRequestID;
-
-// This is an implementation of NavigationURLLoader used when
-// --enable-features=NetworkService is used.
-class CONTENT_EXPORT NavigationURLLoaderNetworkService
- : public NavigationURLLoader {
- public:
- // The caller is responsible for ensuring that |delegate| outlives the loader.
- // Note |initial_interceptors| is there for test purposes only.
- NavigationURLLoaderNetworkService(
- ResourceContext* resource_context,
- StoragePartition* storage_partition,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data,
- ServiceWorkerNavigationHandle* service_worker_handle,
- AppCacheNavigationHandle* appcache_handle,
- NavigationURLLoaderDelegate* delegate,
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
- initial_interceptors);
- ~NavigationURLLoaderNetworkService() override;
-
- // NavigationURLLoader implementation:
- void FollowRedirect() override;
- void ProceedWithResponse() override;
-
- void OnReceiveResponse(
- scoped_refptr<network::ResourceResponse> response,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- std::unique_ptr<NavigationData> navigation_data,
- const GlobalRequestID& global_request_id,
- bool is_download,
- bool is_stream,
- network::mojom::DownloadedTempFilePtr downloaded_file);
- void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
- scoped_refptr<network::ResourceResponse> response);
- void OnComplete(const network::URLLoaderCompletionStatus& status);
-
- private:
- class URLLoaderRequestController;
- void OnRequestStarted(base::TimeTicks timestamp);
-
- void BindNonNetworkURLLoaderFactoryRequest(
- int frame_tree_node_id,
- const GURL& url,
- network::mojom::URLLoaderFactoryRequest factory);
-
- NavigationURLLoaderDelegate* delegate_;
-
- // Lives on the IO thread.
- std::unique_ptr<URLLoaderRequestController> request_controller_;
-
- bool allow_download_;
-
- // Factories to handle navigation requests for non-network resources.
- ContentBrowserClient::NonNetworkURLLoaderFactoryMap
- non_network_url_loader_factories_;
-
- base::WeakPtrFactory<NavigationURLLoaderNetworkService> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderNetworkService);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_NETWORK_SERVICE_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index a4ee76574ab..ea806d87222 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -10,21 +10,17 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
+#include "base/unguessable_token.h"
#include "content/browser/frame_host/navigation_request_info.h"
-#include "content/browser/loader/navigation_url_loader_impl.h"
+#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/test_resource_handler.h"
#include "content/browser/loader_delegate_impl.h"
-#include "content/browser/streams/stream.h"
-#include "content/browser/streams/stream_context.h"
-#include "content/browser/streams/stream_registry.h"
-#include "content/browser/streams/stream_url_request_job.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/stream_handle.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -49,27 +45,6 @@ namespace content {
namespace {
-class StreamProtocolHandler
- : public net::URLRequestJobFactory::ProtocolHandler {
- public:
- StreamProtocolHandler(StreamRegistry* registry) : registry_(registry) {}
-
- // net::URLRequestJobFactory::ProtocolHandler implementation.
- net::URLRequestJob* MaybeCreateJob(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const override {
- scoped_refptr<Stream> stream = registry_->GetStream(request->url());
- if (stream.get())
- return new StreamURLRequestJob(request, network_delegate, stream);
- return nullptr;
- }
-
- private:
- StreamRegistry* registry_;
-
- DISALLOW_COPY_AND_ASSIGN(StreamProtocolHandler);
-};
-
std::unique_ptr<ResourceHandler> CreateTestResourceHandler(
net::URLRequest* request) {
return std::make_unique<TestResourceHandler>();
@@ -90,12 +65,9 @@ class NavigationURLLoaderTest : public testing::Test {
base::RunLoop().RunUntilIdle();
net::URLRequestContext* request_context =
browser_context_->GetResourceContext()->GetRequestContext();
- // Attach URLRequestTestJob and make streams work.
+ // Attach URLRequestTestJob.
job_factory_.SetProtocolHandler(
"test", net::URLRequestTestJob::CreateProtocolHandler());
- job_factory_.SetProtocolHandler(
- "blob", std::make_unique<StreamProtocolHandler>(
- StreamContext::GetFor(browser_context_.get())->registry()));
request_context->set_job_factory(&job_factory_);
}
@@ -123,7 +95,7 @@ class NavigationURLLoaderTest : public testing::Test {
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, std::move(begin_params), url,
true, false, false, -1, false, false, false,
- nullptr));
+ nullptr, base::UnguessableToken::Create()));
return NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
@@ -183,7 +155,8 @@ TEST_F(NavigationURLLoaderTest, RequestFailedCertError) {
ASSERT_EQ(net::ERR_ABORTED, delegate.net_error());
net::SSLInfo ssl_info = delegate.ssl_info();
EXPECT_TRUE(ssl_info.is_valid());
- EXPECT_TRUE(https_server.GetCertificate()->Equals(ssl_info.cert.get()));
+ EXPECT_TRUE(
+ https_server.GetCertificate()->EqualsExcludingChain(ssl_info.cert.get()));
EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID,
net::MapCertStatusToNetError(ssl_info.cert_status));
EXPECT_FALSE(ssl_info.is_fatal_cert_error);
@@ -215,7 +188,8 @@ TEST_F(NavigationURLLoaderTest, RequestFailedCertErrorFatal) {
ASSERT_EQ(net::ERR_ABORTED, delegate.net_error());
net::SSLInfo ssl_info = delegate.ssl_info();
EXPECT_TRUE(ssl_info.is_valid());
- EXPECT_TRUE(https_server.GetCertificate()->Equals(ssl_info.cert.get()));
+ EXPECT_TRUE(
+ https_server.GetCertificate()->EqualsExcludingChain(ssl_info.cert.get()));
EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID,
net::MapCertStatusToNetError(ssl_info.cert_status));
EXPECT_TRUE(ssl_info.is_fatal_cert_error);
@@ -259,7 +233,7 @@ TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
// response body was received.
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(net::URLRequestTestJob::ProcessOnePendingMessage());
- EXPECT_FALSE(delegate.body());
+ EXPECT_FALSE(delegate.has_url_loader_client_endpoints());
}
// Tests that the loader may be canceled by context.
@@ -280,7 +254,8 @@ TEST_F(NavigationURLLoaderTest, CancelByContext) {
EXPECT_EQ(1, delegate.on_request_handled_counter());
}
-// Tests that the request is owned by the body StreamHandle.
+// Tests that the request stays alive as long as the URLLoaderClient endpoints
+// are not destructed.
TEST_F(NavigationURLLoaderTest, OwnedByHandle) {
// Fake a top-level request to a URL whose body does not load immediately.
TestNavigationURLLoaderDelegate delegate;
@@ -293,8 +268,8 @@ TEST_F(NavigationURLLoaderTest, OwnedByHandle) {
// Proceed with the response.
loader->ProceedWithResponse();
- // Release the body.
- delegate.ReleaseBody();
+ // Release the URLLoaderClient endpoints.
+ delegate.ReleaseURLLoaderClientEndpoints();
base::RunLoop().RunUntilIdle();
// Verify that URLRequestTestJob no longer has anything paused.
diff --git a/chromium/content/browser/loader/prefetch_url_loader.cc b/chromium/content/browser/loader/prefetch_url_loader.cc
index a9b0fa9cc26..c0d59319dd0 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader.cc
@@ -5,6 +5,7 @@
#include "content/browser/loader/prefetch_url_loader.h"
#include "base/feature_list.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/browser/web_package/web_package_prefetch_handler.h"
#include "content/public/common/content_features.h"
#include "net/url_request/url_request_context_getter.h"
@@ -17,7 +18,7 @@ PrefetchURLLoader::PrefetchURLLoader(
int32_t routing_id,
int32_t request_id,
uint32_t options,
- int frame_tree_node_id,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
@@ -25,7 +26,9 @@ PrefetchURLLoader::PrefetchURLLoader(
URLLoaderThrottlesGetter url_loader_throttles_getter,
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter)
- : frame_tree_node_id_(frame_tree_node_id),
+ : frame_tree_node_id_getter_(frame_tree_node_id_getter),
+ url_(resource_request.url),
+ report_raw_headers_(resource_request.report_raw_headers),
network_loader_factory_(std::move(network_loader_factory)),
client_binding_(this),
forwarding_client_(std::move(client)),
@@ -48,7 +51,11 @@ PrefetchURLLoader::PrefetchURLLoader(
PrefetchURLLoader::~PrefetchURLLoader() = default;
-void PrefetchURLLoader::FollowRedirect() {
+void PrefetchURLLoader::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
+ "headers was not supported "
+ "yet. crbug.com/845683";
if (web_package_prefetch_handler_) {
// Rebind |client_binding_| and |loader_|.
client_binding_.Bind(web_package_prefetch_handler_->FollowRedirect(
@@ -56,7 +63,7 @@ void PrefetchURLLoader::FollowRedirect() {
return;
}
- loader_->FollowRedirect();
+ loader_->FollowRedirect(base::nullopt);
}
void PrefetchURLLoader::ProceedWithResponse() {
@@ -79,16 +86,16 @@ void PrefetchURLLoader::ResumeReadingBodyFromNet() {
void PrefetchURLLoader::OnReceiveResponse(
const network::ResourceResponseHead& response,
network::mojom::DownloadedTempFilePtr downloaded_file) {
- if (WebPackagePrefetchHandler::IsResponseForWebPackage(response)) {
+ if (signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(url_, response)) {
DCHECK(!web_package_prefetch_handler_);
// Note that after this point this doesn't directly get upcalls from the
// network. (Until |this| calls the handler's FollowRedirect.)
web_package_prefetch_handler_ = std::make_unique<WebPackagePrefetchHandler>(
- frame_tree_node_id_, response, std::move(loader_),
- client_binding_.Unbind(), network_loader_factory_, request_initiator_,
- url_loader_throttles_getter_, resource_context_,
- request_context_getter_, this);
+ frame_tree_node_id_getter_, report_raw_headers_, response,
+ std::move(loader_), client_binding_.Unbind(), network_loader_factory_,
+ request_initiator_, url_, url_loader_throttles_getter_,
+ resource_context_, request_context_getter_, this);
return;
}
forwarding_client_->OnReceiveResponse(response, std::move(downloaded_file));
diff --git a/chromium/content/browser/loader/prefetch_url_loader.h b/chromium/content/browser/loader/prefetch_url_loader.h
index 7522e0484b5..3a63bb0c4cc 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.h
+++ b/chromium/content/browser/loader/prefetch_url_loader.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/callback.h"
#include "base/macros.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -41,11 +42,13 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
// |request_context_getter| may be used when a prefetch handler
// needs to additionally create a request (e.g. for fetching certificate
// if the prefetch was for a signed exchange).
+ // |frame_tree_node_id_getter| is called only on UI thread when NetworkService
+ // is not enabled, but can be also called on IO thread otherwise.
PrefetchURLLoader(
int32_t routing_id,
int32_t request_id,
uint32_t options,
- int frame_tree_node_id,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
@@ -57,7 +60,8 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
private:
// network::mojom::URLLoader overrides:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int intra_priority_value) override;
@@ -87,7 +91,9 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
void OnNetworkConnectionError();
- const int frame_tree_node_id_;
+ const base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
+ const GURL url_;
+ const bool report_raw_headers_;
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.cc b/chromium/content/browser/loader/prefetch_url_loader_service.cc
index afaed7c6c25..a8c1638bf9e 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.cc
@@ -12,11 +12,11 @@
#include "content/public/common/content_client.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/url_loader_throttle.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
namespace content {
@@ -56,7 +56,7 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
- int frame_tree_node_id) {
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(RESOURCE_TYPE_PREFETCH, resource_request.resource_type);
DCHECK(resource_context_);
@@ -70,12 +70,12 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
// TODO(kinuko): Revisit this.
mojo::MakeStrongBinding(
std::make_unique<PrefetchURLLoader>(
- routing_id, request_id, options, frame_tree_node_id, resource_request,
- std::move(client), traffic_annotation,
+ routing_id, request_id, options, frame_tree_node_id_getter,
+ resource_request, std::move(client), traffic_annotation,
std::move(network_loader_factory),
base::BindRepeating(
&PrefetchURLLoaderService::CreateURLLoaderThrottles, this,
- resource_request, frame_tree_node_id),
+ resource_request, frame_tree_node_id_getter),
resource_context_, request_context_getter_),
std::move(request));
}
@@ -100,10 +100,11 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
int frame_tree_node_id = loader_factory_bindings_.dispatch_context();
- CreateLoaderAndStart(std::move(request), routing_id, request_id, options,
- resource_request, std::move(client), traffic_annotation,
- loader_factory_getter_->GetNetworkFactory(),
- frame_tree_node_id);
+ CreateLoaderAndStart(
+ std::move(request), routing_id, request_id, options, resource_request,
+ std::move(client), traffic_annotation,
+ loader_factory_getter_->GetNetworkFactory(),
+ base::BindRepeating([](int id) { return id; }, frame_tree_node_id));
}
void PrefetchURLLoaderService::Clone(
@@ -116,12 +117,12 @@ void PrefetchURLLoaderService::Clone(
std::vector<std::unique_ptr<content::URLLoaderThrottle>>
PrefetchURLLoaderService::CreateURLLoaderThrottles(
const network::ResourceRequest& request,
- int frame_tree_node_id) {
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter) {
if (!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
!request_context_getter_ ||
!request_context_getter_->GetURLRequestContext())
return std::vector<std::unique_ptr<content::URLLoaderThrottle>>();
-
+ int frame_tree_node_id = frame_tree_node_id_getter.Run();
return GetContentClient()->browser()->CreateURLLoaderThrottles(
request, resource_context_,
base::BindRepeating(&WebContents::FromFrameTreeNodeId,
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.h b/chromium/content/browser/loader/prefetch_url_loader_service.h
index 2d6c020ef45..6573ee69d52 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.h
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.h
@@ -63,7 +63,7 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
- int frame_tree_node_id = -1);
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
// Register a callback that is fired right before a prefetch load is started
// by this service.
@@ -93,8 +93,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
// For URLLoaderThrottlesGetter.
std::vector<std::unique_ptr<content::URLLoaderThrottle>>
- CreateURLLoaderThrottles(const network::ResourceRequest& request,
- int frame_tree_node_id);
+ CreateURLLoaderThrottles(
+ const network::ResourceRequest& request,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
mojo::BindingSet<blink::mojom::PrefetchURLLoaderService,
int /* frame_tree_node_id */>
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 6c35edcd265..1c1fb59e02c 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -23,7 +23,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
@@ -47,8 +46,6 @@
#include "content/browser/loader/loader_delegate.h"
#include "content/browser/loader/mime_sniffing_resource_handler.h"
#include "content/browser/loader/mojo_async_resource_handler.h"
-#include "content/browser/loader/navigation_resource_handler.h"
-#include "content/browser/loader/navigation_url_loader_impl_core.h"
#include "content/browser/loader/null_resource_controller.h"
#include "content/browser/loader/redirect_to_file_resource_handler.h"
#include "content/browser/loader/resource_loader.h"
@@ -67,6 +64,7 @@
#include "content/browser/streams/stream_context.h"
#include "content/browser/streams/stream_registry.h"
#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_child_process_host.h"
@@ -80,7 +78,6 @@
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/browser/site_isolation_policy.h"
-#include "content/public/browser/stream_handle.h"
#include "content/public/browser/stream_info.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -335,7 +332,7 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl(
create_download_handler_intercept_(download_handler_intercept),
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
io_thread_task_runner_(io_thread_runner),
- weak_ptr_factory_(this) {
+ weak_factory_on_io_(this) {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
DCHECK(!g_resource_dispatcher_host);
g_resource_dispatcher_host = this;
@@ -447,7 +444,6 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
(loader->GetRequestInfo()->detachable_handler() &&
loader->GetRequestInfo()->detachable_handler()->is_detached()) ||
loader->GetRequestInfo()->requester_info()->IsBrowserSideNavigation() ||
- loader->is_transferring() ||
loader->GetRequestInfo()->GetResourceType() ==
RESOURCE_TYPE_SERVICE_WORKER);
}
@@ -552,7 +548,7 @@ scoped_refptr<LoginDelegate> ResourceDispatcherHostImpl::CreateLoginDelegate(
ResourceRequestInfoImpl* resource_request_info =
ResourceRequestInfoImpl::ForRequest(request);
DCHECK(resource_request_info);
- bool is_main_frame =
+ bool is_request_for_main_frame =
resource_request_info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME;
GlobalRequestID request_id = resource_request_info->GetGlobalRequestID();
@@ -561,9 +557,10 @@ scoped_refptr<LoginDelegate> ResourceDispatcherHostImpl::CreateLoginDelegate(
scoped_refptr<LoginDelegate> login_delegate =
GetContentClient()->browser()->CreateLoginDelegate(
auth_info, resource_request_info->GetWebContentsGetterForRequest(),
- is_main_frame, url, resource_request_info->first_auth_attempt(),
- base::Bind(&ResourceDispatcherHostImpl::RunAuthRequiredCallback,
- base::Unretained(this), request_id));
+ is_request_for_main_frame, url,
+ resource_request_info->first_auth_attempt(),
+ base::BindOnce(&ResourceDispatcherHostImpl::RunAuthRequiredCallback,
+ base::Unretained(this), request_id));
resource_request_info->set_first_auth_attempt(false);
@@ -693,6 +690,10 @@ void ResourceDispatcherHostImpl::OnShutdown() {
is_shutdown_ = true;
+ // Explicitly invalidate while on the IO thread, where the associated WeakPtrs
+ // are used.
+ weak_factory_on_io_.InvalidateWeakPtrs();
+
pending_loaders_.clear();
// Make sure we shutdown the timer now, otherwise by the time our destructor
@@ -749,132 +750,6 @@ bool ResourceDispatcherHostImpl::IsRequestIDInUse(
return false;
}
-void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
- ResourceRequesterInfo* requester_info,
- int route_id,
- int request_id,
- const network::ResourceRequest& request_data,
- LoaderMap::iterator iter,
- network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client) {
- DCHECK(requester_info->IsRenderer());
- int child_id = requester_info->child_id();
- ResourceRequestInfoImpl* info = iter->second->GetRequestInfo();
- GlobalFrameRoutingId old_routing_id(request_data.transferred_request_child_id,
- info->GetRenderFrameID());
- GlobalRequestID old_request_id(request_data.transferred_request_child_id,
- request_data.transferred_request_request_id);
- GlobalFrameRoutingId new_routing_id(child_id, request_data.render_frame_id);
- GlobalRequestID new_request_id(child_id, request_id);
-
- // Clear out data that depends on |info| before updating it.
- // We always need to move the memory stats to the new process. In contrast,
- // stats.num_requests is only tracked for some requests (those that require
- // file descriptors for their shared memory buffer).
- IncrementOutstandingRequestsMemory(-1, *info);
- bool should_update_count = info->counted_as_in_flight_request();
- if (should_update_count)
- IncrementOutstandingRequestsCount(-1, info);
-
- DCHECK(pending_loaders_.find(old_request_id) == iter);
- std::unique_ptr<ResourceLoader> loader = std::move(iter->second);
- ResourceLoader* loader_ptr = loader.get();
- pending_loaders_.erase(iter);
-
- // ResourceHandlers should always get state related to the request from the
- // ResourceRequestInfo rather than caching it locally. This lets us update
- // the info object when a transfer occurs.
- info->UpdateForTransfer(route_id, request_data.render_frame_id, request_id,
- requester_info, std::move(mojo_request),
- std::move(url_loader_client));
-
- // Update maps that used the old IDs, if necessary. Some transfers in tests
- // do not actually use a different ID, so not all maps need to be updated.
- pending_loaders_[new_request_id] = std::move(loader);
- IncrementOutstandingRequestsMemory(1, *info);
- if (should_update_count)
- IncrementOutstandingRequestsCount(1, info);
- if (old_routing_id != new_routing_id) {
- if (blocked_loaders_map_.find(old_routing_id) !=
- blocked_loaders_map_.end()) {
- blocked_loaders_map_[new_routing_id] =
- std::move(blocked_loaders_map_[old_routing_id]);
- blocked_loaders_map_.erase(old_routing_id);
- }
- }
-
- AppCacheInterceptor::CompleteCrossSiteTransfer(
- loader_ptr->request(), child_id, request_data.appcache_host_id,
- requester_info);
-
- ServiceWorkerRequestHandler* handler =
- ServiceWorkerRequestHandler::GetHandler(loader_ptr->request());
- if (handler) {
- if (!handler->SanityCheckIsSameContext(
- requester_info->service_worker_context())) {
- bad_message::ReceivedBadMessage(
- requester_info->filter(), bad_message::RDHI_WRONG_STORAGE_PARTITION);
- } else {
- handler->CompleteCrossSiteTransfer(
- child_id, request_data.service_worker_provider_id);
- }
- }
-}
-
-void ResourceDispatcherHostImpl::CompleteTransfer(
- ResourceRequesterInfo* requester_info,
- int request_id,
- const network::ResourceRequest& request_data,
- int route_id,
- network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client) {
- DCHECK(requester_info->IsRenderer());
- // Caller should ensure that |request_data| is associated with a transfer.
- DCHECK(request_data.transferred_request_child_id != -1 ||
- request_data.transferred_request_request_id != -1);
-
- if (!IsResourceTypeFrame(
- static_cast<ResourceType>(request_data.resource_type))) {
- // Transfers apply only to navigational requests - the renderer seems to
- // have sent bogus IPC data.
- bad_message::ReceivedBadMessage(
- requester_info->filter(),
- bad_message::RDH_TRANSFERRING_NONNAVIGATIONAL_REQUEST);
- return;
- }
-
- // Attempt to find a loader associated with the deferred transfer request.
- LoaderMap::iterator it = pending_loaders_.find(
- GlobalRequestID(request_data.transferred_request_child_id,
- request_data.transferred_request_request_id));
- if (it == pending_loaders_.end()) {
- // Renderer sent transferred_request_request_id and/or
- // transferred_request_child_id that doesn't have a corresponding entry on
- // the browser side.
- // TODO(lukasza): https://crbug.com/659613: Need to understand the scenario
- // that can lead here (and then attempt to reintroduce a renderer kill
- // below).
- return;
- }
- ResourceLoader* pending_loader = it->second.get();
-
- if (!pending_loader->is_transferring()) {
- // Renderer sent transferred_request_request_id and/or
- // transferred_request_child_id that doesn't correspond to an actually
- // transferring loader on the browser side.
- bad_message::ReceivedBadMessage(requester_info->filter(),
- bad_message::RDH_REQUEST_NOT_TRANSFERRING);
- return;
- }
-
- // If the request is transferring to a new process, we can update our
- // state and let it resume with its existing ResourceHandlers.
- UpdateRequestForTransfer(requester_info, route_id, request_id, request_data,
- it, std::move(mojo_request),
- std::move(url_loader_client));
- pending_loader->CompleteTransfer();
-}
-
void ResourceDispatcherHostImpl::BeginRequest(
ResourceRequesterInfo* requester_info,
int request_id,
@@ -887,6 +762,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
DCHECK(requester_info->IsRenderer() ||
requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
+
int child_id = requester_info->child_id();
// Reject request id that's currently in use.
@@ -899,13 +775,10 @@ void ResourceDispatcherHostImpl::BeginRequest(
return;
}
- // PlzNavigate: reject invalid renderer main resource request.
- bool is_navigation_stream_request =
- IsBrowserSideNavigationEnabled() &&
- IsResourceTypeFrame(
- static_cast<ResourceType>(request_data.resource_type));
- if (is_navigation_stream_request &&
- !request_data.resource_body_stream_url.SchemeIs(url::kBlobScheme)) {
+ // Reject main resource request. They are handled by the browser process and
+ // must not use this function.
+ if (IsResourceTypeFrame(
+ static_cast<ResourceType>(request_data.resource_type))) {
// The resource_type of navigation preload requests must be SUB_RESOURCE.
DCHECK(requester_info->IsRenderer());
bad_message::ReceivedBadMessage(requester_info->filter(),
@@ -928,15 +801,6 @@ void ResourceDispatcherHostImpl::BeginRequest(
// http://crbug.com/91398
DEBUG_ALIAS_FOR_GURL(url_buf, request_data.url);
- // If the request that's coming in is being transferred from another process,
- // we want to reuse and resume the old loader rather than start a new one.
- if (request_data.transferred_request_child_id != -1 ||
- request_data.transferred_request_request_id != -1) {
- CompleteTransfer(requester_info, request_id, request_data, route_id,
- std::move(mojo_request), std::move(url_loader_client));
- return;
- }
-
ResourceContext* resource_context = nullptr;
net::URLRequestContext* request_context = nullptr;
requester_info->GetContexts(
@@ -954,56 +818,54 @@ void ResourceDispatcherHostImpl::BeginRequest(
}
BlobHandles blob_handles;
- if (!is_navigation_stream_request) {
- storage::BlobStorageContext* blob_context =
- GetBlobStorageContext(requester_info->blob_storage_context());
- // Resolve elements from request_body and prepare upload data.
- if (request_data.request_body.get()) {
- // |blob_context| could be null when the request is from the plugins
- // because ResourceMessageFilters created in PluginProcessHost don't have
- // the blob context.
- if (blob_context) {
- // Get BlobHandles to request_body to prevent blobs and any attached
- // shareable files from being freed until upload completion. These data
- // will be used in UploadDataStream and ServiceWorkerURLRequestJob.
- if (!GetBodyBlobDataHandles(request_data.request_body.get(),
- resource_context, &blob_handles)) {
- AbortRequestBeforeItStarts(requester_info->filter(), request_id,
- std::move(url_loader_client));
- return;
- }
+ storage::BlobStorageContext* blob_context =
+ GetBlobStorageContext(requester_info->blob_storage_context());
+ // Resolve elements from request_body and prepare upload data.
+ if (request_data.request_body.get()) {
+ // |blob_context| could be null when the request is from the plugins
+ // because ResourceMessageFilters created in PluginProcessHost don't have
+ // the blob context.
+ if (blob_context) {
+ // Get BlobHandles to request_body to prevent blobs and any attached
+ // shareable files from being freed until upload completion. These data
+ // will be used in UploadDataStream and ServiceWorkerURLRequestJob.
+ if (!GetBodyBlobDataHandles(request_data.request_body.get(),
+ resource_context, &blob_handles)) {
+ AbortRequestBeforeItStarts(requester_info->filter(), request_id,
+ std::move(url_loader_client));
+ return;
}
}
+ }
- // Check if we have a registered interceptor for the headers passed in. If
- // yes then we need to mark the current request as pending and wait for the
- // interceptor to invoke the callback with a status code indicating whether
- // the request needs to be aborted or continued.
- for (net::HttpRequestHeaders::Iterator it(request_data.headers);
- it.GetNext();) {
- HeaderInterceptorMap::iterator index =
- http_header_interceptor_map_.find(it.name());
- if (index != http_header_interceptor_map_.end()) {
- HeaderInterceptorInfo& interceptor_info = index->second;
-
- bool call_interceptor = true;
- if (!interceptor_info.starts_with.empty()) {
- call_interceptor =
- base::StartsWith(it.value(), interceptor_info.starts_with,
- base::CompareCase::INSENSITIVE_ASCII);
- }
- if (call_interceptor) {
- interceptor_info.interceptor.Run(
- it.name(), it.value(), child_id, resource_context,
- base::Bind(
- &ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
- base::Unretained(this), base::WrapRefCounted(requester_info),
- request_id, request_data, is_sync_load, route_id,
- request_data.headers, base::Passed(std::move(mojo_request)),
- base::Passed(std::move(url_loader_client)),
- base::Passed(std::move(blob_handles)), traffic_annotation));
- return;
- }
+ // Check if we have a registered interceptor for the headers passed in. If
+ // yes then we need to mark the current request as pending and wait for the
+ // interceptor to invoke the callback with a status code indicating whether
+ // the request needs to be aborted or continued.
+ for (net::HttpRequestHeaders::Iterator it(request_data.headers);
+ it.GetNext();) {
+ HeaderInterceptorMap::iterator index =
+ http_header_interceptor_map_.find(it.name());
+ if (index != http_header_interceptor_map_.end()) {
+ HeaderInterceptorInfo& interceptor_info = index->second;
+
+ bool call_interceptor = true;
+ if (!interceptor_info.starts_with.empty()) {
+ call_interceptor =
+ base::StartsWith(it.value(), interceptor_info.starts_with,
+ base::CompareCase::INSENSITIVE_ASCII);
+ }
+ if (call_interceptor) {
+ interceptor_info.interceptor.Run(
+ it.name(), it.value(), child_id, resource_context,
+ base::Bind(
+ &ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
+ base::Unretained(this), base::WrapRefCounted(requester_info),
+ request_id, request_data, is_sync_load, route_id,
+ request_data.headers, base::Passed(std::move(mojo_request)),
+ base::Passed(std::move(url_loader_client)),
+ base::Passed(std::move(blob_handles)), traffic_annotation));
+ return;
}
}
}
@@ -1029,6 +891,12 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
DCHECK(requester_info->IsRenderer() ||
requester_info->IsNavigationPreload() ||
requester_info->IsCertificateFetcherForSignedExchange());
+ // The request is always for a subresource.
+ // The renderer process is killed in BeginRequest() when it happens with a
+ // main resource and the function returns immediatly.
+ DCHECK(!IsResourceTypeFrame(
+ static_cast<ResourceType>(request_data.resource_type)));
+
if (interceptor_result != HeaderInterceptorResult::CONTINUE) {
if (requester_info->IsRenderer() &&
interceptor_result == HeaderInterceptorResult::KILL) {
@@ -1046,11 +914,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
storage::BlobStorageContext* blob_context = nullptr;
bool do_not_prompt_for_login = false;
bool report_raw_headers = false;
+ bool report_security_info = false;
int load_flags = request_data.load_flags;
- bool is_navigation_stream_request =
- IsBrowserSideNavigationEnabled() &&
- IsResourceTypeFrame(
- static_cast<ResourceType>(request_data.resource_type));
ResourceContext* resource_context = nullptr;
net::URLRequestContext* request_context = nullptr;
@@ -1058,11 +923,9 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
static_cast<ResourceType>(request_data.resource_type), &resource_context,
&request_context);
- // Allow the observer to block/handle the request.
- if (delegate_ && !delegate_->ShouldBeginRequest(
- request_data.method, request_data.url,
- static_cast<ResourceType>(request_data.resource_type),
- resource_context)) {
+ // All PREFETCH requests should be GETs, but be defensive about it.
+ if (request_data.resource_type == RESOURCE_TYPE_PREFETCH &&
+ request_data.method != "GET") {
AbortRequestBeforeItStarts(requester_info->filter(), request_id,
std::move(url_loader_client));
return;
@@ -1070,124 +933,106 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
// Construct the request.
std::unique_ptr<net::URLRequest> new_request = request_context->CreateRequest(
- is_navigation_stream_request ? request_data.resource_body_stream_url
- : request_data.url,
- request_data.priority, nullptr, traffic_annotation);
-
- if (is_navigation_stream_request) {
- // PlzNavigate: Always set the method to GET when gaining access to the
- // stream that contains the response body of a navigation. Otherwise the
- // data that was already fetched by the browser will not be transmitted to
- // the renderer.
- new_request->set_method("GET");
- } else {
- // Log that this request is a service worker navigation preload request
- // here, since navigation preload machinery has no access to netlog.
- // TODO(falken): Figure out how network::mojom::URLLoaderClient can
- // access the request's netlog.
- if (requester_info->IsNavigationPreload()) {
- new_request->net_log().AddEvent(
- net::NetLogEventType::SERVICE_WORKER_NAVIGATION_PRELOAD_REQUEST);
- }
+ request_data.url, request_data.priority, nullptr, traffic_annotation);
- new_request->set_method(request_data.method);
- new_request->set_site_for_cookies(request_data.site_for_cookies);
- new_request->set_attach_same_site_cookies(
- request_data.attach_same_site_cookies);
-
- // The initiator should normally be present, unless this is a navigation.
- // Browser-initiated navigations don't have an initiator document, the
- // others have one.
- DCHECK(request_data.request_initiator.has_value() ||
- IsResourceTypeFrame(
- static_cast<ResourceType>(request_data.resource_type)));
- new_request->set_initiator(request_data.request_initiator);
-
- if (request_data.originated_from_service_worker) {
- new_request->SetUserData(URLRequestServiceWorkerData::kUserDataKey,
- std::make_unique<URLRequestServiceWorkerData>());
- }
+ // Log that this request is a service worker navigation preload request
+ // here, since navigation preload machinery has no access to netlog.
+ // TODO(falken): Figure out how network::mojom::URLLoaderClient can
+ // access the request's netlog.
+ if (requester_info->IsNavigationPreload()) {
+ new_request->net_log().AddEvent(
+ net::NetLogEventType::SERVICE_WORKER_NAVIGATION_PRELOAD_REQUEST);
+ }
- // For PlzNavigate, this request has already been made and the referrer was
- // checked previously. So don't set the referrer for this stream request, or
- // else it will fail for SSL redirects since net/ will think the blob:https
- // for the stream is not a secure scheme (specifically, in the call to
- // ComputeReferrerForRedirect).
- new_request->SetReferrer(network::ComputeReferrer(request_data.referrer));
- new_request->set_referrer_policy(request_data.referrer_policy);
-
- new_request->SetExtraRequestHeaders(headers);
-
- blob_context =
- GetBlobStorageContext(requester_info->blob_storage_context());
- // Resolve elements from request_body and prepare upload data.
- if (request_data.request_body.get()) {
- new_request->set_upload(UploadDataStreamBuilder::Build(
- request_data.request_body.get(), blob_context,
- requester_info->file_system_context(),
- base::CreateSingleThreadTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE})
- .get()));
- }
+ new_request->set_method(request_data.method);
+ new_request->set_site_for_cookies(request_data.site_for_cookies);
+ new_request->set_attach_same_site_cookies(
+ request_data.attach_same_site_cookies);
- do_not_prompt_for_login = request_data.do_not_prompt_for_login;
-
- // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only
- // allow requesting them if requester has ReadRawCookies permission.
- ChildProcessSecurityPolicyImpl* policy =
- ChildProcessSecurityPolicyImpl::GetInstance();
- report_raw_headers = request_data.report_raw_headers;
- if (report_raw_headers && !policy->CanReadRawCookies(child_id) &&
- !requester_info->IsNavigationPreload()) {
- // For navigation preload, the child_id is -1 so CanReadRawCookies would
- // return false. But |report_raw_headers| of the navigation preload
- // request was copied from the original request, so this check has already
- // been carried out.
- // TODO: crbug.com/523063 can we call bad_message::ReceivedBadMessage
- // here?
- VLOG(1) << "Denied unauthorized request for raw headers";
- report_raw_headers = false;
- }
+ // The initiator should normally be present, unless this is a navigation.
+ // Browser-initiated navigations don't have an initiator document, the
+ // others have one.
+ DCHECK(request_data.request_initiator.has_value() ||
+ IsResourceTypeFrame(
+ static_cast<ResourceType>(request_data.resource_type)));
+ new_request->set_initiator(request_data.request_initiator);
- // Do not report raw headers if the request's site needs to be isolated
- // from the current process.
- if (report_raw_headers) {
- bool is_isolated =
- SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
- policy->IsIsolatedOrigin(url::Origin::Create(request_data.url));
- if (is_isolated &&
- !policy->CanAccessDataForOrigin(child_id, request_data.url))
- report_raw_headers = false;
- }
+ if (request_data.originated_from_service_worker) {
+ new_request->SetUserData(URLRequestServiceWorkerData::kUserDataKey,
+ std::make_unique<URLRequestServiceWorkerData>());
+ }
- if (request_data.resource_type == RESOURCE_TYPE_PREFETCH ||
- request_data.resource_type == RESOURCE_TYPE_FAVICON) {
- do_not_prompt_for_login = true;
- }
- if (request_data.resource_type == RESOURCE_TYPE_IMAGE &&
- HTTP_AUTH_RELATION_BLOCKED_CROSS ==
- HttpAuthRelationTypeOf(request_data.url,
- request_data.site_for_cookies)) {
- // Prevent third-party image content from prompting for login, as this
- // is often a scam to extract credentials for another domain from the
- // user. Only block image loads, as the attack applies largely to the
- // "src" property of the <img> tag. It is common for web properties to
- // allow untrusted values for <img src>; this is considered a fair thing
- // for an HTML sanitizer to do. Conversely, any HTML sanitizer that didn't
- // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags
- // would be considered vulnerable in and of itself.
- do_not_prompt_for_login = true;
- load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
- }
+ new_request->SetReferrer(network::ComputeReferrer(request_data.referrer));
+ new_request->set_referrer_policy(request_data.referrer_policy);
- // Sync loads should have maximum priority and should be the only
- // requets that have the ignore limits flag set.
- if (is_sync_load) {
- DCHECK_EQ(request_data.priority, net::MAXIMUM_PRIORITY);
- DCHECK_NE(load_flags & net::LOAD_IGNORE_LIMITS, 0);
- } else {
- DCHECK_EQ(load_flags & net::LOAD_IGNORE_LIMITS, 0);
- }
+ new_request->SetExtraRequestHeaders(headers);
+
+ blob_context = GetBlobStorageContext(requester_info->blob_storage_context());
+ // Resolve elements from request_body and prepare upload data.
+ if (request_data.request_body.get()) {
+ new_request->set_upload(UploadDataStreamBuilder::Build(
+ request_data.request_body.get(), blob_context,
+ requester_info->file_system_context(),
+ base::CreateSingleThreadTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE})
+ .get()));
+ }
+
+ do_not_prompt_for_login = request_data.do_not_prompt_for_login;
+
+ // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only
+ // allow requesting them if requester has ReadRawCookies permission.
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ report_raw_headers = request_data.report_raw_headers;
+ // Security info is less sensitive than raw headers (does not include cookie
+ // values), so |report_security_info| is not subject to the extra security
+ // checks that are applied to |report_raw_headers|.
+ report_security_info = request_data.report_raw_headers;
+ if (report_raw_headers && !policy->CanReadRawCookies(child_id) &&
+ !requester_info->IsNavigationPreload()) {
+ // For navigation preload, the child_id is -1 so CanReadRawCookies would
+ // return false. But |report_raw_headers| of the navigation preload
+ // request was copied from the original request, so this check has already
+ // been carried out.
+ // TODO: https://crbug.com/523063 can we call
+ // bad_message::ReceivedBadMessage here?
+ VLOG(1) << "Denied unauthorized request for raw headers";
+ report_raw_headers = false;
+ }
+
+ // Do not report raw headers if the request's site needs to be isolated
+ // from the current process.
+ if (report_raw_headers) {
+ bool is_isolated =
+ SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
+ policy->IsIsolatedOrigin(url::Origin::Create(request_data.url));
+ if (is_isolated &&
+ !policy->CanAccessDataForOrigin(child_id, request_data.url))
+ report_raw_headers = false;
+ }
+
+ if (DoNotPromptForLogin(static_cast<ResourceType>(request_data.resource_type),
+ request_data.url, request_data.site_for_cookies)) {
+ // Prevent third-party image content from prompting for login, as this
+ // is often a scam to extract credentials for another domain from the
+ // user. Only block image loads, as the attack applies largely to the
+ // "src" property of the <img> tag. It is common for web properties to
+ // allow untrusted values for <img src>; this is considered a fair thing
+ // for an HTML sanitizer to do. Conversely, any HTML sanitizer that didn't
+ // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags
+ // would be considered vulnerable in and of itself.
+ do_not_prompt_for_login = true;
+ load_flags |= net::LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
+ }
+
+ // Sync loads should have maximum priority and should be the only
+ // requets that have the ignore limits flag set.
+ if (is_sync_load) {
+ DCHECK_EQ(request_data.priority, net::MAXIMUM_PRIORITY);
+ DCHECK_NE(load_flags & net::LOAD_IGNORE_LIMITS, 0);
+ } else {
+ DCHECK_EQ(load_flags & net::LOAD_IGNORE_LIMITS, 0);
}
if (request_data.keepalive) {
@@ -1206,7 +1051,6 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
request_data.is_main_frame,
static_cast<ResourceType>(request_data.resource_type),
static_cast<ui::PageTransition>(request_data.transition_type),
- request_data.should_replace_current_entry,
false, // is download
false, // is stream
false, // allow_download,
@@ -1216,9 +1060,8 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
request_data.referrer_policy),
request_data.is_prerendering, resource_context, report_raw_headers,
- !is_sync_load, request_data.previews_state, request_data.request_body,
- request_data.initiated_in_secure_context,
- base::nullopt); // suggested_filename
+ report_security_info, !is_sync_load, request_data.previews_state,
+ request_data.request_body, request_data.initiated_in_secure_context);
extra_info->SetBlobHandles(std::move(blob_handles));
// Request takes ownership.
@@ -1233,40 +1076,31 @@ void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
->GetBlobDataFromPublicURL(new_request->url()));
}
- std::unique_ptr<ResourceHandler> handler;
- if (is_navigation_stream_request) {
- // PlzNavigate: do not add ResourceThrottles for main resource requests from
- // the renderer. Decisions about the navigation should have been done in
- // the initial request.
- handler = CreateBaseResourceHandler(
- new_request.get(), std::move(mojo_request),
- std::move(url_loader_client),
- static_cast<ResourceType>(request_data.resource_type));
- } else {
- // Initialize the service worker handler for the request.
- ServiceWorkerRequestHandler::InitializeHandler(
- new_request.get(), requester_info->service_worker_context(),
- blob_context, child_id, request_data.service_worker_provider_id,
- request_data.skip_service_worker, request_data.fetch_request_mode,
- request_data.fetch_credentials_mode, request_data.fetch_redirect_mode,
- request_data.fetch_integrity, request_data.keepalive,
- static_cast<ResourceType>(request_data.resource_type),
- static_cast<RequestContextType>(
- request_data.fetch_request_context_type),
- request_data.fetch_frame_type, request_data.request_body);
-
- // Have the appcache associate its extra info with the request.
- AppCacheInterceptor::SetExtraRequestInfo(
- new_request.get(), requester_info->appcache_service(), child_id,
- request_data.appcache_host_id,
- static_cast<ResourceType>(request_data.resource_type),
- request_data.should_reset_appcache);
- handler = CreateResourceHandler(requester_info.get(), new_request.get(),
- request_data, route_id, child_id,
- resource_context, std::move(mojo_request),
- std::move(url_loader_client));
- }
+ // Initialize the service worker handler for the request.
+ ServiceWorkerRequestHandler::InitializeHandler(
+ new_request.get(), requester_info->service_worker_context(), blob_context,
+ child_id, request_data.service_worker_provider_id,
+ request_data.skip_service_worker, request_data.fetch_request_mode,
+ request_data.fetch_credentials_mode, request_data.fetch_redirect_mode,
+ request_data.fetch_integrity, request_data.keepalive,
+ static_cast<ResourceType>(request_data.resource_type),
+ static_cast<RequestContextType>(request_data.fetch_request_context_type),
+ request_data.fetch_frame_type, request_data.request_body);
+
+ // Have the appcache associate its extra info with the request.
+ AppCacheInterceptor::SetExtraRequestInfo(
+ new_request.get(), requester_info->appcache_service(), child_id,
+ request_data.appcache_host_id,
+ static_cast<ResourceType>(request_data.resource_type),
+ request_data.should_reset_appcache);
+
+ std::unique_ptr<ResourceHandler> handler = CreateResourceHandler(
+ requester_info.get(), new_request.get(), request_data, route_id, child_id,
+ resource_context, std::move(mojo_request), std::move(url_loader_client));
+
if (handler) {
+ RecordFetchRequestMode(request_data.url, request_data.method,
+ request_data.fetch_request_mode);
const bool is_initiated_by_fetch_api =
request_data.fetch_request_context_type == REQUEST_CONTEXT_TYPE_FETCH;
BeginRequestInternal(std::move(new_request), std::move(handler),
@@ -1299,9 +1133,8 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
new RedirectToFileResourceHandler(std::move(handler), request));
}
- // Prefetches and <a ping> requests outlive their child process.
- if (request_data.resource_type == RESOURCE_TYPE_PREFETCH ||
- request_data.keepalive) {
+ // Prefetches outlive their child process.
+ if (request_data.resource_type == RESOURCE_TYPE_PREFETCH) {
auto detachable_handler = std::make_unique<DetachableResourceHandler>(
request,
base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs),
@@ -1314,7 +1147,7 @@ ResourceDispatcherHostImpl::CreateResourceHandler(
resource_context, request_data.fetch_request_mode,
static_cast<RequestContextType>(request_data.fetch_request_context_type),
requester_info->appcache_service(), child_id, route_id,
- std::move(handler), nullptr, nullptr);
+ std::move(handler));
}
std::unique_ptr<ResourceHandler>
@@ -1340,9 +1173,7 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
AppCacheService* appcache_service,
int child_id,
int route_id,
- std::unique_ptr<ResourceHandler> handler,
- NavigationURLLoaderImplCore* navigation_loader_core,
- std::unique_ptr<StreamHandle> stream_handle) {
+ std::unique_ptr<ResourceHandler> handler) {
// The InterceptingResourceHandler will replace its next handler with an
// appropriate one based on the MIME type of the response if needed. It
// should be placed at the end of the chain, just before |handler|.
@@ -1395,20 +1226,6 @@ ResourceDispatcherHostImpl::AddStandardHandlers(
handler.reset(new ThrottlingResourceHandler(
std::move(handler), request, std::move(post_mime_sniffing_throttles)));
- if (IsBrowserSideNavigationEnabled() && IsResourceTypeFrame(resource_type) &&
- !IsNavigationMojoResponseEnabled()) {
- DCHECK(navigation_loader_core);
- DCHECK(stream_handle);
- // PlzNavigate
- // Add a NavigationResourceHandler that will control the flow of navigation.
- handler.reset(new NavigationResourceHandler(
- request, std::move(handler), navigation_loader_core, delegate(),
- std::move(stream_handle)));
- } else {
- DCHECK(!navigation_loader_core);
- DCHECK(!stream_handle);
- }
-
PluginService* plugin_service = nullptr;
#if BUILDFLAG(ENABLE_PLUGINS)
plugin_service = PluginService::GetInstance();
@@ -1488,7 +1305,6 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
MakeRequestID(), render_frame_route_id,
false, // is_main_frame
RESOURCE_TYPE_SUB_RESOURCE, ui::PAGE_TRANSITION_LINK,
- false, // should_replace_current_entry
download, // is_download
false, // is_stream
download, // allow_download
@@ -1501,11 +1317,11 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
false, // is_prerendering
context,
false, // report_raw_headers
+ false, // report_security_info
true, // is_async
previews_state, // previews_state
nullptr, // body
- false, // initiated_in_secure_context
- base::nullopt); // suggested_filename
+ false); // initiated_in_secure_context
}
void ResourceDispatcherHostImpl::OnRenderViewHostCreated(
@@ -1528,20 +1344,6 @@ void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
scheduler_->DeprecatedOnLoadingStateChanged(child_id, route_id, !is_loading);
}
-void ResourceDispatcherHostImpl::MarkAsTransferredNavigation(
- const GlobalRequestID& id,
- const base::Closure& on_transfer_complete_callback) {
- GetLoader(id)->MarkAsTransferring(on_transfer_complete_callback);
-}
-
-void ResourceDispatcherHostImpl::ResumeDeferredNavigation(
- const GlobalRequestID& id) {
- ResourceLoader* loader = GetLoader(id);
- // The response we were meant to resume could have already been canceled.
- if (loader)
- loader->CompleteTransfer();
-}
-
// The object died, so cancel and detach all requests associated with it except
// for downloads and detachable resources, which belong to the browser process
// even if initiated via a renderer.
@@ -1566,7 +1368,6 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(
int route_id = global_routing_id.frame_routing_id;
bool cancel_all_routes = (route_id == MSG_ROUTING_NONE);
- bool any_requests_transferring = false;
std::vector<GlobalRequestID> matching_requests;
for (const auto& loader : pending_loaders_) {
if (loader.first.child_id != child_id)
@@ -1577,24 +1378,13 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(
GlobalRequestID id(child_id, loader.first.request_id);
DCHECK(id == loader.first);
// Don't cancel navigations that are expected to live beyond this process.
- if (IsTransferredNavigation(id))
- any_requests_transferring = true;
if (cancel_all_routes || route_id == info->GetRenderFrameID()) {
- if (info->detachable_handler()) {
- if (info->keepalive()) {
- // If the feature is enabled, the renderer process's lifetime is
- // prolonged so there's no need to detach.
- if (cancel_all_routes) {
- // If the process is going to shut down for other reasons, we need
- // to cancel the request.
- matching_requests.push_back(id);
- }
- } else {
- // Otherwise, use DetachableResourceHandler's functionality.
- info->detachable_handler()->Detach();
- }
- } else if (!info->IsDownload() && !info->is_stream() &&
- !IsTransferredNavigation(id)) {
+ if (info->keepalive() && !cancel_all_routes) {
+ // If the keepalive flag is set, that request will outlive the frame
+ // deliberately, so we don't cancel it here.
+ } else if (info->detachable_handler()) {
+ info->detachable_handler()->Detach();
+ } else if (!info->IsDownload() && !info->is_stream()) {
matching_requests.push_back(id);
}
}
@@ -1616,14 +1406,6 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(
RemovePendingLoader(iter);
}
- // Don't clear the blocked loaders or offline policy maps if any of the
- // requests in route_id are being transferred to a new process, since those
- // maps will be updated with the new route_id after the transfer. Otherwise
- // we will lose track of this info when the old route goes away, before the
- // new one is created.
- if (any_requests_transferring)
- return;
-
// Now deal with blocked requests if any.
if (!cancel_all_routes) {
if (blocked_loaders_map_.find(global_routing_id) !=
@@ -1784,7 +1566,6 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
storage::FileSystemContext* upload_file_system_context,
const NavigationRequestInfo& info,
std::unique_ptr<NavigationUIData> navigation_ui_data,
- NavigationURLLoaderImplCore* loader,
network::mojom::URLLoaderClientPtr url_loader_client,
network::mojom::URLLoaderRequest url_loader_request,
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
@@ -1795,9 +1576,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// browser-side navigations project.
CHECK(IsBrowserSideNavigationEnabled());
- DCHECK_EQ(IsNavigationMojoResponseEnabled(), !loader);
- DCHECK_EQ(IsNavigationMojoResponseEnabled(), url_loader_client.is_bound());
- DCHECK_EQ(IsNavigationMojoResponseEnabled(), url_loader_request.is_pending());
+ DCHECK(url_loader_client.is_bound());
+ DCHECK(url_loader_request.is_pending());
ResourceType resource_type = info.is_main_frame ?
RESOURCE_TYPE_MAIN_FRAME : RESOURCE_TYPE_SUB_FRAME;
@@ -1817,18 +1597,9 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
!policy->IsWebSafeScheme(info.common_params.url.scheme()) &&
!is_external_protocol;
- if (is_shutdown_ || non_web_url_in_guest ||
- (delegate_ && !delegate_->ShouldBeginRequest(
- info.common_params.method,
- info.common_params.url,
- resource_type,
- resource_context))) {
- if (IsNavigationMojoResponseEnabled()) {
- url_loader_client->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_ABORTED));
- } else {
- loader->NotifyRequestFailed(false, net::ERR_ABORTED, base::nullopt);
- }
+ if (is_shutdown_ || non_web_url_in_guest) {
+ url_loader_client->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED));
return;
}
@@ -1864,7 +1635,10 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
headers.AddHeadersFromString(info.begin_params->headers);
std::string accept_value = network::kFrameAcceptHeader;
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange)) {
+ // TODO(https://crbug.com/840704): Decide whether the Accept header should
+ // advertise the state of kSignedHTTPExchangeOriginTrial before starting the
+ // Origin-Trial.
+ if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) {
DCHECK(!accept_value.empty());
accept_value.append(kAcceptHeaderSignedExchangeSuffix);
}
@@ -1883,12 +1657,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
if (body) {
if (!GetBodyBlobDataHandles(body, resource_context, &blob_handles)) {
new_request->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
- if (IsNavigationMojoResponseEnabled()) {
- url_loader_client->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_ABORTED));
- } else {
- loader->NotifyRequestFailed(false, net::ERR_ABORTED, base::nullopt);
- }
+ url_loader_client->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_ABORTED));
return;
}
new_request->set_upload(UploadDataStreamBuilder::Build(
@@ -1917,9 +1687,6 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
MakeRequestID(),
-1, // request_data.render_frame_id,
info.is_main_frame, resource_type, info.common_params.transition,
- // should_replace_current_entry. This was only maintained at layer for
- // request transfers and isn't needed for browser-side navigations.
- false,
false, // is download
false, // is stream
info.common_params.allow_download, info.common_params.has_user_gesture,
@@ -1929,14 +1696,17 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
false, // keepalive
info.common_params.referrer.policy, info.is_prerendering,
resource_context, info.report_raw_headers,
+ // For navigation requests, security info is reported whenever raw headers
+ // are. This behavior is different for subresources; see
+ // ContinuePendingBeginRequest.
+ info.report_raw_headers,
true, // is_async
previews_state, info.common_params.post_data,
// TODO(mek): Currently initiated_in_secure_context is only used for
// subresource requests, so it doesn't matter what value it gets here.
// If in the future this changes this should be updated to somehow get a
// meaningful value.
- false, // initiated_in_secure_context
- info.common_params.suggested_filename); // suggested_filename
+ false); // initiated_in_secure_context
extra_info->SetBlobHandles(std::move(blob_handles));
extra_info->set_navigation_ui_data(std::move(navigation_ui_data));
@@ -1970,25 +1740,9 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
}
std::unique_ptr<ResourceHandler> handler;
- std::unique_ptr<StreamHandle> stream_handle;
- if (IsNavigationMojoResponseEnabled()) {
- handler = std::make_unique<MojoAsyncResourceHandler>(
- new_request.get(), this, std::move(url_loader_request),
- std::move(url_loader_client), resource_type, url_loader_options);
- } else {
- StreamContext* stream_context =
- GetStreamContextForResourceContext(resource_context);
- // Note: the stream should be created with immediate mode set to true to
- // ensure that data read will be flushed to the reader as soon as it's
- // available. Otherwise, we risk delaying transmitting the body of the
- // resource to the renderer, which will delay parsing accordingly.
- handler = std::make_unique<StreamResourceHandler>(
- new_request.get(), stream_context->registry(),
- new_request->url().GetOrigin(), true);
- stream_handle = static_cast<StreamResourceHandler*>(handler.get())
- ->stream()
- ->CreateHandle();
- }
+ handler = std::make_unique<MojoAsyncResourceHandler>(
+ new_request.get(), this, std::move(url_loader_request),
+ std::move(url_loader_client), resource_type, url_loader_options);
// Safe to consider navigations as kNoCORS.
// TODO(davidben): Fix the dependency on child_id/route_id. Those are used
@@ -2001,8 +1755,10 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
: nullptr,
-1, // child_id
-1, // route_id
- std::move(handler), loader, std::move(stream_handle));
+ std::move(handler));
+ RecordFetchRequestMode(new_request->url(), new_request->method(),
+ network::mojom::FetchRequestMode::kNavigate);
BeginRequestInternal(std::move(new_request), std::move(handler),
false /* is_initiated_by_fetch_api */);
}
@@ -2220,11 +1976,6 @@ int ResourceDispatcherHostImpl::MakeRequestID() {
void ResourceDispatcherHostImpl::CancelRequestFromRenderer(
GlobalRequestID request_id) {
- // When the old renderer dies, it sends a message to us to cancel its
- // requests.
- if (IsTransferredNavigation(request_id))
- return;
-
ResourceLoader* loader = GetLoader(request_id);
// It is possible that the request has been completed and removed from the
@@ -2237,6 +1988,18 @@ void ResourceDispatcherHostImpl::CancelRequestFromRenderer(
loader->CancelRequest(true);
}
+bool ResourceDispatcherHostImpl::DoNotPromptForLogin(
+ ResourceType resource_type,
+ const GURL& url,
+ const GURL& site_for_cookies) {
+ if (resource_type == RESOURCE_TYPE_IMAGE &&
+ HTTP_AUTH_RELATION_BLOCKED_CROSS ==
+ HttpAuthRelationTypeOf(url, site_for_cookies)) {
+ return true;
+ }
+ return false;
+}
+
void ResourceDispatcherHostImpl::StartLoading(
ResourceRequestInfoImpl* info,
std::unique_ptr<ResourceLoader> loader) {
@@ -2362,12 +2125,13 @@ void ResourceDispatcherHostImpl::UpdateLoadInfo() {
// their render frame routing IDs yet (which is what we have for subresource
// requests), we must go to the UI thread and compare the requests using their
// WebContents.
+ DCHECK(!waiting_on_load_state_ack_);
waiting_on_load_state_ack_ = true;
main_thread_task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(UpdateLoadStateOnUI, loader_delegate_, std::move(infos)),
base::BindOnce(&ResourceDispatcherHostImpl::AckUpdateLoadInfo,
- weak_ptr_factory_.GetWeakPtr()));
+ weak_factory_on_io_.GetWeakPtr()));
}
void ResourceDispatcherHostImpl::AckUpdateLoadInfo() {
@@ -2463,12 +2227,6 @@ bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() {
return allow_cross_origin_auth_prompt_;
}
-bool ResourceDispatcherHostImpl::IsTransferredNavigation(
- const GlobalRequestID& id) const {
- ResourceLoader* loader = GetLoader(id);
- return loader ? loader->is_transferring() : false;
-}
-
ResourceLoader* ResourceDispatcherHostImpl::GetLoader(
const GlobalRequestID& id) const {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
@@ -2493,18 +2251,9 @@ bool ResourceDispatcherHostImpl::ShouldServiceRequest(
ResourceContext* resource_context) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- bool is_navigation_stream_request =
- IsBrowserSideNavigationEnabled() &&
- IsResourceTypeFrame(
- static_cast<ResourceType>(request_data.resource_type));
+
// Check if the renderer is permitted to request the requested URL.
- // PlzNavigate: no need to check the URL here. The browser already picked the
- // right renderer to send the request to. The original URL isn't used, as the
- // renderer is fetching the stream URL. Checking the original URL doesn't work
- // in case of redirects across schemes, since the original URL might not be
- // granted to the final URL's renderer.
- if (!is_navigation_stream_request &&
- !policy->CanRequestURL(child_id, request_data.url)) {
+ if (!policy->CanRequestURL(child_id, request_data.url)) {
VLOG(1) << "Denied unauthorized request for "
<< request_data.url.possibly_invalid_spec();
return false;
@@ -2589,6 +2338,28 @@ void ResourceDispatcherHostImpl::RunAuthRequiredCallback(
}
// static
+void ResourceDispatcherHostImpl::RecordFetchRequestMode(
+ const GURL& url,
+ base::StringPiece method,
+ network::mojom::FetchRequestMode mode) {
+ if (!url.SchemeIsHTTPOrHTTPS())
+ return;
+
+ std::string lower_method = base::ToLowerASCII(method);
+ if (lower_method == "get") {
+ UMA_HISTOGRAM_ENUMERATION("Net.ResourceDispatcherHost.RequestMode.Get",
+ mode);
+ } else if (lower_method == "post") {
+ UMA_HISTOGRAM_ENUMERATION("Net.ResourceDispatcherHost.RequestMode.Post",
+ mode);
+ if (url.has_port()) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.ResourceDispatcherHost.RequestMode.Post.WithPort", mode);
+ }
+ }
+}
+
+// static
// We have this function at the bottom of this file because it confuses
// syntax highliting.
net::NetworkTrafficAnnotationTag
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 80be7b79b0f..388f7f84a00 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -70,7 +70,6 @@ namespace content {
class AppCacheNavigationHandleCore;
class AppCacheService;
class LoaderDelegate;
-class NavigationURLLoaderImplCore;
class NavigationUIData;
class ResourceContext;
class ResourceDispatcherHostDelegate;
@@ -127,16 +126,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Cancels the given request if it still exists.
void CancelRequest(int child_id, int request_id);
- // Marks the request, with its current |response|, as "parked". This
- // happens if a request is redirected cross-site and needs to be
- // resumed by a new process.
- void MarkAsTransferredNavigation(
- const GlobalRequestID& id,
- const base::Closure& on_transfer_complete_callback);
-
- // Resumes the request without transferring it to a new process.
- void ResumeDeferredNavigation(const GlobalRequestID& id);
-
// Returns the number of pending requests. This is designed for the unittests
int pending_requests() const {
return static_cast<int>(pending_loaders_.size());
@@ -260,7 +249,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
storage::FileSystemContext* upload_file_system_context,
const NavigationRequestInfo& info,
std::unique_ptr<NavigationUIData> navigation_ui_data,
- NavigationURLLoaderImplCore* loader,
network::mojom::URLLoaderClientPtr url_loader_client,
network::mojom::URLLoaderRequest url_loader_request,
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
@@ -341,6 +329,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
return &keepalive_statistics_recorder_;
}
+ // Checks if needs to prompt for login.
+ bool DoNotPromptForLogin(ResourceType resource_type,
+ const GURL& url,
+ const GURL& site_for_cookies);
+
private:
class ScheduledResourceRequestAdapter;
friend class ResourceDispatcherHostTest;
@@ -360,7 +353,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfoSamePriority);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfoUploadProgress);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfoTwoRenderViews);
- FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest, UpdateLoadState);
struct OustandingRequestsStats {
int memory_cost;
@@ -553,26 +545,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool IsRequestIDInUse(const GlobalRequestID& id) const;
- // Update the ResourceRequestInfo and internal maps when a request is
- // transferred from one process to another.
- void UpdateRequestForTransfer(
- ResourceRequesterInfo* requester_info,
- int route_id,
- int request_id,
- const network::ResourceRequest& request_data,
- LoaderMap::iterator iter,
- network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client);
-
- // If |request_data| is for a request being transferred from another process,
- // then CompleteTransfer method can be used to complete the transfer.
- void CompleteTransfer(ResourceRequesterInfo* requester_info,
- int request_id,
- const network::ResourceRequest& request_data,
- int route_id,
- network::mojom::URLLoaderRequest mojo_request,
- network::mojom::URLLoaderClientPtr url_loader_client);
-
void BeginRequest(ResourceRequesterInfo* requester_info,
int request_id,
const network::ResourceRequest& request_data,
@@ -625,9 +597,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Wraps |handler| in the standard resource handlers for normal resource
// loading and navigation requests. This adds MimeTypeResourceHandler and
// ResourceThrottles.
- // PlzNavigate: |navigation_loader_core| and |stream_handle| are used to
- // properly initialized the NavigationResourceHandler placed in navigation
- // requests. They should be non-null in that case.
std::unique_ptr<ResourceHandler> AddStandardHandlers(
net::URLRequest* request,
ResourceType resource_type,
@@ -637,9 +606,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
AppCacheService* appcache_service,
int child_id,
int route_id,
- std::unique_ptr<ResourceHandler> handler,
- NavigationURLLoaderImplCore* navigation_loader_core,
- std::unique_ptr<StreamHandle> stream_handle);
+ std::unique_ptr<ResourceHandler> handler);
// Creates ResourceRequestInfoImpl for a download or page save.
// |download| should be true if the request is a file download.
@@ -663,13 +630,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
HttpAuthRelationType HttpAuthRelationTypeOf(const GURL& request_url,
const GURL& first_party);
- // Returns whether the URLRequest identified by |transferred_request_id| is
- // currently in the process of being transferred to a different renderer.
- // This happens if a request is redirected cross-site and needs to be resumed
- // by a new process.
- bool IsTransferredNavigation(
- const GlobalRequestID& transferred_request_id) const;
-
ResourceLoader* GetLoader(const GlobalRequestID& id) const;
ResourceLoader* GetLoader(int child_id, int request_id) const;
@@ -699,6 +659,10 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
GlobalRequestID request_id,
const base::Optional<net::AuthCredentials>& credentials);
+ static void RecordFetchRequestMode(const GURL& url,
+ base::StringPiece method,
+ network::mojom::FetchRequestMode mode);
+
static net::NetworkTrafficAnnotationTag GetTrafficAnnotation();
LoaderMap pending_loaders_;
@@ -802,7 +766,9 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Task runner for the IO thead.
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
- base::WeakPtrFactory<ResourceDispatcherHostImpl> weak_ptr_factory_;
+ // Used on the IO thread to allow PostTaskAndReply replies to the IO thread
+ // to be abandoned if they run after OnShutdown().
+ base::WeakPtrFactory<ResourceDispatcherHostImpl> weak_factory_on_io_;
DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHostImpl);
};
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index 7e099c63746..e576ad75157 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -13,7 +13,6 @@
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
@@ -22,6 +21,7 @@
#include "base/task_scheduler/task_traits.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/unguessable_token.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_resource_handler.h"
@@ -671,8 +671,8 @@ class ResourceDispatcherHostTest : public testing::Test {
HandleScheme("test");
scoped_refptr<SiteInstance> site_instance =
SiteInstance::Create(browser_context_.get());
- web_contents_.reset(
- WebContents::Create(WebContents::CreateParams(browser_context_.get())));
+ web_contents_ =
+ WebContents::Create(WebContents::CreateParams(browser_context_.get()));
web_contents_filter_ = new TestFilterSpecifyingChild(
browser_context_->GetResourceContext(),
web_contents_->GetMainFrame()->GetProcess()->GetID());
@@ -818,7 +818,7 @@ class ResourceDispatcherHostTest : public testing::Test {
std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo(common_params, std::move(begin_params), url,
true, false, false, -1, false, false, false,
- nullptr));
+ nullptr, base::UnguessableToken::Create()));
std::unique_ptr<NavigationURLLoader> test_loader =
NavigationURLLoader::Create(
browser_context_->GetResourceContext(),
diff --git a/chromium/content/browser/loader/resource_hints_impl.cc b/chromium/content/browser/loader/resource_hints_impl.cc
index 259dfa23ec6..6365bc19995 100644
--- a/chromium/content/browser/loader/resource_hints_impl.cc
+++ b/chromium/content/browser/loader/resource_hints_impl.cc
@@ -49,8 +49,7 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
const GURL& url,
const GURL& site_for_cookies,
int count,
- bool allow_credentials,
- net::HttpRequestInfo::RequestMotivation motivation) {
+ bool allow_credentials) {
DCHECK(ResourceDispatcherHostImpl::Get()
->io_thread_task_runner()
->BelongsToCurrentThread());
@@ -73,7 +72,6 @@ void PreconnectUrl(net::URLRequestContextGetter* getter,
request_info.method = "GET";
request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
user_agent);
- request_info.motivation = motivation;
net::NetworkDelegate* delegate = request_context->network_delegate();
if (delegate->CanEnablePrivacyMode(url, site_for_cookies))
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index bad80bb69bc..c06232582ab 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -51,6 +51,18 @@ using base::TimeTicks;
namespace content {
namespace {
+// Copies selected fields from |in| to the returned SSLInfo. To avoid sending
+// unnecessary data into the renderer, this only copies the fields that the
+// renderer cares about.
+net::SSLInfo SelectSSLInfoFields(const net::SSLInfo& in) {
+ net::SSLInfo out;
+ out.connection_status = in.connection_status;
+ out.key_exchange_group = in.key_exchange_group;
+ out.signed_certificate_timestamps = in.signed_certificate_timestamps;
+ out.cert = in.cert;
+ return out;
+}
+
void PopulateResourceResponse(
ResourceRequestInfoImpl* info,
net::URLRequest* request,
@@ -117,8 +129,8 @@ void PopulateResourceResponse(
net::IsCertStatusMinorError(response->head.cert_status)) &&
net::IsLegacySymantecCert(request->ssl_info().public_key_hashes);
- if (info->ShouldReportRawHeaders())
- response->head.ssl_info = request->ssl_info();
+ if (info->ShouldReportSecurityInfo())
+ response->head.ssl_info = SelectSSLInfoFields(request->ssl_info());
} else {
// We should not have any SSL state.
DCHECK(!request->ssl_info().cert_status);
@@ -215,7 +227,6 @@ ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request,
request_(std::move(request)),
handler_(std::move(handler)),
delegate_(delegate),
- is_transferring_(false),
times_cancelled_before_request_start_(0),
started_request_(false),
times_cancelled_after_request_start_(0),
@@ -274,46 +285,6 @@ void ResourceLoader::CancelWithError(int error_code) {
CancelRequestInternal(error_code, false);
}
-void ResourceLoader::MarkAsTransferring(
- const base::Closure& on_transfer_complete_callback) {
- CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
- << "Can only transfer for navigations";
- is_transferring_ = true;
- on_transfer_complete_callback_ = on_transfer_complete_callback;
-
- int child_id = GetRequestInfo()->GetChildID();
- AppCacheInterceptor::PrepareForCrossSiteTransfer(request(), child_id);
- ServiceWorkerRequestHandler* handler =
- ServiceWorkerRequestHandler::GetHandler(request());
- if (handler)
- handler->PrepareForCrossSiteTransfer(child_id);
-}
-
-void ResourceLoader::CompleteTransfer() {
- // Although NavigationResourceThrottle defers at WillProcessResponse
- // (DEFERRED_READ), it may be seeing a replay of events via
- // MimeTypeResourceHandler, and so the request itself is actually deferred at
- // a later read stage.
- DCHECK(DEFERRED_READ == deferred_stage_ ||
- DEFERRED_RESPONSE_COMPLETE == deferred_stage_);
- DCHECK(is_transferring_);
- DCHECK(!on_transfer_complete_callback_.is_null());
-
- // In some cases, a process transfer doesn't really happen and the
- // request is resumed in the original process. Real transfers to a new process
- // are completed via ResourceDispatcherHostImpl::UpdateRequestForTransfer.
- int child_id = GetRequestInfo()->GetChildID();
- AppCacheInterceptor::MaybeCompleteCrossSiteTransferInOldProcess(
- request(), child_id);
- ServiceWorkerRequestHandler* handler =
- ServiceWorkerRequestHandler::GetHandler(request());
- if (handler)
- handler->MaybeCompleteCrossSiteTransferInOldProcess(child_id);
-
- is_transferring_ = false;
- base::ResetAndReturn(&on_transfer_complete_callback_).Run();
-}
-
ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
return ResourceRequestInfoImpl::ForRequest(request_.get());
}
@@ -545,8 +516,6 @@ void ResourceLoader::CancelCertificateSelection() {
}
void ResourceLoader::Resume(bool called_from_resource_controller) {
- DCHECK(!is_transferring_);
-
DeferredStage stage = deferred_stage_;
deferred_stage_ = DEFERRED_NONE;
switch (stage) {
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index e5276077af1..93ea0021af1 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
@@ -49,10 +48,6 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void StartRequest();
void CancelRequest(bool from_renderer);
- bool is_transferring() const { return is_transferring_; }
- void MarkAsTransferring(const base::Closure& on_transfer_complete_callback);
- void CompleteTransfer();
-
net::URLRequest* request() { return request_.get(); }
ResourceRequestInfoImpl* GetRequestInfo();
@@ -163,14 +158,6 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
base::TimeTicks read_deferral_start_time_;
- // Indicates that we are in a state of being transferred to a new downstream
- // consumer. We are waiting for a notification to complete the transfer, at
- // which point we'll receive a new ResourceHandler.
- bool is_transferring_;
-
- // Called when a navigation has finished transfer.
- base::Closure on_transfer_complete_callback_;
-
// Instrumentation add to investigate http://crbug.com/503306.
// TODO(mmenke): Remove once bug is fixed.
int times_cancelled_before_request_start_;
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 0fcaeedb1aa..469e35d26be 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -471,8 +471,8 @@ class ResourceLoaderTest : public testing::Test,
browser_context_.reset(new TestBrowserContext());
scoped_refptr<SiteInstance> site_instance =
SiteInstance::Create(browser_context_.get());
- web_contents_.reset(
- TestWebContents::Create(browser_context_.get(), site_instance.get()));
+ web_contents_ =
+ TestWebContents::Create(browser_context_.get(), site_instance.get());
SetUpResourceLoaderForUrl(test_redirect_url());
}
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index c86ba1ee886..4a82566e296 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -8,24 +8,34 @@
#include "base/logging.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_requester_info.h"
#include "content/browser/loader/url_loader_factory_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/content_features.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/cors/cors_url_loader_factory.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "storage/browser/fileapi/file_system_context.h"
namespace content {
namespace {
network::mojom::URLLoaderFactory* g_test_factory;
ResourceMessageFilter* g_current_filter;
+
+int GetFrameTreeNodeId(int render_process_host_id, int render_frame_host_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHost* render_frame_host =
+ RenderFrameHost::FromID(render_process_host_id, render_frame_host_id);
+ return render_frame_host ? render_frame_host->GetFrameTreeNodeId() : -1;
+}
+
} // namespace
ResourceMessageFilter::ResourceMessageFilter(
@@ -116,14 +126,16 @@ void ResourceMessageFilter::CreateLoaderAndStart(
// TODO(kinuko): Remove this flag guard when we have more confidence, this
// doesn't need to be paired up with SignedExchange feature.
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange) &&
+ if (signed_exchange_utils::IsSignedExchangeHandlingEnabled() &&
url_request.resource_type == RESOURCE_TYPE_PREFETCH &&
prefetch_url_loader_service_) {
prefetch_url_loader_service_->CreateLoaderAndStart(
std::move(request), routing_id, request_id, options, url_request,
std::move(client), traffic_annotation,
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
- url_loader_factory_.get()));
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ url_loader_factory_.get()),
+ base::BindRepeating(&GetFrameTreeNodeId, child_id(),
+ url_request.render_frame_id));
return;
}
@@ -167,7 +179,10 @@ void ResourceMessageFilter::InitializeOnIOThread() {
if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS)) {
url_loader_factory_ = std::make_unique<network::cors::CORSURLLoaderFactory>(
- std::move(url_loader_factory_));
+ std::move(url_loader_factory_),
+ base::BindRepeating(&ResourceDispatcherHostImpl::CancelRequest,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ requester_info_->child_id()));
}
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 704bce310f0..651bf20c2c3 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -69,7 +69,6 @@ void ResourceRequestInfo::AllocateForTesting(
is_main_frame, // is_main_frame
resource_type, // resource_type
ui::PAGE_TRANSITION_LINK, // transition_type
- false, // should_replace_current_entry
false, // is_download
false, // is_stream
allow_download, // allow_download
@@ -82,11 +81,11 @@ void ResourceRequestInfo::AllocateForTesting(
false, // is_prerendering
context, // context
false, // report_raw_headers
+ false, // report_security_info
is_async, // is_async
previews_state, // previews_state
nullptr, // body
- false, // initiated_in_secure_context
- base::nullopt); // suggested_filename
+ false); // initiated_in_secure_context
info->AssociateWithRequest(request);
info->set_navigation_ui_data(std::move(navigation_ui_data));
}
@@ -138,7 +137,6 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
bool is_main_frame,
ResourceType resource_type,
ui::PageTransition transition_type,
- bool should_replace_current_entry,
bool is_download,
bool is_stream,
bool allow_download,
@@ -151,11 +149,11 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
bool is_prerendering,
ResourceContext* context,
bool report_raw_headers,
+ bool report_security_info,
bool is_async,
PreviewsState previews_state,
const scoped_refptr<network::ResourceRequestBody> body,
- bool initiated_in_secure_context,
- const base::Optional<std::string>& suggested_filename)
+ bool initiated_in_secure_context)
: detachable_handler_(nullptr),
requester_info_(std::move(requester_info)),
route_id_(route_id),
@@ -164,7 +162,6 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
request_id_(request_id),
render_frame_id_(render_frame_id),
is_main_frame_(is_main_frame),
- should_replace_current_entry_(should_replace_current_entry),
is_download_(is_download),
is_stream_(is_stream),
allow_download_(allow_download),
@@ -181,12 +178,12 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
is_prerendering_(is_prerendering),
context_(context),
report_raw_headers_(report_raw_headers),
+ report_security_info_(report_security_info),
is_async_(is_async),
devtools_status_(DevToolsStatus::kNotCanceled),
previews_state_(previews_state),
body_(body),
initiated_in_secure_context_(initiated_in_secure_context),
- suggested_filename_(suggested_filename),
blocked_cross_site_document_(false),
first_auth_attempt_(true) {}
@@ -315,6 +312,10 @@ bool ResourceRequestInfoImpl::ShouldReportRawHeaders() const {
return report_raw_headers_;
}
+bool ResourceRequestInfoImpl::ShouldReportSecurityInfo() const {
+ return report_security_info_;
+}
+
NavigationUIData* ResourceRequestInfoImpl::GetNavigationUIData() const {
return navigation_ui_data_.get();
}
@@ -324,6 +325,11 @@ ResourceRequestInfo::DevToolsStatus ResourceRequestInfoImpl::GetDevToolsStatus()
return devtools_status_;
}
+base::Optional<blink::ResourceRequestBlockedReason>
+ResourceRequestInfoImpl::GetResourceRequestBlockedReason() const {
+ return resource_request_blocked_reason_;
+}
+
base::StringPiece ResourceRequestInfoImpl::GetCustomCancelReason() const {
return custom_cancel_reason_;
}
@@ -347,26 +353,6 @@ GlobalRoutingID ResourceRequestInfoImpl::GetGlobalRoutingID() const {
return GlobalRoutingID(GetChildID(), route_id_);
}
-void ResourceRequestInfoImpl::UpdateForTransfer(
- int route_id,
- int render_frame_id,
- int request_id,
- ResourceRequesterInfo* requester_info,
- network::mojom::URLLoaderRequest url_loader_request,
- network::mojom::URLLoaderClientPtr url_loader_client) {
- route_id_ = route_id;
- render_frame_id_ = render_frame_id;
- plugin_child_id_ = ChildProcessHost::kInvalidUniqueID;
- request_id_ = request_id;
- requester_info_ = requester_info;
-
- // on_transfer_ is non-null only when MojoAsyncResourceHandler is used.
- if (on_transfer_) {
- on_transfer_.Run(std::move(url_loader_request),
- std::move(url_loader_client));
- }
-}
-
void ResourceRequestInfoImpl::ResetBody() {
body_ = nullptr;
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 10cfae2d9b4..0b65d8c115b 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -36,10 +36,6 @@ struct GlobalRoutingID;
class ResourceRequestInfoImpl : public ResourceRequestInfo,
public base::SupportsUserData::Data {
public:
- using TransferCallback =
- base::Callback<void(network::mojom::URLLoaderRequest,
- network::mojom::URLLoaderClientPtr)>;
-
// Returns the ResourceRequestInfoImpl associated with the given URLRequest.
CONTENT_EXPORT static ResourceRequestInfoImpl* ForRequest(
net::URLRequest* request);
@@ -58,7 +54,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool is_main_frame,
ResourceType resource_type,
ui::PageTransition transition_type,
- bool should_replace_current_entry,
bool is_download,
bool is_stream,
bool allow_download,
@@ -71,11 +66,11 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool is_prerendering,
ResourceContext* context,
bool report_raw_headers,
+ bool report_security_info,
bool is_async,
PreviewsState previews_state,
const scoped_refptr<network::ResourceRequestBody> body,
- bool initiated_in_secure_context,
- const base::Optional<std::string>& suggested_filename);
+ bool initiated_in_secure_context);
~ResourceRequestInfoImpl() override;
// ResourceRequestInfo implementation:
@@ -102,8 +97,13 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
// Returns a bitmask of potentially several Previews optimizations.
PreviewsState GetPreviewsState() const override;
bool ShouldReportRawHeaders() const;
+ bool ShouldReportSecurityInfo() const;
NavigationUIData* GetNavigationUIData() const override;
DevToolsStatus GetDevToolsStatus() const override;
+
+ base::Optional<blink::ResourceRequestBlockedReason>
+ GetResourceRequestBlockedReason() const override;
+
base::StringPiece GetCustomCancelReason() const override;
CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
@@ -120,24 +120,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
return requester_info_.get();
}
- // Updates the data associated with this request after it is is transferred
- // to a new renderer process. Not all data will change during a transfer.
- // We do not expect the ResourceContext to change during navigation, so that
- // does not need to be updated.
- void UpdateForTransfer(int route_id,
- int render_frame_id,
- int request_id,
- ResourceRequesterInfo* requester_info,
- network::mojom::URLLoaderRequest url_loader_request,
- network::mojom::URLLoaderClientPtr url_loader_client);
-
- // Whether this request is part of a navigation that should replace the
- // current session history entry. This state is shuffled up and down the stack
- // for request transfers.
- bool should_replace_current_entry() const {
- return should_replace_current_entry_;
- }
-
// DetachableResourceHandler for this request. May be NULL.
DetachableResourceHandler* detachable_handler() const {
return detachable_handler_;
@@ -198,20 +180,17 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
navigation_ui_data_ = std::move(navigation_ui_data);
}
- void set_on_transfer(const TransferCallback& on_transfer) {
- on_transfer_ = on_transfer;
- }
-
void set_devtools_status(DevToolsStatus devtools_status) {
devtools_status_ = devtools_status;
}
- void SetBlobHandles(BlobHandles blob_handles);
-
- const base::Optional<std::string>& suggested_filename() const {
- return suggested_filename_;
+ void set_resource_request_blocked_reason(
+ base::Optional<blink::ResourceRequestBlockedReason> reason) {
+ resource_request_blocked_reason_ = reason;
}
+ void SetBlobHandles(BlobHandles blob_handles);
+
bool blocked_cross_site_document() const {
return blocked_cross_site_document_;
}
@@ -244,7 +223,6 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
int request_id_;
int render_frame_id_;
bool is_main_frame_;
- bool should_replace_current_entry_;
bool is_download_;
bool is_stream_;
bool allow_download_;
@@ -261,24 +239,21 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool is_prerendering_;
ResourceContext* context_;
bool report_raw_headers_;
+ bool report_security_info_;
bool is_async_;
DevToolsStatus devtools_status_;
+ base::Optional<blink::ResourceRequestBlockedReason>
+ resource_request_blocked_reason_;
PreviewsState previews_state_;
scoped_refptr<network::ResourceRequestBody> body_;
bool initiated_in_secure_context_;
std::unique_ptr<NavigationUIData> navigation_ui_data_;
- base::Optional<std::string> suggested_filename_;
bool blocked_cross_site_document_;
bool first_auth_attempt_;
// Keeps upload body blobs alive for the duration of the request.
BlobHandles blob_handles_;
- // This callback is set by MojoAsyncResourceHandler to update its mojo binding
- // and remote endpoint. This callback will be removed once PlzNavigate is
- // shipped.
- TransferCallback on_transfer_;
-
std::string custom_cancel_reason_;
DISALLOW_COPY_AND_ASSIGN(ResourceRequestInfoImpl);
diff --git a/chromium/content/browser/loader/resource_requester_info.cc b/chromium/content/browser/loader/resource_requester_info.cc
index 9bde2f2936a..862ff7ff379 100644
--- a/chromium/content/browser/loader/resource_requester_info.cc
+++ b/chromium/content/browser/loader/resource_requester_info.cc
@@ -9,6 +9,7 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -134,7 +135,7 @@ scoped_refptr<ResourceRequesterInfo>
ResourceRequesterInfo::CreateForCertificateFetcherForSignedExchange(
const GetContextsCallback& get_contexts_callback) {
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
+ DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
RequesterType::CERTIFICATE_FETCHER_FOR_SIGNED_EXCHANGE,
ChildProcessHost::kInvalidUniqueID, nullptr /* appcache_service */,
diff --git a/chromium/content/browser/loader/source_stream_to_data_pipe_unittest.cc b/chromium/content/browser/loader/source_stream_to_data_pipe_unittest.cc
index 29e851fb7e6..b03704f104d 100644
--- a/chromium/content/browser/loader/source_stream_to_data_pipe_unittest.cc
+++ b/chromium/content/browser/loader/source_stream_to_data_pipe_unittest.cc
@@ -53,8 +53,8 @@ class SourceStreamToDataPipeTest
source_ = source.get();
const MojoCreateDataPipeOptions data_pipe_options{
- sizeof(MojoCreateDataPipeOptions),
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, GetParam().pipe_capacity};
+ sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1,
+ GetParam().pipe_capacity};
mojo::ScopedDataPipeProducerHandle producer_end;
CHECK_EQ(MOJO_RESULT_OK,
mojo::CreateDataPipe(&data_pipe_options, &producer_end,
diff --git a/chromium/content/browser/loader/temporary_file_stream.cc b/chromium/content/browser/loader/temporary_file_stream.cc
index 07e008dce6a..2f1c784f5e0 100644
--- a/chromium/content/browser/loader/temporary_file_stream.cc
+++ b/chromium/content/browser/loader/temporary_file_stream.cc
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/files/file_proxy.h"
#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/file_stream.h"
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index 020fd504f50..fed54aea40a 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -98,10 +98,11 @@ std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
body, file_task_runner, element));
break;
case network::DataElement::TYPE_BLOB: {
- DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length());
DCHECK_EQ(0ul, element.offset());
std::unique_ptr<storage::BlobDataHandle> handle =
blob_context->GetBlobDataFromUUID(element.blob_uuid());
+ DCHECK(element.length() == std::numeric_limits<uint64_t>::max() ||
+ element.length() == handle->size());
element_readers.push_back(
std::make_unique<storage::UploadBlobElementReader>(
std::move(handle)));
diff --git a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
index c1e1aa06fb5..e6ede61511d 100644
--- a/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
+++ b/chromium/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -16,7 +16,6 @@
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -61,20 +60,6 @@ namespace {
constexpr int kChildId = 99;
-class RejectingResourceDispatcherHostDelegate final
- : public ResourceDispatcherHostDelegate {
- public:
- RejectingResourceDispatcherHostDelegate() {}
- bool ShouldBeginRequest(const std::string& method,
- const GURL& url,
- ResourceType resource_type,
- ResourceContext* resource_context) override {
- return false;
- }
-
- DISALLOW_COPY_AND_ASSIGN(RejectingResourceDispatcherHostDelegate);
-};
-
// The test parameter is the number of bytes allocated for the buffer in the
// data pipe, for testing the case where the allocated size is smaller than the
// size the mime sniffer *implicitly* requires.
@@ -149,7 +134,7 @@ TEST_P(URLLoaderFactoryImplTest, GetResponse) {
constexpr int32_t kRequestId = 28;
network::mojom::URLLoaderPtr loader;
base::FilePath root;
- PathService::Get(DIR_TEST_DATA, &root);
+ base::PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestMockHTTPJob::AddUrlHandlers(root);
network::ResourceRequest request;
network::TestURLLoaderClient client;
@@ -310,11 +295,13 @@ TEST_P(URLLoaderFactoryImplTest, InvalidURL) {
// This test tests a case where resource loading is cancelled before started.
TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
network::mojom::URLLoaderPtr loader;
- RejectingResourceDispatcherHostDelegate rdh_delegate;
- rdh_.SetDelegate(&rdh_delegate);
network::ResourceRequest request;
network::TestURLLoaderClient client;
- request.url = GURL("http://localhost/");
+
+ // Child processes cannot request URLs with pseudo schemes like "about",
+ // except for about:blank. See ChildProcessSecurityPolicyImpl::CanRequestURL
+ // for details.
+ request.url = GURL("about:version");
request.method = "GET";
// |resource_type| can't be a frame type. It is because when PlzNavigate is
// enabled, the url scheme of frame type requests from the renderer process
@@ -328,7 +315,6 @@ TEST_P(URLLoaderFactoryImplTest, ShouldNotRequestURL) {
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilComplete();
- rdh_.SetDelegate(nullptr);
ASSERT_FALSE(client.has_received_response());
ASSERT_FALSE(client.response_body().is_valid());
@@ -342,7 +328,7 @@ TEST_P(URLLoaderFactoryImplTest, DownloadToFile) {
network::mojom::URLLoaderPtr loader;
base::FilePath root;
- PathService::Get(DIR_TEST_DATA, &root);
+ base::PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestMockHTTPJob::AddUrlHandlers(root);
network::ResourceRequest request;
@@ -410,7 +396,7 @@ TEST_P(URLLoaderFactoryImplTest, DownloadToFileFailure) {
network::mojom::URLLoaderPtr loader;
base::FilePath root;
- PathService::Get(DIR_TEST_DATA, &root);
+ base::PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestSlowDownloadJob::AddUrlHandler();
network::ResourceRequest request;
@@ -468,7 +454,7 @@ TEST_P(URLLoaderFactoryImplTest, OnTransferSizeUpdated) {
constexpr int32_t kRequestId = 28;
network::mojom::URLLoaderPtr loader;
base::FilePath root;
- PathService::Get(DIR_TEST_DATA, &root);
+ base::PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestMockHTTPJob::AddUrlHandlers(root);
network::ResourceRequest request;
network::TestURLLoaderClient client;
@@ -528,7 +514,7 @@ TEST_P(URLLoaderFactoryImplTest, CancelFromRenderer) {
constexpr int32_t kRequestId = 28;
network::mojom::URLLoaderPtr loader;
base::FilePath root;
- PathService::Get(DIR_TEST_DATA, &root);
+ base::PathService::Get(DIR_TEST_DATA, &root);
net::URLRequestFailedJob::AddUrlHandler();
network::ResourceRequest request;
network::TestURLLoaderClient client;
diff --git a/chromium/content/browser/mach_broker_mac.h b/chromium/content/browser/mach_broker_mac.h
index d146728bece..2d796db3eaa 100644
--- a/chromium/content/browser/mach_broker_mac.h
+++ b/chromium/content/browser/mach_broker_mac.h
@@ -55,13 +55,13 @@ class CONTENT_EXPORT MachBroker : public base::PortProvider,
// Implement |BrowserChildProcessObserver|.
void BrowserChildProcessHostDisconnected(
const ChildProcessData& data) override;
- void BrowserChildProcessCrashed(const ChildProcessData& data,
- int exit_code) override;
+ void BrowserChildProcessCrashed(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) override;
// Implement |RenderProcessHostObserver|.
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override;
+ const ChildProcessTerminationInfo& info) override;
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
// Returns the Mach port name to use when sending or receiving messages.
diff --git a/chromium/content/browser/mach_broker_mac.mm b/chromium/content/browser/mach_broker_mac.mm
index 3cdb0b00781..9b0da7da02f 100644
--- a/chromium/content/browser/mach_broker_mac.mm
+++ b/chromium/content/browser/mach_broker_mac.mm
@@ -68,14 +68,14 @@ void MachBroker::BrowserChildProcessHostDisconnected(
InvalidateChildProcessId(data.id);
}
-void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data,
- int exit_code) {
+void MachBroker::BrowserChildProcessCrashed(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) {
InvalidateChildProcessId(data.id);
}
void MachBroker::RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {
+ const ChildProcessTerminationInfo& info) {
InvalidateChildProcessId(host->GetID());
}
diff --git a/chromium/content/browser/manifest/manifest_browsertest.cc b/chromium/content/browser/manifest/manifest_browsertest.cc
index d8b4b2d615e..ba1a288479d 100644
--- a/chromium/content/browser/manifest/manifest_browsertest.cc
+++ b/chromium/content/browser/manifest/manifest_browsertest.cc
@@ -13,7 +13,6 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/manifest.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -23,7 +22,8 @@
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
namespace content {
@@ -80,15 +80,14 @@ class ManifestBrowserTest : public ContentBrowserTest,
message_loop_runner_->Run();
}
- void OnGetManifest(const GURL& manifest_url, const Manifest& manifest) {
+ void OnGetManifest(const GURL& manifest_url,
+ const blink::Manifest& manifest) {
manifest_url_ = manifest_url;
manifest_ = manifest;
message_loop_runner_->Quit();
}
- const Manifest& manifest() const {
- return manifest_;
- }
+ const blink::Manifest& manifest() const { return manifest_; }
const GURL& manifest_url() const {
return manifest_url_;
@@ -148,7 +147,7 @@ class ManifestBrowserTest : public ContentBrowserTest,
std::unique_ptr<MockWebContentsDelegate> mock_web_contents_delegate_;
std::unique_ptr<net::EmbeddedTestServer> cors_embedded_test_server_;
GURL manifest_url_;
- Manifest manifest_;
+ blink::Manifest manifest_;
int console_error_count_;
std::vector<GURL> reported_manifest_urls_;
std::vector<size_t> manifests_reported_when_favicon_url_updated_;
diff --git a/chromium/content/browser/manifest/manifest_icon_selector.cc b/chromium/content/browser/manifest/manifest_icon_selector.cc
index 90d9bb53200..02afadb3709 100644
--- a/chromium/content/browser/manifest/manifest_icon_selector.cc
+++ b/chromium/content/browser/manifest/manifest_icon_selector.cc
@@ -14,10 +14,10 @@ namespace content {
// static
GURL ManifestIconSelector::FindBestMatchingIcon(
- const std::vector<Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
int ideal_icon_size_in_px,
int minimum_icon_size_in_px,
- Manifest::Icon::IconPurpose purpose) {
+ blink::Manifest::Icon::IconPurpose purpose) {
DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px);
// Icon with exact matching size has priority over icon with size "any", which
diff --git a/chromium/content/browser/manifest/manifest_icon_selector_unittest.cc b/chromium/content/browser/manifest/manifest_icon_selector_unittest.cc
index aa602a92846..467a91a0864 100644
--- a/chromium/content/browser/manifest/manifest_icon_selector_unittest.cc
+++ b/chromium/content/browser/manifest/manifest_icon_selector_unittest.cc
@@ -13,18 +13,18 @@
namespace content {
-using IconPurpose = Manifest::Icon::IconPurpose;
+using IconPurpose = blink::Manifest::Icon::IconPurpose;
namespace {
const int kIdealIconSize = 144;
const int kMinimumIconSize = 0;
-static Manifest::Icon CreateIcon(const std::string& url,
- const std::string& type,
- const std::vector<gfx::Size> sizes,
- IconPurpose purpose) {
- Manifest::Icon icon;
+static blink::Manifest::Icon CreateIcon(const std::string& url,
+ const std::string& type,
+ const std::vector<gfx::Size> sizes,
+ IconPurpose purpose) {
+ blink::Manifest::Icon icon;
icon.src = GURL(url);
icon.type = base::UTF8ToUTF16(type);
icon.sizes = sizes;
@@ -37,7 +37,7 @@ static Manifest::Icon CreateIcon(const std::string& url,
TEST(ManifestIconSelector, NoIcons) {
// No icons should return the empty URL.
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
GURL url = ManifestIconSelector::FindBestMatchingIcon(
icons, kIdealIconSize, kMinimumIconSize, IconPurpose::ANY);
EXPECT_TRUE(url.is_empty());
@@ -45,7 +45,7 @@ TEST(ManifestIconSelector, NoIcons) {
TEST(ManifestIconSelector, NoSizes) {
// Icon with no sizes are ignored.
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon.png", "",
std::vector<gfx::Size>(), IconPurpose::ANY));
@@ -60,7 +60,7 @@ TEST(ManifestIconSelector, MIMETypeFiltering) {
std::vector<gfx::Size> sizes;
sizes.push_back(gfx::Size(1024, 1024));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon.png", "image/foo_bar", sizes,
IconPurpose::ANY));
icons.push_back(
@@ -107,7 +107,7 @@ TEST(ManifestIconSelector, PurposeFiltering) {
std::vector<gfx::Size> sizes_144;
sizes_144.push_back(gfx::Size(144, 144));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_48.png", "", sizes_48,
IconPurpose::BADGE));
icons.push_back(
@@ -147,7 +147,7 @@ TEST(ManifestIconSelector, IdealSizeIsUsedFirst) {
std::vector<gfx::Size> sizes_144;
sizes_144.push_back(gfx::Size(144, 144));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon_48.png", "", sizes_48, IconPurpose::ANY));
icons.push_back(
@@ -182,7 +182,7 @@ TEST(ManifestIconSelector, FirstIconWithIdealSizeIsUsedFirst) {
std::vector<gfx::Size> sizes_3;
sizes_3.push_back(gfx::Size(1024, 1024));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon_x1.png", "", sizes_1, IconPurpose::ANY));
icons.push_back(
@@ -214,7 +214,7 @@ TEST(ManifestIconSelector, FallbackToSmallestLargerIcon) {
std::vector<gfx::Size> sizes_3;
sizes_3.push_back(gfx::Size(192, 192));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon_x1.png", "", sizes_1, IconPurpose::ANY));
icons.push_back(
@@ -244,7 +244,7 @@ TEST(ManifestIconSelector, FallbackToLargestIconLargerThanMinimum) {
sizes_1_2.push_back(gfx::Size(47, 47));
sizes_3.push_back(gfx::Size(95, 95));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_x1.png", "", sizes_1_2,
IconPurpose::ANY));
icons.push_back(CreateIcon("http://foo.com/icon_x2.png", "", sizes_1_2,
@@ -267,7 +267,7 @@ TEST(ManifestIconSelector, IdealVeryCloseToMinimumMatches) {
std::vector<gfx::Size> sizes;
sizes.push_back(gfx::Size(2, 2));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon_x1.png", "", sizes, IconPurpose::ANY));
@@ -280,7 +280,7 @@ TEST(ManifestIconSelector, SizeVeryCloseToMinimumMatches) {
std::vector<gfx::Size> sizes;
sizes.push_back(gfx::Size(2, 2));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon_x1.png", "", sizes, IconPurpose::ANY));
@@ -293,7 +293,7 @@ TEST(ManifestIconSelector, NotSquareIconsAreIgnored) {
std::vector<gfx::Size> sizes;
sizes.push_back(gfx::Size(1024, 1023));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon.png", "", sizes, IconPurpose::ANY));
@@ -320,7 +320,7 @@ TEST(ManifestIconSelector, ClosestIconToIdeal) {
std::vector<gfx::Size> sizes_2;
sizes_2.push_back(gfx::Size(bit_small, bit_small));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
IconPurpose::ANY));
icons.push_back(
@@ -342,7 +342,7 @@ TEST(ManifestIconSelector, ClosestIconToIdeal) {
std::vector<gfx::Size> sizes_3;
sizes_3.push_back(gfx::Size(small_size, small_size));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_no_1.png", "", sizes_1,
IconPurpose::ANY));
icons.push_back(
@@ -363,7 +363,7 @@ TEST(ManifestIconSelector, ClosestIconToIdeal) {
std::vector<gfx::Size> sizes_2;
sizes_2.push_back(gfx::Size(big, big));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
IconPurpose::ANY));
icons.push_back(
@@ -385,7 +385,7 @@ TEST(ManifestIconSelector, ClosestIconToIdeal) {
std::vector<gfx::Size> sizes_3;
sizes_3.push_back(gfx::Size(bit_big, bit_big));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
IconPurpose::ANY));
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_2,
@@ -406,7 +406,7 @@ TEST(ManifestIconSelector, ClosestIconToIdeal) {
std::vector<gfx::Size> sizes_2;
sizes_2.push_back(gfx::Size(very_big, very_big));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
IconPurpose::ANY));
icons.push_back(
@@ -425,7 +425,7 @@ TEST(ManifestIconSelector, ClosestIconToIdeal) {
std::vector<gfx::Size> sizes_2;
sizes_2.push_back(gfx::Size(bit_big, bit_big));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
IconPurpose::ANY));
icons.push_back(
@@ -448,7 +448,7 @@ TEST(ManifestIconSelector, UseAnyIfNoIdealSize) {
std::vector<gfx::Size> sizes_2;
sizes_2.push_back(gfx::Size(0, 0));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon.png", "", sizes_1, IconPurpose::ANY));
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_2,
@@ -466,7 +466,7 @@ TEST(ManifestIconSelector, UseAnyIfNoIdealSize) {
std::vector<gfx::Size> sizes_2;
sizes_2.push_back(gfx::Size(0, 0));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", sizes_1,
IconPurpose::ANY));
icons.push_back(
@@ -482,7 +482,7 @@ TEST(ManifestIconSelector, UseAnyIfNoIdealSize) {
std::vector<gfx::Size> sizes;
sizes.push_back(gfx::Size(0, 0));
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
icons.push_back(
CreateIcon("http://foo.com/icon_no1.png", "", sizes, IconPurpose::ANY));
icons.push_back(
diff --git a/chromium/content/browser/manifest/manifest_manager_host.cc b/chromium/content/browser/manifest/manifest_manager_host.cc
index 0269f2c1446..2d58368b2e0 100644
--- a/chromium/content/browser/manifest/manifest_manager_host.cc
+++ b/chromium/content/browser/manifest/manifest_manager_host.cc
@@ -9,9 +9,9 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/manifest.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
namespace content {
@@ -66,12 +66,13 @@ void ManifestManagerHost::OnConnectionError() {
}
callbacks_.Clear();
for (auto& callback : callbacks)
- std::move(callback).Run(GURL(), Manifest());
+ std::move(callback).Run(GURL(), blink::Manifest());
}
-void ManifestManagerHost::OnRequestManifestResponse(int request_id,
- const GURL& url,
- const Manifest& manifest) {
+void ManifestManagerHost::OnRequestManifestResponse(
+ int request_id,
+ const GURL& url,
+ const blink::Manifest& manifest) {
auto callback = std::move(*callbacks_.Lookup(request_id));
callbacks_.Remove(request_id);
std::move(callback).Run(url, manifest);
diff --git a/chromium/content/browser/manifest/manifest_manager_host.h b/chromium/content/browser/manifest/manifest_manager_host.h
index 40c5c86e002..a49af365284 100644
--- a/chromium/content/browser/manifest/manifest_manager_host.h
+++ b/chromium/content/browser/manifest/manifest_manager_host.h
@@ -11,13 +11,16 @@
#include "content/common/manifest_observer.mojom.h"
#include "content/public/browser/web_contents_binding_set.h"
#include "content/public/browser/web_contents_observer.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h"
+#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
+
+namespace blink {
+struct Manifest;
+}
namespace content {
class RenderFrameHost;
class WebContents;
-struct Manifest;
// ManifestManagerHost is a helper class that allows callers to get the Manifest
// associated with the main frame of the observed WebContents. It handles the
@@ -30,7 +33,7 @@ class ManifestManagerHost : public WebContentsObserver,
~ManifestManagerHost() override;
using GetManifestCallback =
- base::OnceCallback<void(const GURL&, const Manifest&)>;
+ base::OnceCallback<void(const GURL&, const blink::Manifest&)>;
// Calls the given callback with the manifest associated with the main frame.
// If the main frame has no manifest or if getting it failed the callback will
@@ -51,7 +54,7 @@ class ManifestManagerHost : public WebContentsObserver,
void OnRequestManifestResponse(int request_id,
const GURL& url,
- const Manifest& manifest);
+ const blink::Manifest& manifest);
// mojom::ManifestUrlChangeObserver:
void ManifestUrlChanged(const base::Optional<GURL>& manifest_url) override;
diff --git a/chromium/content/browser/media/OWNERS b/chromium/content/browser/media/OWNERS
index 7d1710685d7..966a9171d93 100644
--- a/chromium/content/browser/media/OWNERS
+++ b/chromium/content/browser/media/OWNERS
@@ -1,11 +1,9 @@
file://media/OWNERS
olka@chromium.org
maxmorin@chromium.org
+miu@chromium.org
per-file media_devices_*=guidou@chromium.org
per-file midi_*=toyoshim@chromium.org
-# For changes related to the tab media indicators.
-per-file audio_stream_monitor*=miu@chromium.org
-
# COMPONENT: Internals>Media
diff --git a/chromium/content/browser/media/android/media_resource_getter_impl.cc b/chromium/content/browser/media/android/media_resource_getter_impl.cc
index 73d5d89a975..2633945e003 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.cc
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/path_service.h"
+#include "base/single_thread_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
@@ -97,7 +98,7 @@ static void RequestPlaformPathFromFileSystemURL(
url,
&platform_path);
base::FilePath data_storage_path;
- PathService::Get(base::DIR_ANDROID_APP_DATA, &data_storage_path);
+ base::PathService::Get(base::DIR_ANDROID_APP_DATA, &data_storage_path);
if (data_storage_path.IsParent(platform_path))
ReturnResultOnUIThread(std::move(callback), platform_path.value());
else
diff --git a/chromium/content/browser/media/audio_input_stream_broker.cc b/chromium/content/browser/media/audio_input_stream_broker.cc
new file mode 100644
index 00000000000..e0a2f97fdda
--- /dev/null
+++ b/chromium/content/browser/media/audio_input_stream_broker.cc
@@ -0,0 +1,219 @@
+// 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/media/audio_input_stream_broker.h"
+
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/media/media_internals.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/media_observer.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_client.h"
+#include "media/audio/audio_logging.h"
+#include "media/base/media_switches.h"
+#include "media/base/user_input_monitor.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+#if defined(OS_CHROMEOS)
+#include "content/browser/media/keyboard_mic_registration.h"
+#endif
+
+namespace content {
+
+AudioInputStreamBroker::AudioInputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
+ : AudioStreamBroker(render_process_id, render_frame_id),
+ device_id_(device_id),
+ params_(params),
+ shared_memory_count_(shared_memory_count),
+ enable_agc_(enable_agc),
+ deleter_(std::move(deleter)),
+ renderer_factory_client_(std::move(renderer_factory_client)),
+ observer_binding_(this),
+ weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(renderer_factory_client_);
+ DCHECK(deleter_);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("audio", "AudioInputStreamBroker", this);
+
+ // Unretained is safe because |this| owns |renderer_factory_client_|.
+ renderer_factory_client_.set_connection_error_handler(
+ base::BindOnce(&AudioInputStreamBroker::Cleanup, base::Unretained(this)));
+
+ // Notify RenderProcessHost about input stream so the renderer is not
+ // background.
+ auto* process_host = RenderProcessHost::FromID(render_process_id);
+ if (process_host)
+ process_host->OnMediaStreamAdded();
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream)) {
+ params_.set_format(media::AudioParameters::AUDIO_FAKE);
+ }
+
+ BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
+ // May be null in unit tests.
+ if (!browser_main_loop)
+ return;
+
+#if defined(OS_CHROMEOS)
+ if (params_.channel_layout() ==
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
+ browser_main_loop->keyboard_mic_registration()->Register();
+ }
+#else
+ user_input_monitor_ = static_cast<media::UserInputMonitorBase*>(
+ browser_main_loop->user_input_monitor());
+#endif
+}
+
+AudioInputStreamBroker::~AudioInputStreamBroker() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+#if defined(OS_CHROMEOS)
+ if (params_.channel_layout() ==
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
+ BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
+
+ // May be null in unit tests.
+ if (browser_main_loop)
+ browser_main_loop->keyboard_mic_registration()->Deregister();
+ }
+#else
+ if (user_input_monitor_)
+ user_input_monitor_->DisableKeyPressMonitoring();
+#endif
+
+ auto* process_host = RenderProcessHost::FromID(render_process_id());
+ if (process_host)
+ process_host->OnMediaStreamRemoved();
+
+ // TODO(https://crbug.com/829317) update tab recording indicator.
+
+ if (awaiting_created_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
+ "failed or cancelled");
+ }
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "AudioInputStreamBroker", this,
+ "disconnect reason",
+ static_cast<uint32_t>(disconnect_reason_));
+
+ UMA_HISTOGRAM_ENUMERATION("Media.Audio.Capture.StreamBrokerDisconnectReason",
+ disconnect_reason_);
+}
+
+void AudioInputStreamBroker::CreateStream(
+ audio::mojom::StreamFactory* factory) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!observer_binding_.is_bound());
+ DCHECK(!client_request_);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "CreateStream", this, "device id",
+ device_id_);
+ awaiting_created_ = true;
+
+ base::ReadOnlySharedMemoryRegion key_press_count_buffer;
+ if (user_input_monitor_) {
+ key_press_count_buffer =
+ user_input_monitor_->EnableKeyPressMonitoringWithMapping();
+ }
+
+ media::mojom::AudioInputStreamClientPtr client;
+ client_request_ = mojo::MakeRequest(&client);
+
+ media::mojom::AudioInputStreamPtr stream;
+ media::mojom::AudioInputStreamRequest stream_request =
+ mojo::MakeRequest(&stream);
+
+ media::mojom::AudioInputStreamObserverPtr observer_ptr;
+ observer_binding_.Bind(mojo::MakeRequest(&observer_ptr));
+
+ // Unretained is safe because |this| owns |observer_binding_|.
+ observer_binding_.set_connection_error_with_reason_handler(base::BindOnce(
+ &AudioInputStreamBroker::ObserverBindingLost, base::Unretained(this)));
+
+ // Note that the component id for AudioLog is used to differentiate between
+ // several users of the same audio log. Since this audio log is for a single
+ // stream, the component id used doesn't matter.
+ // TODO(https://crbug.com/836226) pass valid user input monitor handle when
+ // switching to audio service input streams.
+ constexpr int log_component_id = 0;
+ factory->CreateInputStream(
+ std::move(stream_request), std::move(client), std::move(observer_ptr),
+ MediaInternals::GetInstance()->CreateMojoAudioLog(
+ media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER,
+ log_component_id, render_process_id(), render_frame_id()),
+ device_id_, params_, shared_memory_count_, enable_agc_,
+ mojo::WrapReadOnlySharedMemoryRegion(std::move(key_press_count_buffer)),
+ base::BindOnce(&AudioInputStreamBroker::StreamCreated,
+ weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
+}
+
+void AudioInputStreamBroker::DidStartRecording() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // TODO(https://crbug.com/829317) update tab recording indicator.
+}
+
+void AudioInputStreamBroker::StreamCreated(
+ media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ awaiting_created_ = false;
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
+ !!data_pipe);
+
+ if (!data_pipe) {
+ disconnect_reason_ = media::mojom::AudioInputStreamObserver::
+ DisconnectReason::kStreamCreationFailed;
+ Cleanup();
+ return;
+ }
+
+ DCHECK(stream_id.has_value());
+ DCHECK(renderer_factory_client_);
+ renderer_factory_client_->StreamCreated(
+ std::move(stream), std::move(client_request_), std::move(data_pipe),
+ initially_muted, stream_id);
+}
+void AudioInputStreamBroker::ObserverBindingLost(
+ uint32_t reason,
+ const std::string& description) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ const uint32_t maxValidReason = static_cast<uint32_t>(
+ media::mojom::AudioInputStreamObserver::DisconnectReason::kMaxValue);
+ if (reason > maxValidReason) {
+ DLOG(ERROR) << "Invalid reason: " << reason;
+ } else if (disconnect_reason_ == media::mojom::AudioInputStreamObserver::
+ DisconnectReason::kDocumentDestroyed) {
+ disconnect_reason_ =
+ static_cast<media::mojom::AudioInputStreamObserver::DisconnectReason>(
+ reason);
+ }
+
+ Cleanup();
+}
+
+void AudioInputStreamBroker::Cleanup() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ std::move(deleter_).Run(this);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_input_stream_broker.h b/chromium/content/browser/media/audio_input_stream_broker.h
new file mode 100644
index 00000000000..524fb3408e3
--- /dev/null
+++ b/chromium/content/browser/media/audio_input_stream_broker.h
@@ -0,0 +1,86 @@
+// 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_MEDIA_AUDIO_INPUT_STREAM_BROKER_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_INPUT_STREAM_BROKER_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "content/browser/media/audio_stream_broker.h"
+#include "content/common/content_export.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+
+namespace media {
+class UserInputMonitorBase;
+}
+
+namespace content {
+
+// AudioInputStreamBroker is used to broker a connection between a client
+// (typically renderer) and the audio service. It is operated on the UI thread.
+class CONTENT_EXPORT AudioInputStreamBroker final
+ : public AudioStreamBroker,
+ public media::mojom::AudioInputStreamObserver {
+ public:
+ AudioInputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client);
+
+ ~AudioInputStreamBroker() final;
+
+ // Creates the stream.
+ void CreateStream(audio::mojom::StreamFactory* factory) final;
+
+ // media::AudioInputStreamObserver implementation.
+ void DidStartRecording() final;
+
+ private:
+ void StreamCreated(media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id);
+
+ void ObserverBindingLost(uint32_t reason, const std::string& description);
+
+ void Cleanup();
+
+ const std::string device_id_;
+ media::AudioParameters params_;
+ const uint32_t shared_memory_count_;
+ const bool enable_agc_;
+ media::UserInputMonitorBase* user_input_monitor_ = nullptr;
+
+ // Indicates that CreateStream has been called, but not StreamCreated.
+ bool awaiting_created_ = false;
+
+ DeleterCallback deleter_;
+
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client_;
+ mojo::Binding<AudioInputStreamObserver> observer_binding_;
+ media::mojom::AudioInputStreamClientRequest client_request_;
+
+ media::mojom::AudioInputStreamObserver::DisconnectReason disconnect_reason_ =
+ media::mojom::AudioInputStreamObserver::DisconnectReason::
+ kDocumentDestroyed;
+
+ base::WeakPtrFactory<AudioInputStreamBroker> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioInputStreamBroker);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_AUDIO_INPUT_STREAM_BROKER_H_
diff --git a/chromium/content/browser/media/audio_input_stream_broker_unittest.cc b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
new file mode 100644
index 00000000000..809f63f1504
--- /dev/null
+++ b/chromium/content/browser/media/audio_input_stream_broker_unittest.cc
@@ -0,0 +1,278 @@
+// 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/media/audio_input_stream_broker.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/sync_socket.h"
+#include "base/test/mock_callback.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "services/audio/public/cpp/fake_stream_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Test;
+using ::testing::Mock;
+using ::testing::StrictMock;
+using ::testing::InSequence;
+
+namespace content {
+
+namespace {
+
+const int kRenderProcessId = 123;
+const int kRenderFrameId = 234;
+const uint32_t kShMemCount = 10;
+const bool kEnableAgc = false;
+const char kDeviceId[] = "testdeviceid";
+const bool kInitiallyMuted = false;
+
+media::AudioParameters TestParams() {
+ return media::AudioParameters::UnavailableDeviceParams();
+}
+
+using MockDeleterCallback = StrictMock<
+ base::MockCallback<base::OnceCallback<void(AudioStreamBroker*)>>>;
+
+class MockRendererAudioInputStreamFactoryClient
+ : public mojom::RendererAudioInputStreamFactoryClient {
+ public:
+ MockRendererAudioInputStreamFactoryClient() : binding_(this) {}
+ ~MockRendererAudioInputStreamFactoryClient() override {}
+
+ mojom::RendererAudioInputStreamFactoryClientPtr MakePtr() {
+ mojom::RendererAudioInputStreamFactoryClientPtr ret;
+ binding_.Bind(mojo::MakeRequest(&ret));
+ return ret;
+ }
+
+ MOCK_METHOD0(OnStreamCreated, void());
+
+ void StreamCreated(
+ media::mojom::AudioInputStreamPtr input_stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::AudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override {
+ EXPECT_TRUE(stream_id.has_value());
+ input_stream_ = std::move(input_stream);
+ client_request_ = std::move(client_request);
+ OnStreamCreated();
+ }
+
+ void CloseBinding() { binding_.Close(); }
+
+ private:
+ mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> binding_;
+ media::mojom::AudioInputStreamPtr input_stream_;
+ media::mojom::AudioInputStreamClientRequest client_request_;
+ DISALLOW_COPY_AND_ASSIGN(MockRendererAudioInputStreamFactoryClient);
+};
+
+class MockStreamFactory : public audio::FakeStreamFactory {
+ public:
+ MockStreamFactory() {}
+ ~MockStreamFactory() final {}
+
+ // State of an expected stream creation. |device_id| and |params| are set
+ // ahead of time and verified during request. The other fields are filled in
+ // when the request is received.
+ struct StreamRequestData {
+ StreamRequestData(const std::string& device_id,
+ const media::AudioParameters& params)
+ : device_id(device_id), params(params) {}
+
+ bool requested = false;
+ media::mojom::AudioInputStreamRequest stream_request;
+ media::mojom::AudioInputStreamClientPtr client;
+ media::mojom::AudioInputStreamObserverPtr observer;
+ media::mojom::AudioLogPtr log;
+ const std::string device_id;
+ const media::AudioParameters params;
+ uint32_t shared_memory_count;
+ bool enable_agc;
+ mojo::ScopedSharedBufferHandle key_press_count_buffer;
+ CreateInputStreamCallback created_callback;
+ };
+
+ void ExpectStreamCreation(StreamRequestData* ex) {
+ stream_request_data_ = ex;
+ }
+
+ private:
+ void CreateInputStream(media::mojom::AudioInputStreamRequest stream_request,
+ media::mojom::AudioInputStreamClientPtr client,
+ media::mojom::AudioInputStreamObserverPtr observer,
+ media::mojom::AudioLogPtr log,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ mojo::ScopedSharedBufferHandle key_press_count_buffer,
+ CreateInputStreamCallback created_callback) final {
+ // No way to cleanly exit the test here in case of failure, so use CHECK.
+ CHECK(stream_request_data_);
+ EXPECT_EQ(stream_request_data_->device_id, device_id);
+ EXPECT_TRUE(stream_request_data_->params.Equals(params));
+ stream_request_data_->requested = true;
+ stream_request_data_->stream_request = std::move(stream_request);
+ stream_request_data_->client = std::move(client);
+ stream_request_data_->observer = std::move(observer);
+ stream_request_data_->log = std::move(log);
+ stream_request_data_->shared_memory_count = shared_memory_count;
+ stream_request_data_->enable_agc = enable_agc;
+ stream_request_data_->key_press_count_buffer =
+ std::move(key_press_count_buffer);
+ stream_request_data_->created_callback = std::move(created_callback);
+ }
+
+ StreamRequestData* stream_request_data_;
+ DISALLOW_COPY_AND_ASSIGN(MockStreamFactory);
+};
+
+struct TestEnvironment {
+ TestEnvironment()
+ : broker(std::make_unique<AudioInputStreamBroker>(
+ kRenderProcessId,
+ kRenderFrameId,
+ kDeviceId,
+ TestParams(),
+ kShMemCount,
+ kEnableAgc,
+ deleter.Get(),
+ renderer_factory_client.MakePtr())) {}
+
+ void RunUntilIdle() { thread_bundle.RunUntilIdle(); }
+
+ TestBrowserThreadBundle thread_bundle;
+ MockDeleterCallback deleter;
+ StrictMock<MockRendererAudioInputStreamFactoryClient> renderer_factory_client;
+ std::unique_ptr<AudioInputStreamBroker> broker;
+ MockStreamFactory stream_factory;
+ audio::mojom::StreamFactoryPtr factory_ptr = stream_factory.MakePtr();
+};
+
+} // namespace
+
+TEST(AudioInputStreamBrokerTest, StoresProcessAndFrameId) {
+ TestBrowserThreadBundle thread_bundle;
+ MockDeleterCallback deleter;
+ StrictMock<MockRendererAudioInputStreamFactoryClient> renderer_factory_client;
+
+ AudioInputStreamBroker broker(
+ kRenderProcessId, kRenderFrameId, kDeviceId, TestParams(), kShMemCount,
+ kEnableAgc, deleter.Get(), renderer_factory_client.MakePtr());
+
+ EXPECT_EQ(kRenderProcessId, broker.render_process_id());
+ EXPECT_EQ(kRenderFrameId, broker.render_frame_id());
+}
+
+TEST(AudioInputStreamBrokerTest, StreamCreationSuccess_Propagates) {
+ TestEnvironment env;
+ MockStreamFactory::StreamRequestData stream_request_data(kDeviceId,
+ TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+
+ // Set up test IPC primitives.
+ const size_t shmem_size = 456;
+ base::SyncSocket socket1, socket2;
+ base::SyncSocket::CreatePair(&socket1, &socket2);
+ std::move(stream_request_data.created_callback)
+ .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ mojo::WrapPlatformFile(socket1.Release())},
+ kInitiallyMuted, base::UnguessableToken::Create());
+
+ EXPECT_CALL(env.renderer_factory_client, OnStreamCreated());
+
+ env.RunUntilIdle();
+
+ Mock::VerifyAndClear(&env.renderer_factory_client);
+
+ env.broker.reset();
+}
+
+TEST(AudioInputStreamBrokerTest, StreamCreationFailure_CallsDeleter) {
+ TestEnvironment env;
+ MockStreamFactory::StreamRequestData stream_request_data(kDeviceId,
+ TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+
+ std::move(stream_request_data.created_callback)
+ .Run(nullptr, kInitiallyMuted, base::nullopt);
+
+ env.RunUntilIdle();
+}
+
+TEST(AudioInputStreamBrokerTest, RendererFactoryClientDisconnect_CallsDeleter) {
+ InSequence seq;
+ TestEnvironment env;
+ MockStreamFactory::StreamRequestData stream_request_data(kDeviceId,
+ TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+ EXPECT_TRUE(stream_request_data.requested);
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+ env.renderer_factory_client.CloseBinding();
+ env.RunUntilIdle();
+ Mock::VerifyAndClear(&env.deleter);
+
+ env.stream_factory.CloseBinding();
+ env.RunUntilIdle();
+}
+
+TEST(AudioInputStreamBrokerTest, ObserverDisconnect_CallsDeleter) {
+ InSequence seq;
+ TestEnvironment env;
+ MockStreamFactory::StreamRequestData stream_request_data(kDeviceId,
+ TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+ EXPECT_TRUE(stream_request_data.requested);
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+ stream_request_data.observer.reset();
+ env.RunUntilIdle();
+ Mock::VerifyAndClear(&env.deleter);
+
+ env.stream_factory.CloseBinding();
+ env.RunUntilIdle();
+}
+
+TEST(AudioInputStreamBrokerTest,
+ FactoryDisconnectDuringConstruction_CallsDeleter) {
+ TestEnvironment env;
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.stream_factory.CloseBinding();
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+
+ env.RunUntilIdle();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker.cc b/chromium/content/browser/media/audio_loopback_stream_broker.cc
new file mode 100644
index 00000000000..d7cba0187ea
--- /dev/null
+++ b/chromium/content/browser/media/audio_loopback_stream_broker.cc
@@ -0,0 +1,164 @@
+// 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/media/audio_loopback_stream_broker.h"
+
+#include <utility>
+
+#include "base/unguessable_token.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+
+namespace content {
+
+AudioStreamBrokerFactory::LoopbackSource::LoopbackSource() = default;
+
+AudioStreamBrokerFactory::LoopbackSource::LoopbackSource(
+ WebContents* source_contents)
+ : WebContentsObserver(source_contents) {
+ DCHECK(source_contents);
+}
+
+AudioStreamBrokerFactory::LoopbackSource::~LoopbackSource() = default;
+
+base::UnguessableToken AudioStreamBrokerFactory::LoopbackSource::GetGroupID() {
+ if (WebContentsImpl* source_contents =
+ static_cast<WebContentsImpl*>(web_contents())) {
+ return source_contents->GetAudioStreamFactory()->group_id();
+ }
+ return base::UnguessableToken();
+}
+
+void AudioStreamBrokerFactory::LoopbackSource::OnStartCapturing() {
+ if (WebContentsImpl* source_contents =
+ static_cast<WebContentsImpl*>(web_contents())) {
+ source_contents->IncrementCapturerCount(gfx::Size());
+ }
+}
+
+void AudioStreamBrokerFactory::LoopbackSource::OnStopCapturing() {
+ if (WebContentsImpl* source_contents =
+ static_cast<WebContentsImpl*>(web_contents())) {
+ source_contents->DecrementCapturerCount();
+ }
+}
+
+void AudioStreamBrokerFactory::LoopbackSource::WebContentsDestroyed() {
+ if (on_gone_closure_)
+ std::move(on_gone_closure_).Run();
+}
+
+AudioLoopbackStreamBroker::AudioLoopbackStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ std::unique_ptr<AudioStreamBrokerFactory::LoopbackSource> source,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool mute_source,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
+ : AudioStreamBroker(render_process_id, render_frame_id),
+ source_(std::move(source)),
+ params_(params),
+ shared_memory_count_(shared_memory_count),
+ deleter_(std::move(deleter)),
+ renderer_factory_client_(std::move(renderer_factory_client)),
+ observer_binding_(this),
+ weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(source_);
+ DCHECK(source_->GetGroupID());
+ DCHECK(renderer_factory_client_);
+ DCHECK(deleter_);
+
+ // Unretained is safe because |this| owns |source_|.
+ source_->set_on_gone_closure(base::BindOnce(
+ &AudioLoopbackStreamBroker::Cleanup, base::Unretained(this)));
+
+ if (mute_source) {
+ muter_.emplace(source_->GetGroupID());
+ }
+
+ // Unretained is safe because |this| owns |renderer_factory_client_|.
+ renderer_factory_client_.set_connection_error_handler(base::BindOnce(
+ &AudioLoopbackStreamBroker::Cleanup, base::Unretained(this)));
+
+ // Notify the source that we are capturing from it, to prevent its
+ // backgrounding.
+ source_->OnStartCapturing();
+
+ // Notify RenderProcessHost about the input stream, so that the destination
+ // renderer does not get background.
+ if (auto* process_host = RenderProcessHost::FromID(render_process_id))
+ process_host->OnMediaStreamAdded();
+}
+
+AudioLoopbackStreamBroker::~AudioLoopbackStreamBroker() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ source_->OnStopCapturing();
+
+ if (auto* process_host = RenderProcessHost::FromID(render_process_id()))
+ process_host->OnMediaStreamRemoved();
+}
+
+void AudioLoopbackStreamBroker::CreateStream(
+ audio::mojom::StreamFactory* factory) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!observer_binding_.is_bound());
+ DCHECK(!client_request_);
+ DCHECK(source_->GetGroupID());
+
+ if (muter_) // Mute the source.
+ muter_->Connect(factory);
+
+ media::mojom::AudioInputStreamClientPtr client;
+ client_request_ = mojo::MakeRequest(&client);
+
+ media::mojom::AudioInputStreamPtr stream;
+ media::mojom::AudioInputStreamRequest stream_request =
+ mojo::MakeRequest(&stream);
+
+ media::mojom::AudioInputStreamObserverPtr observer_ptr;
+ observer_binding_.Bind(mojo::MakeRequest(&observer_ptr));
+
+ // Unretained is safe because |this| owns |observer_binding_|.
+ observer_binding_.set_connection_error_handler(base::BindOnce(
+ &AudioLoopbackStreamBroker::Cleanup, base::Unretained(this)));
+
+ factory->CreateLoopbackStream(
+ std::move(stream_request), std::move(client), std::move(observer_ptr),
+ params_, shared_memory_count_, source_->GetGroupID(),
+ base::BindOnce(&AudioLoopbackStreamBroker::StreamCreated,
+ weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
+}
+
+void AudioLoopbackStreamBroker::DidStartRecording() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+void AudioLoopbackStreamBroker::StreamCreated(
+ media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!data_pipe) {
+ Cleanup();
+ return;
+ }
+
+ DCHECK(renderer_factory_client_);
+ renderer_factory_client_->StreamCreated(
+ std::move(stream), std::move(client_request_), std::move(data_pipe),
+ false /* |initially_muted|: Loopback streams are never muted. */,
+ base::nullopt /* |stream_id|: Loopback streams don't have ids */);
+}
+
+void AudioLoopbackStreamBroker::Cleanup() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ std::move(deleter_).Run(this);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker.h b/chromium/content/browser/media/audio_loopback_stream_broker.h
new file mode 100644
index 00000000000..71778564a65
--- /dev/null
+++ b/chromium/content/browser/media/audio_loopback_stream_broker.h
@@ -0,0 +1,74 @@
+// 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_MEDIA_AUDIO_LOOPBACK_STREAM_BROKER_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_LOOPBACK_STREAM_BROKER_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "content/browser/media/audio_muting_session.h"
+#include "content/browser/media/audio_stream_broker.h"
+#include "content/common/content_export.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+
+namespace content {
+
+// AudioLoopbackStreamBroker is used to broker a connection between a client
+// (typically renderer) and the audio service. It is operated on the UI thread.
+class CONTENT_EXPORT AudioLoopbackStreamBroker final
+ : public AudioStreamBroker,
+ public media::mojom::AudioInputStreamObserver {
+ public:
+ AudioLoopbackStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ std::unique_ptr<AudioStreamBrokerFactory::LoopbackSource> source,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool mute_source,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client);
+
+ ~AudioLoopbackStreamBroker() final;
+
+ // Creates the stream.
+ void CreateStream(audio::mojom::StreamFactory* factory) final;
+
+ // media::AudioInputStreamObserver implementation.
+ void DidStartRecording() final;
+
+ private:
+ void StreamCreated(media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe);
+ void Cleanup();
+
+ const std::unique_ptr<AudioStreamBrokerFactory::LoopbackSource> source_;
+ const media::AudioParameters params_;
+ const uint32_t shared_memory_count_;
+
+ DeleterCallback deleter_;
+
+ // Constructed only if the loopback source playback should be muted while the
+ // loopback stream is running.
+ base::Optional<AudioMutingSession> muter_;
+
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client_;
+ mojo::Binding<AudioInputStreamObserver> observer_binding_;
+ media::mojom::AudioInputStreamClientRequest client_request_;
+
+ base::WeakPtrFactory<AudioLoopbackStreamBroker> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioLoopbackStreamBroker);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_AUDIO_LOOPBACK_STREAM_BROKER_H_
diff --git a/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc b/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
new file mode 100644
index 00000000000..cfe6cc7ccb3
--- /dev/null
+++ b/chromium/content/browser/media/audio_loopback_stream_broker_unittest.cc
@@ -0,0 +1,374 @@
+// 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/media/audio_loopback_stream_broker.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/sync_socket.h"
+#include "base/test/mock_callback.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "services/audio/public/cpp/fake_stream_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Test;
+using ::testing::Mock;
+using ::testing::NiceMock;
+using ::testing::StrictMock;
+using ::testing::InSequence;
+
+namespace content {
+
+namespace {
+
+const int kRenderProcessId = 123;
+const int kRenderFrameId = 234;
+const uint32_t kShMemCount = 10;
+
+media::AudioParameters TestParams() {
+ return media::AudioParameters::UnavailableDeviceParams();
+}
+
+class MockSource : public AudioStreamBrokerFactory::LoopbackSource {
+ public:
+ explicit MockSource(const base::UnguessableToken& group_id)
+ : group_id_(group_id) {}
+ ~MockSource() override {}
+
+ // AudioStreamBrokerFactory::LoopbackSource mocking.
+ base::UnguessableToken GetGroupID() override { return group_id_; }
+ MOCK_METHOD0(OnStartCapturing, void(void));
+ MOCK_METHOD0(OnStopCapturing, void(void));
+
+ private:
+ base::UnguessableToken group_id_;
+ DISALLOW_COPY_AND_ASSIGN(MockSource);
+};
+
+using MockDeleterCallback = StrictMock<
+ base::MockCallback<base::OnceCallback<void(AudioStreamBroker*)>>>;
+
+class MockRendererAudioInputStreamFactoryClient
+ : public mojom::RendererAudioInputStreamFactoryClient {
+ public:
+ MockRendererAudioInputStreamFactoryClient() : binding_(this) {}
+ ~MockRendererAudioInputStreamFactoryClient() override {}
+
+ mojom::RendererAudioInputStreamFactoryClientPtr MakePtr() {
+ mojom::RendererAudioInputStreamFactoryClientPtr ret;
+ binding_.Bind(mojo::MakeRequest(&ret));
+ return ret;
+ }
+
+ MOCK_METHOD0(OnStreamCreated, void());
+
+ void StreamCreated(
+ media::mojom::AudioInputStreamPtr input_stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::AudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override {
+ // Loopback streams have no stream ids.
+ EXPECT_FALSE(stream_id.has_value());
+ input_stream_ = std::move(input_stream);
+ client_request_ = std::move(client_request);
+ OnStreamCreated();
+ }
+
+ void CloseBinding() { binding_.Close(); }
+
+ private:
+ mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> binding_;
+ media::mojom::AudioInputStreamPtr input_stream_;
+ media::mojom::AudioInputStreamClientRequest client_request_;
+};
+
+class MockStreamFactory : public audio::FakeStreamFactory {
+ public:
+ MockStreamFactory() {}
+ ~MockStreamFactory() final {}
+
+ // State of an expected stream creation. |device_id| and |params| are set
+ // ahead of time and verified during request. The other fields are filled in
+ // when the request is received.
+ struct StreamRequestData {
+ StreamRequestData(const base::UnguessableToken& group_id,
+ const media::AudioParameters& params)
+ : params(params), group_id(group_id) {}
+
+ bool requested = false;
+ media::mojom::AudioInputStreamRequest stream_request;
+ media::mojom::AudioInputStreamClientPtr client;
+ media::mojom::AudioInputStreamObserverPtr observer;
+ const media::AudioParameters params;
+ uint32_t shared_memory_count;
+ base::UnguessableToken group_id;
+ mojo::ScopedSharedBufferHandle key_press_count_buffer;
+ CreateLoopbackStreamCallback created_callback;
+ audio::mojom::LocalMuterAssociatedRequest muter_request;
+ };
+
+ void ExpectStreamCreation(StreamRequestData* ex) {
+ stream_request_data_ = ex;
+ }
+
+ MOCK_METHOD1(IsMuting, void(const base::UnguessableToken&));
+
+ private:
+ void CreateLoopbackStream(
+ media::mojom::AudioInputStreamRequest stream_request,
+ media::mojom::AudioInputStreamClientPtr client,
+ media::mojom::AudioInputStreamObserverPtr observer,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ const base::UnguessableToken& group_id,
+ CreateLoopbackStreamCallback created_callback) final {
+ // No way to cleanly exit the test here in case of failure, so use CHECK.
+ CHECK(stream_request_data_);
+ EXPECT_EQ(stream_request_data_->group_id, group_id);
+ EXPECT_TRUE(stream_request_data_->params.Equals(params));
+ stream_request_data_->requested = true;
+ stream_request_data_->stream_request = std::move(stream_request);
+ stream_request_data_->client = std::move(client);
+ stream_request_data_->observer = std::move(observer);
+ stream_request_data_->shared_memory_count = shared_memory_count;
+ stream_request_data_->created_callback = std::move(created_callback);
+ }
+
+ void BindMuter(audio::mojom::LocalMuterAssociatedRequest request,
+ const base::UnguessableToken& group_id) final {
+ stream_request_data_->muter_request = std::move(request);
+ IsMuting(group_id);
+ }
+
+ StreamRequestData* stream_request_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockStreamFactory);
+};
+
+const bool kMuteSource = true;
+
+struct TestEnvironment {
+ TestEnvironment(const base::UnguessableToken& group_id, bool mute_source) {
+ // Muting should not start until CreateStream() is called.
+ EXPECT_CALL(stream_factory, IsMuting(_)).Times(0);
+ auto mock_source = std::make_unique<NiceMock<MockSource>>(group_id);
+ source = mock_source.get();
+ broker = std::make_unique<AudioLoopbackStreamBroker>(
+ kRenderProcessId, kRenderFrameId, std::move(mock_source), TestParams(),
+ kShMemCount, mute_source, deleter.Get(),
+ renderer_factory_client.MakePtr());
+ }
+
+ void RunUntilIdle() { thread_bundle.RunUntilIdle(); }
+
+ TestBrowserThreadBundle thread_bundle;
+ MockDeleterCallback deleter;
+ MockSource* source;
+ StrictMock<MockRendererAudioInputStreamFactoryClient> renderer_factory_client;
+ std::unique_ptr<AudioLoopbackStreamBroker> broker;
+ MockStreamFactory stream_factory;
+ audio::mojom::StreamFactoryPtr factory_ptr = stream_factory.MakePtr();
+};
+
+} // namespace
+
+TEST(AudioLoopbackStreamBrokerTest, StoresProcessAndFrameId) {
+ InSequence seq;
+ TestBrowserThreadBundle thread_bundle;
+ MockDeleterCallback deleter;
+ StrictMock<MockRendererAudioInputStreamFactoryClient> renderer_factory_client;
+ auto source = std::make_unique<StrictMock<MockSource>>(
+ base::UnguessableToken::Create());
+ MockSource* mock_source = source.get();
+
+ EXPECT_CALL(*mock_source, OnStartCapturing());
+
+ AudioLoopbackStreamBroker broker(kRenderProcessId, kRenderFrameId,
+ std::move(source), TestParams(), kShMemCount,
+ !kMuteSource, deleter.Get(),
+ renderer_factory_client.MakePtr());
+
+ EXPECT_EQ(kRenderProcessId, broker.render_process_id());
+ EXPECT_EQ(kRenderFrameId, broker.render_frame_id());
+
+ EXPECT_CALL(*mock_source, OnStopCapturing());
+}
+
+TEST(AudioLoopbackStreamBrokerTest, StreamCreationSuccess_Propagates) {
+ TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
+ MockStreamFactory::StreamRequestData stream_request_data(
+ env.source->GetGroupID(), TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+
+ // Set up test IPC primitives.
+ const size_t shmem_size = 456;
+ base::SyncSocket socket1, socket2;
+ base::SyncSocket::CreatePair(&socket1, &socket2);
+ std::move(stream_request_data.created_callback)
+ .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ mojo::WrapPlatformFile(socket1.Release())});
+
+ EXPECT_CALL(env.renderer_factory_client, OnStreamCreated());
+
+ env.RunUntilIdle();
+
+ Mock::VerifyAndClear(&env.renderer_factory_client);
+ env.broker.reset();
+}
+
+TEST(AudioLoopbackStreamBrokerTest, MutedStreamCreation_Mutes) {
+ TestEnvironment env(base::UnguessableToken::Create(), kMuteSource);
+ MockStreamFactory::StreamRequestData stream_request_data(
+ env.source->GetGroupID(), TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ EXPECT_CALL(env.stream_factory, IsMuting(env.source->GetGroupID()));
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+
+ // Set up test IPC primitives.
+ const size_t shmem_size = 456;
+ base::SyncSocket socket1, socket2;
+ base::SyncSocket::CreatePair(&socket1, &socket2);
+ std::move(stream_request_data.created_callback)
+ .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ mojo::WrapPlatformFile(socket1.Release())});
+
+ EXPECT_CALL(env.renderer_factory_client, OnStreamCreated());
+
+ env.RunUntilIdle();
+
+ Mock::VerifyAndClear(&env.renderer_factory_client);
+ env.broker.reset();
+}
+
+TEST(AudioLoopbackStreamBrokerTest, SourceGone_CallsDeleter) {
+ TestEnvironment env(base::UnguessableToken::Create(), kMuteSource);
+ MockStreamFactory::StreamRequestData stream_request_data(
+ env.source->GetGroupID(), TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ EXPECT_CALL(env.stream_factory, IsMuting(env.source->GetGroupID()));
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+
+ // Set up test IPC primitives.
+ const size_t shmem_size = 456;
+ base::SyncSocket socket1, socket2;
+ base::SyncSocket::CreatePair(&socket1, &socket2);
+ std::move(stream_request_data.created_callback)
+ .Run({base::in_place, mojo::SharedBufferHandle::Create(shmem_size),
+ mojo::WrapPlatformFile(socket1.Release())});
+
+ EXPECT_CALL(env.renderer_factory_client, OnStreamCreated());
+
+ env.RunUntilIdle();
+
+ Mock::VerifyAndClear(&env.renderer_factory_client);
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+
+ env.source->WebContentsDestroyed();
+
+ env.RunUntilIdle();
+}
+
+TEST(AudioLoopbackStreamBrokerTest, StreamCreationFailure_CallsDeleter) {
+ TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
+ MockStreamFactory::StreamRequestData stream_request_data(
+ env.source->GetGroupID(), TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+
+ std::move(stream_request_data.created_callback).Run(nullptr);
+
+ env.RunUntilIdle();
+}
+
+TEST(AudioLoopbackStreamBrokerTest,
+ RendererFactoryClientDisconnect_CallsDeleter) {
+ TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
+ MockStreamFactory::StreamRequestData stream_request_data(
+ env.source->GetGroupID(), TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+ EXPECT_TRUE(stream_request_data.requested);
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+ env.renderer_factory_client.CloseBinding();
+ env.RunUntilIdle();
+ Mock::VerifyAndClear(&env.deleter);
+
+ env.stream_factory.CloseBinding();
+ env.RunUntilIdle();
+}
+
+TEST(AudioLoopbackStreamBrokerTest, ObserverDisconnect_CallsDeleter) {
+ TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
+ MockStreamFactory::StreamRequestData stream_request_data(
+ env.source->GetGroupID(), TestParams());
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ EXPECT_CALL(env.stream_factory, IsMuting(_)).Times(0);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+ EXPECT_TRUE(stream_request_data.requested);
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+ stream_request_data.observer.reset();
+ env.RunUntilIdle();
+ Mock::VerifyAndClear(&env.deleter);
+
+ env.stream_factory.CloseBinding();
+ env.RunUntilIdle();
+}
+
+TEST(AudioLoopbackStreamBrokerTest,
+ FactoryDisconnectDuringConstruction_CallsDeleter) {
+ TestEnvironment env(base::UnguessableToken::Create(), !kMuteSource);
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.stream_factory.CloseBinding();
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+
+ env.RunUntilIdle();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_muting_session.cc b/chromium/content/browser/media/audio_muting_session.cc
new file mode 100644
index 00000000000..6e8c13d3dc7
--- /dev/null
+++ b/chromium/content/browser/media/audio_muting_session.cc
@@ -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.
+
+#include "content/browser/media/audio_muting_session.h"
+
+namespace content {
+
+AudioMutingSession::AudioMutingSession(const base::UnguessableToken& group_id)
+ : group_id_(group_id) {}
+
+AudioMutingSession::~AudioMutingSession(){};
+
+void AudioMutingSession::Connect(audio::mojom::StreamFactory* factory) {
+ if (muter_)
+ muter_.reset();
+
+ DCHECK(factory);
+ factory->BindMuter(mojo::MakeRequest(&muter_), group_id_);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_muting_session.h b/chromium/content/browser/media/audio_muting_session.h
new file mode 100644
index 00000000000..a13c13c17aa
--- /dev/null
+++ b/chromium/content/browser/media/audio_muting_session.h
@@ -0,0 +1,32 @@
+// 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_MEDIA_AUDIO_MUTING_SESSION_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_MUTING_SESSION_H_
+
+#include <utility>
+
+#include "base/unguessable_token.h"
+#include "content/common/content_export.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+
+namespace content {
+
+class CONTENT_EXPORT AudioMutingSession {
+ public:
+ explicit AudioMutingSession(const base::UnguessableToken& group_id);
+ ~AudioMutingSession();
+
+ void Connect(audio::mojom::StreamFactory* factory);
+
+ private:
+ const base::UnguessableToken group_id_;
+ audio::mojom::LocalMuterAssociatedPtr muter_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioMutingSession);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_AUDIO_MUTING_SESSION_H_
diff --git a/chromium/content/browser/media/audio_output_stream_broker.cc b/chromium/content/browser/media/audio_output_stream_broker.cc
new file mode 100644
index 00000000000..21cf65ea694
--- /dev/null
+++ b/chromium/content/browser/media/audio_output_stream_broker.cc
@@ -0,0 +1,157 @@
+// 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/media/audio_output_stream_broker.h"
+
+#include <utility>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
+#include "content/browser/media/media_internals.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/media_observer.h"
+#include "content/public/common/content_client.h"
+#include "media/audio/audio_logging.h"
+
+namespace content {
+
+AudioOutputStreamBroker::AudioOutputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id,
+ DeleterCallback deleter,
+ media::mojom::AudioOutputStreamProviderClientPtr client)
+ : AudioStreamBroker(render_process_id, render_frame_id),
+ output_device_id_(output_device_id),
+ params_(params),
+ group_id_(group_id),
+ deleter_(std::move(deleter)),
+ client_(std::move(client)),
+ observer_(render_process_id, render_frame_id, stream_id),
+ observer_binding_(&observer_),
+ weak_ptr_factory_(this) {
+ DCHECK(client_);
+ DCHECK(deleter_);
+ DCHECK(group_id_);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("audio", "AudioOutputStreamBroker", this);
+
+ MediaObserver* media_observer =
+ GetContentClient()->browser()->GetMediaObserver();
+
+ // May be null in unit tests.
+ if (media_observer)
+ media_observer->OnCreatingAudioStream(render_process_id, render_frame_id);
+
+ // Unretained is safe because |this| owns |client_|
+ client_.set_connection_error_handler(base::BindOnce(
+ &AudioOutputStreamBroker::Cleanup, base::Unretained(this)));
+}
+
+AudioOutputStreamBroker::~AudioOutputStreamBroker() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+
+ if (awaiting_created_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
+ "failed or cancelled");
+ }
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "AudioOutputStreamBroker", this,
+ "disconnect reason",
+ static_cast<uint32_t>(disconnect_reason_));
+
+ UMA_HISTOGRAM_ENUMERATION("Media.Audio.Render.StreamBrokerDisconnectReason",
+ disconnect_reason_);
+}
+
+void AudioOutputStreamBroker::CreateStream(
+ audio::mojom::StreamFactory* factory) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ DCHECK(!observer_binding_.is_bound());
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "CreateStream", this, "device id",
+ output_device_id_);
+ awaiting_created_ = true;
+
+ // Set up observer ptr. Unretained is safe because |this| owns
+ // |observer_binding_|.
+ media::mojom::AudioOutputStreamObserverAssociatedPtrInfo ptr_info;
+ observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
+ observer_binding_.set_connection_error_with_reason_handler(base::BindOnce(
+ &AudioOutputStreamBroker::ObserverBindingLost, base::Unretained(this)));
+
+ media::mojom::AudioOutputStreamPtr stream;
+ media::mojom::AudioOutputStreamRequest stream_request =
+ mojo::MakeRequest(&stream);
+
+ // Note that the component id for AudioLog is used to differentiate between
+ // several users of the same audio log. Since this audio log is for a single
+ // stream, the component id used doesn't matter.
+ constexpr int log_component_id = 0;
+ factory->CreateOutputStream(
+ std::move(stream_request), std::move(ptr_info),
+ MediaInternals::GetInstance()->CreateMojoAudioLog(
+ media::AudioLogFactory::AudioComponent::AUDIO_OUTPUT_CONTROLLER,
+ log_component_id, render_process_id(), render_frame_id()),
+ output_device_id_, params_, group_id_,
+ base::BindOnce(&AudioOutputStreamBroker::StreamCreated,
+ weak_ptr_factory_.GetWeakPtr(), std::move(stream)));
+}
+
+void AudioOutputStreamBroker::StreamCreated(
+ media::mojom::AudioOutputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "CreateStream", this, "success",
+ !!data_pipe);
+ awaiting_created_ = false;
+ if (!data_pipe) {
+ // Stream creation failed. Signal error.
+ client_.ResetWithReason(
+ static_cast<uint32_t>(media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kPlatformError),
+ std::string());
+ disconnect_reason_ = media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kStreamCreationFailed;
+ Cleanup();
+ return;
+ }
+
+ client_->Created(std::move(stream), std::move(data_pipe));
+}
+
+void AudioOutputStreamBroker::ObserverBindingLost(
+ uint32_t reason,
+ const std::string& description) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("audio", "ObserverBindingLost", this,
+ "reset reason", reason);
+ const uint32_t maxValidReason = static_cast<uint32_t>(
+ media::mojom::AudioOutputStreamObserver::DisconnectReason::kMaxValue);
+ if (reason > maxValidReason) {
+ NOTREACHED() << "Invalid reason: " << reason;
+ } else if (disconnect_reason_ == media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kDocumentDestroyed) {
+ disconnect_reason_ =
+ static_cast<media::mojom::AudioOutputStreamObserver::DisconnectReason>(
+ reason);
+ }
+
+ // TODO(https://crbug.com/787806): Don't propagate errors if we can retry
+ // instead.
+ client_.ResetWithReason(
+ static_cast<uint32_t>(media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kPlatformError),
+ std::string());
+
+ Cleanup();
+}
+
+void AudioOutputStreamBroker::Cleanup() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ std::move(deleter_).Run(this);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_output_stream_broker.h b/chromium/content/browser/media/audio_output_stream_broker.h
new file mode 100644
index 00000000000..d997649ff6d
--- /dev/null
+++ b/chromium/content/browser/media/audio_output_stream_broker.h
@@ -0,0 +1,79 @@
+// 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_MEDIA_AUDIO_OUTPUT_STREAM_BROKER_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_OUTPUT_STREAM_BROKER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/unguessable_token.h"
+#include "content/browser/media/audio_stream_broker.h"
+#include "content/browser/renderer_host/media/audio_output_stream_observer_impl.h"
+#include "content/common/content_export.h"
+#include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+
+namespace content {
+
+// AudioOutputStreamBroker is used to broker a connection between a client
+// (typically renderer) and the audio service. It also sets up all objects
+// used for monitoring the stream.
+class CONTENT_EXPORT AudioOutputStreamBroker final : public AudioStreamBroker {
+ public:
+ AudioOutputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id,
+ DeleterCallback deleter,
+ media::mojom::AudioOutputStreamProviderClientPtr client);
+
+ ~AudioOutputStreamBroker() final;
+
+ // Creates the stream.
+ void CreateStream(audio::mojom::StreamFactory* factory) final;
+
+ private:
+ void StreamCreated(media::mojom::AudioOutputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe);
+ void ObserverBindingLost(uint32_t reason, const std::string& description);
+ void Cleanup();
+
+ SEQUENCE_CHECKER(owning_sequence_);
+
+ const std::string output_device_id_;
+ const media::AudioParameters params_;
+ const base::UnguessableToken group_id_;
+
+ // Indicates that CreateStream has been called, but not StreamCreated.
+ bool awaiting_created_ = false;
+
+ DeleterCallback deleter_;
+
+ media::mojom::AudioOutputStreamProviderClientPtr client_;
+
+ AudioOutputStreamObserverImpl observer_;
+ mojo::AssociatedBinding<media::mojom::AudioOutputStreamObserver>
+ observer_binding_;
+
+ media::mojom::AudioOutputStreamObserver::DisconnectReason disconnect_reason_ =
+ media::mojom::AudioOutputStreamObserver::DisconnectReason::
+ kDocumentDestroyed;
+
+ base::WeakPtrFactory<AudioOutputStreamBroker> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioOutputStreamBroker);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_AUDIO_OUTPUT_STREAM_BROKER_H_
diff --git a/chromium/content/browser/media/audio_output_stream_broker_unittest.cc b/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
new file mode 100644
index 00000000000..5427db631be
--- /dev/null
+++ b/chromium/content/browser/media/audio_output_stream_broker_unittest.cc
@@ -0,0 +1,281 @@
+// 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/media/audio_output_stream_broker.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/sync_socket.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/unguessable_token.h"
+#include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/system/buffer.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "services/audio/public/cpp/fake_stream_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Test;
+using ::testing::Mock;
+using ::testing::StrictMock;
+using ::testing::InSequence;
+
+namespace content {
+
+namespace {
+
+const int kRenderProcessId = 123;
+const int kRenderFrameId = 234;
+const int kStreamId = 345;
+const size_t kShMemSize = 456;
+const char kDeviceId[] = "testdeviceid";
+
+media::AudioParameters TestParams() {
+ return media::AudioParameters::UnavailableDeviceParams();
+}
+
+using MockDeleterCallback = StrictMock<
+ base::MockCallback<base::OnceCallback<void(AudioStreamBroker*)>>>;
+
+class MockAudioOutputStreamProviderClient
+ : public media::mojom::AudioOutputStreamProviderClient {
+ public:
+ MockAudioOutputStreamProviderClient() : binding_(this) {}
+ ~MockAudioOutputStreamProviderClient() override {}
+
+ void Created(media::mojom::AudioOutputStreamPtr,
+ media::mojom::AudioDataPipePtr) override {
+ OnCreated();
+ }
+
+ MOCK_METHOD0(OnCreated, void());
+
+ MOCK_METHOD2(ConnectionError, void(uint32_t, const std::string&));
+
+ media::mojom::AudioOutputStreamProviderClientPtr MakePtr() {
+ media::mojom::AudioOutputStreamProviderClientPtr ptr;
+ binding_.Bind(mojo::MakeRequest(&ptr));
+ binding_.set_connection_error_with_reason_handler(
+ base::BindOnce(&MockAudioOutputStreamProviderClient::ConnectionError,
+ base::Unretained(this)));
+ return ptr;
+ }
+
+ void CloseBinding() { binding_.Close(); }
+
+ private:
+ mojo::Binding<media::mojom::AudioOutputStreamProviderClient> binding_;
+ DISALLOW_COPY_AND_ASSIGN(MockAudioOutputStreamProviderClient);
+};
+
+class MockStreamFactory : public audio::FakeStreamFactory {
+ public:
+ MockStreamFactory() {}
+ ~MockStreamFactory() final {}
+
+ // State of an expected stream creation. |output_device_id|, |params|,
+ // and |groups_id| are set ahead of time and verified during request.
+ // The other fields are filled in when the request is received.
+ struct StreamRequestData {
+ StreamRequestData(const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id)
+ : output_device_id(output_device_id),
+ params(params),
+ group_id(group_id) {}
+
+ bool requested = false;
+ media::mojom::AudioOutputStreamRequest stream_request;
+ media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info;
+ media::mojom::AudioLogPtr log;
+ const std::string output_device_id;
+ const media::AudioParameters params;
+ const base::UnguessableToken group_id;
+ CreateOutputStreamCallback created_callback;
+ };
+
+ void ExpectStreamCreation(StreamRequestData* ex) {
+ stream_request_data_ = ex;
+ }
+
+ private:
+ void CreateOutputStream(
+ media::mojom::AudioOutputStreamRequest stream_request,
+ media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info,
+ media::mojom::AudioLogPtr log,
+ const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id,
+ CreateOutputStreamCallback created_callback) final {
+ // No way to cleanly exit the test here in case of failure, so use CHECK.
+ CHECK(stream_request_data_);
+ EXPECT_EQ(stream_request_data_->output_device_id, output_device_id);
+ EXPECT_TRUE(stream_request_data_->params.Equals(params));
+ EXPECT_EQ(stream_request_data_->group_id, group_id);
+ stream_request_data_->requested = true;
+ stream_request_data_->stream_request = std::move(stream_request);
+ stream_request_data_->observer_info = std::move(observer_info);
+ stream_request_data_->log = std::move(log);
+ stream_request_data_->created_callback = std::move(created_callback);
+ }
+
+ StreamRequestData* stream_request_data_;
+ DISALLOW_COPY_AND_ASSIGN(MockStreamFactory);
+};
+
+// This struct collects test state we need without doing anything fancy.
+struct TestEnvironment {
+ TestEnvironment()
+ : group(base::UnguessableToken::Create()),
+ broker(std::make_unique<AudioOutputStreamBroker>(
+ kRenderProcessId,
+ kRenderFrameId,
+ kStreamId,
+ kDeviceId,
+ TestParams(),
+ group,
+ deleter.Get(),
+ provider_client.MakePtr())) {}
+
+ void RunUntilIdle() { env.RunUntilIdle(); }
+
+ base::test::ScopedTaskEnvironment env;
+ base::UnguessableToken group;
+ MockDeleterCallback deleter;
+ StrictMock<MockAudioOutputStreamProviderClient> provider_client;
+ std::unique_ptr<AudioOutputStreamBroker> broker;
+ MockStreamFactory stream_factory;
+ audio::mojom::StreamFactoryPtr factory_ptr = stream_factory.MakePtr();
+};
+
+} // namespace
+
+TEST(AudioOutputStreamBrokerTest, StoresProcessAndFrameId) {
+ base::test::ScopedTaskEnvironment env;
+ MockDeleterCallback deleter;
+ StrictMock<MockAudioOutputStreamProviderClient> provider_client;
+
+ AudioOutputStreamBroker broker(kRenderProcessId, kRenderFrameId, kStreamId,
+ kDeviceId, TestParams(),
+ base::UnguessableToken::Create(),
+ deleter.Get(), provider_client.MakePtr());
+
+ EXPECT_EQ(kRenderProcessId, broker.render_process_id());
+ EXPECT_EQ(kRenderFrameId, broker.render_frame_id());
+}
+
+TEST(AudioOutputStreamBrokerTest, ClientDisconnect_CallsDeleter) {
+ TestEnvironment env;
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+ env.provider_client.CloseBinding();
+ env.RunUntilIdle();
+}
+
+TEST(AudioOutputStreamBrokerTest, StreamCreationSuccess_Propagates) {
+ TestEnvironment env;
+ MockStreamFactory::StreamRequestData stream_request_data(
+ kDeviceId, TestParams(), env.group);
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+
+ // Set up test IPC primitives.
+ base::SyncSocket socket1, socket2;
+ base::SyncSocket::CreatePair(&socket1, &socket2);
+ std::move(stream_request_data.created_callback)
+ .Run({base::in_place, mojo::SharedBufferHandle::Create(kShMemSize),
+ mojo::WrapPlatformFile(socket1.Release())});
+
+ EXPECT_CALL(env.provider_client, OnCreated());
+
+ env.RunUntilIdle();
+
+ Mock::VerifyAndClear(&env.provider_client);
+
+ env.broker.reset();
+}
+
+TEST(AudioOutputStreamBrokerTest,
+ StreamCreationFailure_PropagatesErrorAndCallsDeleter) {
+ TestEnvironment env;
+ MockStreamFactory::StreamRequestData stream_request_data(
+ kDeviceId, TestParams(), env.group);
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+ EXPECT_CALL(env.provider_client,
+ ConnectionError(static_cast<uint32_t>(
+ media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kPlatformError),
+ std::string()));
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+
+ std::move(stream_request_data.created_callback).Run(nullptr);
+
+ env.RunUntilIdle();
+}
+
+TEST(AudioOutputStreamBrokerTest,
+ ObserverDisconnect_PropagatesErrorAndCallsDeleter) {
+ TestEnvironment env;
+ MockStreamFactory::StreamRequestData stream_request_data(
+ kDeviceId, TestParams(), env.group);
+ env.stream_factory.ExpectStreamCreation(&stream_request_data);
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.RunUntilIdle();
+
+ EXPECT_TRUE(stream_request_data.requested);
+ EXPECT_CALL(env.provider_client,
+ ConnectionError(static_cast<uint32_t>(
+ media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kPlatformError),
+ std::string()));
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+
+ // This results in a connection error.
+ stream_request_data.observer_info.PassHandle();
+
+ env.RunUntilIdle();
+ env.stream_factory.CloseBinding();
+ env.RunUntilIdle();
+}
+
+TEST(AudioOutputStreamBrokerTest,
+ FactoryDisconnectDuringConstruction_PropagatesErrorAndCallsDeleter) {
+ TestEnvironment env;
+
+ env.broker->CreateStream(env.factory_ptr.get());
+ env.stream_factory.CloseBinding();
+
+ EXPECT_CALL(env.deleter, Run(env.broker.release()))
+ .WillOnce(testing::DeleteArg<0>());
+ EXPECT_CALL(env.provider_client,
+ ConnectionError(static_cast<uint32_t>(
+ media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kPlatformError),
+ std::string()));
+
+ env.RunUntilIdle();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_stream_broker.cc b/chromium/content/browser/media/audio_stream_broker.cc
new file mode 100644
index 00000000000..6ff668c3b9e
--- /dev/null
+++ b/chromium/content/browser/media/audio_stream_broker.cc
@@ -0,0 +1,85 @@
+// 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/media/audio_stream_broker.h"
+
+#include <utility>
+
+#include "content/browser/media/audio_input_stream_broker.h"
+#include "content/browser/media/audio_loopback_stream_broker.h"
+#include "content/browser/media/audio_output_stream_broker.h"
+
+namespace content {
+
+namespace {
+
+class AudioStreamBrokerFactoryImpl final : public AudioStreamBrokerFactory {
+ public:
+ AudioStreamBrokerFactoryImpl() = default;
+ ~AudioStreamBrokerFactoryImpl() final = default;
+
+ std::unique_ptr<AudioStreamBroker> CreateAudioInputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
+ final {
+ return std::make_unique<AudioInputStreamBroker>(
+ render_process_id, render_frame_id, device_id, params,
+ shared_memory_count, enable_agc, std::move(deleter),
+ std::move(renderer_factory_client));
+ }
+
+ std::unique_ptr<AudioStreamBroker> CreateAudioLoopbackStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ std::unique_ptr<LoopbackSource> source,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool mute_source,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
+ final {
+ return std::make_unique<AudioLoopbackStreamBroker>(
+ render_process_id, render_frame_id, std::move(source), params,
+ shared_memory_count, mute_source, std::move(deleter),
+ std::move(renderer_factory_client));
+ }
+
+ std::unique_ptr<AudioStreamBroker> CreateAudioOutputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id,
+ AudioStreamBroker::DeleterCallback deleter,
+ media::mojom::AudioOutputStreamProviderClientPtr client) final {
+ return std::make_unique<AudioOutputStreamBroker>(
+ render_process_id, render_frame_id, stream_id, output_device_id, params,
+ group_id, std::move(deleter), std::move(client));
+ }
+};
+
+} // namespace
+
+AudioStreamBroker::AudioStreamBroker(int render_process_id, int render_frame_id)
+ : render_process_id_(render_process_id),
+ render_frame_id_(render_frame_id) {}
+AudioStreamBroker::~AudioStreamBroker() {}
+
+AudioStreamBrokerFactory::AudioStreamBrokerFactory() {}
+AudioStreamBrokerFactory::~AudioStreamBrokerFactory() {}
+
+// static
+std::unique_ptr<AudioStreamBrokerFactory>
+AudioStreamBrokerFactory::CreateImpl() {
+ return std::make_unique<AudioStreamBrokerFactoryImpl>();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_stream_broker.h b/chromium/content/browser/media/audio_stream_broker.h
new file mode 100644
index 00000000000..40af0eac01b
--- /dev/null
+++ b/chromium/content/browser/media/audio_stream_broker.h
@@ -0,0 +1,139 @@
+// 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_MEDIA_AUDIO_STREAM_BROKER_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_STREAM_BROKER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
+
+namespace audio {
+namespace mojom {
+class StreamFactory;
+}
+} // namespace audio
+
+namespace base {
+class UnguessableToken;
+}
+
+namespace media {
+class AudioParameters;
+}
+
+namespace content {
+class WebContents;
+
+// An AudioStreamBroker is used to broker a connection between a client
+// (typically renderer) and the audio service. It also sets up all objects
+// used for monitoring the stream.
+class CONTENT_EXPORT AudioStreamBroker {
+ public:
+ using DeleterCallback = base::OnceCallback<void(AudioStreamBroker*)>;
+
+ AudioStreamBroker(int render_process_id, int render_frame_id);
+ virtual ~AudioStreamBroker();
+
+ virtual void CreateStream(audio::mojom::StreamFactory* factory) = 0;
+
+ int render_process_id() const { return render_process_id_; }
+ int render_frame_id() const { return render_frame_id_; }
+
+ protected:
+ const int render_process_id_;
+ const int render_frame_id_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioStreamBroker);
+};
+
+// Used for dependency injection into ForwardingAudioStreamFactory.
+class CONTENT_EXPORT AudioStreamBrokerFactory {
+ public:
+ class CONTENT_EXPORT LoopbackSource : public WebContentsObserver {
+ public:
+ explicit LoopbackSource(WebContents* source_contents);
+ ~LoopbackSource() override;
+
+ // Virtual for mocking in tests.
+ // Will return an empty token if the source is not present.
+
+ virtual base::UnguessableToken GetGroupID();
+
+ // Signals the source WebContents that capturing started.
+ virtual void OnStartCapturing();
+
+ // Signals the source WebContents that capturing stopped.
+ virtual void OnStopCapturing();
+
+ // Sets the closure to run when the source WebContents is gone.
+ void set_on_gone_closure(base::OnceClosure on_gone_closure) {
+ on_gone_closure_ = std::move(on_gone_closure);
+ }
+
+ // WebContentsObserver implementation.
+ void WebContentsDestroyed() override;
+
+ protected:
+ LoopbackSource();
+
+ private:
+ base::OnceClosure on_gone_closure_;
+ DISALLOW_COPY_AND_ASSIGN(LoopbackSource);
+ };
+
+ static std::unique_ptr<AudioStreamBrokerFactory> CreateImpl();
+
+ AudioStreamBrokerFactory();
+ virtual ~AudioStreamBrokerFactory();
+
+ virtual std::unique_ptr<AudioStreamBroker> CreateAudioInputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr
+ renderer_factory_client) = 0;
+
+ virtual std::unique_ptr<AudioStreamBroker> CreateAudioLoopbackStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ std::unique_ptr<LoopbackSource> source,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool mute_source,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr
+ renderer_factory_client) = 0;
+
+ virtual std::unique_ptr<AudioStreamBroker> CreateAudioOutputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id,
+ AudioStreamBroker::DeleterCallback deleter,
+ media::mojom::AudioOutputStreamProviderClientPtr client) = 0;
+
+ // TODO(https://crbug.com/830493): Other kinds of streams.
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioStreamBrokerFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_AUDIO_STREAM_BROKER_H_
diff --git a/chromium/content/browser/media/capture/OWNERS b/chromium/content/browser/media/capture/OWNERS
index c9e162eb22d..31e7db3290b 100644
--- a/chromium/content/browser/media/capture/OWNERS
+++ b/chromium/content/browser/media/capture/OWNERS
@@ -8,5 +8,4 @@ per-file desktop_capture_device_unittest.cc=zijiehe@chromium.org
per-file image_capture*=mcasas@chromium.org
-# TEAM: media-capture-and-streams@grotations.appspotmail.com
-# COMPONENT: Blink>GetUserMedia
+# COMPONENT: Internals>Media>ScreenCapture
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
index 2d6efe047d8..a485e46bf68 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -114,7 +114,6 @@ class AudioMirroringManagerTest : public testing::Test {
: params_(AudioParameters::AUDIO_FAKE,
media::CHANNEL_LAYOUT_STEREO,
AudioParameters::kAudioCDSampleRate,
- 16,
AudioParameters::kAudioCDSampleRate / 10) {}
MockDiverter* CreateStream(int render_process_id,
diff --git a/chromium/content/browser/media/capture/aura_window_video_capture_device.cc b/chromium/content/browser/media/capture/aura_window_video_capture_device.cc
new file mode 100644
index 00000000000..93160c08dcf
--- /dev/null
+++ b/chromium/content/browser/media/capture/aura_window_video_capture_device.cc
@@ -0,0 +1,171 @@
+// 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/media/capture/aura_window_video_capture_device.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/desktop_media_id.h"
+#include "media/base/bind_to_current_loop.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+
+#if defined(OS_CHROMEOS)
+#include "content/browser/media/capture/lame_window_capturer_chromeos.h"
+#endif
+
+namespace content {
+
+// Threading note: This is constructed on the device thread, while the
+// destructor and the rest of the class will run exclusively on the UI thread.
+class AuraWindowVideoCaptureDevice::WindowTracker
+ : public aura::WindowObserver,
+ public base::SupportsWeakPtr<
+ AuraWindowVideoCaptureDevice::WindowTracker> {
+ public:
+ WindowTracker(base::WeakPtr<AuraWindowVideoCaptureDevice> device,
+ CursorRenderer* cursor_renderer,
+ const DesktopMediaID& source_id)
+ : device_(std::move(device)),
+ device_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ cursor_renderer_(cursor_renderer),
+ target_type_(source_id.type) {
+ DCHECK(device_task_runner_);
+ DCHECK(cursor_renderer_);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&WindowTracker::ResolveTarget, AsWeakPtr(), source_id));
+ }
+
+ ~WindowTracker() final {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (target_window_) {
+ target_window_->RemoveObserver(this);
+ }
+ }
+
+ DesktopMediaID::Type target_type() const { return target_type_; }
+
+ aura::Window* target_window() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ return target_window_;
+ }
+
+ private:
+ // Determines which frame sink and aura::Window should be targeted for capture
+ // and notifies the device.
+ void ResolveTarget(const DesktopMediaID& source_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Since ResolveTarget() should only ever be called once, expect
+ // |target_window_| to be null at this point.
+ DCHECK(!target_window_);
+
+ target_window_ = DesktopMediaID::GetAuraWindowById(source_id);
+ if (target_window_ &&
+#if defined(OS_CHROMEOS)
+ // See class comments for LameWindowCapturerChromeOS.
+ (source_id.type == DesktopMediaID::TYPE_WINDOW ||
+ target_window_->GetFrameSinkId().is_valid()) &&
+#else
+ target_window_->GetFrameSinkId().is_valid() &&
+#endif
+ true) {
+ target_window_->AddObserver(this);
+ device_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FrameSinkVideoCaptureDevice::OnTargetChanged, device_,
+ target_window_->GetFrameSinkId()));
+ // Note: CursorRenderer runs on the UI thread. It's also important that
+ // SetTargetView() be called in the current stack while |target_window_|
+ // is known to be a valid pointer. http://crbug.com/818679
+ cursor_renderer_->SetTargetView(target_window_);
+ } else {
+ device_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FrameSinkVideoCaptureDevice::OnTargetPermanentlyLost,
+ device_));
+ }
+ }
+
+ // aura::WindowObserver override.
+ void OnWindowDestroying(aura::Window* window) final {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_EQ(window, target_window_);
+
+ target_window_->RemoveObserver(this);
+ target_window_ = nullptr;
+
+ device_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FrameSinkVideoCaptureDevice::OnTargetPermanentlyLost,
+ device_));
+ cursor_renderer_->SetTargetView(nullptr);
+ }
+
+ private:
+ // |device_| may be dereferenced only by tasks run by |device_task_runner_|.
+ const base::WeakPtr<FrameSinkVideoCaptureDevice> device_;
+ const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
+
+ // Owned by FrameSinkVideoCaptureDevice. This will be valid for the life of
+ // WindowTracker because the WindowTracker deleter task will be posted to the
+ // UI thread before the CursorRenderer deleter task.
+ CursorRenderer* const cursor_renderer_;
+
+ const DesktopMediaID::Type target_type_;
+
+ aura::Window* target_window_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowTracker);
+};
+
+AuraWindowVideoCaptureDevice::AuraWindowVideoCaptureDevice(
+ const DesktopMediaID& source_id)
+ : tracker_(new WindowTracker(AsWeakPtr(), cursor_renderer(), source_id)) {}
+
+AuraWindowVideoCaptureDevice::~AuraWindowVideoCaptureDevice() = default;
+
+#if defined(OS_CHROMEOS)
+void AuraWindowVideoCaptureDevice::CreateCapturer(
+ viz::mojom::FrameSinkVideoCapturerRequest request) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ [](base::WeakPtr<WindowTracker> tracker_ptr,
+ viz::mojom::FrameSinkVideoCapturerRequest request) {
+ WindowTracker* const tracker = tracker_ptr.get();
+ if (!tracker) {
+ // WindowTracker was destroyed in the meantime, due to early
+ // shutdown.
+ return;
+ }
+
+ if (tracker->target_type() == DesktopMediaID::TYPE_WINDOW) {
+ VLOG(1) << "AuraWindowVideoCaptureDevice is using the LAME "
+ "capturer. :(";
+ mojo::StrongBinding<viz::mojom::FrameSinkVideoCapturer>::Create(
+ std::make_unique<LameWindowCapturerChromeOS>(
+ tracker->target_window()),
+ std::move(request));
+ } else {
+ VLOG(1) << "AuraWindowVideoCaptureDevice is using the frame "
+ "sink capturer. :)";
+ CreateCapturerViaGlobalManager(std::move(request));
+ }
+ },
+ tracker_->AsWeakPtr(), std::move(request)));
+}
+#endif
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/aura_window_video_capture_device.h b/chromium/content/browser/media/capture/aura_window_video_capture_device.h
new file mode 100644
index 00000000000..0295b3d1951
--- /dev/null
+++ b/chromium/content/browser/media/capture/aura_window_video_capture_device.h
@@ -0,0 +1,57 @@
+// 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_MEDIA_CAPTURE_AURA_WINDOW_VIDEO_CAPTURE_DEVICE_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_VIDEO_CAPTURE_DEVICE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "content/browser/media/capture/frame_sink_video_capture_device.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace aura {
+class Window;
+} // namespace aura
+
+namespace content {
+
+struct DesktopMediaID;
+
+// Captures the displayed contents of an aura::Window, producing a stream of
+// video frames.
+class CONTENT_EXPORT AuraWindowVideoCaptureDevice
+ : public FrameSinkVideoCaptureDevice,
+ public base::SupportsWeakPtr<AuraWindowVideoCaptureDevice> {
+ public:
+ explicit AuraWindowVideoCaptureDevice(const DesktopMediaID& source_id);
+ ~AuraWindowVideoCaptureDevice() final;
+
+#if defined(OS_CHROMEOS)
+ protected:
+ // Overrides FrameSinkVideoCaptureDevice::CreateCapturer() to create a
+ // LameWindowCapturerChromeOS for window capture where compositor frame sinks
+ // are not present. See class comments for LameWindowCapturerChromeOS for
+ // further details.
+ void CreateCapturer(viz::mojom::FrameSinkVideoCapturerRequest request) final;
+#endif
+
+ private:
+ // Monitors the target Window and notifies the base class if it is destroyed.
+ class WindowTracker;
+
+ // A helper that runs on the UI thread to monitor the target aura::Window, and
+ // post a notification if it is destroyed.
+ const std::unique_ptr<WindowTracker, BrowserThread::DeleteOnUIThread>
+ tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(AuraWindowVideoCaptureDevice);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_VIDEO_CAPTURE_DEVICE_H_
diff --git a/chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc b/chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc
new file mode 100644
index 00000000000..7ba9955087b
--- /dev/null
+++ b/chromium/content/browser/media/capture/aura_window_video_capture_device_browsertest.cc
@@ -0,0 +1,358 @@
+// 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/media/capture/aura_window_video_capture_device.h"
+
+#include <tuple>
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "build/build_config.h"
+#include "cc/test/pixel_test_utils.h"
+#include "content/browser/media/capture/content_capture_device_browsertest_base.h"
+#include "content/browser/media/capture/fake_video_capture_stack.h"
+#include "content/browser/media/capture/frame_test_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/desktop_media_id.h"
+#include "content/public/browser/web_contents.h"
+#include "content/shell/browser/shell.h"
+#include "media/base/video_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/aura/window.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace content {
+namespace {
+
+class AuraWindowVideoCaptureDeviceBrowserTest
+ : public ContentCaptureDeviceBrowserTestBase {
+ public:
+ AuraWindowVideoCaptureDeviceBrowserTest() = default;
+ ~AuraWindowVideoCaptureDeviceBrowserTest() override = default;
+
+ aura::Window* GetCapturedWindow() const {
+#if defined(OS_CHROMEOS)
+ // Since the LameWindowCapturerChromeOS will be used, just return the normal
+ // shell window.
+ return shell()->window();
+#else
+ // Note: The Window with an associated compositor frame sink (required for
+ // capture) is the root window, which is an immediate ancestor of the
+ // aura::Window provided by shell()->window().
+ return shell()->window()->GetRootWindow();
+#endif
+ }
+
+ // Returns the location of the content within the window.
+ gfx::Rect GetWebContentsRect() const {
+ aura::Window* const contents_window =
+ shell()->web_contents()->GetNativeView();
+ gfx::Rect rect = gfx::Rect(contents_window->bounds().size());
+ aura::Window::ConvertRectToTarget(contents_window, GetCapturedWindow(),
+ &rect);
+ return rect;
+ }
+
+ // Runs the browser until a frame whose content matches the given |color| is
+ // found in the captured frames queue, or until a testing failure has
+ // occurred.
+ void WaitForFrameWithColor(SkColor color) {
+ VLOG(1) << "Waiting for frame content area filled with color: red="
+ << SkColorGetR(color) << ", green=" << SkColorGetG(color)
+ << ", blue=" << SkColorGetB(color);
+
+ while (!testing::Test::HasFailure()) {
+ EXPECT_TRUE(capture_stack()->started());
+ EXPECT_FALSE(capture_stack()->error_occurred());
+ capture_stack()->ExpectNoLogMessages();
+
+ while (capture_stack()->has_captured_frames() &&
+ !testing::Test::HasFailure()) {
+ // Pop the next frame from the front of the queue and convert to a RGB
+ // bitmap for analysis.
+ const SkBitmap rgb_frame = capture_stack()->NextCapturedFrame();
+ EXPECT_FALSE(rgb_frame.empty());
+
+ // Three regions of the frame will be analyzed: 1) the WebContents
+ // region containing a solid color, 2) the remaining part of the
+ // captured window containing the content shell UI, and 3) the
+ // solid-black letterboxed region surrounding them.
+ const gfx::Size frame_size(rgb_frame.width(), rgb_frame.height());
+ const gfx::Size window_size = GetExpectedSourceSize();
+ const gfx::Rect webcontents_rect = GetWebContentsRect();
+
+ // Compute the Rects representing where the three regions would be in
+ // the frame.
+ const gfx::RectF window_in_frame_rect_f(
+ IsFixedAspectRatioTest() ? media::ComputeLetterboxRegion(
+ gfx::Rect(frame_size), window_size)
+ : gfx::Rect(frame_size));
+ const gfx::RectF webcontents_in_frame_rect_f =
+ FrameTestUtil::TransformSimilarly(gfx::Rect(window_size),
+ window_in_frame_rect_f,
+ webcontents_rect);
+ const gfx::Rect window_in_frame_rect =
+ gfx::ToEnclosingRect(window_in_frame_rect_f);
+ const gfx::Rect webcontents_in_frame_rect =
+ gfx::ToEnclosingRect(webcontents_in_frame_rect_f);
+
+ // Determine the average RGB color in the three regions of the frame.
+ const auto average_webcontents_rgb = FrameTestUtil::ComputeAverageColor(
+ rgb_frame, webcontents_in_frame_rect, gfx::Rect());
+ const auto average_window_rgb = FrameTestUtil::ComputeAverageColor(
+ rgb_frame, window_in_frame_rect, webcontents_in_frame_rect);
+ const auto average_letterbox_rgb = FrameTestUtil::ComputeAverageColor(
+ rgb_frame, gfx::Rect(frame_size), window_in_frame_rect);
+
+ // TODO(crbug/810131): Once color space issues are fixed, remove this.
+ // At first, it seemed only to affect ChromeOS; but then on Linux, in
+ // software compositing mode, it seems that sometimes compositing is
+ // switching color spaces during the test (e.g., expected a 255 red, but
+ // we see two frames of 238 followed by a "close-enough" frame of 251).
+ constexpr int max_color_diff =
+ FrameTestUtil::kMaxInaccurateColorDifference;
+
+ VLOG(1) << "Video frame analysis: size=" << frame_size.ToString()
+ << ", captured webcontents should be at "
+ << webcontents_in_frame_rect.ToString()
+ << " and has average color " << average_webcontents_rgb
+ << ", captured window should be at "
+ << window_in_frame_rect.ToString() << " and has average color "
+ << average_window_rgb << ", letterbox region has average color "
+ << average_letterbox_rgb
+ << ", maximum color error=" << max_color_diff;
+
+ // The letterboxed region should always be black.
+ if (IsFixedAspectRatioTest()) {
+ EXPECT_TRUE(FrameTestUtil::IsApproximatelySameColor(
+ SK_ColorBLACK, average_letterbox_rgb, max_color_diff));
+ }
+
+ if (testing::Test::HasFailure()) {
+ ADD_FAILURE() << "Test failure occurred at this frame; PNG dump: "
+ << cc::GetPNGDataUrl(rgb_frame);
+ return;
+ }
+
+ // Return if the WebContents region now has the new |color|.
+ if (FrameTestUtil::IsApproximatelySameColor(
+ color, average_webcontents_rgb, max_color_diff)) {
+ VLOG(1) << "Observed desired frame.";
+ return;
+ } else {
+ VLOG(3) << "PNG dump of undesired frame: "
+ << cc::GetPNGDataUrl(rgb_frame);
+ }
+ }
+
+ // Wait for at least the minimum capture period before checking for more
+ // captured frames.
+ base::RunLoop run_loop;
+ BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+ run_loop.QuitClosure(),
+ GetMinCapturePeriod());
+ run_loop.Run();
+ }
+ }
+
+ protected:
+ // Note: Test code should call <BaseClass>::GetExpectedSourceSize() instead of
+ // this method since it has extra code to sanity-check that the source size is
+ // not changing during the test.
+ gfx::Size GetCapturedSourceSize() const final {
+ return GetCapturedWindow()->bounds().size();
+ }
+
+ std::unique_ptr<FrameSinkVideoCaptureDevice> CreateDevice() final {
+ const DesktopMediaID source_id = DesktopMediaID::RegisterAuraWindow(
+ DesktopMediaID::TYPE_WINDOW, GetCapturedWindow());
+ EXPECT_TRUE(DesktopMediaID::GetAuraWindowById(source_id));
+ return std::make_unique<AuraWindowVideoCaptureDevice>(source_id);
+ }
+
+ void WaitForFirstFrame() final { WaitForFrameWithColor(SK_ColorBLACK); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AuraWindowVideoCaptureDeviceBrowserTest);
+};
+
+// Tests that the device refuses to start if the target window was destroyed
+// before the device could start.
+IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
+ ErrorsOutIfWindowHasGoneBeforeDeviceStart) {
+ NavigateToInitialDocument();
+
+ const DesktopMediaID source_id = DesktopMediaID::RegisterAuraWindow(
+ DesktopMediaID::TYPE_WINDOW, GetCapturedWindow());
+ EXPECT_TRUE(DesktopMediaID::GetAuraWindowById(source_id));
+ const auto capture_params = SnapshotCaptureParams();
+
+ // Close the Shell. This should close the window it owned, making the capture
+ // target invalid.
+ shell()->Close();
+
+ // Create the device.
+ auto device = std::make_unique<AuraWindowVideoCaptureDevice>(source_id);
+ // Running the pending UI tasks should cause the device to realize the window
+ // is gone.
+ RunUntilIdle();
+
+ // Attempt to start the device, and expect the video capture stack to have
+ // been notified of the error.
+ device->AllocateAndStartWithReceiver(capture_params,
+ capture_stack()->CreateFrameReceiver());
+ EXPECT_FALSE(capture_stack()->started());
+ EXPECT_TRUE(capture_stack()->error_occurred());
+ capture_stack()->ExpectHasLogMessages();
+
+ device->StopAndDeAllocate();
+ RunUntilIdle();
+}
+
+// Tests that the device starts, captures a frame, and then gracefully
+// errors-out because the target window is destroyed before the device is
+// stopped.
+IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
+ ErrorsOutWhenWindowIsDestroyed) {
+ NavigateToInitialDocument();
+ AllocateAndStartAndWaitForFirstFrame();
+
+ // Initially, the device captures any content changes normally.
+ ChangePageContentColor(SK_ColorRED);
+ WaitForFrameWithColor(SK_ColorRED);
+
+ // Close the Shell. This should close the window it owned, causing a "target
+ // permanently lost" error to propagate to the video capture stack.
+ shell()->Close();
+ RunUntilIdle();
+ EXPECT_TRUE(capture_stack()->error_occurred());
+ capture_stack()->ExpectHasLogMessages();
+
+ StopAndDeAllocate();
+}
+
+// Tests that the device stops delivering frames while suspended. When resumed,
+// any content changes that occurred during the suspend should cause a new frame
+// to be delivered, to ensure the client is up-to-date.
+IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
+ SuspendsAndResumes) {
+ NavigateToInitialDocument();
+ AllocateAndStartAndWaitForFirstFrame();
+
+ // Initially, the device captures any content changes normally.
+ ChangePageContentColor(SK_ColorRED);
+ WaitForFrameWithColor(SK_ColorRED);
+
+ // Suspend the device.
+ device()->MaybeSuspend();
+ RunUntilIdle();
+ ClearCapturedFramesQueue();
+
+ // Change the page content and run the browser for five seconds. Expect no
+ // frames were queued because the device should be suspended.
+ ChangePageContentColor(SK_ColorGREEN);
+ base::RunLoop run_loop;
+ BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromSeconds(5));
+ run_loop.Run();
+ EXPECT_FALSE(HasCapturedFramesInQueue());
+
+ // Resume the device and wait for an automatic refresh frame containing the
+ // content that was updated while the device was suspended.
+ device()->Resume();
+ WaitForFrameWithColor(SK_ColorGREEN);
+
+ StopAndDeAllocate();
+}
+
+// Tests that the device delivers refresh frames when asked, while the source
+// content is not changing.
+IN_PROC_BROWSER_TEST_F(AuraWindowVideoCaptureDeviceBrowserTest,
+ DeliversRefreshFramesUponRequest) {
+ NavigateToInitialDocument();
+ AllocateAndStartAndWaitForFirstFrame();
+
+ // Set the page content to a known color.
+ ChangePageContentColor(SK_ColorRED);
+ WaitForFrameWithColor(SK_ColorRED);
+
+ // Without making any further changes to the source (which would trigger
+ // frames to be captured), request and wait for ten refresh frames.
+ for (int i = 0; i < 10; ++i) {
+ ClearCapturedFramesQueue();
+ device()->RequestRefreshFrame();
+ WaitForFrameWithColor(SK_ColorRED);
+ }
+
+ StopAndDeAllocate();
+}
+
+class AuraWindowVideoCaptureDeviceBrowserTestP
+ : public AuraWindowVideoCaptureDeviceBrowserTest,
+ public testing::WithParamInterface<std::tuple<bool, bool>> {
+ public:
+ bool IsSoftwareCompositingTest() const override {
+ return std::get<0>(GetParam());
+ }
+ bool IsFixedAspectRatioTest() const override {
+ return std::get<1>(GetParam());
+ }
+};
+
+#if defined(OS_CHROMEOS)
+INSTANTIATE_TEST_CASE_P(
+ ,
+ AuraWindowVideoCaptureDeviceBrowserTestP,
+ testing::Combine(
+ // Note: On ChromeOS, software compositing is not an option.
+ testing::Values(false /* GPU-accelerated compositing */),
+ testing::Values(false /* variable aspect ratio */,
+ true /* fixed aspect ratio */)));
+#else
+INSTANTIATE_TEST_CASE_P(
+ ,
+ AuraWindowVideoCaptureDeviceBrowserTestP,
+ testing::Combine(testing::Values(false /* GPU-accelerated compositing */,
+ true /* software compositing */),
+ testing::Values(false /* variable aspect ratio */,
+ true /* fixed aspect ratio */)));
+#endif // defined(OS_CHROMEOS)
+
+// Tests that the device successfully captures a series of content changes,
+// whether the browser is running with software compositing or GPU-accelerated
+// compositing.
+IN_PROC_BROWSER_TEST_P(AuraWindowVideoCaptureDeviceBrowserTestP,
+ CapturesContentChanges) {
+ SCOPED_TRACE(testing::Message()
+ << "Test parameters: "
+ << (IsSoftwareCompositingTest() ? "Software Compositing"
+ : "GPU Compositing")
+ << " with "
+ << (IsFixedAspectRatioTest() ? "Fixed Video Aspect Ratio"
+ : "Variable Video Aspect Ratio"));
+
+ NavigateToInitialDocument();
+ AllocateAndStartAndWaitForFirstFrame();
+
+ ASSERT_EQ(shell()->web_contents()->GetVisibility(),
+ content::Visibility::VISIBLE);
+
+ static constexpr SkColor kColorsToCycleThrough[] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorYELLOW,
+ SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorWHITE,
+ };
+ for (SkColor color : kColorsToCycleThrough) {
+ ChangePageContentColor(color);
+ WaitForFrameWithColor(color);
+ }
+
+ StopAndDeAllocate();
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc b/chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc
new file mode 100644
index 00000000000..73ba0a4823f
--- /dev/null
+++ b/chromium/content/browser/media/capture/content_capture_device_browsertest_base.cc
@@ -0,0 +1,267 @@
+// 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/media/capture/content_capture_device_browsertest_base.h"
+
+#include <cmath>
+#include <utility>
+
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/media/capture/frame_sink_video_capture_device.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using net::test_server::BasicHttpResponse;
+using net::test_server::HttpRequest;
+using net::test_server::HttpResponse;
+
+namespace content {
+
+ContentCaptureDeviceBrowserTestBase::ContentCaptureDeviceBrowserTestBase() =
+ default;
+
+ContentCaptureDeviceBrowserTestBase::~ContentCaptureDeviceBrowserTestBase() =
+ default;
+
+void ContentCaptureDeviceBrowserTestBase::ChangePageContentColor(
+ SkColor color) {
+ // See the HandleRequest() method for the original documents being modified
+ // here.
+ std::string script;
+ if (IsCrossSiteCaptureTest()) {
+ const GURL& inner_frame_url =
+ embedded_test_server()->GetURL(kInnerFrameHostname, kInnerFramePath);
+ script = base::StringPrintf(
+ "document.getElementsByTagName('iframe')[0].src = '%s?color=123456';",
+ inner_frame_url.spec().c_str());
+ } else {
+ script = "document.body.style.backgroundColor = '#123456';";
+ }
+ script.replace(script.find("123456"), 6,
+ base::StringPrintf("%02x%02x%02x", SkColorGetR(color),
+ SkColorGetG(color), SkColorGetB(color)));
+ CHECK(ExecuteScript(shell()->web_contents(), script));
+}
+
+gfx::Size ContentCaptureDeviceBrowserTestBase::GetExpectedSourceSize() {
+ const gfx::Size source_size = GetCapturedSourceSize();
+ if (expected_source_size_) {
+ EXPECT_EQ(*expected_source_size_, source_size)
+ << "Sanity-check failed: Source size changed during this test.";
+ } else {
+ expected_source_size_.emplace(source_size);
+ VLOG(1) << "Captured source size is " << expected_source_size_->ToString();
+ }
+ return source_size;
+}
+
+media::VideoCaptureParams
+ContentCaptureDeviceBrowserTestBase::SnapshotCaptureParams() {
+ constexpr gfx::Size kMaxCaptureSize = gfx::Size(320, 320);
+ constexpr int kMaxFramesPerSecond = 60;
+
+ gfx::Size capture_size = kMaxCaptureSize;
+ if (IsFixedAspectRatioTest()) {
+ // Half either the width or height, depending on the source size. The goal
+ // is to force obvious letterboxing (or pillarboxing), regardless of how the
+ // source is currently sized/oriented.
+ const gfx::Size source_size = GetExpectedSourceSize();
+ if (source_size.width() < source_size.height()) {
+ capture_size.set_height(capture_size.height() / 2);
+ } else {
+ capture_size.set_width(capture_size.width() / 2);
+ }
+ }
+
+ media::VideoCaptureParams params;
+ params.requested_format = media::VideoCaptureFormat(
+ capture_size, kMaxFramesPerSecond, media::PIXEL_FORMAT_I420);
+ params.resolution_change_policy =
+ IsFixedAspectRatioTest()
+ ? media::ResolutionChangePolicy::FIXED_ASPECT_RATIO
+ : media::ResolutionChangePolicy::ANY_WITHIN_LIMIT;
+ return params;
+}
+
+base::TimeDelta ContentCaptureDeviceBrowserTestBase::GetMinCapturePeriod() {
+ return base::TimeDelta::FromMicroseconds(
+ base::Time::kMicrosecondsPerSecond /
+ device_->capture_params().requested_format.frame_rate);
+}
+
+void ContentCaptureDeviceBrowserTestBase::NavigateToInitialDocument() {
+ // If doing a cross-site capture test, navigate to the more-complex document
+ // that also contains an iframe (rendered in a separate process). Otherwise,
+ // navigate to the simpler document.
+ if (IsCrossSiteCaptureTest()) {
+ ASSERT_TRUE(NavigateToURL(
+ shell(),
+ embedded_test_server()->GetURL(kOuterFrameHostname, kOuterFramePath)));
+ ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // Confirm the iframe is a cross-process child render frame.
+ auto* const child_frame =
+ ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
+ ASSERT_TRUE(child_frame);
+ ASSERT_TRUE(child_frame->IsCrossProcessSubframe());
+ } else {
+ ASSERT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ kSingleFrameHostname, kSingleFramePath)));
+ ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ }
+}
+
+void ContentCaptureDeviceBrowserTestBase::
+ AllocateAndStartAndWaitForFirstFrame() {
+ capture_stack()->Reset();
+
+ device_ = CreateDevice();
+ device_->AllocateAndStartWithReceiver(SnapshotCaptureParams(),
+ capture_stack()->CreateFrameReceiver());
+ RunUntilIdle();
+ EXPECT_TRUE(capture_stack()->started());
+ EXPECT_FALSE(capture_stack()->error_occurred());
+ capture_stack()->ExpectNoLogMessages();
+
+ WaitForFirstFrame();
+}
+
+void ContentCaptureDeviceBrowserTestBase::StopAndDeAllocate() {
+ device_->StopAndDeAllocate();
+ RunUntilIdle();
+ device_.reset();
+}
+
+void ContentCaptureDeviceBrowserTestBase::RunUntilIdle() {
+ base::RunLoop().RunUntilIdle();
+}
+
+bool ContentCaptureDeviceBrowserTestBase::IsSoftwareCompositingTest() const {
+ return false;
+}
+
+bool ContentCaptureDeviceBrowserTestBase::IsFixedAspectRatioTest() const {
+ return false;
+}
+
+bool ContentCaptureDeviceBrowserTestBase::IsCrossSiteCaptureTest() const {
+ return false;
+}
+
+void ContentCaptureDeviceBrowserTestBase::SetUp() {
+ // IMPORTANT: Do not add the switches::kUseGpuInTests command line flag: It
+ // causes the tests to take 12+ seconds just to spin up a render process on
+ // debug builds. It can also cause test failures in MSAN builds, or exacerbate
+ // OOM situations on highly-loaded machines.
+
+ // Screen capture requires readback from compositor output.
+ EnablePixelOutput();
+
+ // Conditionally force software compositing instead of GPU-accelerated
+ // compositing.
+ if (IsSoftwareCompositingTest()) {
+ UseSoftwareCompositing();
+ }
+
+ ContentBrowserTest::SetUp();
+}
+
+void ContentCaptureDeviceBrowserTestBase::SetUpCommandLine(
+ base::CommandLine* command_line) {
+ IsolateAllSitesForTesting(command_line);
+}
+
+void ContentCaptureDeviceBrowserTestBase::SetUpOnMainThread() {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ // Set-up and start the embedded test HTTP server.
+ host_resolver()->AddRule("*", "127.0.0.1");
+ embedded_test_server()->RegisterRequestHandler(
+ base::BindRepeating(&ContentCaptureDeviceBrowserTestBase::HandleRequest,
+ base::Unretained(this)));
+ ASSERT_TRUE(embedded_test_server()->Start());
+}
+
+void ContentCaptureDeviceBrowserTestBase::TearDownOnMainThread() {
+ ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+
+ ClearCapturedFramesQueue();
+
+ // Run any left-over tasks (usually these are delete-soon's and orphaned
+ // tasks).
+ RunUntilIdle();
+
+ ContentBrowserTest::TearDownOnMainThread();
+}
+
+std::unique_ptr<HttpResponse>
+ContentCaptureDeviceBrowserTestBase::HandleRequest(const HttpRequest& request) {
+ auto response = std::make_unique<BasicHttpResponse>();
+ response->set_content_type("text/html");
+ const GURL& url = request.GetURL();
+ if (url.path() == kOuterFramePath) {
+ // A page with a solid white fill color, but containing an iframe in its
+ // upper-left quadrant.
+ const GURL& inner_frame_url =
+ embedded_test_server()->GetURL(kInnerFrameHostname, kInnerFramePath);
+ response->set_content(base::StringPrintf(
+ "<!doctype html>"
+ "<body style='background-color: #ffffff;'>"
+ "<iframe src='%s' style='position:absolute; "
+ "top:0px; left:0px; margin:none; padding:none; border:none;'>"
+ "</iframe>"
+ "<script>"
+ "window.addEventListener('load', () => {"
+ " const iframe = document.getElementsByTagName('iframe')[0];"
+ " iframe.width = document.documentElement.clientWidth / 2;"
+ " iframe.height = document.documentElement.clientHeight / 2;"
+ "});"
+ "</script>"
+ "</body>",
+ inner_frame_url.spec().c_str()));
+ } else {
+ // A page whose solid fill color is based on a query parameter, or
+ // defaults to black.
+ const std::string& query = url.query();
+ std::string color = "#000000";
+ const auto pos = query.find("color=");
+ if (pos != std::string::npos) {
+ color = "#" + query.substr(pos + 6, 6);
+ }
+ response->set_content(
+ base::StringPrintf("<!doctype html>"
+ "<body style='background-color: %s;'></body>",
+ color.c_str()));
+ }
+ return std::move(response);
+}
+
+// static
+constexpr char ContentCaptureDeviceBrowserTestBase::kInnerFrameHostname[];
+// static
+constexpr char ContentCaptureDeviceBrowserTestBase::kInnerFramePath[];
+// static
+constexpr char ContentCaptureDeviceBrowserTestBase::kOuterFrameHostname[];
+// static
+constexpr char ContentCaptureDeviceBrowserTestBase::kOuterFramePath[];
+// static
+constexpr char ContentCaptureDeviceBrowserTestBase::kSingleFrameHostname[];
+// static
+constexpr char ContentCaptureDeviceBrowserTestBase::kSingleFramePath[];
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/content_capture_device_browsertest_base.h b/chromium/content/browser/media/capture/content_capture_device_browsertest_base.h
new file mode 100644
index 00000000000..a6f4135f6c1
--- /dev/null
+++ b/chromium/content/browser/media/capture/content_capture_device_browsertest_base.h
@@ -0,0 +1,129 @@
+// 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_MEDIA_CAPTURE_CONTENT_CAPTURE_DEVICE_BROWSERTEST_BASE_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_CONTENT_CAPTURE_DEVICE_BROWSERTEST_BASE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "content/browser/media/capture/fake_video_capture_stack.h"
+#include "content/public/test/content_browser_test.h"
+#include "media/capture/video_capture_types.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace net {
+namespace test_server {
+struct HttpRequest;
+class HttpResponse;
+} // namespace test_server
+} // namespace net
+
+namespace content {
+
+class FrameSinkVideoCaptureDevice;
+
+// Common base class for screen capture browser tests. Since this is a
+// ContentBrowserTest, it assumes the test environment consists of a content
+// shell and a single WebContents.
+class ContentCaptureDeviceBrowserTestBase : public ContentBrowserTest {
+ public:
+ ContentCaptureDeviceBrowserTestBase();
+ ~ContentCaptureDeviceBrowserTestBase() override;
+
+ FakeVideoCaptureStack* capture_stack() { return &capture_stack_; }
+ FrameSinkVideoCaptureDevice* device() const { return device_.get(); }
+
+ // Alters the solid fill color making up the page content. This will trigger a
+ // compositor update, which will trigger a frame capture.
+ void ChangePageContentColor(SkColor color);
+
+ // Returns the captured source size, but also sanity-checks that it is not
+ // changing during the test. Prefer to use this method instead of
+ // GetCapturedSourceSize() to improve test stability.
+ gfx::Size GetExpectedSourceSize();
+
+ // Returns capture parameters based on the captured source size.
+ media::VideoCaptureParams SnapshotCaptureParams();
+
+ // Returns the actual minimum capture period the device is using. This should
+ // not be called until after AllocateAndStartAndWaitForFirstFrame().
+ base::TimeDelta GetMinCapturePeriod();
+
+ // Navigates to the initial document, according to the current test
+ // parameters, and waits for page load completion. All test fixtures should
+ // call this before any of the other methods.
+ void NavigateToInitialDocument();
+
+ // Creates and starts the device for frame capture, and checks that the
+ // initial refresh frame is delivered.
+ void AllocateAndStartAndWaitForFirstFrame();
+
+ // Stops and destroys the device.
+ void StopAndDeAllocate();
+
+ // Runs the message loop until idle.
+ void RunUntilIdle();
+
+ void ClearCapturedFramesQueue() { capture_stack_.ClearCapturedFramesQueue(); }
+
+ bool HasCapturedFramesInQueue() const {
+ return capture_stack_.has_captured_frames();
+ }
+
+ protected:
+ // These all return false, but can be overridden for parameterized tests to
+ // change the behavior of this base class.
+ virtual bool IsSoftwareCompositingTest() const;
+ virtual bool IsFixedAspectRatioTest() const;
+ virtual bool IsCrossSiteCaptureTest() const;
+
+ // Returns the size of the original content (i.e., not including any
+ // stretching/scaling being done to fit it within a video frame).
+ virtual gfx::Size GetCapturedSourceSize() const = 0;
+
+ // Returns a new FrameSinkVideoCaptureDevice instance.
+ virtual std::unique_ptr<FrameSinkVideoCaptureDevice> CreateDevice() = 0;
+
+ // Called to wait for the first frame with expected content.
+ virtual void WaitForFirstFrame() = 0;
+
+ // ContentBrowserTest overrides to enable pixel output and set-up/tear-down
+ // the embedded HTTP server that provides test content.
+ void SetUp() override;
+ void SetUpCommandLine(base::CommandLine* command_line) override;
+ void SetUpOnMainThread() override;
+ void TearDownOnMainThread() override;
+
+ private:
+ // Called by the embedded test HTTP server to provide the document resources.
+ std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
+ const net::test_server::HttpRequest& request);
+
+ FakeVideoCaptureStack capture_stack_;
+ base::Optional<gfx::Size> expected_source_size_;
+ std::unique_ptr<FrameSinkVideoCaptureDevice> device_;
+
+ // Arbitrary string constants used to refer to each document by
+ // host+path. Note that the "inner frame" and "outer frame" must have
+ // different hostnames to engage the cross-site process isolation logic in the
+ // browser.
+ static constexpr char kInnerFrameHostname[] = "innerframe.com";
+ static constexpr char kInnerFramePath[] = "/inner.html";
+ static constexpr char kOuterFrameHostname[] = "outerframe.com";
+ static constexpr char kOuterFramePath[] = "/outer.html";
+ static constexpr char kSingleFrameHostname[] = "singleframe.com";
+ static constexpr char kSingleFramePath[] = "/single.html";
+
+ DISALLOW_COPY_AND_ASSIGN(ContentCaptureDeviceBrowserTestBase);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_CONTENT_CAPTURE_DEVICE_BROWSERTEST_BASE_H_
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.cc b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
index d390783b242..ec13d0da468 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
@@ -112,9 +112,8 @@ SkBitmap CursorRendererAura::GetLastKnownCursorImage(gfx::Point* hot_point) {
}
gfx::NativeCursor cursor = window_->GetHost()->last_cursor();
- SkBitmap cursor_bitmap;
- ui::GetCursorBitmap(cursor, &cursor_bitmap, hot_point);
- return cursor_bitmap;
+ *hot_point = cursor.GetHotspot();
+ return cursor.GetBitmap();
}
void CursorRendererAura::OnMouseEvent(ui::MouseEvent* event) {
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc b/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
index b9017fa7d5c..4a5209e9985 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
@@ -41,7 +41,7 @@ class CursorRendererAuraTest : public AuraTestBase {
// Initialize the shared global resource bundle that has bitmap
// resources needed by CursorRenderer
base::FilePath pak_file;
- bool r = PathService::Get(base::DIR_MODULE, &pak_file);
+ bool r = base::PathService::Get(base::DIR_MODULE, &pak_file);
DCHECK(r);
pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
@@ -92,18 +92,18 @@ class CursorRendererAuraTest : public AuraTestBase {
void MoveMouseCursorWithinWindow() {
gfx::Point point1(20, 20);
ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point1, point1, Now(), 0, 0);
- aura::Env::GetInstance()->set_last_mouse_location(point1);
+ aura::Env::GetInstance()->SetLastMouseLocation(point1);
cursor_renderer_->OnMouseEvent(&event1);
gfx::Point point2(60, 60);
ui::MouseEvent event2(ui::ET_MOUSE_MOVED, point2, point2, Now(), 0, 0);
- aura::Env::GetInstance()->set_last_mouse_location(point2);
+ aura::Env::GetInstance()->SetLastMouseLocation(point2);
cursor_renderer_->OnMouseEvent(&event2);
}
void MoveMouseCursorOutsideWindow() {
gfx::Point point(1000, 1000);
ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point, point, Now(), 0, 0);
- aura::Env::GetInstance()->set_last_mouse_location(point);
+ aura::Env::GetInstance()->SetLastMouseLocation(point);
cursor_renderer_->OnMouseEvent(&event1);
}
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index df6078bc5f7..01954292117 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -181,6 +181,10 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
// result.
bool first_capture_returned_;
+ // True if the first capture permanent error has been logged. Used to log the
+ // first capture permanent error.
+ bool first_permanent_error_logged;
+
// The type of the capturer.
DesktopMediaID::Type capturer_type_;
@@ -208,6 +212,7 @@ DesktopCaptureDevice::Core::Core(
max_cpu_consumption_percentage_(GetMaximumCpuConsumptionPercentage()),
capture_in_progress_(false),
first_capture_returned_(false),
+ first_permanent_error_logged(false),
capturer_type_(type),
weak_factory_(this) {}
@@ -299,8 +304,17 @@ void DesktopCaptureDevice::Core::OnCaptureResult(
}
if (!success) {
- if (result == webrtc::DesktopCapturer::Result::ERROR_PERMANENT)
+ if (result == webrtc::DesktopCapturer::Result::ERROR_PERMANENT) {
+ if (!first_permanent_error_logged) {
+ first_permanent_error_logged = true;
+ if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
+ IncrementDesktopCaptureCounter(SCREEN_CAPTURER_PERMANENT_ERROR);
+ } else {
+ IncrementDesktopCaptureCounter(WINDOW_CAPTURER_PERMANENT_ERROR);
+ }
+ }
client_->OnError(FROM_HERE, "The desktop capturer has failed.");
+ }
return;
}
DCHECK(frame);
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
index 8714ce6f501..7de25f82bfa 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -51,6 +51,13 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
base::TimeTicks reference_time,
base::TimeDelta tiemstamp,
int frame_feedback_id));
+ MOCK_METHOD6(OnIncomingCapturedGfxBuffer,
+ void(gfx::GpuMemoryBuffer* buffer,
+ const media::VideoCaptureFormat& frame_format,
+ int clockwise_rotation,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
+ int frame_feedback_id));
MOCK_METHOD0(DoReserveOutputBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
@@ -63,10 +70,8 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
// Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
media::VideoPixelFormat format,
- media::VideoPixelStorage storage,
int frame_feedback_id) override {
EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
- EXPECT_EQ(media::VideoPixelStorage::CPU, storage);
DoReserveOutputBuffer();
return Buffer();
}
@@ -87,10 +92,8 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
}
Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
media::VideoPixelFormat format,
- media::VideoPixelStorage storage,
int frame_feedback_id) override {
EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
- EXPECT_EQ(media::VideoPixelStorage::CPU, storage);
DoResurrectLastOutputBuffer();
return Buffer();
}
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h b/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
index 07df96a1864..c2ed81b5e19 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
@@ -24,6 +24,8 @@ enum DesktopCaptureCounters {
SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO,
TAB_VIDEO_CAPTURER_CREATED_WITH_AUDIO,
TAB_VIDEO_CAPTURER_CREATED_WITHOUT_AUDIO,
+ SCREEN_CAPTURER_PERMANENT_ERROR,
+ WINDOW_CAPTURER_PERMANENT_ERROR,
DESKTOP_CAPTURE_COUNTER_BOUNDARY
};
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
index 08f262b5262..96e5f8c1e81 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -13,7 +13,7 @@
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_mock_time_task_runner.h"
@@ -73,6 +73,13 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
base::TimeTicks reference_time,
base::TimeDelta timestamp,
int frame_feedback_id));
+ MOCK_METHOD6(OnIncomingCapturedGfxBuffer,
+ void(gfx::GpuMemoryBuffer* buffer,
+ const media::VideoCaptureFormat& frame_format,
+ int clockwise_rotation,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
+ int frame_feedback_id));
MOCK_METHOD0(DoReserveOutputBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
@@ -85,10 +92,8 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
// Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
media::VideoPixelFormat format,
- media::VideoPixelStorage storage,
int frame_feedback_id) override {
- EXPECT_TRUE(format == media::PIXEL_FORMAT_I420 &&
- storage == media::VideoPixelStorage::CPU);
+ EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
DoReserveOutputBuffer();
return Buffer();
}
@@ -109,10 +114,8 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
}
Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
media::VideoPixelFormat format,
- media::VideoPixelStorage storage,
int frame_feedback_id) override {
- EXPECT_TRUE(format == media::PIXEL_FORMAT_I420 &&
- storage == media::VideoPixelStorage::CPU);
+ EXPECT_TRUE(format == media::PIXEL_FORMAT_I420);
DoResurrectLastOutputBuffer();
return Buffer();
}
@@ -630,7 +633,7 @@ class DesktopCaptureDeviceThrottledTest : public DesktopCaptureDeviceTest {
// 'PostNonNestable' is required to make sure the next one
// shot capture timer is already pushed when forwaring the
// virtual time by the next pending task delay.
- base::MessageLoop::current()
+ base::MessageLoopCurrent::Get()
->task_runner()
->PostNonNestableTask(
FROM_HERE,
diff --git a/chromium/content/browser/media/capture/fake_video_capture_stack.cc b/chromium/content/browser/media/capture/fake_video_capture_stack.cc
new file mode 100644
index 00000000000..8bd1c9c1540
--- /dev/null
+++ b/chromium/content/browser/media/capture/fake_video_capture_stack.cc
@@ -0,0 +1,159 @@
+// 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/media/capture/fake_video_capture_stack.h"
+
+#include <stdint.h>
+
+#include <utility>
+
+#include "base/bind_helpers.h"
+#include "media/base/video_frame.h"
+#include "media/capture/video/video_frame_receiver.h"
+#include "media/capture/video_capture_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libyuv/include/libyuv.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace content {
+
+FakeVideoCaptureStack::FakeVideoCaptureStack() = default;
+
+FakeVideoCaptureStack::~FakeVideoCaptureStack() = default;
+
+void FakeVideoCaptureStack::Reset() {
+ frames_.clear();
+ last_frame_timestamp_ = base::TimeDelta::Min();
+}
+
+class FakeVideoCaptureStack::Receiver : public media::VideoFrameReceiver {
+ public:
+ explicit Receiver(FakeVideoCaptureStack* capture_stack)
+ : capture_stack_(capture_stack) {}
+ ~Receiver() final = default;
+
+ private:
+ using Buffer = media::VideoCaptureDevice::Client::Buffer;
+
+ void OnNewBuffer(int buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle) final {
+ buffers_[buffer_id] = std::move(buffer_handle);
+ }
+
+ void OnFrameReadyInBuffer(
+ int buffer_id,
+ int frame_feedback_id,
+ std::unique_ptr<Buffer::ScopedAccessPermission> access,
+ media::mojom::VideoFrameInfoPtr frame_info) final {
+ const auto it = buffers_.find(buffer_id);
+ CHECK(it != buffers_.end());
+ CHECK(it->second->is_shared_buffer_handle());
+ mojo::ScopedSharedBufferHandle& buffer =
+ it->second->get_shared_buffer_handle();
+
+ const size_t mapped_size =
+ media::VideoCaptureFormat(frame_info->coded_size, 0.0f,
+ frame_info->pixel_format)
+ .ImageAllocationSize();
+ mojo::ScopedSharedBufferMapping mapping = buffer->Map(mapped_size);
+ CHECK(mapping.get());
+
+ auto frame = media::VideoFrame::WrapExternalData(
+ frame_info->pixel_format, frame_info->coded_size,
+ frame_info->visible_rect, frame_info->visible_rect.size(),
+ reinterpret_cast<uint8_t*>(mapping.get()), mapped_size,
+ frame_info->timestamp);
+ CHECK(frame);
+ frame->metadata()->MergeInternalValuesFrom(frame_info->metadata);
+ // This destruction observer will unmap the shared memory when the
+ // VideoFrame goes out-of-scope.
+ frame->AddDestructionObserver(
+ base::BindOnce(base::DoNothing::Once<mojo::ScopedSharedBufferMapping>(),
+ std::move(mapping)));
+ // This destruction observer will notify the video capture device once all
+ // downstream code is done using the VideoFrame.
+ frame->AddDestructionObserver(base::BindOnce(
+ [](std::unique_ptr<Buffer::ScopedAccessPermission> access) {},
+ std::move(access)));
+
+ capture_stack_->OnReceivedFrame(std::move(frame));
+ }
+
+ void OnBufferRetired(int buffer_id) final {
+ const auto it = buffers_.find(buffer_id);
+ CHECK(it != buffers_.end());
+ buffers_.erase(it);
+ }
+
+ void OnError() final { capture_stack_->error_occurred_ = true; }
+
+ void OnLog(const std::string& message) final {
+ capture_stack_->log_messages_.push_back(message);
+ }
+
+ void OnStarted() final { capture_stack_->started_ = true; }
+
+ void OnStartedUsingGpuDecode() final { NOTREACHED(); }
+
+ FakeVideoCaptureStack* const capture_stack_;
+ base::flat_map<int, media::mojom::VideoBufferHandlePtr> buffers_;
+
+ DISALLOW_COPY_AND_ASSIGN(Receiver);
+};
+
+std::unique_ptr<media::VideoFrameReceiver>
+FakeVideoCaptureStack::CreateFrameReceiver() {
+ return std::make_unique<Receiver>(this);
+}
+
+SkBitmap FakeVideoCaptureStack::NextCapturedFrame() {
+ CHECK(!frames_.empty());
+ media::VideoFrame& frame = *(frames_.front());
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(frame.visible_rect().width(),
+ frame.visible_rect().height());
+ // TODO(crbug/810131): This is not Rec.709 colorspace conversion, and so will
+ // introduce inaccuracies.
+ libyuv::I420ToARGB(frame.visible_data(media::VideoFrame::kYPlane),
+ frame.stride(media::VideoFrame::kYPlane),
+ frame.visible_data(media::VideoFrame::kUPlane),
+ frame.stride(media::VideoFrame::kUPlane),
+ frame.visible_data(media::VideoFrame::kVPlane),
+ frame.stride(media::VideoFrame::kVPlane),
+ reinterpret_cast<uint8_t*>(bitmap.getPixels()),
+ static_cast<int>(bitmap.rowBytes()), bitmap.width(),
+ bitmap.height());
+ frames_.pop_front();
+ return bitmap;
+}
+
+void FakeVideoCaptureStack::ClearCapturedFramesQueue() {
+ frames_.clear();
+}
+
+void FakeVideoCaptureStack::ExpectHasLogMessages() {
+ EXPECT_FALSE(log_messages_.empty());
+ while (!log_messages_.empty()) {
+ VLOG(1) << "Next log message: " << log_messages_.front();
+ log_messages_.pop_front();
+ }
+}
+
+void FakeVideoCaptureStack::ExpectNoLogMessages() {
+ while (!log_messages_.empty()) {
+ ADD_FAILURE() << "Unexpected log message: " << log_messages_.front();
+ log_messages_.pop_front();
+ }
+}
+
+void FakeVideoCaptureStack::OnReceivedFrame(
+ scoped_refptr<media::VideoFrame> frame) {
+ // Frame timestamps should be monotionically increasing.
+ EXPECT_LT(last_frame_timestamp_, frame->timestamp());
+ last_frame_timestamp_ = frame->timestamp();
+
+ frames_.emplace_back(std::move(frame));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/fake_video_capture_stack.h b/chromium/content/browser/media/capture/fake_video_capture_stack.h
new file mode 100644
index 00000000000..8092af19359
--- /dev/null
+++ b/chromium/content/browser/media/capture/fake_video_capture_stack.h
@@ -0,0 +1,80 @@
+// 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_MEDIA_CAPTURE_FAKE_VIDEO_CAPTURE_STACK_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_FAKE_VIDEO_CAPTURE_STACK_H_
+
+#include <memory>
+#include <string>
+
+#include "base/containers/circular_deque.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/time/time.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace media {
+class VideoFrame;
+class VideoFrameReceiver;
+}; // namespace media
+
+namespace content {
+
+// Provides a fake representation of the entire video capture stack. It creates
+// a VideoFrameReceiver that a device can deliver video frames to, and adapts
+// that to a simple collector of video frames, represented as SkBitmaps, for
+// further examination by the browser tests.
+class FakeVideoCaptureStack {
+ public:
+ FakeVideoCaptureStack();
+ ~FakeVideoCaptureStack();
+
+ // Reset the capture stack to a state where it contains no frames and is
+ // expecting a first frame.
+ void Reset();
+
+ // Returns a VideoFrameReceiver that the implementation under test delivers
+ // frames to.
+ std::unique_ptr<media::VideoFrameReceiver> CreateFrameReceiver();
+
+ // Returns true if the device called VideoFrameReceiver::OnStarted().
+ bool started() const { return started_; }
+
+ // Returns true if the device called VideoFrameReceiver::OnError().
+ bool error_occurred() const { return error_occurred_; }
+
+ // Accessors to capture frame queue.
+ bool has_captured_frames() const { return !frames_.empty(); }
+ SkBitmap NextCapturedFrame();
+ void ClearCapturedFramesQueue();
+
+ // Called when tests expect there to be one or more log messages sent to the
+ // video capture stack. Turn on verbose logging for a dump of the actual log
+ // messages. This method clears the queue of log messages.
+ void ExpectHasLogMessages();
+
+ // Called when tests expect there to be no log messages sent to the video
+ // capture stack.
+ void ExpectNoLogMessages();
+
+ private:
+ // A minimal implementation of VideoFrameReceiver that wraps buffers into
+ // VideoFrame instances and forwards all relevant callbacks and data to the
+ // parent FakeVideoCaptureStack.
+ class Receiver;
+
+ // Checks that the frame timestamp is monotonically increasing and then
+ // stashes it in the |frames_| queue for later examination by the tests.
+ void OnReceivedFrame(scoped_refptr<media::VideoFrame> frame);
+
+ bool started_ = false;
+ bool error_occurred_ = false;
+ base::circular_deque<std::string> log_messages_;
+ base::circular_deque<scoped_refptr<media::VideoFrame>> frames_;
+ base::TimeDelta last_frame_timestamp_ = base::TimeDelta::Min();
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_FAKE_VIDEO_CAPTURE_STACK_H_
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc b/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
index 8db3dc88281..80ad28d503b 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -33,47 +33,6 @@ std::unique_ptr<T, BrowserThread::DeleteOnUIThread> RescopeToUIThread(
return std::unique_ptr<T, BrowserThread::DeleteOnUIThread>(ptr.release());
}
-// Sets up a mojo message pipe and requests the HostFrameSinkManager create a
-// new capturer instance bound to it. Returns the client-side interface.
-viz::mojom::FrameSinkVideoCapturerPtrInfo CreateCapturer() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- viz::HostFrameSinkManager* const manager = GetHostFrameSinkManager();
- DCHECK(manager);
- viz::mojom::FrameSinkVideoCapturerPtr capturer;
- manager->CreateVideoCapturer(mojo::MakeRequest(&capturer));
- return capturer.PassInterface();
-}
-
-// Adapter for a VideoFrameReceiver to get access to the mojo SharedBufferHandle
-// for a frame.
-class HandleMover
- : public media::VideoCaptureDevice::Client::Buffer::HandleProvider {
- public:
- explicit HandleMover(mojo::ScopedSharedBufferHandle handle)
- : handle_(std::move(handle)) {}
- ~HandleMover() final {}
-
- mojo::ScopedSharedBufferHandle GetHandleForInterProcessTransit(
- bool read_only) final {
- return std::move(handle_);
- }
-
- base::SharedMemoryHandle GetNonOwnedSharedMemoryHandleForLegacyIPC() final {
- NOTREACHED();
- return base::SharedMemoryHandle();
- }
-
- std::unique_ptr<media::VideoCaptureBufferHandle> GetHandleForInProcessAccess()
- final {
- NOTREACHED();
- return nullptr;
- }
-
- private:
- mojo::ScopedSharedBufferHandle handle_;
-};
-
// Adapter for a VideoFrameReceiver to notify once frame consumption is
// complete. VideoFrameReceiver requires owning an object that it will destroy
// once consumption is complete. This class adapts between that scheme and
@@ -90,9 +49,7 @@ class ScopedFrameDoneHelper
} // namespace
FrameSinkVideoCaptureDevice::FrameSinkVideoCaptureDevice()
- : capturer_creator_(base::BindRepeating(&CreateCapturer)),
- binding_(this),
- cursor_renderer_(RescopeToUIThread(CursorRenderer::Create(
+ : cursor_renderer_(RescopeToUIThread(CursorRenderer::Create(
CursorRenderer::CURSOR_DISPLAYED_ON_MOUSE_MOVEMENT))),
weak_factory_(this) {
DCHECK(cursor_renderer_);
@@ -133,12 +90,33 @@ void FrameSinkVideoCaptureDevice::AllocateAndStartWithReceiver(
&FrameSinkVideoCaptureDevice::RequestRefreshFrame,
weak_factory_.GetWeakPtr()))));
- // Hop to the UI thread to request a Mojo connection to a new capturer
- // instance, and then hop back to the device thread to start using it.
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE, base::BindOnce(capturer_creator_),
- base::BindOnce(&FrameSinkVideoCaptureDevice::OnCapturerCreated,
- weak_factory_.GetWeakPtr()));
+ // Shutdown the prior capturer, if any.
+ MaybeStopConsuming();
+
+ capturer_ = std::make_unique<viz::ClientFrameSinkVideoCapturer>(
+ base::BindRepeating(&FrameSinkVideoCaptureDevice::CreateCapturer,
+ base::Unretained(this)));
+
+ capturer_->SetFormat(capture_params_.requested_format.pixel_format,
+ media::COLOR_SPACE_UNSPECIFIED);
+ capturer_->SetMinCapturePeriod(
+ base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>(
+ base::Time::kMicrosecondsPerSecond /
+ capture_params_.requested_format.frame_rate)));
+ const auto& constraints = capture_params_.SuggestConstraints();
+ capturer_->SetResolutionConstraints(constraints.min_frame_size,
+ constraints.max_frame_size,
+ constraints.fixed_aspect_ratio);
+
+ if (target_.is_valid()) {
+ capturer_->ChangeTarget(target_);
+ }
+
+ receiver_->OnStarted();
+
+ if (!suspend_requested_) {
+ MaybeStartConsuming();
+ }
}
void FrameSinkVideoCaptureDevice::AllocateAndStart(
@@ -153,7 +131,7 @@ void FrameSinkVideoCaptureDevice::AllocateAndStart(
void FrameSinkVideoCaptureDevice::RequestRefreshFrame() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (capturer_ && binding_.is_bound() && !suspend_requested_) {
+ if (capturer_ && !suspend_requested_) {
capturer_->RequestRefreshFrame();
}
}
@@ -266,9 +244,11 @@ void FrameSinkVideoCaptureDevice::OnFrameCaptured(
// Pass the video frame to the VideoFrameReceiver. This is done by first
// passing the shared memory buffer handle and then notifying it that a new
// frame is ready to be read from the buffer.
- receiver_->OnNewBufferHandle(
- static_cast<BufferId>(slot_index),
- std::make_unique<HandleMover>(std::move(buffer)));
+ media::mojom::VideoBufferHandlePtr buffer_handle =
+ media::mojom::VideoBufferHandle::New();
+ buffer_handle->set_shared_buffer_handle(std::move(buffer));
+ receiver_->OnNewBuffer(static_cast<BufferId>(slot_index),
+ std::move(buffer_handle));
receiver_->OnFrameReadyInBuffer(
static_cast<BufferId>(slot_index), slot_index,
std::make_unique<ScopedFrameDoneHelper>(
@@ -288,9 +268,9 @@ void FrameSinkVideoCaptureDevice::OnStopped() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// This method would never be called if FrameSinkVideoCaptureDevice explicitly
- // called capturer_->Stop(), because the binding is closed at that time.
- // Therefore, a call to this method means that the capturer cannot continue;
- // and that's a permanent failure.
+ // called capturer_->StopAndResetConsumer(), because the binding is closed at
+ // that time. Therefore, a call to this method means that the capturer cannot
+ // continue; and that's a permanent failure.
OnFatalError("Capturer service cannot continue.");
}
@@ -315,80 +295,47 @@ void FrameSinkVideoCaptureDevice::OnTargetPermanentlyLost() {
OnFatalError("Capture target has been permanently lost.");
}
-void FrameSinkVideoCaptureDevice::SetCapturerCreatorForTesting(
- CapturerCreatorCallback creator) {
- capturer_creator_ = std::move(creator);
-}
-
void FrameSinkVideoCaptureDevice::WillStart() {}
void FrameSinkVideoCaptureDevice::DidStop() {}
-void FrameSinkVideoCaptureDevice::OnCapturerCreated(
- viz::mojom::FrameSinkVideoCapturerPtrInfo info) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- if (!receiver_) {
- return; // StopAndDeAllocate() occurred in the meantime.
- }
-
- // Shutdown the prior capturer, if any.
- MaybeStopConsuming();
- capturer_.reset();
-
- // Bind and configure the new capturer.
- capturer_.Bind(std::move(info));
- // TODO(miu): Remove this once HostFrameSinkManager will notify this
- // consumer when to take recovery steps after VIZ process crashes.
- capturer_.set_connection_error_handler(base::BindOnce(
- &FrameSinkVideoCaptureDevice::OnFatalError, base::Unretained(this),
- "Capturer service connection lost."));
- capturer_->SetFormat(capture_params_.requested_format.pixel_format,
- media::COLOR_SPACE_UNSPECIFIED);
- capturer_->SetMinCapturePeriod(
- base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>(
- base::Time::kMicrosecondsPerSecond /
- capture_params_.requested_format.frame_rate)));
- const auto& constraints = capture_params_.SuggestConstraints();
- capturer_->SetResolutionConstraints(constraints.min_frame_size,
- constraints.max_frame_size,
- constraints.fixed_aspect_ratio);
-
- if (target_.is_valid()) {
- capturer_->ChangeTarget(target_);
- }
-
- receiver_->OnStarted();
+void FrameSinkVideoCaptureDevice::CreateCapturer(
+ viz::mojom::FrameSinkVideoCapturerRequest request) {
+ CreateCapturerViaGlobalManager(std::move(request));
+}
- if (!suspend_requested_) {
- MaybeStartConsuming();
- }
+// static
+void FrameSinkVideoCaptureDevice::CreateCapturerViaGlobalManager(
+ viz::mojom::FrameSinkVideoCapturerRequest request) {
+ // Send the request to UI thread because that's where HostFrameSinkManager
+ // lives.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ [](viz::mojom::FrameSinkVideoCapturerRequest request) {
+ viz::HostFrameSinkManager* const manager =
+ GetHostFrameSinkManager();
+ DCHECK(manager);
+ manager->CreateVideoCapturer(std::move(request));
+ },
+ std::move(request)));
}
void FrameSinkVideoCaptureDevice::MaybeStartConsuming() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!receiver_ || !capturer_ || binding_.is_bound()) {
+ if (!receiver_ || !capturer_) {
return;
}
- viz::mojom::FrameSinkVideoConsumerPtr consumer;
- binding_.Bind(mojo::MakeRequest(&consumer));
- // TODO(miu): Remove this once HostFrameSinkManager will notify this consumer
- // when to take recovery steps after VIZ process crashes.
- binding_.set_connection_error_handler(base::BindOnce(
- &FrameSinkVideoCaptureDevice::OnFatalError, base::Unretained(this),
- "Consumer connection to Capturer service lost."));
- capturer_->Start(std::move(consumer));
+ capturer_->Start(this);
}
void FrameSinkVideoCaptureDevice::MaybeStopConsuming() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (capturer_) {
- capturer_->Stop();
- }
- binding_.Close();
+ if (capturer_)
+ capturer_->StopAndResetConsumer();
}
void FrameSinkVideoCaptureDevice::OnFramePropagationComplete(
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device.h b/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
index bca2bf237a8..fefe7b9d10c 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device.h
@@ -13,6 +13,7 @@
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/host/client_frame_sink_video_capturer.h"
#include "content/browser/media/capture/cursor_renderer.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
@@ -21,7 +22,6 @@
#include "media/capture/video/video_frame_receiver.h"
#include "media/capture/video_capture_types.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
namespace content {
@@ -43,9 +43,6 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
: public media::VideoCaptureDevice,
public viz::mojom::FrameSinkVideoConsumer {
public:
- using CapturerCreatorCallback =
- base::RepeatingCallback<viz::mojom::FrameSinkVideoCapturerPtrInfo()>;
-
FrameSinkVideoCaptureDevice();
~FrameSinkVideoCaptureDevice() override;
@@ -87,9 +84,6 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
void OnTargetChanged(const viz::FrameSinkId& frame_sink_id);
void OnTargetPermanentlyLost();
- // Overrides the callback that is run to create the capturer.
- void SetCapturerCreatorForTesting(CapturerCreatorCallback creator);
-
protected:
CursorRenderer* cursor_renderer() const { return cursor_renderer_.get(); }
@@ -97,12 +91,20 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
virtual void WillStart();
virtual void DidStop();
+ // Establishes connection to FrameSinkVideoCapturer. The default
+ // implementation calls CreateCapturerViaGlobalManager(), but subclasses
+ // and/or tests may provide alternatives.
+ virtual void CreateCapturer(
+ viz::mojom::FrameSinkVideoCapturerRequest request);
+
+ // Establishes connection to FrameSinkVideoCapturer using the global
+ // viz::HostFrameSinkManager.
+ static void CreateCapturerViaGlobalManager(
+ viz::mojom::FrameSinkVideoCapturerRequest request);
+
private:
using BufferId = decltype(media::VideoCaptureDevice::Client::Buffer::id);
- // Bind a newly-created capturer, configure it, and resuming consuming.
- void OnCapturerCreated(viz::mojom::FrameSinkVideoCapturerPtrInfo info);
-
// If not consuming and all preconditions are met, set up and start consuming.
void MaybeStartConsuming();
@@ -135,16 +137,7 @@ class CONTENT_EXPORT FrameSinkVideoCaptureDevice
// cleared by StopAndDeAllocate().
std::unique_ptr<media::VideoFrameReceiver> receiver_;
- // Callback that is run to request a capturer be created and returns the
- // client-side interface. This callback will be run on the UI BrowserThread.
- // The constructor provides a default, but unit tests can override this.
- CapturerCreatorCallback capturer_creator_;
-
- // Mojo pointer to the capturer instance in VIZ.
- viz::mojom::FrameSinkVideoCapturerPtr capturer_;
-
- // Mojo binding to this instance as a consumer of frames from the capturer.
- mojo::Binding<viz::mojom::FrameSinkVideoConsumer> binding_;
+ std::unique_ptr<viz::ClientFrameSinkVideoCapturer> capturer_;
// A pool of structs that hold state relevant to frames currently being
// processed by VideoFrameReceiver. Each "slot" is re-used by later frames.
diff --git a/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
index f52055ef111..b9cc7f8bad8 100644
--- a/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -60,13 +60,12 @@ constexpr int kMaxFrameRate = 25; // It evenly divides 1 million usec.
constexpr base::TimeDelta kMinCapturePeriod = base::TimeDelta::FromMicroseconds(
base::Time::kMicrosecondsPerSecond / kMaxFrameRate);
constexpr media::VideoPixelFormat kFormat = media::PIXEL_FORMAT_I420;
-constexpr media::VideoPixelStorage kStorage = media::VideoPixelStorage::CPU;
// Helper to return the capture parameters packaged in a VideoCaptureParams.
media::VideoCaptureParams GetCaptureParams() {
media::VideoCaptureParams params;
params.requested_format =
- media::VideoCaptureFormat(kResolution, kMaxFrameRate, kFormat, kStorage);
+ media::VideoCaptureFormat(kResolution, kMaxFrameRate, kFormat);
return params;
}
@@ -141,22 +140,22 @@ class MockVideoFrameReceiver : public media::VideoFrameReceiver {
~MockVideoFrameReceiver() override {
DCHECK_ON_DEVICE_THREAD();
- EXPECT_TRUE(handle_providers_.empty());
+ EXPECT_TRUE(buffer_handles_.empty());
EXPECT_TRUE(feedback_ids_.empty());
EXPECT_TRUE(access_permissions_.empty());
EXPECT_TRUE(frame_infos_.empty());
}
- void OnNewBufferHandle(
- int buffer_id,
- std::unique_ptr<Buffer::HandleProvider> handle_provider) final {
+ void OnNewBuffer(int buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle) final {
DCHECK_ON_DEVICE_THREAD();
- auto* const raw_pointer = handle_provider.get();
- handle_providers_[buffer_id] = std::move(handle_provider);
- MockOnNewBufferHandle(buffer_id, raw_pointer);
+ auto* const raw_pointer = buffer_handle.get();
+ buffer_handles_[buffer_id] = std::move(buffer_handle);
+ MockOnNewBuffer(buffer_id, raw_pointer);
}
- MOCK_METHOD2(MockOnNewBufferHandle,
- void(int buffer_id, Buffer::HandleProvider* handle_provider));
+ MOCK_METHOD2(MockOnNewBuffer,
+ void(int buffer_id,
+ media::mojom::VideoBufferHandle* buffer_handle));
void OnFrameReadyInBuffer(
int buffer_id,
int frame_feedback_id,
@@ -184,13 +183,14 @@ class MockVideoFrameReceiver : public media::VideoFrameReceiver {
mojo::ScopedSharedBufferHandle TakeBufferHandle(int buffer_id) {
DCHECK_NOT_ON_DEVICE_THREAD();
- const auto it = handle_providers_.find(buffer_id);
- if (it == handle_providers_.end()) {
+ const auto it = buffer_handles_.find(buffer_id);
+ if (it == buffer_handles_.end()) {
ADD_FAILURE() << "Missing entry for buffer_id=" << buffer_id;
return mojo::ScopedSharedBufferHandle();
}
- auto buffer = it->second->GetHandleForInterProcessTransit(true);
- handle_providers_.erase(it);
+ CHECK(it->second->is_shared_buffer_handle());
+ auto buffer = std::move(it->second->get_shared_buffer_handle());
+ buffer_handles_.erase(it);
return buffer;
}
@@ -229,14 +229,36 @@ class MockVideoFrameReceiver : public media::VideoFrameReceiver {
}
private:
- base::flat_map<int, std::unique_ptr<Buffer::HandleProvider>>
- handle_providers_;
+ base::flat_map<int, media::mojom::VideoBufferHandlePtr> buffer_handles_;
base::flat_map<int, int> feedback_ids_;
base::flat_map<int, std::unique_ptr<Buffer::ScopedAccessPermission>>
access_permissions_;
base::flat_map<int, media::mojom::VideoFrameInfoPtr> frame_infos_;
};
+// A FrameSinkVideoCaptureDevice, but with CreateCapturer() overridden to bind
+// to a MockFrameSinkVideoCapturer instead of the real thing.
+class FrameSinkVideoCaptureDeviceForTest : public FrameSinkVideoCaptureDevice {
+ public:
+ explicit FrameSinkVideoCaptureDeviceForTest(
+ MockFrameSinkVideoCapturer* capturer)
+ : capturer_(capturer) {}
+
+ protected:
+ void CreateCapturer(viz::mojom::FrameSinkVideoCapturerRequest request) final {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ [](MockFrameSinkVideoCapturer* capturer,
+ viz::mojom::FrameSinkVideoCapturerRequest request) {
+ capturer->Bind(std::move(request));
+ },
+ capturer_, std::move(request)));
+ }
+
+ MockFrameSinkVideoCapturer* const capturer_;
+};
+
// Convenience macros to make a non-blocking FrameSinkVideoCaptureDevice method
// call on the device thread.
#define POST_DEVICE_METHOD_CALL0(method) \
@@ -259,21 +281,11 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
// until complete.
POST_DEVICE_TASK(base::BindOnce(
[](FrameSinkVideoCaptureDeviceTest* test) {
- test->device_ = std::make_unique<FrameSinkVideoCaptureDevice>();
+ test->device_ = std::make_unique<FrameSinkVideoCaptureDeviceForTest>(
+ &test->capturer_);
},
this));
WAIT_FOR_DEVICE_TASKS();
-
- // Set an override to "create" the mock capturer instance instead of the
- // real thing.
- device_->SetCapturerCreatorForTesting(base::BindRepeating(
- [](MockFrameSinkVideoCapturer* capturer) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- viz::mojom::FrameSinkVideoCapturerPtr capturer_ptr;
- capturer->Bind(mojo::MakeRequest(&capturer_ptr));
- return capturer_ptr.PassInterface();
- },
- &capturer_));
}
void TearDown() override {
@@ -348,7 +360,7 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
std::move(buffer), buffer_size,
media::mojom::VideoFrameInfo::New(
kMinCapturePeriod * frame_number,
- base::Value(base::Value::Type::DICTIONARY), kFormat, kStorage,
+ base::Value(base::Value::Type::DICTIONARY), kFormat,
kResolution, gfx::Rect(kResolution)),
gfx::Rect(kResolution), gfx::Rect(kResolution),
viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr(
@@ -390,39 +402,6 @@ class FrameSinkVideoCaptureDeviceTest : public testing::Test {
std::unique_ptr<FrameSinkVideoCaptureDevice> device_;
};
-// Tests a racy start condition: Ensure that nothing bad happens if
-// StopAndDeAllocate() is called before the capturer creation completes.
-TEST_F(FrameSinkVideoCaptureDeviceTest,
- AllocatesAndDeallocatesBeforeCapturerCreated) {
- auto receiver = std::make_unique<MockVideoFrameReceiver>();
- EXPECT_CALL(*receiver, OnStarted()).Times(0);
- EXPECT_CALL(*receiver, OnError()).Times(0);
-
- EXPECT_CALL(capturer_, SetFormat(_, _)).Times(0);
- EXPECT_CALL(capturer_, SetMinCapturePeriod(_)).Times(0);
- EXPECT_CALL(capturer_, SetResolutionConstraints(_, _, _)).Times(0);
- EXPECT_CALL(capturer_, ChangeTarget(_)).Times(0);
- EXPECT_CALL(capturer_, MockStart(_)).Times(0);
-
- EXPECT_FALSE(capturer_.is_bound());
- POST_DEVICE_METHOD_CALL(AllocateAndStartWithReceiver, GetCaptureParams(),
- std::move(receiver));
- // A task is pending on the UI thread to create the capturer. Call
- // StopAndDeAllocate() before that task runs.
- POST_DEVICE_METHOD_CALL0(StopAndDeAllocate);
- WAIT_FOR_DEVICE_TASKS();
-
- // Now, run the task on the UI thread, which will post the reply back to the
- // device thread.
- RUN_UI_TASKS();
- EXPECT_TRUE(capturer_.is_bound());
-
- // Now, when the reply task on the device thread is run, the
- // FrameSinkVideoCaptureDevice should realize that StopAndDeAllocate() was
- // called in the meantime and abort.
- WAIT_FOR_DEVICE_TASKS();
-}
-
// Tests a normal session, progressing through the start, frame capture, and
// stop phases.
TEST_F(FrameSinkVideoCaptureDeviceTest, CapturesAndDeliversFrames) {
@@ -452,7 +431,7 @@ TEST_F(FrameSinkVideoCaptureDeviceTest, CapturesAndDeliversFrames) {
const int first_frame_number = next_frame_number;
for (int i = 0; i < in_flight_count; ++i) {
Expectation new_buffer_called =
- EXPECT_CALL(*receiver, MockOnNewBufferHandle(Ge(0), NotNull()))
+ EXPECT_CALL(*receiver, MockOnNewBuffer(Ge(0), NotNull()))
.WillOnce(SaveArg<0>(&buffer_ids[i]));
EXPECT_CALL(*receiver,
MockOnFrameReadyInBuffer(Eq(ByRef(buffer_ids[i])), Ge(0),
@@ -478,7 +457,6 @@ TEST_F(FrameSinkVideoCaptureDeviceTest, CapturesAndDeliversFrames) {
ASSERT_TRUE(info);
EXPECT_EQ(kMinCapturePeriod * frame_number, info->timestamp);
EXPECT_EQ(kFormat, info->pixel_format);
- EXPECT_EQ(kStorage, info->storage_type);
EXPECT_EQ(kResolution, info->coded_size);
EXPECT_EQ(gfx::Rect(kResolution), info->visible_rect);
}
diff --git a/chromium/content/browser/media/capture/frame_test_util.cc b/chromium/content/browser/media/capture/frame_test_util.cc
new file mode 100644
index 00000000000..7f4e218fa24
--- /dev/null
+++ b/chromium/content/browser/media/capture/frame_test_util.cc
@@ -0,0 +1,93 @@
+// 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/media/capture/frame_test_util.h"
+
+#include <stdint.h>
+
+#include <cmath>
+
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/transform.h"
+
+namespace content {
+
+// static
+FrameTestUtil::RGB FrameTestUtil::ComputeAverageColor(
+ SkBitmap frame,
+ const gfx::Rect& raw_include_rect,
+ const gfx::Rect& raw_exclude_rect) {
+ // Clip the rects to the valid region within |frame|. Also, only the subregion
+ // of |exclude_rect| within |include_rect| is relevant.
+ gfx::Rect include_rect = raw_include_rect;
+ include_rect.Intersect(gfx::Rect(0, 0, frame.width(), frame.height()));
+ gfx::Rect exclude_rect = raw_exclude_rect;
+ exclude_rect.Intersect(include_rect);
+
+ // Sum up the color values in each color channel for all pixels in
+ // |include_rect| not contained by |exclude_rect|.
+ int64_t include_sums[3] = {0};
+ for (int y = include_rect.y(), bottom = include_rect.bottom(); y < bottom;
+ ++y) {
+ for (int x = include_rect.x(), right = include_rect.right(); x < right;
+ ++x) {
+ const SkColor color = frame.getColor(x, y);
+ if (exclude_rect.Contains(x, y)) {
+ continue;
+ }
+ include_sums[0] += SkColorGetR(color);
+ include_sums[1] += SkColorGetG(color);
+ include_sums[2] += SkColorGetB(color);
+ }
+ }
+
+ // Divide the sums by the area to compute the average color.
+ const int include_area =
+ include_rect.size().GetArea() - exclude_rect.size().GetArea();
+ if (include_area <= 0) {
+ return RGB{NAN, NAN, NAN};
+ } else {
+ const auto include_area_f = static_cast<double>(include_area);
+ return RGB{include_sums[0] / include_area_f,
+ include_sums[1] / include_area_f,
+ include_sums[2] / include_area_f};
+ }
+}
+
+// static
+bool FrameTestUtil::IsApproximatelySameColor(SkColor color,
+ const RGB& rgb,
+ int max_diff) {
+ const double r_diff = std::abs(SkColorGetR(color) - rgb.r);
+ const double g_diff = std::abs(SkColorGetG(color) - rgb.g);
+ const double b_diff = std::abs(SkColorGetB(color) - rgb.b);
+ return r_diff < max_diff && g_diff < max_diff && b_diff < max_diff;
+}
+
+// static
+gfx::RectF FrameTestUtil::TransformSimilarly(const gfx::Rect& original,
+ const gfx::RectF& transformed,
+ const gfx::Rect& rect) {
+ if (original.IsEmpty()) {
+ return gfx::RectF(transformed.x() - original.x(),
+ transformed.y() - original.y(), 0.0f, 0.0f);
+ }
+ // The following is the scale-then-translate 2D matrix.
+ const gfx::Transform transform(transformed.width() / original.width(), 0.0f,
+ 0.0f, transformed.height() / original.height(),
+ transformed.x() - original.x(),
+ transformed.y() - original.y());
+ gfx::RectF result(rect);
+ transform.TransformRect(&result);
+ return result;
+}
+
+std::ostream& operator<<(std::ostream& out, const FrameTestUtil::RGB& rgb) {
+ return (out << "{r=" << rgb.r << ",g=" << rgb.g << ",b=" << rgb.b << '}');
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/frame_test_util.h b/chromium/content/browser/media/capture/frame_test_util.h
new file mode 100644
index 00000000000..c3667e59b48
--- /dev/null
+++ b/chromium/content/browser/media/capture/frame_test_util.h
@@ -0,0 +1,64 @@
+// 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_MEDIA_CAPTURE_FRAME_TEST_UTIL_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_FRAME_TEST_UTIL_H_
+
+#include <ostream>
+
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace gfx {
+class Rect;
+class RectF;
+} // namespace gfx
+
+namespace content {
+
+class FrameTestUtil {
+ public:
+ struct RGB {
+ double r;
+ double g;
+ double b;
+ };
+
+ // Returns the average RGB color in |include_rect| except for pixels also in
+ // |exclude_rect|.
+ static RGB ComputeAverageColor(SkBitmap frame,
+ const gfx::Rect& include_rect,
+ const gfx::Rect& exclude_rect);
+
+ // Returns true if the red, green, and blue components are all within
+ // |max_diff| of each other.
+ static bool IsApproximatelySameColor(SkColor color,
+ const RGB& rgb,
+ int max_diff = kMaxColorDifference);
+
+ // Determines how |original| has been scaled and translated to become
+ // |transformed|, and then applies the same transform on |rect| and returns
+ // the result.
+ static gfx::RectF TransformSimilarly(const gfx::Rect& original,
+ const gfx::RectF& transformed,
+ const gfx::Rect& rect);
+
+ // The default maximum color value difference, assuming there will be a little
+ // error due to pixel boundaries being rounded after coordinate system
+ // transforms.
+ static constexpr int kMaxColorDifference = 16;
+
+ // A much more-relaxed maximum color value difference, assuming errors caused
+ // by indifference towards color space concerns (and also "studio" versus
+ // "jpeg" YUV ranges).
+ // TODO(crbug/810131): Once color space issues are fixed, remove this.
+ static constexpr int kMaxInaccurateColorDifference = 48;
+};
+
+// A convenience for logging and gtest expectations output.
+std::ostream& operator<<(std::ostream& out, const FrameTestUtil::RGB& rgb);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_FRAME_TEST_UTIL_H_
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
new file mode 100644
index 00000000000..95e5e769f1a
--- /dev/null
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.cc
@@ -0,0 +1,373 @@
+// 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/media/capture/lame_window_capturer_chromeos.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "components/viz/common/frame_sinks/copy_output_request.h"
+#include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "media/base/limits.h"
+#include "media/base/video_util.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "ui/gfx/geometry/rect.h"
+
+using media::VideoFrame;
+using media::VideoFrameMetadata;
+
+namespace content {
+
+namespace {
+// Returns |raw_size| with width and height truncated to even-numbered values.
+gfx::Size AdjustSizeForI420Format(const gfx::Size& raw_size) {
+ return gfx::Size(raw_size.width() & ~1, raw_size.height() & ~1);
+}
+} // namespace
+
+// static
+constexpr base::TimeDelta LameWindowCapturerChromeOS::kAbsoluteMinCapturePeriod;
+
+LameWindowCapturerChromeOS::LameWindowCapturerChromeOS(aura::Window* target)
+ : target_(target),
+ copy_request_source_(base::UnguessableToken::Create()),
+ weak_factory_(this) {
+ if (target_) {
+ target_->AddObserver(this);
+ }
+}
+
+LameWindowCapturerChromeOS::~LameWindowCapturerChromeOS() {
+ if (target_) {
+ target_->RemoveObserver(this);
+ }
+}
+
+void LameWindowCapturerChromeOS::SetFormat(media::VideoPixelFormat format,
+ media::ColorSpace color_space) {
+ if (format != media::PIXEL_FORMAT_I420) {
+ LOG(DFATAL) << "Invalid pixel format: Only I420 is supported.";
+ }
+
+ if (color_space != media::COLOR_SPACE_UNSPECIFIED &&
+ color_space != media::COLOR_SPACE_HD_REC709) {
+ LOG(DFATAL) << "Unsupported color space: Only BT.709 is supported.";
+ }
+}
+
+void LameWindowCapturerChromeOS::SetMinCapturePeriod(
+ base::TimeDelta min_capture_period) {
+ capture_period_ = std::max(min_capture_period, kAbsoluteMinCapturePeriod);
+
+ // If the capture period is being changed while the timer is already running,
+ // re-start with the new capture period.
+ if (timer_.IsRunning()) {
+ timer_.Start(FROM_HERE, capture_period_, this,
+ &LameWindowCapturerChromeOS::CaptureNextFrame);
+ }
+}
+
+void LameWindowCapturerChromeOS::SetMinSizeChangePeriod(
+ base::TimeDelta min_period) {}
+
+void LameWindowCapturerChromeOS::SetResolutionConstraints(
+ const gfx::Size& min_size,
+ const gfx::Size& max_size,
+ bool use_fixed_aspect_ratio) {
+ if (max_size.width() <= 1 || max_size.height() <= 1 ||
+ max_size.width() > media::limits::kMaxDimension ||
+ max_size.height() > media::limits::kMaxDimension) {
+ LOG(DFATAL) << "Invalid max_size (" << max_size.ToString()
+ << "): It must be within media::limits.";
+ return;
+ }
+
+ // Set the capture size to the max size, adjusted for the I420 format.
+ capture_size_ = AdjustSizeForI420Format(max_size);
+ DCHECK(!capture_size_.IsEmpty());
+
+ // Cancel any in-flight captures that would be using the old size and clear
+ // the buffer pool.
+ weak_factory_.InvalidateWeakPtrs();
+ buffer_pool_.clear();
+ in_flight_count_ = 0;
+}
+
+void LameWindowCapturerChromeOS::SetAutoThrottlingEnabled(bool enabled) {
+ NOTIMPLEMENTED();
+}
+
+void LameWindowCapturerChromeOS::ChangeTarget(
+ const viz::FrameSinkId& frame_sink_id) {
+ // The LameWindowCapturerChromeOS does not capture from compositor frame
+ // sinks.
+}
+
+void LameWindowCapturerChromeOS::Start(
+ viz::mojom::FrameSinkVideoConsumerPtr consumer) {
+ DCHECK(consumer);
+
+ Stop();
+
+ consumer_ = std::move(consumer);
+ // In the future, if the connection to the consumer is lost before a call to
+ // Stop(), make that call on its behalf.
+ consumer_.set_connection_error_handler(base::BindOnce(
+ &LameWindowCapturerChromeOS::Stop, base::Unretained(this)));
+
+ timer_.Start(FROM_HERE, capture_period_, this,
+ &LameWindowCapturerChromeOS::CaptureNextFrame);
+}
+
+void LameWindowCapturerChromeOS::Stop() {
+ // Stop the timer, cancel any in-flight frames, and clear the buffer pool.
+ timer_.Stop();
+ weak_factory_.InvalidateWeakPtrs();
+ buffer_pool_.clear();
+ in_flight_count_ = 0;
+
+ if (consumer_) {
+ consumer_->OnStopped();
+ consumer_.reset();
+ }
+}
+
+void LameWindowCapturerChromeOS::RequestRefreshFrame() {
+ // This is ignored because the LameWindowCapturerChromeOS captures frames
+ // continuously.
+}
+
+class LameWindowCapturerChromeOS::InFlightFrame
+ : public viz::mojom::FrameSinkVideoConsumerFrameCallbacks {
+ public:
+ InFlightFrame(base::WeakPtr<LameWindowCapturerChromeOS> capturer,
+ BufferAndSize buffer)
+ : capturer_(std::move(capturer)), buffer_(std::move(buffer)) {}
+
+ ~InFlightFrame() final { Done(); }
+
+ mojo::ScopedSharedBufferHandle CloneBufferHandle() {
+ return buffer_.first->Clone(
+ mojo::SharedBufferHandle::AccessMode::READ_WRITE);
+ }
+
+ size_t buffer_size() const { return buffer_.second; }
+
+ VideoFrame* video_frame() const { return video_frame_.get(); }
+ void set_video_frame(scoped_refptr<VideoFrame> frame) {
+ video_frame_ = std::move(frame);
+ }
+
+ const gfx::Rect& content_rect() const { return content_rect_; }
+ void set_content_rect(const gfx::Rect& rect) { content_rect_ = rect; }
+
+ void Done() final {
+ if (auto* capturer = capturer_.get()) {
+ DCHECK_GT(capturer->in_flight_count_, 0);
+ --capturer->in_flight_count_;
+ // If the capture size hasn't changed, return the buffer to the pool.
+ if (buffer_.second ==
+ VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420,
+ capturer->capture_size_)) {
+ capturer->buffer_pool_.emplace_back(std::move(buffer_));
+ }
+ capturer_ = nullptr;
+ }
+
+ buffer_.first.reset();
+ buffer_.second = 0;
+ }
+
+ void ProvideFeedback(double utilization) final {}
+
+ private:
+ base::WeakPtr<LameWindowCapturerChromeOS> capturer_;
+ BufferAndSize buffer_;
+ scoped_refptr<VideoFrame> video_frame_;
+ gfx::Rect content_rect_;
+
+ DISALLOW_COPY_AND_ASSIGN(InFlightFrame);
+};
+
+void LameWindowCapturerChromeOS::CaptureNextFrame() {
+ // If the maximum frame in-flight count has been reached, skip this frame.
+ if (in_flight_count_ >= kMaxFramesInFlight) {
+ return;
+ }
+
+ // Attempt to re-use a buffer from the pool. Otherwise, create a new one.
+ const size_t allocation_size =
+ VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, capture_size_);
+ BufferAndSize buffer;
+ if (buffer_pool_.empty()) {
+ buffer.first = mojo::SharedBufferHandle::Create(allocation_size);
+ if (!buffer.first.is_valid()) {
+ // If creating the shared memory failed, abort the frame, and hope this
+ // is a transient problem.
+ return;
+ }
+ buffer.second = allocation_size;
+ } else {
+ buffer = std::move(buffer_pool_.back());
+ buffer_pool_.pop_back();
+ DCHECK(buffer.first.is_valid());
+ DCHECK_EQ(buffer.second, allocation_size);
+ }
+
+ // Map the shared memory buffer, to populate its data.
+ mojo::ScopedSharedBufferMapping mapping = buffer.first->Map(buffer.second);
+ if (!mapping) {
+ // If the shared memory mapping failed, just abort this frame, hoping the
+ // issue is a transient one (e.g., lack of an available region in address
+ // space).
+ return;
+ }
+
+ // At this point, frame capture will proceed. Create an InFlightFrame to track
+ // population and consumption of the frame, and to eventually return the
+ // buffer to the pool and decrement |in_flight_count_|.
+ ++in_flight_count_;
+ auto in_flight_frame = std::make_unique<InFlightFrame>(
+ weak_factory_.GetWeakPtr(), std::move(buffer));
+
+ // Create a VideoFrame that wraps the mapped buffer.
+ const base::TimeTicks begin_time = base::TimeTicks::Now();
+ if (first_frame_reference_time_.is_null()) {
+ first_frame_reference_time_ = begin_time;
+ }
+ in_flight_frame->set_video_frame(VideoFrame::WrapExternalData(
+ media::PIXEL_FORMAT_I420, capture_size_, gfx::Rect(capture_size_),
+ capture_size_, static_cast<uint8_t*>(mapping.get()), allocation_size,
+ begin_time - first_frame_reference_time_));
+ auto* const frame = in_flight_frame->video_frame();
+ DCHECK(frame);
+ frame->AddDestructionObserver(
+ base::BindOnce(base::DoNothing::Once<mojo::ScopedSharedBufferMapping>(),
+ std::move(mapping)));
+ VideoFrameMetadata* const metadata = frame->metadata();
+ metadata->SetTimeTicks(VideoFrameMetadata::CAPTURE_BEGIN_TIME, begin_time);
+ metadata->SetInteger(VideoFrameMetadata::COLOR_SPACE,
+ media::COLOR_SPACE_HD_REC709);
+ metadata->SetTimeDelta(VideoFrameMetadata::FRAME_DURATION, capture_period_);
+ metadata->SetDouble(VideoFrameMetadata::FRAME_RATE,
+ 1.0 / capture_period_.InSecondsF());
+ metadata->SetTimeTicks(VideoFrameMetadata::REFERENCE_TIME, begin_time);
+
+ // Compute the region of the VideoFrame that will contain the content. If
+ // there is nothing to copy from/to (e.g., the target is gone, or is sized too
+ // small), send a blank black frame immediately.
+ const gfx::Size source_size =
+ target_ ? target_->bounds().size() : gfx::Size();
+ const gfx::Rect content_rect = source_size.IsEmpty()
+ ? gfx::Rect()
+ : media::ComputeLetterboxRegionForI420(
+ frame->visible_rect(), source_size);
+ in_flight_frame->set_content_rect(content_rect);
+ if (content_rect.IsEmpty()) {
+ media::LetterboxVideoFrame(frame, gfx::Rect());
+ DeliverFrame(std::move(in_flight_frame));
+ return;
+ }
+ DCHECK(target_);
+
+ // Request a copy of the Layer associated with the |target_| aura::Window.
+ auto request = std::make_unique<viz::CopyOutputRequest>(
+ // Note: As of this writing, I420_PLANES is not supported external to VIZ.
+ viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ base::BindOnce(&LameWindowCapturerChromeOS::DidCopyFrame,
+ weak_factory_.GetWeakPtr(), std::move(in_flight_frame)));
+ request->set_source(copy_request_source_);
+ request->set_area(gfx::Rect(source_size));
+ request->SetScaleRatio(
+ gfx::Vector2d(source_size.width(), source_size.height()),
+ gfx::Vector2d(content_rect.width(), content_rect.height()));
+ request->set_result_selection(gfx::Rect(content_rect.size()));
+ target_->layer()->RequestCopyOfOutput(std::move(request));
+}
+
+void LameWindowCapturerChromeOS::DidCopyFrame(
+ std::unique_ptr<InFlightFrame> in_flight_frame,
+ std::unique_ptr<viz::CopyOutputResult> result) {
+ // Populate the VideoFrame from the CopyOutputResult.
+ auto* const frame = in_flight_frame->video_frame();
+ DCHECK(frame);
+ const auto& content_rect = in_flight_frame->content_rect();
+ const int y_stride = frame->stride(VideoFrame::kYPlane);
+ uint8_t* const y = frame->visible_data(VideoFrame::kYPlane) +
+ content_rect.y() * y_stride + content_rect.x();
+ const int u_stride = frame->stride(VideoFrame::kUPlane);
+ uint8_t* const u = frame->visible_data(VideoFrame::kUPlane) +
+ (content_rect.y() / 2) * u_stride + (content_rect.x() / 2);
+ const int v_stride = frame->stride(VideoFrame::kVPlane);
+ uint8_t* const v = frame->visible_data(VideoFrame::kVPlane) +
+ (content_rect.y() / 2) * v_stride + (content_rect.x() / 2);
+ if (!result->ReadI420Planes(y, y_stride, u, u_stride, v, v_stride)) {
+ return; // Copy request failed, punt.
+ }
+
+ // The result may be smaller than what was requested, if unforeseen clamping
+ // to the source boundaries occurred by the executor of the copy request.
+ // However, the result should never contain more than what was requested.
+ DCHECK_LE(result->size().width(), content_rect.width());
+ DCHECK_LE(result->size().height(), content_rect.height());
+ media::LetterboxVideoFrame(
+ frame, gfx::Rect(content_rect.origin(),
+ AdjustSizeForI420Format(result->size())));
+
+ DeliverFrame(std::move(in_flight_frame));
+}
+
+void LameWindowCapturerChromeOS::DeliverFrame(
+ std::unique_ptr<InFlightFrame> in_flight_frame) {
+ auto* const frame = in_flight_frame->video_frame();
+ DCHECK(frame);
+ frame->metadata()->SetTimeTicks(VideoFrameMetadata::CAPTURE_END_TIME,
+ base::TimeTicks::Now());
+
+ // Clone the buffer handle for the consumer.
+ mojo::ScopedSharedBufferHandle buffer_for_consumer =
+ in_flight_frame->CloneBufferHandle();
+ if (!buffer_for_consumer.is_valid()) {
+ return; // This should only fail if the OS is exhausted of handles.
+ }
+ const size_t buffer_allocation_size = in_flight_frame->buffer_size();
+
+ // Assemble frame layout, format, and metadata into a mojo struct to send to
+ // the consumer.
+ media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New();
+ info->timestamp = frame->timestamp();
+ info->metadata = frame->metadata()->GetInternalValues().Clone();
+ info->pixel_format = frame->format();
+ info->coded_size = frame->coded_size();
+ info->visible_rect = frame->visible_rect();
+ const gfx::Rect update_rect = frame->visible_rect();
+ const gfx::Rect content_rect = in_flight_frame->content_rect();
+
+ // Drop the VideoFrame wrapper, which will unmap the shared memory from this
+ // process.
+ in_flight_frame->set_video_frame(nullptr);
+
+ // Create a mojo message pipe and bind to the InFlightFrame to wait for the
+ // Done() signal from the consumer. The mojo::StrongBinding takes ownership of
+ // the InFlightFrame.
+ viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks;
+ mojo::MakeStrongBinding(std::move(in_flight_frame),
+ mojo::MakeRequest(&callbacks));
+
+ // Send the frame to the consumer.
+ consumer_->OnFrameCaptured(std::move(buffer_for_consumer),
+ buffer_allocation_size, std::move(info),
+ update_rect, content_rect, std::move(callbacks));
+}
+
+void LameWindowCapturerChromeOS::OnWindowDestroying(aura::Window* window) {
+ if (window == target_) {
+ target_->RemoveObserver(this);
+ target_ = nullptr;
+ // The capturer may continue running, but it will notice the target is gone
+ // and produce blank black frames hereafter.
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
new file mode 100644
index 00000000000..6978f755f07
--- /dev/null
+++ b/chromium/content/browser/media/capture/lame_window_capturer_chromeos.h
@@ -0,0 +1,139 @@
+// 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_MEDIA_CAPTURE_LAME_WINDOW_CAPTURER_CHROMEOS_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_LAME_WINDOW_CAPTURER_CHROMEOS_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "base/unguessable_token.h"
+#include "media/base/video_frame.h"
+#include "mojo/public/cpp/system/buffer.h"
+#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace viz {
+class CopyOutputResult;
+}
+
+namespace content {
+
+// A minimal FrameSinkVideoCapturer implementation for aura::Window video
+// capture on ChromeOS (i.e., not desktop capture, and not WebContents capture),
+// in cases where a Window does not host a compositor frame sink. This is far
+// less efficient than, and far under-performs, the normal
+// FrameSinkVideoCapturer provided by the VIZ service, as it lacks multiple
+// design features that would be required for low CPU use and high
+// pixels-per-sec throughput. It is a placeholder, until the necessary
+// infrastructure exists to provide VIZ FrameSinkVideoCapturer the compositor
+// frame sink it needs for aura::Windows in the middle of the window tree
+// hierarchy.
+//
+// As this is not meant to be a full-fledged, long-term implementation, it only
+// supports the production of I420-format video (Rec. 709 color space) at a
+// maximum rate of 5 FPS, and only a maximum of 3 frames can be in-flight at any
+// one time. In addition, since source content changes cannot be detected, this
+// capturer indefinitely produces frames at a constant framerate while it is
+// running.
+//
+// TODO(crbug/806366): The goal is to remove this code by 2019.
+class LameWindowCapturerChromeOS : public viz::mojom::FrameSinkVideoCapturer,
+ public aura::WindowObserver {
+ public:
+ explicit LameWindowCapturerChromeOS(aura::Window* target);
+ ~LameWindowCapturerChromeOS() final;
+
+ // viz::mojom::FrameSinkVideoCapturer implementation.
+ void SetFormat(media::VideoPixelFormat format,
+ media::ColorSpace color_space) final;
+ void SetMinCapturePeriod(base::TimeDelta min_capture_period) final;
+ void SetMinSizeChangePeriod(base::TimeDelta min_period) final;
+ void SetResolutionConstraints(const gfx::Size& min_size,
+ const gfx::Size& max_size,
+ bool use_fixed_aspect_ratio) final;
+ void SetAutoThrottlingEnabled(bool enabled) final;
+ void ChangeTarget(const viz::FrameSinkId& frame_sink_id) final;
+ void Start(viz::mojom::FrameSinkVideoConsumerPtr consumer) final;
+ void Stop() final;
+ void RequestRefreshFrame() final;
+
+ private:
+ // Represents an in-flight frame, being populated by this capturer and then
+ // delivered to the consumer. When the consumer is done with the frame, this
+ // returns the buffer back to the pool.
+ class InFlightFrame;
+
+ // Initiates capture of the next frame. This is called periodically by the
+ // |timer_|.
+ void CaptureNextFrame();
+
+ // Populates the frame from the CopyOutputResult and then calls DeliverFrame.
+ void DidCopyFrame(std::unique_ptr<InFlightFrame> in_flight_frame,
+ std::unique_ptr<viz::CopyOutputResult> result);
+
+ // Delivers the frame to the consumer, and sets up the notification path for
+ // when the consumer is done with the frame.
+ void DeliverFrame(std::unique_ptr<InFlightFrame> in_flight_frame);
+
+ // aura::WindowObserver override.
+ void OnWindowDestroying(aura::Window* window) final;
+
+ // The window being captured. If the window is destroyed, this is set to null
+ // and only blank black frames will be produced thereafter.
+ aura::Window* target_;
+
+ // Capture parameters. The defaults are according to the mojo interface
+ // definition comments for viz::mojom::FrameSinkVideoCapturer.
+ base::TimeDelta capture_period_ = kAbsoluteMinCapturePeriod;
+ gfx::Size capture_size_ = gfx::Size(640, 360);
+
+ // The current consumer. This is set by Start() and cleared by Stop().
+ viz::mojom::FrameSinkVideoConsumerPtr consumer_;
+
+ // A timer that calls CaptureNextFrame() periodically, according to the
+ // currently-set |capture_period_|. This timer is only running while a
+ // consumer is present.
+ base::RepeatingTimer timer_;
+
+ // A pool of shared memory buffers for re-use.
+ using BufferAndSize = std::pair<mojo::ScopedSharedBufferHandle, size_t>;
+ std::vector<BufferAndSize> buffer_pool_;
+
+ // The current number of frames in-flight. If incrementing this would be
+ // exceed kMaxInFlightFrames, frame capture is not attempted.
+ int in_flight_count_ = 0;
+
+ // Tick clock time of the first frame since Start() was called. This is used
+ // for generating "media offset" VideoFrame timestamps.
+ base::TimeTicks first_frame_reference_time_;
+
+ // A value provided in the copy requests to enable VIZ to optimize around
+ // video capture.
+ const base::UnguessableToken copy_request_source_;
+
+ // Used for cancelling any outstanding activities' results, once Stop() is
+ // called and there is no longer a consumer to receive another frame.
+ base::WeakPtrFactory<LameWindowCapturerChromeOS> weak_factory_;
+
+ // Enforce a very low maximum frame rate (5 FPS), due to the lack of
+ // design optimizations. See top-level class comments.
+ static constexpr base::TimeDelta kAbsoluteMinCapturePeriod =
+ base::TimeDelta::FromMilliseconds(200);
+
+ // The maximum number of frames in-flight at any one time.
+ static constexpr int kMaxFramesInFlight = 3;
+
+ DISALLOW_COPY_AND_ASSIGN(LameWindowCapturerChromeOS);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_LAME_WINDOW_CAPTURER_CHROMEOS_H_
diff --git a/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc b/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
index 994bfae8014..dda49dcb222 100644
--- a/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
+++ b/chromium/content/browser/media/capture/screen_capture_device_android_unittest.cc
@@ -25,6 +25,13 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
base::TimeTicks reference_time,
base::TimeDelta tiemstamp,
int frame_feedback_id));
+ MOCK_METHOD6(OnIncomingCapturedGfxBuffer,
+ void(gfx::GpuMemoryBuffer* buffer,
+ const media::VideoCaptureFormat& frame_format,
+ int clockwise_rotation,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
+ int frame_feedback_id));
MOCK_METHOD0(DoReserveOutputBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
@@ -38,10 +45,8 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
// Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
media::VideoPixelFormat format,
- media::VideoPixelStorage storage,
int frame_feedback_id) override {
EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
- EXPECT_EQ(media::VideoPixelStorage::CPU, storage);
DoReserveOutputBuffer();
return Buffer();
}
@@ -62,10 +67,8 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
}
Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
media::VideoPixelFormat format,
- media::VideoPixelStorage storage,
int frame_feedback_id) override {
EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
- EXPECT_EQ(media::VideoPixelStorage::CPU, storage);
DoResurrectLastOutputBuffer();
return Buffer();
}
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
index 15957b6d3ec..15115a22b8b 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
@@ -441,4 +441,9 @@ bool WebContentsAudioInputStream::IsMuted() {
return false;
}
+void WebContentsAudioInputStream::SetOutputDeviceForAec(
+ const std::string& output_device_id) {
+ // Not supported. Do nothing.
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream.h b/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
index a7047aff624..427615b9826 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
@@ -48,6 +48,7 @@ class CONTENT_EXPORT WebContentsAudioInputStream
bool SetAutomaticGainControl(bool enabled) override;
bool GetAutomaticGainControl() override;
bool IsMuted() override;
+ void SetOutputDeviceForAec(const std::string& output_device_id) override;
// Create a new audio mirroring session, or return NULL on error. |device_id|
// should be in the format accepted by
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
index 7c1911b90a2..e0d3842142b 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
@@ -55,9 +55,8 @@ const int kAnotherRenderFrameId = 1;
const AudioParameters& TestAudioParameters() {
static const AudioParameters params(
- AudioParameters::AUDIO_FAKE,
- media::CHANNEL_LAYOUT_STEREO,
- AudioParameters::kAudioCDSampleRate, 16,
+ AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
+ AudioParameters::kAudioCDSampleRate,
AudioParameters::kAudioCDSampleRate / 100);
return params;
}
@@ -65,7 +64,7 @@ const AudioParameters& TestAudioParameters() {
class MockAudioMirroringManager : public AudioMirroringManager {
public:
MockAudioMirroringManager() : AudioMirroringManager() {}
- virtual ~MockAudioMirroringManager() {}
+ ~MockAudioMirroringManager() override {}
MOCK_METHOD1(StartMirroring, void(MirroringDestination* destination));
MOCK_METHOD1(StopMirroring, void(MirroringDestination* destination));
@@ -84,7 +83,7 @@ class MockWebContentsTracker : public WebContentsTracker {
MOCK_METHOD0(Stop, void());
private:
- virtual ~MockWebContentsTracker() {}
+ ~MockWebContentsTracker() override {}
DISALLOW_COPY_AND_ASSIGN(MockWebContentsTracker);
};
@@ -131,9 +130,7 @@ class MockVirtualAudioInputStream : public VirtualAudioInputStream {
Invoke(&real_, &VirtualAudioInputStream::RemoveInputProvider));
}
- ~MockVirtualAudioInputStream() {
- DCHECK(real_stream_is_closed_);
- }
+ ~MockVirtualAudioInputStream() override { DCHECK(real_stream_is_closed_); }
MOCK_METHOD0(Open, bool());
MOCK_METHOD1(Start, void(AudioInputStream::AudioInputCallback*));
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
index 5a6951ca012..643c570b0a0 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device_browsertest.cc
@@ -4,300 +4,43 @@
#include "content/browser/media/capture/web_contents_video_capture_device.h"
-#include <stdint.h>
-
-#include <array>
-#include <cmath>
-#include <string>
#include <tuple>
-#include "base/containers/circular_deque.h"
-#include "base/containers/flat_map.h"
+#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "cc/test/pixel_test_utils.h"
+#include "content/browser/media/capture/content_capture_device_browsertest_base.h"
+#include "content/browser/media/capture/fake_video_capture_stack.h"
+#include "content/browser/media/capture/frame_test_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
-#include "media/base/video_frame.h"
#include "media/base/video_util.h"
-#include "media/capture/video/video_frame_receiver.h"
-#include "media/capture/video_capture_types.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/embedded_test_server/http_response.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "url/gurl.h"
-
-using net::test_server::BasicHttpResponse;
-using net::test_server::HttpRequest;
-using net::test_server::HttpResponse;
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
namespace content {
namespace {
-// Provides a fake representation of the entire video capture stack. It creates
-// a VideoFrameReceiver that the device can deliver VideoFrames to, and adapts
-// that to a simple callback structure that allows the browser tests to examine
-// each video frame that was captured.
-class FakeVideoCaptureStack {
- public:
- using FrameCallback =
- base::RepeatingCallback<void(scoped_refptr<media::VideoFrame> frame)>;
- void SetFrameCallback(FrameCallback callback) {
- frame_callback_ = std::move(callback);
- }
-
- std::unique_ptr<media::VideoFrameReceiver> CreateFrameReceiver() {
- return std::make_unique<FakeVideoFrameReceiver>(this);
- }
-
- bool started() const { return started_; }
- bool error_occurred() const { return error_occurred_; }
-
- void ExpectHasLogMessages() {
- EXPECT_FALSE(log_messages_.empty());
- while (!log_messages_.empty()) {
- VLOG(1) << "Next log message: " << log_messages_.front();
- log_messages_.pop_front();
- }
- }
-
- void ExpectNoLogMessages() {
- while (!log_messages_.empty()) {
- ADD_FAILURE() << "Unexpected log message: " << log_messages_.front();
- log_messages_.pop_front();
- }
- }
-
- private:
- // A minimal implementation of VideoFrameReceiver that wraps buffers into
- // VideoFrame instances and forwards all relevant callbacks and data to the
- // parent FakeVideoCaptureStack.
- class FakeVideoFrameReceiver : public media::VideoFrameReceiver {
- public:
- explicit FakeVideoFrameReceiver(FakeVideoCaptureStack* capture_stack)
- : capture_stack_(capture_stack) {}
-
- private:
- using Buffer = media::VideoCaptureDevice::Client::Buffer;
-
- void OnNewBufferHandle(
- int buffer_id,
- std::unique_ptr<Buffer::HandleProvider> handle_provider) final {
- buffers_[buffer_id] =
- handle_provider->GetHandleForInterProcessTransit(true);
- }
-
- void OnFrameReadyInBuffer(
- int buffer_id,
- int frame_feedback_id,
- std::unique_ptr<Buffer::ScopedAccessPermission> access,
- media::mojom::VideoFrameInfoPtr frame_info) final {
- const auto it = buffers_.find(buffer_id);
- CHECK(it != buffers_.end());
- mojo::ScopedSharedBufferHandle& buffer = it->second;
-
- const size_t mapped_size =
- media::VideoCaptureFormat(frame_info->coded_size, 0.0f,
- frame_info->pixel_format,
- frame_info->storage_type)
- .ImageAllocationSize();
- mojo::ScopedSharedBufferMapping mapping = buffer->Map(mapped_size);
- CHECK(mapping.get());
-
- auto frame = media::VideoFrame::WrapExternalData(
- frame_info->pixel_format, frame_info->coded_size,
- frame_info->visible_rect, frame_info->visible_rect.size(),
- reinterpret_cast<uint8_t*>(mapping.get()), mapped_size,
- frame_info->timestamp);
- CHECK(frame);
- frame->metadata()->MergeInternalValuesFrom(frame_info->metadata);
- // This destruction observer will unmap the shared memory when the
- // VideoFrame goes out-of-scope.
- frame->AddDestructionObserver(base::BindOnce(
- [](mojo::ScopedSharedBufferMapping mapping) {}, std::move(mapping)));
- // This destruction observer will notify the WebContentsVideoCaptureDevice
- // once all downstream code is done using the VideoFrame.
- frame->AddDestructionObserver(base::BindOnce(
- [](std::unique_ptr<Buffer::ScopedAccessPermission> access) {},
- std::move(access)));
-
- capture_stack_->frame_callback_.Run(std::move(frame));
- }
-
- void OnBufferRetired(int buffer_id) final {
- const auto it = buffers_.find(buffer_id);
- CHECK(it != buffers_.end());
- buffers_.erase(it);
- }
-
- void OnError() final { capture_stack_->error_occurred_ = true; }
-
- void OnLog(const std::string& message) final {
- capture_stack_->log_messages_.push_back(message);
- }
-
- void OnStarted() final { capture_stack_->started_ = true; }
-
- void OnStartedUsingGpuDecode() final { NOTREACHED(); }
-
- FakeVideoCaptureStack* const capture_stack_;
- base::flat_map<int, mojo::ScopedSharedBufferHandle> buffers_;
- };
-
- FrameCallback frame_callback_;
- bool started_ = false;
- bool error_occurred_ = false;
- base::circular_deque<std::string> log_messages_;
-};
-
-class WebContentsVideoCaptureDeviceBrowserTest : public ContentBrowserTest {
+class WebContentsVideoCaptureDeviceBrowserTest
+ : public ContentCaptureDeviceBrowserTestBase {
public:
- FakeVideoCaptureStack* capture_stack() { return &capture_stack_; }
- WebContentsVideoCaptureDevice* device() const { return device_.get(); }
-
- // Alters the solid fill color making up the page content. This will trigger a
- // compositor update, which will trigger a frame capture.
- void ChangePageContentColor(std::string css_color_hex) {
- // See the HandleRequest() method for the original documents being modified
- // here.
- std::string script;
- if (is_cross_site_capture_test()) {
- const GURL& inner_frame_url =
- embedded_test_server()->GetURL(kInnerFrameHostname, kInnerFramePath);
- script = base::StringPrintf(
- "document.getElementsByTagName('iframe')[0].src = '%s?color=123456';",
- inner_frame_url.spec().c_str());
- } else {
- script = "document.body.style.backgroundColor = '#123456';";
- }
- script.replace(script.find("123456"), 6, css_color_hex);
- CHECK(ExecuteScript(shell()->web_contents(), script));
- }
-
- // Returns the size of the WebContents top-level frame view.
- gfx::Size GetViewSize() const {
- return shell()
- ->web_contents()
- ->GetMainFrame()
- ->GetView()
- ->GetViewBounds()
- .size();
- }
-
- // Returns capture parameters based on the current size of the source view,
- // which is based on the size of the Shell window.
- media::VideoCaptureParams SnapshotCaptureParams() const {
- constexpr gfx::Size kMaxCaptureSize = gfx::Size(320, 320);
- constexpr int kMaxFramesPerSecond = 60;
-
- gfx::Size capture_size = kMaxCaptureSize;
- if (use_fixed_aspect_ratio()) {
- // Half either the width or height, depending on the source view size. The
- // goal is to force obvious letterboxing (or pillarboxing), regardless of
- // how the source view is currently sized.
- const gfx::Size view_size = GetViewSize();
- if (view_size.width() < view_size.height()) {
- capture_size.set_height(capture_size.height() / 2);
- } else {
- capture_size.set_width(capture_size.width() / 2);
- }
- }
-
- media::VideoCaptureParams params;
- params.requested_format = media::VideoCaptureFormat(
- capture_size, kMaxFramesPerSecond, media::PIXEL_FORMAT_I420,
- media::VideoPixelStorage::CPU);
- params.resolution_change_policy =
- use_fixed_aspect_ratio()
- ? media::ResolutionChangePolicy::FIXED_ASPECT_RATIO
- : media::ResolutionChangePolicy::ANY_WITHIN_LIMIT;
- return params;
- }
-
- // Navigates to the initial document, according to the current test
- // parameters, and waits for page load completion.
- void NavigateToInitialDocument() {
- // Navigate to the single-frame test's document and record the view size.
- ASSERT_TRUE(
- NavigateToURL(shell(), embedded_test_server()->GetURL(
- kSingleFrameHostname, kSingleFramePath)));
- ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
- expected_view_size_ = GetViewSize();
- VLOG(1) << "View size is " << expected_view_size_.ToString();
-
- // If doing a cross-site capture test, navigate to the more-complex document
- // that also contains an iframe (rendered in a separate process).
- if (is_cross_site_capture_test()) {
- ASSERT_TRUE(
- NavigateToURL(shell(), embedded_test_server()->GetURL(
- kOuterFrameHostname, kOuterFramePath)));
- ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
-
- // Confirm the iframe is a cross-process child render frame.
- auto* const child_frame =
- ChildFrameAt(shell()->web_contents()->GetMainFrame(), 0);
- ASSERT_TRUE(child_frame);
- ASSERT_TRUE(child_frame->IsCrossProcessSubframe());
- }
- }
-
- // Creates and starts the device for frame capture, and checks that the
- // initial refresh frame is delivered.
- void AllocateAndStartAndWaitForFirstFrame() {
- frames_.clear();
- last_frame_timestamp_ = base::TimeDelta::Min();
- capture_stack()->SetFrameCallback(
- base::BindRepeating(&WebContentsVideoCaptureDeviceBrowserTest::OnFrame,
- base::Unretained(this)));
-
- auto* const main_frame = shell()->web_contents()->GetMainFrame();
- device_ = std::make_unique<WebContentsVideoCaptureDevice>(
- main_frame->GetProcess()->GetID(), main_frame->GetRoutingID());
- device_->AllocateAndStartWithReceiver(
- SnapshotCaptureParams(), capture_stack()->CreateFrameReceiver());
- RunAllPendingInMessageLoop(BrowserThread::UI);
- EXPECT_TRUE(capture_stack()->started());
- EXPECT_FALSE(capture_stack()->error_occurred());
- capture_stack()->ExpectNoLogMessages();
-
- min_capture_period_ = base::TimeDelta::FromMicroseconds(
- base::Time::kMicrosecondsPerSecond /
- device_->capture_params().requested_format.frame_rate);
- WaitForFrameWithColor(SK_ColorBLACK);
- }
+ WebContentsVideoCaptureDeviceBrowserTest() = default;
+ ~WebContentsVideoCaptureDeviceBrowserTest() override = default;
- // Stops and destroys the device.
- void StopAndDeAllocate() {
- device_->StopAndDeAllocate();
- RunAllPendingInMessageLoop(BrowserThread::UI);
- device_.reset();
- }
-
- void ClearCapturedFramesQueue() { frames_.clear(); }
-
- bool HasCapturedFramesInQueue() const { return !frames_.empty(); }
-
- // Runs the browser until a frame with the given |color| is found in the
- // captured frames queue, or until a testing failure has occurred.
+ // Runs the browser until a frame whose content matches the given |color| is
+ // found in the captured frames queue, or until a testing failure has
+ // occurred.
void WaitForFrameWithColor(SkColor color) {
- VLOG(1) << "Waiting for frame filled with color: red=" << SkColorGetR(color)
- << ", green=" << SkColorGetG(color)
+ VLOG(1) << "Waiting for frame content area filled with color: red="
+ << SkColorGetR(color) << ", green=" << SkColorGetG(color)
<< ", blue=" << SkColorGetB(color);
while (!testing::Test::HasFailure()) {
@@ -305,52 +48,59 @@ class WebContentsVideoCaptureDeviceBrowserTest : public ContentBrowserTest {
EXPECT_FALSE(capture_stack()->error_occurred());
capture_stack()->ExpectNoLogMessages();
- while (!frames_.empty() && !testing::Test::HasFailure()) {
+ while (capture_stack()->has_captured_frames() &&
+ !testing::Test::HasFailure()) {
// Pop the next frame from the front of the queue and convert to a RGB
// bitmap for analysis.
- SkBitmap rgb_frame = ConvertToSkBitmap(*(frames_.front()));
- frames_.pop_front();
+ const SkBitmap rgb_frame = capture_stack()->NextCapturedFrame();
EXPECT_FALSE(rgb_frame.empty());
- // Analyze the frame and compute the average color value for each of: 1)
- // the upper-left quadrant of the content region; 2) the remaining three
- // quadrants of the content region; and 3) the non-content (i.e.,
- // letterboxed) region.
+ // Three regions of the frame will be analyzed: 1) the upper-left
+ // quadrant of the content region where the iframe draws; 2) the
+ // remaining three quadrants of the content region where the main frame
+ // draws; and 3) the non-content (i.e., letterboxed) region.
const gfx::Size frame_size(rgb_frame.width(), rgb_frame.height());
- const gfx::Size current_view_size = GetViewSize();
- EXPECT_EQ(expected_view_size_, current_view_size)
- << "Sanity-check failed: View size changed sized during this test.";
- const gfx::Rect content_rect =
- use_fixed_aspect_ratio()
- ? media::ComputeLetterboxRegion(gfx::Rect(frame_size),
- current_view_size)
- : gfx::Rect(frame_size);
- std::array<double, 3> average_ul_content_rgb;
- std::array<double, 3> average_rem_content_rgb;
- std::array<double, 3> average_letterbox_rgb;
- AnalyzeFrame(rgb_frame, content_rect, &average_ul_content_rgb,
- &average_rem_content_rgb, &average_letterbox_rgb);
-
- const auto ToTriplet = [](const std::array<double, 3>& rgb) {
- return base::StringPrintf("(%f,%f,%f)", rgb[0], rgb[1], rgb[2]);
- };
- VLOG(1) << "Video frame analysis: size=" << frame_size.ToString()
- << ", expected content_rect=" << content_rect.ToString()
- << ", average upper-left content quadrant rgb="
- << ToTriplet(average_ul_content_rgb)
- << ", average remaining content rgb="
- << ToTriplet(average_rem_content_rgb)
- << ", average letterbox rgb="
- << ToTriplet(average_letterbox_rgb);
-
- // The letterboxed region should be black.
- if (use_fixed_aspect_ratio()) {
- EXPECT_NEAR(SkColorGetR(SK_ColorBLACK), average_letterbox_rgb[0],
- kMaxColorDifference);
- EXPECT_NEAR(SkColorGetG(SK_ColorBLACK), average_letterbox_rgb[1],
- kMaxColorDifference);
- EXPECT_NEAR(SkColorGetB(SK_ColorBLACK), average_letterbox_rgb[2],
- kMaxColorDifference);
+ const gfx::Size source_size = GetExpectedSourceSize();
+ const gfx::Rect iframe_rect(0, 0, source_size.width() / 2,
+ source_size.height() / 2);
+
+ // Compute the Rects representing where the three regions would be in
+ // the |rgb_frame|.
+ const gfx::RectF content_in_frame_rect_f(
+ IsFixedAspectRatioTest() ? media::ComputeLetterboxRegion(
+ gfx::Rect(frame_size), source_size)
+ : gfx::Rect(frame_size));
+ const gfx::RectF iframe_in_frame_rect_f =
+ FrameTestUtil::TransformSimilarly(
+ gfx::Rect(source_size), content_in_frame_rect_f, iframe_rect);
+ const gfx::Rect content_in_frame_rect =
+ gfx::ToEnclosingRect(content_in_frame_rect_f);
+ const gfx::Rect iframe_in_frame_rect =
+ gfx::ToEnclosingRect(iframe_in_frame_rect_f);
+
+ // Determine the average RGB color in the three regions-of-interest in
+ // the frame.
+ const auto average_iframe_rgb = FrameTestUtil::ComputeAverageColor(
+ rgb_frame, iframe_in_frame_rect, gfx::Rect());
+ const auto average_mainframe_rgb = FrameTestUtil::ComputeAverageColor(
+ rgb_frame, content_in_frame_rect, iframe_in_frame_rect);
+ const auto average_letterbox_rgb = FrameTestUtil::ComputeAverageColor(
+ rgb_frame, gfx::Rect(frame_size), content_in_frame_rect);
+
+ VLOG(1)
+ << "Video frame analysis: size=" << frame_size.ToString()
+ << ", captured upper-left quadrant of content should be at "
+ << iframe_in_frame_rect.ToString() << " and has average color "
+ << average_iframe_rgb
+ << ", captured remaining quadrants of content should be bound by "
+ << content_in_frame_rect.ToString() << " and has average color "
+ << average_mainframe_rgb << ", letterbox region has average color "
+ << average_letterbox_rgb;
+
+ // The letterboxed region should always be black.
+ if (IsFixedAspectRatioTest()) {
+ EXPECT_TRUE(FrameTestUtil::IsApproximatelySameColor(
+ SK_ColorBLACK, average_letterbox_rgb));
}
if (testing::Test::HasFailure()) {
@@ -359,14 +109,19 @@ class WebContentsVideoCaptureDeviceBrowserTest : public ContentBrowserTest {
return;
}
- if (is_cross_site_capture_test() &&
- IsApproximatelySameColor(color, average_ul_content_rgb) &&
- IsApproximatelySameColor(SK_ColorWHITE, average_rem_content_rgb)) {
+ // Return if the content region(s) now has/have the expected color(s).
+ if (IsCrossSiteCaptureTest() &&
+ FrameTestUtil::IsApproximatelySameColor(color,
+ average_iframe_rgb) &&
+ FrameTestUtil::IsApproximatelySameColor(SK_ColorWHITE,
+ average_mainframe_rgb)) {
VLOG(1) << "Observed desired frame.";
return;
- } else if (!is_cross_site_capture_test() &&
- IsApproximatelySameColor(color, average_ul_content_rgb) &&
- IsApproximatelySameColor(color, average_rem_content_rgb)) {
+ } else if (!IsCrossSiteCaptureTest() &&
+ FrameTestUtil::IsApproximatelySameColor(
+ color, average_iframe_rgb) &&
+ FrameTestUtil::IsApproximatelySameColor(
+ color, average_mainframe_rgb)) {
VLOG(1) << "Observed desired frame.";
return;
} else {
@@ -380,226 +135,34 @@ class WebContentsVideoCaptureDeviceBrowserTest : public ContentBrowserTest {
base::RunLoop run_loop;
BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
run_loop.QuitClosure(),
- min_capture_period_);
+ GetMinCapturePeriod());
run_loop.Run();
}
}
protected:
- // These are overridden for the parameterized tests.
- virtual bool use_software_compositing() const { return false; }
- virtual bool use_fixed_aspect_ratio() const { return false; }
- virtual bool is_cross_site_capture_test() const { return false; }
-
- void SetUp() override {
- // IMPORTANT: Do not add the switches::kUseGpuInTests command line flag: It
- // causes the tests to take 12+ seconds just to spin up a render process on
- // debug builds. It can also cause test failures in MSAN builds, or
- // exacerbate OOM situations on highly-loaded machines.
-
- // Screen capture requires readback from compositor output.
- EnablePixelOutput();
-
- // Conditionally force software compositing instead of GPU-accelerated
- // compositing.
- if (use_software_compositing()) {
- UseSoftwareCompositing();
- }
-
- ContentBrowserTest::SetUp();
- }
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- IsolateAllSitesForTesting(command_line);
+ // Don't call this. Call <BaseClass>::GetExpectedSourceSize() instead.
+ gfx::Size GetCapturedSourceSize() const final {
+ return shell()
+ ->web_contents()
+ ->GetMainFrame()
+ ->GetView()
+ ->GetViewBounds()
+ .size();
}
- void SetUpOnMainThread() override {
- ContentBrowserTest::SetUpOnMainThread();
-
- // Set-up and start the embedded test HTTP server.
- host_resolver()->AddRule("*", "127.0.0.1");
- embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
- &WebContentsVideoCaptureDeviceBrowserTest::HandleRequest,
- base::Unretained(this)));
- ASSERT_TRUE(embedded_test_server()->Start());
+ std::unique_ptr<FrameSinkVideoCaptureDevice> CreateDevice() final {
+ auto* const main_frame = shell()->web_contents()->GetMainFrame();
+ return std::make_unique<WebContentsVideoCaptureDevice>(
+ main_frame->GetProcess()->GetID(), main_frame->GetRoutingID());
}
- void TearDownOnMainThread() override {
- ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
-
- frames_.clear();
-
- // Run any left-over tasks (usually these are delete-soon's and orphaned
- // tasks).
- base::RunLoop().RunUntilIdle();
-
- ContentBrowserTest::TearDownOnMainThread();
- }
+ void WaitForFirstFrame() final { WaitForFrameWithColor(SK_ColorBLACK); }
private:
- void OnFrame(scoped_refptr<media::VideoFrame> frame) {
- // Frame timestamps should be monotionically increasing.
- EXPECT_LT(last_frame_timestamp_, frame->timestamp());
- last_frame_timestamp_ = frame->timestamp();
-
- frames_.emplace_back(std::move(frame));
- }
-
- // Called by the embedded test HTTP server to provide the document resources.
- std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
- auto response = std::make_unique<BasicHttpResponse>();
- response->set_content_type("text/html");
- const GURL& url = request.GetURL();
- if (url.path() == kOuterFramePath) {
- // A page with a solid white fill color, but containing an iframe in its
- // upper-left quadrant.
- const GURL& inner_frame_url =
- embedded_test_server()->GetURL(kInnerFrameHostname, kInnerFramePath);
- response->set_content(base::StringPrintf(
- "<!doctype html>"
- "<body style='background-color: #ffffff;'>"
- "<iframe src='%s' width=%d height=%d style='position:absolute; "
- "top:0px; left:0px; margin:none; padding:none; border:none;'>"
- "</iframe>"
- "</body>",
- inner_frame_url.spec().c_str(), expected_view_size_.width() / 2,
- expected_view_size_.height() / 2));
- } else {
- // A page whose solid fill color is based on a query parameter, or
- // defaults to black.
- const std::string& query = url.query();
- std::string color = "#000000";
- const auto pos = query.find("color=");
- if (pos != std::string::npos) {
- color = "#" + query.substr(pos + 6, 6);
- }
- response->set_content(
- base::StringPrintf("<!doctype html>"
- "<body style='background-color: %s;'></body>",
- color.c_str()));
- }
- return std::move(response);
- }
-
- static SkBitmap ConvertToSkBitmap(const media::VideoFrame& frame) {
- SkBitmap bitmap;
- bitmap.allocN32Pixels(frame.visible_rect().width(),
- frame.visible_rect().height());
- // TODO(miu): This is not Rec.709 colorspace conversion, and so will
- // introduce inaccuracies.
- libyuv::I420ToARGB(frame.visible_data(media::VideoFrame::kYPlane),
- frame.stride(media::VideoFrame::kYPlane),
- frame.visible_data(media::VideoFrame::kUPlane),
- frame.stride(media::VideoFrame::kUPlane),
- frame.visible_data(media::VideoFrame::kVPlane),
- frame.stride(media::VideoFrame::kVPlane),
- reinterpret_cast<uint8_t*>(bitmap.getPixels()),
- static_cast<int>(bitmap.rowBytes()), bitmap.width(),
- bitmap.height());
- return bitmap;
- }
-
- // Computes the average color in the frame for each of these regions: 1) the
- // upper-left quadrant of the content; 2) the remaining three quadrants of the
- // content; 3) the letterboxed regions (if any).
- static void AnalyzeFrame(SkBitmap frame,
- const gfx::Rect& content_rect,
- std::array<double, 3>* average_ul_content_rgb,
- std::array<double, 3>* average_rem_content_rgb,
- std::array<double, 3>* average_letterbox_rgb) {
- const gfx::Rect ul_content_rect(content_rect.x(), content_rect.y(),
- content_rect.width() / 2,
- content_rect.height() / 2);
- int64_t sum_of_ul_content_values[3] = {0};
- int64_t sum_of_rem_content_values[3] = {0};
- int64_t sum_of_letterbox_values[3] = {0};
- for (int y = 0; y < frame.height(); ++y) {
- for (int x = 0; x < frame.width(); ++x) {
- const SkColor color = frame.getColor(x, y);
- int64_t* const sums =
- ul_content_rect.Contains(x, y)
- ? sum_of_ul_content_values
- : (content_rect.Contains(x, y) ? sum_of_rem_content_values
- : sum_of_letterbox_values);
- sums[0] += SkColorGetR(color);
- sums[1] += SkColorGetG(color);
- sums[2] += SkColorGetB(color);
- }
- }
-
- const double ul_content_area =
- static_cast<double>(ul_content_rect.size().GetArea());
- for (int i = 0; i < 3; ++i) {
- (*average_ul_content_rgb)[i] =
- (ul_content_area <= 0.0)
- ? NAN
- : (sum_of_ul_content_values[i] / ul_content_area);
- }
-
- const double rem_content_area = static_cast<double>(
- content_rect.size().GetArea() - ul_content_rect.size().GetArea());
- for (int i = 0; i < 3; ++i) {
- (*average_rem_content_rgb)[i] =
- (rem_content_area <= 0.0)
- ? NAN
- : (sum_of_rem_content_values[i] / rem_content_area);
- }
-
- const double letterbox_area = static_cast<double>(
- (frame.width() * frame.height()) - content_rect.size().GetArea());
- for (int i = 0; i < 3; ++i) {
- (*average_letterbox_rgb)[i] =
- (letterbox_area <= 0.0)
- ? NAN
- : (sum_of_letterbox_values[i] / letterbox_area);
- }
- }
-
- static bool IsApproximatelySameColor(SkColor color,
- const std::array<double, 3> rgb) {
- const double r_diff = std::abs(SkColorGetR(color) - rgb[0]);
- const double g_diff = std::abs(SkColorGetG(color) - rgb[1]);
- const double b_diff = std::abs(SkColorGetB(color) - rgb[2]);
- return r_diff < kMaxColorDifference && g_diff < kMaxColorDifference &&
- b_diff < kMaxColorDifference;
- }
-
- FakeVideoCaptureStack capture_stack_;
-
- gfx::Size expected_view_size_;
-
- std::unique_ptr<WebContentsVideoCaptureDevice> device_;
- base::TimeDelta min_capture_period_;
- base::circular_deque<scoped_refptr<media::VideoFrame>> frames_;
- base::TimeDelta last_frame_timestamp_;
-
- static constexpr int kMaxColorDifference = 8;
-
- // Arbitrary string constants used to refer to each document by
- // host+path. Note that the "inner frame" and "outer frame" must have
- // different hostnames to engage the cross-site process isolation logic in the
- // browser.
- static constexpr char kInnerFrameHostname[] = "innerframe.com";
- static constexpr char kInnerFramePath[] = "/inner.html";
- static constexpr char kOuterFrameHostname[] = "outerframe.com";
- static constexpr char kOuterFramePath[] = "/outer.html";
- static constexpr char kSingleFrameHostname[] = "singleframe.com";
- static constexpr char kSingleFramePath[] = "/single.html";
+ DISALLOW_COPY_AND_ASSIGN(WebContentsVideoCaptureDeviceBrowserTest);
};
-// static
-constexpr char WebContentsVideoCaptureDeviceBrowserTest::kInnerFrameHostname[];
-// static
-constexpr char WebContentsVideoCaptureDeviceBrowserTest::kInnerFramePath[];
-// static
-constexpr char WebContentsVideoCaptureDeviceBrowserTest::kOuterFrameHostname[];
-// static
-constexpr char WebContentsVideoCaptureDeviceBrowserTest::kOuterFramePath[];
-// static
-constexpr char WebContentsVideoCaptureDeviceBrowserTest::kSingleFrameHostname[];
-// static
-constexpr char WebContentsVideoCaptureDeviceBrowserTest::kSingleFramePath[];
-
// Tests that the device refuses to start if the WebContents target was
// destroyed before the device could start.
IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
@@ -621,7 +184,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
render_process_id, render_frame_id);
// Running the pending UI tasks should cause the device to realize the
// WebContents is gone.
- RunAllPendingInMessageLoop(BrowserThread::UI);
+ RunUntilIdle();
// Attempt to start the device, and expect the video capture stack to have
// been notified of the error.
@@ -632,7 +195,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
capture_stack()->ExpectHasLogMessages();
device->StopAndDeAllocate();
- RunAllPendingInMessageLoop(BrowserThread::UI);
+ RunUntilIdle();
}
// Tests that the device starts, captures a frame, and then gracefully
@@ -643,13 +206,13 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
AllocateAndStartAndWaitForFirstFrame();
// Initially, the device captures any content changes normally.
- ChangePageContentColor("ff0000");
+ ChangePageContentColor(SK_ColorRED);
WaitForFrameWithColor(SK_ColorRED);
// Delete the WebContents instance and the Shell, and allow the the "target
// permanently lost" error to propagate to the video capture stack.
shell()->web_contents()->Close();
- RunAllPendingInMessageLoop(BrowserThread::UI);
+ RunUntilIdle();
EXPECT_TRUE(capture_stack()->error_occurred());
capture_stack()->ExpectHasLogMessages();
@@ -665,17 +228,17 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
AllocateAndStartAndWaitForFirstFrame();
// Initially, the device captures any content changes normally.
- ChangePageContentColor("ff0000");
+ ChangePageContentColor(SK_ColorRED);
WaitForFrameWithColor(SK_ColorRED);
// Suspend the device.
device()->MaybeSuspend();
- RunAllPendingInMessageLoop(BrowserThread::UI);
+ RunUntilIdle();
ClearCapturedFramesQueue();
// Change the page content and run the browser for five seconds. Expect no
// frames were queued because the device should be suspended.
- ChangePageContentColor("00ff00");
+ ChangePageContentColor(SK_ColorGREEN);
base::RunLoop run_loop;
BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
run_loop.QuitClosure(),
@@ -699,7 +262,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
AllocateAndStartAndWaitForFirstFrame();
// Set the page content to a known color.
- ChangePageContentColor("ff0000");
+ ChangePageContentColor(SK_ColorRED);
WaitForFrameWithColor(SK_ColorRED);
// Without making any further changes to the source (which would trigger
@@ -717,13 +280,13 @@ class WebContentsVideoCaptureDeviceBrowserTestP
: public WebContentsVideoCaptureDeviceBrowserTest,
public testing::WithParamInterface<std::tuple<bool, bool, bool>> {
public:
- bool use_software_compositing() const override {
+ bool IsSoftwareCompositingTest() const override {
return std::get<0>(GetParam());
}
- bool use_fixed_aspect_ratio() const override {
+ bool IsFixedAspectRatioTest() const override {
return std::get<1>(GetParam());
}
- bool is_cross_site_capture_test() const override {
+ bool IsCrossSiteCaptureTest() const override {
return std::get<2>(GetParam());
}
};
@@ -733,23 +296,23 @@ INSTANTIATE_TEST_CASE_P(
,
WebContentsVideoCaptureDeviceBrowserTestP,
testing::Combine(
- // On ChromeOS, software compositing is not an option.
- testing::Values(false),
- // Force video frame resolutions to have a fixed aspect ratio?
- testing::Values(false, true),
- // Test with a document that contains a cross-site iframe?
- testing::Values(false, true)));
+ // Note: On ChromeOS, software compositing is not an option.
+ testing::Values(false /* GPU-accelerated compositing */),
+ testing::Values(false /* variable aspect ratio */,
+ true /* fixed aspect ratio */),
+ testing::Values(false /* page has only a main frame */,
+ true /* page contains a cross-site iframe */)));
#else
INSTANTIATE_TEST_CASE_P(
,
WebContentsVideoCaptureDeviceBrowserTestP,
testing::Combine(
- // Use software compositing instead of GPU-accelerated compositing?
- testing::Values(false, true),
- // Force video frame resolutions to have a fixed aspect ratio?
- testing::Values(false, true),
- // Test with a document that contains a cross-site iframe?
- testing::Values(false, true)));
+ testing::Values(false /* GPU-accelerated compositing */,
+ true /* software compositing */),
+ testing::Values(false /* variable aspect ratio */,
+ true /* fixed aspect ratio */),
+ testing::Values(false /* page has only a main frame */,
+ true /* page contains a cross-site iframe */)));
#endif // defined(OS_CHROMEOS)
// Tests that the device successfully captures a series of content changes,
@@ -760,10 +323,10 @@ IN_PROC_BROWSER_TEST_P(WebContentsVideoCaptureDeviceBrowserTestP,
CapturesContentChanges) {
SCOPED_TRACE(testing::Message()
<< "Test parameters: "
- << (use_software_compositing() ? "Software Compositing"
- : "GPU Compositing")
+ << (IsSoftwareCompositingTest() ? "Software Compositing"
+ : "GPU Compositing")
<< " with "
- << (use_fixed_aspect_ratio() ? "Fixed Video Aspect Ratio"
+ << (IsFixedAspectRatioTest() ? "Fixed Video Aspect Ratio"
: "Variable Video Aspect Ratio"));
NavigateToInitialDocument();
@@ -771,42 +334,46 @@ IN_PROC_BROWSER_TEST_P(WebContentsVideoCaptureDeviceBrowserTestP,
for (int visilibilty_case = 0; visilibilty_case < 3; ++visilibilty_case) {
switch (visilibilty_case) {
- case 0:
- VLOG(1) << "Visibility case: WebContents is showing.";
+ case 0: {
+ SCOPED_TRACE(testing::Message()
+ << "Visibility case: WebContents is showing.");
shell()->web_contents()->WasShown();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(shell()->web_contents()->GetVisibility(),
content::Visibility::VISIBLE);
break;
- case 1:
- VLOG(1) << "Visibility case: WebContents is hidden.";
+ }
+
+ case 1: {
+ SCOPED_TRACE(testing::Message()
+ << "Visibility case: WebContents is hidden.");
shell()->web_contents()->WasHidden();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(shell()->web_contents()->GetVisibility(),
content::Visibility::HIDDEN);
break;
- case 2:
- VLOG(1) << "Visibility case: WebContents is showing, but occluded.";
+ }
+
+ case 2: {
+ SCOPED_TRACE(
+ testing::Message()
+ << "Visibility case: WebContents is showing, but occluded.");
shell()->web_contents()->WasShown();
shell()->web_contents()->WasOccluded();
base::RunLoop().RunUntilIdle();
ASSERT_EQ(shell()->web_contents()->GetVisibility(),
content::Visibility::OCCLUDED);
break;
+ }
}
- static const struct {
- const char* const css_hex;
- SkColor skia;
- } kColorsToCycleThrough[] = {
- {"ff0000", SK_ColorRED}, {"00ff00", SK_ColorGREEN},
- {"0000ff", SK_ColorBLUE}, {"ffff00", SK_ColorYELLOW},
- {"00ffff", SK_ColorCYAN}, {"ff00ff", SK_ColorMAGENTA},
- {"ffffff", SK_ColorWHITE},
+ static constexpr SkColor kColorsToCycleThrough[] = {
+ SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorYELLOW,
+ SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorWHITE,
};
- for (const auto color : kColorsToCycleThrough) {
- ChangePageContentColor(color.css_hex);
- WaitForFrameWithColor(color.skia);
+ for (SkColor color : kColorsToCycleThrough) {
+ ChangePageContentColor(color);
+ WaitForFrameWithColor(color);
}
}
diff --git a/chromium/content/browser/media/cdm_registry_impl_unittest.cc b/chromium/content/browser/media/cdm_registry_impl_unittest.cc
index 90040e2d820..96547c4fc7f 100644
--- a/chromium/content/browser/media/cdm_registry_impl_unittest.cc
+++ b/chromium/content/browser/media/cdm_registry_impl_unittest.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/base_paths.h"
+#include "base/containers/flat_set.h"
#include "base/files/file_path.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -21,6 +22,7 @@
namespace content {
const char kTestCdmName[] = "Test CDM";
+const char kAlternateCdmName[] = "Alternate CDM";
const char kTestCdmGuid[] = "62FE9C4B-384E-48FD-B28A-9F6F248BC8CC";
const char kTestPath[] = "/aa/bb";
const char kVersion1[] = "1.1.1.1";
@@ -41,13 +43,14 @@ class CdmRegistryImplTest : public testing::Test {
const std::string& path,
const std::vector<media::VideoCodec>& supported_video_codecs,
bool supports_persistent_license,
+ const base::flat_set<media::EncryptionMode>& supported_modes,
std::string supported_key_system,
bool supports_sub_key_systems = false) {
- cdm_registry_.RegisterCdm(
- CdmInfo(name, kTestCdmGuid, base::Version(version),
- base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId,
- supported_video_codecs, supports_persistent_license,
- supported_key_system, supports_sub_key_systems));
+ cdm_registry_.RegisterCdm(CdmInfo(
+ name, kTestCdmGuid, base::Version(version),
+ base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId,
+ supported_video_codecs, supports_persistent_license, supported_modes,
+ supported_key_system, supports_sub_key_systems));
}
bool IsRegistered(const std::string& name, const std::string& version) {
@@ -73,7 +76,8 @@ class CdmRegistryImplTest : public testing::Test {
TEST_F(CdmRegistryImplTest, Register) {
Register(kTestCdmName, kVersion1, kTestPath,
- {media::kCodecVP8, media::kCodecVP9}, true, kTestKeySystem, true);
+ {media::kCodecVP8, media::kCodecVP9}, true,
+ {media::EncryptionMode::kCenc}, kTestKeySystem, true);
std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
ASSERT_EQ(1u, cdms.size());
CdmInfo cdm = cdms[0];
@@ -85,29 +89,38 @@ TEST_F(CdmRegistryImplTest, Register) {
EXPECT_EQ(media::kCodecVP8, cdm.supported_video_codecs[0]);
EXPECT_EQ(media::kCodecVP9, cdm.supported_video_codecs[1]);
EXPECT_TRUE(cdm.supports_persistent_license);
+ EXPECT_EQ(1u, cdm.supported_encryption_schemes.size());
+ EXPECT_EQ(
+ 1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
EXPECT_EQ(kTestKeySystem, cdm.supported_key_system);
EXPECT_TRUE(cdm.supports_sub_key_systems);
}
TEST_F(CdmRegistryImplTest, ReRegister) {
- Register(kTestCdmName, kVersion1, "/bb/cc", {}, false, kTestKeySystem);
+ Register(kTestCdmName, kVersion1, "/bb/cc", {}, false,
+ {media::EncryptionMode::kCenc}, kTestKeySystem);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
// Now register same key system with different values.
- Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem);
+ Register(kTestCdmName, kVersion1, kTestPath, {}, false,
+ {media::EncryptionMode::kCenc}, kTestKeySystem);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
}
TEST_F(CdmRegistryImplTest, MultipleVersions) {
- Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem);
- Register(kTestCdmName, kVersion2, "/bb/cc", {}, false, kTestKeySystem);
+ Register(kTestCdmName, kVersion1, kTestPath, {}, false,
+ {media::EncryptionMode::kCenc}, kTestKeySystem);
+ Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
+ {media::EncryptionMode::kCenc}, kTestKeySystem);
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion2));
}
TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
- Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem);
- Register(kTestCdmName, kVersion2, "/bb/cc", {}, false, kTestKeySystem);
+ Register(kTestCdmName, kVersion1, kTestPath, {}, false,
+ {media::EncryptionMode::kCenc}, kTestKeySystem);
+ Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
+ {media::EncryptionMode::kCenc}, kTestKeySystem);
const std::vector<std::string> versions = GetVersions(kTestCdmGuid);
EXPECT_EQ(2u, versions.size());
@@ -115,4 +128,28 @@ TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
EXPECT_EQ(kVersion2, versions[1]);
}
+TEST_F(CdmRegistryImplTest, DifferentNames) {
+ Register(kTestCdmName, kVersion1, kTestPath, {}, false,
+ {media::EncryptionMode::kCenc}, kTestKeySystem);
+ Register(kAlternateCdmName, kVersion1, kTestPath, {}, false,
+ {media::EncryptionMode::kCbcs}, kTestKeySystem);
+ EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
+ EXPECT_TRUE(IsRegistered(kAlternateCdmName, kVersion1));
+}
+
+TEST_F(CdmRegistryImplTest, SupportedEncryptionSchemes) {
+ Register(kTestCdmName, kVersion1, kTestPath, {}, false,
+ {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs},
+ kTestKeySystem);
+
+ std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
+ ASSERT_EQ(1u, cdms.size());
+ const CdmInfo& cdm = cdms[0];
+ EXPECT_EQ(2u, cdm.supported_encryption_schemes.size());
+ EXPECT_EQ(
+ 1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
+ EXPECT_EQ(
+ 1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCbcs));
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index 9a01d1a44e9..7096e1e1fe8 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -47,12 +47,15 @@ const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
// Supported media types.
const char kWebMVorbisAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
const char kWebMOpusAudioOnly[] = "audio/webm; codecs=\"opus\"";
-const char kWebMVP8VideoOnly[] = "video/webm; codecs=\"vp8\"";
-const char kWebMVP9VideoOnly[] = "video/webm; codecs=\"vp9\"";
-const char kWebMOpusAudioVP9Video[] = "video/webm; codecs=\"opus, vp9\"";
-const char kWebMVorbisAudioVP8Video[] = "video/webm; codecs=\"vorbis, vp8\"";
+const char kWebMVp8VideoOnly[] = "video/webm; codecs=\"vp8\"";
+const char kWebMVp9VideoOnly[] = "video/webm; codecs=\"vp9\"";
+const char kWebMOpusAudioVp9Video[] = "video/webm; codecs=\"opus, vp9\"";
+const char kWebMVorbisAudioVp8Video[] = "video/webm; codecs=\"vorbis, vp8\"";
+const char kMp4FlacAudioOnly[] = "audio/mp4; codecs=\"flac\"";
+const char kMp4Vp9VideoOnly[] =
+ "video/mp4; codecs=\"vp09.00.10.08.01.02.02.02.00\"";
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-const char kMP4VideoOnly[] = "video/mp4; codecs=\"avc1.64001E\"";
+const char kMp4Avc1VideoOnly[] = "video/mp4; codecs=\"avc1.64001E\"";
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
// EME-specific test results and errors.
@@ -89,14 +92,14 @@ class EncryptedMediaTest
void TestSimplePlayback(const std::string& encrypted_media,
const std::string& media_type) {
- RunSimpleEncryptedMediaTest(
- encrypted_media, media_type, CurrentKeySystem(), CurrentSourceType());
+ RunSimpleEncryptedMediaTest(encrypted_media, media_type, CurrentKeySystem(),
+ CurrentSourceType());
}
void TestFrameSizeChange() {
RunEncryptedMediaTest("encrypted_frame_size_change.html",
"frame_size_change-av_enc-v.webm",
- kWebMVorbisAudioVP8Video, CurrentKeySystem(),
+ kWebMVorbisAudioVp8Video, CurrentKeySystem(),
CurrentSourceType(), media::kEnded);
}
@@ -141,18 +144,17 @@ class EncryptedMediaTest
src_type, media::kEnded);
}
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
- void TestMP4EncryptionPlayback(const std::string& media_file,
+ void TestMp4EncryptionPlayback(const std::string& media_file,
+ const std::string& media_type,
const std::string& expected_title) {
if (CurrentSourceType() != SrcType::MSE) {
DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
return;
}
- RunEncryptedMediaTest(kDefaultEmePlayer, media_file, kMP4VideoOnly,
+ RunEncryptedMediaTest(kDefaultEmePlayer, media_file, media_type,
CurrentKeySystem(), SrcType::MSE, expected_title);
}
-#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
protected:
// We want to fail quickly when a test fails because an error is encountered.
@@ -205,29 +207,29 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) {
- TestSimplePlayback("bear-320x240-av_enc-a.webm", kWebMVorbisAudioVP8Video);
+ TestSimplePlayback("bear-320x240-av_enc-a.webm", kWebMVorbisAudioVp8Video);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM) {
- TestSimplePlayback("bear-320x240-av_enc-av.webm", kWebMVorbisAudioVP8Video);
+ TestSimplePlayback("bear-320x240-av_enc-av.webm", kWebMVorbisAudioVp8Video);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM) {
- TestSimplePlayback("bear-320x240-v_enc-v.webm", kWebMVP8VideoOnly);
+ TestSimplePlayback("bear-320x240-v_enc-v.webm", kWebMVp8VideoOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM_Fullsample) {
TestSimplePlayback("bear-320x240-v-vp9_fullsample_enc-v.webm",
- kWebMVP9VideoOnly);
+ kWebMVp9VideoOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM_Subsample) {
TestSimplePlayback("bear-320x240-v-vp9_subsample_enc-v.webm",
- kWebMVP9VideoOnly);
+ kWebMVp9VideoOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
- TestSimplePlayback("bear-320x240-av_enc-v.webm", kWebMVorbisAudioVP8Video);
+ TestSimplePlayback("bear-320x240-av_enc-v.webm", kWebMVorbisAudioVp8Video);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM_Opus) {
@@ -244,7 +246,7 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM_Opus) {
return;
#endif
TestSimplePlayback("bear-320x240-opus-av_enc-av.webm",
- kWebMOpusAudioVP9Video);
+ kWebMOpusAudioVp9Video);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
@@ -252,7 +254,21 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
if (!media::PlatformHasOpusSupport())
return;
#endif
- TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVP9Video);
+ TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVp9Video);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_FLAC) {
+ TestMp4EncryptionPlayback("bear-flac-cenc.mp4", kMp4FlacAudioOnly,
+ media::kEnded);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
+ // MP4 without MSE is not support yet, http://crbug.com/170793.
+ if (CurrentSourceType() != SrcType::MSE) {
+ DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
+ return;
+ }
+ TestSimplePlayback("bear-320x240-v_frag-vp9-cenc.mp4", kMp4Vp9VideoOnly);
}
// Strictly speaking this is not an "encrypted" media test. Keep it here for
@@ -286,23 +302,25 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_FrameSizeChangeVideo) {
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CENC) {
- TestMP4EncryptionPlayback("bear-640x360-v_frag-cenc.mp4", media::kEnded);
+ TestMp4EncryptionPlayback("bear-640x360-v_frag-cenc.mp4", kMp4Avc1VideoOnly,
+ media::kEnded);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CBC1) {
- TestMP4EncryptionPlayback("bear-640x360-v_frag-cbc1.mp4", media::kError);
+ TestMp4EncryptionPlayback("bear-640x360-v_frag-cbc1.mp4", kMp4Avc1VideoOnly,
+ media::kError);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CENS) {
- TestMP4EncryptionPlayback("bear-640x360-v_frag-cens.mp4", media::kError);
+ TestMp4EncryptionPlayback("bear-640x360-v_frag-cens.mp4", kMp4Avc1VideoOnly,
+ media::kError);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CBCS) {
-#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
- TestMP4EncryptionPlayback("bear-640x360-v_frag-cbcs.mp4", media::kEnded);
-#else
- TestMP4EncryptionPlayback("bear-640x360-v_frag-cbcs.mp4", media::kError);
-#endif
+ std::string expected_result =
+ BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) ? media::kEnded : media::kError;
+ TestMp4EncryptionPlayback("bear-640x360-v_frag-cbcs.mp4", kMp4Avc1VideoOnly,
+ expected_result);
}
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
diff --git a/chromium/content/browser/media/flinging_renderer.cc b/chromium/content/browser/media/flinging_renderer.cc
new file mode 100644
index 00000000000..8828939c4e5
--- /dev/null
+++ b/chromium/content/browser/media/flinging_renderer.cc
@@ -0,0 +1,100 @@
+// 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/media/flinging_renderer.h"
+
+#include "base/memory/ptr_util.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/presentation_service_delegate.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/common/content_client.h"
+
+namespace content {
+
+FlingingRenderer::FlingingRenderer(std::unique_ptr<MediaController> controller)
+ : controller_(std::move(controller)) {}
+
+FlingingRenderer::~FlingingRenderer() = default;
+
+// static
+std::unique_ptr<FlingingRenderer> FlingingRenderer::Create(
+ RenderFrameHost* render_frame_host,
+ const std::string& presentation_id) {
+ DVLOG(1) << __func__;
+
+ ContentClient* content_client = GetContentClient();
+ if (!content_client)
+ return nullptr;
+
+ ContentBrowserClient* browser_client = content_client->browser();
+ if (!browser_client)
+ return nullptr;
+
+ ControllerPresentationServiceDelegate* presentation_delegate =
+ browser_client->GetControllerPresentationServiceDelegate(
+ static_cast<RenderFrameHostImpl*>(render_frame_host)
+ ->delegate()
+ ->GetAsWebContents());
+
+ if (!presentation_delegate)
+ return nullptr;
+
+ auto media_controller = presentation_delegate->GetMediaController(
+ render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID(), presentation_id);
+
+ if (!media_controller)
+ return nullptr;
+
+ return base::WrapUnique<FlingingRenderer>(
+ new FlingingRenderer(std::move(media_controller)));
+}
+
+// media::Renderer implementation
+void FlingingRenderer::Initialize(media::MediaResource* media_resource,
+ media::RendererClient* client,
+ const media::PipelineStatusCB& init_cb) {
+ DVLOG(2) << __func__;
+ init_cb.Run(media::PIPELINE_OK);
+}
+
+void FlingingRenderer::SetCdm(media::CdmContext* cdm_context,
+ const media::CdmAttachedCB& cdm_attached_cb) {
+ // The flinging renderer does not support playing encrypted content.
+ NOTREACHED();
+}
+
+void FlingingRenderer::Flush(const base::Closure& flush_cb) {
+ DVLOG(2) << __func__;
+ // There is nothing to reset, we can no-op the call.
+ flush_cb.Run();
+}
+
+void FlingingRenderer::StartPlayingFrom(base::TimeDelta time) {
+ DVLOG(2) << __func__;
+ controller_->Seek(time);
+ controller_->Play();
+}
+
+void FlingingRenderer::SetPlaybackRate(double playback_rate) {
+ DVLOG(2) << __func__;
+ if (playback_rate == 0)
+ controller_->Pause();
+ else
+ controller_->Play();
+}
+
+void FlingingRenderer::SetVolume(float volume) {
+ DVLOG(2) << __func__;
+ controller_->SetVolume(volume);
+}
+
+base::TimeDelta FlingingRenderer::GetMediaTime() {
+ // TODO(https://crbug.com/830871): return correct media time.
+ return base::TimeDelta();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/flinging_renderer.h b/chromium/content/browser/media/flinging_renderer.h
new file mode 100644
index 00000000000..59a12b8bf07
--- /dev/null
+++ b/chromium/content/browser/media/flinging_renderer.h
@@ -0,0 +1,62 @@
+// 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_MEDIA_FLINGING_RENDERER_H_
+#define CONTENT_BROWSER_MEDIA_FLINGING_RENDERER_H_
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/media_controller.h"
+#include "media/base/media_resource.h"
+#include "media/base/renderer.h"
+#include "media/base/renderer_client.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class FlingingRendererTest;
+class RenderFrameHost;
+
+// FlingingRenderer adapts from the media::Renderer interface to the
+// MediaController interface. The MediaController is used to issue simple media
+// playback commands. In this case, the media we are controlling should be an
+// already existing RemotingCastSession, which should have been initiated by a
+// blink::RemotePlayback object, using the PresentationService.
+class CONTENT_EXPORT FlingingRenderer : public media::Renderer {
+ public:
+ // Helper method to create a FlingingRenderer from an already existing
+ // presentation ID.
+ // Returns nullptr if there was an error getting the MediaControllor for the
+ // given presentation ID.
+ static std::unique_ptr<FlingingRenderer> Create(
+ RenderFrameHost* render_frame_host,
+ const std::string& presentation_id);
+
+ ~FlingingRenderer() override;
+
+ // media::Renderer implementation
+ void Initialize(media::MediaResource* media_resource,
+ media::RendererClient* client,
+ const media::PipelineStatusCB& init_cb) override;
+ void SetCdm(media::CdmContext* cdm_context,
+ const media::CdmAttachedCB& cdm_attached_cb) override;
+ void Flush(const base::Closure& flush_cb) override;
+ void StartPlayingFrom(base::TimeDelta time) override;
+ void SetPlaybackRate(double playback_rate) override;
+ void SetVolume(float volume) override;
+ base::TimeDelta GetMediaTime() override;
+
+ private:
+ friend class FlingingRendererTest;
+
+ explicit FlingingRenderer(std::unique_ptr<MediaController> controller);
+
+ std::unique_ptr<MediaController> controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlingingRenderer);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_FLINGING_RENDERER_H_
diff --git a/chromium/content/browser/media/flinging_renderer_unittest.cc b/chromium/content/browser/media/flinging_renderer_unittest.cc
new file mode 100644
index 00000000000..923415d94b8
--- /dev/null
+++ b/chromium/content/browser/media/flinging_renderer_unittest.cc
@@ -0,0 +1,84 @@
+// 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/media/flinging_renderer.h"
+
+#include "base/version.h"
+#include "content/public/browser/media_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::StrictMock;
+
+namespace content {
+
+class MockMediaController : public MediaController {
+ public:
+ MOCK_METHOD0(Play, void());
+ MOCK_METHOD0(Pause, void());
+ MOCK_METHOD1(SetMute, void(bool));
+ MOCK_METHOD1(SetVolume, void(float));
+ MOCK_METHOD1(Seek, void(base::TimeDelta));
+};
+
+class FlingingRendererTest : public testing::Test {
+ public:
+ FlingingRendererTest()
+ : media_controller_(new StrictMock<MockMediaController>()),
+ renderer_(std::unique_ptr<MediaController>(media_controller_)) {}
+
+ protected:
+ StrictMock<MockMediaController>* media_controller_;
+ FlingingRenderer renderer_;
+};
+
+TEST_F(FlingingRendererTest, StartPlayingFromTime) {
+ base::TimeDelta seek_time = base::TimeDelta::FromSeconds(10);
+ EXPECT_CALL(*media_controller_, Play());
+ EXPECT_CALL(*media_controller_, Seek(seek_time));
+
+ renderer_.StartPlayingFrom(seek_time);
+}
+
+TEST_F(FlingingRendererTest, StartPlayingFromBeginning) {
+ EXPECT_CALL(*media_controller_, Play());
+ EXPECT_CALL(*media_controller_, Seek(base::TimeDelta()));
+
+ renderer_.StartPlayingFrom(base::TimeDelta());
+}
+
+TEST_F(FlingingRendererTest, SetPlaybackRate) {
+ double playback_rate = 1.0;
+ EXPECT_CALL(*media_controller_, Play());
+
+ renderer_.SetPlaybackRate(playback_rate);
+}
+
+TEST_F(FlingingRendererTest, SetPlaybackRateToZero) {
+ double playback_rate = 0.0;
+ EXPECT_CALL(*media_controller_, Pause());
+
+ renderer_.SetPlaybackRate(playback_rate);
+}
+
+// Setting the volume to a positive value should not change the mute state.
+TEST_F(FlingingRendererTest, SetVolume) {
+ float volume = 0.5;
+ EXPECT_CALL(*media_controller_, SetVolume(volume));
+ EXPECT_CALL(*media_controller_, SetMute(_)).Times(0);
+
+ renderer_.SetVolume(volume);
+}
+
+// Setting the volume to 0 should not set the mute state.
+TEST_F(FlingingRendererTest, SetVolumeToZero) {
+ float volume = 0;
+ EXPECT_CALL(*media_controller_, SetVolume(volume));
+ EXPECT_CALL(*media_controller_, SetMute(_)).Times(0);
+
+ renderer_.SetVolume(volume);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory.cc b/chromium/content/browser/media/forwarding_audio_stream_factory.cc
new file mode 100644
index 00000000000..694f8bfe4d2
--- /dev/null
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory.cc
@@ -0,0 +1,256 @@
+// 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/media/forwarding_audio_stream_factory.h"
+
+#include <utility>
+
+#include "base/trace_event/trace_event.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace content {
+
+ForwardingAudioStreamFactory::ForwardingAudioStreamFactory(
+ WebContents* web_contents,
+ std::unique_ptr<service_manager::Connector> connector,
+ std::unique_ptr<AudioStreamBrokerFactory> broker_factory)
+ : WebContentsObserver(web_contents),
+ connector_(std::move(connector)),
+ broker_factory_(std::move(broker_factory)),
+ group_id_(base::UnguessableToken::Create()) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(web_contents);
+ DCHECK(broker_factory_);
+}
+
+ForwardingAudioStreamFactory::~ForwardingAudioStreamFactory() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+// static
+ForwardingAudioStreamFactory* ForwardingAudioStreamFactory::ForFrame(
+ RenderFrameHost* frame) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ auto* contents =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(frame));
+ if (!contents)
+ return nullptr;
+
+ return contents->GetAudioStreamFactory();
+}
+
+void ForwardingAudioStreamFactory::CreateInputStream(
+ RenderFrameHost* frame,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ const int process_id = frame->GetProcess()->GetID();
+ const int frame_id = frame->GetRoutingID();
+ inputs_
+ .insert(broker_factory_->CreateAudioInputStreamBroker(
+ process_id, frame_id, device_id, params, shared_memory_count,
+ enable_agc,
+ base::BindOnce(&ForwardingAudioStreamFactory::RemoveInput,
+ base::Unretained(this)),
+ std::move(renderer_factory_client)))
+ .first->get()
+ ->CreateStream(GetFactory());
+}
+
+void ForwardingAudioStreamFactory::AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& raw_output_device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Avoid spawning a factory if this for some reason gets called with an
+ // invalid input_stream_id before any streams are created.
+ if (!inputs_.empty()) {
+ GetFactory()->AssociateInputAndOutputForAec(input_stream_id,
+ raw_output_device_id);
+ }
+}
+
+void ForwardingAudioStreamFactory::CreateOutputStream(
+ RenderFrameHost* frame,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ media::mojom::AudioOutputStreamProviderClientPtr client) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ const int process_id = frame->GetProcess()->GetID();
+ const int frame_id = frame->GetRoutingID();
+
+ outputs_
+ .insert(broker_factory_->CreateAudioOutputStreamBroker(
+ process_id, frame_id, ++stream_id_counter_, device_id, params,
+ group_id_,
+ base::BindOnce(&ForwardingAudioStreamFactory::RemoveOutput,
+ base::Unretained(this)),
+ std::move(client)))
+ .first->get()
+ ->CreateStream(GetFactory());
+}
+
+void ForwardingAudioStreamFactory::CreateLoopbackStream(
+ RenderFrameHost* frame,
+ RenderFrameHost* frame_of_source_web_contents,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool mute_source,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(frame);
+ DCHECK(frame_of_source_web_contents);
+
+ TRACE_EVENT_BEGIN1("audio", "CreateLoopbackStream", "group",
+ group_id_.GetLowForSerialization());
+
+ WebContents* source_contents =
+ WebContents::FromRenderFrameHost(frame_of_source_web_contents);
+ if (!source_contents) {
+ TRACE_EVENT_END1("audio", "CreateLoopbackStream", "source",
+ "failed to find source");
+ return;
+ }
+
+ const int process_id = frame->GetProcess()->GetID();
+ const int frame_id = frame->GetRoutingID();
+ inputs_
+ .insert(broker_factory_->CreateAudioLoopbackStreamBroker(
+ process_id, frame_id,
+ std::make_unique<AudioStreamBrokerFactory::LoopbackSource>(
+ source_contents),
+ params, shared_memory_count, mute_source,
+ base::BindOnce(&ForwardingAudioStreamFactory::RemoveInput,
+ base::Unretained(this)),
+ std::move(renderer_factory_client)))
+ .first->get()
+ ->CreateStream(GetFactory());
+ TRACE_EVENT_END1("audio", "CreateLoopbackStream", "source",
+ static_cast<WebContentsImpl*>(source_contents)
+ ->GetAudioStreamFactory()
+ ->group_id()
+ .GetLowForSerialization());
+}
+
+void ForwardingAudioStreamFactory::SetMuted(bool muted) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_NE(muted, IsMuted());
+ TRACE_EVENT_INSTANT2("audio", "SetMuted", TRACE_EVENT_SCOPE_THREAD, "group",
+ group_id_.GetLowForSerialization(), "muted", muted);
+
+ if (!muted) {
+ muter_.reset();
+ return;
+ }
+
+ muter_.emplace(group_id_);
+ if (remote_factory_)
+ muter_->Connect(remote_factory_.get());
+}
+
+bool ForwardingAudioStreamFactory::IsMuted() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return !!muter_;
+}
+
+void ForwardingAudioStreamFactory::FrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ CleanupStreamsBelongingTo(render_frame_host);
+}
+
+void ForwardingAudioStreamFactory::CleanupStreamsBelongingTo(
+ RenderFrameHost* render_frame_host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ const int process_id = render_frame_host->GetProcess()->GetID();
+ const int frame_id = render_frame_host->GetRoutingID();
+
+ TRACE_EVENT_BEGIN2("audio", "CleanupStreamsBelongingTo", "group",
+ group_id_.GetLowForSerialization(), "process id",
+ process_id);
+
+ auto match_rfh =
+ [process_id,
+ frame_id](const std::unique_ptr<AudioStreamBroker>& broker) -> bool {
+ return broker->render_process_id() == process_id &&
+ broker->render_frame_id() == frame_id;
+ };
+
+ base::EraseIf(outputs_, match_rfh);
+ base::EraseIf(inputs_, match_rfh);
+
+ ResetRemoteFactoryPtrIfIdle();
+
+ TRACE_EVENT_END1("audio", "CleanupStreamsBelongingTo", "frame_id", frame_id);
+}
+
+void ForwardingAudioStreamFactory::RemoveInput(AudioStreamBroker* broker) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ size_t removed = inputs_.erase(broker);
+ DCHECK_EQ(1u, removed);
+
+ ResetRemoteFactoryPtrIfIdle();
+}
+
+void ForwardingAudioStreamFactory::RemoveOutput(AudioStreamBroker* broker) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ size_t removed = outputs_.erase(broker);
+ DCHECK_EQ(1u, removed);
+
+ ResetRemoteFactoryPtrIfIdle();
+}
+
+audio::mojom::StreamFactory* ForwardingAudioStreamFactory::GetFactory() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!remote_factory_) {
+ TRACE_EVENT_INSTANT1(
+ "audio", "ForwardingAudioStreamFactory: Binding new factory",
+ TRACE_EVENT_SCOPE_THREAD, "group", group_id_.GetLowForSerialization());
+ connector_->BindInterface(audio::mojom::kServiceName,
+ mojo::MakeRequest(&remote_factory_));
+ // Unretained is safe because |this| owns |remote_factory_|.
+ remote_factory_.set_connection_error_handler(
+ base::BindOnce(&ForwardingAudioStreamFactory::ResetRemoteFactoryPtr,
+ base::Unretained(this)));
+
+ // Restore the muting session on reconnect.
+ if (muter_)
+ muter_->Connect(remote_factory_.get());
+ }
+
+ return remote_factory_.get();
+}
+
+void ForwardingAudioStreamFactory::ResetRemoteFactoryPtrIfIdle() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (inputs_.empty() && outputs_.empty())
+ ResetRemoteFactoryPtr();
+}
+
+void ForwardingAudioStreamFactory::ResetRemoteFactoryPtr() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (remote_factory_) {
+ TRACE_EVENT_INSTANT1(
+ "audio", "ForwardingAudioStreamFactory: Resetting factory",
+ TRACE_EVENT_SCOPE_THREAD, "group", group_id_.GetLowForSerialization());
+ }
+ remote_factory_.reset();
+ // The stream brokers will call a callback to be deleted soon, give them a
+ // chance to signal an error to the client first.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory.h b/chromium/content/browser/media/forwarding_audio_stream_factory.h
new file mode 100644
index 00000000000..26ffbb89bbb
--- /dev/null
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory.h
@@ -0,0 +1,144 @@
+// 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_MEDIA_FORWARDING_AUDIO_STREAM_FACTORY_H_
+#define CONTENT_BROWSER_MEDIA_FORWARDING_AUDIO_STREAM_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
+#include "content/browser/media/audio_muting_session.h"
+#include "content/browser/media/audio_stream_broker.h"
+#include "content/common/content_export.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+
+namespace service_manager {
+class Connector;
+}
+
+namespace media {
+class AudioParameters;
+}
+
+namespace content {
+
+class AudioStreamBroker;
+class RenderFrameHost;
+class WebContents;
+
+// This class handles stream creation operations for a WebContents.
+// This class is operated on the UI thread.
+class CONTENT_EXPORT ForwardingAudioStreamFactory final
+ : public WebContentsObserver {
+ public:
+ ForwardingAudioStreamFactory(
+ WebContents* web_contents,
+ std::unique_ptr<service_manager::Connector> connector,
+ std::unique_ptr<AudioStreamBrokerFactory> factory);
+
+ ~ForwardingAudioStreamFactory() final;
+
+ // Returns the ForwardingAudioStreamFactory which takes care of stream
+ // creation for |frame|. Returns null if |frame| is null or if the frame
+ // doesn't belong to a WebContents.
+ static ForwardingAudioStreamFactory* ForFrame(RenderFrameHost* frame);
+
+ const base::UnguessableToken& group_id() { return group_id_; }
+
+ // TODO(https://crbug.com/787806): Automatically restore streams on audio
+ // service restart.
+ void CreateInputStream(
+ RenderFrameHost* frame,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client);
+
+ void AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& raw_output_device_id);
+
+ void CreateOutputStream(
+ RenderFrameHost* frame,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ media::mojom::AudioOutputStreamProviderClientPtr client);
+
+ void CreateLoopbackStream(
+ RenderFrameHost* frame,
+ RenderFrameHost* frame_of_source_web_contents,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool mute_source,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client);
+
+ // Sets the muting state for all output streams created through this factory.
+ void SetMuted(bool muted);
+
+ // Returns the current muting state.
+ bool IsMuted() const;
+
+ // WebContentsObserver implementation. We observe these events so that we can
+ // clean up streams belonging to a frame when that frame is destroyed.
+ void FrameDeleted(RenderFrameHost* render_frame_host) final;
+
+ // E.g. to override binder.
+ service_manager::Connector* get_connector_for_testing() {
+ return connector_.get();
+ }
+
+ private:
+ using StreamBrokerSet = base::flat_set<std::unique_ptr<AudioStreamBroker>,
+ base::UniquePtrComparator>;
+
+ void CleanupStreamsBelongingTo(RenderFrameHost* render_frame_host);
+
+ void RemoveInput(AudioStreamBroker* handle);
+ void RemoveOutput(AudioStreamBroker* handle);
+
+ audio::mojom::StreamFactory* GetFactory();
+ void ResetRemoteFactoryPtrIfIdle();
+ void ResetRemoteFactoryPtr();
+
+ const std::unique_ptr<service_manager::Connector> connector_;
+ const std::unique_ptr<AudioStreamBrokerFactory> broker_factory_;
+
+ // Unique id indentifying all streams belonging to the WebContents owning
+ // |this|.
+ // TODO(https://crbug.com/824019): Use this for loopback.
+ const base::UnguessableToken group_id_;
+
+ // Lazily acquired. Reset on connection error and when we no longer have any
+ // streams. Note: we don't want muting to force the connection to be open,
+ // since we want to clean up the service when not in use. If we have active
+ // muting but nothing else, we should stop it and start it again when we need
+ // to reacquire the factory for some other reason.
+ audio::mojom::StreamFactoryPtr remote_factory_;
+
+ // Running id used for tracking audible streams. We keep count here to avoid
+ // collisions.
+ // TODO(https://crbug.com/830494): Refactor to make this unnecessary and
+ // remove it.
+ int stream_id_counter_ = 0;
+
+ // Instantiated when |outputs_| should be muted, empty otherwise.
+ base::Optional<AudioMutingSession> muter_;
+
+ StreamBrokerSet inputs_;
+ StreamBrokerSet outputs_;
+
+ DISALLOW_COPY_AND_ASSIGN(ForwardingAudioStreamFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_FORWARDING_AUDIO_STREAM_FACTORY_H_
diff --git a/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc b/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
new file mode 100644
index 00000000000..e0764947aa1
--- /dev/null
+++ b/chromium/content/browser/media/forwarding_audio_stream_factory_unittest.cc
@@ -0,0 +1,711 @@
+// 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/media/forwarding_audio_stream_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/test/mock_callback.h"
+#include "base/unguessable_token.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/test_renderer_host.h"
+#include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/audio/public/cpp/fake_stream_factory.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Test;
+using ::testing::Mock;
+using ::testing::NotNull;
+using ::testing::StrictMock;
+using ::testing::InSequence;
+
+namespace content {
+
+namespace {
+
+class MockStreamFactory : public audio::FakeStreamFactory,
+ public audio::mojom::LocalMuter {
+ public:
+ MockStreamFactory() : muter_binding_(this) {}
+ ~MockStreamFactory() final {}
+
+ bool IsConnected() {
+ return binding_ && !binding_.handle().QuerySignalsState().peer_closed();
+ }
+ bool IsMuterConnected() { return muter_binding_.is_bound(); }
+
+ private:
+ void BindMuter(audio::mojom::LocalMuterAssociatedRequest request,
+ const base::UnguessableToken& group_id) final {
+ muter_binding_.Bind(std::move(request));
+ muter_binding_.set_connection_error_handler(base::BindOnce(
+ &MockStreamFactory::MuterUnbound, base::Unretained(this)));
+ }
+ void MuterUnbound() { muter_binding_.Close(); }
+
+ mojo::AssociatedBinding<audio::mojom::LocalMuter> muter_binding_;
+ DISALLOW_COPY_AND_ASSIGN(MockStreamFactory);
+};
+
+class MockBroker : public AudioStreamBroker {
+ public:
+ explicit MockBroker(RenderFrameHost* rfh)
+ : AudioStreamBroker(rfh->GetProcess()->GetID(), rfh->GetRoutingID()),
+ weak_factory_(this) {}
+
+ ~MockBroker() override {}
+
+ MOCK_METHOD1(CreateStream, void(audio::mojom::StreamFactory* factory));
+
+ // Can be used to verify that |this| has been destructed.
+ base::WeakPtr<MockBroker> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
+
+ DeleterCallback deleter;
+
+ private:
+ base::WeakPtrFactory<MockBroker> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(MockBroker);
+};
+
+class MockBrokerFactory : public AudioStreamBrokerFactory {
+ public:
+ MockBrokerFactory() {}
+ ~MockBrokerFactory() final {
+ EXPECT_TRUE(prepared_input_stream_brokers_.empty())
+ << "Input broker creation was expected but didn't happen";
+ EXPECT_TRUE(prepared_output_stream_brokers_.empty())
+ << "Output broker creation was expected but didn't happen";
+ }
+
+ void ExpectInputStreamBrokerCreation(std::unique_ptr<MockBroker> broker) {
+ prepared_input_stream_brokers_.push(std::move(broker));
+ }
+
+ void ExpectOutputStreamBrokerCreation(std::unique_ptr<MockBroker> broker) {
+ prepared_output_stream_brokers_.push(std::move(broker));
+ }
+
+ void ExpectLoopbackStreamBrokerCreation(std::unique_ptr<MockBroker> broker) {
+ prepared_loopback_stream_brokers_.push(std::move(broker));
+ }
+
+ std::unique_ptr<AudioStreamBroker> CreateAudioInputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
+ final {
+ std::unique_ptr<MockBroker> prepared_broker =
+ std::move(prepared_input_stream_brokers_.front());
+ prepared_input_stream_brokers_.pop();
+ CHECK_NE(nullptr, prepared_broker.get());
+ EXPECT_EQ(render_process_id, prepared_broker->render_process_id());
+ EXPECT_EQ(render_frame_id, prepared_broker->render_frame_id());
+ prepared_broker->deleter = std::move(deleter);
+ return std::move(prepared_broker);
+ }
+
+ std::unique_ptr<AudioStreamBroker> CreateAudioOutputStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id,
+ AudioStreamBroker::DeleterCallback deleter,
+ media::mojom::AudioOutputStreamProviderClientPtr client) final {
+ std::unique_ptr<MockBroker> prepared_broker =
+ std::move(prepared_output_stream_brokers_.front());
+ prepared_output_stream_brokers_.pop();
+ CHECK_NE(nullptr, prepared_broker.get());
+ EXPECT_EQ(render_process_id, prepared_broker->render_process_id());
+ EXPECT_EQ(render_frame_id, prepared_broker->render_frame_id());
+ prepared_broker->deleter = std::move(deleter);
+ return std::move(prepared_broker);
+ }
+
+ std::unique_ptr<AudioStreamBroker> CreateAudioLoopbackStreamBroker(
+ int render_process_id,
+ int render_frame_id,
+ std::unique_ptr<LoopbackSource> source,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool mute_source,
+ AudioStreamBroker::DeleterCallback deleter,
+ mojom::RendererAudioInputStreamFactoryClientPtr renderer_factory_client)
+ final {
+ std::unique_ptr<MockBroker> prepared_broker =
+ std::move(prepared_loopback_stream_brokers_.front());
+ prepared_loopback_stream_brokers_.pop();
+ CHECK_NE(nullptr, prepared_broker.get());
+ EXPECT_EQ(render_process_id, prepared_broker->render_process_id());
+ EXPECT_EQ(render_frame_id, prepared_broker->render_frame_id());
+ prepared_broker->deleter = std::move(deleter);
+ return std::move(prepared_broker);
+ }
+
+ private:
+ base::queue<std::unique_ptr<MockBroker>> prepared_loopback_stream_brokers_;
+ base::queue<std::unique_ptr<MockBroker>> prepared_input_stream_brokers_;
+ base::queue<std::unique_ptr<MockBroker>> prepared_output_stream_brokers_;
+ DISALLOW_COPY_AND_ASSIGN(MockBrokerFactory);
+};
+
+class ForwardingAudioStreamFactoryTest : public RenderViewHostTestHarness {
+ public:
+ ForwardingAudioStreamFactoryTest()
+ : connector_(service_manager::Connector::Create(&connector_request_)),
+ broker_factory_(std::make_unique<MockBrokerFactory>()) {
+ service_manager::Connector::TestApi connector_test_api(connector_.get());
+ connector_test_api.OverrideBinderForTesting(
+ service_manager::Identity(audio::mojom::kServiceName),
+ audio::mojom::StreamFactory::Name_,
+ base::BindRepeating(&ForwardingAudioStreamFactoryTest::BindFactory,
+ base::Unretained(this)));
+ }
+
+ ~ForwardingAudioStreamFactoryTest() override {}
+
+ void SetUp() override {
+ RenderViewHostTestHarness::SetUp();
+ RenderFrameHostTester::For(main_rfh())->InitializeRenderFrameIfNeeded();
+ other_rfh_ =
+ RenderFrameHostTester::For(main_rfh())->AppendChild("other_rfh");
+ }
+
+ void BindFactory(mojo::ScopedMessagePipeHandle factory_request) {
+ stream_factory_.binding_.Bind(
+ audio::mojom::StreamFactoryRequest(std::move(factory_request)));
+ }
+
+ base::WeakPtr<MockBroker> ExpectLoopbackBrokerConstruction(
+ RenderFrameHost* rfh) {
+ auto broker = std::make_unique<StrictMock<MockBroker>>(rfh);
+ auto weak_broker = broker->GetWeakPtr();
+ broker_factory_->ExpectLoopbackStreamBrokerCreation(std::move(broker));
+ return weak_broker;
+ }
+
+ base::WeakPtr<MockBroker> ExpectInputBrokerConstruction(
+ RenderFrameHost* rfh) {
+ auto broker = std::make_unique<StrictMock<MockBroker>>(rfh);
+ auto weak_broker = broker->GetWeakPtr();
+ broker_factory_->ExpectInputStreamBrokerCreation(std::move(broker));
+ return weak_broker;
+ }
+
+ base::WeakPtr<MockBroker> ExpectOutputBrokerConstruction(
+ RenderFrameHost* rfh) {
+ auto broker = std::make_unique<StrictMock<MockBroker>>(rfh);
+ auto weak_broker = broker->GetWeakPtr();
+ broker_factory_->ExpectOutputStreamBrokerCreation(std::move(broker));
+ return weak_broker;
+ }
+
+ RenderFrameHost* other_rfh() { return other_rfh_; }
+
+ static const char kInputDeviceId[];
+ static const char kOutputDeviceId[];
+ static const media::AudioParameters kParams;
+ static const uint32_t kSharedMemoryCount;
+ static const bool kEnableAgc;
+ MockStreamFactory stream_factory_;
+ service_manager::mojom::ConnectorRequest connector_request_;
+ std::unique_ptr<service_manager::Connector> connector_;
+ RenderFrameHost* other_rfh_;
+ std::unique_ptr<MockBrokerFactory> broker_factory_;
+};
+
+const char ForwardingAudioStreamFactoryTest::kInputDeviceId[] =
+ "test input device id";
+const char ForwardingAudioStreamFactoryTest::kOutputDeviceId[] =
+ "test output device id";
+const media::AudioParameters ForwardingAudioStreamFactoryTest::kParams =
+ media::AudioParameters::UnavailableDeviceParams();
+const uint32_t ForwardingAudioStreamFactoryTest::kSharedMemoryCount = 10;
+const bool ForwardingAudioStreamFactoryTest::kEnableAgc = false;
+const bool kMuteSource = true;
+
+} // namespace
+
+TEST_F(ForwardingAudioStreamFactoryTest, CreateInputStream_CreatesInputStream) {
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ base::WeakPtr<MockBroker> broker = ExpectInputBrokerConstruction(main_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ EXPECT_CALL(*broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc, std::move(client));
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ CreateLoopbackStream_CreatesLoopbackStream) {
+ std::unique_ptr<WebContents> source_contents = CreateTestWebContents();
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ base::WeakPtr<MockBroker> broker =
+ ExpectLoopbackBrokerConstruction(main_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ EXPECT_CALL(*broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateLoopbackStream(main_rfh(), source_contents->GetMainFrame(),
+ kParams, kSharedMemoryCount, kMuteSource,
+ std::move(client));
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ CreateOutputStream_CreatesOutputStream) {
+ media::mojom::AudioOutputStreamProviderClientPtr client;
+ base::WeakPtr<MockBroker> broker = ExpectOutputBrokerConstruction(main_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ EXPECT_CALL(*broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(client));
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ InputBrokerDeleterCalled_DestroysInputStream) {
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ base::WeakPtr<MockBroker> main_rfh_broker =
+ ExpectInputBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_broker =
+ ExpectInputBrokerConstruction(other_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ {
+ EXPECT_CALL(*main_rfh_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc,
+ std::move(client));
+ testing::Mock::VerifyAndClear(&*main_rfh_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateInputStream(other_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc,
+ std::move(client));
+ testing::Mock::VerifyAndClear(&*other_rfh_broker);
+ }
+
+ std::move(other_rfh_broker->deleter).Run(&*other_rfh_broker);
+ EXPECT_FALSE(other_rfh_broker)
+ << "Input broker should be destructed when deleter is called.";
+ EXPECT_TRUE(main_rfh_broker);
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ LoopbackBrokerDeleterCalled_DestroysInputStream) {
+ std::unique_ptr<WebContents> source_contents = CreateTestWebContents();
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ base::WeakPtr<MockBroker> main_rfh_broker =
+ ExpectLoopbackBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_broker =
+ ExpectLoopbackBrokerConstruction(other_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ {
+ EXPECT_CALL(*main_rfh_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateLoopbackStream(main_rfh(), source_contents->GetMainFrame(),
+ kParams, kSharedMemoryCount, kMuteSource,
+ std::move(client));
+ testing::Mock::VerifyAndClear(&*main_rfh_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateLoopbackStream(other_rfh(), source_contents->GetMainFrame(),
+ kParams, kSharedMemoryCount, kMuteSource,
+ std::move(client));
+ testing::Mock::VerifyAndClear(&*other_rfh_broker);
+ }
+
+ std::move(other_rfh_broker->deleter).Run(&*other_rfh_broker);
+ EXPECT_FALSE(other_rfh_broker)
+ << "Loopback broker should be destructed when deleter is called.";
+ EXPECT_TRUE(main_rfh_broker);
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ OutputBrokerDeleterCalled_DestroysOutputStream) {
+ media::mojom::AudioOutputStreamProviderClientPtr client;
+ base::WeakPtr<MockBroker> main_rfh_broker =
+ ExpectOutputBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_broker =
+ ExpectOutputBrokerConstruction(other_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ {
+ EXPECT_CALL(*main_rfh_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(client));
+ testing::Mock::VerifyAndClear(&*main_rfh_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateOutputStream(other_rfh(), kOutputDeviceId, kParams,
+ std::move(client));
+ testing::Mock::VerifyAndClear(&*other_rfh_broker);
+ }
+
+ std::move(other_rfh_broker->deleter).Run(&*other_rfh_broker);
+ EXPECT_FALSE(other_rfh_broker)
+ << "Output broker should be destructed when deleter is called.";
+ EXPECT_TRUE(main_rfh_broker);
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest, DestroyFrame_DestroysRelatedStreams) {
+ std::unique_ptr<WebContents> source_contents = CreateTestWebContents();
+
+ mojom::RendererAudioInputStreamFactoryClientPtr input_client;
+ base::WeakPtr<MockBroker> main_rfh_input_broker =
+ ExpectInputBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_input_broker =
+ ExpectInputBrokerConstruction(other_rfh());
+
+ base::WeakPtr<MockBroker> main_rfh_loopback_broker =
+ ExpectLoopbackBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_loopback_broker =
+ ExpectLoopbackBrokerConstruction(other_rfh());
+
+ media::mojom::AudioOutputStreamProviderClientPtr output_client;
+ base::WeakPtr<MockBroker> main_rfh_output_broker =
+ ExpectOutputBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_output_broker =
+ ExpectOutputBrokerConstruction(other_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ {
+ EXPECT_CALL(*main_rfh_input_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&input_client);
+ factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc,
+ std::move(input_client));
+ testing::Mock::VerifyAndClear(&*main_rfh_input_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_input_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&input_client);
+ factory.CreateInputStream(other_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc,
+ std::move(input_client));
+ testing::Mock::VerifyAndClear(&*other_rfh_input_broker);
+ }
+
+ {
+ EXPECT_CALL(*main_rfh_loopback_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&input_client);
+ factory.CreateLoopbackStream(main_rfh(), source_contents->GetMainFrame(),
+ kParams, kSharedMemoryCount, kMuteSource,
+ std::move(input_client));
+ testing::Mock::VerifyAndClear(&*main_rfh_loopback_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_loopback_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&input_client);
+ factory.CreateLoopbackStream(other_rfh(), source_contents->GetMainFrame(),
+ kParams, kSharedMemoryCount, kMuteSource,
+ std::move(input_client));
+ testing::Mock::VerifyAndClear(&*other_rfh_loopback_broker);
+ }
+
+ {
+ EXPECT_CALL(*main_rfh_output_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&output_client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(output_client));
+ testing::Mock::VerifyAndClear(&*main_rfh_output_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_output_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&output_client);
+ factory.CreateOutputStream(other_rfh(), kOutputDeviceId, kParams,
+ std::move(output_client));
+ testing::Mock::VerifyAndClear(&*other_rfh_output_broker);
+ }
+
+ factory.FrameDeleted(other_rfh());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(other_rfh_input_broker)
+ << "Input broker should be destructed when owning frame is destructed.";
+ EXPECT_TRUE(main_rfh_input_broker);
+ EXPECT_FALSE(other_rfh_loopback_broker) << "Loopback broker should be "
+ "destructed when owning frame is "
+ "destructed.";
+ EXPECT_TRUE(main_rfh_loopback_broker);
+ EXPECT_FALSE(other_rfh_output_broker)
+ << "Output broker should be destructed when owning frame is destructed.";
+ EXPECT_TRUE(main_rfh_output_broker);
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest, DestroyWebContents_DestroysStreams) {
+ mojom::RendererAudioInputStreamFactoryClientPtr input_client;
+ base::WeakPtr<MockBroker> input_broker =
+ ExpectInputBrokerConstruction(main_rfh());
+
+ media::mojom::AudioOutputStreamProviderClientPtr output_client;
+ base::WeakPtr<MockBroker> output_broker =
+ ExpectOutputBrokerConstruction(main_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ EXPECT_CALL(*input_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&input_client);
+ factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc,
+ std::move(input_client));
+
+ EXPECT_CALL(*output_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&output_client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(output_client));
+
+ DeleteContents();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(input_broker) << "Input broker should be destructed when owning "
+ "WebContents is destructed.";
+ EXPECT_FALSE(output_broker)
+ << "Output broker should be destructed when owning "
+ "WebContents is destructed.";
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest, LastStreamDeleted_ClearsFactoryPtr) {
+ mojom::RendererAudioInputStreamFactoryClientPtr input_client;
+ base::WeakPtr<MockBroker> main_rfh_input_broker =
+ ExpectInputBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_input_broker =
+ ExpectInputBrokerConstruction(other_rfh());
+
+ media::mojom::AudioOutputStreamProviderClientPtr output_client;
+ base::WeakPtr<MockBroker> main_rfh_output_broker =
+ ExpectOutputBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> other_rfh_output_broker =
+ ExpectOutputBrokerConstruction(other_rfh());
+
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ {
+ EXPECT_CALL(*main_rfh_input_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&input_client);
+ factory.CreateInputStream(main_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc,
+ std::move(input_client));
+ testing::Mock::VerifyAndClear(&*main_rfh_input_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_input_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&input_client);
+ factory.CreateInputStream(other_rfh(), kInputDeviceId, kParams,
+ kSharedMemoryCount, kEnableAgc,
+ std::move(input_client));
+ testing::Mock::VerifyAndClear(&*other_rfh_input_broker);
+ }
+
+ {
+ EXPECT_CALL(*main_rfh_output_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&output_client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(output_client));
+ testing::Mock::VerifyAndClear(&*main_rfh_output_broker);
+ }
+ {
+ EXPECT_CALL(*other_rfh_output_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&output_client);
+ factory.CreateOutputStream(other_rfh(), kOutputDeviceId, kParams,
+ std::move(output_client));
+ testing::Mock::VerifyAndClear(&*other_rfh_output_broker);
+ }
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ std::move(other_rfh_input_broker->deleter).Run(&*other_rfh_input_broker);
+ base::RunLoop().RunUntilIdle();
+ // Connection should still be open, since there are still streams left.
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ std::move(main_rfh_input_broker->deleter).Run(&*main_rfh_input_broker);
+ base::RunLoop().RunUntilIdle();
+ // Connection should still be open, since there are still streams left.
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ std::move(other_rfh_output_broker->deleter).Run(&*other_rfh_output_broker);
+ base::RunLoop().RunUntilIdle();
+ // Connection should still be open, since there's still a stream left.
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ std::move(main_rfh_output_broker->deleter).Run(&*main_rfh_output_broker);
+ base::RunLoop().RunUntilIdle();
+ // Now there are no streams left, connection should be broken.
+ EXPECT_FALSE(stream_factory_.IsConnected());
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ MuteNoOutputStreams_DoesNotConnectMuter) {
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+ EXPECT_FALSE(factory.IsMuted());
+
+ factory.SetMuted(true);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_FALSE(stream_factory_.IsConnected());
+ EXPECT_FALSE(stream_factory_.IsMuterConnected());
+
+ factory.SetMuted(false);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(factory.IsMuted());
+ EXPECT_FALSE(stream_factory_.IsConnected());
+ EXPECT_FALSE(stream_factory_.IsMuterConnected());
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest, MuteWithOutputStream_ConnectsMuter) {
+ media::mojom::AudioOutputStreamProviderClientPtr client;
+ base::WeakPtr<MockBroker> broker = ExpectOutputBrokerConstruction(main_rfh());
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ EXPECT_CALL(*broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(client));
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClear(&*broker);
+
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_FALSE(factory.IsMuted());
+
+ factory.SetMuted(true);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_TRUE(stream_factory_.IsMuterConnected());
+
+ factory.SetMuted(false);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(factory.IsMuted());
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_FALSE(stream_factory_.IsMuterConnected());
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ WhenMuting_ConnectedWhenOutputStreamExists) {
+ media::mojom::AudioOutputStreamProviderClientPtr client;
+ base::WeakPtr<MockBroker> broker = ExpectOutputBrokerConstruction(main_rfh());
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ EXPECT_FALSE(stream_factory_.IsConnected());
+ EXPECT_FALSE(factory.IsMuted());
+
+ factory.SetMuted(true);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_FALSE(stream_factory_.IsConnected());
+ EXPECT_FALSE(stream_factory_.IsMuterConnected());
+
+ EXPECT_CALL(*broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(client));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_TRUE(stream_factory_.IsMuterConnected());
+ testing::Mock::VerifyAndClear(&*broker);
+
+ std::move(broker->deleter).Run(&*broker);
+ EXPECT_FALSE(broker);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_FALSE(stream_factory_.IsConnected());
+ EXPECT_FALSE(stream_factory_.IsMuterConnected());
+}
+
+TEST_F(ForwardingAudioStreamFactoryTest,
+ WhenMuting_AddRemoveSecondStream_DoesNotChangeMuting) {
+ media::mojom::AudioOutputStreamProviderClientPtr client;
+ base::WeakPtr<MockBroker> broker = ExpectOutputBrokerConstruction(main_rfh());
+ base::WeakPtr<MockBroker> another_broker =
+ ExpectOutputBrokerConstruction(main_rfh());
+ ForwardingAudioStreamFactory factory(web_contents(), std::move(connector_),
+ std::move(broker_factory_));
+
+ {
+ EXPECT_CALL(*broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(client));
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClear(&*broker);
+ }
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_FALSE(factory.IsMuted());
+
+ factory.SetMuted(true);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_TRUE(stream_factory_.IsMuterConnected());
+
+ {
+ EXPECT_CALL(*another_broker, CreateStream(NotNull()));
+ mojo::MakeRequest(&client);
+ factory.CreateOutputStream(main_rfh(), kOutputDeviceId, kParams,
+ std::move(client));
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClear(&*another_broker);
+ }
+
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_TRUE(stream_factory_.IsMuterConnected());
+
+ std::move(another_broker->deleter).Run(&*another_broker);
+ EXPECT_FALSE(another_broker);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(factory.IsMuted());
+ EXPECT_TRUE(stream_factory_.IsConnected());
+ EXPECT_TRUE(stream_factory_.IsMuterConnected());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/key_system_support_impl.cc b/chromium/content/browser/media/key_system_support_impl.cc
index 0092ef764f1..414da641e76 100644
--- a/chromium/content/browser/media/key_system_support_impl.cc
+++ b/chromium/content/browser/media/key_system_support_impl.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "base/containers/flat_set.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "content/public/browser/cdm_registry.h"
@@ -62,13 +63,16 @@ void KeySystemSupportImpl::IsKeySystemSupported(
std::unique_ptr<CdmInfo> cdm = GetCdmInfoForKeySystem(key_system);
if (!cdm) {
SendCdmAvailableUMA(key_system, false);
- std::move(callback).Run(false, {}, false);
+ std::move(callback).Run(false, {}, false, {});
return;
}
+ const base::flat_set<media::EncryptionMode>& schemes =
+ cdm->supported_encryption_schemes;
SendCdmAvailableUMA(key_system, true);
- std::move(callback).Run(true, cdm->supported_video_codecs,
- cdm->supports_persistent_license);
+ std::move(callback).Run(
+ true, cdm->supported_video_codecs, cdm->supports_persistent_license,
+ std::vector<media::EncryptionMode>(schemes.begin(), schemes.end()));
}
} // namespace content
diff --git a/chromium/content/browser/media/key_system_support_impl_unittest.cc b/chromium/content/browser/media/key_system_support_impl_unittest.cc
index 719dcf29eec..aa3134ae60e 100644
--- a/chromium/content/browser/media/key_system_support_impl_unittest.cc
+++ b/chromium/content/browser/media/key_system_support_impl_unittest.cc
@@ -14,6 +14,7 @@
#include "content/public/common/cdm_info.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -39,24 +40,16 @@ class KeySystemSupportTest : public testing::Test {
// |supports_persistent_license|. All other values for CdmInfo have some
// default value as they're not returned by IsKeySystemSupported().
void Register(const std::string& key_system,
- const std::vector<media::VideoCodec> supported_video_codecs,
- bool supports_persistent_license) {
+ const std::vector<media::VideoCodec>& supported_video_codecs,
+ bool supports_persistent_license,
+ const base::flat_set<media::EncryptionMode>& supported_modes) {
DVLOG(1) << __func__;
CdmRegistry::GetInstance()->RegisterCdm(
CdmInfo(key_system, kTestCdmGuid, base::Version(kVersion),
base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId,
- supported_video_codecs, supports_persistent_license, key_system,
- false));
-
- // As IsKeySystemSupported() checks for the matching pepper plugin,
- // register a dummy one.
- // TODO(crbug.com/772160) Remove this when pepper CDM support removed.
- PluginService::GetInstance()->RegisterInternalPlugin(
- WebPluginInfo(base::ASCIIToUTF16(key_system),
- base::FilePath::FromUTF8Unsafe(kTestPath),
- base::ASCIIToUTF16(kVersion), base::string16()),
- true);
+ supported_video_codecs, supports_persistent_license,
+ supported_modes, key_system, false));
}
// Determines if |key_system| is registered. If it is, updates |codecs_|
@@ -65,7 +58,8 @@ class KeySystemSupportTest : public testing::Test {
DVLOG(1) << __func__;
bool is_available = false;
key_system_support_->IsKeySystemSupported(key_system, &is_available,
- &codecs_, &persistent_);
+ &codecs_, &persistent_,
+ &encryption_schemes_);
return is_available;
}
@@ -75,6 +69,7 @@ class KeySystemSupportTest : public testing::Test {
// Updated by IsSupported().
std::vector<media::VideoCodec> codecs_;
bool persistent_;
+ std::vector<media::EncryptionMode> encryption_schemes_;
};
// Note that as CdmRegistry::GetInstance() is a static, it is shared between
@@ -86,30 +81,41 @@ TEST_F(KeySystemSupportTest, NoKeySystems) {
}
TEST_F(KeySystemSupportTest, OneKeySystem) {
- Register("KeySystem2", {media::VideoCodec::kCodecVP8}, true);
+ Register("KeySystem2", {media::VideoCodec::kCodecVP8}, true,
+ {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs});
EXPECT_TRUE(IsSupported("KeySystem2"));
EXPECT_EQ(1u, codecs_.size());
EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]);
EXPECT_TRUE(persistent_);
+ EXPECT_EQ(2u, encryption_schemes_.size());
+ EXPECT_EQ(media::EncryptionMode::kCenc, encryption_schemes_[0]);
+ EXPECT_EQ(media::EncryptionMode::kCbcs, encryption_schemes_[1]);
}
TEST_F(KeySystemSupportTest, MultipleKeySystems) {
Register("KeySystem3",
- {media::VideoCodec::kCodecVP8, media::VideoCodec::kCodecVP9}, true);
- Register("KeySystem4", {media::VideoCodec::kCodecVP9}, false);
+ {media::VideoCodec::kCodecVP8, media::VideoCodec::kCodecVP9}, true,
+ {media::EncryptionMode::kCenc});
+ Register("KeySystem4", {media::VideoCodec::kCodecVP9}, false,
+ {media::EncryptionMode::kCbcs});
EXPECT_TRUE(IsSupported("KeySystem3"));
EXPECT_EQ(2u, codecs_.size());
EXPECT_EQ(media::VideoCodec::kCodecVP8, codecs_[0]);
EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[1]);
EXPECT_TRUE(persistent_);
+ EXPECT_EQ(1u, encryption_schemes_.size());
+ EXPECT_EQ(media::EncryptionMode::kCenc, encryption_schemes_[0]);
EXPECT_TRUE(IsSupported("KeySystem4"));
EXPECT_EQ(1u, codecs_.size());
EXPECT_EQ(media::VideoCodec::kCodecVP9, codecs_[0]);
EXPECT_FALSE(persistent_);
+ EXPECT_EQ(1u, encryption_schemes_.size());
+ EXPECT_EQ(media::EncryptionMode::kCbcs, encryption_schemes_[0]);
}
TEST_F(KeySystemSupportTest, MissingKeySystem) {
- Register("KeySystem5", {media::VideoCodec::kCodecVP8}, true);
+ Register("KeySystem5", {media::VideoCodec::kCodecVP8}, true,
+ {media::EncryptionMode::kCenc});
EXPECT_FALSE(IsSupported("KeySystem6"));
}
diff --git a/chromium/content/browser/media/keyboard_mic_registration.cc b/chromium/content/browser/media/keyboard_mic_registration.cc
new file mode 100644
index 00000000000..785f6d3fa7f
--- /dev/null
+++ b/chromium/content/browser/media/keyboard_mic_registration.cc
@@ -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.
+
+#include "content/browser/media/keyboard_mic_registration.h"
+
+#include "chromeos/audio/cras_audio_handler.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+KeyboardMicRegistration::KeyboardMicRegistration() = default;
+
+KeyboardMicRegistration::~KeyboardMicRegistration() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_EQ(0, register_count_);
+}
+
+void KeyboardMicRegistration::Register() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (++register_count_ == 1)
+ chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(true);
+}
+
+void KeyboardMicRegistration::Deregister() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (--register_count_ == 0)
+ chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(false);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/keyboard_mic_registration.h b/chromium/content/browser/media/keyboard_mic_registration.h
new file mode 100644
index 00000000000..267d0dee1ce
--- /dev/null
+++ b/chromium/content/browser/media/keyboard_mic_registration.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 CONTENT_BROWSER_MEDIA_KEYBOARD_MIC_REGISTRATION_H_
+#define CONTENT_BROWSER_MEDIA_KEYBOARD_MIC_REGISTRATION_H_
+
+#include "base/macros.h"
+
+namespace content {
+
+// Chrome OS keyboard mic stream registration. Used on UI thread only and owned
+// by BrowserMainLoop; instance must be obtained through
+// BrowserMainLoop::keyboard_mic_registration().
+class KeyboardMicRegistration {
+ public:
+ KeyboardMicRegistration();
+ ~KeyboardMicRegistration();
+
+ void Register();
+ void Deregister();
+
+ private:
+ int register_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardMicRegistration);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_KEYBOARD_MIC_REGISTRATION_H_
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index 11bfbc8548e..f6706151c8f 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -15,7 +15,7 @@
#include "content/shell/browser/shell.h"
#include "media/base/media_switches.h"
#include "media/media_buildflags.h"
-#include "third_party/libaom/av1_features.h"
+#include "third_party/libaom/av1_buildflags.h"
#include "ui/display/display_switches.h"
#if defined(OS_ANDROID)
diff --git a/chromium/content/browser/media/media_devices_util.cc b/chromium/content/browser/media/media_devices_util.cc
index 9440bc7f4b7..58badef2512 100644
--- a/chromium/content/browser/media/media_devices_util.cc
+++ b/chromium/content/browser/media/media_devices_util.cc
@@ -13,10 +13,12 @@
#include "base/strings/string_tokenizer.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/common/media_stream_request.h"
#include "media/base/media_switches.h"
@@ -91,6 +93,15 @@ std::string GetDefaultMediaDeviceIDFromCommandLine(
} // namespace
+MediaDeviceSaltAndOrigin::MediaDeviceSaltAndOrigin() = default;
+
+MediaDeviceSaltAndOrigin::MediaDeviceSaltAndOrigin(std::string device_id_salt,
+ std::string group_id_salt,
+ url::Origin origin)
+ : device_id_salt(std::move(device_id_salt)),
+ group_id_salt(std::move(group_id_salt)),
+ origin(std::move(origin)) {}
+
void GetDefaultMediaDeviceID(
MediaDeviceType device_type,
int render_process_id,
@@ -113,46 +124,55 @@ void GetDefaultMediaDeviceID(
callback);
}
-std::pair<std::string, url::Origin> GetMediaDeviceSaltAndOrigin(
- int render_process_id,
- int render_frame_id) {
+MediaDeviceSaltAndOrigin GetMediaDeviceSaltAndOrigin(int render_process_id,
+ int render_frame_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHost* frame_host =
RenderFrameHost::FromID(render_process_id, render_frame_id);
RenderProcessHost* process_host =
RenderProcessHost::FromID(render_process_id);
- return std::make_pair(
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderFrameHost(frame_host));
+
+ std::string device_id_salt =
process_host ? process_host->GetBrowserContext()->GetMediaDeviceIDSalt()
- : std::string(),
- frame_host ? frame_host->GetLastCommittedOrigin() : url::Origin());
+ : std::string();
+ std::string group_id_salt =
+ device_id_salt + (web_contents
+ ? web_contents->GetMediaDeviceGroupIDSaltBase()
+ : std::string());
+ url::Origin origin =
+ frame_host ? frame_host->GetLastCommittedOrigin() : url::Origin();
+
+ return {std::move(device_id_salt), std::move(group_id_salt),
+ std::move(origin)};
}
-MediaDeviceInfo TranslateMediaDeviceInfo(bool has_permission,
- const std::string& device_id_salt,
- const std::string& group_id_salt,
- const url::Origin& security_origin,
- const MediaDeviceInfo& device_info) {
+MediaDeviceInfo TranslateMediaDeviceInfo(
+ bool has_permission,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
+ const MediaDeviceInfo& device_info) {
return MediaDeviceInfo(
- GetHMACForMediaDeviceID(device_id_salt, security_origin,
- device_info.device_id),
+ GetHMACForMediaDeviceID(salt_and_origin.device_id_salt,
+ salt_and_origin.origin, device_info.device_id),
has_permission ? device_info.label : std::string(),
device_info.group_id.empty()
? std::string()
- : GetHMACForMediaDeviceID(group_id_salt, security_origin,
- device_info.group_id));
+ : GetHMACForMediaDeviceID(salt_and_origin.group_id_salt,
+ salt_and_origin.origin,
+ device_info.group_id),
+ has_permission ? device_info.video_facing
+ : media::MEDIA_VIDEO_FACING_NONE);
}
MediaDeviceInfoArray TranslateMediaDeviceInfoArray(
bool has_permission,
- const std::string& device_id_salt,
- const std::string& group_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
const MediaDeviceInfoArray& device_infos) {
MediaDeviceInfoArray result;
for (const auto& device_info : device_infos) {
- result.push_back(TranslateMediaDeviceInfo(has_permission, device_id_salt,
- group_id_salt, security_origin,
- device_info));
+ result.push_back(
+ TranslateMediaDeviceInfo(has_permission, salt_and_origin, device_info));
}
return result;
}
diff --git a/chromium/content/browser/media/media_devices_util.h b/chromium/content/browser/media/media_devices_util.h
index c43e6909617..d2a02ef498e 100644
--- a/chromium/content/browser/media/media_devices_util.h
+++ b/chromium/content/browser/media/media_devices_util.h
@@ -17,45 +17,52 @@ namespace content {
// Returns the ID of the user-default device ID via |callback|.
// If no such device ID can be found, |callback| receives an empty string.
-void CONTENT_EXPORT GetDefaultMediaDeviceID(
+CONTENT_EXPORT void GetDefaultMediaDeviceID(
MediaDeviceType device_type,
int render_process_id,
int render_frame_id,
const base::Callback<void(const std::string&)>& callback);
+struct CONTENT_EXPORT MediaDeviceSaltAndOrigin {
+ MediaDeviceSaltAndOrigin();
+ MediaDeviceSaltAndOrigin(std::string device_id_salt,
+ std::string group_id_salt,
+ url::Origin origin);
+
+ std::string device_id_salt;
+ std::string group_id_salt;
+ url::Origin origin;
+};
+
// Returns the current media device ID salt and security origin for the given
// |render_process_id| and |render_frame_id|. These values are used to produce
// unique media-device IDs for each origin and renderer process. These values
// should not be cached since the user can explicitly change them at any time.
// This function must run on the UI thread.
-std::pair<std::string, url::Origin> GetMediaDeviceSaltAndOrigin(
- int render_process_id,
- int render_frame_id);
+MediaDeviceSaltAndOrigin GetMediaDeviceSaltAndOrigin(int render_process_id,
+ int render_frame_id);
// Returns a translated version of |device_info| suitable for use in a renderer
// process.
// The |device_id| field is hashed using |device_id_salt| and |security_origin|.
// The |group_id| field is hashed using |group_id_salt| and |security_origin|.
// The |label| field is removed if |has_permission| is false.
-MediaDeviceInfo TranslateMediaDeviceInfo(bool has_permission,
- const std::string& device_id_salt,
- const std::string& group_id_salt,
- const url::Origin& security_origin,
- const MediaDeviceInfo& device_info);
+MediaDeviceInfo TranslateMediaDeviceInfo(
+ bool has_permission,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
+ const MediaDeviceInfo& device_info);
// Returns a translated version of |device_infos|, with each element translated
// using TranslateMediaDeviceInfo().
MediaDeviceInfoArray TranslateMediaDeviceInfoArray(
bool has_permission,
- const std::string& device_id_salt,
- const std::string& group_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
const MediaDeviceInfoArray& device_infos);
// Type definition to make it easier to use mock alternatives to
// GetMediaDeviceSaltAndOrigin.
using MediaDeviceSaltAndOriginCallback =
- base::RepeatingCallback<std::pair<std::string, url::Origin>(int, int)>;
+ base::RepeatingCallback<MediaDeviceSaltAndOrigin(int, int)>;
} // namespace content
diff --git a/chromium/content/browser/media/media_interface_proxy.cc b/chromium/content/browser/media/media_interface_proxy.cc
index 31bf2c0f4d8..82b0c8c61ac 100644
--- a/chromium/content/browser/media/media_interface_proxy.cc
+++ b/chromium/content/browser/media/media_interface_proxy.cc
@@ -27,7 +27,7 @@
#include "content/public/browser/provision_fetcher_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
-#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#endif
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
@@ -46,6 +46,7 @@
#if defined(OS_ANDROID)
#include "content/browser/media/android/media_player_renderer.h"
+#include "content/browser/media/flinging_renderer.h"
#include "media/mojo/services/mojo_renderer_service.h" // nogncheck
#endif
@@ -161,6 +162,17 @@ void MediaInterfaceProxy::CreateRenderer(
CreateMediaPlayerRenderer(std::move(request));
return;
}
+
+ if (type == media::mojom::HostedRendererType::kFlinging) {
+ std::unique_ptr<FlingingRenderer> renderer =
+ FlingingRenderer::Create(render_frame_host_, type_specific_id);
+
+ media::MojoRendererService::Create(
+ nullptr, std::move(renderer),
+ media::MojoRendererService::InitiateSurfaceRequestCB(),
+ std::move(request));
+ return;
+ }
#endif
InterfaceFactory* factory = GetMediaInterfaceFactory();
@@ -183,6 +195,14 @@ void MediaInterfaceProxy::CreateCdm(
#endif
}
+void MediaInterfaceProxy::CreateDecryptor(
+ int cdm_id,
+ media::mojom::DecryptorRequest request) {
+ InterfaceFactory* factory = GetMediaInterfaceFactory();
+ if (factory)
+ factory->CreateDecryptor(cdm_id, std::move(request));
+}
+
void MediaInterfaceProxy::CreateCdmProxy(
const std::string& cdm_guid,
media::mojom::CdmProxyRequest request) {
@@ -202,12 +222,12 @@ MediaInterfaceProxy::GetFrameServices(const std::string& cdm_guid,
#if BUILDFLAG(ENABLE_MOJO_CDM)
// TODO(slan): Wrap these into a RenderFrame specific ProvisionFetcher impl.
- net::URLRequestContextGetter* context_getter =
- BrowserContext::GetDefaultStoragePartition(
- render_frame_host_->GetProcess()->GetBrowserContext())
- ->GetURLRequestContext();
provider->registry()->AddInterface(base::BindRepeating(
- &ProvisionFetcherImpl::Create, base::RetainedRef(context_getter)));
+ &ProvisionFetcherImpl::Create,
+ base::RetainedRef(
+ BrowserContext::GetDefaultStoragePartition(
+ render_frame_host_->GetProcess()->GetBrowserContext())
+ ->GetURLLoaderFactoryForBrowserProcess())));
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
// Only provide CdmStorageImpl when we have a valid |cdm_file_system_id|,
@@ -386,8 +406,8 @@ void MediaInterfaceProxy::CreateMediaPlayerRenderer(
base::BindRepeating(&MediaPlayerRenderer::InitiateScopedSurfaceRequest,
base::Unretained(renderer.get()));
- media::MojoRendererService::Create(std::move(renderer), surface_request_cb,
- std::move(request));
+ media::MojoRendererService::Create(nullptr, std::move(renderer),
+ surface_request_cb, std::move(request));
}
#endif // defined(OS_ANDROID)
diff --git a/chromium/content/browser/media/media_interface_proxy.h b/chromium/content/browser/media/media_interface_proxy.h
index 08b7661a4a2..ce7e4dfb739 100644
--- a/chromium/content/browser/media/media_interface_proxy.h
+++ b/chromium/content/browser/media/media_interface_proxy.h
@@ -51,6 +51,8 @@ class MediaInterfaceProxy : public media::mojom::InterfaceFactory {
media::mojom::RendererRequest request) final;
void CreateCdm(const std::string& key_system,
media::mojom::ContentDecryptionModuleRequest request) final;
+ void CreateDecryptor(int cdm_id,
+ media::mojom::DecryptorRequest request) final;
void CreateCdmProxy(const std::string& cdm_guid,
media::mojom::CdmProxyRequest request) final;
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index 6e58bdce30f..e245a5feada 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -469,7 +469,8 @@ std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream(
uma_name += "DDS.";
}
- if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName) {
+ if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName ||
+ player_info.video_decoder == "MojoVideoDecoder") {
uma_name += "HW";
} else {
uma_name += "SW";
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index 506227d219e..a02bcadfbf0 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -115,38 +115,6 @@ class MediaInternalsVideoCaptureDeviceTest : public testing::Test,
MediaInternals::UpdateCallback update_cb_;
};
-// TODO(chfremer): Consider removing this. This test seem be
-// a duplicate implementation of the functionality under test.
-// https://crbug.com/630694
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
- defined(OS_ANDROID)
-TEST_F(MediaInternalsVideoCaptureDeviceTest,
- AllCaptureApiTypesHaveProperStringRepresentation) {
- using VideoCaptureApi = media::VideoCaptureApi;
- std::map<VideoCaptureApi, std::string> api_to_string_map;
- api_to_string_map[VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE] = "V4L2 SPLANE";
- api_to_string_map[VideoCaptureApi::WIN_MEDIA_FOUNDATION] = "Media Foundation";
- api_to_string_map[VideoCaptureApi::WIN_MEDIA_FOUNDATION_SENSOR] =
- "Media Foundation Sensor Camera";
- api_to_string_map[VideoCaptureApi::WIN_DIRECT_SHOW] = "Direct Show";
- api_to_string_map[VideoCaptureApi::MACOSX_AVFOUNDATION] = "AV Foundation";
- api_to_string_map[VideoCaptureApi::MACOSX_DECKLINK] = "DeckLink";
- api_to_string_map[VideoCaptureApi::ANDROID_API1] = "Camera API1";
- api_to_string_map[VideoCaptureApi::ANDROID_API2_LEGACY] =
- "Camera API2 Legacy";
- api_to_string_map[VideoCaptureApi::ANDROID_API2_FULL] = "Camera API2 Full";
- api_to_string_map[VideoCaptureApi::ANDROID_API2_LIMITED] =
- "Camera API2 Limited";
- EXPECT_EQ(static_cast<size_t>(VideoCaptureApi::UNKNOWN),
- api_to_string_map.size());
- for (const auto& map_entry : api_to_string_map) {
- media::VideoCaptureDeviceDescriptor descriptor;
- descriptor.capture_api = map_entry.first;
- EXPECT_EQ(map_entry.second, descriptor.GetCaptureApiTypeString());
- }
-}
-#endif
-
TEST_F(MediaInternalsVideoCaptureDeviceTest,
VideoCaptureFormatStringIsInExpectedFormat) {
// Since media internals will send video capture capabilities to JavaScript in
@@ -157,14 +125,11 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest,
const float kFrameRate = 30.0f;
const gfx::Size kFrameSize(1280, 720);
const media::VideoPixelFormat kPixelFormat = media::PIXEL_FORMAT_I420;
- const media::VideoPixelStorage kPixelStorage = media::VideoPixelStorage::CPU;
const media::VideoCaptureFormat capture_format(kFrameSize, kFrameRate,
- kPixelFormat, kPixelStorage);
+ kPixelFormat);
const std::string expected_string = base::StringPrintf(
- "(%s)@%.3ffps, pixel format: %s, storage: %s",
- kFrameSize.ToString().c_str(), kFrameRate,
- media::VideoPixelFormatToString(kPixelFormat).c_str(),
- media::VideoCaptureFormat::PixelStorageToString(kPixelStorage).c_str());
+ "(%s)@%.3ffps, pixel format: %s", kFrameSize.ToString().c_str(),
+ kFrameRate, media::VideoPixelFormatToString(kPixelFormat).c_str());
EXPECT_EQ(expected_string,
media::VideoCaptureFormat::ToString(capture_format));
}
@@ -251,7 +216,7 @@ class MediaInternalsAudioLogTest
private:
static media::AudioParameters MakeAudioParams() {
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LINEAR,
- media::CHANNEL_LAYOUT_MONO, 48000, 16, 128);
+ media::CHANNEL_LAYOUT_MONO, 48000, 128);
params.set_effects(media::AudioParameters::ECHO_CANCELLER |
media::AudioParameters::DUCKING);
return params;
diff --git a/chromium/content/browser/media/media_source_browsertest.cc b/chromium/content/browser/media/media_source_browsertest.cc
index e5571a3b16c..5e3cb0006e5 100644
--- a/chromium/content/browser/media/media_source_browsertest.cc
+++ b/chromium/content/browser/media/media_source_browsertest.cc
@@ -24,14 +24,12 @@ const char kWebMOpusAudioOnly[] = "audio/webm; codecs=\"opus\"";
#endif
const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
-
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
const char kMp4FlacAudioOnly[] = "audio/mp4; codecs=\"flac\"";
-#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
+#if BUILDFLAG(USE_PROPRIETARY_CODECS) && \
+ BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
const char kMp2tAudioVideo[] = "video/mp2t; codecs=\"mp4a.40.2, avc1.42E01E\"";
#endif
-#endif
namespace content {
@@ -51,7 +49,6 @@ class MediaSourceTest : public content::MediaBrowserTest {
command_line->AppendSwitchASCII(
switches::kAutoplayPolicy,
switches::autoplay::kNoUserGestureRequiredPolicy);
- scoped_feature_list_.InitAndDisableFeature(media::kMseFlacInIsobmff);
}
protected:
@@ -121,12 +118,11 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Video_WEBM_Audio_MP4) {
true);
}
-IN_PROC_BROWSER_TEST_F(MediaSourceTest,
- Playback_AudioOnly_FLAC_MP4_Unsupported) {
- // The feature is disabled by test setup, so verify playback failure.
- TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, media::kFailed);
+#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
+
+IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_AudioOnly_FLAC_MP4) {
+ TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, media::kEnded);
}
-#endif
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
@@ -136,24 +132,4 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_AudioVideo_Mp2t) {
#endif
#endif
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-class MediaSourceFlacInIsobmffTest : public content::MediaSourceTest {
- public:
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(
- switches::kAutoplayPolicy,
- switches::autoplay::kNoUserGestureRequiredPolicy);
-
- // Enable MSE FLAC-in-MP4 feature.
- scoped_feature_list_.InitAndEnableFeature(media::kMseFlacInIsobmff);
- }
-};
-
-IN_PROC_BROWSER_TEST_F(MediaSourceFlacInIsobmffTest,
- Playback_AudioOnly_FLAC_MP4_Supported) {
- // The feature is enabled by test setup, so verify playback success.
- TestSimplePlayback("bear-flac_frag.mp4", kMp4FlacAudioOnly, media::kEnded);
-}
-#endif
-
} // namespace content
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index 065f2f24773..b3abe26c982 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -9,6 +9,7 @@
#include "build/build_config.h"
#include "content/browser/media/audible_metrics.h"
#include "content/browser/media/audio_stream_monitor.h"
+#include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/browser/render_frame_host.h"
@@ -134,10 +135,13 @@ bool MediaWebContentsObserver::OnMessageReceived(
IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnMediaSizeChanged,
OnMediaSizeChanged)
IPC_MESSAGE_HANDLER(
- MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged,
- OnPictureInPictureSourceChanged)
+ MediaPlayerDelegateHostMsg_OnPictureInPictureModeStarted,
+ OnPictureInPictureModeStarted)
IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnPictureInPictureModeEnded,
OnPictureInPictureModeEnded)
+ IPC_MESSAGE_HANDLER(
+ MediaPlayerDelegateHostMsg_OnPictureInPictureSurfaceChanged,
+ OnPictureInPictureSurfaceChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -145,23 +149,7 @@ bool MediaWebContentsObserver::OnMessageReceived(
void MediaWebContentsObserver::OnVisibilityChanged(
content::Visibility visibility) {
- if (visibility == content::Visibility::HIDDEN) {
- // If there are entities capturing screenshots or video (e.g., mirroring),
- // don't release the wake lock.
- if (!web_contents()->IsBeingCaptured()) {
- GetVideoWakeLock()->CancelWakeLock();
- has_video_wake_lock_for_testing_ = false;
- }
- } else {
- // TODO(ke.he@intel.com): Determine whether a tab should be allowed to
- // request the wake lock when it's occluded.
- DCHECK(visibility == content::Visibility::VISIBLE ||
- visibility == content::Visibility::OCCLUDED);
-
- // Restore wake lock if there are active video players running.
- if (!active_video_players_.empty())
- LockVideo();
- }
+ UpdateVideoLock();
}
void MediaWebContentsObserver::RequestPersistentVideo(bool value) {
@@ -184,15 +172,20 @@ bool MediaWebContentsObserver::IsPlayerActive(
return MediaPlayerEntryExists(player_id, active_audio_players_);
}
+void MediaWebContentsObserver::OnPictureInPictureWindowResize(
+ const gfx::Size& window_size) {
+ DCHECK(pip_player_.has_value());
+
+ RenderFrameHost* frame = pip_player_->first;
+ int delegate_id = pip_player_->second;
+ frame->Send(new MediaPlayerDelegateMsg_OnPictureInPictureWindowResize(
+ frame->GetRoutingID(), delegate_id, window_size));
+}
+
void MediaWebContentsObserver::OnMediaDestroyed(
RenderFrameHost* render_frame_host,
int delegate_id) {
OnMediaPaused(render_frame_host, delegate_id, true);
-
- if (pip_player_ &&
- pip_player_ == MediaPlayerId(render_frame_host, delegate_id)) {
- pip_player_.reset();
- }
}
void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
@@ -203,7 +196,8 @@ void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
RemoveMediaPlayerEntry(player_id, &active_audio_players_);
const bool removed_video =
RemoveMediaPlayerEntry(player_id, &active_video_players_);
- MaybeCancelVideoLock();
+
+ UpdateVideoLock();
if (removed_audio || removed_video) {
// Notify observers the player has been "paused".
@@ -241,9 +235,7 @@ void MediaWebContentsObserver::OnMediaPlaying(
if (has_video) {
AddMediaPlayerEntry(id, &active_video_players_);
- // If we're not hidden and have just created a player, create a wakelock.
- if (!web_contents_impl()->IsHidden())
- LockVideo();
+ UpdateVideoLock();
}
if (!session_controllers_manager_.RequestPlay(
@@ -296,16 +288,61 @@ void MediaWebContentsObserver::OnMediaSizeChanged(
web_contents_impl()->MediaResized(size, id);
}
-void MediaWebContentsObserver::OnPictureInPictureSourceChanged(
+void MediaWebContentsObserver::OnPictureInPictureModeStarted(
RenderFrameHost* render_frame_host,
- int delegate_id) {
+ int delegate_id,
+ const viz::SurfaceId& surface_id,
+ const gfx::Size& natural_size,
+ int request_id) {
+ DCHECK(surface_id.is_valid());
pip_player_ = MediaPlayerId(render_frame_host, delegate_id);
+
+ UpdateVideoLock();
+
+ gfx::Size window_size =
+ web_contents_impl()->EnterPictureInPicture(surface_id, natural_size);
+
+ render_frame_host->Send(
+ new MediaPlayerDelegateMsg_OnPictureInPictureModeStarted_ACK(
+ render_frame_host->GetRoutingID(), delegate_id, request_id,
+ window_size));
}
void MediaWebContentsObserver::OnPictureInPictureModeEnded(
RenderFrameHost* render_frame_host,
- int delegate_id) {
- pip_player_.reset();
+ int delegate_id,
+ int request_id) {
+ // TODO(mlamouri): must be a DCHECK but can't at the moment because we do not
+ // correctly notify players when switching PIP video in the same tab.
+ if (pip_player_) {
+ web_contents_impl()->ExitPictureInPicture();
+
+ // Reset must happen after notifying the WebContents because it may interact
+ // with it.
+ pip_player_.reset();
+
+ UpdateVideoLock();
+ }
+
+ render_frame_host->Send(
+ new MediaPlayerDelegateMsg_OnPictureInPictureModeEnded_ACK(
+ render_frame_host->GetRoutingID(), delegate_id, request_id));
+}
+
+void MediaWebContentsObserver::OnPictureInPictureSurfaceChanged(
+ RenderFrameHost* render_frame_host,
+ int delegate_id,
+ const viz::SurfaceId& surface_id,
+ const gfx::Size& natural_size) {
+ DCHECK(surface_id.is_valid());
+ DCHECK(pip_player_);
+
+ PictureInPictureWindowControllerImpl* pip_controller =
+ PictureInPictureWindowControllerImpl::FromWebContents(
+ web_contents_impl());
+ DCHECK(pip_controller);
+
+ pip_controller->EmbedSurface(surface_id, natural_size);
}
void MediaWebContentsObserver::ClearWakeLocks(
@@ -322,7 +359,7 @@ void MediaWebContentsObserver::ClearWakeLocks(
audio_players.begin(), audio_players.end(),
std::inserter(removed_players, removed_players.end()));
- MaybeCancelVideoLock();
+ UpdateVideoLock();
// Notify all observers the player has been "paused".
for (const auto& id : removed_players) {
@@ -379,21 +416,25 @@ void MediaWebContentsObserver::CancelAudioLock() {
has_audio_wake_lock_for_testing_ = false;
}
-void MediaWebContentsObserver::LockVideo() {
- DCHECK(!active_video_players_.empty());
- GetVideoWakeLock()->RequestWakeLock();
- has_video_wake_lock_for_testing_ = true;
-}
+void MediaWebContentsObserver::UpdateVideoLock() {
+ if (active_video_players_.empty() ||
+ (web_contents()->GetVisibility() == Visibility::HIDDEN &&
+ !web_contents()->IsBeingCaptured() && !pip_player_.has_value())) {
+ // Need to release a wake lock if one is held.
+ if (!has_video_wake_lock_)
+ return;
-void MediaWebContentsObserver::CancelVideoLock() {
- GetVideoWakeLock()->CancelWakeLock();
- has_video_wake_lock_for_testing_ = false;
-}
+ GetVideoWakeLock()->CancelWakeLock();
+ has_video_wake_lock_ = false;
+ return;
+ }
+
+ // Need to take a wake lock if not already done.
+ if (has_video_wake_lock_)
+ return;
-void MediaWebContentsObserver::MaybeCancelVideoLock() {
- // If there are no more video players, cancel the video wake lock.
- if (active_video_players_.empty())
- CancelVideoLock();
+ GetVideoWakeLock()->RequestWakeLock();
+ has_video_wake_lock_ = true;
}
void MediaWebContentsObserver::OnMediaMutedStatusChanged(
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index 7b9f1f1d399..2655629a1da 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -33,6 +33,10 @@ namespace gfx {
class Size;
} // namespace size
+namespace viz {
+class SurfaceId;
+} // namespace viz
+
namespace content {
// This class manages all RenderFrame based media related managers at the
@@ -85,13 +89,16 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
// Returns whether or not the given player id is active.
bool IsPlayerActive(const MediaPlayerId& player_id) const;
+ // Called by the Picture-in-Picture controller when the associated window is
+ // resized. |window_size| represents the new size of the window. It MUST be
+ // called when there is a player in Picture-in-Picture.
+ void OnPictureInPictureWindowResize(const gfx::Size& window_size);
+
bool has_audio_wake_lock_for_testing() const {
return has_audio_wake_lock_for_testing_;
}
- bool has_video_wake_lock_for_testing() const {
- return has_video_wake_lock_for_testing_;
- }
+ bool has_video_wake_lock_for_testing() const { return has_video_wake_lock_; }
protected:
MediaSessionControllersManager* session_controllers_manager() {
@@ -119,10 +126,18 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
void OnMediaMutedStatusChanged(RenderFrameHost* render_frame_host,
int delegate_id,
bool muted);
- void OnPictureInPictureSourceChanged(RenderFrameHost* render_frame_host,
- int delegate_id);
+ void OnPictureInPictureModeStarted(RenderFrameHost* render_frame_host,
+ int delegate_id,
+ const viz::SurfaceId&,
+ const gfx::Size& natural_size,
+ int request_id);
void OnPictureInPictureModeEnded(RenderFrameHost* render_frame_host,
- int delegate_id);
+ int delegate_id,
+ int request_id);
+ void OnPictureInPictureSurfaceChanged(RenderFrameHost*,
+ int delegate_id,
+ const viz::SurfaceId&,
+ const gfx::Size&);
// Clear |render_frame_host|'s tracking entry for its WakeLocks.
void ClearWakeLocks(RenderFrameHost* render_frame_host);
@@ -130,12 +145,10 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
device::mojom::WakeLock* GetAudioWakeLock();
device::mojom::WakeLock* GetVideoWakeLock();
+ // WakeLock related methods for audio and video.
void LockAudio();
- void LockVideo();
-
void CancelAudioLock();
- void CancelVideoLock();
- void MaybeCancelVideoLock();
+ void UpdateVideoLock();
// Helper methods for adding or removing player entries in |player_map|.
void AddMediaPlayerEntry(const MediaPlayerId& id,
@@ -161,7 +174,7 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
base::Optional<MediaPlayerId> pip_player_;
base::Optional<bool> picture_in_picture_allowed_in_fullscreen_;
bool has_audio_wake_lock_for_testing_ = false;
- bool has_video_wake_lock_for_testing_ = false;
+ bool has_video_wake_lock_ = false;
MediaSessionControllersManager session_controllers_manager_;
diff --git a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc b/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
index 46d2c1ce196..459ce5089f4 100644
--- a/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
+++ b/chromium/content/browser/media/session/audio_focus_manager_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/media/session/audio_focus_manager.h"
+#include <memory>
+
#include "base/command_line.h"
#include "base/run_loop.h"
#include "content/browser/media/session/media_session_impl.h"
@@ -43,7 +45,8 @@ class AudioFocusManagerTest : public testing::Test {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableAudioFocus);
rph_factory_.reset(new MockRenderProcessHostFactory());
- RenderProcessHostImpl::set_render_process_host_factory(rph_factory_.get());
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(
+ rph_factory_.get());
browser_context_.reset(new TestBrowserContext());
pepper_observer_.reset(new MockMediaSessionPlayerObserver());
}
@@ -53,7 +56,7 @@ class AudioFocusManagerTest : public testing::Test {
base::RunLoop().RunUntilIdle();
browser_context_.reset();
- RenderProcessHostImpl::set_render_process_host_factory(nullptr);
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(nullptr);
rph_factory_.reset();
}
@@ -99,7 +102,7 @@ class AudioFocusManagerTest : public testing::Test {
session->AbandonSystemAudioFocusIfNeeded();
}
- WebContents* CreateWebContents() {
+ std::unique_ptr<WebContents> CreateWebContents() {
return TestWebContents::Create(browser_context_.get(),
SiteInstance::SiteInstance::Create(browser_context_.get()));
}
diff --git a/chromium/content/browser/media/session/media_session_android.cc b/chromium/content/browser/media/session/media_session_android.cc
index b9733ddb545..cd30af13b23 100644
--- a/chromium/content/browser/media/session/media_session_android.cc
+++ b/chromium/content/browser/media/session/media_session_android.cc
@@ -162,6 +162,14 @@ void MediaSessionAndroid::DidReceiveAction(JNIEnv* env,
static_cast<blink::mojom::MediaSessionAction>(action));
}
+void MediaSessionAndroid::RequestSystemAudioFocus(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_obj) {
+ DCHECK(media_session());
+ static_cast<MediaSessionImpl*>(media_session())
+ ->RequestSystemAudioFocus(AudioFocusManager::AudioFocusType::Gain);
+}
+
WebContentsAndroid* MediaSessionAndroid::GetWebContentsAndroid() {
MediaSessionImpl* session = static_cast<MediaSessionImpl*>(media_session());
if (!session)
diff --git a/chromium/content/browser/media/session/media_session_android.h b/chromium/content/browser/media/session/media_session_android.h
index 3d3ea8ea58d..3a95d72f0cd 100644
--- a/chromium/content/browser/media/session/media_session_android.h
+++ b/chromium/content/browser/media/session/media_session_android.h
@@ -53,6 +53,9 @@ class MediaSessionAndroid final : public MediaSessionObserver {
void DidReceiveAction(JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_obj,
jint action);
+ void RequestSystemAudioFocus(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_obj);
private:
WebContentsAndroid* GetWebContentsAndroid();
diff --git a/chromium/content/browser/media/session/media_session_impl.cc b/chromium/content/browser/media/session/media_session_impl.cc
index 311371a2770..a66c5d02e07 100644
--- a/chromium/content/browser/media/session/media_session_impl.cc
+++ b/chromium/content/browser/media/session/media_session_impl.cc
@@ -579,6 +579,10 @@ bool MediaSessionImpl::RequestSystemAudioFocus(
bool result = delegate_->RequestAudioFocus(audio_focus_type);
uma_helper_.RecordRequestAudioFocusResult(result);
+ // Make sure we are unducked.
+ if (result)
+ StopDucking();
+
// MediaSessionImpl must change its state & audio focus type AFTER requesting
// audio focus.
SetAudioFocusState(result ? State::ACTIVE : State::INACTIVE);
diff --git a/chromium/content/browser/media/session/media_session_impl.h b/chromium/content/browser/media/session/media_session_impl.h
index 3a681b8b3bc..637acb6dfcf 100644
--- a/chromium/content/browser/media/session/media_session_impl.h
+++ b/chromium/content/browser/media/session/media_session_impl.h
@@ -199,6 +199,11 @@ class MediaSessionImpl : public MediaSession,
// to blink::MediaSession corresponding to the current routed service.
void DidReceiveAction(blink::mojom::MediaSessionAction action) override;
+ // Requests audio focus to the AudioFocusDelegate.
+ // Returns whether the request was granted.
+ CONTENT_EXPORT bool RequestSystemAudioFocus(
+ AudioFocusManager::AudioFocusType audio_focus_type);
+
private:
friend class content::WebContentsUserData<MediaSessionImpl>;
friend class ::MediaSessionImplBrowserTest;
@@ -240,11 +245,6 @@ class MediaSessionImpl : public MediaSession,
State new_state);
CONTENT_EXPORT void OnResumeInternal(MediaSession::SuspendType suspend_type);
- // Requests audio focus to the AudioFocusDelegate.
- // Returns whether the request was granted.
- CONTENT_EXPORT bool RequestSystemAudioFocus(
- AudioFocusManager::AudioFocusType audio_focus_type);
-
// To be called after a call to AbandonAudioFocus() in order request the
// delegate to abandon the audio focus.
CONTENT_EXPORT void AbandonSystemAudioFocusIfNeeded();
diff --git a/chromium/content/browser/media/session/media_session_impl_browsertest.cc b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
index df48df6df53..28fdcebf58d 100644
--- a/chromium/content/browser/media/session/media_session_impl_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_browsertest.cc
@@ -336,6 +336,34 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, AudioFocusInitialState) {
EXPECT_FALSE(IsActive());
}
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ AddPlayerOnSuspendedFocusUnducks) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+
+ UISuspend();
+ EXPECT_FALSE(IsActive());
+
+ SystemStartDucking();
+ EXPECT_EQ(kDuckingVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
+
+ EXPECT_TRUE(
+ AddPlayer(player_observer.get(), 0, media::MediaContentType::Persistent));
+ EXPECT_EQ(kDefaultVolumeMultiplier, player_observer->GetVolumeMultiplier(0));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
+ CanRequestFocusBeforePlayerCreation) {
+ auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
+
+ media_session_->RequestSystemAudioFocus(
+ content::AudioFocusManager::AudioFocusType::Gain);
+ EXPECT_TRUE(IsActive());
+
+ StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent);
+ EXPECT_TRUE(IsActive());
+}
+
IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, StartPlayerGivesFocus) {
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
diff --git a/chromium/content/browser/media/session/mock_media_session_observer.h b/chromium/content/browser/media/session/mock_media_session_observer.h
index 6421fa9b4e6..069fdc9a296 100644
--- a/chromium/content/browser/media/session/mock_media_session_observer.h
+++ b/chromium/content/browser/media/session/mock_media_session_observer.h
@@ -13,7 +13,7 @@ namespace content {
class MockMediaSessionObserver : public MediaSessionObserver {
public:
MockMediaSessionObserver(MediaSession* media_session);
- virtual ~MockMediaSessionObserver() override;
+ ~MockMediaSessionObserver() override;
MOCK_METHOD0(MediaSessionDestroyed, void());
MOCK_METHOD2(MediaSessionStateChanged,
diff --git a/chromium/content/browser/media/url_provision_fetcher.cc b/chromium/content/browser/media/url_provision_fetcher.cc
index e6f57a7964b..4b77be7c34d 100644
--- a/chromium/content/browser/media/url_provision_fetcher.cc
+++ b/chromium/content/browser/media/url_provision_fetcher.cc
@@ -8,17 +8,19 @@
#include "media/base/bind_to_current_loop.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_fetcher.h"
-
-using net::URLFetcher;
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
namespace content {
// Implementation of URLProvisionFetcher.
URLProvisionFetcher::URLProvisionFetcher(
- net::URLRequestContextGetter* context_getter)
- : context_getter_(context_getter) {}
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : url_loader_factory_(std::move(url_loader_factory)) {
+ DCHECK(url_loader_factory_);
+}
URLProvisionFetcher::~URLProvisionFetcher() {}
@@ -32,7 +34,7 @@ void URLProvisionFetcher::Retrieve(
default_url + "&signedRequest=" + request_data;
DVLOG(1) << __func__ << ": request:" << request_string;
- DCHECK(!request_);
+ DCHECK(!simple_url_loader_);
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("url_prevision_fetcher", R"(
semantics {
@@ -62,49 +64,48 @@ void URLProvisionFetcher::Retrieve(
"Media Identifier permissions."
policy_exception_justification: "Not implemented."
})");
- request_ = URLFetcher::Create(GURL(request_string), URLFetcher::POST, this,
- traffic_annotation);
-
- // SetUploadData is mandatory even if we are not uploading anything.
- request_->SetUploadData("", "");
- request_->AddExtraRequestHeader("User-Agent: Widevine CDM v1.0");
- request_->AddExtraRequestHeader("Content-Type: application/json");
- request_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES);
-
- DCHECK(context_getter_);
- request_->SetRequestContext(context_getter_);
-
- request_->Start();
+ auto resource_request = std::make_unique<network::ResourceRequest>();
+ resource_request->url = GURL(request_string);
+ resource_request->load_flags =
+ net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES;
+ resource_request->method = "POST";
+ resource_request->headers.SetHeader("User-Agent", "Widevine CDM v1.0");
+ simple_url_loader_ = network::SimpleURLLoader::Create(
+ std::move(resource_request), traffic_annotation);
+ simple_url_loader_->AttachStringForUpload("", "application/json");
+ simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+ url_loader_factory_.get(),
+ base::BindOnce(&URLProvisionFetcher::OnSimpleLoaderComplete,
+ base::Unretained(this)));
}
-void URLProvisionFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
- DCHECK(source);
-
- int response_code = source->GetResponseCode();
- DVLOG(1) << __func__ << ": response code:" << source->GetResponseCode();
-
- std::string response;
+void URLProvisionFetcher::OnSimpleLoaderComplete(
+ std::unique_ptr<std::string> response_body) {
bool success = false;
- if (response_code == 200) {
- success = source->GetResponseAsString(&response);
- DVLOG_IF(1, !success) << __func__ << ": GetResponseAsString() failed";
+ std::string response;
+ if (response_body) {
+ success = true;
+ response = std::move(*response_body);
} else {
+ int response_code = -1;
+ if (simple_url_loader_->ResponseInfo() &&
+ simple_url_loader_->ResponseInfo()->headers) {
+ response_code =
+ simple_url_loader_->ResponseInfo()->headers->response_code();
+ }
DVLOG(1) << "CDM provision: server returned error code " << response_code;
}
- request_.reset();
- // URLFetcher implementation calls OnURLFetchComplete() on the same thread
- // that called Start() and it does this asynchronously.
+ simple_url_loader_.reset();
response_cb_.Run(success, response);
}
// Implementation of content public method CreateProvisionFetcher().
std::unique_ptr<media::ProvisionFetcher> CreateProvisionFetcher(
- net::URLRequestContextGetter* context_getter) {
- DCHECK(context_getter);
- return std::make_unique<URLProvisionFetcher>(context_getter);
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+ DCHECK(url_loader_factory);
+ return std::make_unique<URLProvisionFetcher>(std::move(url_loader_factory));
}
} // namespace content
diff --git a/chromium/content/browser/media/url_provision_fetcher.h b/chromium/content/browser/media/url_provision_fetcher.h
index 02a594b7347..053e2c09a65 100644
--- a/chromium/content/browser/media/url_provision_fetcher.h
+++ b/chromium/content/browser/media/url_provision_fetcher.h
@@ -7,17 +7,20 @@
#include "base/macros.h"
#include "media/base/provision_fetcher.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+class SimpleURLLoader;
+} // namespace network
namespace content {
// The ProvisionFetcher that retrieves the data by HTTP POST request.
-class URLProvisionFetcher : public media::ProvisionFetcher,
- public net::URLFetcherDelegate {
+class URLProvisionFetcher : public media::ProvisionFetcher {
public:
- explicit URLProvisionFetcher(net::URLRequestContextGetter* context_getter);
+ explicit URLProvisionFetcher(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
~URLProvisionFetcher() override;
// media::ProvisionFetcher implementation.
@@ -26,11 +29,10 @@ class URLProvisionFetcher : public media::ProvisionFetcher,
const ProvisionFetcher::ResponseCB& response_cb) override;
private:
- // net::URLFetcherDelegate implementation.
- void OnURLFetchComplete(const net::URLFetcher* source) override;
+ void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
- net::URLRequestContextGetter* context_getter_;
- std::unique_ptr<net::URLFetcher> request_;
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+ std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
media::ProvisionFetcher::ResponseCB response_cb_;
DISALLOW_COPY_AND_ASSIGN(URLProvisionFetcher);
diff --git a/chromium/content/browser/memory/memory_coordinator_impl.cc b/chromium/content/browser/memory/memory_coordinator_impl.cc
index ad14cde1f5b..c0e70c3ba0c 100644
--- a/chromium/content/browser/memory/memory_coordinator_impl.cc
+++ b/chromium/content/browser/memory/memory_coordinator_impl.cc
@@ -276,7 +276,8 @@ MemoryState MemoryCoordinatorImpl::GetStateForProcess(
for (auto& iter : children()) {
auto* render_process_host = GetRenderProcessHost(iter.first);
- if (render_process_host && render_process_host->GetHandle() == handle)
+ if (render_process_host &&
+ render_process_host->GetProcess().Handle() == handle)
return iter.second.memory_state;
}
return MemoryState::UNKNOWN;
diff --git a/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc b/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
index 7cafc26c995..d99810e4bab 100644
--- a/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
+++ b/chromium/content/browser/memory/memory_coordinator_impl_unittest.cc
@@ -7,7 +7,6 @@
#include "base/memory/memory_coordinator_client_registry.h"
#include "base/memory/memory_coordinator_proxy.h"
#include "base/memory/memory_pressure_monitor.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/multiprocess_test.h"
#include "base/test/scoped_feature_list.h"
@@ -447,23 +446,24 @@ TEST_F(MemoryCoordinatorImplTest, MAYBE_GetStateForProcess) {
coordinator_->CreateChildMemoryCoordinator(1);
coordinator_->CreateChildMemoryCoordinator(2);
base::Process process1 = SpawnChild("process1");
+ base::ProcessHandle process1_handle = process1.Handle();
base::Process process2 = SpawnChild("process2");
- coordinator_->GetMockRenderProcessHost(1)->SetProcessHandle(
- std::make_unique<base::ProcessHandle>(process1.Handle()));
- coordinator_->GetMockRenderProcessHost(2)->SetProcessHandle(
- std::make_unique<base::ProcessHandle>(process2.Handle()));
+ base::ProcessHandle process2_handle = process2.Handle();
+
+ coordinator_->GetMockRenderProcessHost(1)->SetProcess(std::move(process1));
+ coordinator_->GetMockRenderProcessHost(2)->SetProcess(std::move(process2));
EXPECT_EQ(base::MemoryState::NORMAL,
- coordinator_->GetStateForProcess(process1.Handle()));
+ coordinator_->GetStateForProcess(process1_handle));
EXPECT_EQ(base::MemoryState::NORMAL,
- coordinator_->GetStateForProcess(process2.Handle()));
+ coordinator_->GetStateForProcess(process2_handle));
EXPECT_TRUE(
coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED));
EXPECT_EQ(base::MemoryState::THROTTLED,
- coordinator_->GetStateForProcess(process1.Handle()));
+ coordinator_->GetStateForProcess(process1_handle));
EXPECT_EQ(base::MemoryState::NORMAL,
- coordinator_->GetStateForProcess(process2.Handle()));
+ coordinator_->GetStateForProcess(process2_handle));
}
} // namespace content
diff --git a/chromium/content/browser/message_port_provider.cc b/chromium/content/browser/message_port_provider.cc
index 86ebc20d724..e5d8f6681d5 100644
--- a/chromium/content/browser/message_port_provider.cc
+++ b/chromium/content/browser/message_port_provider.cc
@@ -9,6 +9,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/browser_thread.h"
+#include "third_party/blink/public/common/message_port/string_message_codec.h"
#if defined(OS_ANDROID)
#include "base/android/jni_string.h"
@@ -28,11 +29,10 @@ void PostMessageToFrameInternal(WebContents* web_contents,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
FrameMsg_PostMessage_Params params;
- params.is_data_raw_string = true;
params.message = new base::RefCountedData<blink::TransferableMessage>();
+ params.message->data.owned_encoded_message = blink::EncodeStringMessage(data);
params.message->data.encoded_message =
- base::make_span(reinterpret_cast<const uint8_t*>(data.data()),
- data.size() * sizeof(base::char16));
+ params.message->data.owned_encoded_message;
params.message->data.ports = std::move(channels);
params.source_routing_id = MSG_ROUTING_NONE;
params.source_origin = source_origin;
diff --git a/chromium/content/browser/net/accept_header_browsertest.cc b/chromium/content/browser/net/accept_header_browsertest.cc
index d3a6a676497..54bcbf5ea33 100644
--- a/chromium/content/browser/net/accept_header_browsertest.cc
+++ b/chromium/content/browser/net/accept_header_browsertest.cc
@@ -149,7 +149,7 @@ IN_PROC_BROWSER_TEST_F(AcceptHeaderTest, Check) {
EXPECT_EQ("custom/type", GetFor("/xhr_with_accept_header"));
shell()->web_contents()->GetManifest(
- base::BindOnce([](const GURL&, const content::Manifest&) {}));
+ base::BindOnce([](const GURL&, const blink::Manifest&) {}));
// RESOURCE_TYPE_SUB_RESOURCE
EXPECT_EQ("*/*", GetFor("/manifest"));
diff --git a/chromium/content/browser/network_service_browsertest.cc b/chromium/content/browser/network_service_browsertest.cc
index ae882db2697..1e329cf5dfa 100644
--- a/chromium/content/browser/network_service_browsertest.cc
+++ b/chromium/content/browser/network_service_browsertest.cc
@@ -18,6 +18,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "services/network/public/cpp/features.h"
@@ -112,12 +113,21 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
WebUIControllerFactory::RegisterFactory(&factory_);
}
- bool CheckCanLoadHttp() {
- GURL test_url = embedded_test_server()->GetURL("/echo");
+ bool ExecuteScript(const std::string& script) {
+ bool xhr_result = false;
+ // The JS call will fail if disallowed because the process will be killed.
+ bool execute_result =
+ ExecuteScriptAndExtractBool(shell(), script, &xhr_result);
+ return xhr_result && execute_result;
+ }
+
+ bool FetchResource(const GURL& url) {
+ if (!url.is_valid())
+ return false;
std::string script(
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', '");
- script += test_url.spec() +
+ script += url.spec() +
"', true);"
"xhr.onload = function (e) {"
" if (xhr.readyState === 4) {"
@@ -128,11 +138,11 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
" window.domAutomationController.send(false);"
"};"
"xhr.send(null)";
- bool xhr_result = false;
- // The JS call will fail if disallowed because the process will be killed.
- bool execute_result =
- ExecuteScriptAndExtractBool(shell(), script, &xhr_result);
- return xhr_result && execute_result;
+ return ExecuteScript(script);
+ }
+
+ bool CheckCanLoadHttp() {
+ return FetchResource(embedded_test_server()->GetURL("/echo"));
}
void SetUpOnMainThread() override {
@@ -144,6 +154,7 @@ class NetworkServiceBrowserTest : public ContentBrowserTest {
// Since we assume exploited renderer process, it can bypass the same origin
// policy at will. Simulate that by passing the disable-web-security flag.
command_line->AppendSwitch(switches::kDisableWebSecurity);
+ IsolateAllSitesForTesting(command_line);
}
private:
@@ -170,6 +181,20 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, NoWebUIBindingsHttp) {
ASSERT_TRUE(CheckCanLoadHttp());
}
+// Verifies the filesystem URLLoaderFactory's check, using
+// ChildProcessSecurityPolicyImpl::CanRequestURL is properly rejected.
+IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
+ FileSystemBindingsCorrectOrigin) {
+ GURL test_url("chrome://webui/nobinding/");
+ NavigateToURL(shell(), test_url);
+
+ // Note: must be filesystem scheme (obviously).
+ // file: is not a safe web scheme (see IsWebSafeScheme),
+ // and /etc/passwd fails the CanCommitURL check.
+ GURL file_url("filesystem:file:///etc/passwd");
+ EXPECT_FALSE(FetchResource(file_url));
+}
+
class NetworkServiceInProcessBrowserTest : public ContentBrowserTest {
public:
NetworkServiceInProcessBrowserTest() {
diff --git a/chromium/content/browser/network_service_client.cc b/chromium/content/browser/network_service_client.cc
index 85848f344f9..08fdcd44f7e 100644
--- a/chromium/content/browser/network_service_client.cc
+++ b/chromium/content/browser/network_service_client.cc
@@ -6,6 +6,7 @@
#include "base/optional.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/ssl/ssl_manager.h"
@@ -157,21 +158,25 @@ class SSLClientAuthDelegate : public SSLClientAuthHandler::Delegate {
class LoginHandlerDelegate {
public:
LoginHandlerDelegate(
- network::mojom::NetworkServiceClient::OnAuthRequiredCallback callback,
+ network::mojom::AuthChallengeResponderPtr auth_challenge_responder,
ResourceRequestInfo::WebContentsGetter web_contents_getter,
scoped_refptr<net::AuthChallengeInfo> auth_info,
- bool is_main_frame,
+ bool is_request_for_main_frame,
uint32_t process_id,
uint32_t routing_id,
uint32_t request_id,
const GURL& url,
bool first_auth_attempt)
- : callback_(std::move(callback)),
+ : auth_challenge_responder_(std::move(auth_challenge_responder)),
auth_info_(auth_info),
- is_main_frame_(is_main_frame),
+ is_request_for_main_frame_(is_request_for_main_frame),
url_(url),
first_auth_attempt_(first_auth_attempt),
web_contents_getter_(web_contents_getter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auth_challenge_responder_.set_connection_error_handler(base::BindOnce(
+ &LoginHandlerDelegate::OnRequestCancelled, base::Unretained(this)));
+
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&LoginHandlerDelegate::DispatchInterceptorHookAndStart,
@@ -179,10 +184,28 @@ class LoginHandlerDelegate {
request_id));
}
+ void OnRequestCancelled() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!login_delegate_)
+ return;
+
+ // LoginDelegate::OnRequestCancelled can only be called from the IO thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&LoginHandlerDelegate::OnRequestCancelledOnIOThread,
+ base::Unretained(this)));
+ }
+
+ void OnRequestCancelledOnIOThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ login_delegate_->OnRequestCancelled();
+ }
+
private:
void DispatchInterceptorHookAndStart(uint32_t process_id,
uint32_t routing_id,
uint32_t request_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DevToolsURLLoaderInterceptor::HandleAuthRequest(
process_id, routing_id, request_id, auth_info_,
base::BindOnce(&LoginHandlerDelegate::ContinueAfterInterceptor,
@@ -192,37 +215,47 @@ class LoginHandlerDelegate {
void ContinueAfterInterceptor(
bool use_fallback,
const base::Optional<net::AuthCredentials>& auth_credentials) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!(use_fallback && auth_credentials.has_value()));
if (use_fallback)
CreateLoginDelegate();
else
- RunAuthRequiredCallback(auth_credentials);
+ RunAuthCredentials(auth_credentials);
}
void CreateLoginDelegate() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
login_delegate_ = GetContentClient()->browser()->CreateLoginDelegate(
- auth_info_.get(), web_contents_getter_, is_main_frame_, url_,
- first_auth_attempt_,
- base::Bind(&LoginHandlerDelegate::RunAuthRequiredCallback,
- base::Unretained(this)));
+ auth_info_.get(), web_contents_getter_, is_request_for_main_frame_,
+ url_, first_auth_attempt_,
+ base::BindOnce(&LoginHandlerDelegate::RunAuthCredentials,
+ base::Unretained(this)));
if (!login_delegate_) {
- RunAuthRequiredCallback(base::nullopt);
+ RunAuthCredentials(base::nullopt);
return;
}
}
- void RunAuthRequiredCallback(
+ void RunAuthCredentials(
const base::Optional<net::AuthCredentials>& auth_credentials) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback_), auth_credentials));
+ base::BindOnce(&LoginHandlerDelegate::RunAuthCredentialsOnUI,
+ base::Unretained(this), auth_credentials));
+ }
+
+ void RunAuthCredentialsOnUI(
+ const base::Optional<net::AuthCredentials>& auth_credentials) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auth_challenge_responder_->OnAuthCredentials(auth_credentials);
delete this;
}
- network::mojom::NetworkServiceClient::OnAuthRequiredCallback callback_;
+ network::mojom::AuthChallengeResponderPtr auth_challenge_responder_;
scoped_refptr<net::AuthChallengeInfo> auth_info_;
- bool is_main_frame_;
+ bool is_request_for_main_frame_;
GURL url_;
bool first_auth_attempt_;
ResourceRequestInfo::WebContentsGetter web_contents_getter_;
@@ -241,25 +274,34 @@ void NetworkServiceClient::OnAuthRequired(
uint32_t process_id,
uint32_t routing_id,
uint32_t request_id,
- int32_t resource_type,
const GURL& url,
+ const GURL& site_for_cookies,
bool first_auth_attempt,
const scoped_refptr<net::AuthChallengeInfo>& auth_info,
- network::mojom::NetworkServiceClient::OnAuthRequiredCallback callback) {
+ int32_t resource_type,
+ network::mojom::AuthChallengeResponderPtr auth_challenge_responder) {
base::Callback<WebContents*(void)> web_contents_getter =
process_id ? base::Bind(WebContentsImpl::FromRenderFrameHostID,
process_id, routing_id)
: base::Bind(WebContents::FromFrameTreeNodeId, routing_id);
if (!web_contents_getter.Run()) {
- std::move(callback).Run(net::AuthCredentials());
+ std::move(auth_challenge_responder)
+ ->OnAuthCredentials(net::AuthCredentials());
+ return;
+ }
+
+ if (ResourceDispatcherHostImpl::Get()->DoNotPromptForLogin(
+ static_cast<ResourceType>(resource_type), url, site_for_cookies)) {
+ std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt);
return;
}
- bool is_main_frame =
+ bool is_request_for_main_frame =
static_cast<ResourceType>(resource_type) == RESOURCE_TYPE_MAIN_FRAME;
- new LoginHandlerDelegate(std::move(callback), std::move(web_contents_getter),
- auth_info, is_main_frame, process_id, routing_id,
+ new LoginHandlerDelegate(std::move(auth_challenge_responder),
+ std::move(web_contents_getter), auth_info,
+ is_request_for_main_frame, process_id, routing_id,
request_id, url,
first_auth_attempt); // deletes self
}
diff --git a/chromium/content/browser/network_service_client.h b/chromium/content/browser/network_service_client.h
index 149b307cdd6..900cba838bc 100644
--- a/chromium/content/browser/network_service_client.h
+++ b/chromium/content/browser/network_service_client.h
@@ -19,16 +19,16 @@ class NetworkServiceClient : public network::mojom::NetworkServiceClient {
~NetworkServiceClient() override;
// network::mojom::NetworkServiceClient implementation:
- void OnAuthRequired(
- uint32_t process_id,
- uint32_t routing_id,
- uint32_t request_id,
- int32_t resource_type,
- const GURL& url,
- bool first_auth_attempt,
- const scoped_refptr<net::AuthChallengeInfo>& auth_info,
- network::mojom::NetworkServiceClient::OnAuthRequiredCallback callback)
- override;
+ void OnAuthRequired(uint32_t process_id,
+ uint32_t routing_id,
+ uint32_t request_id,
+ const GURL& url,
+ const GURL& site_for_cookies,
+ bool first_auth_attempt,
+ const scoped_refptr<net::AuthChallengeInfo>& auth_info,
+ int32_t resource_type,
+ network::mojom::AuthChallengeResponderPtr
+ auth_challenge_responder) override;
void OnCertificateRequested(
uint32_t process_id,
uint32_t routing_id,
diff --git a/chromium/content/browser/network_service_instance.cc b/chromium/content/browser/network_service_instance.cc
index edd112d7fdc..c62cf6403bf 100644
--- a/chromium/content/browser/network_service_instance.cc
+++ b/chromium/content/browser/network_service_instance.cc
@@ -75,7 +75,6 @@ network::NetworkService* GetNetworkServiceImpl() {
void FlushNetworkServiceInstanceForTesting() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
if (g_network_service_ptr)
g_network_service_ptr->FlushForTesting();
diff --git a/chromium/content/browser/network_service_restart_browsertest.cc b/chromium/content/browser/network_service_restart_browsertest.cc
index 6dcb8876dfc..96551970a99 100644
--- a/chromium/content/browser/network_service_restart_browsertest.cc
+++ b/chromium/content/browser/network_service_restart_browsertest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/test/scoped_feature_list.h"
+#include "base/test/test_timeouts.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -11,14 +12,17 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/simple_url_loader_test_helper.h"
+#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
+#include "content/test/storage_partition_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -42,52 +46,6 @@ network::mojom::NetworkContextPtr CreateNetworkContext() {
return network_context;
}
-network::SimpleURLLoader::BodyAsStringCallback RunOnUIThread(
- network::SimpleURLLoader::BodyAsStringCallback ui_callback) {
- return base::BindOnce(
- [](network::SimpleURLLoader::BodyAsStringCallback callback,
- std::unique_ptr<std::string> response_body) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(std::move(callback), std::move(response_body)));
- },
- std::move(ui_callback));
-}
-
-int LoadBasicRequestOnIOThread(
- network::mojom::URLLoaderFactory* url_loader_factory,
- const GURL& url) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto request = std::make_unique<network::ResourceRequest>();
- request->url = url;
-
- // |simple_loader_helper| lives on UI thread and shouldn't be accessed on
- // other threads.
- SimpleURLLoaderTestHelper simple_loader_helper;
-
- std::unique_ptr<network::SimpleURLLoader> simple_loader =
- network::SimpleURLLoader::Create(std::move(request),
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- [](network::SimpleURLLoader* loader,
- network::mojom::URLLoaderFactory* factory,
- network::SimpleURLLoader::BodyAsStringCallback
- body_as_string_callback) {
- loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
- factory, std::move(body_as_string_callback));
- },
- base::Unretained(simple_loader.get()),
- base::Unretained(url_loader_factory),
- RunOnUIThread(simple_loader_helper.GetCallback())));
-
- simple_loader_helper.WaitForCallback();
- return simple_loader->NetError();
-}
-
int LoadBasicRequestOnUIThread(
network::mojom::URLLoaderFactory* url_loader_factory,
const GURL& url) {
@@ -105,47 +63,39 @@ int LoadBasicRequestOnUIThread(
return simple_loader->NetError();
}
-scoped_refptr<network::SharedURLLoaderFactory> GetSharedFactoryOnIOThread(
- SharedURLLoaderFactoryGetterCallback shared_url_loader_factory_getter) {
- scoped_refptr<network::SharedURLLoaderFactory> shared_factory;
+std::vector<network::mojom::NetworkUsagePtr> GetTotalNetworkUsages() {
+ std::vector<network::mojom::NetworkUsagePtr> network_usages;
base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- [](SharedURLLoaderFactoryGetterCallback getter,
- scoped_refptr<network::SharedURLLoaderFactory>*
- shared_factory_ptr) {
- *shared_factory_ptr = std::move(getter).Run();
- },
- std::move(shared_url_loader_factory_getter),
- base::Unretained(&shared_factory)),
- run_loop.QuitClosure());
+ GetNetworkService()->GetTotalNetworkUsages(base::BindOnce(
+ [](std::vector<network::mojom::NetworkUsagePtr>* p_network_usages,
+ base::OnceClosure quit_closure,
+ std::vector<network::mojom::NetworkUsagePtr> returned_usages) {
+ *p_network_usages = std::move(returned_usages);
+ std::move(quit_closure).Run();
+ },
+ base::Unretained(&network_usages), run_loop.QuitClosure()));
run_loop.Run();
- return shared_factory;
-}
-
-scoped_refptr<network::SharedURLLoaderFactory> GetSharedFactoryOnIOThread(
- URLLoaderFactoryGetter* url_loader_factory_getter) {
- return GetSharedFactoryOnIOThread(
- base::BindOnce(&URLLoaderFactoryGetter::GetNetworkFactory,
- base::Unretained(url_loader_factory_getter)));
+ return network_usages;
}
-scoped_refptr<network::SharedURLLoaderFactory> GetSharedFactoryOnIOThread(
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> info) {
- return GetSharedFactoryOnIOThread(base::BindOnce(
- &network::SharedURLLoaderFactory::Create, std::move(info)));
+bool CheckContainsProcessID(
+ const std::vector<network::mojom::NetworkUsagePtr>& usages,
+ int process_id) {
+ for (const auto& usage : usages) {
+ if ((int)usage->process_id == process_id)
+ return true;
+ }
+ return false;
}
-void ReleaseOnIOThread(
- scoped_refptr<network::SharedURLLoaderFactory> shared_factory) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- [](scoped_refptr<network::SharedURLLoaderFactory> factory) {
- factory = nullptr;
- },
- std::move(shared_factory)));
+// Wait until |condition| returns true.
+void WaitForCondition(base::RepeatingCallback<bool()> condition) {
+ while (!condition.Run()) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+ run_loop.Run();
+ }
}
} // namespace
@@ -182,7 +132,7 @@ class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
shell()->web_contents()->GetMainFrame());
}
- bool CheckCanLoadHttp(const std::string& relative_url) {
+ bool CheckCanLoadHttp(Shell* shell, const std::string& relative_url) {
GURL test_url = embedded_test_server()->GetURL(relative_url);
std::string script(
"var xhr = new XMLHttpRequest();"
@@ -201,7 +151,7 @@ class NetworkServiceRestartBrowserTest : public ContentBrowserTest {
bool xhr_result = false;
// The JS call will fail if disallowed because the process will be killed.
bool execute_result =
- ExecuteScriptAndExtractBool(shell(), script, &xhr_result);
+ ExecuteScriptAndExtractBool(shell, script, &xhr_result);
return xhr_result && execute_result;
}
@@ -359,11 +309,9 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter =
partition->url_loader_factory_getter();
- scoped_refptr<network::SharedURLLoaderFactory> shared_factory =
- GetSharedFactoryOnIOThread(url_loader_factory_getter.get());
- EXPECT_EQ(net::OK,
- LoadBasicRequestOnIOThread(shared_factory.get(), GetTestURL()));
- ReleaseOnIOThread(std::move(shared_factory));
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ url_loader_factory_getter.get());
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
// Crash the NetworkService process. Existing interfaces should receive error
// notifications at some point.
@@ -374,10 +322,9 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
// |url_loader_factory_getter| should be able to get a valid new pointer after
// crash.
- shared_factory = GetSharedFactoryOnIOThread(url_loader_factory_getter.get());
- EXPECT_EQ(net::OK,
- LoadBasicRequestOnIOThread(shared_factory.get(), GetTestURL()));
- ReleaseOnIOThread(std::move(shared_factory));
+ factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ url_loader_factory_getter.get());
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
}
// Make sure the factory returned from
@@ -388,11 +335,10 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(browser_context()));
- scoped_refptr<network::SharedURLLoaderFactory> shared_factory =
- GetSharedFactoryOnIOThread(partition->url_loader_factory_getter().get());
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ partition->url_loader_factory_getter().get());
- EXPECT_EQ(net::OK,
- LoadBasicRequestOnIOThread(shared_factory.get(), GetTestURL()));
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
// Crash the NetworkService process. Existing interfaces should receive error
// notifications at some point.
@@ -403,9 +349,7 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
->FlushNetworkInterfaceOnIOThreadForTesting();
// |shared_factory| should continue to work.
- EXPECT_EQ(net::OK,
- LoadBasicRequestOnIOThread(shared_factory.get(), GetTestURL()));
- ReleaseOnIOThread(std::move(shared_factory));
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
}
// Make sure the factory returned from
@@ -418,17 +362,15 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
std::make_unique<ShellBrowserContext>(true, nullptr);
auto* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(browser_context.get()));
- scoped_refptr<network::SharedURLLoaderFactory> shared_factory(
- GetSharedFactoryOnIOThread(partition->url_loader_factory_getter().get()));
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ partition->url_loader_factory_getter().get());
- EXPECT_EQ(net::OK,
- LoadBasicRequestOnIOThread(shared_factory.get(), GetTestURL()));
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
browser_context.reset();
EXPECT_EQ(net::ERR_FAILED,
- LoadBasicRequestOnIOThread(shared_factory.get(), GetTestURL()));
- ReleaseOnIOThread(std::move(shared_factory));
+ factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
}
// Make sure basic navigation works after crash.
@@ -458,7 +400,7 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) {
BrowserContext::GetDefaultStoragePartition(browser_context()));
EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo")));
- EXPECT_TRUE(CheckCanLoadHttp("/title1.html"));
+ EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title1.html"));
EXPECT_EQ(last_request_relative_url(), "/title1.html");
// Crash the NetworkService process. Existing interfaces should receive error
@@ -471,7 +413,7 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BasicXHR) {
// frame.
main_frame()->FlushNetworkAndNavigationInterfacesForTesting();
- EXPECT_TRUE(CheckCanLoadHttp("/title2.html"));
+ EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
EXPECT_EQ(last_request_relative_url(), "/title2.html");
}
@@ -513,18 +455,21 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
LoadBasicRequestOnUIThread(factory.get(), GetTestURL()));
}
-// Make sure the factory returned from
-// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| continues
-// to work after crashes.
-IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserIOFactory) {
+// Make sure the factory info returned from
+// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| can be
+// used after crashes.
+// Flaky on Windows. https://crbug.com/840127
+#if defined(OS_WIN)
+#define MAYBE_BrowserIOFactoryInfo DISABLED_BrowserIOFactoryInfo
+#else
+#define MAYBE_BrowserIOFactoryInfo BrowserIOFactoryInfo
+#endif
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
+ MAYBE_BrowserIOFactoryInfo) {
auto* partition =
BrowserContext::GetDefaultStoragePartition(browser_context());
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory =
- GetSharedFactoryOnIOThread(
- partition->GetURLLoaderFactoryForBrowserProcessIOThread());
-
- EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(shared_url_loader_factory.get(),
- GetTestURL()));
+ auto shared_url_loader_factory_info =
+ partition->GetURLLoaderFactoryForBrowserProcessIOThread();
SimulateNetworkServiceCrash();
// Flush the interface to make sure the error notification was received.
@@ -533,58 +478,31 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserIOFactory) {
->url_loader_factory_getter()
->FlushNetworkInterfaceOnIOThreadForTesting();
- EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(shared_url_loader_factory.get(),
- GetTestURL()));
- ReleaseOnIOThread(std::move(shared_url_loader_factory));
-}
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ std::move(shared_url_loader_factory_info));
-// Make sure the factory getter returned from
-// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| doesn't
-// crash if it's called after the StoragePartition is deleted.
-IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
- BrowserIOFactoryGetterAfterStoragePartitionGone) {
- base::ScopedAllowBlockingForTesting allow_blocking;
- std::unique_ptr<ShellBrowserContext> browser_context =
- std::make_unique<ShellBrowserContext>(true, nullptr);
- auto* partition =
- BrowserContext::GetDefaultStoragePartition(browser_context.get());
- auto shared_url_loader_factory_info =
- partition->GetURLLoaderFactoryForBrowserProcessIOThread();
-
- browser_context.reset();
-
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory =
- GetSharedFactoryOnIOThread(std::move(shared_url_loader_factory_info));
-
- EXPECT_EQ(net::ERR_FAILED,
- LoadBasicRequestOnIOThread(shared_url_loader_factory.get(),
- GetTestURL()));
- ReleaseOnIOThread(std::move(shared_url_loader_factory));
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
}
-// Make sure the factory returned from
-// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| doesn't
-// crash if it's called after the StoragePartition is deleted.
-IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
- BrowserIOFactoryAfterStoragePartitionGone) {
- base::ScopedAllowBlockingForTesting allow_blocking;
- std::unique_ptr<ShellBrowserContext> browser_context =
- std::make_unique<ShellBrowserContext>(true, nullptr);
+// Make sure the factory constructed from
+// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| continues
+// to work after crashes.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, BrowserIOFactory) {
auto* partition =
- BrowserContext::GetDefaultStoragePartition(browser_context.get());
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory =
- GetSharedFactoryOnIOThread(
- partition->GetURLLoaderFactoryForBrowserProcessIOThread());
+ BrowserContext::GetDefaultStoragePartition(browser_context());
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ partition->GetURLLoaderFactoryForBrowserProcessIOThread());
- EXPECT_EQ(net::OK, LoadBasicRequestOnIOThread(shared_url_loader_factory.get(),
- GetTestURL()));
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
- browser_context.reset();
+ SimulateNetworkServiceCrash();
+ // Flush the interface to make sure the error notification was received.
+ partition->FlushNetworkInterfaceForTesting();
+ static_cast<StoragePartitionImpl*>(partition)
+ ->url_loader_factory_getter()
+ ->FlushNetworkInterfaceOnIOThreadForTesting();
- EXPECT_EQ(net::ERR_FAILED,
- LoadBasicRequestOnIOThread(shared_url_loader_factory.get(),
- GetTestURL()));
- ReleaseOnIOThread(std::move(shared_url_loader_factory));
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
}
// Make sure the window from |window.open()| can load XHR after crash.
@@ -672,4 +590,79 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest, MultipleWorkerFetch) {
EXPECT_EQ(last_request_relative_url(), "/title2.html");
}
+// Make sure the entry in |NetworkService::GetTotalNetworkUsages()| was cleared
+// after process closed.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
+ GetNetworkUsagesClosed) {
+ EXPECT_TRUE(NavigateToURL(shell(), GetTestURL()));
+ Shell* shell2 = CreateBrowser();
+ EXPECT_TRUE(NavigateToURL(shell2, GetTestURL()));
+
+ int process_id1 =
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
+ int process_id2 =
+ shell2->web_contents()->GetMainFrame()->GetProcess()->GetID();
+
+ // Load resource on the renderer to make sure the traffic was recorded.
+ EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
+ EXPECT_TRUE(CheckCanLoadHttp(shell2, "/title3.html"));
+
+ // Both processes should have traffic recorded.
+ auto network_usages = GetTotalNetworkUsages();
+ EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
+ EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id2));
+
+ // Closing |shell2| should cause the entry to be cleared.
+ shell2->Close();
+ shell2 = nullptr;
+
+ // Wait until the Network Service has noticed the change. We don't have a
+ // better way to force a flush on the Network Service side.
+ WaitForCondition(base::BindRepeating(
+ [](int process_id) {
+ auto usages = GetTotalNetworkUsages();
+ return !CheckContainsProcessID(usages, process_id);
+ },
+ process_id2));
+
+ network_usages = GetTotalNetworkUsages();
+ EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
+ EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
+}
+
+// Make sure |NetworkService::GetTotalNetworkUsages()| continues to work after
+// crash. See 'network_usage_accumulator_unittest' for quantified tests.
+IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
+ GetNetworkUsagesCrashed) {
+ EXPECT_TRUE(NavigateToURL(shell(), GetTestURL()));
+ Shell* shell2 = CreateBrowser();
+ EXPECT_TRUE(NavigateToURL(shell2, GetTestURL()));
+
+ int process_id1 =
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
+ int process_id2 =
+ shell2->web_contents()->GetMainFrame()->GetProcess()->GetID();
+
+ // Load resource on the renderer to make sure the traffic was recorded.
+ EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
+ EXPECT_TRUE(CheckCanLoadHttp(shell2, "/title3.html"));
+
+ // Both processes should have traffic recorded.
+ auto network_usages = GetTotalNetworkUsages();
+ EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
+ EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id2));
+
+ // Crashing Network Service should cause all entries to be cleared.
+ SimulateNetworkServiceCrash();
+ network_usages = GetTotalNetworkUsages();
+ EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id1));
+ EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
+
+ // Should still be able to recored new traffic after crash.
+ EXPECT_TRUE(CheckCanLoadHttp(shell(), "/title2.html"));
+ network_usages = GetTotalNetworkUsages();
+ EXPECT_TRUE(CheckContainsProcessID(network_usages, process_id1));
+ EXPECT_FALSE(CheckContainsProcessID(network_usages, process_id2));
+}
+
} // namespace content
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.cc b/chromium/content/browser/notifications/blink_notification_service_impl.cc
index 605a9ed20ce..53101e0342c 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/notifications/blink_notification_service_impl.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/strings/string16.h"
@@ -141,8 +142,10 @@ void BlinkNotificationServiceImpl::CloseNonPersistentNotificationOnUIThread(
const std::string& notification_id) {
Service()->CloseNotification(browser_context_, notification_id);
+ // TODO(https://crbug.com/442141): Pass a callback here to focus the tab
+ // which created the notification, unless the event is canceled.
NotificationEventDispatcherImpl::GetInstance()
- ->DispatchNonPersistentCloseEvent(notification_id);
+ ->DispatchNonPersistentCloseEvent(notification_id, base::DoNothing());
}
blink::mojom::PermissionStatus
@@ -245,6 +248,24 @@ void BlinkNotificationServiceImpl::
std::move(callback).Run(blink::mojom::PersistentNotificationError::NONE);
}
+void BlinkNotificationServiceImpl::ClosePersistentNotification(
+ const std::string& notification_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (CheckPermissionStatus() != blink::mojom::PermissionStatus::GRANTED)
+ return;
+
+ // Using base::Unretained here is safe because Service() returns a singleton.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&PlatformNotificationService::ClosePersistentNotification,
+ base::Unretained(Service()), browser_context_,
+ notification_id));
+
+ notification_context_->DeleteNotificationData(
+ notification_id, origin_.GetURL(), base::DoNothing());
+}
+
void BlinkNotificationServiceImpl::GetNotifications(
int64_t service_worker_registration_id,
const std::string& filter_tag,
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl.h b/chromium/content/browser/notifications/blink_notification_service_impl.h
index 98819833d8c..1ddd97d69ef 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl.h
+++ b/chromium/content/browser/notifications/blink_notification_service_impl.h
@@ -51,6 +51,7 @@ class CONTENT_EXPORT BlinkNotificationServiceImpl
const PlatformNotificationData& platform_notification_data,
const NotificationResources& notification_resources,
DisplayPersistentNotificationCallback) override;
+ void ClosePersistentNotification(const std::string& notification_id) override;
void GetNotifications(int64_t service_worker_registration_id,
const std::string& filter_tag,
GetNotificationsCallback callback) override;
diff --git a/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc b/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
index e171e48bf69..26622dee5f7 100644
--- a/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
+++ b/chromium/content/browser/notifications/blink_notification_service_impl_unittest.cc
@@ -54,7 +54,9 @@ class MockNonPersistentNotificationListener
// NonPersistentNotificationListener interface.
void OnShow() override {}
void OnClick() override {}
- void OnClose() override {}
+ void OnClose(OnCloseCallback completed_closure) override {
+ std::move(completed_closure).Run();
+ }
private:
mojo::Binding<blink::mojom::NonPersistentNotificationListener> binding_;
@@ -220,6 +222,13 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
std::move(quit_closure).Run();
}
+ void DidReadNotificationData(base::OnceClosure quit_closure,
+ bool success,
+ const NotificationDatabaseData& data) {
+ read_notification_data_callback_result_ = success;
+ std::move(quit_closure).Run();
+ }
+
void DisplayPersistentNotificationSync(
int64_t service_worker_registration_id,
const PlatformNotificationData& platform_notification_data,
@@ -259,6 +268,19 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
return get_displayed_callback_result_;
}
+ // Synchronous wrapper of
+ // PlatformNotificationContext::ReadNotificationData
+ bool ReadNotificationData(const std::string& notification_id) {
+ base::RunLoop run_loop;
+ notification_context_->ReadNotificationData(
+ notification_id, GURL(kTestOrigin),
+ base::AdaptCallbackForRepeating(base::BindOnce(
+ &BlinkNotificationServiceImplTest::DidReadNotificationData,
+ base::Unretained(this), run_loop.QuitClosure())));
+ run_loop.Run();
+ return read_notification_data_callback_result_;
+ }
+
protected:
TestBrowserThreadBundle thread_bundle_; // Must be first member.
@@ -268,6 +290,8 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
TestBrowserContext browser_context_;
+ scoped_refptr<PlatformNotificationContextImpl> notification_context_;
+
MockPlatformNotificationService mock_platform_service_;
MockNonPersistentNotificationListener non_persistent_notification_listener_;
@@ -277,8 +301,6 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
private:
NotificationBrowserClient notification_browser_client_;
- scoped_refptr<PlatformNotificationContextImpl> notification_context_;
-
blink::mojom::PermissionStatus permission_callback_result_ =
blink::mojom::PermissionStatus::ASK;
@@ -286,6 +308,8 @@ class BlinkNotificationServiceImplTest : public ::testing::Test {
std::vector<std::string> get_notifications_callback_result_;
+ bool read_notification_data_callback_result_ = false;
+
MockResourceContext resource_context_;
DISALLOW_COPY_AND_ASSIGN(BlinkNotificationServiceImplTest);
@@ -371,6 +395,65 @@ TEST_F(BlinkNotificationServiceImplTest,
EXPECT_EQ(1u, GetDisplayedNotifications().size());
}
+TEST_F(BlinkNotificationServiceImplTest, CloseDisplayedPersistentNotification) {
+ mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ RegisterServiceWorker(&registration);
+
+ DisplayPersistentNotificationSync(
+ registration->id(), PlatformNotificationData(), NotificationResources());
+
+ ASSERT_EQ(blink::mojom::PersistentNotificationError::NONE,
+ display_persistent_callback_result_);
+
+ // Wait for service to receive the Display call.
+ RunAllTasksUntilIdle();
+
+ std::set<std::string> notification_ids = GetDisplayedNotifications();
+ ASSERT_EQ(1u, notification_ids.size());
+
+ notification_service_->ClosePersistentNotification(*notification_ids.begin());
+
+ // Wait for service to receive the Close call.
+ RunAllTasksUntilIdle();
+
+ EXPECT_EQ(0u, GetDisplayedNotifications().size());
+}
+
+TEST_F(BlinkNotificationServiceImplTest,
+ ClosePersistentNotificationDeletesFromDatabase) {
+ mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::GRANTED);
+
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ RegisterServiceWorker(&registration);
+
+ DisplayPersistentNotificationSync(
+ registration->id(), PlatformNotificationData(), NotificationResources());
+
+ ASSERT_EQ(blink::mojom::PersistentNotificationError::NONE,
+ display_persistent_callback_result_);
+
+ // Wait for service to receive the Display call.
+ RunAllTasksUntilIdle();
+
+ std::set<std::string> notification_ids = GetDisplayedNotifications();
+ ASSERT_EQ(1u, notification_ids.size());
+
+ std::string notification_id = *notification_ids.begin();
+
+ // Check data was indeed written.
+ ASSERT_EQ(true /* success */, ReadNotificationData(notification_id));
+
+ notification_service_->ClosePersistentNotification(notification_id);
+
+ // Wait for service to receive the Close call.
+ RunAllTasksUntilIdle();
+
+ // Data should now be deleted.
+ EXPECT_EQ(false /* success */, ReadNotificationData(notification_id));
+}
+
TEST_F(BlinkNotificationServiceImplTest,
DisplayPersistentNotificationWithoutPermission) {
mock_platform_service_.SetPermission(blink::mojom::PermissionStatus::DENIED);
diff --git a/chromium/content/browser/notifications/notification_database.cc b/chromium/content/browser/notifications/notification_database.cc
index c148fdc656d..87dca497209 100644
--- a/chromium/content/browser/notifications/notification_database.cc
+++ b/chromium/content/browser/notifications/notification_database.cc
@@ -128,7 +128,7 @@ NotificationDatabase::Status NotificationDatabase::Open(
options.filter_policy = filter_policy_.get();
options.block_cache = leveldb_chrome::GetSharedWebBlockCache();
if (IsInMemoryDatabase()) {
- env_.reset(leveldb_chrome::NewMemEnv(leveldb::Env::Default()));
+ env_ = leveldb_chrome::NewMemEnv("notification");
options.env = env_.get();
}
diff --git a/chromium/content/browser/notifications/notification_database_data.proto b/chromium/content/browser/notifications/notification_database_data.proto
index 005e7c8a10c..6a631180461 100644
--- a/chromium/content/browser/notifications/notification_database_data.proto
+++ b/chromium/content/browser/notifications/notification_database_data.proto
@@ -11,8 +11,14 @@ package content;
// Stores information about a Web Notification. This message is the protocol
// buffer meant to serialize the content::NotificationDatabaseData structure.
//
-// Next tag: 6
+// Next tag: 14
message NotificationDatabaseDataProto {
+ enum ClosedReason {
+ USER = 0;
+ DEVELOPER = 1;
+ UNKNOWN = 2;
+ }
+
// DEPRECATED: Use |notification_id| instead.
optional int64 persistent_notification_id = 1;
@@ -20,6 +26,14 @@ message NotificationDatabaseDataProto {
optional string origin = 2;
optional int64 service_worker_registration_id = 3;
+ optional bool replaced_existing_notification = 6;
+ optional int32 num_clicks = 7;
+ optional int32 num_action_button_clicks = 8;
+ optional int64 creation_time_millis = 9;
+ optional int64 time_until_first_click_millis = 10;
+ optional int64 time_until_last_click_millis = 11;
+ optional int64 time_until_close_millis = 12;
+ optional ClosedReason closed_reason = 13;
// A notification action, corresponds to content::PlatformNotificationAction.
//
diff --git a/chromium/content/browser/notifications/notification_database_data_conversions.cc b/chromium/content/browser/notifications/notification_database_data_conversions.cc
index e95d912bb0f..557692ae53e 100644
--- a/chromium/content/browser/notifications/notification_database_data_conversions.cc
+++ b/chromium/content/browser/notifications/notification_database_data_conversions.cc
@@ -28,6 +28,30 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
output->origin = GURL(message.origin());
output->service_worker_registration_id =
message.service_worker_registration_id();
+ output->replaced_existing_notification =
+ message.replaced_existing_notification();
+ output->num_clicks = message.num_clicks();
+ output->num_action_button_clicks = message.num_action_button_clicks();
+ output->creation_time_millis = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(message.creation_time_millis()));
+ output->time_until_first_click_millis = base::TimeDelta::FromMilliseconds(
+ message.time_until_first_click_millis());
+ output->time_until_last_click_millis =
+ base::TimeDelta::FromMilliseconds(message.time_until_last_click_millis());
+ output->time_until_close_millis =
+ base::TimeDelta::FromMilliseconds(message.time_until_close_millis());
+
+ switch (message.closed_reason()) {
+ case NotificationDatabaseDataProto::USER:
+ output->closed_reason = NotificationDatabaseData::ClosedReason::USER;
+ break;
+ case NotificationDatabaseDataProto::DEVELOPER:
+ output->closed_reason = NotificationDatabaseData::ClosedReason::DEVELOPER;
+ break;
+ case NotificationDatabaseDataProto::UNKNOWN:
+ output->closed_reason = NotificationDatabaseData::ClosedReason::UNKNOWN;
+ break;
+ }
PlatformNotificationData* notification_data = &output->notification_data;
const NotificationDatabaseDataProto::NotificationData& payload =
@@ -178,6 +202,30 @@ bool SerializeNotificationDatabaseData(const NotificationDatabaseData& input,
message.set_service_worker_registration_id(
input.service_worker_registration_id);
message.set_allocated_notification_data(payload.release());
+ message.set_replaced_existing_notification(
+ input.replaced_existing_notification);
+ message.set_num_clicks(input.num_clicks);
+ message.set_num_action_button_clicks(input.num_action_button_clicks);
+ message.set_creation_time_millis(
+ input.creation_time_millis.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ message.set_time_until_first_click_millis(
+ input.time_until_first_click_millis.InMilliseconds());
+ message.set_time_until_last_click_millis(
+ input.time_until_last_click_millis.InMilliseconds());
+ message.set_time_until_close_millis(
+ input.time_until_close_millis.InMilliseconds());
+
+ switch (input.closed_reason) {
+ case NotificationDatabaseData::ClosedReason::USER:
+ message.set_closed_reason(NotificationDatabaseDataProto::USER);
+ break;
+ case NotificationDatabaseData::ClosedReason::DEVELOPER:
+ message.set_closed_reason(NotificationDatabaseDataProto::DEVELOPER);
+ break;
+ case NotificationDatabaseData::ClosedReason::UNKNOWN:
+ message.set_closed_reason(NotificationDatabaseDataProto::UNKNOWN);
+ break;
+ }
return message.SerializeToString(output);
}
diff --git a/chromium/content/browser/notifications/notification_database_data_unittest.cc b/chromium/content/browser/notifications/notification_database_data_unittest.cc
index 5bdbb4ce880..6436f409c4e 100644
--- a/chromium/content/browser/notifications/notification_database_data_unittest.cc
+++ b/chromium/content/browser/notifications/notification_database_data_unittest.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/stl_util.h"
#include "base/strings/nullable_string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
@@ -21,6 +22,13 @@ namespace content {
const char kNotificationId[] = "my-notification";
const int64_t kServiceWorkerRegistrationId = 9001;
+const bool kReplacedExistingNotification = true;
+const int kNumClicks = 8;
+const int kNumActionButtonClicks = 9;
+const double kInitTimeMillis = 12345;
+const int kTimeUntilFirstClickMillis = 11111;
+const int kTimeUntilLastClickMillis = 22222;
+const int kTimeUntilCloseMillis = 33333;
const PlatformNotificationActionType kNotificationActionType =
PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
@@ -40,10 +48,11 @@ const unsigned char kNotificationData[] = {0xdf, 0xff, 0x0, 0x0, 0xff, 0xdf};
TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
std::vector<int> vibration_pattern(
kNotificationVibrationPattern,
- kNotificationVibrationPattern + arraysize(kNotificationVibrationPattern));
+ kNotificationVibrationPattern +
+ base::size(kNotificationVibrationPattern));
std::vector<char> developer_data(
- kNotificationData, kNotificationData + arraysize(kNotificationData));
+ kNotificationData, kNotificationData + base::size(kNotificationData));
PlatformNotificationData notification_data;
notification_data.title = base::ASCIIToUTF16(kNotificationTitle);
@@ -77,7 +86,17 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
database_data.origin = GURL(kOrigin);
database_data.service_worker_registration_id = kServiceWorkerRegistrationId;
database_data.notification_data = notification_data;
-
+ database_data.replaced_existing_notification = kReplacedExistingNotification;
+ database_data.num_clicks = kNumClicks;
+ database_data.num_action_button_clicks = kNumActionButtonClicks;
+ database_data.creation_time_millis = base::Time::FromDoubleT(kInitTimeMillis);
+ database_data.time_until_first_click_millis =
+ base::TimeDelta::FromMilliseconds(kTimeUntilFirstClickMillis);
+ database_data.time_until_last_click_millis =
+ base::TimeDelta::FromMilliseconds(kTimeUntilLastClickMillis);
+ database_data.time_until_close_millis =
+ base::TimeDelta::FromMilliseconds(kTimeUntilCloseMillis);
+ database_data.closed_reason = NotificationDatabaseData::ClosedReason::USER;
std::string serialized_data;
// Serialize the data in |notification_data| to the string |serialized_data|.
@@ -94,6 +113,20 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
EXPECT_EQ(database_data.origin, copied_data.origin);
EXPECT_EQ(database_data.service_worker_registration_id,
copied_data.service_worker_registration_id);
+ EXPECT_EQ(database_data.num_clicks, copied_data.num_clicks);
+ EXPECT_EQ(database_data.num_action_button_clicks,
+ copied_data.num_action_button_clicks);
+ EXPECT_EQ(database_data.replaced_existing_notification,
+ copied_data.replaced_existing_notification);
+ EXPECT_EQ(database_data.creation_time_millis,
+ copied_data.creation_time_millis);
+ EXPECT_EQ(database_data.time_until_first_click_millis,
+ copied_data.time_until_first_click_millis);
+ EXPECT_EQ(database_data.time_until_last_click_millis,
+ copied_data.time_until_last_click_millis);
+ EXPECT_EQ(database_data.time_until_close_millis,
+ copied_data.time_until_close_millis);
+ EXPECT_EQ(database_data.closed_reason, copied_data.closed_reason);
const PlatformNotificationData& copied_notification_data =
copied_data.notification_data;
@@ -170,7 +203,7 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeDirections) {
PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT,
PlatformNotificationData::DIRECTION_AUTO};
- for (size_t i = 0; i < arraysize(directions); ++i) {
+ for (size_t i = 0; i < base::size(directions); ++i) {
PlatformNotificationData notification_data;
notification_data.direction = directions[i];
@@ -189,6 +222,28 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeDirections) {
}
}
+TEST(NotificationDatabaseDataTest, SerializeAndDeserializeclosed_reasons) {
+ NotificationDatabaseData::ClosedReason closed_reasons[] = {
+ NotificationDatabaseData::ClosedReason::USER,
+ NotificationDatabaseData::ClosedReason::DEVELOPER,
+ NotificationDatabaseData::ClosedReason::UNKNOWN};
+
+ for (size_t i = 0; i < base::size(closed_reasons); ++i) {
+ NotificationDatabaseData database_data;
+ database_data.closed_reason = closed_reasons[i];
+
+ std::string serialized_data;
+ ASSERT_TRUE(
+ SerializeNotificationDatabaseData(database_data, &serialized_data));
+
+ NotificationDatabaseData copied_data;
+ ASSERT_TRUE(
+ DeserializeNotificationDatabaseData(serialized_data, &copied_data));
+
+ EXPECT_EQ(closed_reasons[i], copied_data.closed_reason);
+ }
+}
+
TEST(NotificationDatabaseDataTest, SerializeAndDeserializeNullPlaceholder) {
PlatformNotificationAction action;
action.type = kNotificationActionType;
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index 3b593eb6c0b..1f00936370a 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -4,11 +4,11 @@
#include "content/browser/notifications/notification_event_dispatcher_impl.h"
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/optional.h"
#include "build/build_config.h"
-#include "content/browser/notifications/notification_message_filter.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
@@ -422,7 +422,7 @@ void NotificationEventDispatcherImpl::RegisterNonPersistentNotificationListener(
// from the JavaScript point of view there will be two notification objects,
// and the old one needs to receive a close event before the new one
// receives a show event.
- DispatchNonPersistentCloseEvent(notification_id);
+ DispatchNonPersistentCloseEvent(notification_id, base::DoNothing());
}
blink::mojom::NonPersistentNotificationListenerPtr listener_ptr(
@@ -455,11 +455,25 @@ void NotificationEventDispatcherImpl::DispatchNonPersistentClickEvent(
}
void NotificationEventDispatcherImpl::DispatchNonPersistentCloseEvent(
- const std::string& notification_id) {
- if (!non_persistent_notification_listeners_.count(notification_id))
+ const std::string& notification_id,
+ base::OnceClosure completed_closure) {
+ if (!non_persistent_notification_listeners_.count(notification_id)) {
+ std::move(completed_closure).Run();
return;
- non_persistent_notification_listeners_[notification_id]->OnClose();
+ }
+ // Listeners get freed together with |this|, thus the Unretained is safe.
+ non_persistent_notification_listeners_[notification_id]->OnClose(
+ base::BindOnce(
+ &NotificationEventDispatcherImpl::OnNonPersistentCloseComplete,
+ base::Unretained(this), notification_id,
+ std::move(completed_closure)));
+}
+
+void NotificationEventDispatcherImpl::OnNonPersistentCloseComplete(
+ const std::string& notification_id,
+ base::OnceClosure completed_closure) {
non_persistent_notification_listeners_.erase(notification_id);
+ std::move(completed_closure).Run();
}
void NotificationEventDispatcherImpl::
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
index e77b7ddf789..dff47bf1dbe 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
@@ -7,6 +7,7 @@
#include <map>
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "content/common/content_export.h"
@@ -42,7 +43,8 @@ class CONTENT_EXPORT NotificationEventDispatcherImpl
void DispatchNonPersistentClickEvent(
const std::string& notification_id) override;
void DispatchNonPersistentCloseEvent(
- const std::string& notification_id) override;
+ const std::string& notification_id,
+ base::OnceClosure completed_closure) override;
// Registers |listener| to receive the show, click and close events of the
// non-persistent notification identified by |notification_id|.
@@ -58,6 +60,13 @@ class CONTENT_EXPORT NotificationEventDispatcherImpl
~NotificationEventDispatcherImpl() override;
// Removes all references to the listener registered to receive events
+ // from the non-persistent notification identified by |notification_id|,
+ // and executes |completed_closure|. This method is called after OnClose has
+ // been dispatched to the non-persistent notification listener.
+ void OnNonPersistentCloseComplete(const std::string& notification_id,
+ base::OnceClosure completed_closure);
+
+ // Removes all references to the listener registered to receive events
// from the non-persistent notification identified by |notification_id|.
// Should be called when the connection to this listener goes away.
void HandleConnectionErrorForNonPersistentNotificationListener(
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
index dac1cc89ca3..a2bbe92a81e 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
@@ -51,7 +51,10 @@ class TestNotificationListener
// blink::mojom::NonPersistentNotificationListener implementation.
void OnShow() override { on_show_count_++; }
void OnClick() override { on_click_count_++; }
- void OnClose() override { on_close_count_++; }
+ void OnClose(OnCloseCallback completed_closure) override {
+ on_close_count_++;
+ std::move(completed_closure).Run();
+ }
private:
int on_show_count_ = 0;
@@ -165,14 +168,16 @@ TEST_F(NotificationEventDispatcherImplTest,
dispatcher_->RegisterNonPersistentNotificationListener(
kSomeOtherUniqueId, other_listener->GetPtr().PassInterface());
- dispatcher_->DispatchNonPersistentCloseEvent(kPrimaryUniqueId);
+ dispatcher_->DispatchNonPersistentCloseEvent(kPrimaryUniqueId,
+ base::DoNothing());
WaitForMojoTasksToComplete();
EXPECT_EQ(listener->on_close_count(), 1);
EXPECT_EQ(other_listener->on_close_count(), 0);
- dispatcher_->DispatchNonPersistentCloseEvent(kSomeOtherUniqueId);
+ dispatcher_->DispatchNonPersistentCloseEvent(kSomeOtherUniqueId,
+ base::DoNothing());
WaitForMojoTasksToComplete();
@@ -188,7 +193,8 @@ TEST_F(NotificationEventDispatcherImplTest,
dispatcher_->DispatchNonPersistentShowEvent(kPrimaryUniqueId);
dispatcher_->DispatchNonPersistentClickEvent(kPrimaryUniqueId);
- dispatcher_->DispatchNonPersistentCloseEvent(kPrimaryUniqueId);
+ dispatcher_->DispatchNonPersistentCloseEvent(kPrimaryUniqueId,
+ base::DoNothing());
WaitForMojoTasksToComplete();
diff --git a/chromium/content/browser/notifications/notification_message_filter.cc b/chromium/content/browser/notifications/notification_message_filter.cc
deleted file mode 100644
index 518fdf07991..00000000000
--- a/chromium/content/browser/notifications/notification_message_filter.cc
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright 2014 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/notifications/notification_message_filter.h"
-
-#include <utility>
-
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "content/browser/bad_message.h"
-#include "content/browser/notifications/notification_event_dispatcher_impl.h"
-#include "content/browser/notifications/notification_id_generator.h"
-#include "content/browser/notifications/platform_notification_context_impl.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/common/platform_notification_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/notification_database_data.h"
-#include "content/public/browser/platform_notification_service.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_constants.h"
-
-namespace content {
-
-namespace {
-
-const int kMinimumVibrationDurationMs = 1; // 1 millisecond
-const int kMaximumVibrationDurationMs = 10000; // 10 seconds
-
-PlatformNotificationData SanitizeNotificationData(
- const PlatformNotificationData& notification_data) {
- PlatformNotificationData sanitized_data = notification_data;
-
- // Make sure that the vibration values are within reasonable bounds.
- for (int& pattern : sanitized_data.vibration_pattern) {
- pattern = std::min(kMaximumVibrationDurationMs,
- std::max(kMinimumVibrationDurationMs, pattern));
- }
-
- // Ensure there aren't more actions than supported.
- if (sanitized_data.actions.size() > blink::kWebNotificationMaxActions)
- sanitized_data.actions.resize(blink::kWebNotificationMaxActions);
-
- return sanitized_data;
-}
-
-// Returns true when |resources| looks ok, false otherwise.
-bool ValidateNotificationResources(const NotificationResources& resources) {
- if (!resources.image.drawsNothing() &&
- !base::FeatureList::IsEnabled(features::kNotificationContentImage)) {
- return false;
- }
- if (resources.image.width() > blink::kWebNotificationMaxImageWidthPx ||
- resources.image.height() > blink::kWebNotificationMaxImageHeightPx) {
- return false;
- }
- if (resources.notification_icon.width() >
- blink::kWebNotificationMaxIconSizePx ||
- resources.notification_icon.height() >
- blink::kWebNotificationMaxIconSizePx) {
- return false;
- }
- if (resources.badge.width() > blink::kWebNotificationMaxBadgeSizePx ||
- resources.badge.height() > blink::kWebNotificationMaxBadgeSizePx) {
- return false;
- }
- for (const auto& action_icon : resources.action_icons) {
- if (action_icon.width() > blink::kWebNotificationMaxActionIconSizePx ||
- action_icon.height() > blink::kWebNotificationMaxActionIconSizePx) {
- return false;
- }
- }
- return true;
-}
-
-} // namespace
-
-NotificationMessageFilter::NotificationMessageFilter(
- int process_id,
- PlatformNotificationContextImpl* notification_context,
- ResourceContext* resource_context,
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
- BrowserContext* browser_context)
- : BrowserMessageFilter(PlatformNotificationMsgStart),
- process_id_(process_id),
- notification_context_(notification_context),
- resource_context_(resource_context),
- service_worker_context_(service_worker_context),
- browser_context_(browser_context),
- weak_factory_io_(this) {}
-
-NotificationMessageFilter::~NotificationMessageFilter() = default;
-
-void NotificationMessageFilter::OnDestruct() const {
- BrowserThread::DeleteOnIOThread::Destruct(this);
-}
-
-bool NotificationMessageFilter::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(NotificationMessageFilter, message)
- IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_ShowPersistent,
- OnShowPersistentNotification)
- IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_GetNotifications,
- OnGetNotifications)
- IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_ClosePersistent,
- OnClosePersistentNotification)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void NotificationMessageFilter::OnShowPersistentNotification(
- int request_id,
- int64_t service_worker_registration_id,
- const GURL& origin,
- const PlatformNotificationData& notification_data,
- const NotificationResources& notification_resources) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (GetPermissionForOriginOnIO(origin) !=
- blink::mojom::PermissionStatus::GRANTED) {
- // We can't assume that the renderer is compromised at this point because
- // it's possible for the user to revoke an origin's permission between the
- // time where a website requests the notification to be shown and the call
- // arriving in the message filter.
- return;
- }
-
- if (!ValidateNotificationResources(notification_resources)) {
- bad_message::ReceivedBadMessage(this, bad_message::NMF_INVALID_ARGUMENT);
- return;
- }
-
- NotificationDatabaseData database_data;
- database_data.origin = origin;
- database_data.service_worker_registration_id = service_worker_registration_id;
-
- PlatformNotificationData sanitized_notification_data =
- SanitizeNotificationData(notification_data);
- database_data.notification_data = sanitized_notification_data;
-
- notification_context_->WriteNotificationData(
- origin, database_data,
- base::Bind(&NotificationMessageFilter::DidWritePersistentNotificationData,
- weak_factory_io_.GetWeakPtr(), request_id,
- service_worker_registration_id, origin,
- sanitized_notification_data, notification_resources));
-}
-
-void NotificationMessageFilter::DidWritePersistentNotificationData(
- int request_id,
- int64_t service_worker_registration_id,
- const GURL& origin,
- const PlatformNotificationData& notification_data,
- const NotificationResources& notification_resources,
- bool success,
- const std::string& notification_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!success) {
- Send(new PlatformNotificationMsg_DidShowPersistent(request_id, false));
- return;
- }
-
- // Get the service worker scope.
- service_worker_context_->FindReadyRegistrationForId(
- service_worker_registration_id, origin,
- base::BindOnce(
- &NotificationMessageFilter::DidFindServiceWorkerRegistration,
- weak_factory_io_.GetWeakPtr(), request_id, origin, notification_data,
- notification_resources, notification_id));
-}
-
-void NotificationMessageFilter::DidFindServiceWorkerRegistration(
- int request_id,
- const GURL& origin,
- const PlatformNotificationData& notification_data,
- const NotificationResources& notification_resources,
- const std::string& notification_id,
- content::ServiceWorkerStatusCode service_worker_status,
- scoped_refptr<content::ServiceWorkerRegistration> registration) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (service_worker_status != SERVICE_WORKER_OK) {
- Send(new PlatformNotificationMsg_DidShowPersistent(request_id, false));
- LOG(ERROR) << "Registration not found for " << origin.spec();
- // TODO(peter): Add UMA to track how often this occurs.
- return;
- }
-
- PlatformNotificationService* service =
- GetContentClient()->browser()->GetPlatformNotificationService();
- DCHECK(service);
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(
- &PlatformNotificationService::DisplayPersistentNotification,
- base::Unretained(service), // The service is a singleton.
- browser_context_, notification_id, registration->pattern(), origin,
- notification_data, notification_resources));
-
- Send(new PlatformNotificationMsg_DidShowPersistent(request_id, true));
-}
-
-void NotificationMessageFilter::OnGetNotifications(
- int request_id,
- int64_t service_worker_registration_id,
- const GURL& origin,
- const std::string& filter_tag) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (GetPermissionForOriginOnIO(origin) !=
- blink::mojom::PermissionStatus::GRANTED) {
- // No permission has been granted for the given origin. It is harmless to
- // try to get notifications without permission, so return an empty vector
- // indicating that no (accessible) notifications exist at this time.
- Send(new PlatformNotificationMsg_DidGetNotifications(
- request_id, std::vector<PersistentNotificationInfo>()));
- return;
- }
-
- notification_context_->ReadAllNotificationDataForServiceWorkerRegistration(
- origin, service_worker_registration_id,
- base::Bind(&NotificationMessageFilter::DidGetNotifications,
- weak_factory_io_.GetWeakPtr(), request_id, filter_tag));
-}
-
-void NotificationMessageFilter::DidGetNotifications(
- int request_id,
- const std::string& filter_tag,
- bool success,
- const std::vector<NotificationDatabaseData>& notifications) {
- std::vector<PersistentNotificationInfo> persistent_notifications;
- for (const NotificationDatabaseData& database_data : notifications) {
- if (!filter_tag.empty()) {
- const std::string& tag = database_data.notification_data.tag;
- if (tag != filter_tag)
- continue;
- }
-
- persistent_notifications.push_back(std::make_pair(
- database_data.notification_id, database_data.notification_data));
- }
-
- Send(new PlatformNotificationMsg_DidGetNotifications(
- request_id, persistent_notifications));
-}
-
-void NotificationMessageFilter::OnClosePersistentNotification(
- const GURL& origin,
- const std::string& tag,
- const std::string& notification_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (GetPermissionForOriginOnIO(origin) !=
- blink::mojom::PermissionStatus::GRANTED) {
- return;
- }
-
- PlatformNotificationService* service =
- GetContentClient()->browser()->GetPlatformNotificationService();
- DCHECK(service);
-
- // There's no point in waiting until the database data has been removed before
- // closing the notification presented to the user. Post that task immediately.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&PlatformNotificationService::ClosePersistentNotification,
- base::Unretained(service), // The service is a singleton.
- browser_context_, notification_id));
-
- notification_context_->DeleteNotificationData(
- notification_id, origin,
- base::Bind(
- &NotificationMessageFilter::DidDeletePersistentNotificationData,
- weak_factory_io_.GetWeakPtr()));
-}
-
-void NotificationMessageFilter::DidDeletePersistentNotificationData(
- bool success) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(peter): Consider feeding back to the renderer that the notification
- // has been closed.
-}
-
-blink::mojom::PermissionStatus
-NotificationMessageFilter::GetPermissionForOriginOnIO(
- const GURL& origin) const {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- PlatformNotificationService* service =
- GetContentClient()->browser()->GetPlatformNotificationService();
- if (!service)
- return blink::mojom::PermissionStatus::DENIED;
-
- return service->CheckPermissionOnIOThread(resource_context_, origin,
- process_id_);
-}
-
-bool NotificationMessageFilter::VerifyNotificationPermissionGranted(
- PlatformNotificationService* service,
- const GURL& origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- blink::mojom::PermissionStatus permission_status =
- service->CheckPermissionOnUIThread(browser_context_, origin, process_id_);
-
- // We can't assume that the renderer is compromised at this point because
- // it's possible for the user to revoke an origin's permission between the
- // time where a website requests the notification to be shown and the call
- // arriving in the message filter.
-
- return permission_status == blink::mojom::PermissionStatus::GRANTED;
-}
-
-NotificationIdGenerator* NotificationMessageFilter::GetNotificationIdGenerator()
- const {
- return notification_context_->notification_id_generator();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/notifications/notification_message_filter.h b/chromium/content/browser/notifications/notification_message_filter.h
deleted file mode 100644
index 948e0f18e0c..00000000000
--- a/chromium/content/browser/notifications/notification_message_filter.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2014 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_NOTIFICATIONS_NOTIFICATION_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_MESSAGE_FILTER_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/service_worker/service_worker_status_code.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/notification_database_data.h"
-#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
-
-class GURL;
-
-namespace content {
-
-class BrowserContext;
-class NotificationIdGenerator;
-struct NotificationResources;
-class PlatformNotificationContextImpl;
-struct PlatformNotificationData;
-class PlatformNotificationService;
-class ResourceContext;
-class ServiceWorkerContextWrapper;
-class ServiceWorkerRegistration;
-
-class NotificationMessageFilter : public BrowserMessageFilter {
- public:
- NotificationMessageFilter(
- int process_id,
- PlatformNotificationContextImpl* notification_context,
- ResourceContext* resource_context,
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
- BrowserContext* browser_context);
-
- // BrowserMessageFilter implementation. Called on the UI thread.
- void OnDestruct() const override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- protected:
- ~NotificationMessageFilter() override;
-
- private:
- friend class base::DeleteHelper<NotificationMessageFilter>;
- friend class BrowserThread;
-
- void OnShowPersistentNotification(
- int request_id,
- int64_t service_worker_registration_id,
- const GURL& origin,
- const PlatformNotificationData& notification_data,
- const NotificationResources& notification_resources);
- void OnGetNotifications(int request_id,
- int64_t service_worker_registration_id,
- const GURL& origin,
- const std::string& filter_tag);
- void OnClosePersistentNotification(const GURL& origin,
- const std::string& tag,
- const std::string& notification_id);
-
- // Callback to be invoked by the notification context when the notification
- // data for the persistent notification may have been written, as indicated by
- // |success|. Will present the notification to the user when successful.
- void DidWritePersistentNotificationData(
- int request_id,
- int64_t service_worker_registration_id,
- const GURL& origin,
- const PlatformNotificationData& notification_data,
- const NotificationResources& notification_resources,
- bool success,
- const std::string& notification_id);
-
- // Callback to be invoked by the service worker context when the service
- // worker registration was retrieved. Will present the notification to the
- // user when successful.
- void DidFindServiceWorkerRegistration(
- int request_id,
- const GURL& origin,
- const PlatformNotificationData& notification_data,
- const NotificationResources& notification_resources,
- const std::string& notification_id,
- content::ServiceWorkerStatusCode service_worker_status,
- scoped_refptr<ServiceWorkerRegistration> registration);
-
- // Callback to be invoked when all notifications belonging to a Service Worker
- // registration have been read from the database. The |success| argument
- // indicates whether the data could be read successfully, whereas the actual
- // notifications will be stored in |notifications|.
- void DidGetNotifications(
- int request_id,
- const std::string& filter_tag,
- bool success,
- const std::vector<NotificationDatabaseData>& notifications);
-
- // Callback to be invoked when the data associated with a persistent
- // notification has been removed by the database, unless an error occurred,
- // which will be indicated by |success|.
- void DidDeletePersistentNotificationData(bool success);
-
- // Returns the permission status for |origin|. Must only be used on the IO
- // thread. If the PlatformNotificationService is unavailable, permission will
- // assumed to be denied.
- blink::mojom::PermissionStatus GetPermissionForOriginOnIO(
- const GURL& origin) const;
-
- // Verifies that Web Notification permission has been granted for |origin| in
- // cases where the renderer shouldn't send messages if it weren't the case.
- bool VerifyNotificationPermissionGranted(PlatformNotificationService* service,
- const GURL& origin);
-
- // Returns the NotificationIdGenerator instance owned by the context.
- NotificationIdGenerator* GetNotificationIdGenerator() const;
-
- int process_id_;
- scoped_refptr<PlatformNotificationContextImpl> notification_context_;
- ResourceContext* resource_context_;
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
- BrowserContext* browser_context_;
-
- base::WeakPtrFactory<NotificationMessageFilter> weak_factory_io_;
-
- DISALLOW_COPY_AND_ASSIGN(NotificationMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/oop_browsertest.cc b/chromium/content/browser/oop_browsertest.cc
index e3502bb016c..e6e00b92256 100644
--- a/chromium/content/browser/oop_browsertest.cc
+++ b/chromium/content/browser/oop_browsertest.cc
@@ -35,7 +35,7 @@ class OOPBrowserTest : public ContentBrowserTest {
command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
command_line->AppendSwitch(switches::kEnableOOPRasterization);
- const bool use_gpu_in_tests = !features::IsMusEnabled();
+ const bool use_gpu_in_tests = !features::IsMashEnabled();
if (use_gpu_in_tests)
command_line->AppendSwitch(switches::kUseGpuInTests);
}
@@ -60,7 +60,7 @@ IN_PROC_BROWSER_TEST_F(OOPBrowserTest, Basic) {
NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(base::Bind(
&OOPBrowserTest::VerifyVisualStateUpdated, base::Unretained(this),
- base::MessageLoop::QuitWhenIdleClosure()));
+ base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()));
content::RunMessageLoop();
auto* rwh = shell()->web_contents()->GetRenderViewHost()->GetWidget();
diff --git a/chromium/content/browser/payments/payment_app_browsertest.cc b/chromium/content/browser/payments/payment_app_browsertest.cc
index 53fe0b064f4..bd35aa9b848 100644
--- a/chromium/content/browser/payments/payment_app_browsertest.cc
+++ b/chromium/content/browser/payments/payment_app_browsertest.cc
@@ -178,7 +178,7 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
const std::string& supported_method) {
CanMakePaymentEventDataPtr event_data = CanMakePaymentEventData::New();
- event_data->top_level_origin = GURL("https://example.com");
+ event_data->top_origin = GURL("https://example.com");
event_data->payment_request_origin = GURL("https://example.com");
@@ -202,7 +202,7 @@ class PaymentAppBrowserTest : public ContentBrowserTest {
const std::string& instrument_key) {
PaymentRequestEventDataPtr event_data = PaymentRequestEventData::New();
- event_data->top_level_origin = GURL("https://example.com");
+ event_data->top_origin = GURL("https://example.com");
event_data->payment_request_origin = GURL("https://example.com");
@@ -272,15 +272,15 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, CanMakePayment) {
ClearStoragePartitionData();
- EXPECT_EQ("https://example.com/", PopConsoleString() /* topLevelOrigin */);
+ EXPECT_EQ("https://example.com/", PopConsoleString() /* topOrigin */);
EXPECT_EQ("https://example.com/",
PopConsoleString() /* paymentRequestOrigin */);
EXPECT_EQ("[{\"supportedMethods\":[\"basic-card\"]}]",
PopConsoleString() /* methodData */);
EXPECT_EQ(
"[{\"additionalDisplayItems\":[],\"supportedMethods\":[\"basic-card\"],"
- "\"total\":{\"amount\":{\"currency\":\"USD\",\"currencySystem\":\"urn:"
- "iso:std:iso:4217\",\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
+ "\"total\":{\"amount\":{\"currency\":\"USD\","
+ "\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
"]",
PopConsoleString() /* modifiers */);
}
@@ -316,20 +316,20 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppInvocation) {
registrationIds = GetAllPaymentAppRegistrationIDs();
ASSERT_EQ(0U, registrationIds.size());
- EXPECT_EQ("https://example.com/", PopConsoleString() /* topLevelOrigin */);
+ EXPECT_EQ("https://example.com/", PopConsoleString() /* topOrigin */);
EXPECT_EQ("https://example.com/",
PopConsoleString() /* paymentRequestOrigin */);
EXPECT_EQ("payment-request-id", PopConsoleString() /* paymentRequestId */);
EXPECT_EQ("[{\"supportedMethods\":[\"basic-card\"]}]",
PopConsoleString() /* methodData */);
EXPECT_EQ(
- "{\"currency\":\"USD\",\"currencySystem\":\"urn:iso:std:iso:4217\","
+ "{\"currency\":\"USD\","
"\"value\":\"55\"}",
PopConsoleString() /* total */);
EXPECT_EQ(
"[{\"additionalDisplayItems\":[],\"supportedMethods\":[\"basic-card\"],"
- "\"total\":{\"amount\":{\"currency\":\"USD\",\"currencySystem\":\"urn:"
- "iso:std:iso:4217\",\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
+ "\"total\":{\"amount\":{\"currency\":\"USD\","
+ "\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
"]",
PopConsoleString() /* modifiers */);
EXPECT_EQ("basic-card-payment-app-id",
@@ -353,21 +353,19 @@ IN_PROC_BROWSER_TEST_F(PaymentAppBrowserTest, PaymentAppOpenWindowFailed) {
registrationIds = GetAllPaymentAppRegistrationIDs();
ASSERT_EQ(0U, registrationIds.size());
- EXPECT_EQ("https://example.com/", PopConsoleString() /* topLevelOrigin */);
+ EXPECT_EQ("https://example.com/", PopConsoleString() /* topOrigin */);
EXPECT_EQ("https://example.com/",
PopConsoleString() /* paymentRequestOrigin */);
EXPECT_EQ("payment-request-id", PopConsoleString() /* paymentRequestId */);
EXPECT_EQ("[{\"supportedMethods\":[\"https://bobpay.com\"]}]",
PopConsoleString() /* methodData */);
- EXPECT_EQ(
- "{\"currency\":\"USD\",\"currencySystem\":\"urn:iso:std:iso:4217\","
- "\"value\":\"55\"}",
- PopConsoleString() /* total */);
+ EXPECT_EQ("{\"currency\":\"USD\",\"value\":\"55\"}",
+ PopConsoleString() /* total */);
EXPECT_EQ(
"[{\"additionalDisplayItems\":[],\"supportedMethods\":[\"https://"
"bobpay.com\"],"
- "\"total\":{\"amount\":{\"currency\":\"USD\",\"currencySystem\":\"urn:"
- "iso:std:iso:4217\",\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
+ "\"total\":{\"amount\":{\"currency\":\"USD\","
+ "\"value\":\"55\"},\"label\":\"\",\"pending\":false}}"
"]",
PopConsoleString() /* modifiers */);
EXPECT_EQ("bobpay-payment-app-id", PopConsoleString() /* instrumentKey */);
diff --git a/chromium/content/browser/payments/payment_app_content_unittest_base.cc b/chromium/content/browser/payments/payment_app_content_unittest_base.cc
index 94b10e0fda4..35732115848 100644
--- a/chromium/content/browser/payments/payment_app_content_unittest_base.cc
+++ b/chromium/content/browser/payments/payment_app_content_unittest_base.cc
@@ -66,7 +66,6 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -78,9 +77,8 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
pause_after_download, std::move(dispatcher_request),
- std::move(controller_request), std::move(service_worker_host),
- std::move(instance_host), std::move(provider_info),
- std::move(installed_scripts_info));
+ std::move(controller_request), std::move(instance_host),
+ std::move(provider_info), std::move(installed_scripts_info));
}
void OnPaymentRequestEvent(
@@ -88,9 +86,15 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
mojom::ServiceWorkerEventDispatcher::DispatchPaymentRequestEventCallback
callback) override {
- EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
- std::move(event_data), std::move(response_callback),
- std::move(callback));
+ if (respond_payment_request_immediately) {
+ EmbeddedWorkerTestHelper::OnPaymentRequestEvent(
+ std::move(event_data), std::move(response_callback),
+ std::move(callback));
+ } else {
+ pending_response_callback_ = std::move(response_callback);
+ std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
+ base::Time::Now());
+ }
}
void OnCanMakePaymentEvent(
@@ -114,6 +118,10 @@ class PaymentAppContentUnitTestBase::PaymentAppForWorkerTestHelper
int64_t last_sw_registration_id_;
GURL last_sw_scope_;
+ // Variables to delay payment request response.
+ bool respond_payment_request_immediately = true;
+ payments::mojom::PaymentHandlerResponseCallbackPtr pending_response_callback_;
+
private:
DISALLOW_COPY_AND_ASSIGN(PaymentAppForWorkerTestHelper);
};
@@ -210,6 +218,16 @@ void PaymentAppContentUnitTestBase::UnregisterServiceWorker(
EXPECT_TRUE(called);
}
+void PaymentAppContentUnitTestBase::SetNoPaymentRequestResponseImmediately() {
+ worker_helper_->respond_payment_request_immediately = false;
+}
+
+void PaymentAppContentUnitTestBase::RespondPendingPaymentRequest() {
+ std::move(worker_helper_->pending_response_callback_)
+ ->OnResponseForPaymentRequest(
+ payments::mojom::PaymentHandlerResponse::New(), base::Time::Now());
+}
+
int64_t PaymentAppContentUnitTestBase::last_sw_registration_id() const {
return worker_helper_->last_sw_registration_id_;
}
diff --git a/chromium/content/browser/payments/payment_app_content_unittest_base.h b/chromium/content/browser/payments/payment_app_content_unittest_base.h
index 7b3c482c414..12a82842839 100644
--- a/chromium/content/browser/payments/payment_app_content_unittest_base.h
+++ b/chromium/content/browser/payments/payment_app_content_unittest_base.h
@@ -37,6 +37,9 @@ class PaymentAppContentUnitTestBase : public testing::Test {
int64_t last_sw_registration_id() const;
const GURL& last_sw_scope_url() const;
+ void SetNoPaymentRequestResponseImmediately();
+ void RespondPendingPaymentRequest();
+
private:
class PaymentAppForWorkerTestHelper;
diff --git a/chromium/content/browser/payments/payment_app_context_impl.cc b/chromium/content/browser/payments/payment_app_context_impl.cc
index ed979000a08..f4801e11a63 100644
--- a/chromium/content/browser/payments/payment_app_context_impl.cc
+++ b/chromium/content/browser/payments/payment_app_context_impl.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "content/browser/payments/payment_manager.h"
@@ -82,9 +81,9 @@ void PaymentAppContextImpl::CreatePaymentAppDatabaseOnIO(
void PaymentAppContextImpl::CreatePaymentManagerOnIO(
mojo::InterfaceRequest<payments::mojom::PaymentManager> request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- PaymentManager* payment_manager =
- new PaymentManager(this, std::move(request));
- payment_managers_[payment_manager] = base::WrapUnique(payment_manager);
+ auto payment_manager =
+ std::make_unique<PaymentManager>(this, std::move(request));
+ payment_managers_[payment_manager.get()] = std::move(payment_manager);
}
void PaymentAppContextImpl::ShutdownOnIO() {
diff --git a/chromium/content/browser/payments/payment_app_database.cc b/chromium/content/browser/payments/payment_app_database.cc
index 41360d31265..664e105455e 100644
--- a/chromium/content/browser/payments/payment_app_database.cc
+++ b/chromium/content/browser/payments/payment_app_database.cc
@@ -17,7 +17,7 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/manifest.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"
@@ -71,7 +71,7 @@ PaymentInstrumentPtr ToPaymentInstrumentForMojo(const std::string& input) {
PaymentInstrumentPtr instrument = PaymentInstrument::New();
instrument->name = instrument_proto.name();
for (const auto& icon_proto : instrument_proto.icons()) {
- Manifest::Icon icon;
+ blink::Manifest::Icon icon;
icon.src = GURL(icon_proto.src());
icon.type = base::UTF8ToUTF16(icon_proto.type());
for (const auto& size_proto : icon_proto.sizes()) {
@@ -197,7 +197,7 @@ void PaymentAppDatabase::WritePaymentInstrument(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (instrument->icons.size() > 0) {
- std::vector<Manifest::Icon> icons(instrument->icons);
+ std::vector<blink::Manifest::Icon> icons(instrument->icons);
PaymentInstrumentIconFetcher::Start(
scope, service_worker_context_->GetProviderHostIds(scope.GetOrigin()),
icons,
@@ -457,10 +457,14 @@ void PaymentAppDatabase::DidFindRegistrationToSetPaymentApp(
bool success = payment_app_proto.SerializeToString(&serialized_payment_app);
DCHECK(success);
+ // Constructing registration_id, registration_origin and storage_key before
+ // moving registration.
+ int64_t registration_id = registration->id();
+ GURL registration_origin = registration->pattern().GetOrigin();
+ std::string storage_key = CreatePaymentAppKey(registration->pattern().spec());
service_worker_context_->StoreRegistrationUserData(
- registration->id(), registration->pattern().GetOrigin(),
- {{CreatePaymentAppKey(registration->pattern().spec()),
- serialized_payment_app}},
+ registration_id, registration_origin,
+ {{storage_key, serialized_payment_app}},
base::BindOnce(&PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp,
weak_ptr_factory_.GetWeakPtr(), instrument_key, method,
std::move(callback), std::move(registration)));
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.cc b/chromium/content/browser/payments/payment_app_info_fetcher.cc
index 2d3e5e39810..7ffe9e44457 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.cc
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.cc
@@ -127,7 +127,7 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::RunCallbackAndDestroy() {
void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
const GURL& url,
- const Manifest& manifest) {
+ const blink::Manifest& manifest) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
manifest_url_ = url;
@@ -211,7 +211,7 @@ void PaymentAppInfoFetcher::SelfDeleteFetcher::FetchPaymentAppManifestCallback(
icon_url_ = ManifestIconSelector::FindBestMatchingIcon(
manifest.icons, kPaymentAppIdealIconSize, kPaymentAppMinimumIconSize,
- Manifest::Icon::ANY);
+ blink::Manifest::Icon::ANY);
if (!icon_url_.is_valid()) {
WarnIfPossible(
"No suitable payment handler icon found in the \"icons\" field defined "
diff --git a/chromium/content/browser/payments/payment_app_info_fetcher.h b/chromium/content/browser/payments/payment_app_info_fetcher.h
index 4100d1d7ba7..73dd74fcd45 100644
--- a/chromium/content/browser/payments/payment_app_info_fetcher.h
+++ b/chromium/content/browser/payments/payment_app_info_fetcher.h
@@ -12,7 +12,7 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/browser/stored_payment_app.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/manifest.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace content {
@@ -67,7 +67,7 @@ class PaymentAppInfoFetcher {
// The WebContents::GetManifestCallback.
void FetchPaymentAppManifestCallback(const GURL& url,
- const Manifest& manifest);
+ const blink::Manifest& manifest);
// The ManifestIconDownloader::IconFetchCallback.
void OnIconFetched(const SkBitmap& icon);
diff --git a/chromium/content/browser/payments/payment_app_provider_impl.cc b/chromium/content/browser/payments/payment_app_provider_impl.cc
index 5d4aefd1644..db44e03f061 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl.cc
@@ -13,6 +13,7 @@
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"
@@ -31,6 +32,50 @@ using ServiceWorkerStartCallback =
base::OnceCallback<void(scoped_refptr<ServiceWorkerVersion>,
ServiceWorkerStatusCode)>;
+class RespondWithCallbacks;
+
+// A repository to store invoking payment app callback. It is used to abort
+// payment when the opened payment handler window is closed before payment
+// response is received or timeout.
+// Note that there is only one opened payment handler window per browser
+// context.
+class InvokePaymentAppCallbackRepository {
+ public:
+ static InvokePaymentAppCallbackRepository* GetInstance() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return base::Singleton<InvokePaymentAppCallbackRepository>::get();
+ }
+
+ RespondWithCallbacks* GetCallback(BrowserContext* browser_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto it = invoke_callbacks_.find(browser_context);
+ if (it != invoke_callbacks_.end()) {
+ return it->second;
+ }
+ return nullptr;
+ }
+
+ void SetCallback(BrowserContext* browser_context,
+ RespondWithCallbacks* callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ invoke_callbacks_[browser_context] = callback;
+ }
+
+ void RemoveCallback(BrowserContext* browser_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ invoke_callbacks_.erase(browser_context);
+ }
+
+ private:
+ InvokePaymentAppCallbackRepository() {}
+ ~InvokePaymentAppCallbackRepository() {}
+
+ friend struct base::DefaultSingletonTraits<
+ InvokePaymentAppCallbackRepository>;
+
+ std::map<BrowserContext*, RespondWithCallbacks*> invoke_callbacks_;
+};
+
// Note that one and only one of the callbacks from this class must/should be
// called.
class RespondWithCallbacks
@@ -42,6 +87,7 @@ class RespondWithCallbacks
scoped_refptr<ServiceWorkerVersion> service_worker_version,
PaymentAppProvider::InvokePaymentAppCallback callback)
: browser_context_(browser_context),
+ event_type_(event_type),
service_worker_version_(service_worker_version),
invoke_payment_app_callback_(std::move(callback)),
binding_(this),
@@ -49,13 +95,18 @@ class RespondWithCallbacks
request_id_ = service_worker_version->StartRequest(
event_type, base::BindOnce(&RespondWithCallbacks::OnErrorStatus,
weak_ptr_factory_.GetWeakPtr()));
+ InvokePaymentAppCallbackRepository::GetInstance()->SetCallback(
+ browser_context, this);
}
RespondWithCallbacks(
+ BrowserContext* browser_context,
ServiceWorkerMetrics::EventType event_type,
scoped_refptr<ServiceWorkerVersion> service_worker_version,
PaymentAppProvider::PaymentEventResultCallback callback)
- : service_worker_version_(service_worker_version),
+ : browser_context_(browser_context),
+ event_type_(event_type),
+ service_worker_version_(service_worker_version),
payment_event_result_callback_(std::move(callback)),
binding_(this),
weak_ptr_factory_(this) {
@@ -82,9 +133,7 @@ class RespondWithCallbacks
base::BindOnce(std::move(invoke_payment_app_callback_),
std::move(response)));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&CloseClientWindowOnUIThread, browser_context_));
+ ClearCallbackRepositoryAndCloseWindow();
delete this;
}
@@ -110,9 +159,7 @@ class RespondWithCallbacks
base::BindOnce(std::move(payment_event_result_callback_),
payment_aborted));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&CloseClientWindowOnUIThread, browser_context_));
+ ClearCallbackRepositoryAndCloseWindow();
delete this;
}
@@ -135,18 +182,34 @@ class RespondWithCallbacks
if (event_type_ == ServiceWorkerMetrics::EventType::PAYMENT_REQUEST ||
event_type_ == ServiceWorkerMetrics::EventType::ABORT_PAYMENT) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&CloseClientWindowOnUIThread, browser_context_));
+ ClearCallbackRepositoryAndCloseWindow();
}
delete this;
}
int request_id() { return request_id_; }
+ void AbortPaymentSinceOpennedWindowClosing() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ service_worker_version_->FinishRequest(request_id_, false,
+ base::Time::Now());
+ OnErrorStatus(SERVICE_WORKER_ERROR_ABORT);
+ }
+
private:
~RespondWithCallbacks() override {}
+ void ClearCallbackRepositoryAndCloseWindow() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ InvokePaymentAppCallbackRepository::GetInstance()->RemoveCallback(
+ browser_context_);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&CloseClientWindowOnUIThread, browser_context_));
+ }
+
static void CloseClientWindowOnUIThread(BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -183,6 +246,7 @@ void GetAllPaymentAppsOnIO(
}
void DispatchAbortPaymentEvent(
+ BrowserContext* browser_context,
PaymentAppProvider::PaymentEventResultCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
ServiceWorkerStatusCode service_worker_status) {
@@ -200,9 +264,9 @@ void DispatchAbortPaymentEvent(
ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT, base::DoNothing());
// This object self-deletes after either success or error callback is invoked.
- RespondWithCallbacks* invocation_callbacks =
- new RespondWithCallbacks(ServiceWorkerMetrics::EventType::ABORT_PAYMENT,
- active_version, std::move(callback));
+ RespondWithCallbacks* invocation_callbacks = new RespondWithCallbacks(
+ browser_context, ServiceWorkerMetrics::EventType::ABORT_PAYMENT,
+ active_version, std::move(callback));
active_version->event_dispatcher()->DispatchAbortPaymentEvent(
invocation_callbacks->request_id(),
@@ -211,6 +275,7 @@ void DispatchAbortPaymentEvent(
}
void DispatchCanMakePaymentEvent(
+ BrowserContext* browser_context,
payments::mojom::CanMakePaymentEventDataPtr event_data,
PaymentAppProvider::PaymentEventResultCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
@@ -230,8 +295,8 @@ void DispatchCanMakePaymentEvent(
// This object self-deletes after either success or error callback is invoked.
RespondWithCallbacks* invocation_callbacks = new RespondWithCallbacks(
- ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT, active_version,
- std::move(callback));
+ browser_context, ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT,
+ active_version, std::move(callback));
active_version->event_dispatcher()->DispatchCanMakePaymentEvent(
invocation_callbacks->request_id(), std::move(event_data),
@@ -359,6 +424,16 @@ void CheckPermissionForPaymentApps(
std::move(callback).Run(std::move(permitted_apps));
}
+void AbortInvokePaymentApp(BrowserContext* browser_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ RespondWithCallbacks* callback =
+ InvokePaymentAppCallbackRepository::GetInstance()->GetCallback(
+ browser_context);
+ if (callback)
+ callback->AbortPaymentSinceOpennedWindowClosing();
+}
+
} // namespace
// static
@@ -452,8 +527,8 @@ void PaymentAppProviderImpl::CanMakePayment(
StartServiceWorkerForDispatch(
browser_context, registration_id,
- base::BindOnce(&DispatchCanMakePaymentEvent, std::move(event_data),
- std::move(callback)));
+ base::BindOnce(&DispatchCanMakePaymentEvent, browser_context,
+ std::move(event_data), std::move(callback)));
}
void PaymentAppProviderImpl::AbortPayment(BrowserContext* browser_context,
@@ -463,7 +538,8 @@ void PaymentAppProviderImpl::AbortPayment(BrowserContext* browser_context,
StartServiceWorkerForDispatch(
browser_context, registration_id,
- base::BindOnce(&DispatchAbortPaymentEvent, std::move(callback)));
+ base::BindOnce(&DispatchAbortPaymentEvent, browser_context,
+ std::move(callback)));
}
void PaymentAppProviderImpl::SetOpenedWindow(WebContents* web_contents) {
@@ -488,6 +564,44 @@ void PaymentAppProviderImpl::CloseOpenedWindow(
}
}
+void PaymentAppProviderImpl::OnClosingOpenedWindow(
+ BrowserContext* browser_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&AbortInvokePaymentApp, browser_context));
+}
+
+bool PaymentAppProviderImpl::IsValidInstallablePaymentApp(
+ const GURL& manifest_url,
+ const GURL& sw_js_url,
+ const GURL& sw_scope,
+ std::string* error_message) {
+ DCHECK(manifest_url.is_valid() && sw_js_url.is_valid() &&
+ sw_scope.is_valid());
+
+ // TODO(crbug.com/853924): Unify duplicated code between here and
+ // ServiceWorkerProviderHost::IsValidRegisterMessage.
+ if (ServiceWorkerUtils::ContainsDisallowedCharacter(sw_js_url, sw_scope,
+ error_message)) {
+ return false;
+ }
+
+ std::vector<GURL> urls = {manifest_url, sw_js_url, sw_scope};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+ *error_message =
+ "Origins are not matching, or some origins cannot access service "
+ "worker "
+ "(manifest:" +
+ manifest_url.spec() + " scope:" + sw_scope.spec() +
+ " sw:" + sw_js_url.spec() + ")";
+ return false;
+ }
+
+ return true;
+}
+
PaymentAppProviderImpl::PaymentAppProviderImpl() = default;
PaymentAppProviderImpl::~PaymentAppProviderImpl() = default;
diff --git a/chromium/content/browser/payments/payment_app_provider_impl.h b/chromium/content/browser/payments/payment_app_provider_impl.h
index 09cd78ff9f5..cd7d6956c98 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl.h
+++ b/chromium/content/browser/payments/payment_app_provider_impl.h
@@ -44,6 +44,11 @@ class CONTENT_EXPORT PaymentAppProviderImpl : public PaymentAppProvider {
PaymentEventResultCallback callback) override;
void SetOpenedWindow(WebContents* web_contents) override;
void CloseOpenedWindow(BrowserContext* browser_context) override;
+ void OnClosingOpenedWindow(BrowserContext* browser_context) override;
+ bool IsValidInstallablePaymentApp(const GURL& manifest_url,
+ const GURL& sw_js_url,
+ const GURL& sw_scope,
+ std::string* error_message) override;
private:
PaymentAppProviderImpl();
diff --git a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
index ef9b9a68aa4..6143488d152 100644
--- a/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
+++ b/chromium/content/browser/payments/payment_app_provider_impl_unittest.cc
@@ -110,6 +110,12 @@ class PaymentAppProviderTest : public PaymentAppContentUnitTestBase {
browser_context(), registration_id, std::move(callback));
}
+ void OnClosingOpenedWindow() {
+ PaymentAppProviderImpl::GetInstance()->OnClosingOpenedWindow(
+ browser_context());
+ base::RunLoop().RunUntilIdle();
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(PaymentAppProviderTest);
};
@@ -266,4 +272,51 @@ TEST_F(PaymentAppProviderTest, GetAllPaymentAppsFromTheSameOriginTest) {
ASSERT_EQ(2U, apps[bobpay_b_registration_id]->enabled_methods.size());
}
+TEST_F(PaymentAppProviderTest, AbortPaymentWhenClosingOpenedWindow) {
+ PaymentManager* manager1 = CreatePaymentManager(
+ GURL("https://hellopay.com/a"), GURL("https://hellopay.com/a/script.js"));
+ PaymentManager* manager2 = CreatePaymentManager(
+ GURL("https://bobpay.com/b"), GURL("https://bobpay.com/b/script.js"));
+
+ PaymentHandlerStatus status;
+ SetPaymentInstrument(manager1, "test_key1",
+ payments::mojom::PaymentInstrument::New(),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+ SetPaymentInstrument(manager2, "test_key2",
+ payments::mojom::PaymentInstrument::New(),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+ SetPaymentInstrument(manager2, "test_key3",
+ payments::mojom::PaymentInstrument::New(),
+ base::BindOnce(&SetPaymentInstrumentCallback, &status));
+
+ PaymentAppProvider::PaymentApps apps;
+ GetAllPaymentApps(base::BindOnce(&GetAllPaymentAppsCallback, &apps));
+ ASSERT_EQ(2U, apps.size());
+
+ int64_t bobpay_registration_id = last_sw_registration_id();
+ EXPECT_EQ(apps[bobpay_registration_id]->scope.spec(), "https://bobpay.com/b");
+
+ payments::mojom::PaymentRequestEventDataPtr event_data =
+ payments::mojom::PaymentRequestEventData::New();
+ event_data->method_data.push_back(payments::mojom::PaymentMethodData::New());
+ event_data->total = payments::mojom::PaymentCurrencyAmount::New();
+
+ SetNoPaymentRequestResponseImmediately();
+
+ bool called = false;
+ InvokePaymentApp(bobpay_registration_id, std::move(event_data),
+ base::BindOnce(&InvokePaymentAppCallback, &called));
+ ASSERT_FALSE(called);
+
+ // Abort payment request as closing opened window.
+ OnClosingOpenedWindow();
+ ASSERT_TRUE(called);
+
+ // Response after abort should not crash and take effect.
+ called = false;
+ RespondPendingPaymentRequest();
+ base::RunLoop().RunUntilIdle();
+ ASSERT_FALSE(called);
+}
+
} // namespace content
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
index e2d683926ef..bfcb804f5d0 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.cc
@@ -28,13 +28,13 @@ const int kPaymentAppMinimumIconSize = 0;
void DownloadBestMatchingIcon(
WebContents* web_contents,
- const std::vector<Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback
callback);
void OnIconFetched(
WebContents* web_contents,
- const std::vector<Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback callback,
const SkBitmap& bitmap) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -64,14 +64,14 @@ void OnIconFetched(
void DownloadBestMatchingIcon(
WebContents* web_contents,
- const std::vector<Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback
callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GURL icon_url = ManifestIconSelector::FindBestMatchingIcon(
icons, kPaymentAppIdealIconSize, kPaymentAppMinimumIconSize,
- Manifest::Icon::IconPurpose::ANY);
+ blink::Manifest::Icon::IconPurpose::ANY);
if (web_contents == nullptr || !icon_url.is_valid()) {
// If the icon url is invalid, it's better to give the information to
// developers in advance unlike when fetching or decoding fails. We already
@@ -82,7 +82,7 @@ void DownloadBestMatchingIcon(
return;
}
- std::vector<Manifest::Icon> copy_icons;
+ std::vector<blink::Manifest::Icon> copy_icons;
for (const auto& icon : icons) {
if (icon.src != icon_url) {
copy_icons.emplace_back(icon);
@@ -123,7 +123,7 @@ WebContents* GetWebContentsFromProviderHostIds(
void StartOnUI(
const GURL& scope,
std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
- const std::vector<Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcherCallback
callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -139,7 +139,7 @@ void StartOnUI(
void PaymentInstrumentIconFetcher::Start(
const GURL& scope,
std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
- const std::vector<Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
PaymentInstrumentIconFetcherCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/payments/payment_instrument_icon_fetcher.h b/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
index 9e4f9adb866..e3c5f8e608d 100644
--- a/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
+++ b/chromium/content/browser/payments/payment_instrument_icon_fetcher.h
@@ -11,7 +11,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "content/public/common/manifest.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/platform/modules/payments/payment_app.mojom.h"
namespace content {
@@ -25,7 +25,7 @@ class PaymentInstrumentIconFetcher {
static void Start(
const GURL& scope,
std::unique_ptr<std::vector<std::pair<int, int>>> provider_hosts,
- const std::vector<Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
PaymentInstrumentIconFetcherCallback callback);
private:
diff --git a/chromium/content/browser/permissions/permission_service_context.h b/chromium/content/browser/permissions/permission_service_context.h
index 6c0dda7c6bc..b53bdbbea79 100644
--- a/chromium/content/browser/permissions/permission_service_context.h
+++ b/chromium/content/browser/permissions/permission_service_context.h
@@ -49,6 +49,9 @@ class CONTENT_EXPORT PermissionServiceContext : public WebContentsObserver {
GURL GetEmbeddingOrigin() const;
RenderFrameHost* render_frame_host() const;
+ RenderProcessHost* render_process_host() const {
+ return render_process_host_;
+ }
private:
class PermissionSubscription;
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index f6c0538a690..4c86c799dc9 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -7,9 +7,13 @@
#include <stddef.h>
#include <memory>
+#include <set>
#include <utility>
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
+#include "content/browser/bad_message.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"
@@ -24,44 +28,64 @@ namespace content {
namespace {
-PermissionType PermissionDescriptorToPermissionType(
- const PermissionDescriptorPtr& descriptor) {
+bool PermissionDescriptorToPermissionType(
+ const PermissionDescriptorPtr& descriptor,
+ PermissionType* permission_type) {
switch (descriptor->name) {
case PermissionName::GEOLOCATION:
- return PermissionType::GEOLOCATION;
+ *permission_type = PermissionType::GEOLOCATION;
+ return true;
case PermissionName::NOTIFICATIONS:
- return PermissionType::NOTIFICATIONS;
+ *permission_type = PermissionType::NOTIFICATIONS;
+ return true;
case PermissionName::MIDI: {
if (descriptor->extension && descriptor->extension->is_midi() &&
descriptor->extension->get_midi()->sysex) {
- return PermissionType::MIDI_SYSEX;
+ *permission_type = PermissionType::MIDI_SYSEX;
+ return true;
}
- return PermissionType::MIDI;
+ *permission_type = PermissionType::MIDI;
+ return true;
}
case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
- return PermissionType::PROTECTED_MEDIA_IDENTIFIER;
+#if defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
+ *permission_type = PermissionType::PROTECTED_MEDIA_IDENTIFIER;
+ return true;
+#else
+ NOTIMPLEMENTED();
+ return false;
+#endif // defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
case PermissionName::DURABLE_STORAGE:
- return PermissionType::DURABLE_STORAGE;
+ *permission_type = PermissionType::DURABLE_STORAGE;
+ return true;
case PermissionName::AUDIO_CAPTURE:
- return PermissionType::AUDIO_CAPTURE;
+ *permission_type = PermissionType::AUDIO_CAPTURE;
+ return true;
case PermissionName::VIDEO_CAPTURE:
- return PermissionType::VIDEO_CAPTURE;
+ *permission_type = PermissionType::VIDEO_CAPTURE;
+ return true;
case PermissionName::BACKGROUND_SYNC:
- return PermissionType::BACKGROUND_SYNC;
+ *permission_type = PermissionType::BACKGROUND_SYNC;
+ return true;
case PermissionName::SENSORS:
- return PermissionType::SENSORS;
+ *permission_type = PermissionType::SENSORS;
+ return true;
case PermissionName::ACCESSIBILITY_EVENTS:
- return PermissionType::ACCESSIBILITY_EVENTS;
+ *permission_type = PermissionType::ACCESSIBILITY_EVENTS;
+ return true;
case PermissionName::CLIPBOARD_READ:
- return PermissionType::CLIPBOARD_READ;
+ *permission_type = PermissionType::CLIPBOARD_READ;
+ return true;
case PermissionName::CLIPBOARD_WRITE:
- return PermissionType::CLIPBOARD_WRITE;
+ *permission_type = PermissionType::CLIPBOARD_WRITE;
+ return true;
case PermissionName::PAYMENT_HANDLER:
- return PermissionType::PAYMENT_HANDLER;
+ *permission_type = PermissionType::PAYMENT_HANDLER;
+ return true;
}
NOTREACHED();
- return PermissionType::NUM;
+ return false;
}
// This function allows the usage of the the multiple request map with single
@@ -145,8 +169,19 @@ void PermissionServiceImpl::RequestPermissions(
}
std::vector<PermissionType> types(permissions.size());
- for (size_t i = 0; i < types.size(); ++i)
- types[i] = PermissionDescriptorToPermissionType(permissions[i]);
+ std::set<PermissionType> duplicates_check;
+ for (size_t i = 0; i < types.size(); ++i) {
+ if (!PermissionDescriptorToPermissionType(permissions[i], &types[i])) {
+ ReceivedBadMessage();
+ return;
+ }
+ // Each permission should appear at most once in the message.
+ bool inserted = duplicates_check.insert(types[i]).second;
+ if (!inserted) {
+ ReceivedBadMessage();
+ return;
+ }
+ }
std::unique_ptr<PendingRequest> pending_request =
std::make_unique<PendingRequest>(types, std::move(callback));
@@ -182,8 +217,11 @@ void PermissionServiceImpl::HasPermission(PermissionDescriptorPtr permission,
void PermissionServiceImpl::RevokePermission(
PermissionDescriptorPtr permission,
PermissionStatusCallback callback) {
- PermissionType permission_type =
- PermissionDescriptorToPermissionType(permission);
+ PermissionType permission_type;
+ if (!PermissionDescriptorToPermissionType(permission, &permission_type)) {
+ ReceivedBadMessage();
+ return;
+ }
PermissionStatus status = GetPermissionStatusFromType(permission_type);
// Resetting the permission should only be possible if the permission is
@@ -208,14 +246,23 @@ void PermissionServiceImpl::AddPermissionObserver(
last_known_status = current_status;
}
- context_->CreateSubscription(PermissionDescriptorToPermissionType(permission),
- origin_, std::move(observer));
+ PermissionType type;
+ if (!PermissionDescriptorToPermissionType(permission, &type)) {
+ ReceivedBadMessage();
+ return;
+ }
+
+ context_->CreateSubscription(type, origin_, std::move(observer));
}
PermissionStatus PermissionServiceImpl::GetPermissionStatus(
const PermissionDescriptorPtr& permission) {
- return GetPermissionStatusFromType(
- PermissionDescriptorToPermissionType(permission));
+ PermissionType type;
+ if (!PermissionDescriptorToPermissionType(permission, &type)) {
+ ReceivedBadMessage();
+ return PermissionStatus::DENIED;
+ }
+ return GetPermissionStatusFromType(type);
}
PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
@@ -254,4 +301,16 @@ void PermissionServiceImpl::ResetPermissionStatus(PermissionType type) {
embedding_origin.is_empty() ? requesting_origin : embedding_origin);
}
+void PermissionServiceImpl::ReceivedBadMessage() {
+ if (context_->render_frame_host()) {
+ bad_message::ReceivedBadMessage(
+ context_->render_frame_host()->GetProcess(),
+ bad_message::PERMISSION_SERVICE_BAD_PERMISSION_DESCRIPTOR);
+ } else {
+ bad_message::ReceivedBadMessage(
+ context_->render_process_host(),
+ bad_message::PERMISSION_SERVICE_BAD_PERMISSION_DESCRIPTOR);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/permissions/permission_service_impl.h b/chromium/content/browser/permissions/permission_service_impl.h
index ae0e8a4df99..85359a821fb 100644
--- a/chromium/content/browser/permissions/permission_service_impl.h
+++ b/chromium/content/browser/permissions/permission_service_impl.h
@@ -67,6 +67,7 @@ class CONTENT_EXPORT PermissionServiceImpl
blink::mojom::PermissionStatus GetPermissionStatusFromType(
PermissionType type);
void ResetPermissionStatus(PermissionType type);
+ void ReceivedBadMessage();
RequestsMap pending_requests_;
// context_ owns |this|.
diff --git a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
index 6af72c47f20..5e8617b1ddf 100644
--- a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
+++ b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.cc
@@ -11,19 +11,19 @@ namespace content {
OverlaySurfaceEmbedder::OverlaySurfaceEmbedder(OverlayWindow* window)
: window_(window) {
DCHECK(window_);
- surface_layer_ = std::make_unique<ui::Layer>(ui::LAYER_TEXTURED);
- surface_layer_->SetMasksToBounds(true);
+ video_layer_ = window_->GetVideoLayer();
+ video_layer_->SetMasksToBounds(true);
// The frame provided by the parent window's layer needs to show through
- // |surface_layer_|.
- surface_layer_->SetFillsBoundsOpaquely(false);
- // |surface_layer_| bounds are set with the (0, 0) origin point. The
+ // |video_layer_|.
+ video_layer_->SetFillsBoundsOpaquely(false);
+ // |video_layer_| bounds are set with the (0, 0) origin point. The
// positioning of |window_| is dictated by itself.
- // TODO(apacible): Update |surface_layer_| size when the window is resized.
- // http://crbug.com/726621
- surface_layer_->SetBounds(
+ video_layer_->SetBounds(
gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size()));
- window_->GetLayer()->Add(surface_layer_.get());
+ window_->GetLayer()->Add(video_layer_);
+
+ AddControlsLayers();
}
OverlaySurfaceEmbedder::~OverlaySurfaceEmbedder() = default;
@@ -31,10 +31,45 @@ OverlaySurfaceEmbedder::~OverlaySurfaceEmbedder() = default;
void OverlaySurfaceEmbedder::SetPrimarySurfaceId(
const viz::SurfaceId& surface_id) {
// SurfaceInfo has information about the embedded surface.
- surface_layer_->SetShowPrimarySurface(
+ video_layer_->SetShowPrimarySurface(
surface_id, window_->GetBounds().size(), SK_ColorBLACK,
cc::DeadlinePolicy::UseDefaultDeadline(),
true /* stretch_content_to_fill_bounds */);
}
+void OverlaySurfaceEmbedder::UpdateLayerBounds() {
+ // Update the size and position of the video to stretch on the entire window.
+ gfx::Size window_size = window_->GetBounds().size();
+ gfx::Rect window_bounds = gfx::Rect(gfx::Point(0, 0), window_size);
+ video_layer_->SetBounds(window_bounds);
+ video_layer_->SetSurfaceSize(window_size);
+
+ // Update the size and position of controls.
+ controls_background_layer_->SetBounds(window_bounds);
+ close_controls_layer_->SetBounds(window_->GetCloseControlsBounds());
+ play_pause_controls_layer_->SetBounds(window_->GetPlayPauseControlsBounds());
+}
+
+void OverlaySurfaceEmbedder::AddControlsLayers() {
+ // These control layers are expected to be set up by |window_|.
+ controls_background_layer_ = window_->GetControlsBackgroundLayer();
+ DCHECK(controls_background_layer_);
+ controls_background_layer_->SetBounds(
+ gfx::Rect(gfx::Point(0, 0), window_->GetBounds().size()));
+
+ close_controls_layer_ = window_->GetCloseControlsLayer();
+ DCHECK(close_controls_layer_);
+ close_controls_layer_->SetFillsBoundsOpaquely(false);
+ close_controls_layer_->SetBounds(window_->GetCloseControlsBounds());
+
+ play_pause_controls_layer_ = window_->GetPlayPauseControlsLayer();
+ DCHECK(play_pause_controls_layer_);
+ play_pause_controls_layer_->SetFillsBoundsOpaquely(false);
+ play_pause_controls_layer_->SetBounds(window_->GetPlayPauseControlsBounds());
+
+ window_->GetLayer()->Add(controls_background_layer_);
+ window_->GetLayer()->Add(close_controls_layer_);
+ window_->GetLayer()->Add(play_pause_controls_layer_);
+}
+
} // namespace content
diff --git a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h
index 5b0858944b1..dd0f277dc6d 100644
--- a/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h
+++ b/chromium/content/browser/picture_in_picture/overlay_surface_embedder.h
@@ -24,6 +24,8 @@ class OverlaySurfaceEmbedder {
~OverlaySurfaceEmbedder();
void SetPrimarySurfaceId(const viz::SurfaceId& surface_id);
+ void UpdateLayerBounds();
+ void AddControlsLayers();
private:
// The window which embeds the client. Weak pointer since the
@@ -33,6 +35,13 @@ class OverlaySurfaceEmbedder {
// Contains the client's content.
std::unique_ptr<ui::Layer> surface_layer_;
+ // Owned by the OverlayWindow implementation.
+ // These are set in AddControlsLayer(), which is called in the constructor.
+ ui::Layer* video_layer_ = nullptr;
+ ui::Layer* controls_background_layer_ = nullptr;
+ ui::Layer* close_controls_layer_ = nullptr;
+ ui::Layer* play_pause_controls_layer_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(OverlaySurfaceEmbedder);
};
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
index e3c6e4fa4ed..f0835214f02 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
@@ -40,30 +40,48 @@ PictureInPictureWindowControllerImpl::GetOrCreateForWebContents(
PictureInPictureWindowControllerImpl::~PictureInPictureWindowControllerImpl() {
if (window_)
window_->Close();
+
+ // If the initiator WebContents is being destroyed, there is no need to put
+ // the video's media player in a post-Picture-in-Picture mode. In fact, some
+ // things, such as the MediaWebContentsObserver, may already been torn down.
+ if (initiator_->IsBeingDestroyed())
+ return;
+
+ initiator_->SetHasPictureInPictureVideo(false);
+ OnLeavingPictureInPicture();
}
PictureInPictureWindowControllerImpl::PictureInPictureWindowControllerImpl(
WebContents* initiator)
- : initiator_(initiator) {
+ : initiator_(static_cast<WebContentsImpl* const>(initiator)) {
DCHECK(initiator_);
+ media_web_contents_observer_ = initiator_->media_web_contents_observer();
+
window_ =
- content::GetContentClient()->browser()->CreateWindowForPictureInPicture(
- this);
+ GetContentClient()->browser()->CreateWindowForPictureInPicture(this);
DCHECK(window_) << "Picture in Picture requires a valid window.";
}
-void PictureInPictureWindowControllerImpl::Show() {
+gfx::Size PictureInPictureWindowControllerImpl::Show() {
DCHECK(window_);
DCHECK(surface_id_.is_valid());
+
window_->Show();
+ initiator_->SetHasPictureInPictureVideo(true);
+
+ return window_->GetBounds().size();
}
void PictureInPictureWindowControllerImpl::Close() {
- if (window_)
- window_->Close();
+ DCHECK(window_);
+
+ window_->Hide();
+ initiator_->SetHasPictureInPictureVideo(false);
surface_id_ = viz::SurfaceId();
+
+ OnLeavingPictureInPicture();
}
void PictureInPictureWindowControllerImpl::EmbedSurface(
@@ -73,6 +91,13 @@ void PictureInPictureWindowControllerImpl::EmbedSurface(
DCHECK(surface_id.is_valid());
surface_id_ = surface_id;
+ // Update the media player id in step with the video surface id. If the
+ // surface id was updated for the same video, this is a no-op. This could
+ // be updated for a different video if another media player on the same
+ // |initiator_| enters Picture-in-Picture mode.
+ media_player_id_ =
+ media_web_contents_observer_->GetPictureInPictureVideoMediaPlayerId();
+
window_->UpdateVideoSize(natural_size);
if (!embedder_)
@@ -84,23 +109,52 @@ OverlayWindow* PictureInPictureWindowControllerImpl::GetWindowForTesting() {
return window_.get();
}
-void PictureInPictureWindowControllerImpl::TogglePlayPause() {
+void PictureInPictureWindowControllerImpl::UpdateLayerBounds() {
+ if (window_) {
+ media_web_contents_observer_->OnPictureInPictureWindowResize(
+ window_->GetBounds().size());
+ }
+
+ if (embedder_)
+ embedder_->UpdateLayerBounds();
+}
+
+bool PictureInPictureWindowControllerImpl::IsPlayerActive() {
+ if (!media_player_id_.has_value())
+ media_web_contents_observer_->GetPictureInPictureVideoMediaPlayerId();
+
+ return media_player_id_.has_value() &&
+ media_web_contents_observer_->IsPlayerActive(*media_player_id_);
+}
+
+WebContents* PictureInPictureWindowControllerImpl::GetInitiatorWebContents() {
+ return initiator_;
+}
+
+bool PictureInPictureWindowControllerImpl::TogglePlayPause() {
DCHECK(window_ && window_->IsActive());
- content::MediaWebContentsObserver* observer =
- static_cast<content::WebContentsImpl* const>(initiator_)
- ->media_web_contents_observer();
- base::Optional<content::WebContentsObserver::MediaPlayerId> player_id =
- observer->GetPictureInPictureVideoMediaPlayerId();
- DCHECK(player_id.has_value());
-
- if (observer->IsPlayerActive(*player_id)) {
- player_id->first->Send(new MediaPlayerDelegateMsg_Pause(
- player_id->first->GetRoutingID(), player_id->second));
- } else {
- player_id->first->Send(new MediaPlayerDelegateMsg_Play(
- player_id->first->GetRoutingID(), player_id->second));
+ if (IsPlayerActive()) {
+ media_player_id_->first->Send(new MediaPlayerDelegateMsg_Pause(
+ media_player_id_->first->GetRoutingID(), media_player_id_->second));
+ return false;
+ }
+
+ media_player_id_->first->Send(new MediaPlayerDelegateMsg_Play(
+ media_player_id_->first->GetRoutingID(), media_player_id_->second));
+ return true;
+}
+
+void PictureInPictureWindowControllerImpl::OnLeavingPictureInPicture() {
+ if (IsPlayerActive()) {
+ // Pause the current video so there is only one video playing at a time.
+ media_player_id_->first->Send(new MediaPlayerDelegateMsg_Pause(
+ media_player_id_->first->GetRoutingID(), media_player_id_->second));
}
+
+ media_player_id_->first->Send(
+ new MediaPlayerDelegateMsg_EndPictureInPictureMode(
+ media_player_id_->first->GetRoutingID(), media_player_id_->second));
}
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
index 4746e6915a1..7a960800ec2 100644
--- a/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
+++ b/chromium/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
@@ -13,6 +13,7 @@
namespace content {
class OverlaySurfaceEmbedder;
class WebContents;
+class MediaWebContentsObserver;
// TODO(thakis,mlamouri): PictureInPictureWindowControllerImpl isn't
// CONTENT_EXPORT'd because it creates complicated build issues with
@@ -33,12 +34,15 @@ class PictureInPictureWindowControllerImpl
~PictureInPictureWindowControllerImpl() override;
// PictureInPictureWindowController:
- CONTENT_EXPORT void Show() override;
+ CONTENT_EXPORT gfx::Size Show() override;
CONTENT_EXPORT void Close() override;
CONTENT_EXPORT void EmbedSurface(const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) override;
CONTENT_EXPORT OverlayWindow* GetWindowForTesting() override;
- CONTENT_EXPORT void TogglePlayPause() override;
+ CONTENT_EXPORT void UpdateLayerBounds() override;
+ CONTENT_EXPORT bool IsPlayerActive() override;
+ CONTENT_EXPORT WebContents* GetInitiatorWebContents() override;
+ CONTENT_EXPORT bool TogglePlayPause() override;
private:
friend class WebContentsUserData<PictureInPictureWindowControllerImpl>;
@@ -48,9 +52,17 @@ class PictureInPictureWindowControllerImpl
CONTENT_EXPORT explicit PictureInPictureWindowControllerImpl(
WebContents* initiator);
+ // Signal to the media player that |this| is leaving Picture-in-Picture mode.
+ void OnLeavingPictureInPicture();
+
std::unique_ptr<OverlayWindow> window_;
std::unique_ptr<OverlaySurfaceEmbedder> embedder_;
- content::WebContents* const initiator_;
+ WebContentsImpl* const initiator_;
+
+ // Used to determine the state of the media player and route messages to
+ // the corresponding media player with id |media_player_id_|.
+ MediaWebContentsObserver* media_web_contents_observer_;
+ base::Optional<WebContentsObserver::MediaPlayerId> media_player_id_;
viz::SurfaceId surface_id_;
@@ -59,4 +71,4 @@ class PictureInPictureWindowControllerImpl
} // namespace content
-#endif // CONTENT_BROWSER_PICTURE_IN_PICTURE_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_IMPL_H_ \ No newline at end of file
+#endif // CONTENT_BROWSER_PICTURE_IN_PICTURE_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_IMPL_H_
diff --git a/chromium/content/browser/plugin_data_remover_impl.cc b/chromium/content/browser/plugin_data_remover_impl.cc
index 3090fe463df..9e6ef2a6610 100644
--- a/chromium/content/browser/plugin_data_remover_impl.cc
+++ b/chromium/content/browser/plugin_data_remover_impl.cc
@@ -9,7 +9,6 @@
#include <limits>
#include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
@@ -107,7 +106,6 @@ class PluginDataRemoverImpl::Context
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- remove_start_time_ = base::Time::Now();
is_removing_ = true;
// Balanced in OnPpapiChannelOpened.
@@ -219,8 +217,6 @@ class PluginDataRemoverImpl::Context
void OnPpapiClearSiteDataResult(uint32_t request_id, bool success) {
DCHECK_EQ(0u, request_id);
LOG_IF(ERROR, !success) << "ClearSiteData returned error";
- UMA_HISTOGRAM_TIMES("ClearPluginData.time",
- base::Time::Now() - remove_start_time_);
SignalDone();
}
@@ -235,8 +231,6 @@ class PluginDataRemoverImpl::Context
}
std::unique_ptr<base::WaitableEvent> event_;
- // The point in time when we start removing data.
- base::Time remove_start_time_;
// The point in time from which on we remove data.
base::Time begin_time_;
bool is_removing_;
diff --git a/chromium/content/browser/pointer_lock_browsertest.cc b/chromium/content/browser/pointer_lock_browsertest.cc
index b60766b97b4..1e547b71308 100644
--- a/chromium/content/browser/pointer_lock_browsertest.cc
+++ b/chromium/content/browser/pointer_lock_browsertest.cc
@@ -247,7 +247,8 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockEventRouting) {
gfx::PointF transformed_point;
root_view->TransformPointToCoordSpaceForView(gfx::PointF(0, 0), child_view,
- &transformed_point);
+ &transformed_point,
+ viz::EventSource::MOUSE);
mouse_event.SetPositionInWidget(-transformed_point.x() + 14,
-transformed_point.y() + 15);
@@ -481,7 +482,8 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
gfx::PointF transformed_point;
root_view->TransformPointToCoordSpaceForView(gfx::PointF(0, 0), child_view,
- &transformed_point);
+ &transformed_point,
+ viz::EventSource::MOUSE);
wheel_event.SetPositionInWidget(-transformed_point.x() + 14,
-transformed_point.y() + 15);
diff --git a/chromium/content/browser/power_monitor_browsertest.cc b/chromium/content/browser/power_monitor_browsertest.cc
index 76132c11da8..633b768ff5f 100644
--- a/chromium/content/browser/power_monitor_browsertest.cc
+++ b/chromium/content/browser/power_monitor_browsertest.cc
@@ -119,10 +119,12 @@ class PowerMonitorTest : public ContentBrowserTest {
DCHECK(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
}
} else if (source_info.identity.name() == mojom::kUtilityServiceName) {
- ++request_count_from_utility_;
-
- DCHECK(utility_bound_closure_);
- std::move(utility_bound_closure_).Run();
+ // If the network service is enabled, it will create utility processes
+ // without a utility closure.
+ if (utility_bound_closure_) {
+ ++request_count_from_utility_;
+ std::move(utility_bound_closure_).Run();
+ }
} else if (source_info.identity.name() == mojom::kGpuServiceName) {
++request_count_from_gpu_;
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index 251df387700..f2de22ce7fe 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -25,17 +25,16 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_channel_switches.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/process_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_names.mojom.h"
-#include "content/public/common/zygote_buildflags.h"
#include "mojo/edk/embedder/embedder.h"
#include "net/base/network_change_notifier.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/sandbox/switches.h"
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
#include "ui/base/ui_base_switches.h"
#if defined(OS_WIN)
@@ -48,7 +47,7 @@
#endif
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
-#include "content/public/common/zygote_handle.h"
+#include "services/service_manager/zygote/common/zygote_handle.h" // nogncheck
#endif
namespace content {
@@ -58,8 +57,7 @@ class PpapiPluginSandboxedProcessLauncherDelegate
: public content::SandboxedProcessLauncherDelegate {
public:
explicit PpapiPluginSandboxedProcessLauncherDelegate(bool is_broker)
-#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \
- defined(OS_WIN)
+#if BUILDFLAG(USE_ZYGOTE_HANDLE) || defined(OS_WIN)
: is_broker_(is_broker)
#endif
{
@@ -104,14 +102,14 @@ class PpapiPluginSandboxedProcessLauncherDelegate
#endif // OS_WIN
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
- ZygoteHandle GetZygote() override {
+ service_manager::ZygoteHandle GetZygote() override {
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
base::CommandLine::StringType plugin_launcher = browser_command_line
.GetSwitchValueNative(switches::kPpapiPluginLauncher);
if (is_broker_ || !plugin_launcher.empty())
return nullptr;
- return GetGenericZygote();
+ return service_manager::GetGenericZygote();
}
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
@@ -124,8 +122,7 @@ class PpapiPluginSandboxedProcessLauncherDelegate
}
private:
-#if (defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) || \
- defined(OS_WIN)
+#if BUILDFLAG(USE_ZYGOTE_HANDLE) || defined(OS_WIN)
bool is_broker_;
#endif
@@ -367,10 +364,10 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
if (!is_broker_) {
static const char* const kPluginForwardSwitches[] = {
service_manager::switches::kDisableSeccompFilterSandbox,
+ service_manager::switches::kNoSandbox,
#if defined(OS_MACOSX)
- switches::kEnableSandboxLogging,
+ service_manager::switches::kEnableSandboxLogging,
#endif
- switches::kNoSandbox,
switches::kPpapiStartupDialog,
};
cmd_line->CopySwitchesFrom(browser_command_line, kPluginForwardSwitches,
diff --git a/chromium/content/browser/presentation/presentation_service_impl.cc b/chromium/content/browser/presentation/presentation_service_impl.cc
index 367e9558162..321adbda8a1 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include <utility>
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "content/public/browser/content_browser_client.h"
@@ -18,14 +19,24 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/frame_navigate_params.h"
#include "content/public/common/presentation_connection_message.h"
+using blink::mojom::PresentationConnectionState;
+using blink::mojom::PresentationError;
+using blink::mojom::PresentationErrorPtr;
+using blink::mojom::PresentationErrorType;
+using blink::mojom::PresentationInfo;
+using blink::mojom::PresentationInfoPtr;
+using blink::mojom::ScreenAvailability;
+
namespace content {
namespace {
-const int kInvalidRequestId = -1;
+static constexpr int kInvalidRequestId = -1;
+static constexpr size_t kMaxPresentationIdLength = 256;
int GetNextRequestId() {
static int next_request_id = 0;
@@ -35,9 +46,9 @@ int GetNextRequestId() {
void InvokeNewPresentationCallbackWithError(
PresentationServiceImpl::NewPresentationCallback callback) {
std::move(callback).Run(
- base::nullopt,
- PresentationError(
- PRESENTATION_ERROR_PREVIOUS_START_IN_PROGRESS,
+ PresentationInfoPtr(),
+ PresentationError::New(
+ PresentationErrorType::PREVIOUS_START_IN_PROGRESS,
"There is already an unsettled Promise from a previous call "
"to start."));
}
@@ -54,6 +65,7 @@ PresentationServiceImpl::PresentationServiceImpl(
controller_delegate_(controller_delegate),
receiver_delegate_(receiver_delegate),
start_presentation_request_id_(kInvalidRequestId),
+ binding_(this),
// TODO(imcheng): Consider using RenderFrameHost* directly instead of IDs.
render_process_id_(render_frame_host->GetProcess()->GetID()),
render_frame_id_(render_frame_host->GetRoutingID()),
@@ -68,9 +80,6 @@ PresentationServiceImpl::PresentationServiceImpl(
if (auto* delegate = GetPresentationServiceDelegate())
delegate->AddObserver(render_process_id_, render_frame_id_, this);
-
- bindings_.set_connection_error_handler(base::BindRepeating(
- &PresentationServiceImpl::OnConnectionError, base::Unretained(this)));
}
PresentationServiceImpl::~PresentationServiceImpl() {
@@ -87,8 +96,8 @@ PresentationServiceImpl::~PresentationServiceImpl() {
// static
std::unique_ptr<PresentationServiceImpl> PresentationServiceImpl::Create(
RenderFrameHost* render_frame_host) {
- DVLOG(2) << __func__ << render_frame_host->GetProcess()->GetID() << ", "
- << render_frame_host->GetRoutingID();
+ DVLOG(2) << __func__ << ": " << render_frame_host->GetProcess()->GetID()
+ << ", " << render_frame_host->GetRoutingID();
WebContents* web_contents =
WebContents::FromRenderFrameHost(render_frame_host);
DCHECK(web_contents);
@@ -110,7 +119,9 @@ std::unique_ptr<PresentationServiceImpl> PresentationServiceImpl::Create(
void PresentationServiceImpl::Bind(
blink::mojom::PresentationServiceRequest request) {
- bindings_.AddBinding(this, std::move(request));
+ binding_.Bind(std::move(request));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &PresentationServiceImpl::OnConnectionError, base::Unretained(this)));
}
void PresentationServiceImpl::SetController(
@@ -127,9 +138,15 @@ void PresentationServiceImpl::SetController(
void PresentationServiceImpl::SetReceiver(
blink::mojom::PresentationReceiverPtr receiver) {
- // The render frame should register a PresentationReceiver only once, and
- // this should be done when the navigator.presentation.receiver is
- // initialized.
+ // Presentation receiver virtual layout tests (which have the flag set) has no
+ // ReceiverPresentationServiceDelegate implementation.
+ // TODO(imcheng): Refactor content_browser_client to return a no-op
+ // PresentationService instead.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForcePresentationReceiverForTesting)) {
+ return;
+ }
+
if (!receiver_delegate_ || !is_main_frame_) {
mojo::ReportBadMessage(
"SetReceiver can only be called from a "
@@ -154,8 +171,8 @@ void PresentationServiceImpl::ListenForScreenAvailability(const GURL& url) {
DVLOG(2) << "ListenForScreenAvailability " << url.spec();
if (!controller_delegate_ || !url.is_valid()) {
if (controller_) {
- controller_->OnScreenAvailabilityUpdated(
- url, blink::mojom::ScreenAvailability::UNAVAILABLE);
+ controller_->OnScreenAvailabilityUpdated(url,
+ ScreenAvailability::UNAVAILABLE);
}
return;
}
@@ -194,9 +211,9 @@ void PresentationServiceImpl::StartPresentation(
DVLOG(2) << "StartPresentation";
if (!controller_delegate_) {
std::move(callback).Run(
- base::nullopt,
- PresentationError(PRESENTATION_ERROR_NO_AVAILABLE_SCREENS,
- "No screens found."));
+ PresentationInfoPtr(),
+ PresentationError::New(PresentationErrorType::NO_AVAILABLE_SCREENS,
+ "No screens found."));
return;
}
@@ -230,9 +247,9 @@ void PresentationServiceImpl::ReconnectPresentation(
DVLOG(2) << "ReconnectPresentation";
if (!controller_delegate_) {
std::move(callback).Run(
- base::nullopt,
- PresentationError(PRESENTATION_ERROR_NO_PRESENTATION_FOUND,
- "Error joining route: No matching route"));
+ PresentationInfoPtr(),
+ PresentationError::New(PresentationErrorType::NO_PRESENTATION_FOUND,
+ "Error joining route: No matching route"));
return;
}
@@ -284,7 +301,9 @@ void PresentationServiceImpl::OnStartPresentationSucceeded(
return;
CHECK(pending_start_presentation_cb_.get());
- pending_start_presentation_cb_->Run(presentation_info, base::nullopt);
+ DCHECK(presentation_info.id.length() <= kMaxPresentationIdLength);
+ pending_start_presentation_cb_->Run(PresentationInfo::New(presentation_info),
+ PresentationErrorPtr());
ListenForConnectionStateChange(presentation_info);
pending_start_presentation_cb_.reset();
start_presentation_request_id_ = kInvalidRequestId;
@@ -292,12 +311,13 @@ void PresentationServiceImpl::OnStartPresentationSucceeded(
void PresentationServiceImpl::OnStartPresentationError(
int request_id,
- const PresentationError& error) {
+ const blink::mojom::PresentationError& error) {
if (request_id != start_presentation_request_id_)
return;
CHECK(pending_start_presentation_cb_.get());
- pending_start_presentation_cb_->Run(base::nullopt, error);
+ pending_start_presentation_cb_->Run(PresentationInfoPtr(),
+ PresentationError::New(error));
pending_start_presentation_cb_.reset();
start_presentation_request_id_ = kInvalidRequestId;
}
@@ -305,29 +325,31 @@ void PresentationServiceImpl::OnStartPresentationError(
void PresentationServiceImpl::OnReconnectPresentationSucceeded(
int request_id,
const PresentationInfo& presentation_info) {
+ DCHECK(presentation_info.id.length() <= kMaxPresentationIdLength);
if (RunAndEraseReconnectPresentationMojoCallback(
- request_id, presentation_info, base::nullopt)) {
+ request_id, PresentationInfo::New(presentation_info),
+ PresentationErrorPtr())) {
ListenForConnectionStateChange(presentation_info);
}
}
void PresentationServiceImpl::OnReconnectPresentationError(
int request_id,
- const PresentationError& error) {
- RunAndEraseReconnectPresentationMojoCallback(request_id, base::nullopt,
- error);
+ const blink::mojom::PresentationError& error) {
+ RunAndEraseReconnectPresentationMojoCallback(
+ request_id, PresentationInfoPtr(), PresentationError::New(error));
}
bool PresentationServiceImpl::RunAndEraseReconnectPresentationMojoCallback(
int request_id,
- const base::Optional<PresentationInfo>& presentation_info,
- const base::Optional<PresentationError>& error) {
+ PresentationInfoPtr presentation_info,
+ PresentationErrorPtr error) {
auto it = pending_reconnect_presentation_cbs_.find(request_id);
if (it == pending_reconnect_presentation_cbs_.end())
return false;
DCHECK(it->second.get());
- it->second->Run(presentation_info, error);
+ it->second->Run(std::move(presentation_info), std::move(error));
pending_reconnect_presentation_cbs_.erase(it);
return true;
}
@@ -372,16 +394,17 @@ void PresentationServiceImpl::OnConnectionStateChanged(
const PresentationInfo& connection,
const PresentationConnectionStateChangeInfo& info) {
DVLOG(2) << "PresentationServiceImpl::OnConnectionStateChanged "
- << "[presentation_id]: " << connection.presentation_id
+ << "[presentation_id]: " << connection.id
<< " [state]: " << info.state;
if (!controller_)
return;
- if (info.state == PRESENTATION_CONNECTION_STATE_CLOSED) {
- controller_->OnConnectionClosed(connection, info.close_reason,
- info.message);
+ if (info.state == PresentationConnectionState::CLOSED) {
+ controller_->OnConnectionClosed(PresentationInfo::New(connection),
+ info.close_reason, info.message);
} else {
- controller_->OnConnectionStateChanged(connection, info.state);
+ controller_->OnConnectionStateChanged(PresentationInfo::New(connection),
+ info.state);
}
}
@@ -406,7 +429,7 @@ PresentationServiceImpl::GetPresentationServiceDelegate() {
}
void PresentationServiceImpl::SetPresentationConnection(
- const PresentationInfo& presentation_info,
+ PresentationInfoPtr presentation_info,
blink::mojom::PresentationConnectionPtr controller_connection_ptr,
blink::mojom::PresentationConnectionRequest receiver_connection_request) {
DVLOG(2) << "SetPresentationConnection";
@@ -415,19 +438,19 @@ void PresentationServiceImpl::SetPresentationConnection(
return;
controller_delegate_->ConnectToPresentation(
- render_process_id_, render_frame_id_, presentation_info,
+ render_process_id_, render_frame_id_, *presentation_info,
std::move(controller_connection_ptr),
std::move(receiver_connection_request));
}
void PresentationServiceImpl::OnReceiverConnectionAvailable(
- const content::PresentationInfo& presentation_info,
+ PresentationInfoPtr presentation_info,
PresentationConnectionPtr controller_connection_ptr,
PresentationConnectionRequest receiver_connection_request) {
DVLOG(2) << "PresentationServiceImpl::OnReceiverConnectionAvailable";
receiver_->OnReceiverConnectionAvailable(
- presentation_info, std::move(controller_connection_ptr),
+ std::move(presentation_info), std::move(controller_connection_ptr),
std::move(receiver_connection_request));
}
@@ -467,7 +490,7 @@ void PresentationServiceImpl::Reset() {
pending_reconnect_presentation_cbs_.clear();
- bindings_.CloseAllBindings();
+ binding_.Close();
controller_.reset();
receiver_.reset();
}
@@ -482,7 +505,8 @@ void PresentationServiceImpl::OnDelegateDestroyed() {
void PresentationServiceImpl::OnDefaultPresentationStarted(
const PresentationInfo& connection) {
if (controller_)
- controller_->OnDefaultPresentationStarted(connection);
+ controller_->OnDefaultPresentationStarted(
+ PresentationInfo::New(connection));
ListenForConnectionStateChange(connection);
}
@@ -519,17 +543,18 @@ PresentationServiceImpl::NewPresentationCallbackWrapper::
~NewPresentationCallbackWrapper() {
if (!callback_.is_null()) {
std::move(callback_).Run(
- base::nullopt,
- PresentationError(PRESENTATION_ERROR_PRESENTATION_REQUEST_CANCELLED,
- "The frame is navigating or being destroyed."));
+ PresentationInfoPtr(),
+ PresentationError::New(
+ PresentationErrorType::PRESENTATION_REQUEST_CANCELLED,
+ "The frame is navigating or being destroyed."));
}
}
void PresentationServiceImpl::NewPresentationCallbackWrapper::Run(
- const base::Optional<PresentationInfo>& presentation_info,
- const base::Optional<PresentationError>& error) {
+ PresentationInfoPtr presentation_info,
+ PresentationErrorPtr error) {
DCHECK(!callback_.is_null());
- std::move(callback_).Run(presentation_info, error);
+ std::move(callback_).Run(std::move(presentation_info), std::move(error));
}
} // namespace content
diff --git a/chromium/content/browser/presentation/presentation_service_impl.h b/chromium/content/browser/presentation/presentation_service_impl.h
index 4a3155bc541..333d2ac479c 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.h
+++ b/chromium/content/browser/presentation/presentation_service_impl.h
@@ -17,14 +17,13 @@
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/presentation_screen_availability_listener.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/frame_navigate_params.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
#include "url/gurl.h"
@@ -56,8 +55,8 @@ class CONTENT_EXPORT PresentationServiceImpl
public PresentationServiceDelegate::Observer {
public:
using NewPresentationCallback =
- base::OnceCallback<void(const base::Optional<PresentationInfo>&,
- const base::Optional<PresentationError>&)>;
+ base::OnceCallback<void(blink::mojom::PresentationInfoPtr,
+ blink::mojom::PresentationErrorPtr)>;
// Creates a PresentationServiceImpl using the given RenderFrameHost.
static std::unique_ptr<PresentationServiceImpl> Create(
@@ -87,7 +86,7 @@ class CONTENT_EXPORT PresentationServiceImpl
void Terminate(const GURL& presentation_url,
const std::string& presentation_id) override;
void SetPresentationConnection(
- const PresentationInfo& presentation_info,
+ blink::mojom::PresentationInfoPtr presentation_info,
blink::mojom::PresentationConnectionPtr controller_connection_ptr,
blink::mojom::PresentationConnectionRequest receiver_connection_request)
override;
@@ -145,8 +144,8 @@ class CONTENT_EXPORT PresentationServiceImpl
explicit NewPresentationCallbackWrapper(NewPresentationCallback callback);
~NewPresentationCallbackWrapper();
- void Run(const base::Optional<PresentationInfo>& presentation_info,
- const base::Optional<PresentationError>& error);
+ void Run(blink::mojom::PresentationInfoPtr presentation_info,
+ blink::mojom::PresentationErrorPtr error);
private:
NewPresentationCallback callback_;
@@ -178,7 +177,8 @@ class CONTENT_EXPORT PresentationServiceImpl
// Passed to embedder's implementation of PresentationServiceDelegate for
// later invocation when default presentation has started.
- void OnDefaultPresentationStarted(const PresentationInfo& presentation_info);
+ void OnDefaultPresentationStarted(
+ const blink::mojom::PresentationInfo& presentation_info);
// Finds the callback from |pending_reconnect_presentation_cbs_| using
// |request_id|.
@@ -187,8 +187,8 @@ class CONTENT_EXPORT PresentationServiceImpl
// was found.
bool RunAndEraseReconnectPresentationMojoCallback(
int request_id,
- const base::Optional<PresentationInfo>& presentation_info,
- const base::Optional<PresentationError>& error);
+ blink::mojom::PresentationInfoPtr presentation_info,
+ blink::mojom::PresentationErrorPtr error);
// Removes all listeners and resets default presentation URL on this instance
// and informs the PresentationServiceDelegate of such.
@@ -197,30 +197,34 @@ class CONTENT_EXPORT PresentationServiceImpl
// These functions are bound as base::Callbacks and passed to
// embedder's implementation of PresentationServiceDelegate for later
// invocation.
- void OnStartPresentationSucceeded(int request_id,
- const PresentationInfo& presentation_info);
- void OnStartPresentationError(int request_id, const PresentationError& error);
+ void OnStartPresentationSucceeded(
+ int request_id,
+ const blink::mojom::PresentationInfo& presentation_info);
+ void OnStartPresentationError(int request_id,
+ const blink::mojom::PresentationError& error);
void OnReconnectPresentationSucceeded(
int request_id,
- const PresentationInfo& presentation_info);
- void OnReconnectPresentationError(int request_id,
- const PresentationError& error);
+ const blink::mojom::PresentationInfo& presentation_info);
+ void OnReconnectPresentationError(
+ int request_id,
+ const blink::mojom::PresentationError& error);
// Calls to |delegate_| to start listening for state changes for |connection|.
// State changes will be returned via |OnConnectionStateChanged|.
- void ListenForConnectionStateChange(const PresentationInfo& connection);
+ void ListenForConnectionStateChange(
+ const blink::mojom::PresentationInfo& connection);
// Passed to embedder's implementation of PresentationServiceDelegate for
// later invocation when connection messages arrive.
void OnConnectionMessages(
- const content::PresentationInfo& presentation_info,
+ const blink::mojom::PresentationInfo& presentation_info,
std::vector<content::PresentationConnectionMessage> messages);
// A callback registered to LocalPresentationManager when
// the PresentationServiceImpl for the presentation receiver is initialized.
// Calls |receiver_| to create a new PresentationConnection on receiver page.
void OnReceiverConnectionAvailable(
- const content::PresentationInfo& presentation_info,
+ blink::mojom::PresentationInfoPtr presentation_info,
PresentationConnectionPtr controller_connection_ptr,
PresentationConnectionRequest receiver_connection_request);
@@ -233,7 +237,7 @@ class CONTENT_EXPORT PresentationServiceImpl
// Invoked by the embedder's PresentationServiceDelegate when a
// PresentationConnection's state has changed.
void OnConnectionStateChanged(
- const PresentationInfo& connection,
+ const blink::mojom::PresentationInfo& connection,
const PresentationConnectionStateChangeInfo& info);
// Returns true if this object is associated with |render_frame_host|.
@@ -283,8 +287,8 @@ class CONTENT_EXPORT PresentationServiceImpl
base::hash_map<int, linked_ptr<NewPresentationCallbackWrapper>>
pending_reconnect_presentation_cbs_;
- // RAII binding of |this| to PresentationService requests.
- mojo::BindingSet<blink::mojom::PresentationService> bindings_;
+ // RAII binding of |this| to PresentationService request.
+ mojo::Binding<blink::mojom::PresentationService> binding_;
// ID of the RenderFrameHost this object is associated with.
int render_process_id_;
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index 58ce9132e07..ad4ff3ef346 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -14,18 +14,22 @@
#include <vector>
#include "base/run_loop.h"
-#include "base/test/mock_callback.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/presentation_request.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/common/presentation_connection_message.h"
-#include "content/public/common/presentation_info.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "testing/gmock/include/gmock/gmock.h"
+using blink::mojom::PresentationConnectionCloseReason;
+using blink::mojom::PresentationConnectionState;
+using blink::mojom::PresentationError;
+using blink::mojom::PresentationErrorType;
+using blink::mojom::PresentationInfo;
+using blink::mojom::PresentationInfoPtr;
using blink::mojom::ScreenAvailability;
using ::testing::_;
using ::testing::Eq;
@@ -39,22 +43,13 @@ namespace content {
namespace {
-MATCHER(OptionalIsNotNull, "") {
- return !!arg;
-}
-
-MATCHER(OptionalIsNull, "") {
- return !arg;
-}
-
MATCHER_P(PresentationUrlsAre, expected_urls, "") {
return arg.presentation_urls == expected_urls;
}
-// Matches content::PresentationInfo.
+// Matches blink::mojom::PresentationInfo.
MATCHER_P(InfoEquals, expected, "") {
- return expected.presentation_url == arg.presentation_url &&
- expected.presentation_id == arg.presentation_id;
+ return expected.url == arg.url && expected.id == arg.id;
}
ACTION_TEMPLATE(SaveArgByMove,
@@ -105,19 +100,21 @@ class MockPresentationServiceDelegate
// TODO(crbug.com/729950): Use MOCK_METHOD directly once GMock gets the
// move-only type support.
- void StartPresentation(const PresentationRequest& request,
- PresentationConnectionCallback success_cb,
- PresentationConnectionErrorCallback error_cb) {
+ void StartPresentation(
+ const PresentationRequest& request,
+ PresentationConnectionCallback success_cb,
+ PresentationConnectionErrorCallback error_cb) override {
StartPresentationInternal(request, success_cb, error_cb);
}
MOCK_METHOD3(StartPresentationInternal,
void(const PresentationRequest& request,
PresentationConnectionCallback& success_cb,
PresentationConnectionErrorCallback& error_cb));
- void ReconnectPresentation(const PresentationRequest& request,
- const std::string& presentation_id,
- PresentationConnectionCallback success_cb,
- PresentationConnectionErrorCallback error_cb) {
+ void ReconnectPresentation(
+ const PresentationRequest& request,
+ const std::string& presentation_id,
+ PresentationConnectionCallback success_cb,
+ PresentationConnectionErrorCallback error_cb) override {
ReconnectPresentationInternal(request, presentation_id, success_cb,
error_cb);
}
@@ -193,15 +190,15 @@ class MockPresentationServiceDelegate
class MockPresentationReceiver : public blink::mojom::PresentationReceiver {
public:
void OnReceiverConnectionAvailable(
- const content::PresentationInfo& info,
+ PresentationInfoPtr info,
blink::mojom::PresentationConnectionPtr controller_connection,
blink::mojom::PresentationConnectionRequest receiver_connection_request)
override {
- OnReceiverConnectionAvailable(info);
+ OnReceiverConnectionAvailable(*info);
}
MOCK_METHOD1(OnReceiverConnectionAvailable,
- void(const content::PresentationInfo& info));
+ void(const PresentationInfo& info));
};
class MockReceiverPresentationServiceDelegate
@@ -222,7 +219,7 @@ class MockPresentationConnection : public blink::mojom::PresentationConnection {
public:
// PresentationConnectionMessage is move-only.
void OnMessage(PresentationConnectionMessage message,
- base::OnceCallback<void(bool)> send_message_cb) {
+ base::OnceCallback<void(bool)> send_message_cb) override {
OnMessageInternal(message, send_message_cb);
}
MOCK_METHOD2(OnMessageInternal,
@@ -236,24 +233,37 @@ class MockPresentationController : public blink::mojom::PresentationController {
public:
MOCK_METHOD2(OnScreenAvailabilityUpdated,
void(const GURL& url, ScreenAvailability availability));
- MOCK_METHOD2(OnConnectionStateChanged,
+ void OnConnectionStateChanged(PresentationInfoPtr connection,
+ PresentationConnectionState new_state) {
+ OnConnectionStateChangedInternal(*connection, new_state);
+ }
+ MOCK_METHOD2(OnConnectionStateChangedInternal,
void(const PresentationInfo& connection,
PresentationConnectionState new_state));
- MOCK_METHOD3(OnConnectionClosed,
+ void OnConnectionClosed(
+ PresentationInfoPtr connection,
+ blink::mojom::PresentationConnectionCloseReason reason,
+ const std::string& message) {
+ OnConnectionClosedInternal(*connection, reason, message);
+ }
+ MOCK_METHOD3(OnConnectionClosedInternal,
void(const PresentationInfo& connection,
- PresentationConnectionCloseReason reason,
+ blink::mojom::PresentationConnectionCloseReason reason,
const std::string& message));
// PresentationConnectionMessage is move-only.
void OnConnectionMessagesReceived(
- const PresentationInfo& presentation_info,
+ PresentationInfoPtr presentation_info,
std::vector<PresentationConnectionMessage> messages) {
- OnConnectionMessagesReceivedInternal(presentation_info, messages);
+ OnConnectionMessagesReceivedInternal(*presentation_info, messages);
}
MOCK_METHOD2(
OnConnectionMessagesReceivedInternal,
void(const PresentationInfo& presentation_info,
const std::vector<PresentationConnectionMessage>& messages));
- MOCK_METHOD1(OnDefaultPresentationStarted,
+ void OnDefaultPresentationStarted(PresentationInfoPtr presentation_info) {
+ OnDefaultPresentationStartedInternal(*presentation_info);
+ }
+ MOCK_METHOD1(OnDefaultPresentationStartedInternal,
void(const PresentationInfo& presentation_info));
};
@@ -284,6 +294,13 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
presentation_urls_.push_back(presentation_url1_);
presentation_urls_.push_back(presentation_url2_);
+
+ expect_presentation_success_cb_ =
+ base::BindOnce(&PresentationServiceImplTest::ExpectPresentationSuccess,
+ base::Unretained(this));
+ expect_presentation_error_cb_ =
+ base::BindOnce(&PresentationServiceImplTest::ExpectPresentationError,
+ base::Unretained(this));
}
void TearDown() override {
@@ -338,6 +355,25 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
service_impl_->screen_availability_listeners_.end());
}
+ void ExpectPresentationSuccess(PresentationInfoPtr info,
+ blink::mojom::PresentationErrorPtr error) {
+ EXPECT_FALSE(info.is_null());
+ EXPECT_TRUE(error.is_null());
+ presentation_cb_was_run_ = true;
+ }
+
+ void ExpectPresentationError(PresentationInfoPtr info,
+ blink::mojom::PresentationErrorPtr error) {
+ EXPECT_TRUE(info.is_null());
+ EXPECT_FALSE(error.is_null());
+ presentation_cb_was_run_ = true;
+ }
+
+ void ExpectPresentationCallbackWasRun() const {
+ EXPECT_TRUE(presentation_cb_was_run_)
+ << "ExpectPresentationSuccess or ExpectPresentationError was called";
+ }
+
MockPresentationServiceDelegate mock_delegate_;
MockReceiverPresentationServiceDelegate mock_receiver_delegate_;
@@ -351,6 +387,10 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
GURL presentation_url2_;
GURL presentation_url3_;
std::vector<GURL> presentation_urls_;
+
+ NewPresentationCallback expect_presentation_success_cb_;
+ NewPresentationCallback expect_presentation_error_cb_;
+ bool presentation_cb_was_run_ = false;
};
TEST_F(PresentationServiceImplTest, ListenForScreenAvailability) {
@@ -429,8 +469,8 @@ TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrls) {
PresentationInfo presentation_info(presentation_url2_, kPresentationId);
- EXPECT_CALL(mock_controller_,
- OnDefaultPresentationStarted(InfoEquals(presentation_info)));
+ EXPECT_CALL(mock_controller_, OnDefaultPresentationStartedInternal(
+ InfoEquals(presentation_info)));
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _));
std::move(callback).Run(
PresentationInfo(presentation_url2_, kPresentationId));
@@ -463,11 +503,11 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionStateChange) {
.WillOnce(SaveArg<3>(&state_changed_cb));
service_impl_->ListenForConnectionStateChange(connection);
- EXPECT_CALL(mock_controller_, OnConnectionStateChanged(
+ EXPECT_CALL(mock_controller_, OnConnectionStateChangedInternal(
InfoEquals(presentation_connection),
- PRESENTATION_CONNECTION_STATE_TERMINATED));
+ PresentationConnectionState::TERMINATED));
state_changed_cb.Run(PresentationConnectionStateChangeInfo(
- PRESENTATION_CONNECTION_STATE_TERMINATED));
+ PresentationConnectionState::TERMINATED));
base::RunLoop().RunUntilIdle();
}
@@ -482,14 +522,14 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionClose) {
// |mock_controller_|.
PresentationInfo presentation_connection(presentation_url1_, kPresentationId);
PresentationConnectionStateChangeInfo closed_info(
- PRESENTATION_CONNECTION_STATE_CLOSED);
- closed_info.close_reason = PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY;
+ PresentationConnectionState::CLOSED);
+ closed_info.close_reason = PresentationConnectionCloseReason::WENT_AWAY;
closed_info.message = "Foo";
EXPECT_CALL(mock_controller_,
- OnConnectionClosed(InfoEquals(presentation_connection),
- PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY,
- "Foo"));
+ OnConnectionClosedInternal(
+ InfoEquals(presentation_connection),
+ PresentationConnectionCloseReason::WENT_AWAY, "Foo"));
state_changed_cb.Run(closed_info);
base::RunLoop().RunUntilIdle();
}
@@ -505,31 +545,29 @@ TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrls) {
}
TEST_F(PresentationServiceImplTest, StartPresentationSuccess) {
- base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationInfo&)> success_cb;
EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _))
.WillOnce(SaveArgByMove<1>(&success_cb));
service_impl_->StartPresentation(presentation_urls_,
- mock_presentation_cb.Get());
+ std::move(expect_presentation_success_cb_));
EXPECT_FALSE(success_cb.is_null());
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.Times(1);
- EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNotNull(), OptionalIsNull()));
std::move(success_cb)
.Run(PresentationInfo(presentation_url1_, kPresentationId));
+ ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, StartPresentationError) {
- base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationError&)> error_cb;
EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _))
.WillOnce(SaveArgByMove<2>(&error_cb));
service_impl_->StartPresentation(presentation_urls_,
- mock_presentation_cb.Get());
+ std::move(expect_presentation_error_cb_));
EXPECT_FALSE(error_cb.is_null());
- EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNull(), OptionalIsNotNull()));
std::move(error_cb).Run(
- PresentationError(PRESENTATION_ERROR_UNKNOWN, "Error message"));
+ PresentationError(PresentationErrorType::UNKNOWN, "Error message"));
+ ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, StartPresentationInProgress) {
@@ -540,40 +578,39 @@ TEST_F(PresentationServiceImplTest, StartPresentationInProgress) {
// This request should fail immediately, since there is already a
// StartPresentation in progress.
- base::MockCallback<NewPresentationCallback> mock_presentation_cb;
- EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNull(), OptionalIsNotNull()));
service_impl_->StartPresentation(presentation_urls_,
- mock_presentation_cb.Get());
+ std::move(expect_presentation_error_cb_));
+ ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, ReconnectPresentationSuccess) {
- base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationInfo&)> success_cb;
EXPECT_CALL(mock_delegate_,
ReconnectPresentationInternal(_, kPresentationId, _, _))
.WillOnce(SaveArgByMove<2>(&success_cb));
- service_impl_->ReconnectPresentation(presentation_urls_, kPresentationId,
- mock_presentation_cb.Get());
+ service_impl_->ReconnectPresentation(
+ presentation_urls_, kPresentationId,
+ std::move(expect_presentation_success_cb_));
EXPECT_FALSE(success_cb.is_null());
EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
.Times(1);
- EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNotNull(), OptionalIsNull()));
std::move(success_cb)
.Run(PresentationInfo(presentation_url1_, kPresentationId));
+ ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, ReconnectPresentationError) {
- base::MockCallback<NewPresentationCallback> mock_presentation_cb;
base::OnceCallback<void(const PresentationError&)> error_cb;
EXPECT_CALL(mock_delegate_,
ReconnectPresentationInternal(_, kPresentationId, _, _))
.WillOnce(SaveArgByMove<3>(&error_cb));
- service_impl_->ReconnectPresentation(presentation_urls_, kPresentationId,
- mock_presentation_cb.Get());
+ service_impl_->ReconnectPresentation(
+ presentation_urls_, kPresentationId,
+ std::move(expect_presentation_error_cb_));
EXPECT_FALSE(error_cb.is_null());
- EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNull(), OptionalIsNotNull()));
std::move(error_cb).Run(
- PresentationError(PRESENTATION_ERROR_UNKNOWN, "Error message"));
+ PresentationError(PresentationErrorType::UNKNOWN, "Error message"));
+ ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, MaxPendingReconnectPresentationRequests) {
@@ -593,10 +630,10 @@ TEST_F(PresentationServiceImplTest, MaxPendingReconnectPresentationRequests) {
std::vector<GURL> urls = {GURL(base::StringPrintf(presentation_url, i))};
// Exceeded maximum queue size, should invoke mojo callback with error.
- base::MockCallback<NewPresentationCallback> mock_presentation_cb;
- EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNull(), OptionalIsNotNull()));
service_impl_->ReconnectPresentation(
- urls, base::StringPrintf(presentation_id, i), mock_presentation_cb.Get());
+ urls, base::StringPrintf(presentation_id, i),
+ std::move(expect_presentation_error_cb_));
+ ExpectPresentationCallbackWasRun();
}
TEST_F(PresentationServiceImplTest, CloseConnection) {
@@ -610,7 +647,8 @@ TEST_F(PresentationServiceImplTest, Terminate) {
}
TEST_F(PresentationServiceImplTest, SetPresentationConnection) {
- PresentationInfo presentation_info(presentation_url1_, kPresentationId);
+ PresentationInfoPtr presentation_info =
+ PresentationInfo::New(presentation_url1_, kPresentationId);
blink::mojom::PresentationConnectionPtr connection;
MockPresentationConnection mock_presentation_connection;
@@ -624,7 +662,7 @@ TEST_F(PresentationServiceImplTest, SetPresentationConnection) {
_, _, InfoEquals(expected), _));
service_impl_->SetPresentationConnection(
- presentation_info, std::move(connection), std::move(request));
+ std::move(presentation_info), std::move(connection), std::move(request));
}
TEST_F(PresentationServiceImplTest, ReceiverPresentationServiceDelegate) {
@@ -646,7 +684,7 @@ TEST_F(PresentationServiceImplTest, ReceiverPresentationServiceDelegate) {
service_impl.SetReceiver(std::move(receiver_ptr));
EXPECT_FALSE(callback.is_null());
- PresentationInfo presentation_info(presentation_url1_, kPresentationId);
+ PresentationInfo expected(presentation_url1_, kPresentationId);
// Client gets notified of receiver connections.
blink::mojom::PresentationConnectionPtr controller_connection;
@@ -656,9 +694,10 @@ TEST_F(PresentationServiceImplTest, ReceiverPresentationServiceDelegate) {
blink::mojom::PresentationConnectionPtr receiver_connection;
EXPECT_CALL(mock_receiver,
- OnReceiverConnectionAvailable(InfoEquals(presentation_info)))
+ OnReceiverConnectionAvailable(InfoEquals(expected)))
.Times(1);
- callback.Run(presentation_info, std::move(controller_connection),
+ callback.Run(PresentationInfo::New(expected),
+ std::move(controller_connection),
mojo::MakeRequest(&receiver_connection));
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/public/common/zygote_features.gni b/chromium/content/browser/process_internals/BUILD.gn
index c7580b35ff3..fedd9d9609b 100644
--- a/chromium/content/public/common/zygote_features.gni
+++ b/chromium/content/browser/process_internals/BUILD.gn
@@ -2,4 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-use_zygote_handle = is_posix && !is_android && !is_mac
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojo_bindings") {
+ sources = [
+ "process_internals.mojom",
+ ]
+}
diff --git a/chromium/content/browser/process_internals/OWNERS b/chromium/content/browser/process_internals/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/content/browser/process_internals/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/browser/process_internals/process_internals.mojom b/chromium/content/browser/process_internals/process_internals.mojom
new file mode 100644
index 00000000000..da65f0ffb15
--- /dev/null
+++ b/chromium/content/browser/process_internals/process_internals.mojom
@@ -0,0 +1,17 @@
+// 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.
+
+module mojom;
+
+// Interface used by chrome://process-internals to query data from the
+// browser process.
+interface ProcessInternalsHandler {
+
+ // Returns a string containing the currently active isolation modes.
+ GetIsolationMode() => (string mode);
+
+ // Returns a list of isolated origins in their serialized to string
+ // format. This avoids duplicating serialization code to JavaScript.
+ GetIsolatedOrigins() => (array<string> isolated_origins);
+};
diff --git a/chromium/content/browser/process_internals/process_internals_handler_impl.cc b/chromium/content/browser/process_internals/process_internals_handler_impl.cc
new file mode 100644
index 00000000000..ae4fc6d9ac6
--- /dev/null
+++ b/chromium/content/browser/process_internals/process_internals_handler_impl.cc
@@ -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.
+
+#include "content/browser/process_internals/process_internals_handler_impl.h"
+
+#include "content/browser/process_internals/process_internals.mojom.h"
+#include "content/public/browser/site_isolation_policy.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+
+ProcessInternalsHandlerImpl::ProcessInternalsHandlerImpl(
+ mojo::InterfaceRequest<::mojom::ProcessInternalsHandler> request)
+ : binding_(this, std::move(request)) {}
+
+ProcessInternalsHandlerImpl::~ProcessInternalsHandlerImpl() = default;
+
+void ProcessInternalsHandlerImpl::GetIsolationMode(
+ GetIsolationModeCallback callback) {
+ std::vector<base::StringPiece> modes;
+ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
+ modes.push_back("Site Per Process");
+ if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled())
+ modes.push_back("Top Document Isolation");
+ if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
+ modes.push_back("Isolate Origins");
+
+ std::move(callback).Run(modes.empty() ? "Disabled"
+ : base::JoinString(modes, ", "));
+}
+
+void ProcessInternalsHandlerImpl::GetIsolatedOrigins(
+ GetIsolatedOriginsCallback callback) {
+ std::vector<url::Origin> origins_list =
+ SiteIsolationPolicy::GetIsolatedOrigins();
+ std::vector<std::string> origins;
+ for (size_t i = 0; i < origins_list.size(); ++i)
+ origins.push_back(origins_list[i].Serialize());
+
+ std::move(callback).Run(origins);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/process_internals/process_internals_handler_impl.h b/chromium/content/browser/process_internals/process_internals_handler_impl.h
new file mode 100644
index 00000000000..3a8ee50a94e
--- /dev/null
+++ b/chromium/content/browser/process_internals/process_internals_handler_impl.h
@@ -0,0 +1,35 @@
+// 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_PROCESS_INTERNALS_PROCESS_INTERNALS_HANDLER_IMPL_H_
+#define CONTENT_BROWSER_PROCESS_INTERNALS_PROCESS_INTERNALS_HANDLER_IMPL_H_
+
+#include "content/browser/process_internals/process_internals.mojom.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace content {
+
+// Implementation of the ProcessInternalsHandler interface, which is used to
+// communicate between the chrome://process-internals/ WebUI and the browser
+// process.
+class ProcessInternalsHandlerImpl : public ::mojom::ProcessInternalsHandler {
+ public:
+ ProcessInternalsHandlerImpl(
+ mojo::InterfaceRequest<::mojom::ProcessInternalsHandler> request);
+ ~ProcessInternalsHandlerImpl() override;
+
+ // mojom::ProcessInternalsHandler overrides:
+ void GetIsolationMode(GetIsolationModeCallback callback) override;
+ void GetIsolatedOrigins(GetIsolatedOriginsCallback callback) override;
+
+ private:
+ mojo::Binding<::mojom::ProcessInternalsHandler> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessInternalsHandlerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PROCESS_INTERNALS_PROCESS_INTERNALS_HANDLER_IMPL_H_
diff --git a/chromium/content/browser/process_internals/process_internals_ui.cc b/chromium/content/browser/process_internals/process_internals_ui.cc
new file mode 100644
index 00000000000..f6015e79efd
--- /dev/null
+++ b/chromium/content/browser/process_internals/process_internals_ui.cc
@@ -0,0 +1,73 @@
+// 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/process_internals/process_internals_ui.h"
+
+#include <memory>
+
+#include "base/macros.h"
+#include "content/grit/content_resources.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/browser/web_ui_message_handler.h"
+#include "content/public/common/bindings_policy.h"
+#include "content/public/common/url_constants.h"
+
+#include "content/browser/process_internals/process_internals.mojom.h"
+#include "content/browser/process_internals/process_internals_handler_impl.h"
+
+#include "content/public/common/bindings_policy.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace content {
+
+ProcessInternalsUI::ProcessInternalsUI(WebUI* web_ui)
+ : WebUIController(web_ui), WebContentsObserver(web_ui->GetWebContents()) {
+ // Grant only Mojo WebUI bindings, since this WebUI will not use
+ // chrome.send().
+ web_ui->SetBindings(content::BINDINGS_POLICY_WEB_UI);
+
+ // Create a WebUIDataSource to serve the HTML/JS files to the WebUI.
+ WebUIDataSource* source =
+ WebUIDataSource::Create(kChromeUIProcessInternalsHost);
+
+ source->AddResourcePath("process_internals.js", IDR_PROCESS_INTERNALS_JS);
+ source->AddResourcePath("process_internals.mojom.js",
+ IDR_PROCESS_INTERNALS_MOJO_JS);
+ source->SetDefaultResource(IDR_PROCESS_INTERNALS_HTML);
+ source->UseGzip();
+
+ WebUIDataSource::Add(web_contents()->GetBrowserContext(), source);
+
+ AddHandlerToRegistry(
+ base::BindRepeating(&ProcessInternalsUI::BindProcessInternalsHandler,
+ base::Unretained(this)));
+}
+
+ProcessInternalsUI::~ProcessInternalsUI() = default;
+
+void ProcessInternalsUI::BindProcessInternalsHandler(
+ ::mojom::ProcessInternalsHandlerRequest request) {
+ ui_handler_ =
+ std::make_unique<ProcessInternalsHandlerImpl>(std::move(request));
+}
+
+void ProcessInternalsUI::OnInterfaceRequestFromFrame(
+ content::RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) {
+ // This should not be requested by subframes, so terminate the renderer if
+ // it issues such a request.
+ if (render_frame_host->GetParent()) {
+ render_frame_host->GetProcess()->ShutdownForBadMessage(
+ content::RenderProcessHost::CrashReportMode::GENERATE_CRASH_DUMP);
+ return;
+ }
+
+ registry_.TryBindInterface(interface_name, interface_pipe);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/process_internals/process_internals_ui.h b/chromium/content/browser/process_internals/process_internals_ui.h
new file mode 100644
index 00000000000..8c760bcf5f8
--- /dev/null
+++ b/chromium/content/browser/process_internals/process_internals_ui.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 CONTENT_BROWSER_PROCESS_INTERNALS_PROCESS_INTERNALS_UI_H_
+#define CONTENT_BROWSER_PROCESS_INTERNALS_PROCESS_INTERNALS_UI_H_
+
+#include "content/browser/process_internals/process_internals.mojom.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+
+namespace content {
+
+// WebUI which handles serving the chrome://process-internals page.
+// TODO(nasko): Change the inheritance of this class to be from
+// MojoWebUIController, so the registry_ can be removed and properly
+// inherited from common base class for Mojo WebUIs.
+class ProcessInternalsUI : public WebUIController, public WebContentsObserver {
+ public:
+ explicit ProcessInternalsUI(WebUI* web_ui);
+ ~ProcessInternalsUI() override;
+
+ // content::WebContentsObserver implementation.
+ void OnInterfaceRequestFromFrame(
+ content::RenderFrameHost* render_frame_host,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle* interface_pipe) override;
+
+ template <typename Binder>
+ void AddHandlerToRegistry(Binder binder) {
+ registry_.AddInterface(std::move(binder));
+ }
+ void BindProcessInternalsHandler(
+ ::mojom::ProcessInternalsHandlerRequest request);
+
+ private:
+ std::unique_ptr<::mojom::ProcessInternalsHandler> ui_handler_;
+ service_manager::BinderRegistry registry_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessInternalsUI);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PROCESS_INTERNALS_PROCESS_INTERNALS_UI_H_
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index e2a73e36e6d..8ac26e104a5 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -60,4 +60,7 @@ specific_include_rules = {
"render_widget_host_input_event_router.cc": [
"+content/browser/frame_host/render_widget_host_view_guest.h",
],
+ "render_widget_host_view_base\.cc": [
+ "+content/browser/frame_host/render_widget_host_view_guest.h",
+ ],
}
diff --git a/chromium/content/browser/renderer_host/OWNERS b/chromium/content/browser/renderer_host/OWNERS
index cfd24da8ccd..d671fbdac2c 100644
--- a/chromium/content/browser/renderer_host/OWNERS
+++ b/chromium/content/browser/renderer_host/OWNERS
@@ -23,13 +23,13 @@ fsamuel@chromium.org
per-file *delegated_frame*=fsamuel@chromium.org
# WebSQL
-per-file database_*=jsbell@chromium.org
-per-file database_*=michaeln@chromium.org
-per-file database_*=pwnall@chromium.org
-
-# Offscreen Canvas
-per-file offscreen_canvas*.*=xlai@chromium.org
-per-file offscreen_canvas*.*=xidachen@chromium.org
-per-file offscreen_canvas*.*=junov@chromium.org
+per-file web_database_*=jsbell@chromium.org
+per-file web_database_*=pwnall@chromium.org
+
+# Embedded Frame Sinks (eg. Offscreen Canvas)
+per-file embedded_frame_sink*.*=xlai@chromium.org
+per-file embedded_frame_sink*.*=xidachen@chromium.org
+per-file embedded_frame_sink*.*=junov@chromium.org
+per-file embedded_frame_sink*.*=kylechar@chromium.org
# COMPONENT: Internals>Core
diff --git a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
index e7d40839956..bc9eba153a6 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -11,9 +11,11 @@
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "components/viz/common/surfaces/scoped_surface_id_allocator.h"
#include "content/browser/renderer_host/delegated_frame_host.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
+#include "ui/compositor/layer_observer.h"
#include "ui/display/display.h"
namespace ui {
@@ -31,7 +33,7 @@ class BrowserCompositorMacClient {
virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
virtual void DidReceiveFirstFrameAfterNavigation() = 0;
virtual void DestroyCompositorForShutdown() = 0;
- virtual void WasResized() = 0;
+ virtual bool SynchronizeVisualProperties() = 0;
};
// This class owns a DelegatedFrameHost, and will dynamically attach and
@@ -42,7 +44,8 @@ class BrowserCompositorMacClient {
// is visible.
// - The RenderWidgetHostViewMac that is used to display these frames is
// attached to the NSView hierarchy of an NSWindow.
-class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
+class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
+ public ui::LayerObserver {
public:
BrowserCompositorMac(
ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
@@ -60,6 +63,12 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
// potentially visible).
void ClearCompositorFrame();
+ bool RequestRepaintForTesting();
+
+ // Return the parameters of the most recently received frame, or nullptr if
+ // no valid frame is available.
+ const gfx::CALayerParams* GetLastCALayerParams() const;
+
gfx::AcceleratedWidget GetAcceleratedWidget();
void DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink);
@@ -78,9 +87,11 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
bool UpdateNSViewAndDisplay(const gfx::Size& new_size_dip,
const display::Display& new_display);
- // Update the renderer's SurfaceId to reflect |size_dip| in anticipation of
- // the NSView resizing during auto-resize.
- void UpdateForAutoResize(const gfx::Size& size_dip);
+ // Update the renderer's SurfaceId to reflect |new_size_in_pixels| in
+ // anticipation of the NSView resizing during auto-resize.
+ void SynchronizeVisualProperties(
+ const gfx::Size& new_size_in_pixels,
+ const viz::LocalSurfaceId& child_allocated_local_surface_id);
// This is used to ensure that the ui::Compositor be attached to the
// DelegatedFrameHost while the RWHImpl is visible.
@@ -94,11 +105,20 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
// hidden (e.g, because it is occluded by another window).
void SetNSViewAttachedToWindow(bool attached);
+ // Sets or clears the parent ui::Layer and updates state to reflect that
+ // we are now using the ui::Compositor from |parent_ui_layer| (if non-nullptr)
+ // or one from |recyclable_compositor_| (if a compositor is needed).
+ void SetParentUiLayer(ui::Layer* parent_ui_layer);
+
viz::FrameSinkId GetRootFrameSinkId();
const gfx::Size& GetRendererSize() const { return dfh_size_dip_; }
void GetRendererScreenInfo(ScreenInfo* screen_info) const;
- const viz::LocalSurfaceId& GetRendererLocalSurfaceId() const;
+ viz::ScopedSurfaceIdAllocator GetScopedRendererSurfaceIdAllocator(
+ base::OnceCallback<void()> allocation_task);
+ const viz::LocalSurfaceId& GetRendererLocalSurfaceId();
+ bool UpdateRendererLocalSurfaceIdFromChild(
+ const viz::LocalSurfaceId& child_allocated_local_surface_id);
// Indicate that the recyclable compositor should be destroyed, and no future
// compositors should be recycled.
@@ -108,12 +128,8 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
ui::Layer* DelegatedFrameHostGetLayer() const override;
bool DelegatedFrameHostIsVisible() const override;
SkColor DelegatedFrameHostGetGutterColor() const override;
- bool DelegatedFrameCanCreateResizeLock() const override;
- std::unique_ptr<CompositorResizeLock> DelegatedFrameHostCreateResizeLock()
- override;
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnBeginFrame(base::TimeTicks frame_time) override;
- bool IsAutoResizeEnabled() const override;
void OnFrameTokenChanged(uint32_t frame_token) override;
void DidReceiveFirstFrameAfterNavigation() override;
@@ -121,25 +137,34 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
return weak_factory_.GetWeakPtr();
}
- // Returns nullptr if no compositor is attached.
- ui::Compositor* CompositorForTesting() const;
-
void DidNavigate();
void BeginPauseForFrame(bool auto_resize_enabled);
void EndPauseForFrame();
bool ShouldContinueToPauseForFrame() const;
+ bool ForceNewSurfaceForTesting();
+
+ ui::Compositor* GetCompositorForTesting() const;
+
private:
+ // ui::LayerObserver implementation:
+ void LayerDestroyed(ui::Layer* layer) override;
+
+ cc::DeadlinePolicy GetDeadlinePolicy() const;
+
// The state of |delegated_frame_host_| and |recyclable_compositor_| to
- // manage being visible, hidden, or occluded.
+ // manage being visible, occluded, hidden, or drawn via a ui::Layer. Note that
+ // TransitionToState will transition through each intermediate state according
+ // to enum values (e.g, going from HasAttachedCompositor to HasNoCompositor
+ // will temporarily go through HasDetachedCompositor).
enum State {
// Effects:
// - |recyclable_compositor_| exists and is attached to
// |delegated_frame_host_|.
// Happens when:
// - |render_widet_host_| is in the visible state.
- HasAttachedCompositor,
+ HasAttachedCompositor = 0,
// Effects:
// - |recyclable_compositor_| exists, but |delegated_frame_host_| is
// hidden and detached from it.
@@ -150,7 +175,7 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
// around so that we will have content to show when we are un-occluded. If
// we had a way to keep the CALayers attached to the NSView while
// detaching the ui::Compositor, then there would be no need for this
- HasDetachedCompositor,
+ HasDetachedCompositor = 1,
// Effects:
// - |recyclable_compositor_| has been recycled and |delegated_frame_host_|
// is hidden and detached from it.
@@ -158,14 +183,22 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
// - The |render_widget_host_| hidden or gone, and |cocoa_view_| is not
// attached to an NSWindow.
// - This happens for backgrounded tabs.
- HasNoCompositor,
+ HasNoCompositor = 2,
+ // Effects:
+ // - |recyclable_compositor_| does not exist. |delegated_frame_host_| is
+ // attached to |parent_ui_layer_|'s compositor.
+ // Happens when:
+ // - |parent_ui_layer_| is non-nullptr.
+ UseParentLayerCompositor = 3,
};
State state_ = HasNoCompositor;
void UpdateState();
void TransitionToState(State new_state);
- void GetViewProperties(gfx::Size* bounds_in_dip,
- float* scale_factor,
- gfx::ColorSpace* color_space) const;
+
+ // Weak pointer to the layer supplied and reset via SetParentUiLayer. |this|
+ // is an observer of |parent_ui_layer_|, to ensure that |parent_ui_layer_|
+ // always be valid when non-null.
+ ui::Layer* parent_ui_layer_ = nullptr;
bool render_widget_host_is_hidden_ = true;
bool ns_view_attached_to_window_ = false;
@@ -188,12 +221,6 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
gfx::Size dfh_size_dip_;
display::Display dfh_display_;
- // The viz::ParentLocalSurfaceIdAllocator for the ui::Compositor dispenses
- // viz::LocalSurfaceIds that are renderered into by the ui::Compositor.
- viz::ParentLocalSurfaceIdAllocator compositor_local_surface_id_allocator_;
- gfx::Size compositor_size_pixels_;
- float compositor_scale_factor_ = 1.f;
-
// Used to disable screen updates while resizing (because frames are drawn in
// the GPU process, they can end up appearing on-screen before our window
// resizes).
@@ -206,7 +233,6 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient {
ScreenUpdatesDisabled,
} repaint_state_ = RepaintState::None;
bool repaint_auto_resize_enabled_ = false;
-
bool is_first_navigation_ = true;
base::WeakPtrFactory<BrowserCompositorMac> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
index 3d5a2193bd5..3d12a1126a0 100644
--- a/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -4,8 +4,8 @@
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
+#import <Cocoa/Cocoa.h>
#include <stdint.h>
-
#include <utility>
#include "base/command_line.h"
@@ -14,7 +14,6 @@
#include "base/trace_event/trace_event.h"
#include "components/viz/common/features.h"
#include "content/browser/compositor/image_transport_factory.h"
-#include "content/browser/renderer_host/compositor_resize_lock.h"
#include "content/browser/renderer_host/display_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/context_factory.h"
@@ -75,6 +74,8 @@ class RecyclableCompositorMac : public ui::CompositorObserver {
ui::AcceleratedWidgetMac* accelerated_widget_mac() {
return accelerated_widget_mac_.get();
}
+ const gfx::Size pixel_size() const { return size_pixels_; }
+ float scale_factor() const { return scale_factor_; }
// Suspend will prevent the compositor from producing new frames. This should
// be called to avoid creating spurious frames while changing state.
@@ -82,6 +83,17 @@ class RecyclableCompositorMac : public ui::CompositorObserver {
void Suspend();
void Unsuspend();
+ // Update the compositor's surface information, if needed.
+ void UpdateSurface(const gfx::Size& size_pixels, float scale_factor);
+ // Invalidate the compositor's surface information.
+ void InvalidateSurface();
+
+ // The viz::ParentLocalSurfaceIdAllocator for the ui::Compositor dispenses
+ // viz::LocalSurfaceIds that are renderered into by the ui::Compositor.
+ viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
+ gfx::Size size_pixels_;
+ float scale_factor_ = 1.f;
+
private:
RecyclableCompositorMac();
@@ -129,11 +141,29 @@ void RecyclableCompositorMac::Unsuspend() {
compositor_suspended_lock_ = nullptr;
}
+void RecyclableCompositorMac::UpdateSurface(const gfx::Size& size_pixels,
+ float scale_factor) {
+ if (size_pixels != size_pixels_ || scale_factor != scale_factor_) {
+ size_pixels_ = size_pixels;
+ scale_factor_ = scale_factor;
+ compositor()->SetScaleAndSize(scale_factor_, size_pixels_,
+ local_surface_id_allocator_.GenerateId());
+ }
+}
+
+void RecyclableCompositorMac::InvalidateSurface() {
+ size_pixels_ = gfx::Size();
+ scale_factor_ = 1.f;
+ local_surface_id_allocator_.Invalidate();
+ compositor()->SetScaleAndSize(
+ scale_factor_, size_pixels_,
+ local_surface_id_allocator_.GetCurrentLocalSurfaceId());
+}
+
void RecyclableCompositorMac::OnCompositingDidCommit(
ui::Compositor* compositor_that_did_commit) {
DCHECK_EQ(compositor_that_did_commit, compositor());
- content::ImageTransportFactory::GetInstance()
- ->SetCompositorSuspendedForRecycle(compositor(), false);
+ accelerated_widget_mac_->SetSuspended(false);
}
// static
@@ -151,8 +181,7 @@ std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::Create() {
// static
void RecyclableCompositorMac::Recycle(
std::unique_ptr<RecyclableCompositorMac> compositor) {
- content::ImageTransportFactory::GetInstance()
- ->SetCompositorSuspendedForRecycle(compositor->compositor(), true);
+ compositor->accelerated_widget_mac_->SetSuspended(true);
// Make this RecyclableCompositorMac recyclable for future instances.
g_spare_recyclable_compositors.Get().push_back(std::move(compositor));
@@ -181,8 +210,11 @@ BrowserCompositorMac::BrowserCompositorMac(
g_browser_compositors.Get().insert(this);
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
+ // Ensure that this layer draws nothing when it does not not have delegated
+ // content (otherwise this solid color will be flashed during navigation).
+ root_layer_->SetColor(SK_ColorTRANSPARENT);
delegated_frame_host_.reset(new DelegatedFrameHost(
- frame_sink_id, this, features::IsSurfaceSynchronizationEnabled(),
+ frame_sink_id, this,
base::FeatureList::IsEnabled(features::kVizDisplayCompositor),
true /* should_register_frame_sink_id */));
@@ -232,7 +264,24 @@ void BrowserCompositorMac::ClearCompositorFrame() {
delegated_frame_host_->ClearDelegatedFrame();
}
+bool BrowserCompositorMac::RequestRepaintForTesting() {
+ const viz::LocalSurfaceId& new_local_surface_id =
+ dfh_local_surface_id_allocator_.GenerateId();
+ delegated_frame_host_->SynchronizeVisualProperties(
+ new_local_surface_id, dfh_size_dip_,
+ cc::DeadlinePolicy::UseExistingDeadline());
+ return client_->SynchronizeVisualProperties();
+}
+
+const gfx::CALayerParams* BrowserCompositorMac::GetLastCALayerParams() const {
+ if (!recyclable_compositor_)
+ return nullptr;
+ return recyclable_compositor_->accelerated_widget_mac()->GetCALayerParams();
+}
+
viz::FrameSinkId BrowserCompositorMac::GetRootFrameSinkId() {
+ if (parent_ui_layer_)
+ return parent_ui_layer_->GetCompositor()->frame_sink_id();
if (recyclable_compositor_)
return recyclable_compositor_->compositor()->frame_sink_id();
return viz::FrameSinkId();
@@ -251,9 +300,8 @@ void BrowserCompositorMac::OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {
void BrowserCompositorMac::SetBackgroundColor(SkColor background_color) {
background_color_ = background_color;
- if (recyclable_compositor_) {
+ if (recyclable_compositor_)
recyclable_compositor_->compositor()->SetBackgroundColor(background_color_);
- }
}
bool BrowserCompositorMac::UpdateNSViewAndDisplay(
@@ -270,35 +318,44 @@ bool BrowserCompositorMac::UpdateNSViewAndDisplay(
dfh_size_dip_ = new_size_dip;
dfh_size_pixels_ = gfx::ConvertSizeToPixel(dfh_display_.device_scale_factor(),
dfh_size_dip_);
+ root_layer_->SetBounds(gfx::Rect(dfh_size_dip_));
if (needs_new_surface_id) {
if (recyclable_compositor_)
recyclable_compositor_->Suspend();
- GetDelegatedFrameHost()->WasResized(
+ GetDelegatedFrameHost()->SynchronizeVisualProperties(
dfh_local_surface_id_allocator_.GenerateId(), dfh_size_dip_,
- cc::DeadlinePolicy::UseExistingDeadline());
+ GetDeadlinePolicy());
}
if (recyclable_compositor_) {
recyclable_compositor_->compositor()->SetDisplayColorSpace(
dfh_display_.color_space());
+ recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
+ dfh_display_.device_scale_factor());
}
+
return true;
}
-void BrowserCompositorMac::UpdateForAutoResize(const gfx::Size& new_size_dip) {
- if (new_size_dip == dfh_size_dip_)
- return;
-
- dfh_size_dip_ = new_size_dip;
- dfh_size_pixels_ = gfx::ConvertSizeToPixel(dfh_display_.device_scale_factor(),
- dfh_size_dip_);
-
- if (recyclable_compositor_)
- recyclable_compositor_->Suspend();
- GetDelegatedFrameHost()->WasResized(
- dfh_local_surface_id_allocator_.GenerateId(), dfh_size_dip_,
- cc::DeadlinePolicy::UseExistingDeadline());
+void BrowserCompositorMac::SynchronizeVisualProperties(
+ const gfx::Size& new_size_in_pixels,
+ const viz::LocalSurfaceId& child_allocated_local_surface_id) {
+ if (dfh_local_surface_id_allocator_.UpdateFromChild(
+ child_allocated_local_surface_id)) {
+ dfh_size_dip_ = gfx::ConvertSizeToDIP(dfh_display_.device_scale_factor(),
+ new_size_in_pixels);
+ dfh_size_pixels_ = new_size_in_pixels;
+ root_layer_->SetBounds(gfx::Rect(dfh_size_dip_));
+ if (recyclable_compositor_) {
+ recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
+ dfh_display_.device_scale_factor());
+ }
+ GetDelegatedFrameHost()->SynchronizeVisualProperties(
+ dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ dfh_size_dip_, GetDeadlinePolicy());
+ }
+ client_->SynchronizeVisualProperties();
}
void BrowserCompositorMac::UpdateVSyncParameters(
@@ -321,25 +378,49 @@ void BrowserCompositorMac::SetNSViewAttachedToWindow(bool attached) {
}
void BrowserCompositorMac::UpdateState() {
- // If the host is visible then a compositor is required.
+ // Always use the parent ui::Layer's ui::Compositor if available.
+ if (parent_ui_layer_) {
+ TransitionToState(UseParentLayerCompositor);
+ return;
+ }
+
+ // If the host is visible and a compositor is required then create one.
if (!render_widget_host_is_hidden_) {
TransitionToState(HasAttachedCompositor);
return;
}
+
// If the host is not visible but we are attached to a window then keep around
// a compositor only if it already exists.
- if (ns_view_attached_to_window_ && state_ != HasNoCompositor) {
+ if (ns_view_attached_to_window_ && state_ == HasAttachedCompositor) {
TransitionToState(HasDetachedCompositor);
return;
}
+
// Otherwise put the compositor up for recycling.
TransitionToState(HasNoCompositor);
}
void BrowserCompositorMac::TransitionToState(State new_state) {
+ // Note that the state enum values represent the other through which
+ // transitions must be done (see comments in State definition).
+
+ // Transition UseParentLayerCompositor -> HasNoCompositor.
+ if (state_ == UseParentLayerCompositor &&
+ new_state < UseParentLayerCompositor) {
+ DCHECK(root_layer_->parent());
+ root_layer_->parent()->RemoveObserver(this);
+ root_layer_->parent()->Remove(root_layer_.get());
+ delegated_frame_host_->WasHidden();
+ delegated_frame_host_->ResetCompositor();
+ state_ = HasNoCompositor;
+ }
+
// Transition HasNoCompositor -> HasDetachedCompositor.
- if (state_ == HasNoCompositor && new_state != HasNoCompositor) {
+ if (state_ == HasNoCompositor && new_state < HasNoCompositor) {
recyclable_compositor_ = RecyclableCompositorMac::Create();
+ recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
+ dfh_display_.device_scale_factor());
recyclable_compositor_->compositor()->SetRootLayer(root_layer_.get());
recyclable_compositor_->compositor()->SetBackgroundColor(background_color_);
recyclable_compositor_->compositor()->SetDisplayColorSpace(
@@ -350,7 +431,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
}
// Transition HasDetachedCompositor -> HasAttachedCompositor.
- if (state_ == HasDetachedCompositor && new_state == HasAttachedCompositor) {
+ if (state_ == HasDetachedCompositor && new_state < HasDetachedCompositor) {
delegated_frame_host_->SetCompositor(recyclable_compositor_->compositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
ui::LatencyInfo());
@@ -358,25 +439,14 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// If there exists a saved frame ready to display, unsuspend the compositor
// now (if one is not ready, the compositor will unsuspend on first surface
// activation).
- if (delegated_frame_host_->HasSavedFrame()) {
- if (compositor_scale_factor_ != dfh_display_.device_scale_factor() ||
- compositor_size_pixels_ != dfh_size_pixels_) {
- compositor_scale_factor_ = dfh_display_.device_scale_factor();
- compositor_size_pixels_ = dfh_size_pixels_;
- root_layer_->SetBounds(gfx::Rect(gfx::ConvertSizeToDIP(
- compositor_scale_factor_, compositor_size_pixels_)));
- recyclable_compositor_->compositor()->SetScaleAndSize(
- compositor_scale_factor_, compositor_size_pixels_,
- compositor_local_surface_id_allocator_.GenerateId());
- }
+ if (delegated_frame_host_->HasSavedFrame())
recyclable_compositor_->Unsuspend();
- }
state_ = HasAttachedCompositor;
}
// Transition HasAttachedCompositor -> HasDetachedCompositor.
- if (state_ == HasAttachedCompositor && new_state != HasAttachedCompositor) {
+ if (state_ == HasAttachedCompositor && new_state > HasAttachedCompositor) {
// Ensure that any changes made to the ui::Compositor do not result in new
// frames being produced.
recyclable_compositor_->Suspend();
@@ -388,18 +458,26 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
}
// Transition HasDetachedCompositor -> HasNoCompositor.
- if (state_ == HasDetachedCompositor && new_state == HasNoCompositor) {
+ if (state_ == HasDetachedCompositor && new_state > HasDetachedCompositor) {
recyclable_compositor_->accelerated_widget_mac()->ResetNSView();
- compositor_scale_factor_ = 1.f;
- compositor_size_pixels_ = gfx::Size();
- compositor_local_surface_id_allocator_.Invalidate();
- recyclable_compositor_->compositor()->SetScaleAndSize(
- compositor_scale_factor_, compositor_size_pixels_,
- compositor_local_surface_id_allocator_.GetCurrentLocalSurfaceId());
recyclable_compositor_->compositor()->SetRootLayer(nullptr);
+ recyclable_compositor_->InvalidateSurface();
RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_));
state_ = HasNoCompositor;
}
+
+ // Transition HasNoCompositor -> UseParentLayerCompositor.
+ if (state_ == HasNoCompositor && new_state > HasNoCompositor) {
+ DCHECK(parent_ui_layer_);
+ DCHECK(parent_ui_layer_->GetCompositor());
+ DCHECK(!root_layer_->parent());
+ delegated_frame_host_->SetCompositor(parent_ui_layer_->GetCompositor());
+ delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
+ ui::LatencyInfo());
+ parent_ui_layer_->Add(root_layer_.get());
+ parent_ui_layer_->AddObserver(this);
+ state_ = UseParentLayerCompositor;
+ }
}
// static
@@ -425,17 +503,14 @@ void BrowserCompositorMac::SetWantsAnimateOnlyBeginFrames() {
void BrowserCompositorMac::TakeFallbackContentFrom(
BrowserCompositorMac* other) {
- // We will have a flash if we can't recycle the compositor from |other|.
- if (other->state_ != HasDetachedCompositor || state_ != HasNoCompositor) {
- return;
- }
-
delegated_frame_host_->TakeFallbackContentFrom(
other->delegated_frame_host_.get());
- other->recyclable_compositor_->accelerated_widget_mac()
- ->ResetNSViewPreservingContents();
- other->TransitionToState(HasNoCompositor);
- TransitionToState(HasAttachedCompositor);
+
+ // We will have a flash if we can't recycle the compositor from |other|.
+ if (other->state_ == HasDetachedCompositor && state_ == HasNoCompositor) {
+ other->TransitionToState(HasNoCompositor);
+ TransitionToState(HasAttachedCompositor);
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -446,24 +521,13 @@ ui::Layer* BrowserCompositorMac::DelegatedFrameHostGetLayer() const {
}
bool BrowserCompositorMac::DelegatedFrameHostIsVisible() const {
- return state_ == HasAttachedCompositor || state_ == HasDetachedCompositor;
+ return state_ != HasNoCompositor;
}
SkColor BrowserCompositorMac::DelegatedFrameHostGetGutterColor() const {
return client_->BrowserCompositorMacGetGutterColor();
}
-bool BrowserCompositorMac::DelegatedFrameCanCreateResizeLock() const {
- // Mac uses the RenderWidgetResizeHelper instead of a resize lock.
- return false;
-}
-
-std::unique_ptr<CompositorResizeLock>
-BrowserCompositorMac::DelegatedFrameHostCreateResizeLock() {
- NOTREACHED();
- return nullptr;
-}
-
void BrowserCompositorMac::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
if (!recyclable_compositor_)
@@ -471,25 +535,13 @@ void BrowserCompositorMac::OnFirstSurfaceActivation(
recyclable_compositor_->Unsuspend();
- // Resize the compositor to match the current frame size, if needed.
- if (compositor_size_pixels_ == surface_info.size_in_pixels() &&
- compositor_scale_factor_ == surface_info.device_scale_factor()) {
- return;
- }
- compositor_size_pixels_ = surface_info.size_in_pixels();
- compositor_scale_factor_ = surface_info.device_scale_factor();
- root_layer_->SetBounds(gfx::Rect(gfx::ConvertSizeToDIP(
- compositor_scale_factor_, compositor_size_pixels_)));
- recyclable_compositor_->compositor()->SetScaleAndSize(
- compositor_scale_factor_, compositor_size_pixels_,
- compositor_local_surface_id_allocator_.GenerateId());
-
// Disable screen updates until the frame of the new size appears (because the
// content is drawn in the GPU process, it may change before we want it to).
if (repaint_state_ == RepaintState::Paused) {
bool compositor_is_nsview_size =
- compositor_size_pixels_ == dfh_size_pixels_ &&
- compositor_scale_factor_ == dfh_display_.device_scale_factor();
+ recyclable_compositor_->pixel_size() == dfh_size_pixels_ &&
+ recyclable_compositor_->scale_factor() ==
+ dfh_display_.device_scale_factor();
if (compositor_is_nsview_size || repaint_auto_resize_enabled_) {
NSDisableScreenUpdates();
repaint_state_ = RepaintState::ScreenUpdatesDisabled;
@@ -501,34 +553,23 @@ void BrowserCompositorMac::OnBeginFrame(base::TimeTicks frame_time) {
client_->BrowserCompositorMacOnBeginFrame(frame_time);
}
-bool BrowserCompositorMac::IsAutoResizeEnabled() const {
- NOTREACHED();
- return false;
-}
-
void BrowserCompositorMac::OnFrameTokenChanged(uint32_t frame_token) {
client_->OnFrameTokenChanged(frame_token);
}
-ui::Compositor* BrowserCompositorMac::CompositorForTesting() const {
- if (recyclable_compositor_)
- return recyclable_compositor_->compositor();
- return nullptr;
-}
-
void BrowserCompositorMac::DidNavigate() {
// The first navigation does not need a new LocalSurfaceID. The renderer can
// use the ID that was already provided.
- if (!is_first_navigation_) {
- const viz::LocalSurfaceId& new_local_surface_id =
- dfh_local_surface_id_allocator_.GenerateId();
- delegated_frame_host_->WasResized(
- new_local_surface_id, dfh_size_dip_,
- cc::DeadlinePolicy::UseExistingDeadline());
- }
- is_first_navigation_ = false;
- client_->WasResized();
+ if (!is_first_navigation_)
+ dfh_local_surface_id_allocator_.GenerateId();
+ const viz::LocalSurfaceId& local_surface_id =
+ dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
+ delegated_frame_host_->SynchronizeVisualProperties(
+ local_surface_id, dfh_size_dip_,
+ cc::DeadlinePolicy::UseExistingDeadline());
+ client_->SynchronizeVisualProperties();
delegated_frame_host_->DidNavigate();
+ is_first_navigation_ = false;
}
void BrowserCompositorMac::DidReceiveFirstFrameAfterNavigation() {
@@ -547,6 +588,9 @@ void BrowserCompositorMac::EndPauseForFrame() {
}
bool BrowserCompositorMac::ShouldContinueToPauseForFrame() const {
+ if (state_ == UseParentLayerCompositor)
+ return false;
+
// The renderer won't produce a frame if its frame sink hasn't been created
// yet.
if (!renderer_compositor_frame_sink_)
@@ -559,14 +603,71 @@ bool BrowserCompositorMac::ShouldContinueToPauseForFrame() const {
dfh_size_dip_);
}
+void BrowserCompositorMac::SetParentUiLayer(ui::Layer* new_parent_ui_layer) {
+ if (new_parent_ui_layer) {
+ DCHECK(new_parent_ui_layer->GetCompositor());
+ DCHECK(!parent_ui_layer_);
+ parent_ui_layer_ = new_parent_ui_layer;
+ } else if (parent_ui_layer_) {
+ DCHECK(root_layer_->parent());
+ DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
+ parent_ui_layer_ = nullptr;
+ }
+ UpdateState();
+}
+
+bool BrowserCompositorMac::ForceNewSurfaceForTesting() {
+ display::Display new_display(dfh_display_);
+ new_display.set_device_scale_factor(new_display.device_scale_factor() * 2.0f);
+ return UpdateNSViewAndDisplay(dfh_size_dip_, new_display);
+}
+
void BrowserCompositorMac::GetRendererScreenInfo(
ScreenInfo* screen_info) const {
DisplayUtil::DisplayToScreenInfo(screen_info, dfh_display_);
}
-const viz::LocalSurfaceId& BrowserCompositorMac::GetRendererLocalSurfaceId()
- const {
- return dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
+viz::ScopedSurfaceIdAllocator
+BrowserCompositorMac::GetScopedRendererSurfaceIdAllocator(
+ base::OnceCallback<void()> allocation_task) {
+ return viz::ScopedSurfaceIdAllocator(&dfh_local_surface_id_allocator_,
+ std::move(allocation_task));
+}
+
+const viz::LocalSurfaceId& BrowserCompositorMac::GetRendererLocalSurfaceId() {
+ if (dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId().is_valid())
+ return dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
+
+ return dfh_local_surface_id_allocator_.GenerateId();
+}
+
+bool BrowserCompositorMac::UpdateRendererLocalSurfaceIdFromChild(
+ const viz::LocalSurfaceId& child_allocated_local_surface_id) {
+ return dfh_local_surface_id_allocator_.UpdateFromChild(
+ child_allocated_local_surface_id);
+}
+
+void BrowserCompositorMac::LayerDestroyed(ui::Layer* layer) {
+ DCHECK_EQ(layer, parent_ui_layer_);
+ SetParentUiLayer(nullptr);
+}
+
+ui::Compositor* BrowserCompositorMac::GetCompositorForTesting() const {
+ if (recyclable_compositor_)
+ return recyclable_compositor_->compositor();
+ return nullptr;
+}
+
+cc::DeadlinePolicy BrowserCompositorMac::GetDeadlinePolicy() const {
+ // Determined empirically for smoothness.
+ uint32_t frames_to_wait = 8;
+
+ // When using the RecyclableCompositor, never wait for frames to arrive
+ // (surface sync is managed by the Suspend/Unsuspend lock).
+ if (recyclable_compositor_)
+ frames_to_wait = 0;
+
+ return cc::DeadlinePolicy::UseSpecifiedDeadline(frames_to_wait);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl.cc b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
index 219539bad29..a951584df7c 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.cc
@@ -241,7 +241,7 @@ void ClipboardHostImpl::WriteSmartPasteMarker(ui::ClipboardType) {
void ClipboardHostImpl::WriteCustomData(
ui::ClipboardType,
- const std::unordered_map<base::string16, base::string16>& data) {
+ const base::flat_map<base::string16, base::string16>& data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::Pickle pickle;
ui::WriteCustomDataToPickle(data, &pickle);
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl.h b/chromium/content/browser/renderer_host/clipboard_host_impl.h
index f0a867c5490..7199ebced1b 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl.h
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl.h
@@ -9,7 +9,6 @@
#include <memory>
#include <string>
-#include <unordered_map>
#include <vector>
#include "base/macros.h"
@@ -78,7 +77,7 @@ class CONTENT_EXPORT ClipboardHostImpl : public blink::mojom::ClipboardHost {
void WriteSmartPasteMarker(ui::ClipboardType clipboard_type) override;
void WriteCustomData(
ui::ClipboardType clipboard_type,
- const std::unordered_map<base::string16, base::string16>& data) override;
+ const base::flat_map<base::string16, base::string16>& data) override;
void WriteBookmark(ui::ClipboardType clipboard_type,
const std::string& url,
const base::string16& title) override;
diff --git a/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc b/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
index 618b97cfca3..704acc6673d 100644
--- a/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/clipboard_host_impl_unittest.cc
@@ -103,15 +103,4 @@ TEST_F(ClipboardHostImplTest, ImageSizeOverflows32BitRowBytes) {
clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE));
}
-TEST_F(ClipboardHostImplTest, InvalidSharedMemoryHandle) {
- mojo::ScopedSharedBufferHandle shared_memory;
- CallWriteImage(gfx::Size(5, 5), std::move(shared_memory), 0);
- uint64_t sequence_number =
- clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
- CallCommitWrite();
-
- EXPECT_EQ(sequence_number,
- clipboard()->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE));
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 8738af74a88..12b20bd638a 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -7,8 +7,11 @@
#include <android/bitmap.h>
#include <android/native_window_jni.h>
#include <stdint.h>
+
+#include <string>
#include <unordered_set>
#include <utility>
+#include <vector>
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
@@ -19,6 +22,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
+#include "base/no_destructor.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/sys_info.h"
@@ -34,7 +38,10 @@
#include "cc/resources/ui_resource_manager.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_settings.h"
+#include "components/viz/client/client_layer_tree_frame_sink.h"
#include "components/viz/client/frame_eviction_manager.h"
+#include "components/viz/client/hit_test_data_provider_draw_quad.h"
+#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/common/features.h"
#include "components/viz/common/gl_helper.h"
#include "components/viz/common/gpu/context_provider.h"
@@ -52,6 +59,7 @@
#include "components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/compositor/in_process_display_client.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -63,12 +71,15 @@
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
+#include "gpu/command_buffer/common/swap_buffers_flags.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "gpu/vulkan/buildflags.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
+#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
@@ -78,6 +89,11 @@
#include "ui/gfx/ca_layer_params.h"
#include "ui/gfx/swap_result.h"
#include "ui/gl/gl_utils.h"
+#include "ui/latency/latency_tracker.h"
+
+namespace gpu {
+class VulkanSurface;
+}
namespace content {
@@ -96,18 +112,47 @@ class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
~SingleThreadTaskGraphRunner() override { Shutdown(); }
};
-struct CompositorDependencies {
- CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) {
- // TODO(danakj): Don't make a FrameSinkManagerImpl when display is in the
- // Gpu process, instead get the mojo pointer from the Gpu process.
- frame_sink_manager_impl = std::make_unique<viz::FrameSinkManagerImpl>();
- surface_utils::ConnectWithLocalFrameSinkManager(
- &host_frame_sink_manager, frame_sink_manager_impl.get());
+class CompositorDependencies {
+ public:
+ static CompositorDependencies& Get() {
+ static base::NoDestructor<CompositorDependencies> instance;
+ return *instance;
+ }
+
+ void CreateVizFrameSinkManager() {
+ viz::mojom::FrameSinkManagerPtr frame_sink_manager;
+ viz::mojom::FrameSinkManagerRequest frame_sink_manager_request =
+ mojo::MakeRequest(&frame_sink_manager);
+ viz::mojom::FrameSinkManagerClientPtr frame_sink_manager_client;
+ viz::mojom::FrameSinkManagerClientRequest
+ frame_sink_manager_client_request =
+ mojo::MakeRequest(&frame_sink_manager_client);
+
+ // Setup HostFrameSinkManager with interface endpoints.
+ GetHostFrameSinkManager()->BindAndSetManager(
+ std::move(frame_sink_manager_client_request),
+ base::ThreadTaskRunnerHandle::Get(), std::move(frame_sink_manager));
+
+ // Set up a callback to automatically re-connect if we lose our
+ // connection.
+ GetHostFrameSinkManager()->SetConnectionLostCallback(base::BindRepeating(
+ []() { CompositorDependencies::Get().CreateVizFrameSinkManager(); }));
+
+ BrowserMainLoop::GetInstance()
+ ->gpu_channel_establish_factory()
+ ->EstablishGpuChannel(base::BindOnce(
+ &CompositorDependencies::
+ OnReadyToConnectVizFrameSinkManagerOnMainThread,
+ base::Unretained(this), std::move(frame_sink_manager_request),
+ frame_sink_manager_client.PassInterface()));
}
SingleThreadTaskGraphRunner task_graph_runner;
viz::HostFrameSinkManager host_frame_sink_manager;
viz::FrameSinkIdAllocator frame_sink_id_allocator;
+ viz::ParentLocalSurfaceIdAllocator surface_id_allocator;
+
+ // Non-viz members:
// This is owned here so that SurfaceManager will be accessible in process
// when display is in the same process. Other than using SurfaceManager,
// access to |in_process_frame_sink_manager_| should happen via
@@ -115,13 +160,60 @@ struct CompositorDependencies {
// http://crbug.com/657959.
std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_impl;
+ // Viz-only members:
+ viz::mojom::DisplayPrivateAssociatedPtr display_private;
+ std::unique_ptr<InProcessDisplayClient> display_client;
+
#if BUILDFLAG(ENABLE_VULKAN)
scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider;
#endif
-};
+ private:
+ friend class base::NoDestructor<CompositorDependencies>;
+
+ CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) {
+ bool enable_viz =
+ base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
+ if (!enable_viz) {
+ frame_sink_manager_impl = std::make_unique<viz::FrameSinkManagerImpl>();
+ surface_utils::ConnectWithLocalFrameSinkManager(
+ &host_frame_sink_manager, frame_sink_manager_impl.get());
+ }
+ }
-base::LazyInstance<CompositorDependencies>::DestructorAtExit
- g_compositor_dependencies = LAZY_INSTANCE_INITIALIZER;
+ void OnReadyToConnectVizFrameSinkManagerOnMainThread(
+ viz::mojom::FrameSinkManagerRequest request,
+ viz::mojom::FrameSinkManagerClientPtrInfo client,
+ scoped_refptr<gpu::GpuChannelHost> host) {
+ if (!host) {
+ // If host creation failed, try again. We have no software fallback on
+ // Android. This must succeed.
+ CreateVizFrameSinkManager();
+ return;
+ }
+
+ // Forward |connect_on_io| to the IO thread to run.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&CompositorDependencies::
+ OnReadyToConnectVizFrameSinkManagerOnIOThread,
+ base::Unretained(this), std::move(request),
+ std::move(client)));
+ }
+
+ void OnReadyToConnectVizFrameSinkManagerOnIOThread(
+ viz::mojom::FrameSinkManagerRequest request,
+ viz::mojom::FrameSinkManagerClientPtrInfo client) {
+ // There should always be a GpuProcessHost instance, and GPU
+ // process at this point. The exception is
+ // during shutdown the GPU process won't be restarted and
+ // GpuProcessHost::Get() can return null.
+ auto* gpu_process_host = GpuProcessHost::Get();
+ if (gpu_process_host) {
+ gpu_process_host->ConnectFrameSinkManager(std::move(request),
+ std::move(client));
+ }
+ }
+};
const unsigned int kMaxDisplaySwapBuffers = 1U;
@@ -130,7 +222,7 @@ scoped_refptr<viz::VulkanContextProvider> GetSharedVulkanContextProvider() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableVulkan)) {
scoped_refptr<viz::VulkanContextProvider> context_provider =
- g_compositor_dependencies.Get().vulkan_context_provider;
+ CompositorDependencies::Get().vulkan_context_provider;
if (!*context_provider)
*context_provider = viz::VulkanInProcessContextProvider::Create();
return *context_provider;
@@ -243,23 +335,20 @@ void CreateContextProviderAfterGpuChannelEstablished(
stream_id, stream_priority, handle,
GURL(std::string("chrome://gpu/Compositor::CreateContextProvider")),
automatic_flushes, support_locking, support_grcontext,
- shared_memory_limits, attributes, nullptr /* shared_context */,
+ shared_memory_limits, attributes,
ui::command_buffer_metrics::CONTEXT_TYPE_UNKNOWN);
callback.Run(std::move(context_provider));
}
-class AndroidOutputSurface
- : public viz::OutputSurface,
- public viz::OutputSurface::LatencyInfoCache::Client {
+class AndroidOutputSurface : public viz::OutputSurface {
public:
AndroidOutputSurface(
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider,
- base::Closure swap_buffers_callback)
+ base::RepeatingCallback<void(gfx::Size)> swap_buffers_callback)
: viz::OutputSurface(std::move(context_provider)),
swap_buffers_callback_(std::move(swap_buffers_callback)),
overlay_candidate_validator_(
new viz::CompositorOverlayCandidateValidatorAndroid()),
- latency_info_cache_(this),
weak_ptr_factory_(this) {
capabilities_.max_frames_pending = kMaxDisplaySwapBuffers;
}
@@ -267,32 +356,35 @@ class AndroidOutputSurface
~AndroidOutputSurface() override = default;
void SwapBuffers(viz::OutputSurfaceFrame frame) override {
- if (latency_info_cache_.WillSwap(std::move(frame.latency_info)))
+ if (LatencyInfoHasSnapshotRequest(frame.latency_info))
GetCommandBufferProxy()->SetSnapshotRequested();
+ auto callback =
+ base::BindOnce(&AndroidOutputSurface::OnSwapBuffersCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(frame.latency_info), frame.size);
+ uint32_t flags = 0;
+ gpu::ContextSupport::PresentationCallback presentation_callback;
+ if (frame.need_presentation_feedback) {
+ flags |= gpu::SwapBuffersFlags::kPresentationFeedback;
+ presentation_callback =
+ base::BindOnce(&AndroidOutputSurface::OnPresentation,
+ weak_ptr_factory_.GetWeakPtr());
+ }
if (frame.sub_buffer_rect) {
DCHECK(frame.sub_buffer_rect->IsEmpty());
- context_provider_->ContextSupport()->CommitOverlayPlanes();
+ context_provider_->ContextSupport()->CommitOverlayPlanes(
+ flags, std::move(callback), std::move(presentation_callback));
} else {
- context_provider_->ContextSupport()->Swap();
+ context_provider_->ContextSupport()->Swap(
+ flags, std::move(callback), std::move(presentation_callback));
}
}
- // OutputSurface::LatencyInfoCache::Client implementation.
- void LatencyInfoCompleted(
- const std::vector<ui::LatencyInfo>& latency_info) override {
- RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
- }
-
void BindToClient(viz::OutputSurfaceClient* client) override {
DCHECK(client);
DCHECK(!client_);
client_ = client;
- GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
- base::Bind(&AndroidOutputSurface::OnSwapBuffersCompleted,
- weak_ptr_factory_.GetWeakPtr()));
- GetCommandBufferProxy()->SetPresentationCallback(base::BindRepeating(
- &AndroidOutputSurface::OnPresentation, weak_ptr_factory_.GetWeakPtr()));
}
void EnsureBackbuffer() override {}
@@ -327,7 +419,6 @@ class AndroidOutputSurface
gfx::BufferFormat GetOverlayBufferFormat() const override {
return gfx::BufferFormat::RGBX_8888;
}
- bool SurfaceIsSuspendForRecycle() const override { return false; }
bool HasExternalStencilTest() const override { return false; }
void ApplyExternalStencil() override {}
@@ -337,6 +428,8 @@ class AndroidOutputSurface
return gl->GetCopyTextureInternalFormat();
}
+ unsigned UpdateGpuFence() override { return 0; }
+
private:
gpu::CommandBufferProxyImpl* GetCommandBufferProxy() {
ui::ContextProviderCommandBuffer* provider_command_buffer =
@@ -347,22 +440,25 @@ class AndroidOutputSurface
return command_buffer_proxy;
}
- void OnSwapBuffersCompleted(const gpu::SwapBuffersCompleteParams& params) {
- client_->DidReceiveSwapBuffersAck(params.swap_response.swap_id);
- swap_buffers_callback_.Run();
- latency_info_cache_.OnSwapBuffersCompleted(params.swap_response);
+ void OnSwapBuffersCompleted(std::vector<ui::LatencyInfo> latency_info,
+ gfx::Size swap_size,
+ const gpu::SwapBuffersCompleteParams& params) {
+ client_->DidReceiveSwapBuffersAck();
+ swap_buffers_callback_.Run(swap_size);
+ UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
+ RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(latency_info);
+ latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
}
- void OnPresentation(uint64_t swap_id,
- const gfx::PresentationFeedback& feedback) {
- client_->DidReceivePresentationFeedback(swap_id, feedback);
+ void OnPresentation(const gfx::PresentationFeedback& feedback) {
+ client_->DidReceivePresentationFeedback(feedback);
}
private:
viz::OutputSurfaceClient* client_ = nullptr;
- base::Closure swap_buffers_callback_;
+ base::RepeatingCallback<void(gfx::Size)> swap_buffers_callback_;
std::unique_ptr<viz::OverlayCandidateValidator> overlay_candidate_validator_;
- LatencyInfoCache latency_info_cache_;
+ ui::LatencyTracker latency_tracker_;
base::WeakPtrFactory<AndroidOutputSurface> weak_ptr_factory_;
};
@@ -415,7 +511,9 @@ class VulkanOutputSurface : public viz::OutputSurface {
private:
void SwapBuffersAck() { client_->DidReceiveSwapBuffersAck(); }
+#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanSurface> surface_;
+#endif
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtrFactory<VulkanOutputSurface> weak_ptr_factory_;
@@ -423,6 +521,28 @@ class VulkanOutputSurface : public viz::OutputSurface {
};
#endif
+void SendOnBackgroundedToGpuService() {
+ content::GpuProcessHost::CallOnIO(
+ content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ false /* force_create */,
+ base::BindRepeating([](content::GpuProcessHost* host) {
+ if (host) {
+ host->gpu_service()->OnBackgrounded();
+ }
+ }));
+}
+
+void SendOnForegroundedToGpuService() {
+ content::GpuProcessHost::CallOnIO(
+ content::GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ false /* force_create */,
+ base::BindRepeating([](content::GpuProcessHost* host) {
+ if (host) {
+ host->gpu_service()->OnForegrounded();
+ }
+ }));
+}
+
static bool g_initialized = false;
} // anonymous namespace
@@ -455,17 +575,17 @@ void Compositor::CreateContextProvider(
// static
viz::FrameSinkManagerImpl* CompositorImpl::GetFrameSinkManager() {
- return g_compositor_dependencies.Get().frame_sink_manager_impl.get();
+ return CompositorDependencies::Get().frame_sink_manager_impl.get();
}
// static
viz::HostFrameSinkManager* CompositorImpl::GetHostFrameSinkManager() {
- return &g_compositor_dependencies.Get().host_frame_sink_manager;
+ return &CompositorDependencies::Get().host_frame_sink_manager;
}
// static
viz::FrameSinkId CompositorImpl::AllocateFrameSinkId() {
- return g_compositor_dependencies.Get()
+ return CompositorDependencies::Get()
.frame_sink_id_allocator.NextFrameSinkId();
}
@@ -485,7 +605,17 @@ CompositorImpl::CompositorImpl(CompositorClient* client,
pending_frames_(0U),
layer_tree_frame_sink_request_pending_(false),
lock_manager_(base::ThreadTaskRunnerHandle::Get(), this),
+ enable_surface_synchronization_(
+ features::IsSurfaceSynchronizationEnabled()),
+ enable_viz_(
+ base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
weak_factory_(this) {
+ // In Viz mode, we create the frame sink manager here. For some reason we
+ // can't do this in the CompositorDependencies constructor.
+ // TODO(ericrk): Investigate this.
+ if (enable_viz_)
+ CompositorDependencies::Get().CreateVizFrameSinkManager();
+
GetHostFrameSinkManager()->RegisterFrameSinkId(frame_sink_id_, this);
GetHostFrameSinkManager()->SetFrameSinkDebugLabel(frame_sink_id_,
"CompositorImpl");
@@ -555,9 +685,8 @@ void CompositorImpl::SetRootWindow(gfx::NativeWindow root_window) {
resource_manager_.Init(host_->GetUIResourceManager());
}
host_->SetRootLayer(root_window_->GetLayer());
- // TODO(ccameron): Ensure a valid LocalSurfaceId here.
host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
- viz::LocalSurfaceId());
+ GenerateLocalSurfaceId());
}
void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
@@ -614,6 +743,8 @@ void CompositorImpl::CreateLayerTreeHost() {
cc::LayerTreeSettings settings;
settings.use_zero_copy = true;
+ settings.enable_surface_synchronization = enable_surface_synchronization_;
+ settings.build_hit_test_data = features::IsVizHitTestingSurfaceLayerEnabled();
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
settings.initial_debug_state.SetRecordRenderingStats(
@@ -627,15 +758,14 @@ void CompositorImpl::CreateLayerTreeHost() {
cc::LayerTreeHost::InitParams params;
params.client = this;
- params.task_graph_runner = &g_compositor_dependencies.Get().task_graph_runner;
+ params.task_graph_runner = &CompositorDependencies::Get().task_graph_runner;
params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
params.settings = &settings;
params.mutator_host = animation_host_.get();
host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
DCHECK(!host_->IsVisible());
- // TODO(ccameron): Ensure a valid LocalSurfaceId here.
host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
- viz::LocalSurfaceId());
+ GenerateLocalSurfaceId());
if (needs_animate_)
host_->SetNeedsAnimate();
@@ -661,14 +791,18 @@ void CompositorImpl::SetVisible(bool visible) {
root_window_->GetBeginFrameSource());
}
display_.reset();
+ SendOnBackgroundedToGpuService();
EnqueueLowEndBackgroundCleanup();
} else {
host_->SetVisible(true);
has_submitted_frame_since_became_visible_ = false;
if (layer_tree_frame_sink_request_pending_)
HandlePendingLayerTreeFrameSinkRequest();
+ SendOnForegroundedToGpuService();
low_end_background_cleanup_task_.Cancel();
}
+ if (CompositorDependencies::Get().display_private)
+ CompositorDependencies::Get().display_private->SetDisplayVisible(visible);
}
void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
@@ -679,7 +813,7 @@ void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
if (host_) {
// TODO(ccameron): Ensure a valid LocalSurfaceId here.
host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
- viz::LocalSurfaceId());
+ GenerateLocalSurfaceId());
}
if (display_)
display_->Resize(size);
@@ -785,9 +919,12 @@ void CompositorImpl::OnGpuChannelEstablished(
return;
}
- // We don't need the context anymore if we are invisible.
- if (!host_->IsVisible())
+ // We don't need the context anymore if we are invisible. Additionally, we
+ // should notify the channel that we are invisible.
+ if (!host_->IsVisible()) {
+ SendOnBackgroundedToGpuService();
return;
+ }
DCHECK(window_);
DCHECK_NE(surface_handle_, gpu::kNullSurfaceHandle);
@@ -804,19 +941,18 @@ void CompositorImpl::OnGpuChannelEstablished(
display_color_space_ = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_window_)
.color_space();
-
- ui::ContextProviderCommandBuffer* shared_context = nullptr;
+ gpu::SurfaceHandle surface_handle =
+ enable_viz_ ? gpu::kNullSurfaceHandle : surface_handle_;
auto context_provider =
base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
std::move(gpu_channel_host), factory->GetGpuMemoryBufferManager(),
- stream_id, stream_priority, surface_handle_,
+ stream_id, stream_priority, surface_handle,
GURL(std::string("chrome://gpu/CompositorImpl::") +
std::string("CompositorContextProvider")),
automatic_flushes, support_locking, support_grcontext,
GetCompositorContextSharedMemoryLimits(root_window_),
GetCompositorContextAttributes(display_color_space_,
requires_alpha_channel_),
- shared_context,
ui::command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
auto result = context_provider->BindToCurrentThread();
LOG_IF(FATAL, result == gpu::ContextResult::kFatalFailure)
@@ -826,12 +962,16 @@ void CompositorImpl::OnGpuChannelEstablished(
return;
}
- // Unretained is safe this owns viz::Display which owns OutputSurface.
- auto display_output_surface = std::make_unique<AndroidOutputSurface>(
- context_provider,
- base::Bind(&CompositorImpl::DidSwapBuffers, base::Unretained(this)));
- InitializeDisplay(std::move(display_output_surface),
- std::move(context_provider));
+ if (enable_viz_) {
+ InitializeVizLayerTreeFrameSink(std::move(context_provider));
+ } else {
+ // Unretained is safe this owns viz::Display which owns OutputSurface.
+ auto display_output_surface = std::make_unique<AndroidOutputSurface>(
+ context_provider, base::BindRepeating(&CompositorImpl::DidSwapBuffers,
+ base::Unretained(this)));
+ InitializeDisplay(std::move(display_output_surface),
+ std::move(context_provider));
+ }
}
void CompositorImpl::InitializeDisplay(
@@ -857,6 +997,7 @@ void CompositorImpl::InitializeDisplay(
viz::RendererSettings renderer_settings;
renderer_settings.allow_antialiasing = false;
renderer_settings.highp_threshold_min = 2048;
+ renderer_settings.auto_resize_output_surface = false;
auto* gpu_memory_buffer_manager = BrowserMainLoop::GetInstance()
->gpu_channel_establish_factory()
->GetGpuMemoryBufferManager();
@@ -873,8 +1014,7 @@ void CompositorImpl::InitializeDisplay(
frame_sink_id_, GetHostFrameSinkManager(), manager, display_.get(),
nullptr /* display_client */, context_provider,
nullptr /* worker_context_provider */, task_runner,
- gpu_memory_buffer_manager, viz::ServerSharedBitmapManager::current(),
- features::IsVizHitTestingEnabled());
+ gpu_memory_buffer_manager, features::IsVizHitTestingEnabled());
display_->SetVisible(true);
display_->Resize(size_);
@@ -886,8 +1026,8 @@ void CompositorImpl::InitializeDisplay(
host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
}
-void CompositorImpl::DidSwapBuffers() {
- client_->DidSwapBuffers();
+void CompositorImpl::DidSwapBuffers(gfx::Size swap_size) {
+ client_->DidSwapBuffers(swap_size);
}
cc::UIResourceId CompositorImpl::CreateUIResource(
@@ -909,6 +1049,12 @@ void CompositorImpl::DidSubmitCompositorFrame() {
TRACE_EVENT0("compositor", "CompositorImpl::DidSubmitCompositorFrame");
pending_frames_++;
has_submitted_frame_since_became_visible_ = true;
+
+ if (enable_viz_) {
+ // TODO(ericrk): Viz should use the actual swap callback from the Viz
+ // process. This is just a workaround until we wire that up.
+ DidSwapBuffers(size_);
+ }
}
void CompositorImpl::DidReceiveCompositorFrameAck() {
@@ -972,6 +1118,13 @@ void CompositorImpl::RemoveChildFrameSink(
void CompositorImpl::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
+ if (enable_viz_) {
+ // Force a new surface to be generated.
+ // TODO(ericrk): Remove this once we correctly set up fallback surfaces.
+ host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
+ GenerateLocalSurfaceId());
+ }
+
// TODO(fsamuel): Once surface synchronization is turned on, the fallback
// surface should be set here.
}
@@ -986,7 +1139,7 @@ void CompositorImpl::OnDisplayMetricsChanged(const display::Display& display,
// TODO(ccameron): This is transiently incorrect -- |size_| must be
// recalculated here as well. Is the call in SetWindowBounds sufficient?
host_->SetViewportSizeAndScale(size_, root_window_->GetDipScale(),
- viz::LocalSurfaceId());
+ GenerateLocalSurfaceId());
}
}
@@ -1035,9 +1188,69 @@ void CompositorImpl::DoLowEndBackgroundCleanup() {
false /* force_create */,
base::BindRepeating([](content::GpuProcessHost* host) {
if (host) {
- host->gpu_service()->OnBackgrounded();
+ host->gpu_service()->OnBackgroundCleanup();
}
}));
}
+void CompositorImpl::InitializeVizLayerTreeFrameSink(
+ scoped_refptr<ui::ContextProviderCommandBuffer> context_provider) {
+ DCHECK(enable_viz_);
+
+ auto& deps = CompositorDependencies::Get();
+ pending_frames_ = 0;
+ gpu_capabilities_ = context_provider->ContextCapabilities();
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ base::ThreadTaskRunnerHandle::Get();
+
+ auto root_params = viz::mojom::RootCompositorFrameSinkParams::New();
+
+ // Create interfaces for a root CompositorFrameSink.
+ viz::mojom::CompositorFrameSinkAssociatedPtrInfo sink_info;
+ root_params->compositor_frame_sink = mojo::MakeRequest(&sink_info);
+ viz::mojom::CompositorFrameSinkClientRequest client_request =
+ mojo::MakeRequest(&root_params->compositor_frame_sink_client);
+ root_params->display_private = mojo::MakeRequest(&deps.display_private);
+ deps.display_client = std::make_unique<InProcessDisplayClient>(window_);
+ root_params->display_client =
+ deps.display_client->GetBoundPtr(task_runner).PassInterface();
+
+ viz::RendererSettings renderer_settings;
+ renderer_settings.allow_antialiasing = false;
+ renderer_settings.highp_threshold_min = 2048;
+ root_params->frame_sink_id = frame_sink_id_;
+ root_params->widget = surface_handle_;
+ root_params->gpu_compositing = true;
+ root_params->renderer_settings = renderer_settings;
+
+ GetHostFrameSinkManager()->CreateRootCompositorFrameSink(
+ std::move(root_params));
+
+ // Create LayerTreeFrameSink with the browser end of CompositorFrameSink.
+ viz::ClientLayerTreeFrameSink::InitParams params;
+ params.compositor_task_runner = task_runner;
+ params.gpu_memory_buffer_manager = BrowserMainLoop::GetInstance()
+ ->gpu_channel_establish_factory()
+ ->GetGpuMemoryBufferManager();
+ params.pipes.compositor_frame_sink_associated_info = std::move(sink_info);
+ params.pipes.client_request = std::move(client_request);
+ params.local_surface_id_provider =
+ std::make_unique<viz::DefaultLocalSurfaceIdProvider>();
+ params.enable_surface_synchronization = true;
+ params.hit_test_data_provider =
+ std::make_unique<viz::HitTestDataProviderDrawQuad>(
+ /*should_ask_for_child_region=*/false);
+ auto layer_tree_frame_sink = std::make_unique<viz::ClientLayerTreeFrameSink>(
+ std::move(context_provider), nullptr, &params);
+ host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
+ CompositorDependencies::Get().display_private->SetDisplayVisible(true);
+}
+
+viz::LocalSurfaceId CompositorImpl::GenerateLocalSurfaceId() const {
+ if (enable_surface_synchronization_)
+ return CompositorDependencies::Get().surface_id_allocator.GenerateId();
+
+ return viz::LocalSurfaceId();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index 6b59f095804..c55917e4a60 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -17,6 +17,7 @@
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/host/host_frame_sink_client.h"
#include "content/common/content_export.h"
#include "content/public/browser/android/compositor.h"
@@ -158,7 +159,7 @@ class CONTENT_EXPORT CompositorImpl
void InitializeDisplay(
std::unique_ptr<viz::OutputSurface> display_output_surface,
scoped_refptr<viz::ContextProvider> context_provider);
- void DidSwapBuffers();
+ void DidSwapBuffers(gfx::Size swap_size);
bool HavePendingReadbacks();
@@ -169,6 +170,14 @@ class CONTENT_EXPORT CompositorImpl
void EnqueueLowEndBackgroundCleanup();
void DoLowEndBackgroundCleanup();
+ // Returns a new surface ID when in surface-synchronization mode. Otherwise
+ // returns an empty surface.
+ viz::LocalSurfaceId GenerateLocalSurfaceId() const;
+
+ // Viz specific functions:
+ void InitializeVizLayerTreeFrameSink(
+ scoped_refptr<ui::ContextProviderCommandBuffer> context_provider);
+
viz::FrameSinkId frame_sink_id_;
// root_layer_ is the persistent internal root layer, while subroot_layer_
@@ -220,6 +229,12 @@ class CONTENT_EXPORT CompositorImpl
// when we hide, canceled when we're shown.
base::CancelableOnceClosure low_end_background_cleanup_task_;
+ // If true, we are using surface synchronization.
+ const bool enable_surface_synchronization_;
+
+ // If true, we are using a Viz process.
+ const bool enable_viz_;
+
base::WeakPtrFactory<CompositorImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CompositorImpl);
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock.cc b/chromium/content/browser/renderer_host/compositor_resize_lock.cc
deleted file mode 100644
index 7336dba0aa4..00000000000
--- a/chromium/content/browser/renderer_host/compositor_resize_lock.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 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/renderer_host/compositor_resize_lock.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/trace_event/trace_event.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/compositor/compositor.h"
-
-namespace content {
-
-CompositorResizeLock::CompositorResizeLock(CompositorResizeLockClient* client,
- const gfx::Size& new_size)
- : client_(client),
- expected_size_(new_size),
- acquisition_time_(base::TimeTicks::Now()) {
- TRACE_EVENT_ASYNC_BEGIN2("ui", "CompositorResizeLock", this, "width",
- expected_size().width(), "height",
- expected_size().height());
-}
-
-CompositorResizeLock::~CompositorResizeLock() {
- compositor_lock_ = nullptr;
- if (client_)
- client_->CompositorResizeLockEnded();
-
- TRACE_EVENT_ASYNC_END2("ui", "CompositorResizeLock", this, "width",
- expected_size().width(), "height",
- expected_size().height());
-
- UMA_HISTOGRAM_TIMES("UI.CompositorResizeLock.Duration",
- base::TimeTicks::Now() - acquisition_time_);
-
- UMA_HISTOGRAM_BOOLEAN("UI.CompositorResizeLock.TimedOut", timed_out_);
-}
-
-bool CompositorResizeLock::Lock() {
- if (unlocked_ || compositor_lock_)
- return false;
- compositor_lock_ = client_->GetCompositorLock(this);
- return true;
-}
-
-void CompositorResizeLock::UnlockCompositor() {
- unlocked_ = true;
- compositor_lock_ = nullptr;
-}
-
-void CompositorResizeLock::CompositorLockTimedOut() {
- timed_out_ = true;
- UnlockCompositor();
- if (client_) {
- client_->CompositorResizeLockEnded();
- client_ = nullptr;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock.h b/chromium/content/browser/renderer_host/compositor_resize_lock.h
deleted file mode 100644
index 23036898b9f..00000000000
--- a/chromium/content/browser/renderer_host/compositor_resize_lock.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 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_RENDERER_HOST_COMPOSITOR_RESIZE_LOCK_H_
-#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITOR_RESIZE_LOCK_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "ui/compositor/compositor_lock.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace content {
-
-class CompositorResizeLockClient {
- public:
- virtual ~CompositorResizeLockClient() {}
-
- // Creates and returns a CompositorLock for the CompositoResizeLock to
- // hold.
- virtual std::unique_ptr<ui::CompositorLock> GetCompositorLock(
- ui::CompositorLockClient* client) = 0;
-
- // Called when the CompositorResizeLock ends. This can happen
- // before the CompositorResizeLock is destroyed if it times out.
- virtual void CompositorResizeLockEnded() = 0;
-};
-
-// Used to prevent further resizes while a resize is pending.
-class CONTENT_EXPORT CompositorResizeLock : public ui::CompositorLockClient {
- public:
- CompositorResizeLock(CompositorResizeLockClient* client,
- const gfx::Size& new_size);
- ~CompositorResizeLock() override;
-
- // Returns |true| if the call locks the compositor, or false if it was ever
- // locked/unlocked.
- bool Lock();
-
- // Releases the lock on the compositor without releasing the whole resize
- // lock. The client is not told about this. If called before locking, it will
- // prevent locking from happening.
- void UnlockCompositor();
-
- bool timed_out() const { return timed_out_; }
-
- const gfx::Size& expected_size() const { return expected_size_; }
-
- private:
- // ui::CompositorLockClient implementation.
- void CompositorLockTimedOut() override;
-
- CompositorResizeLockClient* client_;
- const gfx::Size expected_size_;
- std::unique_ptr<ui::CompositorLock> compositor_lock_;
- bool unlocked_ = false;
- bool timed_out_ = false;
- const base::TimeTicks acquisition_time_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositorResizeLock);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITOR_RESIZE_LOCK_AURA_H_
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc b/chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc
deleted file mode 100644
index f4c42a1c4f9..00000000000
--- a/chromium/content/browser/renderer_host/compositor_resize_lock_unittest.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2017 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/renderer_host/compositor_resize_lock.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/test/null_task_runner.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-namespace {
-
-class FakeCompositorResizeLockClient : public CompositorResizeLockClient,
- public ui::CompositorLockManagerClient {
- public:
- FakeCompositorResizeLockClient()
- : lock_manager_(new base::NullTaskRunner(), this) {}
- std::unique_ptr<ui::CompositorLock> GetCompositorLock(
- ui::CompositorLockClient* client) override {
- created_ = true;
- return lock_manager_.GetCompositorLock(client, base::TimeDelta());
- }
-
- // CompositorResizeLockClient implementation.
- void CompositorResizeLockEnded() override {
- // This informs when the CompositorResizeLock ends for the client to
- // release anything else it is holding.
- ended_ = true;
- }
-
- // ui::CompositorLockManagerClient implementation.
- void OnCompositorLockStateChanged(bool locked) override {
- if (!locked) {
- // This is where the ui::Compositor would be physically unlocked.
- unlocked_ = true;
- }
- }
-
- void CauseTimeout() { lock_manager_.TimeoutLocksForTesting(); }
-
- bool created() const { return created_; }
- bool unlocked() const { return unlocked_; }
- bool ended() const { return ended_; }
-
- private:
- bool created_ = false;
- bool unlocked_ = false;
- bool ended_ = false;
- ui::CompositorLockManager lock_manager_;
-};
-
-TEST(CompositorResizeLockTest, EndWithoutLock) {
- FakeCompositorResizeLockClient resize_client;
- gfx::Size resize_to(10, 11);
-
- {
- CompositorResizeLock resize_lock(&resize_client, resize_to);
- EXPECT_FALSE(resize_client.created());
- EXPECT_FALSE(resize_client.unlocked());
- EXPECT_FALSE(resize_client.ended());
- }
- // The compositor was never locked.
- EXPECT_FALSE(resize_client.unlocked());
- // The resize lock tells the client when it is destroyed.
- EXPECT_TRUE(resize_client.ended());
-}
-
-TEST(CompositorResizeLockTest, EndAfterLock) {
- FakeCompositorResizeLockClient resize_client;
- gfx::Size resize_to(10, 11);
-
- {
- CompositorResizeLock resize_lock(&resize_client, resize_to);
- EXPECT_FALSE(resize_client.created());
- EXPECT_FALSE(resize_client.ended());
-
- resize_lock.Lock();
- EXPECT_TRUE(resize_client.created());
- EXPECT_FALSE(resize_client.ended());
- }
- // The resize lock unlocks the compositor when it ends.
- EXPECT_TRUE(resize_client.unlocked());
- // The resize lock tells the client when it ends.
- EXPECT_TRUE(resize_client.ended());
-}
-
-TEST(CompositorResizeLockTest, EndAfterUnlock) {
- FakeCompositorResizeLockClient resize_client;
- gfx::Size resize_to(10, 11);
-
- {
- CompositorResizeLock resize_lock(&resize_client, resize_to);
- EXPECT_FALSE(resize_client.created());
- EXPECT_FALSE(resize_client.ended());
-
- resize_lock.Lock();
- EXPECT_TRUE(resize_client.created());
- EXPECT_FALSE(resize_client.ended());
-
- // Unlocking the compositor but keeping the resize lock.
- resize_lock.UnlockCompositor();
- EXPECT_TRUE(resize_client.unlocked());
- EXPECT_FALSE(resize_client.ended());
- }
- // The resize lock tells the client when it ends.
- EXPECT_TRUE(resize_client.ended());
-}
-
-TEST(CompositorResizeLockTest, EndAfterTimeout) {
- FakeCompositorResizeLockClient resize_client;
- gfx::Size resize_to(10, 11);
-
- {
- CompositorResizeLock resize_lock(&resize_client, resize_to);
- EXPECT_FALSE(resize_client.created());
- EXPECT_FALSE(resize_client.ended());
-
- resize_lock.Lock();
- EXPECT_TRUE(resize_client.created());
- EXPECT_FALSE(resize_client.ended());
-
- // A timeout tells the client that the lock ended.
- resize_client.CauseTimeout();
- EXPECT_TRUE(resize_client.unlocked());
- EXPECT_TRUE(resize_client.ended());
- }
-}
-
-class CallbackClient : public FakeCompositorResizeLockClient {
- public:
- CallbackClient() = default;
-
- void CompositorResizeLockEnded() override {
- std::move(resize_lock_ended_).Run();
- }
-
- void set_resize_lock_ended(base::OnceClosure c) {
- resize_lock_ended_ = std::move(c);
- }
-
- private:
- base::OnceClosure resize_lock_ended_;
-};
-
-TEST(CompositorResizeLockTest, TimeoutSetBeforeClientTold) {
- CallbackClient resize_client;
- gfx::Size resize_to(10, 11);
-
- {
- CompositorResizeLock resize_lock(&resize_client, resize_to);
- resize_lock.Lock();
-
- // When the resize lock times out, it should report that before telling
- // the client about that.
- bool saw_resize_lock_end = false;
- auto resize_lock_ended = [](CompositorResizeLock* resize_lock, bool* saw) {
- EXPECT_TRUE(resize_lock->timed_out());
- *saw = true;
- };
- resize_client.set_resize_lock_ended(
- base::BindOnce(resize_lock_ended, &resize_lock, &saw_resize_lock_end));
-
- // A timeout tells the client that the lock ended.
- resize_client.CauseTimeout();
- EXPECT_TRUE(saw_resize_lock_end);
- }
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index f5882bcd792..47455e4a512 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -11,7 +11,6 @@
#include "base/callback_helpers.h"
#include "base/command_line.h"
-#include "base/time/default_tick_clock.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -24,7 +23,6 @@
#include "components/viz/service/surfaces/surface_hittest.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/renderer_host/compositor_resize_lock.h"
#include "content/public/common/content_switches.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -36,15 +34,12 @@ namespace content {
DelegatedFrameHost::DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
DelegatedFrameHostClient* client,
- bool enable_surface_synchronization,
bool enable_viz,
bool should_register_frame_sink_id)
: frame_sink_id_(frame_sink_id),
client_(client),
- enable_surface_synchronization_(enable_surface_synchronization),
enable_viz_(enable_viz),
should_register_frame_sink_id_(should_register_frame_sink_id),
- tick_clock_(base::DefaultTickClock::GetInstance()),
frame_evictor_(std::make_unique<viz::FrameEvictor>(this)) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
factory->GetContextFactory()->AddObserver(this);
@@ -76,19 +71,14 @@ void DelegatedFrameHost::WasShown(
const ui::LatencyInfo& latency_info) {
frame_evictor_->SetVisible(true);
- if (!enable_surface_synchronization_ && !HasFallbackSurface() &&
- !released_front_lock_.get()) {
- if (compositor_)
- released_front_lock_ = compositor_->GetCompositorLock(nullptr);
- }
-
if (compositor_)
compositor_->SetLatencyInfo(latency_info);
// Use the default deadline to synchronize web content with browser UI.
// TODO(fsamuel): Investigate if there is a better deadline to use here.
- WasResized(new_pending_local_surface_id, new_pending_dip_size,
- cc::DeadlinePolicy::UseDefaultDeadline());
+ SynchronizeVisualProperties(new_pending_local_surface_id,
+ new_pending_dip_size,
+ cc::DeadlinePolicy::UseDefaultDeadline());
}
bool DelegatedFrameHost::HasSavedFrame() const {
@@ -97,34 +87,6 @@ bool DelegatedFrameHost::HasSavedFrame() const {
void DelegatedFrameHost::WasHidden() {
frame_evictor_->SetVisible(false);
- released_front_lock_ = nullptr;
-}
-
-void DelegatedFrameHost::MaybeCreateResizeLock() {
- DCHECK(!resize_lock_);
-
- if (!compositor_)
- return;
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableResizeLock))
- return;
-
- if (!HasFallbackSurface())
- return;
-
- if (!client_->DelegatedFrameCanCreateResizeLock())
- return;
-
- gfx::Size desired_size = pending_surface_dip_size_;
- if (desired_size.IsEmpty())
- return;
- if (desired_size == current_frame_size_in_dip_)
- return;
-
- resize_lock_ = client_->DelegatedFrameHostCreateResizeLock();
- bool locked = resize_lock_->Lock();
- DCHECK(locked);
}
void DelegatedFrameHost::CopyFromCompositingSurface(
@@ -183,7 +145,7 @@ bool DelegatedFrameHost::CanCopyFromCompositingSurface() const {
active_device_scale_factor_ != 0.f;
}
-bool DelegatedFrameHost::TransformPointToLocalCoordSpace(
+bool DelegatedFrameHost::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
@@ -203,13 +165,14 @@ bool DelegatedFrameHost::TransformPointToLocalCoordSpace(
bool DelegatedFrameHost::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) {
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
if (!HasFallbackSurface())
return false;
return target_view->TransformPointToLocalCoordSpace(
point, viz::SurfaceId(frame_sink_id_, active_local_surface_id_),
- transformed_point);
+ transformed_point, source);
}
void DelegatedFrameHost::SetNeedsBeginFrames(bool needs_begin_frames) {
@@ -253,19 +216,7 @@ bool DelegatedFrameHost::HasFallbackSurface() const {
return fallback_surface_id && fallback_surface_id->is_valid();
}
-bool DelegatedFrameHost::ShouldSkipFrame(const gfx::Size& size_in_dip) {
- if (!resize_lock_)
- return false;
- // Allow a single renderer frame through even though there's a resize lock
- // currently in place.
- if (allow_one_renderer_frame_during_resize_lock_) {
- allow_one_renderer_frame_during_resize_lock_ = false;
- return false;
- }
- return size_in_dip != resize_lock_->expected_size();
-}
-
-void DelegatedFrameHost::WasResized(
+void DelegatedFrameHost::SynchronizeVisualProperties(
const viz::LocalSurfaceId& new_pending_local_surface_id,
const gfx::Size& new_pending_dip_size,
cc::DeadlinePolicy deadline_policy) {
@@ -275,66 +226,49 @@ void DelegatedFrameHost::WasResized(
pending_local_surface_id_ = new_pending_local_surface_id;
pending_surface_dip_size_ = new_pending_dip_size;
- if (enable_surface_synchronization_) {
- if (!client_->DelegatedFrameHostIsVisible()) {
- // If the tab is resized while hidden, reset the fallback so that the next
- // time user switches back to it the page is blank. This is preferred to
- // showing contents of old size. Don't call EvictDelegatedFrame to avoid
- // races when dragging tabs across displays. See https://crbug.com/813157.
- if (pending_surface_dip_size_ != current_frame_size_in_dip_ &&
- HasFallbackSurface()) {
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- viz::SurfaceId());
- }
- // Don't update the SurfaceLayer when invisible to avoid blocking on
- // renderers that do not submit CompositorFrames. Next time the renderer
- // is visible, WasResized will be called again. See WasShown.
- return;
+ if (!client_->DelegatedFrameHostIsVisible()) {
+ // If the tab is resized while hidden, reset the fallback so that the next
+ // time user switches back to it the page is blank. This is preferred to
+ // showing contents of old size. Don't call EvictDelegatedFrame to avoid
+ // races when dragging tabs across displays. See https://crbug.com/813157.
+ if (pending_surface_dip_size_ != current_frame_size_in_dip_ &&
+ HasFallbackSurface()) {
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
+ viz::SurfaceId());
}
+ // Don't update the SurfaceLayer when invisible to avoid blocking on
+ // renderers that do not submit CompositorFrames. Next time the renderer
+ // is visible, SynchronizeVisualProperties will be called again. See
+ // WasShown.
+ return;
+ }
- if (!primary_surface_id ||
- primary_surface_id->local_surface_id() != pending_local_surface_id_) {
- viz::SurfaceId surface_id(frame_sink_id_, pending_local_surface_id_);
+ if (!primary_surface_id ||
+ primary_surface_id->local_surface_id() != pending_local_surface_id_) {
+ viz::SurfaceId surface_id(frame_sink_id_, pending_local_surface_id_);
#if defined(OS_WIN) || defined(USE_X11)
- // On Windows and Linux, we would like to produce new content as soon as
- // possible or the OS will create an additional black gutter. Until we can
- // block resize on surface synchronization on these platforms, we will not
- // block UI on the top-level renderer. The exception to this is if we're
- // using an infinite deadline, in which case we should respect the
- // specified deadline and block UI since that's what was requested.
- if (deadline_policy.policy_type() !=
- cc::DeadlinePolicy::kUseInfiniteDeadline &&
- !current_frame_size_in_dip_.IsEmpty() &&
- current_frame_size_in_dip_ != pending_surface_dip_size_) {
- deadline_policy = cc::DeadlinePolicy::UseSpecifiedDeadline(0u);
- }
+ // On Windows and Linux, we would like to produce new content as soon as
+ // possible or the OS will create an additional black gutter. Until we can
+ // block resize on surface synchronization on these platforms, we will not
+ // block UI on the top-level renderer. The exception to this is if we're
+ // using an infinite deadline, in which case we should respect the
+ // specified deadline and block UI since that's what was requested.
+ if (deadline_policy.policy_type() !=
+ cc::DeadlinePolicy::kUseInfiniteDeadline &&
+ !current_frame_size_in_dip_.IsEmpty() &&
+ current_frame_size_in_dip_ != pending_surface_dip_size_) {
+ deadline_policy = cc::DeadlinePolicy::UseSpecifiedDeadline(0u);
+ }
#endif
- current_frame_size_in_dip_ = pending_surface_dip_size_;
- client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
- surface_id, current_frame_size_in_dip_, GetGutterColor(),
- deadline_policy, false /* stretch_content_to_fill_bounds */);
- if (compositor_ && !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableResizeLock)) {
- compositor_->OnChildResizing();
- }
+ current_frame_size_in_dip_ = pending_surface_dip_size_;
+ client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
+ surface_id, current_frame_size_in_dip_, GetGutterColor(),
+ deadline_policy, false /* stretch_content_to_fill_bounds */);
+ if (compositor_ && !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableResizeLock)) {
+ compositor_->OnChildResizing();
}
-
- // Input throttling and guttering are handled differently when surface
- // synchronization is enabled so exit early here.
- return;
- }
-
- if (pending_surface_dip_size_ != current_frame_size_in_dip_ &&
- !client_->DelegatedFrameHostIsVisible()) {
- EvictDelegatedFrame();
}
-
- // If |create_resize_lock_after_commit_| is true, we're waiting to recreate
- // an expired resize lock after the next UI frame is submitted, so don't
- // make a lock here.
- if (!resize_lock_ && !create_resize_lock_after_commit_)
- MaybeCreateResizeLock();
- UpdateGutters();
}
SkColor DelegatedFrameHost::GetGutterColor() const {
@@ -344,57 +278,8 @@ SkColor DelegatedFrameHost::GetGutterColor() const {
return client_->DelegatedFrameHostGetGutterColor();
}
-void DelegatedFrameHost::UpdateGutters() {
- if (!HasFallbackSurface() || enable_surface_synchronization_) {
- right_gutter_.reset();
- bottom_gutter_.reset();
- return;
- }
-
- gfx::Size size_in_dip = pending_surface_dip_size_;
- if (current_frame_size_in_dip_.width() < size_in_dip.width()) {
- right_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
- right_gutter_->SetColor(GetGutterColor());
- int width = size_in_dip.width() - current_frame_size_in_dip_.width();
- // The right gutter also includes the bottom-right corner, if necessary.
- int height = size_in_dip.height();
- right_gutter_->SetBounds(
- gfx::Rect(current_frame_size_in_dip_.width(), 0, width, height));
-
- client_->DelegatedFrameHostGetLayer()->Add(right_gutter_.get());
- } else {
- right_gutter_.reset();
- }
-
- if (current_frame_size_in_dip_.height() < size_in_dip.height()) {
- bottom_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
- bottom_gutter_->SetColor(GetGutterColor());
- int width = current_frame_size_in_dip_.width();
- int height = size_in_dip.height() - current_frame_size_in_dip_.height();
- bottom_gutter_->SetBounds(
- gfx::Rect(0, current_frame_size_in_dip_.height(), width, height));
- client_->DelegatedFrameHostGetLayer()->Add(bottom_gutter_.get());
- } else {
- bottom_gutter_.reset();
- }
-}
-
gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const {
- if (resize_lock_)
- return resize_lock_->expected_size();
- else
- return pending_surface_dip_size_;
-}
-
-void DelegatedFrameHost::CheckResizeLock() {
- if (!resize_lock_ ||
- resize_lock_->expected_size() != current_frame_size_in_dip_)
- return;
-
- // Since we got the size we were looking for, unlock the compositor. But delay
- // the release of the lock until we've kicked a frame with the new texture, to
- // avoid resizing the UI before we have a chance to draw a "good" frame.
- resize_lock_->UnlockCompositor();
+ return pending_surface_dip_size_;
}
void DelegatedFrameHost::DidCreateNewRendererCompositorFrameSink(
@@ -407,55 +292,7 @@ void DelegatedFrameHost::DidCreateNewRendererCompositorFrameSink(
void DelegatedFrameHost::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) {
-#if defined(OS_CHROMEOS)
- DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled());
-#endif
- float frame_device_scale_factor = frame.metadata.device_scale_factor;
- viz::BeginFrameAck ack(frame.metadata.begin_frame_ack);
-
- DCHECK(!frame.render_pass_list.empty());
-
- viz::RenderPass* root_pass = frame.render_pass_list.back().get();
-
- gfx::Size frame_size = root_pass->output_rect.size();
- gfx::Size frame_size_in_dip =
- gfx::ConvertSizeToDIP(frame_device_scale_factor, frame_size);
-
- if (ShouldSkipFrame(frame_size_in_dip)) {
- std::vector<viz::ReturnedResource> resources =
- viz::TransferableResource::ReturnResources(frame.resource_list);
-
- skipped_latency_info_list_.insert(skipped_latency_info_list_.end(),
- frame.metadata.latency_info.begin(),
- frame.metadata.latency_info.end());
-
- renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);
-
- skipped_frames_ = true;
- ack.has_damage = false;
- DidNotProduceFrame(ack);
- return;
- }
-
- // If we are allowing one renderer frame through, this would ensure the frame
- // gets through even if we regrab the lock after the UI compositor makes one
- // frame. If the renderer frame beats the UI compositor, then we don't need to
- // allow any more, though.
- allow_one_renderer_frame_during_resize_lock_ = false;
-
- if (skipped_frames_) {
- skipped_frames_ = false;
-
- // Give the same damage rect to the compositor.
- root_pass->damage_rect = gfx::Rect(frame_size);
- }
-
- frame.metadata.latency_info.insert(frame.metadata.latency_info.end(),
- skipped_latency_info_list_.begin(),
- skipped_latency_info_list_.end());
- skipped_latency_info_list_.clear();
-
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) {
// If surface synchronization is off, then OnFirstSurfaceActivation will be
// called in the same call stack.
support_->SubmitCompositorFrame(local_surface_id, std::move(frame),
@@ -467,7 +304,6 @@ void DelegatedFrameHost::ClearDelegatedFrame() {
// content. This will result in a white flash if we switch back to this
// content.
// https://crbug.com/739621
- released_front_lock_.reset();
EvictDelegatedFrame();
}
@@ -502,51 +338,42 @@ void DelegatedFrameHost::OnBeginFramePausedChanged(bool paused) {
void DelegatedFrameHost::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
- gfx::Size frame_size_in_dip = gfx::ConvertSizeToDIP(
- surface_info.device_scale_factor(), surface_info.size_in_pixels());
- if (enable_surface_synchronization_) {
- // If this is the first Surface created after navigation, notify |client_|.
- // If the Surface was created before navigation, drop it.
- uint32_t parent_sequence_number =
- surface_info.id().local_surface_id().parent_sequence_number();
- uint32_t latest_parent_sequence_number =
- pending_local_surface_id_.parent_sequence_number();
- // If |latest_parent_sequence_number| is less than
- // |first_parent_sequence_number_after_navigation_|, then the parent id has
- // wrapped around. Make sure that case is covered.
- if (parent_sequence_number >=
- first_parent_sequence_number_after_navigation_ ||
- (latest_parent_sequence_number <
- first_parent_sequence_number_after_navigation_ &&
- parent_sequence_number <= latest_parent_sequence_number)) {
- if (!received_frame_after_navigation_) {
- received_frame_after_navigation_ = true;
- client_->DidReceiveFirstFrameAfterNavigation();
- }
- } else {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- viz::HostFrameSinkManager* host_frame_sink_manager =
- factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
- host_frame_sink_manager->DropTemporaryReference(surface_info.id());
- return;
- }
-
- // If there's no primary surface, then we don't wish to display content at
- // this time (e.g. the view is hidden) and so we don't need a fallback
- // surface either. Since we won't use the fallback surface, we drop the
- // temporary reference here to save resources.
- if (!HasPrimarySurface()) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- viz::HostFrameSinkManager* host_frame_sink_manager =
- factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
- host_frame_sink_manager->DropTemporaryReference(surface_info.id());
- return;
+ // If this is the first Surface created after navigation, notify |client_|.
+ // If the Surface was created before navigation, drop it.
+ uint32_t parent_sequence_number =
+ surface_info.id().local_surface_id().parent_sequence_number();
+ uint32_t latest_parent_sequence_number =
+ pending_local_surface_id_.parent_sequence_number();
+ // If |latest_parent_sequence_number| is less than
+ // |first_parent_sequence_number_after_navigation_|, then the parent id has
+ // wrapped around. Make sure that case is covered.
+ if (parent_sequence_number >=
+ first_parent_sequence_number_after_navigation_ ||
+ (latest_parent_sequence_number <
+ first_parent_sequence_number_after_navigation_ &&
+ parent_sequence_number <= latest_parent_sequence_number)) {
+ if (!received_frame_after_navigation_) {
+ received_frame_after_navigation_ = true;
+ client_->DidReceiveFirstFrameAfterNavigation();
}
} else {
- client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
- surface_info.id(), frame_size_in_dip, GetGutterColor(),
- cc::DeadlinePolicy::UseDefaultDeadline(),
- false /* stretch_content_to_fill_bounds */);
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ viz::HostFrameSinkManager* host_frame_sink_manager =
+ factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
+ host_frame_sink_manager->DropTemporaryReference(surface_info.id());
+ return;
+ }
+
+ // If there's no primary surface, then we don't wish to display content at
+ // this time (e.g. the view is hidden) and so we don't need a fallback
+ // surface either. Since we won't use the fallback surface, we drop the
+ // temporary reference here to save resources.
+ if (!HasPrimarySurface()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ viz::HostFrameSinkManager* host_frame_sink_manager =
+ factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
+ host_frame_sink_manager->DropTemporaryReference(surface_info.id());
+ return;
}
client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
@@ -554,15 +381,6 @@ void DelegatedFrameHost::OnFirstSurfaceActivation(
active_local_surface_id_ = surface_info.id().local_surface_id();
active_device_scale_factor_ = surface_info.device_scale_factor();
- // Surface synchronization deals with resizes in WasResized().
- if (!enable_surface_synchronization_) {
- released_front_lock_ = nullptr;
- current_frame_size_in_dip_ = frame_size_in_dip;
- CheckResizeLock();
-
- UpdateGutters();
- }
-
// This is used by macOS' unique resize path.
client_->OnFirstSurfaceActivation(surface_info);
@@ -591,15 +409,9 @@ void DelegatedFrameHost::EvictDelegatedFrame() {
// It is possible that we are embedding the contents of previous
// DelegatedFrameHost. In this case, HasSavedFrame() will return false but we
// still need to clear the layer.
- if (enable_surface_synchronization_) {
- if (HasFallbackSurface()) {
- client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
- viz::SurfaceId());
- }
- } else {
- client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent();
- resize_lock_.reset();
- UpdateGutters();
+ if (HasFallbackSurface()) {
+ client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
+ viz::SurfaceId());
}
if (!HasSavedFrame())
@@ -613,21 +425,6 @@ void DelegatedFrameHost::EvictDelegatedFrame() {
// DelegatedFrameHost, ui::CompositorObserver implementation:
void DelegatedFrameHost::OnCompositingDidCommit(ui::Compositor* compositor) {
- // If |create_resize_lock_after_commit_| then we should have popped the old
- // lock already.
- DCHECK(!resize_lock_ || !create_resize_lock_after_commit_);
-
- if (resize_lock_ &&
- resize_lock_->expected_size() == current_frame_size_in_dip_) {
- resize_lock_.reset();
- // We had a lock but the UI may have resized in the meantime.
- create_resize_lock_after_commit_ = true;
- }
-
- if (create_resize_lock_after_commit_) {
- create_resize_lock_after_commit_ = false;
- MaybeCreateResizeLock();
- }
}
void DelegatedFrameHost::OnCompositingStarted(ui::Compositor* compositor,
@@ -637,22 +434,6 @@ void DelegatedFrameHost::OnCompositingEnded(ui::Compositor* compositor) {}
void DelegatedFrameHost::OnCompositingLockStateChanged(
ui::Compositor* compositor) {
- if (resize_lock_ && resize_lock_->timed_out()) {
- // A compositor lock that is part of a resize lock timed out. We allow
- // the UI to produce a frame before locking it again, so we don't lock here.
- // We release the |resize_lock_| though to allow any other resizes that are
- // desired at the same time since we're allowing the UI to make a frame
- // which will gutter anyways.
- resize_lock_.reset();
- create_resize_lock_after_commit_ = true;
- // Because this timed out, we're going to allow the UI to update and lock
- // again. We would allow renderer frames through during this time if they
- // came late, but would stop them again once the UI finished its frame. We
- // want to allow the slow renderer to show us one frame even if its wrong
- // since we're guttering anyways, but not unlimited number of frames as that
- // would be a waste of power.
- allow_one_renderer_frame_during_resize_lock_ = true;
- }
}
void DelegatedFrameHost::OnCompositingChildResizing(
@@ -687,7 +468,6 @@ void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) {
void DelegatedFrameHost::ResetCompositor() {
if (!compositor_)
return;
- resize_lock_.reset();
if (compositor_->HasObserver(this))
compositor_->RemoveObserver(this);
if (should_register_frame_sink_id_)
@@ -763,10 +543,6 @@ void DelegatedFrameHost::TakeFallbackContentFrom(DelegatedFrameHost* other) {
}
client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId(
*other->client_->DelegatedFrameHostGetLayer()->GetFallbackSurfaceId());
- if (!enable_surface_synchronization_) {
- current_frame_size_in_dip_ = other->current_frame_size_in_dip_;
- UpdateGutters();
- }
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index c8a99f8374e..98f59da7af8 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -13,6 +13,7 @@
#include "components/viz/client/frame_evictor.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/host/hit_test/hit_test_query.h"
#include "components/viz/host/host_frame_sink_client.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/renderer_host/dip_util.h"
@@ -27,10 +28,6 @@
#include "ui/events/event.h"
#include "ui/gfx/geometry/rect_conversions.h"
-namespace base {
-class TickClock;
-}
-
namespace viz {
class CompositorFrameSinkSupport;
}
@@ -38,7 +35,6 @@ class CompositorFrameSinkSupport;
namespace content {
class DelegatedFrameHost;
-class CompositorResizeLock;
// The DelegatedFrameHostClient is the interface from the DelegatedFrameHost,
// which manages delegated frames, and the ui::Compositor being used to
@@ -53,14 +49,9 @@ class CONTENT_EXPORT DelegatedFrameHostClient {
// Returns the color that the resize gutters should be drawn with.
virtual SkColor DelegatedFrameHostGetGutterColor() const = 0;
- virtual bool DelegatedFrameCanCreateResizeLock() const = 0;
- virtual std::unique_ptr<CompositorResizeLock>
- DelegatedFrameHostCreateResizeLock() = 0;
-
virtual void OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) = 0;
virtual void OnBeginFrame(base::TimeTicks frame_time) = 0;
- virtual bool IsAutoResizeEnabled() const = 0;
virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
virtual void DidReceiveFirstFrameAfterNavigation() = 0;
};
@@ -82,7 +73,6 @@ class CONTENT_EXPORT DelegatedFrameHost
// responsible for doing the appropriate [un]registration.
DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
DelegatedFrameHostClient* client,
- bool enable_surface_synchronization,
bool enable_viz,
bool should_register_frame_sink_id);
~DelegatedFrameHost() override;
@@ -126,16 +116,16 @@ class CONTENT_EXPORT DelegatedFrameHost
void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list);
+ 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,
const gfx::Size& dip_size,
const ui::LatencyInfo& latency_info);
- void WasResized(const viz::LocalSurfaceId& local_surface_id,
- const gfx::Size& dip_size,
- cc::DeadlinePolicy deadline_policy);
+ void SynchronizeVisualProperties(const viz::LocalSurfaceId& local_surface_id,
+ const gfx::Size& dip_size,
+ cc::DeadlinePolicy deadline_policy);
bool HasSavedFrame() const;
gfx::Size GetRequestedRendererSize() const;
void SetCompositor(ui::Compositor* compositor);
@@ -154,18 +144,21 @@ class CONTENT_EXPORT DelegatedFrameHost
// Surface, find the relative transform between the Surfaces and apply it
// to a point. Returns false if a Surface has not yet been created or if
// |original_surface| is not embedded within our current Surface.
- bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
- const viz::SurfaceId& original_surface,
- gfx::PointF* transformed_point);
+ bool TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point);
// Given a RenderWidgetHostViewBase that renders to a Surface that is
// contained within this class' Surface, find the relative transform between
// the Surfaces and apply it to a point. Returns false if a Surface has not
// yet been created or if |target_view| is not a descendant RWHV from our
// client.
- bool TransformPointToCoordSpaceForView(const gfx::PointF& point,
- RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point);
+ bool TransformPointToCoordSpaceForView(
+ const gfx::PointF& point,
+ RenderWidgetHostViewBase* target_view,
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY);
void SetNeedsBeginFrames(bool needs_begin_frames);
void SetWantsAnimateOnlyBeginFrames();
@@ -187,9 +180,6 @@ class CONTENT_EXPORT DelegatedFrameHost
void OnCompositingDidCommitForTesting(ui::Compositor* compositor) {
OnCompositingDidCommit(compositor);
}
- bool ReleasedFrontLockActiveForTesting() const {
- return !!released_front_lock_.get();
- }
gfx::Size CurrentFrameSizeInDipForTesting() const {
return current_frame_size_in_dip_;
@@ -215,21 +205,8 @@ class CONTENT_EXPORT DelegatedFrameHost
void LockResources();
void UnlockResources();
- bool ShouldSkipFrame(const gfx::Size& size_in_dip);
-
- // Lazily grab a resize lock if the aura window size doesn't match the current
- // frame size, to give time to the renderer.
- void MaybeCreateResizeLock();
-
- // Checks if the resize lock can be released because we received an new frame.
- void CheckResizeLock();
-
SkColor GetGutterColor() const;
- // Update the layers for the resize gutters to the right and bottom of the
- // surface layer.
- void UpdateGutters();
-
void CreateCompositorFrameSinkSupport();
void ResetCompositorFrameSinkSupport();
@@ -238,7 +215,6 @@ class CONTENT_EXPORT DelegatedFrameHost
const viz::FrameSinkId frame_sink_id_;
DelegatedFrameHostClient* const client_;
- const bool enable_surface_synchronization_;
const bool enable_viz_;
const bool should_register_frame_sink_id_;
ui::Compositor* compositor_ = nullptr;
@@ -249,49 +225,25 @@ class CONTENT_EXPORT DelegatedFrameHost
// The scale factor of the above surface.
float active_device_scale_factor_ = 0.f;
- // The local surface id as of the most recent call to WasResized or WasShown.
- // This is the surface that we expect future frames to reference. This will
- // eventually equal the active surface.
+ // The local surface id as of the most recent call to
+ // SynchronizeVisualProperties or WasShown. This is the surface that we expect
+ // future frames to reference. This will eventually equal the active surface.
viz::LocalSurfaceId pending_local_surface_id_;
// The size of the above surface (updated at the same time).
gfx::Size pending_surface_dip_size_;
// In non-surface sync, this is the size of the most recently activated
// surface (which is suitable for calculating gutter size). In surface sync,
- // this is most recent size set in WasResized.
+ // this is most recent size set in SynchronizeVisualProperties.
// TODO(ccameron): The meaning of "current" should be made more clear here.
gfx::Size current_frame_size_in_dip_;
- // Overridable tick clock used for testing functions using current time.
- const base::TickClock* tick_clock_;
-
- // True after a delegated frame has been skipped, until a frame is not
- // skipped.
- bool skipped_frames_ = false;
- std::vector<ui::LatencyInfo> skipped_latency_info_list_;
-
- std::unique_ptr<ui::Layer> right_gutter_;
- std::unique_ptr<ui::Layer> bottom_gutter_;
-
// This is the last root background color from a swapped frame.
SkColor background_color_;
// State for rendering into a Surface.
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
- // This lock is the one waiting for a frame of the right size to come back
- // from the renderer/GPU process. It is set from the moment the aura window
- // got resized, to the moment we committed the renderer frame of the same
- // size. It keeps track of the size we expect from the renderer, and locks the
- // compositor, as well as the UI for a short time to give a chance to the
- // renderer of producing a frame of the right size.
- std::unique_ptr<CompositorResizeLock> resize_lock_;
- bool create_resize_lock_after_commit_ = false;
- bool allow_one_renderer_frame_during_resize_lock_ = false;
-
- // This lock is for waiting for a front surface to become available to draw.
- std::unique_ptr<ui::CompositorLock> released_front_lock_;
-
bool needs_begin_frame_ = false;
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc
index 6aa11b0afd0..4c83aa1b8d5 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.cc
@@ -37,34 +37,9 @@ SkColor DelegatedFrameHostClientAura::DelegatedFrameHostGetGutterColor() const {
->IsFullscreenForCurrentTab()) {
return SK_ColorBLACK;
}
- return render_widget_host_view_->background_color_;
-}
-
-bool DelegatedFrameHostClientAura::DelegatedFrameCanCreateResizeLock() const {
-#if !defined(OS_CHROMEOS)
- // On Windows and Linux, holding pointer moves will not help throttling
- // resizes.
- // TODO(piman): on Windows we need to block (nested run loop?) the
- // WM_SIZE event. On Linux we need to throttle at the WM level using
- // _NET_WM_SYNC_REQUEST.
- return false;
-#else
- if (!render_widget_host_view_->host_->renderer_initialized() ||
- render_widget_host_view_->host_->auto_resize_enabled()) {
- return false;
- }
- return true;
-#endif
-}
-
-std::unique_ptr<CompositorResizeLock>
-DelegatedFrameHostClientAura::DelegatedFrameHostCreateResizeLock() {
- // Pointer moves are released when the CompositorResizeLock ends.
- auto* host = render_widget_host_view_->window_->GetHost();
- host->dispatcher()->HoldPointerMoves();
-
- gfx::Size desired_size = render_widget_host_view_->window_->bounds().size();
- return std::make_unique<CompositorResizeLock>(this, desired_size);
+ if (render_widget_host_view_->GetBackgroundColor())
+ return *render_widget_host_view_->GetBackgroundColor();
+ return SK_ColorWHITE;
}
void DelegatedFrameHostClientAura::OnFirstSurfaceActivation(
@@ -74,27 +49,10 @@ void DelegatedFrameHostClientAura::OnBeginFrame(base::TimeTicks frame_time) {
render_widget_host_view_->OnBeginFrame(frame_time);
}
-bool DelegatedFrameHostClientAura::IsAutoResizeEnabled() const {
- return render_widget_host_view_->host_->auto_resize_enabled();
-}
-
void DelegatedFrameHostClientAura::OnFrameTokenChanged(uint32_t frame_token) {
render_widget_host_view_->OnFrameTokenChangedForView(frame_token);
}
-std::unique_ptr<ui::CompositorLock>
-DelegatedFrameHostClientAura::GetCompositorLock(
- ui::CompositorLockClient* client) {
- auto* window_host = render_widget_host_view_->window_->GetHost();
- return window_host->compositor()->GetCompositorLock(client);
-}
-
-void DelegatedFrameHostClientAura::CompositorResizeLockEnded() {
- auto* window_host = render_widget_host_view_->window_->GetHost();
- window_host->dispatcher()->ReleasePointerMoves();
- render_widget_host_view_->host_->WasResized();
-}
-
void DelegatedFrameHostClientAura::DidReceiveFirstFrameAfterNavigation() {
render_widget_host_view_->host_->DidReceiveFirstFrameAfterNavigation();
}
diff --git a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h
index 0fcd7a4c647..9a7964ddc24 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host_client_aura.h
@@ -6,7 +6,6 @@
#define CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_HOST_CLIENT_AURA_H_
#include "base/macros.h"
-#include "content/browser/renderer_host/compositor_resize_lock.h"
#include "content/browser/renderer_host/delegated_frame_host.h"
#include "content/common/content_export.h"
@@ -16,8 +15,7 @@ class RenderWidgetHostViewAura;
// DelegatedFrameHostClient implementation for aura, not used in mus.
class CONTENT_EXPORT DelegatedFrameHostClientAura
- : public DelegatedFrameHostClient,
- public CompositorResizeLockClient {
+ : public DelegatedFrameHostClient {
public:
explicit DelegatedFrameHostClientAura(
RenderWidgetHostViewAura* render_widget_host_view);
@@ -32,20 +30,11 @@ class CONTENT_EXPORT DelegatedFrameHostClientAura
ui::Layer* DelegatedFrameHostGetLayer() const override;
bool DelegatedFrameHostIsVisible() const override;
SkColor DelegatedFrameHostGetGutterColor() const override;
- bool DelegatedFrameCanCreateResizeLock() const override;
- std::unique_ptr<CompositorResizeLock> DelegatedFrameHostCreateResizeLock()
- override;
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnBeginFrame(base::TimeTicks frame_time) override;
- bool IsAutoResizeEnabled() const override;
void OnFrameTokenChanged(uint32_t frame_token) override;
void DidReceiveFirstFrameAfterNavigation() override;
- // CompositorResizeLockClient implementation.
- std::unique_ptr<ui::CompositorLock> GetCompositorLock(
- ui::CompositorLockClient* client) override;
- void CompositorResizeLockEnded() override;
-
private:
RenderWidgetHostViewAura* render_widget_host_view_;
diff --git a/chromium/content/browser/renderer_host/direct_manipulation_browsertest.cc b/chromium/content/browser/renderer_host/direct_manipulation_browsertest.cc
index 38c2793c6fc..9a266c839f9 100644
--- a/chromium/content/browser/renderer_host/direct_manipulation_browsertest.cc
+++ b/chromium/content/browser/renderer_host/direct_manipulation_browsertest.cc
@@ -113,10 +113,10 @@ IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, HWNDReparent) {
UpdateParent(
shell2->window()->GetRootWindow()->GetHost()->GetAcceleratedWidget());
- shell()->Close();
-
// The animation observer should be removed.
EXPECT_FALSE(HasCompositorAnimationObserver(lrwhh));
+
+ shell2->Close();
}
// EventLogger is to obserser the events sent from WindowEventTarget (the root
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/chromium/content/browser/renderer_host/embedded_frame_sink_impl.cc
index 59d8e00e150..0d7a15810ea 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
+++ b/chromium/content/browser/renderer_host/embedded_frame_sink_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
+#include "content/browser/renderer_host/embedded_frame_sink_impl.h"
#include <memory>
#include <utility>
@@ -14,11 +14,11 @@
namespace content {
-OffscreenCanvasSurfaceImpl::OffscreenCanvasSurfaceImpl(
+EmbeddedFrameSinkImpl::EmbeddedFrameSinkImpl(
viz::HostFrameSinkManager* host_frame_sink_manager,
const viz::FrameSinkId& parent_frame_sink_id,
const viz::FrameSinkId& frame_sink_id,
- blink::mojom::OffscreenCanvasSurfaceClientPtr client,
+ blink::mojom::EmbeddedFrameSinkClientPtr client,
DestroyCallback destroy_callback)
: host_frame_sink_manager_(host_frame_sink_manager),
client_(std::move(client)),
@@ -26,11 +26,11 @@ OffscreenCanvasSurfaceImpl::OffscreenCanvasSurfaceImpl(
frame_sink_id_(frame_sink_id) {
client_.set_connection_error_handler(std::move(destroy_callback));
host_frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_, this);
- host_frame_sink_manager_->SetFrameSinkDebugLabel(
- frame_sink_id_, "OffscreenCanvasSurfaceImpl");
+ host_frame_sink_manager_->SetFrameSinkDebugLabel(frame_sink_id_,
+ "EmbeddedFrameSinkImpl");
}
-OffscreenCanvasSurfaceImpl::~OffscreenCanvasSurfaceImpl() {
+EmbeddedFrameSinkImpl::~EmbeddedFrameSinkImpl() {
if (has_created_compositor_frame_sink_) {
host_frame_sink_manager_->UnregisterFrameSinkHierarchy(
parent_frame_sink_id_, frame_sink_id_);
@@ -38,23 +38,29 @@ OffscreenCanvasSurfaceImpl::~OffscreenCanvasSurfaceImpl() {
host_frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
}
-void OffscreenCanvasSurfaceImpl::CreateCompositorFrameSink(
+void EmbeddedFrameSinkImpl::CreateCompositorFrameSink(
viz::mojom::CompositorFrameSinkClientPtr client,
viz::mojom::CompositorFrameSinkRequest request) {
- if (has_created_compositor_frame_sink_) {
- DLOG(ERROR) << "CreateCompositorFrameSink() called more than once.";
- return;
+ // We might recreate the CompositorFrameSink on context loss or GPU crash.
+ // Only register frame sink hierarchy the first time.
+ if (!has_created_compositor_frame_sink_) {
+ // The request to create an embedded frame sink and the lifetime of the
+ // parent are controlled by different IPC channels. It's possible the parent
+ // FrameSinkId has been invalidated by the time this request has arrived. In
+ // that case, drop the request since there is no embedder.
+ if (!host_frame_sink_manager_->RegisterFrameSinkHierarchy(
+ parent_frame_sink_id_, frame_sink_id_)) {
+ return;
+ }
}
host_frame_sink_manager_->CreateCompositorFrameSink(
frame_sink_id_, std::move(request), std::move(client));
- host_frame_sink_manager_->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
- frame_sink_id_);
has_created_compositor_frame_sink_ = true;
}
-void OffscreenCanvasSurfaceImpl::OnFirstSurfaceActivation(
+void EmbeddedFrameSinkImpl::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
DCHECK_EQ(surface_info.id().frame_sink_id(), frame_sink_id_);
@@ -63,7 +69,7 @@ void OffscreenCanvasSurfaceImpl::OnFirstSurfaceActivation(
client_->OnFirstSurfaceActivation(surface_info);
}
-void OffscreenCanvasSurfaceImpl::OnFrameTokenChanged(uint32_t frame_token) {
+void EmbeddedFrameSinkImpl::OnFrameTokenChanged(uint32_t frame_token) {
// TODO(yiyix, fsamuel): To complete plumbing of frame tokens for offscreen
// canvas
}
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h b/chromium/content/browser/renderer_host/embedded_frame_sink_impl.h
index d098b8b1386..9fd4f631cac 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_surface_impl.h
+++ b/chromium/content/browser/renderer_host/embedded_frame_sink_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_IMPL_H_
-#define CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_IMPL_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_EMBEDDED_FRAME_SINK_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_EMBEDDED_FRAME_SINK_IMPL_H_
#include "base/callback.h"
#include "base/compiler_specific.h"
@@ -12,7 +12,7 @@
#include "components/viz/host/host_frame_sink_client.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/blink/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h"
+#include "third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom.h"
namespace viz {
class HostFrameSinkManager;
@@ -20,32 +20,28 @@ class HostFrameSinkManager;
namespace content {
-// The browser owned object for an embedded surface in a renderer process. Both
-// the embedder and embedded surface are in the same renderer. Holds a client
-// connection to the renderer that is notified when a new SurfaceId activates
-// for the embedded surface.
-class CONTENT_EXPORT OffscreenCanvasSurfaceImpl
- : public viz::HostFrameSinkClient {
+// The browser owned object for an embedded frame sink in a renderer process.
+// Both the embedder and embedded frame sink are in the same renderer. Holds a
+// client connection to the renderer that is notified when a new SurfaceId
+// activates for the embedded frame sink.
+class CONTENT_EXPORT EmbeddedFrameSinkImpl : public viz::HostFrameSinkClient {
public:
using DestroyCallback = base::OnceCallback<void()>;
- OffscreenCanvasSurfaceImpl(
- viz::HostFrameSinkManager* host_frame_sink_manager,
- const viz::FrameSinkId& parent_frame_sink_id,
- const viz::FrameSinkId& frame_sink_id,
- blink::mojom::OffscreenCanvasSurfaceClientPtr client,
- DestroyCallback destroy_callback);
- ~OffscreenCanvasSurfaceImpl() override;
+ EmbeddedFrameSinkImpl(viz::HostFrameSinkManager* host_frame_sink_manager,
+ const viz::FrameSinkId& parent_frame_sink_id,
+ const viz::FrameSinkId& frame_sink_id,
+ blink::mojom::EmbeddedFrameSinkClientPtr client,
+ DestroyCallback destroy_callback);
+ ~EmbeddedFrameSinkImpl() override;
const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
const viz::LocalSurfaceId& local_surface_id() const {
return local_surface_id_;
}
- // Creates a CompositorFrameSink connection to FrameSinkManagerImpl for an
- // offscreen canvas client. The corresponding private interface will be owned
- // here to control CompositorFrameSink lifetime. This should only ever be
- // called once.
+ // Creates a CompositorFrameSink connection to FrameSinkManagerImpl. This
+ // should only ever be called once.
void CreateCompositorFrameSink(
viz::mojom::CompositorFrameSinkClientPtr client,
viz::mojom::CompositorFrameSinkRequest request);
@@ -57,7 +53,7 @@ class CONTENT_EXPORT OffscreenCanvasSurfaceImpl
private:
viz::HostFrameSinkManager* const host_frame_sink_manager_;
- blink::mojom::OffscreenCanvasSurfaceClientPtr client_;
+ blink::mojom::EmbeddedFrameSinkClientPtr client_;
// Surface-related state
const viz::FrameSinkId parent_frame_sink_id_;
@@ -66,9 +62,9 @@ class CONTENT_EXPORT OffscreenCanvasSurfaceImpl
bool has_created_compositor_frame_sink_ = false;
- DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasSurfaceImpl);
+ DISALLOW_COPY_AND_ASSIGN(EmbeddedFrameSinkImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_SURFACE_IMPL_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_EMBEDDED_FRAME_SINK_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.cc b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.cc
new file mode 100644
index 00000000000..6ed9bb436f9
--- /dev/null
+++ b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.cc
@@ -0,0 +1,89 @@
+// Copyright 2016 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/renderer_host/embedded_frame_sink_provider_impl.h"
+
+#include "base/bind.h"
+#include "components/viz/host/host_frame_sink_manager.h"
+#include "content/browser/renderer_host/embedded_frame_sink_impl.h"
+
+namespace content {
+
+EmbeddedFrameSinkProviderImpl::EmbeddedFrameSinkProviderImpl(
+ viz::HostFrameSinkManager* host_frame_sink_manager,
+ uint32_t renderer_client_id)
+ : host_frame_sink_manager_(host_frame_sink_manager),
+ renderer_client_id_(renderer_client_id) {
+ DCHECK(host_frame_sink_manager);
+}
+
+EmbeddedFrameSinkProviderImpl::~EmbeddedFrameSinkProviderImpl() = default;
+
+void EmbeddedFrameSinkProviderImpl::Add(
+ blink::mojom::EmbeddedFrameSinkProviderRequest request) {
+ bindings_.AddBinding(this, std::move(request));
+}
+
+void EmbeddedFrameSinkProviderImpl::RegisterEmbeddedFrameSink(
+ const viz::FrameSinkId& parent_frame_sink_id,
+ const viz::FrameSinkId& frame_sink_id,
+ blink::mojom::EmbeddedFrameSinkClientPtr client) {
+ // TODO(kylechar): Kill the renderer too.
+ if (parent_frame_sink_id.client_id() != renderer_client_id_) {
+ DLOG(ERROR) << "Invalid parent client id " << parent_frame_sink_id;
+ return;
+ }
+ if (frame_sink_id.client_id() != renderer_client_id_) {
+ DLOG(ERROR) << "Invalid client id " << frame_sink_id;
+ return;
+ }
+
+ auto destroy_callback =
+ base::BindOnce(&EmbeddedFrameSinkProviderImpl::DestroyEmbeddedFrameSink,
+ base::Unretained(this), frame_sink_id);
+
+ frame_sink_map_[frame_sink_id] = std::make_unique<EmbeddedFrameSinkImpl>(
+ host_frame_sink_manager_, parent_frame_sink_id, frame_sink_id,
+ std::move(client), std::move(destroy_callback));
+}
+
+void EmbeddedFrameSinkProviderImpl::CreateCompositorFrameSink(
+ const viz::FrameSinkId& frame_sink_id,
+ viz::mojom::CompositorFrameSinkClientPtr client,
+ viz::mojom::CompositorFrameSinkRequest request) {
+ // TODO(kylechar): Kill the renderer too.
+ if (frame_sink_id.client_id() != renderer_client_id_) {
+ DLOG(ERROR) << "Invalid client id " << frame_sink_id;
+ return;
+ }
+
+ auto iter = frame_sink_map_.find(frame_sink_id);
+ if (iter == frame_sink_map_.end()) {
+ DLOG(ERROR) << "No EmbeddedFrameSinkImpl for " << frame_sink_id;
+ return;
+ }
+
+ iter->second->CreateCompositorFrameSink(std::move(client),
+ std::move(request));
+}
+
+void EmbeddedFrameSinkProviderImpl::CreateSimpleCompositorFrameSink(
+ const viz::FrameSinkId& parent_frame_sink_id,
+ const viz::FrameSinkId& frame_sink_id,
+ blink::mojom::EmbeddedFrameSinkClientPtr embedded_frame_sink_client,
+ viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client,
+ viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request) {
+ RegisterEmbeddedFrameSink(parent_frame_sink_id, frame_sink_id,
+ std::move(embedded_frame_sink_client));
+ CreateCompositorFrameSink(frame_sink_id,
+ std::move(compositor_frame_sink_client),
+ std::move(compositor_frame_sink_request));
+}
+
+void EmbeddedFrameSinkProviderImpl::DestroyEmbeddedFrameSink(
+ viz::FrameSinkId frame_sink_id) {
+ frame_sink_map_.erase(frame_sink_id);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.h b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.h
new file mode 100644
index 00000000000..92435a35f4a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl.h
@@ -0,0 +1,74 @@
+// Copyright 2016 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_RENDERER_HOST_EMBEDDED_FRAME_SINK_PROVIDER_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_EMBEDDED_FRAME_SINK_PROVIDER_IMPL_H_
+
+#include <memory>
+
+#include "base/containers/flat_map.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom.h"
+
+namespace viz {
+class HostFrameSinkManager;
+}
+
+namespace content {
+
+class EmbeddedFrameSinkImpl;
+
+// Provides embedded frame sinks for a renderer.
+class CONTENT_EXPORT EmbeddedFrameSinkProviderImpl
+ : public blink::mojom::EmbeddedFrameSinkProvider {
+ public:
+ EmbeddedFrameSinkProviderImpl(
+ viz::HostFrameSinkManager* host_frame_sink_manager,
+ uint32_t renderer_client_id);
+ ~EmbeddedFrameSinkProviderImpl() override;
+
+ void Add(blink::mojom::EmbeddedFrameSinkProviderRequest request);
+
+ // blink::mojom::EmbeddedFrameSinkProvider implementation.
+ void RegisterEmbeddedFrameSink(
+ const viz::FrameSinkId& parent_frame_sink_id,
+ const viz::FrameSinkId& frame_sink_id,
+ blink::mojom::EmbeddedFrameSinkClientPtr client) override;
+ void CreateCompositorFrameSink(
+ const viz::FrameSinkId& frame_sink_id,
+ viz::mojom::CompositorFrameSinkClientPtr client,
+ viz::mojom::CompositorFrameSinkRequest request) override;
+ void CreateSimpleCompositorFrameSink(
+ const viz::FrameSinkId& parent_frame_sink_id,
+ const viz::FrameSinkId& frame_sink_id,
+ blink::mojom::EmbeddedFrameSinkClientPtr embedded_frame_sink_client,
+ viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client,
+ viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request)
+ override;
+
+ private:
+ friend class EmbeddedFrameSinkProviderImplTest;
+
+ // Destroys the |frame_sink_map_| entry for |frame_sink_id|. Provided as
+ // a callback to each EmbeddedFrameSinkImpl so they can destroy themselves.
+ void DestroyEmbeddedFrameSink(viz::FrameSinkId frame_sink_id);
+
+ viz::HostFrameSinkManager* const host_frame_sink_manager_;
+
+ // FrameSinkIds for embedded frame sinks must use the renderer client id.
+ const uint32_t renderer_client_id_;
+
+ mojo::BindingSet<blink::mojom::EmbeddedFrameSinkProvider> bindings_;
+
+ base::flat_map<viz::FrameSinkId, std::unique_ptr<EmbeddedFrameSinkImpl>>
+ frame_sink_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(EmbeddedFrameSinkProviderImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_EMBEDDED_FRAME_SINK_PROVIDER_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
index eb896c946a4..02999045b0b 100644
--- a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/renderer_host/offscreen_canvas_provider_impl.h"
+#include "content/browser/renderer_host/embedded_frame_sink_provider_impl.h"
#include <algorithm>
#include <utility>
@@ -10,6 +10,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -17,11 +18,11 @@
#include "components/viz/test/fake_host_frame_sink_client.h"
#include "components/viz/test/mock_compositor_frame_sink_client.h"
#include "content/browser/compositor/surface_utils.h"
-#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
+#include "content/browser/renderer_host/embedded_frame_sink_impl.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h"
+#include "third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom.h"
#include "ui/compositor/compositor.h"
#if !defined(OS_ANDROID)
@@ -39,25 +40,27 @@ constexpr viz::FrameSinkId kFrameSinkParent(kRendererClientId, 1);
constexpr viz::FrameSinkId kFrameSinkA(kRendererClientId, 3);
constexpr viz::FrameSinkId kFrameSinkB(kRendererClientId, 4);
-// Creates a closure that sets |error_variable| true when run.
-base::OnceClosure ConnectionErrorClosure(bool* error_variable) {
- DCHECK(error_variable);
- return base::BindOnce([](bool* error_variable) { *error_variable = true; },
- error_variable);
+// Runs RunLoop until |endpoint| encounters a connection error.
+template <class T>
+void WaitForConnectionError(T* endpoint) {
+ base::RunLoop run_loop;
+ endpoint->set_connection_error_handler(run_loop.QuitClosure());
+ run_loop.Run();
}
-// Stub OffscreenCanvasSurfaceClient that stores the latest SurfaceInfo.
-class StubOffscreenCanvasSurfaceClient
- : public blink::mojom::OffscreenCanvasSurfaceClient {
+// Stub EmbeddedFrameSinkClient that stores the latest SurfaceInfo.
+class StubEmbeddedFrameSinkClient
+ : public blink::mojom::EmbeddedFrameSinkClient {
public:
- StubOffscreenCanvasSurfaceClient() : binding_(this) {}
- ~StubOffscreenCanvasSurfaceClient() override {}
+ StubEmbeddedFrameSinkClient() : binding_(this) {}
+ ~StubEmbeddedFrameSinkClient() override {}
- blink::mojom::OffscreenCanvasSurfaceClientPtr GetInterfacePtr() {
- blink::mojom::OffscreenCanvasSurfaceClientPtr client;
+ blink::mojom::EmbeddedFrameSinkClientPtr GetInterfacePtr() {
+ blink::mojom::EmbeddedFrameSinkClientPtr client;
binding_.Bind(mojo::MakeRequest(&client));
binding_.set_connection_error_handler(
- ConnectionErrorClosure(&connection_error_));
+ base::BindOnce([](bool* error_variable) { *error_variable = true; },
+ &connection_error_));
return client;
}
@@ -70,44 +73,44 @@ class StubOffscreenCanvasSurfaceClient
bool connection_error() const { return connection_error_; }
private:
- // blink::mojom::OffscreenCanvasSurfaceClient:
+ // blink::mojom::EmbeddedFrameSinkClient:
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
last_surface_info_ = surface_info;
}
- mojo::Binding<blink::mojom::OffscreenCanvasSurfaceClient> binding_;
+ mojo::Binding<blink::mojom::EmbeddedFrameSinkClient> binding_;
viz::SurfaceInfo last_surface_info_;
bool connection_error_ = false;
- DISALLOW_COPY_AND_ASSIGN(StubOffscreenCanvasSurfaceClient);
+ DISALLOW_COPY_AND_ASSIGN(StubEmbeddedFrameSinkClient);
};
} // namespace
-class OffscreenCanvasProviderImplTest : public testing::Test {
+class EmbeddedFrameSinkProviderImplTest : public testing::Test {
public:
- OffscreenCanvasProviderImpl* provider() { return provider_.get(); }
+ EmbeddedFrameSinkProviderImpl* provider() { return provider_.get(); }
- // Gets the OffscreenCanvasSurfaceImpl for |frame_sink_id| or null if it
- // it doesn't exist.
- OffscreenCanvasSurfaceImpl* GetOffscreenCanvasSurface(
+ // Gets the EmbeddedFrameSinkImpl for |frame_sink_id| or null if it doesn't
+ // exist.
+ EmbeddedFrameSinkImpl* GetEmbeddedFrameSink(
const viz::FrameSinkId& frame_sink_id) {
- auto iter = provider_->canvas_map_.find(frame_sink_id);
- if (iter == provider_->canvas_map_.end())
+ auto iter = provider_->frame_sink_map_.find(frame_sink_id);
+ if (iter == provider_->frame_sink_map_.end())
return nullptr;
return iter->second.get();
}
- // Gets list of FrameSinkId for all offscreen canvases.
+ // Gets list of FrameSinkId for all EmbeddedFrameSinkImpls.
std::vector<viz::FrameSinkId> GetAllCanvases() {
std::vector<viz::FrameSinkId> frame_sink_ids;
- for (auto& map_entry : provider_->canvas_map_)
+ for (auto& map_entry : provider_->frame_sink_map_)
frame_sink_ids.push_back(map_entry.second->frame_sink_id());
std::sort(frame_sink_ids.begin(), frame_sink_ids.end());
return frame_sink_ids;
}
- void DeleteOffscreenCanvasProviderImpl() { provider_.reset(); }
+ void DeleteEmbeddedFrameSinkProviderImpl() { provider_.reset(); }
void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
@@ -120,7 +123,7 @@ class OffscreenCanvasProviderImplTest : public testing::Test {
surface_utils::ConnectWithLocalFrameSinkManager(
host_frame_sink_manager_.get(), frame_sink_manager_.get());
- provider_ = std::make_unique<OffscreenCanvasProviderImpl>(
+ provider_ = std::make_unique<EmbeddedFrameSinkProviderImpl>(
host_frame_sink_manager_.get(), kRendererClientId);
host_frame_sink_manager_->RegisterFrameSinkId(kFrameSinkParent,
@@ -140,23 +143,22 @@ class OffscreenCanvasProviderImplTest : public testing::Test {
viz::FakeHostFrameSinkClient host_frame_sink_client_;
std::unique_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_;
std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_;
- std::unique_ptr<OffscreenCanvasProviderImpl> provider_;
+ std::unique_ptr<EmbeddedFrameSinkProviderImpl> provider_;
};
// Mimics the workflow of OffscreenCanvas.commit() on renderer process.
-TEST_F(OffscreenCanvasProviderImplTest,
+TEST_F(EmbeddedFrameSinkProviderImplTest,
SingleHTMLCanvasElementTransferToOffscreen) {
// Mimic connection from the renderer main thread to browser.
- StubOffscreenCanvasSurfaceClient surface_client;
- provider()->CreateOffscreenCanvasSurface(kFrameSinkParent, kFrameSinkA,
- surface_client.GetInterfacePtr());
+ StubEmbeddedFrameSinkClient efs_client;
+ provider()->RegisterEmbeddedFrameSink(kFrameSinkParent, kFrameSinkA,
+ efs_client.GetInterfacePtr());
- OffscreenCanvasSurfaceImpl* surface_impl =
- GetOffscreenCanvasSurface(kFrameSinkA);
+ EmbeddedFrameSinkImpl* efs_impl = GetEmbeddedFrameSink(kFrameSinkA);
- // There should be a single OffscreenCanvasSurfaceImpl and it should have the
+ // There should be a single EmbeddedFrameSinkImpl and it should have the
// provided FrameSinkId.
- EXPECT_EQ(kFrameSinkA, surface_impl->frame_sink_id());
+ EXPECT_EQ(kFrameSinkA, efs_impl->frame_sink_id());
EXPECT_THAT(GetAllCanvases(), ElementsAre(kFrameSinkA));
// Mimic connection from the renderer main or worker thread to browser.
@@ -169,137 +171,147 @@ TEST_F(OffscreenCanvasProviderImplTest,
// Renderer submits a CompositorFrame with |local_id|.
const viz::LocalSurfaceId local_id(1, base::UnguessableToken::Create());
compositor_frame_sink->SubmitCompositorFrame(
- local_id, viz::MakeDefaultCompositorFrame(), nullptr,
+ local_id, viz::MakeDefaultCompositorFrame(), base::nullopt,
base::TimeTicks::Now().since_origin().InMicroseconds());
RunUntilIdle();
- // OffscreenCanvasSurfaceImpl in browser should have LocalSurfaceId that was
+ // EmbeddedFrameSinkImpl in browser should have LocalSurfaceId that was
// submitted with the CompositorFrame.
- EXPECT_EQ(local_id, surface_impl->local_surface_id());
+ EXPECT_EQ(local_id, efs_impl->local_surface_id());
- // OffscreenCanvasSurfaceClient in the renderer should get the new SurfaceId
+ // EmbeddedFrameSinkClient in the renderer should get the new SurfaceId
// including the |local_id|.
- const auto& surface_info = surface_client.last_surface_info();
+ const auto& surface_info = efs_client.last_surface_info();
EXPECT_EQ(kFrameSinkA, surface_info.id().frame_sink_id());
EXPECT_EQ(local_id, surface_info.id().local_surface_id());
}
-// Check that renderer closing the mojom::OffscreenCanvasSurface connection
-// destroys the OffscreenCanvasSurfaceImpl in browser.
-TEST_F(OffscreenCanvasProviderImplTest, ClientClosesConnection) {
- StubOffscreenCanvasSurfaceClient surface_client;
- provider()->CreateOffscreenCanvasSurface(kFrameSinkParent, kFrameSinkA,
- surface_client.GetInterfacePtr());
+// Check that renderer closing the mojom::EmbeddedFrameSinkClient connection
+// destroys the EmbeddedFrameSinkImpl in browser.
+TEST_F(EmbeddedFrameSinkProviderImplTest, ClientClosesConnection) {
+ StubEmbeddedFrameSinkClient efs_client;
+ provider()->RegisterEmbeddedFrameSink(kFrameSinkParent, kFrameSinkA,
+ efs_client.GetInterfacePtr());
RunUntilIdle();
EXPECT_THAT(GetAllCanvases(), ElementsAre(kFrameSinkA));
// Mimic closing the connection from the renderer.
- surface_client.Close();
+ efs_client.Close();
RunUntilIdle();
// The renderer closing the connection should destroy the
- // OffscreenCanvasSurfaceImpl.
+ // EmbeddedFrameSinkImpl.
EXPECT_THAT(GetAllCanvases(), IsEmpty());
}
-// Check that destroying OffscreenCanvasProviderImpl closes connection to
+// Check that destroying EmbeddedFrameSinkProviderImpl closes connection to
// renderer.
-TEST_F(OffscreenCanvasProviderImplTest, ProviderClosesConnections) {
- StubOffscreenCanvasSurfaceClient surface_client;
- provider()->CreateOffscreenCanvasSurface(kFrameSinkParent, kFrameSinkA,
- surface_client.GetInterfacePtr());
+TEST_F(EmbeddedFrameSinkProviderImplTest, ProviderClosesConnections) {
+ StubEmbeddedFrameSinkClient efs_client;
+ provider()->RegisterEmbeddedFrameSink(kFrameSinkParent, kFrameSinkA,
+ efs_client.GetInterfacePtr());
RunUntilIdle();
- // There should be a OffscreenCanvasSurfaceImpl and |surface_client| should be
+ // There should be a EmbeddedFrameSinkImpl and |efs_client| should be
// bound.
EXPECT_THAT(GetAllCanvases(), ElementsAre(kFrameSinkA));
- EXPECT_FALSE(surface_client.connection_error());
+ EXPECT_FALSE(efs_client.connection_error());
- // Delete OffscreenCanvasProviderImpl before client disconnects.
- DeleteOffscreenCanvasProviderImpl();
+ // Delete EmbeddedFrameSinkProviderImpl before client disconnects.
+ DeleteEmbeddedFrameSinkProviderImpl();
RunUntilIdle();
- // This should destroy the OffscreenCanvasSurfaceImpl and close the connection
- // to |surface_client| triggering a connection error.
- EXPECT_TRUE(surface_client.connection_error());
+ // This should destroy the EmbeddedFrameSinkImpl and close the connection
+ // to |efs_client| triggering a connection error.
+ EXPECT_TRUE(efs_client.connection_error());
}
// Check that connecting CompositorFrameSink without first making a
-// OffscreenCanvasSurface connection fails.
-TEST_F(OffscreenCanvasProviderImplTest, ClientConnectionWrongOrder) {
+// EmbeddedFrameSink connection fails.
+TEST_F(EmbeddedFrameSinkProviderImplTest, ClientConnectionWrongOrder) {
// Mimic connection from the renderer main or worker thread.
viz::mojom::CompositorFrameSinkPtr compositor_frame_sink;
viz::MockCompositorFrameSinkClient compositor_frame_sink_client;
// Try to connect CompositorFrameSink without first making
- // OffscreenCanvasSurface connection. This should fail.
+ // EmbeddedFrameSink connection. This should fail.
provider()->CreateCompositorFrameSink(
kFrameSinkA, compositor_frame_sink_client.BindInterfacePtr(),
mojo::MakeRequest(&compositor_frame_sink));
- // Observe connection errors on |compositor_frame_sink|.
- bool connection_error = false;
- compositor_frame_sink.set_connection_error_handler(
- ConnectionErrorClosure(&connection_error));
+ // The request will fail and trigger a connection error.
+ WaitForConnectionError(&compositor_frame_sink);
+}
- RunUntilIdle();
+// Check that trying to create an EmbeddedFrameSinkImpl when the parent
+// FrameSinkId has already been invalidated fails.
+TEST_F(EmbeddedFrameSinkProviderImplTest, ParentNotRegistered) {
+ StubEmbeddedFrameSinkClient efs_client;
+ provider()->RegisterEmbeddedFrameSink(kFrameSinkA, kFrameSinkB,
+ efs_client.GetInterfacePtr());
- // The connection for |compositor_frame_sink| will have failed and triggered a
- // connection error.
- EXPECT_TRUE(connection_error);
+ viz::mojom::CompositorFrameSinkPtr compositor_frame_sink;
+ viz::MockCompositorFrameSinkClient compositor_frame_sink_client;
+ // The embedder, kFrameSinkA, has already been invalidated and isn't
+ // registered at this point. This request should fail.
+ provider()->CreateCompositorFrameSink(
+ kFrameSinkB, compositor_frame_sink_client.BindInterfacePtr(),
+ mojo::MakeRequest(&compositor_frame_sink));
+
+ // The request will fail and trigger a connection error.
+ WaitForConnectionError(&compositor_frame_sink);
}
-// Check that trying to create an OffscreenCanvasSurfaceImpl with a client id
+// Check that trying to create an EmbeddedFrameSinkImpl with a client id
// that doesn't match the renderer fails.
-TEST_F(OffscreenCanvasProviderImplTest, InvalidClientId) {
+TEST_F(EmbeddedFrameSinkProviderImplTest, InvalidClientId) {
const viz::FrameSinkId invalid_frame_sink_id(4, 3);
EXPECT_NE(kRendererClientId, invalid_frame_sink_id.client_id());
- StubOffscreenCanvasSurfaceClient surface_client;
- provider()->CreateOffscreenCanvasSurface(kFrameSinkParent,
- invalid_frame_sink_id,
- surface_client.GetInterfacePtr());
+ StubEmbeddedFrameSinkClient efs_client;
+ provider()->RegisterEmbeddedFrameSink(kFrameSinkParent, invalid_frame_sink_id,
+ efs_client.GetInterfacePtr());
RunUntilIdle();
- // No OffscreenCanvasSurfaceImpl should have been created.
+ // No EmbeddedFrameSinkImpl should have been created.
EXPECT_THAT(GetAllCanvases(), IsEmpty());
- // The connection for |surface_client| will have failed and triggered a
+ // The connection for |efs_client| will have failed and triggered a
// connection error.
- EXPECT_TRUE(surface_client.connection_error());
+ EXPECT_TRUE(efs_client.connection_error());
}
// Mimic renderer with two offscreen canvases.
-TEST_F(OffscreenCanvasProviderImplTest,
+TEST_F(EmbeddedFrameSinkProviderImplTest,
MultiHTMLCanvasElementTransferToOffscreen) {
- StubOffscreenCanvasSurfaceClient surface_client_a;
- provider()->CreateOffscreenCanvasSurface(kFrameSinkParent, kFrameSinkA,
- surface_client_a.GetInterfacePtr());
+ StubEmbeddedFrameSinkClient efs_client_a;
+ provider()->RegisterEmbeddedFrameSink(kFrameSinkParent, kFrameSinkA,
+ efs_client_a.GetInterfacePtr());
- StubOffscreenCanvasSurfaceClient surface_client_b;
- provider()->CreateOffscreenCanvasSurface(kFrameSinkParent, kFrameSinkB,
- surface_client_b.GetInterfacePtr());
+ StubEmbeddedFrameSinkClient efs_client_b;
+ provider()->RegisterEmbeddedFrameSink(kFrameSinkParent, kFrameSinkB,
+ efs_client_b.GetInterfacePtr());
RunUntilIdle();
- // There should be two OffscreenCanvasSurfaceImpls created.
+ // There should be two EmbeddedFrameSinkImpls created.
EXPECT_THAT(GetAllCanvases(), ElementsAre(kFrameSinkA, kFrameSinkB));
// Mimic closing first connection from the renderer.
- surface_client_a.Close();
+ efs_client_a.Close();
RunUntilIdle();
EXPECT_THAT(GetAllCanvases(), ElementsAre(kFrameSinkB));
// Mimic closing second connection from the renderer.
- surface_client_b.Close();
+ efs_client_b.Close();
RunUntilIdle();
diff --git a/chromium/content/browser/renderer_host/file_utilities_host_impl.cc b/chromium/content/browser/renderer_host/file_utilities_host_impl.cc
index e3b08f3083b..3ac5de41d00 100644
--- a/chromium/content/browser/renderer_host/file_utilities_host_impl.cc
+++ b/chromium/content/browser/renderer_host/file_utilities_host_impl.cc
@@ -20,7 +20,7 @@ FileUtilitiesHostImpl::~FileUtilitiesHostImpl() = default;
void FileUtilitiesHostImpl::Create(
int process_id,
- content::mojom::FileUtilitiesHostRequest request) {
+ blink::mojom::FileUtilitiesHostRequest request) {
mojo::MakeStrongBinding(std::make_unique<FileUtilitiesHostImpl>(process_id),
std::move(request));
}
diff --git a/chromium/content/browser/renderer_host/file_utilities_host_impl.h b/chromium/content/browser/renderer_host/file_utilities_host_impl.h
index 56fb38ae40f..23fe4807e3b 100644
--- a/chromium/content/browser/renderer_host/file_utilities_host_impl.h
+++ b/chromium/content/browser/renderer_host/file_utilities_host_impl.h
@@ -5,17 +5,17 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_FILE_UTILITIES_HOST_IMPL_H_
#define CONTENT_BROWSER_RENDERER_HOST_FILE_UTILITIES_HOST_IMPL_H_
-#include "content/common/file_utilities.mojom.h"
+#include "third_party/blink/public/mojom/file/file_utilities.mojom.h"
namespace content {
-class FileUtilitiesHostImpl : public content::mojom::FileUtilitiesHost {
+class FileUtilitiesHostImpl : public blink::mojom::FileUtilitiesHost {
public:
explicit FileUtilitiesHostImpl(int process_id);
~FileUtilitiesHostImpl() override;
static void Create(int process_id,
- content::mojom::FileUtilitiesHostRequest request);
+ blink::mojom::FileUtilitiesHostRequest request);
private:
// blink::mojom::FileUtilitiesHost implementation.
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.cc b/chromium/content/browser/renderer_host/frame_connector_delegate.cc
index 9ec6c756d3c..1a5aec8c20d 100644
--- a/chromium/content/browser/renderer_host/frame_connector_delegate.cc
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.cc
@@ -7,7 +7,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
namespace content {
@@ -25,11 +25,12 @@ FrameConnectorDelegate::GetRootRenderWidgetHostView() {
return nullptr;
}
-void FrameConnectorDelegate::UpdateResizeParams(
+void FrameConnectorDelegate::SynchronizeVisualProperties(
const viz::SurfaceId& surface_id,
- const FrameResizeParams& resize_params) {
+ const FrameVisualProperties& resize_params) {
screen_info_ = resize_params.screen_info;
local_surface_id_ = surface_id.local_surface_id();
+ capture_sequence_number_ = resize_params.capture_sequence_number;
SetScreenSpaceRect(resize_params.screen_space_rect);
SetLocalFrameSize(resize_params.local_frame_size);
@@ -47,13 +48,7 @@ void FrameConnectorDelegate::UpdateResizeParams(
resize_params.min_size_for_auto_resize,
resize_params.max_size_for_auto_resize);
- if (render_widget_host->auto_resize_enabled()) {
- render_widget_host->DidAllocateLocalSurfaceIdForAutoResize(
- resize_params.auto_resize_sequence_number);
- return;
- }
-
- render_widget_host->WasResized();
+ render_widget_host->SynchronizeVisualProperties();
}
gfx::PointF FrameConnectorDelegate::TransformPointToRootCoordSpace(
@@ -62,7 +57,7 @@ gfx::PointF FrameConnectorDelegate::TransformPointToRootCoordSpace(
return gfx::PointF();
}
-bool FrameConnectorDelegate::TransformPointToLocalCoordSpace(
+bool FrameConnectorDelegate::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
const viz::SurfaceId& local_surface_id,
@@ -74,7 +69,8 @@ bool FrameConnectorDelegate::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
const viz::SurfaceId& local_surface_id,
- gfx::PointF* transformed_point) {
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
return false;
}
@@ -95,6 +91,10 @@ bool FrameConnectorDelegate::IsInert() const {
return false;
}
+cc::TouchAction FrameConnectorDelegate::InheritedEffectiveTouchAction() const {
+ return cc::TouchAction::kTouchActionAuto;
+}
+
bool FrameConnectorDelegate::IsHidden() const {
return false;
}
diff --git a/chromium/content/browser/renderer_host/frame_connector_delegate.h b/chromium/content/browser/renderer_host/frame_connector_delegate.h
index 577db6d0147..a1239217056 100644
--- a/chromium/content/browser/renderer_host/frame_connector_delegate.h
+++ b/chromium/content/browser/renderer_host/frame_connector_delegate.h
@@ -5,7 +5,9 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_CONNECTOR_DELEGATE_H_
#define CONTENT_BROWSER_RENDERER_HOST_FRAME_CONNECTOR_DELEGATE_H_
+#include "cc/input/touch_action.h"
#include "components/viz/common/surfaces/local_surface_id.h"
+#include "components/viz/host/hit_test/hit_test_query.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
#include "content/public/common/input_event_ack_state.h"
@@ -21,6 +23,10 @@ class WebGestureEvent;
struct WebIntrinsicSizingInfo;
}
+namespace cc {
+class RenderFrameMetadata;
+}
+
namespace viz {
class SurfaceId;
class SurfaceInfo;
@@ -30,7 +36,7 @@ namespace content {
class RenderWidgetHostViewBase;
class RenderWidgetHostViewChildFrame;
class WebCursor;
-struct FrameResizeParams;
+struct FrameVisualProperties;
//
// FrameConnectorDelegate
@@ -73,32 +79,35 @@ class CONTENT_EXPORT FrameConnectorDelegate {
const blink::WebIntrinsicSizingInfo&) {}
// Sends new resize parameters to the sub-frame's renderer.
- void UpdateResizeParams(const viz::SurfaceId& surface_id,
- const FrameResizeParams& resize_params);
+ void SynchronizeVisualProperties(const viz::SurfaceId& surface_id,
+ const FrameVisualProperties& resize_params);
// Return the size of the CompositorFrame to use in the child renderer.
- const gfx::Size& local_frame_size_in_pixels() {
+ const gfx::Size& local_frame_size_in_pixels() const {
return local_frame_size_in_pixels_;
}
// Return the size of the CompositorFrame to use in the child renderer in DIP.
// This is used to set the layout size of the child renderer.
- const gfx::Size& local_frame_size_in_dip() {
+ const gfx::Size& local_frame_size_in_dip() const {
return local_frame_size_in_dip_;
}
// Return the rect in DIP that the RenderWidgetHostViewChildFrame's content
// will render into.
- const gfx::Rect& screen_space_rect_in_dip() {
+ const gfx::Rect& screen_space_rect_in_dip() const {
return screen_space_rect_in_dip_;
}
// Return the rect in pixels that the RenderWidgetHostViewChildFrame's content
// will render into.
- const gfx::Rect& screen_space_rect_in_pixels() {
+ const gfx::Rect& screen_space_rect_in_pixels() const {
return screen_space_rect_in_pixels_;
}
+ // Return the latest capture sequence number of this delegate.
+ uint32_t capture_sequence_number() const { return capture_sequence_number_; }
+
// Request that the platform change the mouse cursor when the mouse is
// positioned over this view's content.
virtual void UpdateCursor(const WebCursor& cursor) {}
@@ -113,12 +122,12 @@ class CONTENT_EXPORT FrameConnectorDelegate {
// Given a point in the coordinate space of a different Surface, transform
// it into the coordinate space for this view (corresponding to
// local_surface_id).
- // TransformPointToLocalCoordSpace() can only transform points between
+ // TransformPointToLocalCoordSpaceLegacy() can only transform points between
// surfaces where one is embedded (not necessarily directly) within the
// other, and will return false if this is not the case. For points that can
// be in sibling surfaces, they must first be converted to the root
// surface's coordinate space.
- virtual bool TransformPointToLocalCoordSpace(
+ virtual bool TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
const viz::SurfaceId& local_surface_id,
@@ -132,7 +141,8 @@ class CONTENT_EXPORT FrameConnectorDelegate {
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
const viz::SurfaceId& local_surface_id,
- gfx::PointF* transformed_point);
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY);
// Pass acked touch events to the root view for gesture processing.
virtual void ForwardProcessAckedTouchEvent(
@@ -195,6 +205,10 @@ class CONTENT_EXPORT FrameConnectorDelegate {
// or because the inert attribute has been specified.
virtual bool IsInert() const;
+ // Returns the inherited effective touch action property that should be
+ // applied to any nested child RWHVCFs inside the caller RWHVCF.
+ virtual cc::TouchAction InheritedEffectiveTouchAction() const;
+
// Determines whether the RenderWidgetHostViewChildFrame is hidden due to
// a higher-level embedder being hidden. This is distinct from the
// RenderWidgetHostImpl being hidden, which is a property set when
@@ -226,10 +240,10 @@ class CONTENT_EXPORT FrameConnectorDelegate {
ui::mojom::WindowTreeClientPtr window_tree_client) {}
#endif
- // Called by RenderWidgetHostViewChildFrame when the child frame has resized
- // to |new_size| because auto-resize is enabled.
- virtual void ResizeDueToAutoResize(const gfx::Size& new_size,
- uint64_t sequence_number) {}
+ // Called by RenderWidgetHostViewChildFrame when the child frame has updated
+ // its visual properties and its viz::LocalSurfaceId has changed.
+ virtual void DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {}
bool has_size() const { return has_size_; }
@@ -258,6 +272,8 @@ class CONTENT_EXPORT FrameConnectorDelegate {
bool has_size_ = false;
const bool use_zoom_for_device_scale_factor_;
+ uint32_t capture_sequence_number_ = 0u;
+
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewChildFrameZoomForDSFTest,
CompositorViewportPixelSize);
};
diff --git a/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc b/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc
index 8b1215bfdbe..b984d94d725 100644
--- a/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc
+++ b/chromium/content/browser/renderer_host/frame_sink_provider_impl.cc
@@ -27,7 +27,21 @@ void FrameSinkProviderImpl::Unbind() {
void FrameSinkProviderImpl::CreateForWidget(
int32_t widget_id,
viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request,
- viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client,
+ viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client) {
+ RenderWidgetHostImpl* render_widget_host_impl =
+ RenderWidgetHostImpl::FromID(process_id_, widget_id);
+ if (!render_widget_host_impl) {
+ DLOG(ERROR) << "No RenderWidgetHost exists with id " << widget_id
+ << " in process " << process_id_;
+ return;
+ }
+ render_widget_host_impl->RequestCompositorFrameSink(
+ std::move(compositor_frame_sink_request),
+ std::move(compositor_frame_sink_client));
+}
+
+void FrameSinkProviderImpl::RegisterRenderFrameMetadataObserver(
+ int32_t widget_id,
mojom::RenderFrameMetadataObserverClientRequest
render_frame_metadata_observer_client_request,
mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer) {
@@ -38,9 +52,7 @@ void FrameSinkProviderImpl::CreateForWidget(
<< " in process " << process_id_;
return;
}
- render_widget_host_impl->RequestCompositorFrameSink(
- std::move(compositor_frame_sink_request),
- std::move(compositor_frame_sink_client),
+ render_widget_host_impl->RegisterRenderFrameMetadataObserver(
std::move(render_frame_metadata_observer_client_request),
std::move(render_frame_metadata_observer));
}
diff --git a/chromium/content/browser/renderer_host/frame_sink_provider_impl.h b/chromium/content/browser/renderer_host/frame_sink_provider_impl.h
index e717c44fe48..05949c53398 100644
--- a/chromium/content/browser/renderer_host/frame_sink_provider_impl.h
+++ b/chromium/content/browser/renderer_host/frame_sink_provider_impl.h
@@ -25,7 +25,10 @@ class FrameSinkProviderImpl : public mojom::FrameSinkProvider {
void CreateForWidget(
int32_t widget_id,
viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request,
- viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client,
+ viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client)
+ override;
+ void RegisterRenderFrameMetadataObserver(
+ int32_t widget_id,
mojom::RenderFrameMetadataObserverClientRequest
render_frame_metadata_observer_client_request,
mojom::RenderFrameMetadataObserverPtr observer) override;
diff --git a/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc b/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
index 556aace335c..2d8b6535c6b 100644
--- a/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
@@ -32,14 +32,14 @@ const char kCompositedScrollingDataURL[] =
"<!DOCTYPE html>"
"<meta name='viewport' content='width=device-width'/>"
"<style>"
- "#scroller {"
+ "%23scroller {"
" width:500px;"
" height:500px;"
" overflow:scroll;"
" transform: rotateX(-30deg);"
"}"
- "#content {"
+ "%23content {"
" background-color:red;"
" width:1000px;"
" height:1000px;"
diff --git a/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc b/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
index d8f9d3d57b7..b20cceec519 100644
--- a/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
@@ -248,8 +248,7 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
// Send GSB to start scrolling sequence.
blink::WebGestureEvent gesture_scroll_begin(
blink::WebGestureEvent::kGestureScrollBegin,
- blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
gesture_scroll_begin.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
gesture_scroll_begin.data.scroll_begin.delta_hint_units =
blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
@@ -261,8 +260,7 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
// has started.
blink::WebGestureEvent gesture_fling_start(
blink::WebGestureEvent::kGestureFlingStart,
- blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
gesture_fling_start.data.fling_start.velocity_x = 0.f;
gesture_fling_start.data.fling_start.velocity_y = -2000.f;
@@ -283,8 +281,7 @@ IN_PROC_BROWSER_TEST_F(CompositorEventAckBrowserTest,
WebInputEvent::kTouchStart);
SyntheticWebTouchEvent touch_event;
touch_event.PressPoint(50, 50);
- touch_event.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ touch_event.SetTimeStamp(ui::EventTimeForNow());
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch_event,
ui::LatencyInfo());
touch_start_ack_observer.Wait();
diff --git a/chromium/content/browser/renderer_host/input/fling_browsertest.cc b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
index 00d86d6ccff..401de60bf93 100644
--- a/chromium/content/browser/renderer_host/input/fling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_browsertest.cc
@@ -68,8 +68,7 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
blink::WebMouseEvent down_event = SyntheticWebMouseEventBuilder::Build(
blink::WebInputEvent::kMouseDown, x, y, modifiers);
down_event.button = blink::WebMouseEvent::Button::kMiddle;
- down_event.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ down_event.SetTimeStamp(ui::EventTimeForNow());
down_event.SetPositionInScreen(x, y);
GetWidgetHost()->ForwardMouseEvent(down_event);
@@ -77,8 +76,7 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
blink::WebMouseEvent up_event = SyntheticWebMouseEventBuilder::Build(
blink::WebInputEvent::kMouseUp, x, y, modifiers);
up_event.button = blink::WebMouseEvent::Button::kMiddle;
- up_event.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ up_event.SetTimeStamp(ui::EventTimeForNow());
up_event.SetPositionInScreen(x, y);
GetWidgetHost()->ForwardMouseEvent(up_event);
}
@@ -87,6 +85,70 @@ class BrowserSideFlingBrowserTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(BrowserSideFlingBrowserTest);
};
+IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchscreenFling) {
+ LoadURL(kBrowserFlingDataURL);
+
+ // Send a GSB to start scrolling sequence.
+ blink::WebGestureEvent gesture_scroll_begin(
+ blink::WebGestureEvent::kGestureScrollBegin,
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
+ gesture_scroll_begin.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
+ gesture_scroll_begin.data.scroll_begin.delta_hint_units =
+ blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
+ gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0.f;
+ gesture_scroll_begin.data.scroll_begin.delta_y_hint = -5.f;
+ GetWidgetHost()->ForwardGestureEvent(gesture_scroll_begin);
+
+ // Send a GFS and wait for the page to scroll making sure that fling progress
+ // has started.
+ blink::WebGestureEvent gesture_fling_start(
+ blink::WebGestureEvent::kGestureFlingStart,
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
+ gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
+ gesture_fling_start.data.fling_start.velocity_x = 0.f;
+ gesture_fling_start.data.fling_start.velocity_y = -2000.f;
+ GetWidgetHost()->ForwardGestureEvent(gesture_fling_start);
+ RenderFrameSubmissionObserver observer(
+ GetWidgetHost()->render_frame_metadata_provider());
+ gfx::Vector2dF default_scroll_offset;
+ while (observer.LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset)
+ .y() <= 0) {
+ observer.WaitForMetadataChange();
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, TouchpadFling) {
+ LoadURL(kBrowserFlingDataURL);
+
+ // Send a wheel event to start scrolling sequence.
+ auto input_msg_watcher = std::make_unique<InputMsgWatcher>(
+ GetWidgetHost(), blink::WebInputEvent::kMouseWheel);
+ blink::WebMouseWheelEvent wheel_event =
+ SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true);
+ wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ GetWidgetHost()->ForwardWheelEvent(wheel_event);
+ input_msg_watcher->WaitForAck();
+
+ // Send a GFS and wait for the page to scroll more than 60 pixels making sure
+ // that fling progress has started.
+ blink::WebGestureEvent gesture_fling_start(
+ blink::WebGestureEvent::kGestureFlingStart,
+ blink::WebInputEvent::kNoModifiers, ui::EventTimeForNow());
+ gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchpad);
+ gesture_fling_start.data.fling_start.velocity_x = 0.f;
+ gesture_fling_start.data.fling_start.velocity_y = -2000.f;
+ GetWidgetHost()->ForwardGestureEvent(gesture_fling_start);
+ RenderFrameSubmissionObserver observer(
+ GetWidgetHost()->render_frame_metadata_provider());
+ gfx::Vector2dF default_scroll_offset;
+ while (observer.LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset)
+ .y() <= 60) {
+ observer.WaitForMetadataChange();
+ }
+}
+
// TODO(sahel): This test is flaking on OS_CHROMEOS https://crbug.com/838769
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
#define MAYBE_AutoscrollFling DISABLED_AutoscrollFling
@@ -108,8 +170,7 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest, MAYBE_AutoscrollFling) {
blink::WebMouseEvent move_event = SyntheticWebMouseEventBuilder::Build(
blink::WebInputEvent::kMouseMove, 30, 30,
blink::WebInputEvent::kNoModifiers);
- move_event.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ move_event.SetTimeStamp(ui::EventTimeForNow());
move_event.SetPositionInScreen(30, 30);
GetWidgetHost()->ForwardMouseEvent(move_event);
gfx::Vector2dF default_scroll_offset;
@@ -159,4 +220,4 @@ IN_PROC_BROWSER_TEST_F(BrowserSideFlingBrowserTest,
}
}
-} // namespace content \ No newline at end of file
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.cc b/chromium/content/browser/renderer_host/input/fling_controller.cc
index e09036a18b7..ce13d23f10a 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/input/fling_controller.h"
+#include "base/trace_event/trace_event.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/public/common/content_features.h"
#include "ui/events/base_event_utils.h"
@@ -20,6 +21,8 @@ namespace {
// progress.
constexpr base::TimeDelta kMaxMicrosecondsFromFlingTimestampToFirstProgress =
base::TimeDelta::FromMicroseconds(33333);
+
+const char* kFlingTraceName = "FlingController::HandlingGestureFling";
} // namespace
namespace content {
@@ -28,28 +31,28 @@ FlingController::Config::Config() {}
FlingController::FlingController(
GestureEventQueue* gesture_event_queue,
- TouchpadTapSuppressionControllerClient* touchpad_client,
- FlingControllerClient* fling_client,
+ FlingControllerEventSenderClient* event_sender_client,
+ FlingControllerSchedulerClient* scheduler_client,
const Config& config)
: gesture_event_queue_(gesture_event_queue),
- client_(fling_client),
+ event_sender_client_(event_sender_client),
+ scheduler_client_(scheduler_client),
touchpad_tap_suppression_controller_(
- touchpad_client,
config.touchpad_tap_suppression_config),
touchscreen_tap_suppression_controller_(
- gesture_event_queue,
config.touchscreen_tap_suppression_config),
fling_in_progress_(false),
send_wheel_events_nonblocking_(
base::FeatureList::IsEnabled(
features::kTouchpadAndWheelScrollLatching) &&
- base::FeatureList::IsEnabled(features::kAsyncWheelEvents)) {
+ base::FeatureList::IsEnabled(features::kAsyncWheelEvents)),
+ weak_ptr_factory_(this) {
DCHECK(gesture_event_queue);
- DCHECK(touchpad_client);
- DCHECK(fling_client);
+ DCHECK(event_sender_client);
+ DCHECK(scheduler_client);
}
-FlingController::~FlingController() {}
+FlingController::~FlingController() = default;
bool FlingController::ShouldForwardForGFCFiltering(
const GestureEventWithLatencyInfo& gesture_event) const {
@@ -59,8 +62,7 @@ bool FlingController::ShouldForwardForGFCFiltering(
if (fling_in_progress_)
return !fling_booster_->fling_cancellation_is_deferred();
- // Auto-scroll flings are still handled by renderer.
- return !gesture_event_queue_->ShouldDiscardFlingCancelEvent(gesture_event);
+ return false;
}
bool FlingController::ShouldForwardForTapSuppression(
@@ -69,10 +71,11 @@ bool FlingController::ShouldForwardForTapSuppression(
case WebInputEvent::kGestureFlingCancel:
if (gesture_event.event.SourceDevice() ==
blink::kWebGestureDeviceTouchscreen) {
- touchscreen_tap_suppression_controller_.GestureFlingCancel();
+ touchscreen_tap_suppression_controller_
+ .GestureFlingCancelStoppedFling();
} else if (gesture_event.event.SourceDevice() ==
blink::kWebGestureDeviceTouchpad) {
- touchpad_tap_suppression_controller_.GestureFlingCancel();
+ touchpad_tap_suppression_controller_.GestureFlingCancelStoppedFling();
}
return true;
case WebInputEvent::kGestureTapDown:
@@ -114,10 +117,30 @@ bool FlingController::FilterGestureEventForFlingBoosting(
CancelCurrentFling();
}
- if (should_filter_event &&
- gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart) {
- UpdateCurrentFlingState(gesture_event.event,
- fling_booster_->current_fling_velocity());
+ if (should_filter_event) {
+ if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart) {
+ UpdateCurrentFlingState(gesture_event.event,
+ fling_booster_->current_fling_velocity());
+ TRACE_EVENT_INSTANT2("input",
+ fling_booster_->fling_boosted()
+ ? "FlingController::FlingBoosted"
+ : "FlingController::FlingReplaced",
+ TRACE_EVENT_SCOPE_THREAD, "vx",
+ fling_booster_->current_fling_velocity().x(), "vy",
+ fling_booster_->current_fling_velocity().y());
+ } else if (gesture_event.event.GetType() ==
+ WebInputEvent::kGestureFlingCancel) {
+ DCHECK(fling_booster_->fling_cancellation_is_deferred());
+ TRACE_EVENT_INSTANT0("input", "FlingController::FlingBoostStart",
+ TRACE_EVENT_SCOPE_THREAD);
+ } else if (gesture_event.event.GetType() ==
+ WebInputEvent::kGestureScrollBegin ||
+ gesture_event.event.GetType() ==
+ WebInputEvent::kGestureScrollUpdate) {
+ TRACE_EVENT_INSTANT0("input",
+ "FlingController::ExtendBoostedFlingTimeout",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
}
return should_filter_event;
@@ -156,6 +179,8 @@ void FlingController::ProcessGestureFlingStart(
if (!UpdateCurrentFlingState(gesture_event.event, gfx::Vector2dF(vx, vy)))
return;
+ TRACE_EVENT_ASYNC_BEGIN2("input", kFlingTraceName, this, "vx", vx, "vy", vy);
+
has_fling_animation_started_ = false;
fling_in_progress_ = true;
fling_booster_ = std::make_unique<ui::FlingBooster>(
@@ -166,36 +191,28 @@ void FlingController::ProcessGestureFlingStart(
}
void FlingController::ScheduleFlingProgress() {
- client_->SetNeedsBeginFrameForFlingProgress();
+ scheduler_client_->ScheduleFlingProgress(weak_ptr_factory_.GetWeakPtr());
}
void FlingController::ProcessGestureFlingCancel(
const GestureEventWithLatencyInfo& gesture_event) {
fling_in_progress_ = false;
- bool processed = false;
- if (fling_curve_) {
+
+ if (fling_curve_)
CancelCurrentFling();
- processed = true;
- }
- // FlingCancelEvent handled without being sent to the renderer.
- blink::WebGestureDevice source_device = gesture_event.event.SourceDevice();
- if (source_device == blink::kWebGestureDeviceTouchscreen) {
- touchscreen_tap_suppression_controller_.GestureFlingCancelAck(processed);
- } else if (source_device == blink::kWebGestureDeviceTouchpad) {
- touchpad_tap_suppression_controller_.GestureFlingCancelAck(processed);
- }
}
-gfx::Vector2dF FlingController::ProgressFling(base::TimeTicks current_time) {
+void FlingController::ProgressFling(base::TimeTicks current_time) {
if (!fling_curve_)
- return gfx::Vector2dF();
+ return;
+ TRACE_EVENT_ASYNC_STEP_INTO0("input", kFlingTraceName, this, "ProgressFling");
DCHECK(fling_booster_);
fling_booster_->set_last_fling_animation_time(
(current_time - base::TimeTicks()).InSecondsF());
if (fling_booster_->MustCancelDeferredFling()) {
CancelCurrentFling();
- return gfx::Vector2dF();
+ return;
}
if (!has_fling_animation_started_) {
@@ -207,7 +224,7 @@ gfx::Vector2dF FlingController::ProgressFling(base::TimeTicks current_time) {
kMaxMicrosecondsFromFlingTimestampToFirstProgress) {
current_fling_parameters_.start_time = current_time;
ScheduleFlingProgress();
- return current_fling_parameters_.velocity;
+ return;
}
}
@@ -223,14 +240,13 @@ gfx::Vector2dF FlingController::ProgressFling(base::TimeTicks current_time) {
// As long as the fling curve is active, the fling progress must get
// scheduled even when the last delta to scroll was zero.
ScheduleFlingProgress();
- return current_fling_parameters_.velocity;
+ return;
}
if (current_fling_parameters_.source_device !=
blink::kWebGestureDeviceSyntheticAutoscroll) {
CancelCurrentFling();
}
- return gfx::Vector2dF();
}
void FlingController::StopFling() {
@@ -245,8 +261,7 @@ void FlingController::GenerateAndSendWheelEvents(
blink::WebMouseWheelEvent::Phase phase) {
MouseWheelEventWithLatencyInfo synthetic_wheel(
WebInputEvent::kMouseWheel, current_fling_parameters_.modifiers,
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()),
- ui::LatencyInfo(ui::SourceEventType::WHEEL));
+ base::TimeTicks::Now(), ui::LatencyInfo(ui::SourceEventType::WHEEL));
synthetic_wheel.event.delta_x = delta.x();
synthetic_wheel.event.delta_y = delta.y();
synthetic_wheel.event.has_precise_scrolling_deltas = true;
@@ -265,16 +280,15 @@ void FlingController::GenerateAndSendWheelEvents(
: WebInputEvent::kBlocking;
}
- client_->SendGeneratedWheelEvent(synthetic_wheel);
+ event_sender_client_->SendGeneratedWheelEvent(synthetic_wheel);
}
void FlingController::GenerateAndSendGestureScrollEvents(
WebInputEvent::Type type,
const gfx::Vector2dF& delta /* = gfx::Vector2dF() */) {
GestureEventWithLatencyInfo synthetic_gesture(
- type, current_fling_parameters_.modifiers,
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()),
- ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ type, current_fling_parameters_.modifiers, base::TimeTicks::Now(),
+ ui::LatencyInfo(ui::SourceEventType::INERTIAL));
synthetic_gesture.event.SetPositionInWidget(current_fling_parameters_.point);
synthetic_gesture.event.SetPositionInScreen(
current_fling_parameters_.global_point);
@@ -292,7 +306,7 @@ void FlingController::GenerateAndSendGestureScrollEvents(
synthetic_gesture.event.data.scroll_end.inertial_phase =
WebGestureEvent::kMomentumPhase;
}
- client_->SendGeneratedGestureScrollEvents(synthetic_gesture);
+ event_sender_client_->SendGeneratedGestureScrollEvents(synthetic_gesture);
}
void FlingController::GenerateAndSendFlingProgressEvents(
@@ -363,8 +377,6 @@ void FlingController::CancelCurrentFling() {
WebInputEvent::kGestureScrollUpdate)) {
WebGestureEvent scroll_begin_event = last_fling_boost_event;
scroll_begin_event.SetType(WebInputEvent::kGestureScrollBegin);
- scroll_begin_event.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()));
bool is_update =
last_fling_boost_event.GetType() == WebInputEvent::kGestureScrollUpdate;
float delta_x_hint =
@@ -379,18 +391,21 @@ void FlingController::CancelCurrentFling() {
ui::SourceEventType::UNKNOWN;
if (scroll_begin_event.SourceDevice() ==
blink::kWebGestureDeviceTouchscreen) {
- latency_source_event_type = ui::SourceEventType::TOUCH;
+ latency_source_event_type = ui::SourceEventType::INERTIAL;
} else if (scroll_begin_event.SourceDevice() ==
blink::kWebGestureDeviceTouchpad) {
latency_source_event_type = ui::SourceEventType::WHEEL;
}
- client_->SendGeneratedGestureScrollEvents(GestureEventWithLatencyInfo(
- scroll_begin_event, ui::LatencyInfo(latency_source_event_type)));
+ event_sender_client_->SendGeneratedGestureScrollEvents(
+ GestureEventWithLatencyInfo(
+ scroll_begin_event, ui::LatencyInfo(latency_source_event_type)));
}
- if (had_active_fling)
- client_->DidStopFlingingOnBrowser();
+ if (had_active_fling) {
+ scheduler_client_->DidStopFlingingOnBrowser(weak_ptr_factory_.GetWeakPtr());
+ TRACE_EVENT_ASYNC_END0("input", kFlingTraceName, this);
+ }
}
bool FlingController::UpdateCurrentFlingState(
@@ -403,9 +418,7 @@ bool FlingController::UpdateCurrentFlingState(
current_fling_parameters_.global_point = fling_start_event.PositionInScreen();
current_fling_parameters_.modifiers = fling_start_event.GetModifiers();
current_fling_parameters_.source_device = fling_start_event.SourceDevice();
- current_fling_parameters_.start_time =
- base::TimeTicks() +
- base::TimeDelta::FromSecondsD(fling_start_event.TimeStampSeconds());
+ current_fling_parameters_.start_time = fling_start_event.TimeStamp();
if (velocity.IsZero() && fling_start_event.SourceDevice() !=
blink::kWebGestureDeviceSyntheticAutoscroll) {
@@ -430,6 +443,10 @@ bool FlingController::TouchscreenFlingInProgress() const {
blink::kWebGestureDeviceTouchscreen;
}
+gfx::Vector2dF FlingController::CurrentFlingVelocity() const {
+ return current_fling_parameters_.velocity;
+}
+
TouchpadTapSuppressionController*
FlingController::GetTouchpadTapSuppressionController() {
return &touchpad_tap_suppression_controller_;
diff --git a/chromium/content/browser/renderer_host/input/fling_controller.h b/chromium/content/browser/renderer_host/input/fling_controller.h
index c762b57c02c..929d35ec1c8 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller.h
+++ b/chromium/content/browser/renderer_host/input/fling_controller.h
@@ -21,21 +21,31 @@ namespace content {
class GestureEventQueue;
+class FlingController;
+
// Interface with which the FlingController can forward generated fling progress
// events.
-class CONTENT_EXPORT FlingControllerClient {
+class CONTENT_EXPORT FlingControllerEventSenderClient {
public:
- virtual ~FlingControllerClient() {}
+ virtual ~FlingControllerEventSenderClient() {}
virtual void SendGeneratedWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) = 0;
virtual void SendGeneratedGestureScrollEvents(
const GestureEventWithLatencyInfo& gesture_event) = 0;
+};
+
+// Interface with which the fling progress gets scheduled.
+class CONTENT_EXPORT FlingControllerSchedulerClient {
+ public:
+ virtual ~FlingControllerSchedulerClient() {}
- virtual void SetNeedsBeginFrameForFlingProgress() = 0;
+ virtual void ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) = 0;
- virtual void DidStopFlingingOnBrowser() = 0;
+ virtual void DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) = 0;
};
class CONTENT_EXPORT FlingController {
@@ -62,15 +72,14 @@ class CONTENT_EXPORT FlingController {
};
FlingController(GestureEventQueue* gesture_event_queue,
- TouchpadTapSuppressionControllerClient* touchpad_client,
- FlingControllerClient* fling_client,
+ FlingControllerEventSenderClient* event_sender_client,
+ FlingControllerSchedulerClient* scheduler_client,
const Config& config);
~FlingController();
- // Used to progress an active fling on every begin frame and return the
- // current fling velocity.
- gfx::Vector2dF ProgressFling(base::TimeTicks current_time);
+ // Used to progress an active fling on every begin frame.
+ void ProgressFling(base::TimeTicks current_time);
// Used to halt an active fling progress whenever needed.
void StopFling();
@@ -92,6 +101,8 @@ class CONTENT_EXPORT FlingController {
bool TouchscreenFlingInProgress() const;
+ gfx::Vector2dF CurrentFlingVelocity() const;
+
// Returns the |TouchpadTapSuppressionController| instance.
TouchpadTapSuppressionController* GetTouchpadTapSuppressionController();
@@ -141,7 +152,9 @@ class CONTENT_EXPORT FlingController {
GestureEventQueue* gesture_event_queue_;
- FlingControllerClient* client_;
+ FlingControllerEventSenderClient* event_sender_client_;
+
+ FlingControllerSchedulerClient* scheduler_client_;
// An object tracking the state of touchpad on the delivery of mouse events to
// the renderer to filter mouse immediately after a touchpad fling canceling
@@ -167,6 +180,8 @@ class CONTENT_EXPORT FlingController {
bool send_wheel_events_nonblocking_;
+ base::WeakPtrFactory<FlingController> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(FlingController);
};
diff --git a/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc b/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
index d95159d2c7b..31a8d531226 100644
--- a/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -22,21 +22,22 @@ namespace content {
class FakeFlingController : public FlingController {
public:
FakeFlingController(GestureEventQueue* gesture_event_queue,
- TouchpadTapSuppressionControllerClient* touchpad_client,
- FlingControllerClient* fling_client,
+
+ FlingControllerEventSenderClient* event_sender_client,
+ FlingControllerSchedulerClient* scheduler_client,
const Config& config)
: FlingController(gesture_event_queue,
- touchpad_client,
- fling_client,
+ event_sender_client,
+ scheduler_client,
config) {}
bool FlingBoosted() const { return fling_booster_->fling_boosted(); }
};
class FlingControllerTest : public testing::Test,
- public TouchpadTapSuppressionControllerClient,
public GestureEventQueueClient,
- public FlingControllerClient {
+ public FlingControllerEventSenderClient,
+ public FlingControllerSchedulerClient {
public:
// testing::Test
FlingControllerTest()
@@ -54,10 +55,6 @@ class FlingControllerTest : public testing::Test,
features::kTouchpadAndWheelScrollLatching.name, "");
}
- // TouchpadTapSuppressionControllerClient
- void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& event) override {}
-
// GestureEventQueueClient
void SendGestureEventImmediately(
const GestureEventWithLatencyInfo& event) override {}
@@ -65,7 +62,7 @@ class FlingControllerTest : public testing::Test,
InputEventAckSource ack_source,
InputEventAckState ack_result) override {}
- // FlingControllerClient
+ // FlingControllerEventSenderClient
void SendGeneratedWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) override {
last_sent_wheel_ = wheel_event.event;
@@ -74,20 +71,23 @@ class FlingControllerTest : public testing::Test,
const GestureEventWithLatencyInfo& gesture_event) override {
last_sent_gesture_ = gesture_event.event;
}
- void SetNeedsBeginFrameForFlingProgress() override {
+
+ // FlingControllerSchedulerClient
+ void ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) override {
DCHECK(!scheduled_next_fling_progress_);
scheduled_next_fling_progress_ = true;
}
- void DidStopFlingingOnBrowser() override {
+ void DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) override {
notified_client_after_fling_stop_ = true;
}
void SimulateFlingStart(blink::WebGestureDevice source_device,
const gfx::Vector2dF& velocity) {
scheduled_next_fling_progress_ = false;
- WebGestureEvent fling_start(
- WebInputEvent::kGestureFlingStart, 0,
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()), source_device);
+ WebGestureEvent fling_start(WebInputEvent::kGestureFlingStart, 0,
+ base::TimeTicks::Now(), source_device);
fling_start.data.fling_start.velocity_x = velocity.x();
fling_start.data.fling_start.velocity_y = velocity.y();
GestureEventWithLatencyInfo fling_start_with_latency(fling_start);
@@ -97,9 +97,8 @@ class FlingControllerTest : public testing::Test,
void SimulateFlingCancel(blink::WebGestureDevice source_device) {
notified_client_after_fling_stop_ = false;
- WebGestureEvent fling_cancel(
- WebInputEvent::kGestureFlingCancel, 0,
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()), source_device);
+ WebGestureEvent fling_cancel(WebInputEvent::kGestureFlingCancel, 0,
+ base::TimeTicks::Now(), source_device);
// autoscroll fling cancel doesn't allow fling boosting.
if (source_device == blink::kWebGestureDeviceSyntheticAutoscroll)
fling_cancel.data.fling_cancel.prevent_boosting = true;
@@ -257,9 +256,8 @@ TEST_F(FlingControllerTest,
EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
// A non-consumed GSU ack in inertial state cancels out the rest of the fling.
- WebGestureEvent scroll_update(
- WebInputEvent::kGestureScrollUpdate, 0,
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()));
+ WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
+ base::TimeTicks::Now());
scroll_update.data.scroll_update.inertial_phase =
WebGestureEvent::kMomentumPhase;
@@ -286,9 +284,8 @@ TEST_F(FlingControllerTest,
EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
// A non-consumed GSU ack in inertial state cancels out the rest of the fling.
- WebGestureEvent scroll_update(
- WebInputEvent::kGestureScrollUpdate, 0,
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()));
+ WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
+ base::TimeTicks::Now());
scroll_update.data.scroll_update.inertial_phase =
WebGestureEvent::kMomentumPhase;
@@ -352,7 +349,8 @@ TEST_F(FlingControllerTest, GestureFlingCancelsFiltered) {
EXPECT_TRUE(last_fling_cancel_filtered_);
}
-TEST_F(FlingControllerTest, GestureFlingNotCancelledBySmallTimeDelta) {
+// Flaky. https://crbug.com/836996.
+TEST_F(FlingControllerTest, DISABLED_GestureFlingNotCancelledBySmallTimeDelta) {
base::TimeTicks progress_time = base::TimeTicks::Now();
SimulateFlingStart(blink::kWebGestureDeviceTouchscreen,
gfx::Vector2dF(1000, 0));
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler.cc b/chromium/content/browser/renderer_host/input/fling_scheduler.cc
new file mode 100644
index 00000000000..0b6ab39313d
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler.cc
@@ -0,0 +1,91 @@
+// 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/renderer_host/input/fling_scheduler.h"
+
+#include "build/build_config.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "ui/compositor/compositor.h"
+
+#if defined(USE_AURA)
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#endif
+
+namespace content {
+
+FlingScheduler::FlingScheduler(RenderWidgetHostImpl* host) : host_(host) {
+ DCHECK(host);
+}
+
+FlingScheduler::~FlingScheduler() {
+ if (observed_compositor_)
+ observed_compositor_->RemoveAnimationObserver(this);
+}
+
+void FlingScheduler::ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) {
+ DCHECK(fling_controller);
+ fling_controller_ = fling_controller;
+ // Don't do anything if a ui::Compositor is already being observed.
+ if (observed_compositor_)
+ return;
+ ui::Compositor* compositor = GetCompositor();
+ // If a ui::Compositor can't be obtained, ask the host for BeginFrames.
+ if (!compositor) {
+ host_->SetNeedsBeginFrameForFlingProgress();
+ return;
+ }
+ compositor->AddAnimationObserver(this);
+ observed_compositor_ = compositor;
+}
+
+void FlingScheduler::DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) {
+ DCHECK(fling_controller);
+ if (observed_compositor_) {
+ observed_compositor_->RemoveAnimationObserver(this);
+ observed_compositor_ = nullptr;
+ }
+ fling_controller_ = nullptr;
+ host_->DidStopFlinging();
+}
+
+void FlingScheduler::ProgressFlingOnBeginFrameIfneeded(
+ base::TimeTicks current_time) {
+ // No fling is active.
+ if (!fling_controller_)
+ return;
+
+ // FlingProgress will be called within FlingController::OnAnimationStep.
+ if (observed_compositor_)
+ return;
+
+ fling_controller_->ProgressFling(current_time);
+}
+
+ui::Compositor* FlingScheduler::GetCompositor() {
+#if defined(USE_AURA)
+ if (host_->GetView() && host_->GetView()->GetNativeView() &&
+ host_->GetView()->GetNativeView()->GetHost() &&
+ host_->GetView()->GetNativeView()->GetHost()->compositor()) {
+ return host_->GetView()->GetNativeView()->GetHost()->compositor();
+ }
+#endif
+
+ return nullptr;
+}
+
+void FlingScheduler::OnAnimationStep(base::TimeTicks timestamp) {
+ if (fling_controller_)
+ fling_controller_->ProgressFling(timestamp);
+}
+
+void FlingScheduler::OnCompositingShuttingDown(ui::Compositor* compositor) {
+ DCHECK_EQ(observed_compositor_, compositor);
+ observed_compositor_->RemoveAnimationObserver(this);
+ observed_compositor_ = nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler.h b/chromium/content/browser/renderer_host/input/fling_scheduler.h
new file mode 100644
index 00000000000..c29c0fc43f5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler.h
@@ -0,0 +1,49 @@
+// 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_RENDERER_HOST_INPUT_FLING_SCHEDULER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_H_
+
+#include "content/browser/renderer_host/input/fling_controller.h"
+#include "ui/compositor/compositor_animation_observer.h"
+
+namespace ui {
+class Compositor;
+}
+
+namespace content {
+
+class RenderWidgetHostImpl;
+
+class CONTENT_EXPORT FlingScheduler : public FlingControllerSchedulerClient,
+ private ui::CompositorAnimationObserver {
+ public:
+ FlingScheduler(RenderWidgetHostImpl* host);
+ ~FlingScheduler() override;
+
+ // FlingControllerSchedulerClient
+ void ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) override;
+ void DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) override;
+
+ void ProgressFlingOnBeginFrameIfneeded(base::TimeTicks current_time);
+
+ protected:
+ virtual ui::Compositor* GetCompositor();
+ RenderWidgetHostImpl* host_;
+ base::WeakPtr<FlingController> fling_controller_;
+ ui::Compositor* observed_compositor_ = nullptr;
+
+ private:
+ // ui::CompositorAnimationObserver
+ void OnAnimationStep(base::TimeTicks timestamp) override;
+ void OnCompositingShuttingDown(ui::Compositor* compositor) override;
+
+ DISALLOW_COPY_AND_ASSIGN(FlingScheduler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_H_
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_mac.h b/chromium/content/browser/renderer_host/input/fling_scheduler_mac.h
new file mode 100644
index 00000000000..21c180c0ea0
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_mac.h
@@ -0,0 +1,27 @@
+// 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_RENDERER_HOST_INPUT_FLING_SCHEDULER_MAC_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_MAC_H_
+
+#include "content/browser/renderer_host/input/fling_scheduler.h"
+
+namespace content {
+
+class RenderWidgetHostImpl;
+
+class CONTENT_EXPORT FlingSchedulerMac : public FlingScheduler {
+ public:
+ FlingSchedulerMac(RenderWidgetHostImpl* host);
+ ~FlingSchedulerMac() override;
+
+ private:
+ ui::Compositor* GetCompositor() override;
+
+ DISALLOW_COPY_AND_ASSIGN(FlingSchedulerMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_SCHEDULER_MAC_H_
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm b/chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm
new file mode 100644
index 00000000000..f2ac740bea5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_mac.mm
@@ -0,0 +1,36 @@
+// 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/renderer_host/input/fling_scheduler_mac.h"
+
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#include "ui/compositor/compositor.h"
+
+namespace content {
+
+FlingSchedulerMac::FlingSchedulerMac(RenderWidgetHostImpl* host)
+ : FlingScheduler(host) {}
+FlingSchedulerMac::~FlingSchedulerMac() = default;
+
+ui::Compositor* FlingSchedulerMac::GetCompositor() {
+ if (!host_->GetView())
+ return nullptr;
+
+ // RWHV_child_frame doesn't have DelegatedFrameHost with ui::Compositor.
+ if (host_->GetView()->IsRenderWidgetHostViewChildFrame())
+ return nullptr;
+
+ // TODO(sahel): Uncomment this once Viz is ready on Mac.
+ // https://crbug.com/833985
+ /* RenderWidgetHostViewMac* view =
+ static_cast<RenderWidgetHostViewMac*>(host_->GetView());
+ if (view->BrowserCompositor())
+ return view->BrowserCompositor()->Compositor();
+ } */
+
+ return nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/fling_scheduler_unittest.cc b/chromium/content/browser/renderer_host/input/fling_scheduler_unittest.cc
new file mode 100644
index 00000000000..e031a097a54
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/fling_scheduler_unittest.cc
@@ -0,0 +1,162 @@
+// 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/renderer_host/input/fling_scheduler.h"
+
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/mock_render_widget_host_delegate.h"
+#include "content/test/test_render_view_host.h"
+#include "content/test/test_render_widget_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class FakeFlingScheduler : public FlingScheduler {
+ public:
+ FakeFlingScheduler(RenderWidgetHostImpl* host) : FlingScheduler(host) {}
+
+ void ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) override {
+ FlingScheduler::ScheduleFlingProgress(fling_controller);
+ fling_in_progress_ = true;
+ }
+
+ void DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) override {
+ FlingScheduler::DidStopFlingingOnBrowser(fling_controller);
+ fling_in_progress_ = false;
+ }
+
+ bool fling_in_progress() const { return fling_in_progress_; }
+
+ ui::Compositor* compositor() { return GetCompositor(); }
+ ui::Compositor* observed_compositor() { return observed_compositor_; }
+
+ base::WeakPtr<FlingController> fling_controller() const {
+ return fling_controller_;
+ }
+
+ private:
+ bool fling_in_progress_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeFlingScheduler);
+};
+
+class FlingSchedulerTest : public testing::Test,
+ public GestureEventQueueClient,
+ public FlingControllerEventSenderClient {
+ public:
+ FlingSchedulerTest() {}
+ void SetUp() override {
+ view_ = CreateView();
+ widget_host_->SetView(view_);
+
+ fling_scheduler_ = std::make_unique<FakeFlingScheduler>(widget_host_);
+ queue_ = std::make_unique<GestureEventQueue>(
+ this, this, fling_scheduler_.get(), GestureEventQueue::Config());
+ fling_controller_ = std::make_unique<FlingController>(
+ queue_.get(), this, fling_scheduler_.get(), FlingController::Config());
+ }
+
+ void TearDown() override {
+ view_->Destroy();
+ widget_host_->ShutdownAndDestroyWidget(true);
+ browser_context_.reset();
+
+ base::RunLoop().RunUntilIdle();
+ }
+
+ TestRenderWidgetHostView* CreateView() {
+ browser_context_ = std::make_unique<TestBrowserContext>();
+ process_host_ = new MockRenderProcessHost(browser_context_.get());
+ process_host_->Init();
+ int32_t routing_id = process_host_->GetNextRoutingID();
+ delegate_ = std::make_unique<MockRenderWidgetHostDelegate>();
+ widget_host_ = TestRenderWidgetHost::Create(delegate_.get(), process_host_,
+ routing_id, false)
+ .release();
+ delegate_->set_widget_host(widget_host_);
+ return new TestRenderWidgetHostView(widget_host_);
+ }
+
+ void SimulateFlingStart(const gfx::Vector2dF& velocity) {
+ blink::WebGestureEvent fling_start(blink::WebInputEvent::kGestureFlingStart,
+ 0, base::TimeTicks::Now(),
+ blink::kWebGestureDeviceTouchscreen);
+ fling_start.data.fling_start.velocity_x = velocity.x();
+ fling_start.data.fling_start.velocity_y = velocity.y();
+ GestureEventWithLatencyInfo fling_start_with_latency(fling_start);
+ if (!fling_controller_->FilterGestureEvent(fling_start_with_latency))
+ fling_controller_->ProcessGestureFlingStart(fling_start_with_latency);
+ }
+
+ void SimulateFlingCancel() {
+ blink::WebGestureEvent fling_cancel(
+ blink::WebInputEvent::kGestureFlingCancel, 0, base::TimeTicks::Now(),
+ blink::kWebGestureDeviceTouchscreen);
+ fling_cancel.data.fling_cancel.prevent_boosting = true;
+ GestureEventWithLatencyInfo fling_cancel_with_latency(fling_cancel);
+ if (!fling_controller_->FilterGestureEvent(fling_cancel_with_latency))
+ fling_controller_->ProcessGestureFlingCancel(fling_cancel_with_latency);
+ }
+
+ // GestureEventQueueClient
+ void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& event) override {}
+ void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckSource ack_source,
+ InputEventAckState ack_result) override {}
+
+ // FlingControllerEventSenderClient
+ void SendGeneratedWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) override {}
+ void SendGeneratedGestureScrollEvents(
+ const GestureEventWithLatencyInfo& gesture_event) override {}
+
+ std::unique_ptr<FlingController> fling_controller_;
+ std::unique_ptr<FakeFlingScheduler> fling_scheduler_;
+
+ private:
+ TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<GestureEventQueue> queue_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+ RenderWidgetHostImpl* widget_host_;
+ MockRenderProcessHost* process_host_;
+ TestRenderWidgetHostView* view_;
+ std::unique_ptr<MockRenderWidgetHostDelegate> delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlingSchedulerTest);
+};
+
+TEST_F(FlingSchedulerTest, ScheduleNextFlingProgress) {
+ base::TimeTicks progress_time = base::TimeTicks::Now();
+ SimulateFlingStart(gfx::Vector2dF(1000, 0));
+ EXPECT_TRUE(fling_scheduler_->fling_in_progress());
+ EXPECT_EQ(fling_controller_.get(),
+ fling_scheduler_->fling_controller().get());
+ EXPECT_EQ(fling_scheduler_->compositor(),
+ fling_scheduler_->observed_compositor());
+
+ progress_time += base::TimeDelta::FromMilliseconds(17);
+ fling_controller_->ProgressFling(progress_time);
+ EXPECT_TRUE(fling_scheduler_->fling_in_progress());
+}
+
+TEST_F(FlingSchedulerTest, FlingCancelled) {
+ SimulateFlingStart(gfx::Vector2dF(1000, 0));
+ EXPECT_TRUE(fling_scheduler_->fling_in_progress());
+ EXPECT_EQ(fling_controller_.get(),
+ fling_scheduler_->fling_controller().get());
+ EXPECT_EQ(fling_scheduler_->compositor(),
+ fling_scheduler_->observed_compositor());
+
+ SimulateFlingCancel();
+ EXPECT_FALSE(fling_scheduler_->fling_in_progress());
+ EXPECT_EQ(nullptr, fling_scheduler_->fling_controller());
+ EXPECT_EQ(nullptr, fling_scheduler_->observed_compositor());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
index 673be7eae63..10cdaaf1a25 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -26,8 +26,8 @@ GestureEventQueue::Config::Config() {
GestureEventQueue::GestureEventQueue(
GestureEventQueueClient* client,
- TouchpadTapSuppressionControllerClient* touchpad_client,
- FlingControllerClient* fling_client,
+ FlingControllerEventSenderClient* fling_event_sender_client,
+ FlingControllerSchedulerClient* fling_scheduler_client,
const Config& config)
: client_(client),
fling_in_progress_(false),
@@ -37,12 +37,12 @@ GestureEventQueue::GestureEventQueue(
base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)),
debounce_interval_(config.debounce_interval),
fling_controller_(this,
- touchpad_client,
- fling_client,
+ fling_event_sender_client,
+ fling_scheduler_client,
config.fling_config) {
DCHECK(client);
- DCHECK(touchpad_client);
- DCHECK(fling_client);
+ DCHECK(fling_event_sender_client);
+ DCHECK(fling_scheduler_client);
}
GestureEventQueue::~GestureEventQueue() { }
@@ -77,10 +77,6 @@ bool GestureEventQueue::QueueEvent(
return true;
}
-gfx::Vector2dF GestureEventQueue::ProgressFling(base::TimeTicks current_time) {
- return fling_controller_.ProgressFling(current_time);
-}
-
void GestureEventQueue::StopFling() {
fling_in_progress_ = false;
fling_controller_.StopFling();
@@ -93,6 +89,9 @@ bool GestureEventQueue::FlingCancellationIsDeferred() const {
bool GestureEventQueue::TouchscreenFlingInProgress() const {
return fling_controller_.TouchscreenFlingInProgress();
}
+gfx::Vector2dF GestureEventQueue::CurrentFlingVelocity() const {
+ return fling_controller_.CurrentFlingVelocity();
+}
bool GestureEventQueue::ShouldDiscardFlingCancelEvent(
const GestureEventWithLatencyInfo& gesture_event) const {
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.h b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
index fbba8a4597e..db490fde11b 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
@@ -72,8 +72,8 @@ class CONTENT_EXPORT GestureEventQueue {
// Both |client| and |touchpad_client| must outlive the GestureEventQueue.
GestureEventQueue(GestureEventQueueClient* client,
- TouchpadTapSuppressionControllerClient* touchpad_client,
- FlingControllerClient* fling_client,
+ FlingControllerEventSenderClient* fling_event_sender_client,
+ FlingControllerSchedulerClient* fling_scheduler_client,
const Config& config);
~GestureEventQueue();
@@ -109,10 +109,6 @@ class CONTENT_EXPORT GestureEventQueue {
bool ShouldDiscardFlingCancelEvent(
const GestureEventWithLatencyInfo& gesture_event) const;
- // Calls |fling_controller_.ProgressFling| to advance an active fling on every
- // begin frame and returns the current fling velocity if a fling is active.
- gfx::Vector2dF ProgressFling(base::TimeTicks current_time);
-
// Calls |fling_controller_.StopFling| to halt an active fling if such exists.
void StopFling();
@@ -120,6 +116,8 @@ class CONTENT_EXPORT GestureEventQueue {
bool TouchscreenFlingInProgress() const;
+ gfx::Vector2dF CurrentFlingVelocity() const;
+
void set_debounce_interval_time_ms_for_testing(int interval_ms) {
debounce_interval_ = base::TimeDelta::FromMilliseconds(interval_ms);
}
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
index 75ad2cd71de..d9fc411f476 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -12,7 +12,6 @@
#include "base/location.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
@@ -36,8 +35,8 @@ namespace content {
class GestureEventQueueTest : public testing::Test,
public GestureEventQueueClient,
- public TouchpadTapSuppressionControllerClient,
- public FlingControllerClient {
+ public FlingControllerEventSenderClient,
+ public FlingControllerSchedulerClient {
public:
GestureEventQueueTest() : GestureEventQueueTest(false) {}
@@ -65,17 +64,13 @@ class GestureEventQueueTest : public testing::Test,
queue_.reset();
}
- void SetUpForTapSuppression(int max_cancel_to_down_time_ms,
- int max_tap_gap_time_ms) {
+ void SetUpForTapSuppression(int max_cancel_to_down_time_ms) {
GestureEventQueue::Config gesture_config;
gesture_config.fling_config.touchscreen_tap_suppression_config.enabled =
true;
gesture_config.fling_config.touchscreen_tap_suppression_config
.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(max_cancel_to_down_time_ms);
- gesture_config.fling_config.touchscreen_tap_suppression_config
- .max_tap_gap_time =
- base::TimeDelta::FromMilliseconds(max_tap_gap_time_ms);
queue_.reset(new GestureEventQueue(this, this, this, gesture_config));
}
@@ -101,17 +96,17 @@ class GestureEventQueueTest : public testing::Test,
}
}
- // TouchpadTapSuppressionControllerClient
- void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& event) override {}
-
- // FlingControllerClient
+ // FlingControllerEventSenderClient
void SendGeneratedWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) override {}
void SendGeneratedGestureScrollEvents(
const GestureEventWithLatencyInfo& gesture_event) override {}
- void SetNeedsBeginFrameForFlingProgress() override {}
- void DidStopFlingingOnBrowser() override {}
+
+ // FlingControllerSchedulerClient
+ void ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) override {}
+ void DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) override {}
protected:
static GestureEventQueue::Config DefaultConfig() {
@@ -1036,7 +1031,7 @@ TEST_F(GestureEventQueueTest, DebounceDefersFollowingGestureEvents) {
EXPECT_EQ(2U, GestureEventDebouncingQueueSize());
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMilliseconds(5));
base::RunLoop().Run();
@@ -1159,7 +1154,7 @@ TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) {
// Test that the fling cancelling tap down event and its following tap get
// suppressed when tap suppression is enabled.
TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) {
- SetUpForTapSuppression(400, 200);
+ SetUpForTapSuppression(400);
SimulateGestureFlingStartEvent(0, -10, blink::kWebGestureDeviceTouchscreen);
EXPECT_TRUE(FlingInProgress());
// The fling start event is not sent to the renderer.
diff --git a/chromium/content/browser/renderer_host/input/input_router.h b/chromium/content/browser/renderer_host/input/input_router.h
index dbced13759e..7b6c6f8cb4b 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -70,9 +70,6 @@ class InputRouter : public IPC::Listener {
virtual void BindHost(mojom::WidgetInputHandlerHostRequest request,
bool frame_handler) = 0;
- // Used to progress an active fling on every begin frame.
- virtual void ProgressFling(base::TimeTicks current_time) = 0;
-
// Used to stop an active fling if such exists.
virtual void StopFling() = 0;
diff --git a/chromium/content/browser/renderer_host/input/input_router_client.h b/chromium/content/browser/renderer_host/input/input_router_client.h
index 7d776d1e4c2..e714ee3f9c3 100644
--- a/chromium/content/browser/renderer_host/input/input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/input_router_client.h
@@ -71,9 +71,12 @@ class CONTENT_EXPORT InputRouterClient {
const blink::WebMouseWheelEvent& wheel_event,
const ui::LatencyInfo& latency_info) = 0;
- // Called when the input router needs a begin frame to advance an active
- // fling.
- virtual void SetNeedsBeginFrameForFlingProgress() = 0;
+ // Called to see if there is an ongoing wheel scroll sequence on the client.
+ virtual bool IsWheelScrollInProgress() = 0;
+
+ // Called to toggle whether the RenderWidgetHost should capture all mouse
+ // input.
+ virtual void SetMouseCapture(bool capture) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_config_helper.cc b/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
index 46fd57cf564..6028f64d343 100644
--- a/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
@@ -5,9 +5,7 @@
#include "content/browser/renderer_host/input/input_router_config_helper.h"
#include "base/command_line.h"
-#include "base/feature_list.h"
#include "build/build_config.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gesture_detection/gesture_detector.h"
@@ -30,12 +28,8 @@ PassthroughTouchEventQueue::Config GetTouchEventQueueConfig() {
base::TimeDelta::FromMilliseconds(kMobileTouchAckTimeoutDelayMs);
#if defined(OS_ANDROID)
- // For historical reasons only Android enables the touch ack timeout. The
- // touch ack timeout will be replaced by an intervention which forces events
- // to be non-blocking if the main thread is busy. This is currently behind a
- // flag.
- config.touch_ack_timeout_supported = !base::FeatureList::IsEnabled(
- features::kMainThreadBusyScrollIntervention);
+ // For historical reasons only Android enables the touch ack timeout.
+ config.touch_ack_timeout_supported = true;
#else
config.touch_ack_timeout_supported = false;
#endif
@@ -56,24 +50,11 @@ GestureEventQueue::Config GetGestureEventQueueConfig() {
.max_cancel_to_down_time = base::TimeDelta::FromMilliseconds(
gesture_config->fling_max_cancel_to_down_time_in_ms());
- // Tap suppression controller forwards the stashed tapDown and drops the rest
- // of the stashed events when the tapDownTimer expires. If a fling cancel ack
- // with |processed = false| arrives before the timer expiration, all stashed
- // events will be forwarded. The timer is used to avoid waiting for an
- // arbitrarily late fling cancel ack. Its delay should be large enough for
- // a long press to get stashed and forwarded if needed.
- config.fling_config.touchscreen_tap_suppression_config.max_tap_gap_time =
- base::TimeDelta::FromMilliseconds(
- gesture_config->long_press_time_in_ms() + 50);
-
config.fling_config.touchpad_tap_suppression_config.enabled =
gesture_config->fling_touchpad_tap_suppression_enabled();
config.fling_config.touchpad_tap_suppression_config.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(
gesture_config->fling_max_cancel_to_down_time_in_ms());
- config.fling_config.touchpad_tap_suppression_config.max_tap_gap_time =
- base::TimeDelta::FromMilliseconds(
- gesture_config->fling_max_tap_gap_time_in_ms());
return config;
}
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.cc b/chromium/content/browser/renderer_host/input/input_router_impl.cc
index be695174e56..c1308d16722 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -15,7 +15,6 @@
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/browser/renderer_host/input/input_disposition_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/common/content_constants_internal.h"
#include "content/common/edit_command.h"
#include "content/common/input/input_handler.mojom.h"
@@ -69,9 +68,11 @@ ui::WebScopedInputEvent ScaleEvent(const WebInputEvent& event, double scale) {
} // namespace
-InputRouterImpl::InputRouterImpl(InputRouterImplClient* client,
- InputDispositionHandler* disposition_handler,
- const Config& config)
+InputRouterImpl::InputRouterImpl(
+ InputRouterImplClient* client,
+ InputDispositionHandler* disposition_handler,
+ FlingControllerSchedulerClient* fling_scheduler_client,
+ const Config& config)
: client_(client),
disposition_handler_(disposition_handler),
frame_tree_node_id_(-1),
@@ -81,7 +82,10 @@ InputRouterImpl::InputRouterImpl(InputRouterImplClient* client,
features::kTouchpadAndWheelScrollLatching)),
wheel_event_queue_(this, wheel_scroll_latching_enabled_),
touch_event_queue_(this, config.touch_config),
- gesture_event_queue_(this, this, this, config.gesture_config),
+ gesture_event_queue_(this,
+ this,
+ fling_scheduler_client,
+ config.gesture_config),
device_scale_factor_(1.f),
host_binding_(this),
frame_host_binding_(this),
@@ -90,6 +94,7 @@ InputRouterImpl::InputRouterImpl(InputRouterImplClient* client,
DCHECK(client);
DCHECK(disposition_handler);
+ DCHECK(fling_scheduler_client);
UpdateTouchAckTimeoutEnabled();
}
@@ -99,7 +104,7 @@ void InputRouterImpl::SendMouseEvent(
const MouseEventWithLatencyInfo& mouse_event) {
if (mouse_event.event.GetType() == WebInputEvent::kMouseDown &&
gesture_event_queue_.GetTouchpadTapSuppressionController()
- ->ShouldDeferMouseDown(mouse_event))
+ ->ShouldSuppressMouseDown(mouse_event))
return;
if (mouse_event.event.GetType() == WebInputEvent::kMouseUp &&
gesture_event_queue_.GetTouchpadTapSuppressionController()
@@ -131,7 +136,8 @@ void InputRouterImpl::SendGestureEvent(
GestureEventWithLatencyInfo gesture_event(original_gesture_event);
- if (touch_action_filter_.FilterGestureEvent(&gesture_event.event)) {
+ if (touch_action_filter_.FilterGestureEvent(&gesture_event.event) ==
+ FilterGestureEventResult::kFilterGestureEventFiltered) {
disposition_handler_->OnGestureEventAck(gesture_event,
InputEventAckSource::BROWSER,
INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -209,10 +215,6 @@ void InputRouterImpl::BindHost(mojom::WidgetInputHandlerHostRequest request,
}
}
-void InputRouterImpl::ProgressFling(base::TimeTicks current_time) {
- current_fling_velocity_ = gesture_event_queue_.ProgressFling(current_time);
-}
-
void InputRouterImpl::StopFling() {
gesture_event_queue_.StopFling();
}
@@ -221,11 +223,6 @@ bool InputRouterImpl::FlingCancellationIsDeferred() {
return gesture_event_queue_.FlingCancellationIsDeferred();
}
-void InputRouterImpl::DidStopFlingingOnBrowser() {
- current_fling_velocity_ = gfx::Vector2dF();
- client_->DidStopFlinging();
-}
-
void InputRouterImpl::CancelTouchTimeout() {
touch_event_queue_.SetAckTimeoutEnabled(false);
}
@@ -243,7 +240,8 @@ void InputRouterImpl::SetWhiteListedTouchAction(cc::TouchAction touch_action,
void InputRouterImpl::DidOverscroll(const ui::DidOverscrollParams& params) {
// Touchpad and Touchscreen flings are handled on the browser side.
ui::DidOverscrollParams fling_updated_params = params;
- fling_updated_params.current_fling_velocity = current_fling_velocity_;
+ fling_updated_params.current_fling_velocity =
+ gesture_event_queue_.CurrentFlingVelocity();
client_->DidOverscroll(fling_updated_params);
}
@@ -270,6 +268,10 @@ void InputRouterImpl::ImeCompositionRangeChanged(
client_->OnImeCompositionRangeChanged(range, bounds);
}
+void InputRouterImpl::SetMouseCapture(bool capture) {
+ client_->SetMouseCapture(capture);
+}
+
bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) {
// TODO(dtapuska): Move these to mojo
bool handled = true;
@@ -390,10 +392,6 @@ void InputRouterImpl::SendGeneratedGestureScrollEvents(
gesture_event.latency);
}
-void InputRouterImpl::SetNeedsBeginFrameForFlingProgress() {
- client_->SetNeedsBeginFrameForFlingProgress();
-}
-
void InputRouterImpl::SendMouseWheelEventImmediately(
const MouseWheelEventWithLatencyInfo& wheel_event) {
mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
@@ -415,6 +413,10 @@ void InputRouterImpl::ForwardGestureEventWithLatencyInfo(
client_->ForwardGestureEventWithLatencyInfo(event, latency_info);
}
+bool InputRouterImpl::IsWheelScrollInProgress() {
+ return client_->IsWheelScrollInProgress();
+}
+
void InputRouterImpl::FilterAndSendWebInputEvent(
const WebInputEvent& input_event,
const ui::LatencyInfo& latency_info,
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.h b/chromium/content/browser/renderer_host/input/input_router_impl.h
index a7da333622a..205cb3abc83 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -15,13 +15,13 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "cc/input/touch_action.h"
+#include "content/browser/renderer_host/input/fling_scheduler.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/browser/renderer_host/input/input_router.h"
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
#include "content/browser/renderer_host/input/touch_action_filter.h"
-#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/common/input/input_event_stream_validator.h"
#include "content/common/input/input_handler.mojom.h"
#include "content/common/widget.mojom.h"
@@ -50,17 +50,16 @@ class CONTENT_EXPORT InputRouterImplClient : public InputRouterClient {
};
// A default implementation for browser input event routing.
-class CONTENT_EXPORT InputRouterImpl
- : public InputRouter,
- public GestureEventQueueClient,
- public FlingControllerClient,
- public MouseWheelEventQueueClient,
- public PassthroughTouchEventQueueClient,
- public TouchpadTapSuppressionControllerClient,
- public mojom::WidgetInputHandlerHost {
+class CONTENT_EXPORT InputRouterImpl : public InputRouter,
+ public GestureEventQueueClient,
+ public FlingControllerEventSenderClient,
+ public MouseWheelEventQueueClient,
+ public PassthroughTouchEventQueueClient,
+ public mojom::WidgetInputHandlerHost {
public:
InputRouterImpl(InputRouterImplClient* client,
InputDispositionHandler* disposition_handler,
+ FlingControllerSchedulerClient* fling_scheduler_client,
const Config& config);
~InputRouterImpl() override;
@@ -81,10 +80,8 @@ class CONTENT_EXPORT InputRouterImpl
cc::TouchAction AllowedTouchAction() override;
void BindHost(mojom::WidgetInputHandlerHostRequest request,
bool frame_handler) override;
- void ProgressFling(base::TimeTicks current_time) override;
void StopFling() override;
bool FlingCancellationIsDeferred() override;
- void DidStopFlingingOnBrowser() override;
// InputHandlerHost impl
void CancelTouchTimeout() override;
@@ -98,6 +95,13 @@ class CONTENT_EXPORT InputRouterImpl
void ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& bounds) override;
+ void SetMouseCapture(bool capture) override;
+
+ // Exposed so that tests can swap out the implementation and intercept calls.
+ mojo::Binding<mojom::WidgetInputHandlerHost>&
+ frame_host_binding_for_testing() {
+ return frame_host_binding_;
+ }
// IPC::Listener
bool OnMessageReceived(const IPC::Message& message) override;
@@ -109,9 +113,7 @@ class CONTENT_EXPORT InputRouterImpl
// Keeps track of last position of touch points and sets MovementXY for them.
void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);
- // TouchpadTapSuppressionControllerClient
- void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) override;
+ void SendMouseEventImmediately(const MouseEventWithLatencyInfo& mouse_event);
// PassthroughTouchEventQueueClient
void SendTouchEventImmediately(
@@ -129,12 +131,11 @@ class CONTENT_EXPORT InputRouterImpl
InputEventAckSource ack_source,
InputEventAckState ack_result) override;
- // FlingControllerClient
+ // FlingControllerEventSenderClient
void SendGeneratedWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) override;
void SendGeneratedGestureScrollEvents(
const GestureEventWithLatencyInfo& gesture_event) override;
- void SetNeedsBeginFrameForFlingProgress() override;
// MouseWheelEventQueueClient
void SendMouseWheelEventImmediately(
@@ -145,6 +146,7 @@ class CONTENT_EXPORT InputRouterImpl
void ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& latency_info) override;
+ bool IsWheelScrollInProgress() override;
void FilterAndSendWebInputEvent(
const blink::WebInputEvent& input_event,
@@ -221,8 +223,6 @@ class CONTENT_EXPORT InputRouterImpl
float device_scale_factor_;
- gfx::Vector2dF current_fling_velocity_;
-
// Last touch position relative to screen. Used to compute movementX/Y.
base::flat_map<int, gfx::Point> global_touch_position_;
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 1761884fa5b..3e580d0864f 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -15,7 +15,6 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
@@ -115,6 +114,8 @@ class MockInputRouterImplClient : public InputRouterImplClient {
void OnImeCancelComposition() override {}
+ void SetMouseCapture(bool capture) override {}
+
MockWidgetInputHandler::MessageVector GetAndResetDispatchedMessages() {
return widget_input_handler_.GetAndResetDispatchedMessages();
}
@@ -147,10 +148,6 @@ class MockInputRouterImplClient : public InputRouterImplClient {
input_router_client_.DidStartScrollingViewport();
}
- void SetNeedsBeginFrameForFlingProgress() override {
- input_router_client_.SetNeedsBeginFrameForFlingProgress();
- }
-
void ForwardWheelEventWithLatencyInfo(
const blink::WebMouseWheelEvent& wheel_event,
const ui::LatencyInfo& latency_info) override {
@@ -165,6 +162,10 @@ class MockInputRouterImplClient : public InputRouterImplClient {
latency_info);
}
+ bool IsWheelScrollInProgress() override {
+ return input_router_client_.IsWheelScrollInProgress();
+ }
+
void OnSetWhiteListedTouchAction(cc::TouchAction touch_action) override {
input_router_client_.OnSetWhiteListedTouchAction(touch_action);
}
@@ -245,8 +246,9 @@ class InputRouterImplTest : public testing::Test {
command_line->AppendSwitch(switches::kValidateInputEventStream);
client_.reset(new MockInputRouterImplClient());
disposition_handler_.reset(new MockInputDispositionHandler());
- input_router_.reset(new InputRouterImpl(
- client_.get(), disposition_handler_.get(), config_));
+ input_router_.reset(
+ new InputRouterImpl(client_.get(), disposition_handler_.get(),
+ &client_->input_router_client_, config_));
client_->set_input_router(input_router());
disposition_handler_->set_input_router(input_router());
@@ -274,8 +276,8 @@ class InputRouterImplTest : public testing::Test {
void SimulateKeyboardEvent(WebInputEvent::Type type) {
NativeWebKeyboardEventWithLatencyInfo key_event(
- type, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()), ui::LatencyInfo());
+ type, WebInputEvent::kNoModifiers, ui::EventTimeForNow(),
+ ui::LatencyInfo());
input_router_->SendKeyboardEvent(key_event);
}
@@ -431,7 +433,8 @@ class InputRouterImplTest : public testing::Test {
static void RunTasksAndWait(base::TimeDelta delay) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), delay);
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
+ delay);
base::RunLoop().Run();
}
@@ -2351,48 +2354,4 @@ TEST_F(InputRouterImplScaleGestureEventTest, GestureTwoFingerTap) {
EXPECT_EQ(40, filter_event->data.two_finger_tap.first_finger_height);
}
-// Thie test is flaky on Fuchsia. crbug.com/807803
-#if defined(OS_FUCHSIA)
-#define MAYBE_GestureFlingStart DISABLED_GestureFlingStart
-#else
-#define MAYBE_GestureFlingStart GestureFlingStart
-#endif
-TEST_F(InputRouterImplScaleGestureEventTest, MAYBE_GestureFlingStart) {
- // Simulate a GSB since touchscreen flings must happen inside scroll.
- SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollBegin(
- 10.f, 20.f, blink::kWebGestureDeviceTouchscreen));
- FlushGestureEvent(WebInputEvent::kGestureScrollBegin);
-
- const gfx::PointF orig(10, 20), scaled(20, 40);
- WebGestureEvent event =
- BuildGestureEvent(WebInputEvent::kGestureFlingStart, orig);
- event.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
- event.data.fling_start.velocity_x = 30;
- event.data.fling_start.velocity_y = 40;
- SimulateGestureEvent(event);
- // Fling events don't get sent to the renderer.
- UpdateDispatchedMessages();
- ASSERT_EQ(0u, dispatched_messages_.size());
-
- // Progress the fling and check the first GestureScrollUpdate generated by
- // fling progress, note that |at(0)| is TouchScrollStarted.
- base::TimeTicks progress_time =
- base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(17);
- input_router_->ProgressFling(progress_time);
- UpdateDispatchedMessages();
- ASSERT_EQ(2u, dispatched_messages_.size());
- const WebGestureEvent* sent_event = static_cast<const WebGestureEvent*>(
- dispatched_messages_[1]->ToEvent()->Event()->web_event.get());
- TestLocationInSentEvent(sent_event, orig, scaled);
- float sent_delta_x = sent_event->data.scroll_update.delta_x;
- float sent_delta_y = sent_event->data.scroll_update.delta_y;
- EXPECT_LT(0, sent_delta_x);
- EXPECT_LT(0, sent_delta_y);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- TestLocationInFilterEvent(filter_event, orig);
- EXPECT_FLOAT_EQ(sent_delta_x, 2 * filter_event->data.scroll_update.delta_x);
- EXPECT_FLOAT_EQ(sent_delta_y, 2 * filter_event->data.scroll_update.delta_y);
-}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc b/chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc
deleted file mode 100644
index 9a96150ec70..00000000000
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.cc
+++ /dev/null
@@ -1,706 +0,0 @@
-// Copyright 2013 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/renderer_host/input/legacy_input_router_impl.h"
-
-#include <math.h>
-
-#include <utility>
-
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "content/browser/renderer_host/input/gesture_event_queue.h"
-#include "content/browser/renderer_host/input/input_disposition_handler.h"
-#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
-#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
-#include "content/common/content_constants_internal.h"
-#include "content/common/edit_command.h"
-#include "content/common/input/web_touch_event_traits.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/input_event_ack_state.h"
-#include "ipc/ipc_sender.h"
-#include "ui/events/blink/blink_event_util.h"
-#include "ui/events/blink/web_input_event_traits.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-using base::TimeDelta;
-using base::TimeTicks;
-using blink::WebGestureEvent;
-using blink::WebInputEvent;
-using blink::WebKeyboardEvent;
-using blink::WebMouseEvent;
-using blink::WebMouseWheelEvent;
-using blink::WebTouchEvent;
-using ui::WebInputEventTraits;
-
-namespace content {
-
-LegacyInputRouterImpl::LegacyInputRouterImpl(
- IPC::Sender* sender,
- InputRouterClient* client,
- InputDispositionHandler* disposition_handler,
- int routing_id,
- const Config& config)
- : sender_(sender),
- client_(client),
- disposition_handler_(disposition_handler),
- routing_id_(routing_id),
- frame_tree_node_id_(-1),
- select_message_pending_(false),
- move_caret_pending_(false),
- active_renderer_fling_count_(0),
- touch_scroll_started_sent_(false),
- wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching)),
- wheel_event_queue_(this, wheel_scroll_latching_enabled_),
- gesture_event_queue_(this, this, this, config.gesture_config),
- device_scale_factor_(1.f) {
- touch_event_queue_.reset(
- new PassthroughTouchEventQueue(this, config.touch_config));
-
- DCHECK(sender);
- DCHECK(client);
- DCHECK(disposition_handler);
- UpdateTouchAckTimeoutEnabled();
-}
-
-LegacyInputRouterImpl::~LegacyInputRouterImpl() {}
-
-bool LegacyInputRouterImpl::SendInput(std::unique_ptr<IPC::Message> message) {
- DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart);
- switch (message->type()) {
- // Check for types that require an ACK.
- case InputMsg_SelectRange::ID:
- case InputMsg_MoveRangeSelectionExtent::ID:
- return SendSelectMessage(std::move(message));
- case InputMsg_MoveCaret::ID:
- return SendMoveCaret(std::move(message));
- case InputMsg_HandleInputEvent::ID:
- NOTREACHED() << "WebInputEvents should never be sent via SendInput.";
- return false;
- default:
- return Send(message.release());
- }
-}
-
-void LegacyInputRouterImpl::SendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) {
- if (mouse_event.event.GetType() == WebInputEvent::kMouseDown &&
- gesture_event_queue_.GetTouchpadTapSuppressionController()
- ->ShouldDeferMouseDown(mouse_event))
- return;
- if (mouse_event.event.GetType() == WebInputEvent::kMouseUp &&
- gesture_event_queue_.GetTouchpadTapSuppressionController()
- ->ShouldSuppressMouseUp())
- return;
-
- SendMouseEventImmediately(mouse_event);
-}
-
-void LegacyInputRouterImpl::SendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) {
- wheel_event_queue_.QueueEvent(wheel_event);
-}
-
-void LegacyInputRouterImpl::SendKeyboardEvent(
- const NativeWebKeyboardEventWithLatencyInfo& key_event) {
- // Put all WebKeyboardEvent objects in a queue since we can't trust the
- // renderer and we need to give something to the HandleKeyboardEvent
- // handler.
- key_queue_.push_back(key_event);
- LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
-
- gesture_event_queue_.FlingHasBeenHalted();
-
- // Only forward the non-native portions of our event.
- FilterAndSendWebInputEvent(key_event.event, key_event.latency);
-}
-
-void LegacyInputRouterImpl::SendGestureEvent(
- const GestureEventWithLatencyInfo& original_gesture_event) {
- input_stream_validator_.Validate(original_gesture_event.event,
- FlingCancellationIsDeferred());
-
- GestureEventWithLatencyInfo gesture_event(original_gesture_event);
-
- if (touch_action_filter_.FilterGestureEvent(&gesture_event.event))
- return;
-
- wheel_event_queue_.OnGestureScrollEvent(gesture_event);
-
- if (gesture_event.event.SourceDevice() ==
- blink::kWebGestureDeviceTouchscreen) {
- if (gesture_event.event.GetType() ==
- blink::WebInputEvent::kGestureScrollBegin) {
- touch_scroll_started_sent_ = false;
- } else if (!touch_scroll_started_sent_ &&
- gesture_event.event.GetType() ==
- blink::WebInputEvent::kGestureScrollUpdate) {
- // A touch scroll hasn't really started until the first
- // GestureScrollUpdate event. Eg. if the page consumes all touchmoves
- // then no scrolling really ever occurs (even though we still send
- // GestureScrollBegin).
- touch_scroll_started_sent_ = true;
- touch_event_queue_->PrependTouchScrollNotification();
- }
- touch_event_queue_->OnGestureScrollEvent(gesture_event);
- }
-
- gesture_event_queue_.QueueEvent(gesture_event);
-}
-
-void LegacyInputRouterImpl::SendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) {
- TouchEventWithLatencyInfo updatd_touch_event = touch_event;
- SetMovementXYForTouchPoints(&updatd_touch_event.event);
- input_stream_validator_.Validate(updatd_touch_event.event);
- touch_event_queue_->QueueEvent(updatd_touch_event);
-}
-
-// Forwards MouseEvent without passing it through
-// TouchpadTapSuppressionController.
-void LegacyInputRouterImpl::SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) {
- mouse_event_queue_.push_back(mouse_event);
- FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency);
-}
-
-void LegacyInputRouterImpl::SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) {
- FilterAndSendWebInputEvent(touch_event.event, touch_event.latency);
-}
-
-void LegacyInputRouterImpl::SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) {
- FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency);
-}
-
-void LegacyInputRouterImpl::NotifySiteIsMobileOptimized(
- bool is_mobile_optimized) {
- touch_event_queue_->SetIsMobileOptimizedSite(is_mobile_optimized);
-}
-
-bool LegacyInputRouterImpl::HasPendingEvents() const {
- return !touch_event_queue_->Empty() || !gesture_event_queue_.empty() ||
- !key_queue_.empty() || !mouse_event_queue_.empty() ||
- wheel_event_queue_.has_pending() || select_message_pending_ ||
- move_caret_pending_ || active_renderer_fling_count_ > 0;
-}
-
-void LegacyInputRouterImpl::SetDeviceScaleFactor(float device_scale_factor) {
- device_scale_factor_ = device_scale_factor;
-}
-
-void LegacyInputRouterImpl::BindHost(
- mojom::WidgetInputHandlerHostRequest request,
- bool frame_handler) {
- NOTREACHED();
-}
-
-void LegacyInputRouterImpl::ProgressFling(base::TimeTicks current_time) {
- current_fling_velocity_ = gesture_event_queue_.ProgressFling(current_time);
-}
-
-void LegacyInputRouterImpl::StopFling() {
- gesture_event_queue_.StopFling();
-}
-
-bool LegacyInputRouterImpl::FlingCancellationIsDeferred() {
- return gesture_event_queue_.FlingCancellationIsDeferred();
-}
-
-void LegacyInputRouterImpl::DidStopFlingingOnBrowser() {
- current_fling_velocity_ = gfx::Vector2dF();
- client_->DidStopFlinging();
-}
-
-bool LegacyInputRouterImpl::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(LegacyInputRouterImpl, message)
- IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
- IPC_MESSAGE_HANDLER(InputHostMsg_DidOverscroll, OnDidOverscroll)
- IPC_MESSAGE_HANDLER(InputHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
- IPC_MESSAGE_HANDLER(InputHostMsg_SelectRange_ACK, OnSelectMessageAck)
- IPC_MESSAGE_HANDLER(InputHostMsg_MoveRangeSelectionExtent_ACK,
- OnSelectMessageAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
- OnHasTouchEventHandlers)
- IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction, OnSetTouchAction)
- IPC_MESSAGE_HANDLER(InputHostMsg_SetWhiteListedTouchAction,
- OnSetWhiteListedTouchAction)
- IPC_MESSAGE_HANDLER(InputHostMsg_DidStopFlinging, OnDidStopFlinging)
- IPC_MESSAGE_HANDLER(InputHostMsg_DidStartScrollingViewport,
- OnDidStartScrollingViewport)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void LegacyInputRouterImpl::OnTouchEventAck(
- const TouchEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) {
- // Touchstart events sent to the renderer indicate a new touch sequence, but
- // in some cases we may filter out sending the touchstart - catch those here.
- if (WebTouchEventTraits::IsTouchSequenceStart(event.event) &&
- ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
- touch_action_filter_.ResetTouchAction();
- UpdateTouchAckTimeoutEnabled();
- }
- disposition_handler_->OnTouchEventAck(event, ack_source, ack_result);
-
- // Reset the touch action at the end of a touch-action sequence.
- if (WebTouchEventTraits::IsTouchSequenceEnd(event.event)) {
- touch_action_filter_.ReportAndResetTouchAction();
- UpdateTouchAckTimeoutEnabled();
- }
-}
-
-void LegacyInputRouterImpl::OnFilteringTouchEvent(
- const WebTouchEvent& touch_event) {
- // The event stream given to the renderer is not guaranteed to be
- // valid based on the current TouchEventStreamValidator rules. This event will
- // never be given to the renderer, but in order to ensure that the event
- // stream |output_stream_validator_| sees is valid, we give events which are
- // filtered out to the validator. crbug.com/589111 proposes adding an
- // additional validator for the events which are actually sent to the
- // renderer.
- output_stream_validator_.Validate(touch_event);
-}
-
-bool LegacyInputRouterImpl::TouchscreenFlingInProgress() {
- return gesture_event_queue_.TouchscreenFlingInProgress();
-}
-
-void LegacyInputRouterImpl::OnGestureEventAck(
- const GestureEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) {
- touch_event_queue_->OnGestureEventAck(event, ack_result);
- disposition_handler_->OnGestureEventAck(event, ack_source, ack_result);
-}
-
-void LegacyInputRouterImpl::ForwardGestureEventWithLatencyInfo(
- const blink::WebGestureEvent& event,
- const ui::LatencyInfo& latency_info) {
- client_->ForwardGestureEventWithLatencyInfo(event, latency_info);
-}
-
-void LegacyInputRouterImpl::SendGeneratedWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) {
- client_->ForwardWheelEventWithLatencyInfo(wheel_event.event,
- wheel_event.latency);
-}
-
-void LegacyInputRouterImpl::SendGeneratedGestureScrollEvents(
- const GestureEventWithLatencyInfo& gesture_event) {
- client_->ForwardGestureEventWithLatencyInfo(gesture_event.event,
- gesture_event.latency);
-}
-
-void LegacyInputRouterImpl::SetNeedsBeginFrameForFlingProgress() {
- client_->SetNeedsBeginFrameForFlingProgress();
-}
-
-void LegacyInputRouterImpl::SendMouseWheelEventImmediately(
- const MouseWheelEventWithLatencyInfo& wheel_event) {
- FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency);
-}
-
-void LegacyInputRouterImpl::OnMouseWheelEventAck(
- const MouseWheelEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) {
- disposition_handler_->OnWheelEventAck(event, ack_source, ack_result);
-}
-
-bool LegacyInputRouterImpl::SendSelectMessage(
- std::unique_ptr<IPC::Message> message) {
- DCHECK(message->type() == InputMsg_SelectRange::ID ||
- message->type() == InputMsg_MoveRangeSelectionExtent::ID);
-
- // TODO(jdduke): Factor out common logic between selection and caret-related
- // IPC messages.
- if (select_message_pending_) {
- if (!pending_select_messages_.empty() &&
- pending_select_messages_.back()->type() == message->type()) {
- pending_select_messages_.pop_back();
- }
-
- pending_select_messages_.push_back(std::move(message));
- return true;
- }
-
- select_message_pending_ = true;
- return Send(message.release());
-}
-
-bool LegacyInputRouterImpl::SendMoveCaret(
- std::unique_ptr<IPC::Message> message) {
- DCHECK(message->type() == InputMsg_MoveCaret::ID);
- if (move_caret_pending_) {
- next_move_caret_ = std::move(message);
- return true;
- }
-
- move_caret_pending_ = true;
- return Send(message.release());
-}
-
-bool LegacyInputRouterImpl::Send(IPC::Message* message) {
- return sender_->Send(message);
-}
-
-void LegacyInputRouterImpl::FilterAndSendWebInputEvent(
- const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) {
- TRACE_EVENT1("input", "LegacyInputRouterImpl::FilterAndSendWebInputEvent",
- "type", WebInputEvent::GetName(input_event.GetType()));
- TRACE_EVENT_WITH_FLOW2(
- "input,benchmark,devtools.timeline", "LatencyInfo.Flow",
- TRACE_ID_DONT_MANGLE(latency_info.trace_id()),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
- "SendInputEventUI", "frameTreeNodeId", frame_tree_node_id_);
-
- OfferToHandlers(input_event, latency_info);
-}
-
-void LegacyInputRouterImpl::OfferToHandlers(
- const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) {
- output_stream_validator_.Validate(input_event);
-
- if (OfferToClient(input_event, latency_info))
- return;
-
- bool should_block = WebInputEventTraits::ShouldBlockEventStream(
- input_event, wheel_scroll_latching_enabled_);
- OfferToRenderer(input_event, latency_info,
- should_block
- ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
- : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING);
-
- // Generate a synthetic ack if the event was sent so it doesn't block.
- if (!should_block) {
- ProcessInputEventAck(
- input_event.GetType(), InputEventAckSource::BROWSER,
- INPUT_EVENT_ACK_STATE_IGNORED, latency_info,
- WebInputEventTraits::GetUniqueTouchEventId(input_event));
- }
-}
-
-bool LegacyInputRouterImpl::OfferToClient(const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) {
- bool consumed = false;
-
- InputEventAckState filter_ack =
- client_->FilterInputEvent(input_event, latency_info);
- switch (filter_ack) {
- case INPUT_EVENT_ACK_STATE_CONSUMED:
- case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
- // Send the ACK and early exit.
- ProcessInputEventAck(
- input_event.GetType(), InputEventAckSource::BROWSER, filter_ack,
- latency_info,
- WebInputEventTraits::GetUniqueTouchEventId(input_event));
- // WARNING: |this| may be deleted at this point.
- consumed = true;
- break;
- case INPUT_EVENT_ACK_STATE_UNKNOWN:
- // Simply drop the event.
- consumed = true;
- break;
- default:
- break;
- }
-
- return consumed;
-}
-
-bool LegacyInputRouterImpl::OfferToRenderer(
- const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info,
- InputEventDispatchType dispatch_type) {
- // This conversion is temporary. WebInputEvent should be generated
- // directly from ui::Event with the viewport coordinates. See
- // crbug.com/563730.
- std::unique_ptr<blink::WebInputEvent> event_in_viewport =
- ui::ScaleWebInputEvent(input_event, device_scale_factor_);
- const WebInputEvent* event_to_send =
- event_in_viewport ? event_in_viewport.get() : &input_event;
-
- if (Send(new InputMsg_HandleInputEvent(
- routing_id(), event_to_send, std::vector<IPC::WebInputEventPointer>(),
- latency_info, dispatch_type))) {
- // Ack messages for ignored ack event types should never be sent by the
- // renderer. Consequently, such event types should not affect event time
- // or in-flight event count metrics.
- if (dispatch_type == InputEventDispatchType::DISPATCH_TYPE_BLOCKING)
- client_->IncrementInFlightEventCount();
- return true;
- }
- return false;
-}
-
-void LegacyInputRouterImpl::OnInputEventAck(const InputEventAck& ack) {
- client_->DecrementInFlightEventCount(ack.source);
-
- if (ack.overscroll) {
- DCHECK(ack.type == WebInputEvent::kMouseWheel ||
- ack.type == WebInputEvent::kGestureScrollUpdate);
- OnDidOverscroll(*ack.overscroll);
- }
-
- // Since input messages over mojo require the touch action in the
- // ACK we mirror that behavior in Chrome IPC for simplicity.
- if (ack.touch_action.has_value())
- OnSetTouchAction(ack.touch_action.value());
-
- ProcessInputEventAck(ack.type, ack.source, ack.state, ack.latency,
- ack.unique_touch_event_id);
-}
-
-void LegacyInputRouterImpl::OnDidOverscroll(
- const ui::DidOverscrollParams& params) {
- // Touchpad and Touchscreen flings are handled on the browser side.
- ui::DidOverscrollParams fling_updated_params = params;
- fling_updated_params.current_fling_velocity = current_fling_velocity_;
- client_->DidOverscroll(fling_updated_params);
-}
-
-void LegacyInputRouterImpl::OnMsgMoveCaretAck() {
- move_caret_pending_ = false;
- if (next_move_caret_)
- SendMoveCaret(std::move(next_move_caret_));
-}
-
-void LegacyInputRouterImpl::OnSelectMessageAck() {
- select_message_pending_ = false;
- if (!pending_select_messages_.empty()) {
- std::unique_ptr<IPC::Message> next_message =
- std::move(pending_select_messages_.front());
- pending_select_messages_.pop_front();
-
- SendSelectMessage(std::move(next_message));
- }
-}
-
-void LegacyInputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
- TRACE_EVENT1("input", "LegacyInputRouterImpl::OnHasTouchEventHandlers",
- "has_handlers", has_handlers);
-
- // Lack of a touch handler indicates that the page either has no touch-action
- // modifiers or that all its touch-action modifiers are auto. Resetting the
- // touch-action here allows forwarding of subsequent gestures even if the
- // underlying touches never reach the router.
- if (!has_handlers)
- touch_action_filter_.ResetTouchAction();
-
- touch_event_queue_->OnHasTouchEventHandlers(has_handlers);
- client_->OnHasTouchEventHandlers(has_handlers);
-}
-
-void LegacyInputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) {
- TRACE_EVENT1("input", "LegacyInputRouterImpl::OnSetTouchAction", "action",
- touch_action);
-
- // It is possible we get a touch action for a touch start that is no longer
- // in the queue. eg. Events that have fired the Touch ACK timeout.
- if (!touch_event_queue_->IsPendingAckTouchStart())
- return;
-
- touch_action_filter_.OnSetTouchAction(touch_action);
-
- // kTouchActionNone should disable the touch ack timeout.
- UpdateTouchAckTimeoutEnabled();
-}
-
-void LegacyInputRouterImpl::OnSetWhiteListedTouchAction(
- cc::TouchAction white_listed_touch_action,
- uint32_t unique_touch_event_id,
- InputEventAckState ack_result) {
- // TODO(hayleyferr): Catch the cases that we have filtered out sending the
- // touchstart.
-
- touch_action_filter_.OnSetWhiteListedTouchAction(white_listed_touch_action);
- client_->OnSetWhiteListedTouchAction(white_listed_touch_action);
-}
-
-void LegacyInputRouterImpl::OnDidStopFlinging() {
- DCHECK_GT(active_renderer_fling_count_, 0);
- // Note that we're only guaranteed to get a fling end notification from the
- // renderer, not from any other consumers. Consequently, the GestureEventQueue
- // cannot use this bookkeeping for logic like tap suppression.
- --active_renderer_fling_count_;
-
- client_->DidStopFlinging();
-}
-
-void LegacyInputRouterImpl::OnDidStartScrollingViewport() {
- client_->DidStartScrollingViewport();
-}
-
-void LegacyInputRouterImpl::ProcessInputEventAck(
- WebInputEvent::Type event_type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency_info,
- uint32_t unique_touch_event_id) {
- TRACE_EVENT2("input", "LegacyInputRouterImpl::ProcessInputEventAck", "type",
- WebInputEvent::GetName(event_type), "ack",
- InputEventAckStateToString(ack_result));
-
- if (WebInputEvent::IsKeyboardEventType(event_type)) {
- // Note: The keyboard ack must be treated carefully, as it may result in
- // synchronous destruction of |this|. Handling immediately guards against
- // future references to |this|.
- ProcessKeyboardAck(event_type, ack_source, ack_result, latency_info);
- // WARNING: |this| may be deleted at this point.
- return;
- } else if (WebInputEvent::IsMouseEventType(event_type)) {
- ProcessMouseAck(event_type, ack_source, ack_result, latency_info);
- } else if (event_type == WebInputEvent::kMouseWheel) {
- ProcessWheelAck(ack_source, ack_result, latency_info);
- } else if (WebInputEvent::IsTouchEventType(event_type)) {
- ProcessTouchAck(ack_source, ack_result, latency_info,
- unique_touch_event_id);
- } else if (WebInputEvent::IsGestureEventType(event_type)) {
- ProcessGestureAck(event_type, ack_source, ack_result, latency_info);
- } else if (event_type != WebInputEvent::kUndefined) {
- disposition_handler_->OnUnexpectedEventAck(
- InputDispositionHandler::BAD_ACK_MESSAGE);
- }
-}
-
-void LegacyInputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency) {
- if (key_queue_.empty()) {
- disposition_handler_->OnUnexpectedEventAck(
- InputDispositionHandler::UNEXPECTED_ACK);
- } else if (key_queue_.front().event.GetType() != type) {
- // Something must be wrong. Clear the |key_queue_| and char event
- // suppression so that we can resume from the error.
- key_queue_.clear();
- disposition_handler_->OnUnexpectedEventAck(
- InputDispositionHandler::UNEXPECTED_EVENT_TYPE);
- } else {
- NativeWebKeyboardEventWithLatencyInfo front_item = key_queue_.front();
- front_item.latency.AddNewLatencyFrom(latency);
- key_queue_.pop_front();
-
- disposition_handler_->OnKeyboardEventAck(front_item, ack_source,
- ack_result);
- // WARNING: This LegacyInputRouterImpl can be deallocated at this point
- // (i.e. in the case of Ctrl+W, where the call to
- // HandleKeyboardEvent destroys this LegacyInputRouterImpl).
- // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async.
- }
-}
-
-void LegacyInputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency) {
- if (mouse_event_queue_.empty()) {
- disposition_handler_->OnUnexpectedEventAck(
- InputDispositionHandler::UNEXPECTED_ACK);
- } else {
- MouseEventWithLatencyInfo front_item = mouse_event_queue_.front();
- front_item.latency.AddNewLatencyFrom(latency);
- mouse_event_queue_.pop_front();
- disposition_handler_->OnMouseEventAck(front_item, ack_source, ack_result);
- }
-}
-
-void LegacyInputRouterImpl::ProcessWheelAck(InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency) {
- wheel_event_queue_.ProcessMouseWheelAck(ack_source, ack_result, latency);
-}
-
-void LegacyInputRouterImpl::ProcessGestureAck(WebInputEvent::Type type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency) {
- if (type == blink::WebInputEvent::kGestureFlingStart &&
- ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
- ++active_renderer_fling_count_;
- }
-
- // |gesture_event_queue_| will forward to OnGestureEventAck when appropriate.
- gesture_event_queue_.ProcessGestureAck(ack_source, ack_result, type, latency);
-}
-
-void LegacyInputRouterImpl::ProcessTouchAck(InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency,
- uint32_t unique_touch_event_id) {
- // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
- touch_event_queue_->ProcessTouchAck(ack_source, ack_result, latency,
- unique_touch_event_id);
-}
-
-void LegacyInputRouterImpl::UpdateTouchAckTimeoutEnabled() {
- // kTouchActionNone will prevent scrolling, in which case the timeout serves
- // little purpose. It's also a strong signal that touch handling is critical
- // to page functionality, so the timeout could do more harm than good.
- const bool touch_ack_timeout_enabled =
- touch_action_filter_.allowed_touch_action() != cc::kTouchActionNone;
- touch_event_queue_->SetAckTimeoutEnabled(touch_ack_timeout_enabled);
-}
-
-void LegacyInputRouterImpl::SetFrameTreeNodeId(int frameTreeNodeId) {
- frame_tree_node_id_ = frameTreeNodeId;
-}
-
-cc::TouchAction LegacyInputRouterImpl::AllowedTouchAction() {
- return touch_action_filter_.allowed_touch_action();
-}
-
-void LegacyInputRouterImpl::SetForceEnableZoom(bool enabled) {
- touch_action_filter_.SetForceEnableZoom(enabled);
-}
-
-void LegacyInputRouterImpl::SetMovementXYForTouchPoints(
- blink::WebTouchEvent* event) {
- for (size_t i = 0; i < event->touches_length; ++i) {
- blink::WebTouchPoint* touch_point = &event->touches[i];
- if (touch_point->state == blink::WebTouchPoint::kStateMoved) {
- const gfx::Point& last_position = global_touch_position_[touch_point->id];
- touch_point->movement_x =
- touch_point->PositionInScreen().x - last_position.x();
- touch_point->movement_y =
- touch_point->PositionInScreen().y - last_position.y();
- global_touch_position_[touch_point->id].SetPoint(
- touch_point->PositionInScreen().x, touch_point->PositionInScreen().y);
- } else {
- touch_point->movement_x = 0;
- touch_point->movement_y = 0;
- if (touch_point->state == blink::WebTouchPoint::kStateReleased ||
- touch_point->state == blink::WebTouchPoint::kStateCancelled) {
- global_touch_position_.erase(touch_point->id);
- } else if (touch_point->state == blink::WebTouchPoint::kStatePressed) {
- DCHECK(global_touch_position_.find(touch_point->id) ==
- global_touch_position_.end());
- global_touch_position_[touch_point->id] =
- gfx::Point(touch_point->PositionInScreen().x,
- touch_point->PositionInScreen().y);
- }
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.h b/chromium/content/browser/renderer_host/input/legacy_input_router_impl.h
deleted file mode 100644
index ca897e6dd5b..00000000000
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl.h
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2013 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_RENDERER_HOST_INPUT_LEGACY_INPUT_ROUTER_IMPL_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_LEGACY_INPUT_ROUTER_IMPL_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-
-#include "base/containers/circular_deque.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "cc/input/touch_action.h"
-#include "content/browser/renderer_host/input/gesture_event_queue.h"
-#include "content/browser/renderer_host/input/input_router.h"
-#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
-#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
-#include "content/browser/renderer_host/input/touch_action_filter.h"
-#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
-#include "content/common/input/input_event_dispatch_type.h"
-#include "content/common/input/input_event_stream_validator.h"
-#include "content/public/browser/native_web_keyboard_event.h"
-
-namespace IPC {
-class Sender;
-}
-
-namespace ui {
-class LatencyInfo;
-struct DidOverscrollParams;
-}
-
-namespace content {
-
-class InputDispositionHandler;
-class InputRouterClient;
-struct InputEventAck;
-
-class MockRenderWidgetHost;
-
-// An implementation for browser input event routing based on
-// Chrome IPC. This class is named "legacy" because it is largely tied to
-// Chrome IPC which is deprecated. This class will be replaced with a Mojo
-// backed transport. See crbug.com/722928.
-class CONTENT_EXPORT LegacyInputRouterImpl
- : public InputRouter,
- public GestureEventQueueClient,
- public FlingControllerClient,
- public MouseWheelEventQueueClient,
- public PassthroughTouchEventQueueClient,
- public TouchpadTapSuppressionControllerClient {
- public:
- LegacyInputRouterImpl(IPC::Sender* sender,
- InputRouterClient* client,
- InputDispositionHandler* disposition_handler,
- int routing_id,
- const Config& config);
- ~LegacyInputRouterImpl() override;
-
- bool SendInput(std::unique_ptr<IPC::Message> message);
-
- // InputRouter
- void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override;
- void SendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) override;
- void SendKeyboardEvent(
- const NativeWebKeyboardEventWithLatencyInfo& key_event) override;
- void SendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) override;
- void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override;
- void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override;
- bool HasPendingEvents() const override;
- void SetDeviceScaleFactor(float device_scale_factor) override;
- void BindHost(mojom::WidgetInputHandlerHostRequest request,
- bool frame_handler) override;
- void ProgressFling(base::TimeTicks current_time) override;
- void StopFling() override;
- bool FlingCancellationIsDeferred() override;
- void DidStopFlingingOnBrowser() override;
-
- // IPC::Listener
- bool OnMessageReceived(const IPC::Message& message) override;
-
- void SetFrameTreeNodeId(int frameTreeNodeId) override;
-
- cc::TouchAction AllowedTouchAction() override;
-
- void SetForceEnableZoom(bool enabled) override;
-
- int routing_id() const { return routing_id_; }
-
- private:
- friend class LegacyInputRouterImplTest;
- friend class MockRenderWidgetHost;
-
- FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
- SubframeTouchEventRouting);
- FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
- MainframeTouchEventRouting);
-
- // Keeps track of last position of touch points and sets MovementXY for them.
- void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);
-
- // TouchpadTapSuppressionControllerClient
- void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) override;
-
- // PassthroughTouchEventQueueClient
- void SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) override;
- void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override;
- void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override;
- bool TouchscreenFlingInProgress() override;
-
- // GestureEventFilterClient
- void SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) override;
- void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override;
-
- // FlingControllerClient
- void SendGeneratedWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) override;
- void SendGeneratedGestureScrollEvents(
- const GestureEventWithLatencyInfo& gesture_event) override;
- void SetNeedsBeginFrameForFlingProgress() override;
-
- // MouseWheelEventQueueClient
- void SendMouseWheelEventImmediately(
- const MouseWheelEventWithLatencyInfo& touch_event) override;
- void OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override;
- void ForwardGestureEventWithLatencyInfo(
- const blink::WebGestureEvent& gesture_event,
- const ui::LatencyInfo& latency_info) override;
-
- bool SendMoveCaret(std::unique_ptr<IPC::Message> message);
- bool SendSelectMessage(std::unique_ptr<IPC::Message> message);
- bool Send(IPC::Message* message);
-
- // Filters and forwards |input_event| to the appropriate handler.
- void FilterAndSendWebInputEvent(const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info);
-
- // Utility routine for filtering and forwarding |input_event| to the
- // appropriate handler. |input_event| will be offered to the overscroll
- // controller, client and renderer, in that order.
- void OfferToHandlers(const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info);
-
- // Returns true if |input_event| was consumed by the client.
- bool OfferToClient(const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info);
-
- // Returns true if |input_event| was successfully sent to the renderer
- // as an async IPC Message.
- bool OfferToRenderer(const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info,
- InputEventDispatchType dispatch_type);
-
- // IPC message handlers
- void OnInputEventAck(const InputEventAck& ack);
- void OnDidOverscroll(const ui::DidOverscrollParams& params);
- void OnMsgMoveCaretAck();
- void OnSelectMessageAck();
- void OnHasTouchEventHandlers(bool has_handlers);
- void OnSetTouchAction(cc::TouchAction touch_action);
- void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action,
- uint32_t unique_touch_event_id,
- InputEventAckState ack_result);
- void OnDidStopFlinging();
- void OnDidStartScrollingViewport();
-
- // Note: This function may result in |this| being deleted, and as such
- // should be the last method called in any internal chain of event handling.
- void ProcessInputEventAck(blink::WebInputEvent::Type event_type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency_info,
- uint32_t unique_touch_event_id);
-
- // Dispatches the ack'ed event to |ack_handler_|.
- void ProcessKeyboardAck(blink::WebInputEvent::Type type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency);
-
- // Forwards a valid |next_mouse_move_| if |type| is MouseMove.
- void ProcessMouseAck(blink::WebInputEvent::Type type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency);
-
- // Dispatches the ack'ed event to |ack_handler_|, forwarding queued events
- // from |coalesced_mouse_wheel_events_|.
- void ProcessWheelAck(InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency);
-
- // Forwards the event ack to |gesture_event_queue|, potentially triggering
- // dispatch of queued gesture events.
- void ProcessGestureAck(blink::WebInputEvent::Type type,
- InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency);
-
- // Forwards the event ack to |touch_event_queue_|, potentially triggering
- // dispatch of queued touch events, or the creation of gesture events.
- void ProcessTouchAck(InputEventAckSource ack_source,
- InputEventAckState ack_result,
- const ui::LatencyInfo& latency,
- uint32_t unique_touch_event_id);
-
- // Called when a touch timeout-affecting bit has changed, in turn toggling the
- // touch ack timeout feature of the |touch_event_queue_| as appropriate. Input
- // to that determination includes current view properties and the allowed
- // touch action. Note that this will only affect platforms that have a
- // non-zero touch timeout configuration.
- void UpdateTouchAckTimeoutEnabled();
-
- IPC::Sender* sender_;
- InputRouterClient* client_;
- InputDispositionHandler* disposition_handler_;
- int routing_id_;
- int frame_tree_node_id_;
-
- // (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK
- // or MoveRangeSelectionExtent_ACK.
- bool select_message_pending_;
-
- // Queue of pending select messages to send after receiving the next select
- // message ack.
- base::circular_deque<std::unique_ptr<IPC::Message>> pending_select_messages_;
-
- // True while waiting for MoveCaret_ACK.
- bool move_caret_pending_;
-
- // The next MoveCaret to send, if any.
- std::unique_ptr<IPC::Message> next_move_caret_;
-
- // A queue of the mouse move events sent to the renderer. Similar
- // to |key_queue_|.
- using MouseEventQueue = base::circular_deque<MouseEventWithLatencyInfo>;
- MouseEventQueue mouse_event_queue_;
-
- // A queue of keyboard events. We can't trust data from the renderer so we
- // stuff key events into a queue and pop them out on ACK, feeding our copy
- // back to whatever unhandled handler instead of the returned version.
- using KeyQueue = base::circular_deque<NativeWebKeyboardEventWithLatencyInfo>;
- KeyQueue key_queue_;
-
- // Whether there are any active flings in the renderer. As the fling
- // end notification is asynchronous, we use a count rather than a boolean
- // to avoid races in bookkeeping when starting a new fling.
- int active_renderer_fling_count_;
-
- // Whether the TouchScrollStarted event has been sent for the current
- // gesture scroll yet.
- bool touch_scroll_started_sent_;
-
- bool wheel_scroll_latching_enabled_;
-
- MouseWheelEventQueue wheel_event_queue_;
- std::unique_ptr<PassthroughTouchEventQueue> touch_event_queue_;
- GestureEventQueue gesture_event_queue_;
- TouchActionFilter touch_action_filter_;
- InputEventStreamValidator input_stream_validator_;
- InputEventStreamValidator output_stream_validator_;
-
- float device_scale_factor_;
-
- // Last touch position relative to screen. Used to compute movementX/Y.
- std::map<int, gfx::Point> global_touch_position_;
-
- gfx::Vector2dF current_fling_velocity_;
-
- DISALLOW_COPY_AND_ASSIGN(LegacyInputRouterImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_LEGACY_INPUT_ROUTER_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc b/chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc
deleted file mode 100644
index 97d32e7e5fc..00000000000
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc
+++ /dev/null
@@ -1,407 +0,0 @@
-// Copyright 2014 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 <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "content/browser/renderer_host/input/input_disposition_handler.h"
-#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/common/content_features.h"
-#include "ipc/ipc_sender.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-#include "ui/events/base_event_utils.h"
-#include "ui/events/blink/web_input_event_traits.h"
-#include "ui/gfx/geometry/vector2d_f.h"
-
-using base::TimeDelta;
-using blink::WebGestureEvent;
-using blink::WebInputEvent;
-using blink::WebTouchEvent;
-using blink::WebTouchPoint;
-
-namespace content {
-
-namespace {
-
-class NullInputDispositionHandler : public InputDispositionHandler {
- public:
- NullInputDispositionHandler() : ack_count_(0) {}
- ~NullInputDispositionHandler() override {}
-
- // InputDispositionHandler
- void OnKeyboardEventAck(const NativeWebKeyboardEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override {
- ++ack_count_;
- }
- void OnMouseEventAck(const MouseEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override {
- ++ack_count_;
- }
- void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override {
- ++ack_count_;
- }
- void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override {
- ++ack_count_;
- }
- void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
- InputEventAckSource ack_source,
- InputEventAckState ack_result) override {
- ++ack_count_;
- }
- void OnUnexpectedEventAck(UnexpectedEventAckType type) override {
- ++ack_count_;
- }
-
- size_t GetAndResetAckCount() {
- size_t ack_count = ack_count_;
- ack_count_ = 0;
- return ack_count;
- }
-
- size_t ack_count() const { return ack_count_; }
-
- private:
- size_t ack_count_;
-};
-
-class NullInputRouterClient : public InputRouterClient {
- public:
- NullInputRouterClient() {}
- ~NullInputRouterClient() override {}
-
- // InputRouterClient
- InputEventAckState FilterInputEvent(
- const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) override {
- return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- }
- void IncrementInFlightEventCount() override {}
- void DecrementInFlightEventCount(InputEventAckSource ack_source) override {}
- void OnHasTouchEventHandlers(bool has_handlers) override {}
- void DidOverscroll(const ui::DidOverscrollParams& params) override {}
- void OnSetWhiteListedTouchAction(
- cc::TouchAction white_listed_touch_action) override {}
- void DidStopFlinging() override {}
- void DidStartScrollingViewport() override {}
- void ForwardWheelEventWithLatencyInfo(
- const blink::WebMouseWheelEvent& event,
- const ui::LatencyInfo& latency_info) override {}
- void ForwardGestureEventWithLatencyInfo(
- const blink::WebGestureEvent& event,
- const ui::LatencyInfo& latency_info) override {}
- void SetNeedsBeginFrameForFlingProgress() override {}
-};
-
-class NullIPCSender : public IPC::Sender {
- public:
- NullIPCSender() : sent_count_(0) {}
- ~NullIPCSender() override {}
-
- bool Send(IPC::Message* message) override {
- delete message;
- ++sent_count_;
- return true;
- }
-
- size_t GetAndResetSentEventCount() {
- size_t message_count = sent_count_;
- sent_count_ = 0;
- return message_count;
- }
-
- bool HasMessages() const { return sent_count_ > 0; }
-
- private:
- size_t sent_count_;
-};
-
-typedef std::vector<WebGestureEvent> Gestures;
-Gestures BuildScrollSequence(size_t steps,
- const gfx::Vector2dF& origin,
- const gfx::Vector2dF& distance) {
- Gestures gestures;
- const gfx::Vector2dF delta = ScaleVector2d(distance, 1.f / steps);
-
- WebGestureEvent gesture(WebInputEvent::kGestureScrollBegin,
- WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
- gesture.SetPositionInWidget(gfx::PointF(origin.x(), origin.y()));
- gestures.push_back(gesture);
-
- gesture.SetType(WebInputEvent::kGestureScrollUpdate);
- gesture.data.scroll_update.delta_x = delta.x();
- gesture.data.scroll_update.delta_y = delta.y();
- for (size_t i = 0; i < steps; ++i) {
- gesture.SetPositionInWidget(gesture.PositionInWidget() + delta);
- gestures.push_back(gesture);
- }
-
- gesture.SetType(WebInputEvent::kGestureScrollEnd);
- gestures.push_back(gesture);
- return gestures;
-}
-
-typedef std::vector<WebTouchEvent> Touches;
-Touches BuildTouchSequence(size_t steps,
- const gfx::Vector2dF& origin,
- const gfx::Vector2dF& distance) {
- Touches touches;
- const gfx::Vector2dF delta = ScaleVector2d(distance, 1.f / steps);
-
- WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
- touch.touches_length = 1;
- touch.touches[0].id = 0;
- touch.touches[0].state = WebTouchPoint::kStatePressed;
- touch.touches[0].SetPositionInWidget(origin.x(), origin.y());
- touch.touches[0].SetPositionInScreen(origin.x(), origin.y());
- touches.push_back(touch);
-
- touch.SetType(WebInputEvent::kTouchMove);
- touch.touches[0].state = WebTouchPoint::kStateMoved;
- for (size_t i = 0; i < steps; ++i) {
- touch.touches[0].SetPositionInWidget(
- touch.touches[0].PositionInWidget().x + delta.x(),
- touch.touches[0].PositionInWidget().y + delta.y());
- touch.touches[0].SetPositionInScreen(
- touch.touches[0].PositionInScreen().x + delta.x(),
- touch.touches[0].PositionInScreen().y + delta.y());
- touches.push_back(touch);
- }
-
- touch.SetType(WebInputEvent::kTouchEnd);
- touch.touches[0].state = WebTouchPoint::kStateReleased;
- touches.push_back(touch);
- return touches;
-}
-
-class InputEventTimer {
- public:
- InputEventTimer(const char* test_name, int64_t event_count)
- : test_name_(test_name),
- event_count_(event_count),
- start_(base::TimeTicks::Now()) {}
-
- ~InputEventTimer() {
- perf_test::PrintResult(
- "avg_time_per_event", "", test_name_,
- static_cast<size_t>(((base::TimeTicks::Now() - start_) / event_count_)
- .InMicroseconds()),
- "us", true);
- }
-
- private:
- const char* test_name_;
- int64_t event_count_;
- base::TimeTicks start_;
- DISALLOW_COPY_AND_ASSIGN(InputEventTimer);
-};
-
-bool ShouldBlockEventStream(const blink::WebInputEvent& event) {
- return ui::WebInputEventTraits::ShouldBlockEventStream(
- event,
- base::FeatureList::IsEnabled(features::kTouchpadAndWheelScrollLatching));
-}
-
-} // namespace
-
-class LegacyInputRouterImplPerfTest : public testing::Test {
- public:
- LegacyInputRouterImplPerfTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI),
- last_input_id_(0) {}
- ~LegacyInputRouterImplPerfTest() override {}
-
- protected:
- // testing::Test
- void SetUp() override {
- sender_.reset(new NullIPCSender());
- client_.reset(new NullInputRouterClient());
- disposition_handler_.reset(new NullInputDispositionHandler());
- input_router_.reset(new LegacyInputRouterImpl(
- sender_.get(), client_.get(), disposition_handler_.get(),
- MSG_ROUTING_NONE, InputRouter::Config()));
- }
-
- void TearDown() override {
- base::RunLoop().RunUntilIdle();
-
- input_router_.reset();
- disposition_handler_.reset();
- client_.reset();
- sender_.reset();
- }
-
- void SendEvent(const WebGestureEvent& gesture,
- const ui::LatencyInfo& latency) {
- input_router_->SendGestureEvent(
- GestureEventWithLatencyInfo(gesture, latency));
- }
-
- void SendEvent(const WebTouchEvent& touch, const ui::LatencyInfo& latency) {
- input_router_->SendTouchEvent(TouchEventWithLatencyInfo(touch, latency));
- }
-
- void SendEventAckIfNecessary(const blink::WebInputEvent& event,
- InputEventAckState ack_result) {
- if (!ShouldBlockEventStream(event))
- return;
- InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, event.GetType(),
- ack_result);
- InputHostMsg_HandleInputEvent_ACK response(0, ack);
- input_router_->OnMessageReceived(response);
- }
-
- void OnHasTouchEventHandlers(bool has_handlers) {
- input_router_->OnMessageReceived(
- ViewHostMsg_HasTouchEventHandlers(0, has_handlers));
- }
-
- size_t GetAndResetSentEventCount() {
- return sender_->GetAndResetSentEventCount();
- }
-
- size_t GetAndResetAckCount() {
- return disposition_handler_->GetAndResetAckCount();
- }
-
- size_t AckCount() const { return disposition_handler_->ack_count(); }
-
- int64_t NextLatencyID() { return ++last_input_id_; }
-
- ui::LatencyInfo CreateLatencyInfo() {
- ui::LatencyInfo latency;
- latency.AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, 1, 0);
- latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 1,
- NextLatencyID());
- return latency;
- }
-
- template <typename EventType>
- void SimulateEventSequence(const char* test_name,
- const std::vector<EventType>& events,
- bool ack_delay,
- size_t iterations) {
- OnHasTouchEventHandlers(true);
-
- const size_t event_count = events.size();
- const size_t total_event_count = event_count * iterations;
-
- InputEventTimer timer(test_name, total_event_count);
- while (iterations--) {
- size_t i = 0, ack_i = 0;
- if (ack_delay)
- SendEvent(events[i++], CreateLatencyInfo());
-
- for (; i < event_count; ++i, ++ack_i) {
- SendEvent(events[i], CreateLatencyInfo());
- SendEventAckIfNecessary(events[ack_i], INPUT_EVENT_ACK_STATE_CONSUMED);
- }
-
- if (ack_delay)
- SendEventAckIfNecessary(events.back(), INPUT_EVENT_ACK_STATE_CONSUMED);
-
- EXPECT_EQ(event_count, GetAndResetSentEventCount());
- EXPECT_EQ(event_count, GetAndResetAckCount());
- }
- }
-
- void SimulateTouchAndScrollEventSequence(const char* test_name,
- size_t steps,
- const gfx::Vector2dF& origin,
- const gfx::Vector2dF& distance,
- size_t iterations) {
- OnHasTouchEventHandlers(true);
-
- Gestures gestures = BuildScrollSequence(steps, origin, distance);
- Touches touches = BuildTouchSequence(steps, origin, distance);
- ASSERT_EQ(touches.size(), gestures.size());
-
- const size_t event_count = gestures.size();
- const size_t total_event_count = event_count * iterations * 2;
-
- InputEventTimer timer(test_name, total_event_count);
- while (iterations--) {
- for (size_t i = 0; i < event_count; ++i) {
- SendEvent(touches[i], CreateLatencyInfo());
- // Touches may not be forwarded after the scroll sequence has begun, so
- // only ack if necessary.
- if (!AckCount()) {
- SendEventAckIfNecessary(touches[i],
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- }
-
- SendEvent(gestures[i], CreateLatencyInfo());
- SendEventAckIfNecessary(gestures[i], INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(2U, GetAndResetAckCount());
- }
- }
- }
-
- private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- int64_t last_input_id_;
- std::unique_ptr<NullIPCSender> sender_;
- std::unique_ptr<NullInputRouterClient> client_;
- std::unique_ptr<NullInputDispositionHandler> disposition_handler_;
- std::unique_ptr<LegacyInputRouterImpl> input_router_;
-};
-
-const size_t kDefaultSteps(100);
-const size_t kDefaultIterations(100);
-const gfx::Vector2dF kDefaultOrigin(100, 100);
-const gfx::Vector2dF kDefaultDistance(500, 500);
-
-TEST_F(LegacyInputRouterImplPerfTest, TouchSwipe) {
- SimulateEventSequence(
- "TouchSwipe ",
- BuildTouchSequence(kDefaultSteps, kDefaultOrigin, kDefaultDistance),
- false, kDefaultIterations);
-}
-
-TEST_F(LegacyInputRouterImplPerfTest, TouchSwipeDelayedAck) {
- SimulateEventSequence(
- "TouchSwipeDelayedAck ",
- BuildTouchSequence(kDefaultSteps, kDefaultOrigin, kDefaultDistance), true,
- kDefaultIterations);
-}
-
-TEST_F(LegacyInputRouterImplPerfTest, GestureScroll) {
- SimulateEventSequence(
- "GestureScroll ",
- BuildScrollSequence(kDefaultSteps, kDefaultOrigin, kDefaultDistance),
- false, kDefaultIterations);
-}
-
-TEST_F(LegacyInputRouterImplPerfTest, GestureScrollDelayedAck) {
- SimulateEventSequence(
- "GestureScrollDelayedAck ",
- BuildScrollSequence(kDefaultSteps, kDefaultOrigin, kDefaultDistance),
- true, kDefaultIterations);
-}
-
-TEST_F(LegacyInputRouterImplPerfTest, TouchSwipeToGestureScroll) {
- SimulateTouchAndScrollEventSequence("TouchSwipeToGestureScroll ",
- kDefaultSteps, kDefaultOrigin,
- kDefaultDistance, kDefaultIterations);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
deleted file mode 100644
index baa4ff3b31c..00000000000
--- a/chromium/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
+++ /dev/null
@@ -1,2350 +0,0 @@
-// Copyright 2013 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/renderer_host/input/legacy_input_router_impl.h"
-
-#include <math.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <tuple>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "cc/input/touch_action.h"
-#include "content/browser/renderer_host/input/gesture_event_queue.h"
-#include "content/browser/renderer_host/input/input_router_client.h"
-#include "content/browser/renderer_host/input/mock_input_disposition_handler.h"
-#include "content/browser/renderer_host/input/mock_input_router_client.h"
-#include "content/common/content_constants_internal.h"
-#include "content/common/edit_command.h"
-#include "content/common/input/synthetic_web_input_event_builders.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/base_event_utils.h"
-#include "ui/events/blink/blink_features.h"
-#include "ui/events/blink/web_input_event_traits.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-#if defined(USE_AURA)
-#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/events/event.h"
-#endif
-
-using blink::WebGestureDevice;
-using blink::WebGestureEvent;
-using blink::WebKeyboardEvent;
-using blink::WebInputEvent;
-using blink::WebMouseEvent;
-using blink::WebMouseWheelEvent;
-using blink::WebTouchEvent;
-using blink::WebTouchPoint;
-using ui::DidOverscrollParams;
-using ui::WebInputEventTraits;
-
-namespace content {
-
-namespace {
-
-bool ShouldBlockEventStream(const blink::WebInputEvent& event) {
- return ui::WebInputEventTraits::ShouldBlockEventStream(
- event,
- base::FeatureList::IsEnabled(features::kTouchpadAndWheelScrollLatching));
-}
-
-const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) {
- base::PickleIterator iter(message);
- const char* data;
- int data_length;
- if (!iter.ReadData(&data, &data_length))
- return nullptr;
- return reinterpret_cast<const WebInputEvent*>(data);
-}
-
-WebInputEvent& GetEventWithType(WebInputEvent::Type type) {
- WebInputEvent* event = nullptr;
- if (WebInputEvent::IsMouseEventType(type)) {
- static WebMouseEvent mouse;
- event = &mouse;
- } else if (WebInputEvent::IsTouchEventType(type)) {
- static WebTouchEvent touch;
- event = &touch;
- } else if (WebInputEvent::IsKeyboardEventType(type)) {
- static WebKeyboardEvent key;
- event = &key;
- } else if (WebInputEvent::IsGestureEventType(type)) {
- static WebGestureEvent gesture;
- event = &gesture;
- } else if (type == WebInputEvent::kMouseWheel) {
- static WebMouseWheelEvent wheel;
- event = &wheel;
- }
- CHECK(event);
- event->SetType(type);
- return *event;
-}
-
-template <typename MSG_T, typename ARG_T1>
-void ExpectIPCMessageWithArg1(const IPC::Message* msg, const ARG_T1& arg1) {
- ASSERT_EQ(static_cast<uint32_t>(MSG_T::ID), msg->type());
- typename MSG_T::Schema::Param param;
- ASSERT_TRUE(MSG_T::Read(msg, &param));
- EXPECT_EQ(arg1, std::get<0>(param));
-}
-
-template <typename MSG_T, typename ARG_T1, typename ARG_T2>
-void ExpectIPCMessageWithArg2(const IPC::Message* msg,
- const ARG_T1& arg1,
- const ARG_T2& arg2) {
- ASSERT_EQ(static_cast<uint32_t>(MSG_T::ID), msg->type());
- typename MSG_T::Schema::Param param;
- ASSERT_TRUE(MSG_T::Read(msg, &param));
- EXPECT_EQ(arg1, std::get<0>(param));
- EXPECT_EQ(arg2, std::get<1>(param));
-}
-
-enum WheelScrollingMode {
- kWheelScrollingModeNone,
- kWheelScrollLatching,
- kAsyncWheelEvents,
-};
-
-} // namespace
-
-class LegacyInputRouterImplTest : public testing::Test {
- public:
- LegacyInputRouterImplTest(
- WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
- : wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
- kWheelScrollingModeNone) {
- if (wheel_scrolling_mode == kAsyncWheelEvents) {
- feature_list_.InitWithFeatures({features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents},
- {});
- } else if (wheel_scrolling_mode == kWheelScrollLatching) {
- feature_list_.InitWithFeatures(
- {features::kTouchpadAndWheelScrollLatching},
- {features::kAsyncWheelEvents});
- } else if (wheel_scrolling_mode == kWheelScrollingModeNone) {
- feature_list_.InitWithFeatures({},
- {features::kTouchpadAndWheelScrollLatching,
- features::kAsyncWheelEvents});
- }
-
- vsync_feature_list_.InitAndEnableFeature(
- features::kVsyncAlignedInputEvents);
- }
-
- ~LegacyInputRouterImplTest() override {}
-
- protected:
- // testing::Test
- void SetUp() override {
- browser_context_.reset(new TestBrowserContext());
- process_.reset(new MockRenderProcessHost(browser_context_.get()));
- client_.reset(new MockInputRouterClient());
- disposition_handler_.reset(new MockInputDispositionHandler());
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- command_line->AppendSwitch(switches::kValidateInputEventStream);
- input_router_.reset(new LegacyInputRouterImpl(process_.get(), client_.get(),
- disposition_handler_.get(),
- MSG_ROUTING_NONE, config_));
- client_->set_input_router(input_router());
- disposition_handler_->set_input_router(input_router());
- }
-
- void TearDown() override {
- // Process all pending tasks to avoid leaks.
- base::RunLoop().RunUntilIdle();
-
- input_router_.reset();
- client_.reset();
- process_.reset();
- browser_context_.reset();
- }
-
- void SetUpForTouchAckTimeoutTest(int desktop_timeout_ms,
- int mobile_timeout_ms) {
- config_.touch_config.desktop_touch_ack_timeout_delay =
- base::TimeDelta::FromMilliseconds(desktop_timeout_ms);
- config_.touch_config.mobile_touch_ack_timeout_delay =
- base::TimeDelta::FromMilliseconds(mobile_timeout_ms);
- config_.touch_config.touch_ack_timeout_supported = true;
- TearDown();
- SetUp();
- input_router()->NotifySiteIsMobileOptimized(false);
- }
-
- void SimulateKeyboardEvent(WebInputEvent::Type type) {
- NativeWebKeyboardEventWithLatencyInfo key_event(
- type, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()), ui::LatencyInfo());
- input_router_->SendKeyboardEvent(key_event);
- }
-
- void SimulateWheelEvent(float x,
- float y,
- float dX,
- float dY,
- int modifiers,
- bool precise) {
- input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
- SyntheticWebMouseWheelEventBuilder::Build(x, y, dX, dY, modifiers,
- precise)));
- }
-
- void SimulateWheelEventWithPhase(float x,
- float y,
- float dX,
- float dY,
- int modifiers,
- bool precise,
- WebMouseWheelEvent::Phase phase) {
- WebMouseWheelEvent wheel_event = SyntheticWebMouseWheelEventBuilder::Build(
- x, y, dX, dY, modifiers, precise);
- wheel_event.phase = phase;
- input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(wheel_event));
- }
-
- void SimulateWheelEventPossiblyIncludingPhase(
- bool ignore_phase,
- float x,
- float y,
- float dX,
- float dY,
- int modifiers,
- bool precise,
- WebMouseWheelEvent::Phase phase) {
- if (ignore_phase)
- SimulateWheelEvent(x, y, dX, dY, modifiers, precise);
- else
- SimulateWheelEventWithPhase(x, y, dX, dY, modifiers, precise, phase);
- }
-
- void SimulateMouseEvent(WebInputEvent::Type type, int x, int y) {
- input_router_->SendMouseEvent(MouseEventWithLatencyInfo(
- SyntheticWebMouseEventBuilder::Build(type, x, y, 0)));
- }
-
- void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) {
- input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo(
- SyntheticWebMouseWheelEventBuilder::Build(phase)));
- }
-
- void SimulateGestureEvent(WebGestureEvent gesture) {
- if (gesture.GetType() == WebInputEvent::kGestureScrollBegin &&
- gesture.SourceDevice() == blink::kWebGestureDeviceTouchscreen &&
- !gesture.data.scroll_begin.delta_x_hint &&
- !gesture.data.scroll_begin.delta_y_hint) {
- // Ensure non-zero scroll-begin offset-hint to make the event sane,
- // prevents unexpected filtering at TouchActionFilter.
- gesture.data.scroll_begin.delta_y_hint = 2.f;
- } else if (gesture.GetType() == WebInputEvent::kGestureFlingStart &&
- gesture.SourceDevice() == blink::kWebGestureDeviceTouchscreen &&
- !gesture.data.fling_start.velocity_x &&
- !gesture.data.fling_start.velocity_y) {
- // Ensure non-zero touchscreen fling velocities, as the router will
- // validate against such.
- gesture.data.fling_start.velocity_x = 5.f;
- }
-
- input_router_->SendGestureEvent(GestureEventWithLatencyInfo(gesture));
- }
-
- void SimulateGestureEvent(WebInputEvent::Type type,
- WebGestureDevice source_device) {
- SimulateGestureEvent(
- SyntheticWebGestureEventBuilder::Build(type, source_device));
- }
-
- void SimulateGestureScrollUpdateEvent(float dX,
- float dY,
- int modifiers,
- WebGestureDevice source_device) {
- SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollUpdate(
- dX, dY, modifiers, source_device));
- }
-
- void SimulateGesturePinchUpdateEvent(float scale,
- float anchor_x,
- float anchor_y,
- int modifiers,
- WebGestureDevice source_device) {
- SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildPinchUpdate(
- scale, anchor_x, anchor_y, modifiers, source_device));
- }
-
- void SimulateGestureFlingStartEvent(float velocity_x,
- float velocity_y,
- WebGestureDevice source_device) {
- SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildFling(
- velocity_x, velocity_y, source_device));
- }
-
- void SetTouchTimestamp(base::TimeTicks timestamp) {
- touch_event_.SetTimestamp(timestamp);
- }
-
- uint32_t SendTouchEvent() {
- uint32_t touch_event_id = touch_event_.unique_touch_event_id;
- input_router_->SendTouchEvent(TouchEventWithLatencyInfo(touch_event_));
- touch_event_.ResetPoints();
- return touch_event_id;
- }
-
- int PressTouchPoint(int x, int y) { return touch_event_.PressPoint(x, y); }
-
- void MoveTouchPoint(int index, int x, int y) {
- touch_event_.MovePoint(index, x, y);
- }
-
- void ReleaseTouchPoint(int index) { touch_event_.ReleasePoint(index); }
-
- void CancelTouchPoint(int index) { touch_event_.CancelPoint(index); }
-
- void SendInputEventACK(blink::WebInputEvent::Type type,
- InputEventAckState ack_result) {
- DCHECK(!WebInputEvent::IsTouchEventType(type));
- InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result);
- input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
- }
-
- void SendScrollBeginAckIfNeeded(InputEventAckState ack_result) {
- if (wheel_scroll_latching_enabled_) {
- // GSB events are blocking, send the ack.
- SendInputEventACK(WebInputEvent::kGestureScrollBegin, ack_result);
- }
- }
-
- void SendTouchEventACK(blink::WebInputEvent::Type type,
- InputEventAckState ack_result,
- uint32_t touch_event_id) {
- DCHECK(WebInputEvent::IsTouchEventType(type));
- InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result,
- touch_event_id);
- input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
- }
-
- LegacyInputRouterImpl* input_router() const { return input_router_.get(); }
-
- bool TouchEventQueueEmpty() const {
- return input_router()->touch_event_queue_->Empty();
- }
-
- bool TouchEventTimeoutEnabled() const {
- return input_router()->touch_event_queue_->IsAckTimeoutEnabled();
- }
-
- bool HasPendingEvents() const { return input_router_->HasPendingEvents(); }
-
- void OnHasTouchEventHandlers(bool has_handlers) {
- input_router_->OnMessageReceived(
- ViewHostMsg_HasTouchEventHandlers(0, has_handlers));
- }
-
- void OnSetTouchAction(cc::TouchAction touch_action) {
- input_router_->OnMessageReceived(
- InputHostMsg_SetTouchAction(0, touch_action));
- }
-
- void OnSetWhiteListedTouchAction(cc::TouchAction white_listed_touch_action,
- uint32_t unique_touch_event_id,
- InputEventAckState ack_result) {
- input_router_->OnMessageReceived(InputHostMsg_SetWhiteListedTouchAction(
- 0, white_listed_touch_action, unique_touch_event_id, ack_result));
- }
-
- size_t GetSentMessageCountAndResetSink() {
- size_t count = process_->sink().message_count();
- process_->sink().ClearMessages();
- return count;
- }
-
- static void RunTasksAndWait(base::TimeDelta delay) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), delay);
- base::RunLoop().Run();
- }
-
- void UnhandledWheelEvent();
-
- void OverscrollDispatch();
-
- InputRouter::Config config_;
- std::unique_ptr<MockRenderProcessHost> process_;
- std::unique_ptr<MockInputRouterClient> client_;
- std::unique_ptr<MockInputDispositionHandler> disposition_handler_;
- std::unique_ptr<LegacyInputRouterImpl> input_router_;
- bool wheel_scroll_latching_enabled_;
-
- private:
- TestBrowserThreadBundle thread_bundle_;
- SyntheticWebTouchEvent touch_event_;
-
- base::test::ScopedFeatureList vsync_feature_list_;
- base::test::ScopedFeatureList feature_list_;
-
- std::unique_ptr<TestBrowserContext> browser_context_;
-};
-
-class LegacyInputRouterImplWheelScrollLatchingDisabledTest
- : public LegacyInputRouterImplTest {
- public:
- LegacyInputRouterImplWheelScrollLatchingDisabledTest()
- : LegacyInputRouterImplTest(kWheelScrollingModeNone) {}
-};
-
-class LegacyInputRouterImplAsyncWheelEventEnabledTest
- : public LegacyInputRouterImplTest {
- public:
- LegacyInputRouterImplAsyncWheelEventEnabledTest()
- : LegacyInputRouterImplTest(kAsyncWheelEvents) {}
-};
-
-TEST_F(LegacyInputRouterImplTest, CoalescesRangeSelection) {
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0), gfx::Point(1, 2), gfx::Point(3, 4));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Send two more messages without acking.
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(5, 6), gfx::Point(7, 8))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(9, 10), gfx::Point(11, 12))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- // Now ack the first message.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify that the two messages are coalesced into one message.
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0), gfx::Point(9, 10), gfx::Point(11, 12));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Acking the coalesced msg should not send any more msg.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-}
-
-TEST_F(LegacyInputRouterImplTest, CoalescesMoveRangeSelectionExtent) {
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(1, 2))));
- ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
- process_->sink().GetMessageAt(0), gfx::Point(1, 2));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Send two more messages without acking.
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(3, 4))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- // Now ack the first message.
- {
- std::unique_ptr<IPC::Message> response(
- new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify that the two messages are coalesced into one message.
- ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
- process_->sink().GetMessageAt(0), gfx::Point(5, 6));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Acking the coalesced msg should not send any more msg.
- {
- std::unique_ptr<IPC::Message> response(
- new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-}
-
-TEST_F(LegacyInputRouterImplTest,
- InterleaveSelectRangeAndMoveRangeSelectionExtent) {
- // Send first message: SelectRange.
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0), gfx::Point(1, 2), gfx::Point(3, 4));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Send second message: MoveRangeSelectionExtent.
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- // Send third message: SelectRange.
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(7, 8), gfx::Point(9, 10))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- // Ack the messages and verify that they're not coalesced and that they're
- // in correct order.
-
- // Ack the first message.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
- process_->sink().GetMessageAt(0), gfx::Point(5, 6));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Ack the second message.
- {
- std::unique_ptr<IPC::Message> response(
- new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0), gfx::Point(7, 8), gfx::Point(9, 10));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Ack the third message.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-}
-
-TEST_F(LegacyInputRouterImplTest,
- CoalescesInterleavedSelectRangeAndMoveRangeSelectionExtent) {
- // Send interleaved SelectRange and MoveRangeSelectionExtent messages. They
- // should be coalesced as shown by the arrows.
- // > SelectRange
- // MoveRangeSelectionExtent
- // MoveRangeSelectionExtent
- // > MoveRangeSelectionExtent
- // SelectRange
- // > SelectRange
- // > MoveRangeSelectionExtent
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0), gfx::Point(1, 2), gfx::Point(3, 4));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(7, 8))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(9, 10))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(11, 12), gfx::Point(13, 14))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_SelectRange(0, gfx::Point(15, 16), gfx::Point(17, 18))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(19, 20))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- // Ack the first message.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify that the three MoveRangeSelectionExtent messages are coalesced
- // into one message.
- ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
- process_->sink().GetMessageAt(0), gfx::Point(9, 10));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Ack the second message.
- {
- std::unique_ptr<IPC::Message> response(
- new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify that the two SelectRange messages are coalesced into one message.
- ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
- process_->sink().GetMessageAt(0), gfx::Point(15, 16), gfx::Point(17, 18));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Ack the third message.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify the fourth message.
- ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
- process_->sink().GetMessageAt(0), gfx::Point(19, 20));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Ack the fourth message.
- {
- std::unique_ptr<IPC::Message> response(
- new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-}
-
-TEST_F(LegacyInputRouterImplTest, CoalescesCaretMove) {
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveCaret(0, gfx::Point(1, 2))));
- ExpectIPCMessageWithArg1<InputMsg_MoveCaret>(process_->sink().GetMessageAt(0),
- gfx::Point(1, 2));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Send two more messages without acking.
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveCaret(0, gfx::Point(5, 6))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- input_router_->SendInput(std::unique_ptr<IPC::Message>(
- new InputMsg_MoveCaret(0, gfx::Point(9, 10))));
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- // Now ack the first message.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_MoveCaret_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
-
- // Verify that the two messages are coalesced into one message.
- ExpectIPCMessageWithArg1<InputMsg_MoveCaret>(process_->sink().GetMessageAt(0),
- gfx::Point(9, 10));
- EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
-
- // Acking the coalesced msg should not send any more msg.
- {
- std::unique_ptr<IPC::Message> response(new InputHostMsg_MoveCaret_ACK(0));
- input_router_->OnMessageReceived(*response);
- }
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-}
-
-TEST_F(LegacyInputRouterImplTest, HandledInputEvent) {
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
- // Make sure no input event is sent to the renderer.
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
-
- // OnKeyboardEventAck should be triggered without actual ack.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-}
-
-TEST_F(LegacyInputRouterImplTest, ClientCanceledKeyboardEvent) {
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
-
- // Simulate a keyboard event that has no consumer.
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
- // Make sure no input event is sent to the renderer.
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-
- // Simulate a keyboard event that should be dropped.
- client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
- // Make sure no input event is sent to the renderer, and no ack is sent.
- EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
-}
-
-TEST_F(LegacyInputRouterImplTest, NoncorrespondingKeyEvents) {
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
- SendInputEventACK(WebInputEvent::kKeyUp, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(disposition_handler_->unexpected_event_ack_called());
-}
-
-// Tests ported from RenderWidgetHostTest -------------------------------------
-
-TEST_F(LegacyInputRouterImplTest, HandleKeyEventsWeSent) {
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kRawKeyDown,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(WebInputEvent::kRawKeyDown,
- disposition_handler_->acked_keyboard_event().GetType());
-}
-
-TEST_F(LegacyInputRouterImplTest, IgnoreKeyEventsWeDidntSend) {
- // Send a simulated, unrequested key response. We should ignore this.
- SendInputEventACK(WebInputEvent::kRawKeyDown,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
-}
-
-TEST_F(LegacyInputRouterImplTest, CoalescesWheelEvents) {
- // Simulate wheel events.
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 0, -5, 0, false,
- WebMouseWheelEvent::kPhaseBegan); // sent directly
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged); // enqueued
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 8, -6, 0, false,
- WebMouseWheelEvent::kPhaseChanged); // coalesced into previous event
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 9, -7, 1, false,
- WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
- SimulateWheelEventPossiblyIncludingPhase(
- !wheel_scroll_latching_enabled_, 0, 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged); // enqueued, different modifiers
- // Explicitly verify that PhaseEnd isn't coalesced to avoid bugs like
- // https://crbug.com/154740.
- SimulateWheelEventWithPhase(WebMouseWheelEvent::kPhaseEnded); // enqueued
-
- // Check that only the first event was sent.
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- const WebInputEvent* input_event =
- GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
- ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
- const WebMouseWheelEvent* wheel_event =
- static_cast<const WebMouseWheelEvent*>(input_event);
- EXPECT_EQ(0, wheel_event->delta_x);
- EXPECT_EQ(-5, wheel_event->delta_y);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Check that the ACK sends the second message immediately.
- SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- // The coalesced events can queue up a delayed ack
- // so that additional input events can be processed before
- // we turn off coalescing.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
- ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
- wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
- EXPECT_EQ(8, wheel_event->delta_x);
- EXPECT_EQ(-10 + -6, wheel_event->delta_y); // coalesced
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Ack the second event (which had the third coalesced into it).
- SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
- ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
- wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
- EXPECT_EQ(9, wheel_event->delta_x);
- EXPECT_EQ(-7, wheel_event->delta_y);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Ack the fourth event.
- SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
- ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
- wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
- EXPECT_EQ(0, wheel_event->delta_x);
- EXPECT_EQ(-10, wheel_event->delta_y);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Ack the fifth event.
- SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
- ASSERT_EQ(WebInputEvent::kMouseWheel, input_event->GetType());
- wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
- EXPECT_EQ(0, wheel_event->delta_x);
- EXPECT_EQ(0, wheel_event->delta_y);
- EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->phase);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // After the final ack, the queue should be empty.
- SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-}
-
-// Tests that touch-events are sent properly.
-TEST_F(LegacyInputRouterImplTest, TouchEventQueue) {
- OnHasTouchEventHandlers(true);
-
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id = SendTouchEvent();
- EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_FALSE(TouchEventQueueEmpty());
-
- // The second touch should be sent right away.
- MoveTouchPoint(0, 5, 5);
- uint32_t touch_move_event_id = SendTouchEvent();
- EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_FALSE(TouchEventQueueEmpty());
-
- // Receive an ACK for the first touch-event.
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id);
- EXPECT_FALSE(TouchEventQueueEmpty());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(WebInputEvent::kTouchStart,
- disposition_handler_->acked_touch_event().event.GetType());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_move_event_id);
- EXPECT_TRUE(TouchEventQueueEmpty());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(WebInputEvent::kTouchMove,
- disposition_handler_->acked_touch_event().event.GetType());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-}
-
-// Tests that the touch-queue is emptied after a page stops listening for
-// touch events and the outstanding ack is received.
-TEST_F(LegacyInputRouterImplTest, TouchEventQueueFlush) {
- OnHasTouchEventHandlers(true);
- EXPECT_TRUE(client_->has_touch_handler());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_TRUE(TouchEventQueueEmpty());
-
- // Send a touch-press event.
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id = SendTouchEvent();
- MoveTouchPoint(0, 2, 2);
- MoveTouchPoint(0, 3, 3);
- EXPECT_FALSE(TouchEventQueueEmpty());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // The page stops listening for touch-events. Note that flushing is deferred
- // until the outstanding ack is received.
- OnHasTouchEventHandlers(false);
- EXPECT_FALSE(client_->has_touch_handler());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_FALSE(TouchEventQueueEmpty());
-
- // After the ack, the touch-event queue should be empty, and none of the
- // flushed touch-events should have been sent to the renderer.
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_TRUE(TouchEventQueueEmpty());
-}
-
-void LegacyInputRouterImplTest::UnhandledWheelEvent() {
- // Simulate wheel events.
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 0, -5, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged);
-
- // Check that only the first event was sent.
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Indicate that the wheel event was unhandled.
- SendInputEventACK(WebInputEvent::kMouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Check that the ack for the MouseWheel, ScrollBegin were processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
-
- if (wheel_scroll_latching_enabled_) {
- // There should be a ScrollBegin, ScrollUpdate, and MouseWheel sent.
- EXPECT_EQ("GestureScrollBegin GestureScrollUpdate MouseWheel",
- GetInputMessageTypes(process_.get()));
- } else {
- // There should be a ScrollBegin, ScrollUpdate, ScrollEnd, and MouseWheel
- // sent.
- EXPECT_EQ(
- "GestureScrollBegin GestureScrollUpdate GestureScrollEnd MouseWheel",
- GetInputMessageTypes(process_.get()));
- }
-
- EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -5);
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- if (wheel_scroll_latching_enabled_) {
- // Check that the ack for ScrollUpdate were processed.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- } else {
- // GestureScrollEnd should have already been sent.
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- // Check that the ack for the ScrollUpdate and ScrollEnd were processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- }
-
- SendInputEventACK(WebInputEvent::kMouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- if (wheel_scroll_latching_enabled_) {
- // There should be a ScrollUpdate sent.
- EXPECT_EQ("GestureScrollUpdate", GetInputMessageTypes(process_.get()));
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- } else {
- // There should be a ScrollBegin and ScrollUpdate sent.
- EXPECT_EQ("GestureScrollBegin GestureScrollUpdate GestureScrollEnd",
- GetInputMessageTypes(process_.get()));
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- }
-
- // Check that the correct unhandled wheel event was received.
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- disposition_handler_->acked_wheel_event_state());
- EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
-
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- if (wheel_scroll_latching_enabled_) {
- // Check that the ack for ScrollUpdate were processed.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- } else {
- // GestureScrollEnd should have already been sent.
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- // Check that the ack for the ScrollUpdate and ScrollEnd were processed.
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- }
-}
-
-TEST_F(LegacyInputRouterImplTest, UnhandledWheelEvent) {
- UnhandledWheelEvent();
-}
-TEST_F(LegacyInputRouterImplWheelScrollLatchingDisabledTest,
- UnhandledWheelEvent) {
- UnhandledWheelEvent();
-}
-TEST_F(LegacyInputRouterImplAsyncWheelEventEnabledTest, UnhandledWheelEvent) {
- // Simulate wheel events.
- SimulateWheelEventWithPhase(0, 0, 0, -5, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
- SimulateWheelEventWithPhase(0, 0, 0, -10, 0, false,
- WebMouseWheelEvent::kPhaseChanged);
-
- // Check that only the first event was sent.
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Indicate that the wheel event was unhandled.
- SendInputEventACK(WebInputEvent::kMouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Check that the ack for the first MouseWheel, ScrollBegin, and the second
- // MouseWheel were processed.
- EXPECT_EQ(3U, disposition_handler_->GetAndResetAckCount());
-
- // There should be a ScrollBegin, MouseWheel, and two ScrollUpdate sent.
- EXPECT_EQ(4U, GetSentMessageCountAndResetSink());
-
- // The last acked wheel event should be the second one since the input router
- // has already sent the immediate ack for the second wheel event.
- EXPECT_EQ(disposition_handler_->acked_wheel_event().delta_y, -10);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_IGNORED,
- disposition_handler_->acked_wheel_event_state());
-
- // Ack the first ScrollUpdate.
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(
- -5,
- disposition_handler_->acked_gesture_event().data.scroll_update.delta_y);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-
- // Ack the second ScrollUpdate.
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(
- -10,
- disposition_handler_->acked_gesture_event().data.scroll_update.delta_y);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-}
-
-TEST_F(LegacyInputRouterImplTest, TouchTypesIgnoringAck) {
- OnHasTouchEventHandlers(true);
- // Only acks for TouchCancel should always be ignored.
- ASSERT_TRUE(
- ShouldBlockEventStream(GetEventWithType(WebInputEvent::kTouchStart)));
- ASSERT_TRUE(
- ShouldBlockEventStream(GetEventWithType(WebInputEvent::kTouchMove)));
- ASSERT_TRUE(
- ShouldBlockEventStream(GetEventWithType(WebInputEvent::kTouchEnd)));
-
- // Precede the TouchCancel with an appropriate TouchStart;
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id);
- ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- ASSERT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- ASSERT_EQ(0, client_->in_flight_event_count());
-
- // The TouchCancel ack is always ignored.
- CancelTouchPoint(0);
- uint32_t touch_cancel_event_id = SendTouchEvent();
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0, client_->in_flight_event_count());
- EXPECT_FALSE(HasPendingEvents());
- SendTouchEventACK(WebInputEvent::kTouchCancel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED, touch_cancel_event_id);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_FALSE(HasPendingEvents());
-}
-
-TEST_F(LegacyInputRouterImplTest, GestureTypesIgnoringAck) {
- // We test every gesture type, ensuring that the stream of gestures is valid.
- const WebInputEvent::Type eventTypes[] = {
- WebInputEvent::kGestureTapDown, WebInputEvent::kGestureShowPress,
- WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureScrollBegin,
- WebInputEvent::kGestureFlingStart, WebInputEvent::kGestureFlingCancel,
- WebInputEvent::kGestureTapDown, WebInputEvent::kGestureTap,
- WebInputEvent::kGestureTapDown, WebInputEvent::kGestureLongPress,
- WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureLongTap,
- WebInputEvent::kGestureTapDown, WebInputEvent::kGestureTapUnconfirmed,
- WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureTapDown,
- WebInputEvent::kGestureDoubleTap, WebInputEvent::kGestureTapDown,
- WebInputEvent::kGestureTapCancel, WebInputEvent::kGestureTwoFingerTap,
- WebInputEvent::kGestureTapDown, WebInputEvent::kGestureTapCancel,
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kGestureScrollUpdate,
- WebInputEvent::kGesturePinchBegin, WebInputEvent::kGesturePinchUpdate,
- WebInputEvent::kGesturePinchEnd, WebInputEvent::kGestureScrollEnd};
- for (size_t i = 0; i < arraysize(eventTypes); ++i) {
- WebInputEvent::Type type = eventTypes[i];
- if (ShouldBlockEventStream(GetEventWithType(type))) {
- SimulateGestureEvent(type, blink::kWebGestureDeviceTouchscreen);
- if (type == WebInputEvent::kGestureFlingStart) {
- // Fling start event is not sent to the renderer.
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- } else if (type == WebInputEvent::kGestureFlingCancel) {
- // The fling controller processes the GFC to generate and send a GSE.
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
- disposition_handler_->acked_gesture_event().GetType());
- } else { // type!=WebInputEvent::kGestureFlingStart && type !=
- // WebInputEvent::kGestureFlingCancel)
- if (type == WebInputEvent::kGestureScrollUpdate)
- EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
- else
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1, client_->in_flight_event_count());
- EXPECT_TRUE(HasPendingEvents());
-
- SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- }
- EXPECT_EQ(0, client_->in_flight_event_count());
- EXPECT_FALSE(HasPendingEvents());
- continue;
- }
-
- SimulateGestureEvent(type, blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0, client_->in_flight_event_count());
- EXPECT_FALSE(HasPendingEvents());
- }
-}
-
-TEST_F(LegacyInputRouterImplTest, MouseTypesIgnoringAck) {
- int start_type = static_cast<int>(WebInputEvent::kMouseDown);
- int end_type = static_cast<int>(WebInputEvent::kContextMenu);
- ASSERT_LT(start_type, end_type);
- for (int i = start_type; i <= end_type; ++i) {
- WebInputEvent::Type type = static_cast<WebInputEvent::Type>(i);
-
- SimulateMouseEvent(type, 0, 0);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- if (ShouldBlockEventStream(GetEventWithType(type))) {
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1, client_->in_flight_event_count());
-
- SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0, client_->in_flight_event_count());
- } else {
- // Note: events which don't block the event stream immediately receive
- // synthetic ACKs.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0, client_->in_flight_event_count());
- }
- }
-}
-
-// Guard against breaking changes to the list of ignored event ack types in
-// |WebInputEventTraits::ShouldBlockEventStream|.
-TEST_F(LegacyInputRouterImplTest, RequiredEventAckTypes) {
- const WebInputEvent::Type kRequiredEventAckTypes[] = {
- WebInputEvent::kMouseMove,
- WebInputEvent::kMouseWheel,
- WebInputEvent::kRawKeyDown,
- WebInputEvent::kKeyDown,
- WebInputEvent::kKeyUp,
- WebInputEvent::kChar,
- WebInputEvent::kGestureScrollUpdate,
- WebInputEvent::kGestureFlingStart,
- WebInputEvent::kGestureFlingCancel,
- WebInputEvent::kGesturePinchUpdate,
- WebInputEvent::kTouchStart,
- WebInputEvent::kTouchMove};
- for (size_t i = 0; i < arraysize(kRequiredEventAckTypes); ++i) {
- const WebInputEvent::Type required_ack_type = kRequiredEventAckTypes[i];
- ASSERT_TRUE(ShouldBlockEventStream(GetEventWithType(required_ack_type)));
- }
-}
-
-TEST_F(LegacyInputRouterImplTest, GestureTypesIgnoringAckInterleaved) {
- // Interleave a few events that do and do not ignore acks. All gesture events
- // should be dispatched immediately, but the acks will be blocked on blocking
- // events.
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0, client_->in_flight_event_count());
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchscreen);
- ASSERT_EQ(2U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1, client_->in_flight_event_count());
-
- SimulateGestureEvent(WebInputEvent::kGestureTapDown,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1, client_->in_flight_event_count());
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(2, client_->in_flight_event_count());
-
- SimulateGestureEvent(WebInputEvent::kGestureShowPress,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(2, client_->in_flight_event_count());
-
- SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(3, client_->in_flight_event_count());
-
- SimulateGestureEvent(WebInputEvent::kGestureTapCancel,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(3, client_->in_flight_event_count());
-
- // Now ack each ack-respecting event. Should see in-flight event count
- // decreasing and additional acks coming back.
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(2, client_->in_flight_event_count());
-
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1, client_->in_flight_event_count());
-
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0, client_->in_flight_event_count());
-}
-
-// Test that GestureShowPress events don't get out of order due to
-// ignoring their acks.
-TEST_F(LegacyInputRouterImplTest, GestureShowPressIsInOrder) {
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-
- // GesturePinchBegin ignores its ack.
- SimulateGestureEvent(WebInputEvent::kGesturePinchBegin,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-
- // GesturePinchUpdate waits for an ack.
- // This also verifies that GesturePinchUpdates for touchscreen are sent
- // to the renderer (in contrast to the TrackpadPinchUpdate test).
- SimulateGestureEvent(WebInputEvent::kGesturePinchUpdate,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
-
- // GestureShowPress will be sent immediately since GestureEventQueue allows
- // multiple in-flight events. However the acks will be blocked on outstanding
- // in-flight events.
- SimulateGestureEvent(WebInputEvent::kGestureShowPress,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
-
- SimulateGestureEvent(WebInputEvent::kGestureShowPress,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
-
- // Ack the GesturePinchUpdate to release two GestureShowPress ack.
- SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(3U, disposition_handler_->GetAndResetAckCount());
-}
-
-// Test that touch ack timeout behavior is properly configured for
-// mobile-optimized sites and allowed touch actions.
-TEST_F(LegacyInputRouterImplTest, TouchAckTimeoutConfigured) {
- const int kDesktopTimeoutMs = 1;
- const int kMobileTimeoutMs = 0;
- SetUpForTouchAckTimeoutTest(kDesktopTimeoutMs, kMobileTimeoutMs);
- ASSERT_TRUE(TouchEventTimeoutEnabled());
-
- // Verify that the touch ack timeout fires upon the delayed ack.
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id1 = SendTouchEvent();
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
-
- // The timed-out event should have been ack'ed.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- // Ack'ing the timed-out event should fire a TouchCancel.
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id1);
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // The remainder of the touch sequence should be dropped.
- ReleaseTouchPoint(0);
- SendTouchEvent();
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- ASSERT_TRUE(TouchEventTimeoutEnabled());
-
- // A mobile-optimized site should use the mobile timeout. For this test that
- // timeout value is 0, which disables the timeout.
- input_router()->NotifySiteIsMobileOptimized(true);
- EXPECT_FALSE(TouchEventTimeoutEnabled());
-
- input_router()->NotifySiteIsMobileOptimized(false);
- EXPECT_TRUE(TouchEventTimeoutEnabled());
-
- // kTouchActionNone (and no other touch-action) should disable the timeout.
- OnHasTouchEventHandlers(true);
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id2 = SendTouchEvent();
- OnSetTouchAction(cc::kTouchActionPanY);
- EXPECT_TRUE(TouchEventTimeoutEnabled());
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id2 = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id2);
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_release_event_id2);
-
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id3 = SendTouchEvent();
- OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(TouchEventTimeoutEnabled());
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id3 = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id3);
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_release_event_id3);
-
- // As the touch-action is reset by a new touch sequence, the timeout behavior
- // should be restored.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_TRUE(TouchEventTimeoutEnabled());
-}
-
-// Test that a touch sequenced preceded by kTouchActionNone is not affected by
-// the touch timeout.
-TEST_F(LegacyInputRouterImplTest,
- TouchAckTimeoutDisabledForTouchSequenceAfterTouchActionNone) {
- const int kDesktopTimeoutMs = 1;
- const int kMobileTimeoutMs = 2;
- SetUpForTouchAckTimeoutTest(kDesktopTimeoutMs, kMobileTimeoutMs);
- ASSERT_TRUE(TouchEventTimeoutEnabled());
- OnHasTouchEventHandlers(true);
-
- // Start a touch sequence.
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id = SendTouchEvent();
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // kTouchActionNone should disable the timeout.
- OnSetTouchAction(cc::kTouchActionNone);
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_FALSE(TouchEventTimeoutEnabled());
-
- MoveTouchPoint(0, 1, 2);
- uint32_t touch_move_event_id = SendTouchEvent();
- EXPECT_FALSE(TouchEventTimeoutEnabled());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Delay the move ack. The timeout should not fire.
- RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_move_event_id);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-
- // End the touch sequence.
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_release_event_id);
- EXPECT_TRUE(TouchEventTimeoutEnabled());
- disposition_handler_->GetAndResetAckCount();
- GetSentMessageCountAndResetSink();
-
- // Start another touch sequence. This should restore the touch timeout.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_TRUE(TouchEventTimeoutEnabled());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
-
- // Wait for the touch ack timeout to fire.
- RunTasksAndWait(base::TimeDelta::FromMilliseconds(kDesktopTimeoutMs + 1));
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
-}
-
-// Test that TouchActionFilter::ResetTouchAction is called before the
-// first touch event for a touch sequence reaches the renderer.
-TEST_F(LegacyInputRouterImplTest, TouchActionResetBeforeEventReachesRenderer) {
- OnHasTouchEventHandlers(true);
-
- // Sequence 1.
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id1 = SendTouchEvent();
- OnSetTouchAction(cc::kTouchActionNone);
- MoveTouchPoint(0, 50, 50);
- uint32_t touch_move_event_id1 = SendTouchEvent();
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id1 = SendTouchEvent();
-
- // Sequence 2.
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id2 = SendTouchEvent();
- MoveTouchPoint(0, 50, 50);
- uint32_t touch_move_event_id2 = SendTouchEvent();
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id2 = SendTouchEvent();
-
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id1);
- SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_move_event_id1);
-
- // Ensure touch action is still none, as the next touch start hasn't been
- // acked yet. ScrollBegin and ScrollEnd don't require acks.
- EXPECT_EQ(6U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- // This allows the next touch sequence to start.
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_release_event_id1);
-
- // Ensure touch action has been set to auto, as a new touch sequence has
- // started.
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id2);
- SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_move_event_id2);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_release_event_id2);
-}
-
-// Test that TouchActionFilter::ResetTouchAction is called when a new touch
-// sequence has no consumer.
-TEST_F(LegacyInputRouterImplTest, TouchActionResetWhenTouchHasNoConsumer) {
- OnHasTouchEventHandlers(true);
-
- // Sequence 1.
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id1 = SendTouchEvent();
- MoveTouchPoint(0, 50, 50);
- uint32_t touch_move_event_id1 = SendTouchEvent();
- OnSetTouchAction(cc::kTouchActionNone);
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id1);
- SendTouchEventACK(WebInputEvent::kTouchMove, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_move_event_id1);
-
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id1 = SendTouchEvent();
-
- // Sequence 2
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id2 = SendTouchEvent();
- MoveTouchPoint(0, 50, 50);
- SendTouchEvent();
- ReleaseTouchPoint(0);
- SendTouchEvent();
-
- // Ensure we have touch-action:none. ScrollBegin and ScrollEnd don't require
- // acks.
- EXPECT_EQ(6U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_release_event_id1);
- SendTouchEventACK(WebInputEvent::kTouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- touch_press_event_id2);
-
- // Ensure touch action has been set to auto, as the touch had no consumer.
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-}
-
-// Test that TouchActionFilter::ResetTouchAction is called when the touch
-// handler is removed.
-TEST_F(LegacyInputRouterImplTest, TouchActionResetWhenTouchHandlerRemoved) {
- // Touch sequence with touch handler.
- OnHasTouchEventHandlers(true);
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id = SendTouchEvent();
- MoveTouchPoint(0, 50, 50);
- uint32_t touch_move_event_id = SendTouchEvent();
- OnSetTouchAction(cc::kTouchActionNone);
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id = SendTouchEvent();
- EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
-
- // Ensure we have touch-action:none, suppressing scroll events.
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SendTouchEventACK(WebInputEvent::kTouchMove,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED, touch_move_event_id);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- SendTouchEventACK(WebInputEvent::kTouchEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED, touch_release_event_id);
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- // Sequence without a touch handler. Note that in this case, the view may not
- // necessarily forward touches to the router (as no touch handler exists).
- OnHasTouchEventHandlers(false);
-
- // Ensure touch action has been set to auto, as the touch handler has been
- // removed.
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-}
-
-// Tests that async touch-moves are ack'd from the browser side.
-TEST_F(LegacyInputRouterImplTest, AsyncTouchMoveAckedImmediately) {
- OnHasTouchEventHandlers(true);
-
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id = SendTouchEvent();
- EXPECT_TRUE(client_->GetAndResetFilterEventCalled());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_FALSE(TouchEventQueueEmpty());
-
- // Receive an ACK for the first touch-event.
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfNeeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
-
- // Now send an async move.
- MoveTouchPoint(0, 5, 5);
- SendTouchEvent();
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-}
-
-// Test that the double tap gesture depends on the touch action of the first
-// tap.
-TEST_F(LegacyInputRouterImplTest, DoubleTapGestureDependsOnFirstTap) {
- OnHasTouchEventHandlers(true);
-
- // Sequence 1.
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id1 = SendTouchEvent();
- OnSetTouchAction(cc::kTouchActionNone);
- SendTouchEventACK(WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_press_event_id1);
-
- ReleaseTouchPoint(0);
- uint32_t touch_release_event_id = SendTouchEvent();
-
- // Sequence 2
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id2 = SendTouchEvent();
-
- // First tap.
- EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureTapDown,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // The GestureTapUnconfirmed is converted into a tap, as the touch action is
- // none.
- SimulateGestureEvent(WebInputEvent::kGestureTapUnconfirmed,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- // This test will become invalid if GestureTap stops requiring an ack.
- ASSERT_TRUE(
- ShouldBlockEventStream(GetEventWithType(WebInputEvent::kGestureTap)));
- EXPECT_EQ(3, client_->in_flight_event_count());
- SendInputEventACK(WebInputEvent::kGestureTap, INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(2, client_->in_flight_event_count());
-
- // This tap gesture is dropped, since the GestureTapUnconfirmed was turned
- // into a tap.
- SimulateGestureEvent(WebInputEvent::kGestureTap,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_release_event_id);
- SendTouchEventACK(WebInputEvent::kTouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- touch_press_event_id2);
-
- // Second Tap.
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- SimulateGestureEvent(WebInputEvent::kGestureTapDown,
- blink::kWebGestureDeviceTouchscreen);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Although the touch-action is now auto, the double tap still won't be
- // dispatched, because the first tap occured when the touch-action was none.
- SimulateGestureEvent(WebInputEvent::kGestureDoubleTap,
- blink::kWebGestureDeviceTouchscreen);
- // This test will become invalid if GestureDoubleTap stops requiring an ack.
- ASSERT_TRUE(ShouldBlockEventStream(
- GetEventWithType(WebInputEvent::kGestureDoubleTap)));
- EXPECT_EQ(1, client_->in_flight_event_count());
- SendInputEventACK(WebInputEvent::kGestureTap, INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0, client_->in_flight_event_count());
-}
-
-// Test that GesturePinchUpdate is handled specially for trackpad
-TEST_F(LegacyInputRouterImplTest, TouchpadPinchUpdate) {
- // GesturePinchUpdate for trackpad sends synthetic wheel events.
- // Note that the Touchscreen case is verified as NOT doing this as
- // part of the ShowPressIsInOrder test.
-
- SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
- blink::kWebGestureDeviceTouchpad);
-
- // Verify we actually sent a special wheel event to the renderer.
- const WebInputEvent* input_event =
- GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
- ASSERT_EQ(WebInputEvent::kGesturePinchUpdate, input_event->GetType());
- const WebGestureEvent* gesture_event =
- static_cast<const WebGestureEvent*>(input_event);
- EXPECT_EQ(20, gesture_event->PositionInWidget().x);
- EXPECT_EQ(25, gesture_event->PositionInWidget().y);
- EXPECT_EQ(20, gesture_event->PositionInScreen().x);
- EXPECT_EQ(25, gesture_event->PositionInScreen().y);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Indicate that the wheel event was unhandled.
- SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Check that the correct unhandled pinch event was received.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- ASSERT_EQ(WebInputEvent::kGesturePinchUpdate,
- disposition_handler_->ack_event_type());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- disposition_handler_->ack_state());
- EXPECT_EQ(
- 1.5f,
- disposition_handler_->acked_gesture_event().data.pinch_update.scale);
- EXPECT_EQ(0, client_->in_flight_event_count());
-
- // Second a second pinch event.
- SimulateGesturePinchUpdateEvent(0.3f, 20, 25, 0,
- blink::kWebGestureDeviceTouchpad);
- input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
- ASSERT_EQ(WebInputEvent::kGesturePinchUpdate, input_event->GetType());
- gesture_event = static_cast<const WebGestureEvent*>(input_event);
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
-
- // Indicate that the wheel event was handled this time.
- SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Check that the correct HANDLED pinch event was received.
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
- disposition_handler_->ack_event_type());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, disposition_handler_->ack_state());
- EXPECT_FLOAT_EQ(
- 0.3f,
- disposition_handler_->acked_gesture_event().data.pinch_update.scale);
-}
-
-// Test proper handling of touchpad Gesture{Pinch,Scroll}Update sequences.
-TEST_F(LegacyInputRouterImplTest, TouchpadPinchAndScrollUpdate) {
- // All gesture events should be sent immediately.
- SimulateGestureScrollUpdateEvent(1.5f, 0.f, 0,
- blink::kWebGestureDeviceTouchpad);
- SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchpad);
- ASSERT_EQ(2U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(2, client_->in_flight_event_count());
-
- // Subsequent scroll and pinch events will also be sent immediately.
- SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
- blink::kWebGestureDeviceTouchpad);
- ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(3, client_->in_flight_event_count());
-
- SimulateGestureScrollUpdateEvent(1.5f, 1.5f, 0,
- blink::kWebGestureDeviceTouchpad);
- ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(4, client_->in_flight_event_count());
-
- SimulateGesturePinchUpdateEvent(1.5f, 20, 25, 0,
- blink::kWebGestureDeviceTouchpad);
- ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(5, client_->in_flight_event_count());
-
- SimulateGestureScrollUpdateEvent(0.f, 1.5f, 0,
- blink::kWebGestureDeviceTouchpad);
- ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(6, client_->in_flight_event_count());
-
- // Ack'ing events should decrease in-flight event count.
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(5, client_->in_flight_event_count());
-
- // Ack the second scroll.
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(4, client_->in_flight_event_count());
-
- // Ack the pinch event.
- SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(3, client_->in_flight_event_count());
-
- // Ack the scroll event.
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(2, client_->in_flight_event_count());
-
- // Ack the pinch event.
- SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(1, client_->in_flight_event_count());
-
- // Ack the scroll event.
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount());
- EXPECT_EQ(0, client_->in_flight_event_count());
-}
-
-// Test proper routing of overscroll notifications received either from
-// event acks or from |DidOverscroll| IPC messages.
-void LegacyInputRouterImplTest::OverscrollDispatch() {
- DidOverscrollParams overscroll;
- overscroll.accumulated_overscroll = gfx::Vector2dF(-14, 14);
- overscroll.latest_overscroll_delta = gfx::Vector2dF(-7, 0);
- overscroll.current_fling_velocity = gfx::Vector2dF(-1, 0);
-
- input_router_->OnMessageReceived(InputHostMsg_DidOverscroll(0, overscroll));
- DidOverscrollParams client_overscroll = client_->GetAndResetOverscroll();
- EXPECT_EQ(overscroll.accumulated_overscroll,
- client_overscroll.accumulated_overscroll);
- EXPECT_EQ(overscroll.latest_overscroll_delta,
- client_overscroll.latest_overscroll_delta);
- // With browser side fling, the fling velocity doesn't come from overscroll
- // params of the renderer, instead the input router sets the
- // params.current_fling_velocity based on the velocity received from the fling
- // controller.
- EXPECT_EQ(gfx::Vector2dF(), client_overscroll.current_fling_velocity);
-
- DidOverscrollParams wheel_overscroll;
- wheel_overscroll.accumulated_overscroll = gfx::Vector2dF(7, -7);
- wheel_overscroll.latest_overscroll_delta = gfx::Vector2dF(3, 0);
- wheel_overscroll.current_fling_velocity = gfx::Vector2dF(1, 0);
-
- SimulateWheelEventPossiblyIncludingPhase(!wheel_scroll_latching_enabled_, 0,
- 0, 3, 0, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
- InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD,
- WebInputEvent::kMouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- ack.overscroll.reset(new DidOverscrollParams(wheel_overscroll));
- input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
-
- client_overscroll = client_->GetAndResetOverscroll();
- EXPECT_EQ(wheel_overscroll.accumulated_overscroll,
- client_overscroll.accumulated_overscroll);
- EXPECT_EQ(wheel_overscroll.latest_overscroll_delta,
- client_overscroll.latest_overscroll_delta);
- // With browser side fling, the fling velocity doesn't come from overscroll
- // params of the renderer, instead the input router sets the
- // params.current_fling_velocity based on the velocity received from the fling
- // controller.
- EXPECT_EQ(gfx::Vector2dF(), client_overscroll.current_fling_velocity);
-}
-TEST_F(LegacyInputRouterImplTest, OverscrollDispatch) {
- OverscrollDispatch();
-}
-TEST_F(LegacyInputRouterImplWheelScrollLatchingDisabledTest,
- OverscrollDispatch) {
- OverscrollDispatch();
-}
-TEST_F(LegacyInputRouterImplAsyncWheelEventEnabledTest, OverscrollDispatch) {
- OverscrollDispatch();
-}
-
-// Test proper routing of whitelisted touch action notifications received from
-// |SetWhiteListedTouchAction| IPC messages.
-TEST_F(LegacyInputRouterImplTest, OnSetWhiteListedTouchAction) {
- cc::TouchAction touch_action = cc::kTouchActionPanY;
- input_router_->OnMessageReceived(InputHostMsg_SetWhiteListedTouchAction(
- 0, touch_action, 0, INPUT_EVENT_ACK_STATE_NOT_CONSUMED));
- cc::TouchAction white_listed_touch_action =
- client_->GetAndResetWhiteListedTouchAction();
- EXPECT_EQ(touch_action, white_listed_touch_action);
-}
-
-// Tests that touch event stream validation passes when events are filtered
-// out. See crbug.com/581231 for details.
-TEST_F(LegacyInputRouterImplTest,
- TouchValidationPassesWithFilteredInputEvents) {
- // Touch sequence with touch handler.
- OnHasTouchEventHandlers(true);
- PressTouchPoint(1, 1);
- uint32_t touch_press_event_id = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- touch_press_event_id);
-
- PressTouchPoint(1, 1);
- touch_press_event_id = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- touch_press_event_id);
-
- // This event will be filtered out, since no consumer exists.
- ReleaseTouchPoint(1);
- uint32_t touch_release_event_id = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED, touch_release_event_id);
-
- // If the validator didn't see the filtered out release event, it will crash
- // now, upon seeing a press for a touch which it believes to be still pressed.
- PressTouchPoint(1, 1);
- touch_press_event_id = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchStart,
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- touch_press_event_id);
-}
-
-namespace {
-
-class LegacyInputRouterImplScaleEventTest : public LegacyInputRouterImplTest {
- public:
- LegacyInputRouterImplScaleEventTest() {}
-
- void SetUp() override {
- LegacyInputRouterImplTest::SetUp();
- input_router_->SetDeviceScaleFactor(2.f);
- }
-
- template <typename T>
- const T* GetSentWebInputEvent() const {
- EXPECT_EQ(1u, process_->sink().message_count());
-
- InputMsg_HandleInputEvent::Schema::Param param;
- InputMsg_HandleInputEvent::Read(process_->sink().GetMessageAt(0), &param);
- return static_cast<const T*>(std::get<0>(param));
- }
-
- template <typename T>
- const T* GetFilterWebInputEvent() const {
- return static_cast<const T*>(client_->last_filter_event());
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LegacyInputRouterImplScaleEventTest);
-};
-
-class LegacyInputRouterImplScaleMouseEventTest
- : public LegacyInputRouterImplScaleEventTest {
- public:
- LegacyInputRouterImplScaleMouseEventTest() {}
-
- void RunMouseEventTest(const std::string& name, WebInputEvent::Type type) {
- SCOPED_TRACE(name);
- SimulateMouseEvent(type, 10, 10);
- const WebMouseEvent* sent_event = GetSentWebInputEvent<WebMouseEvent>();
- EXPECT_EQ(20, sent_event->PositionInWidget().x);
- EXPECT_EQ(20, sent_event->PositionInWidget().y);
-
- const WebMouseEvent* filter_event = GetFilterWebInputEvent<WebMouseEvent>();
- EXPECT_EQ(10, filter_event->PositionInWidget().x);
- EXPECT_EQ(10, filter_event->PositionInWidget().y);
-
- process_->sink().ClearMessages();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LegacyInputRouterImplScaleMouseEventTest);
-};
-
-} // namespace
-
-TEST_F(LegacyInputRouterImplScaleMouseEventTest, ScaleMouseEventTest) {
- RunMouseEventTest("Enter", WebInputEvent::kMouseEnter);
- RunMouseEventTest("Down", WebInputEvent::kMouseDown);
- RunMouseEventTest("Move", WebInputEvent::kMouseMove);
- RunMouseEventTest("Up", WebInputEvent::kMouseUp);
-}
-
-TEST_F(LegacyInputRouterImplScaleEventTest, ScaleMouseWheelEventTest) {
- ASSERT_EQ(0u, process_->sink().message_count());
- SimulateWheelEventWithPhase(5, 5, 10, 10, 0, false,
- WebMouseWheelEvent::kPhaseBegan);
- ASSERT_EQ(1u, process_->sink().message_count());
-
- const WebMouseWheelEvent* sent_event =
- GetSentWebInputEvent<WebMouseWheelEvent>();
- EXPECT_EQ(10, sent_event->PositionInWidget().x);
- EXPECT_EQ(10, sent_event->PositionInWidget().y);
- EXPECT_EQ(20, sent_event->delta_x);
- EXPECT_EQ(20, sent_event->delta_y);
- EXPECT_EQ(2, sent_event->wheel_ticks_x);
- EXPECT_EQ(2, sent_event->wheel_ticks_y);
-
- const WebMouseWheelEvent* filter_event =
- GetFilterWebInputEvent<WebMouseWheelEvent>();
- EXPECT_EQ(5, filter_event->PositionInWidget().x);
- EXPECT_EQ(5, filter_event->PositionInWidget().y);
- EXPECT_EQ(10, filter_event->delta_x);
- EXPECT_EQ(10, filter_event->delta_y);
- EXPECT_EQ(1, filter_event->wheel_ticks_x);
- EXPECT_EQ(1, filter_event->wheel_ticks_y);
-
- EXPECT_EQ(sent_event->acceleration_ratio_x,
- filter_event->acceleration_ratio_x);
- EXPECT_EQ(sent_event->acceleration_ratio_y,
- filter_event->acceleration_ratio_y);
-}
-
-namespace {
-
-class LegacyInputRouterImplScaleTouchEventTest
- : public LegacyInputRouterImplScaleEventTest {
- public:
- LegacyInputRouterImplScaleTouchEventTest() {}
-
- // Test tests if two finger touch event at (10, 20) and (100, 200) are
- // properly scaled. The touch event must be generated ans flushed into
- // the message sink prior to this method.
- void RunTouchEventTest(const std::string& name, WebTouchPoint::State state) {
- SCOPED_TRACE(name);
- ASSERT_EQ(1u, process_->sink().message_count());
- const WebTouchEvent* sent_event = GetSentWebInputEvent<WebTouchEvent>();
- ASSERT_EQ(2u, sent_event->touches_length);
- EXPECT_EQ(state, sent_event->touches[0].state);
- EXPECT_EQ(20, sent_event->touches[0].PositionInWidget().x);
- EXPECT_EQ(40, sent_event->touches[0].PositionInWidget().y);
- EXPECT_EQ(10, sent_event->touches[0].PositionInScreen().x);
- EXPECT_EQ(20, sent_event->touches[0].PositionInScreen().y);
- EXPECT_EQ(40, sent_event->touches[0].radius_x);
- EXPECT_EQ(40, sent_event->touches[0].radius_y);
-
- EXPECT_EQ(200, sent_event->touches[1].PositionInWidget().x);
- EXPECT_EQ(400, sent_event->touches[1].PositionInWidget().y);
- EXPECT_EQ(100, sent_event->touches[1].PositionInScreen().x);
- EXPECT_EQ(200, sent_event->touches[1].PositionInScreen().y);
- EXPECT_EQ(40, sent_event->touches[1].radius_x);
- EXPECT_EQ(40, sent_event->touches[1].radius_y);
-
- const WebTouchEvent* filter_event = GetFilterWebInputEvent<WebTouchEvent>();
- ASSERT_EQ(2u, filter_event->touches_length);
- EXPECT_EQ(10, filter_event->touches[0].PositionInWidget().x);
- EXPECT_EQ(20, filter_event->touches[0].PositionInWidget().y);
- EXPECT_EQ(10, filter_event->touches[0].PositionInScreen().x);
- EXPECT_EQ(20, filter_event->touches[0].PositionInScreen().y);
- EXPECT_EQ(20, filter_event->touches[0].radius_x);
- EXPECT_EQ(20, filter_event->touches[0].radius_y);
-
- EXPECT_EQ(100, filter_event->touches[1].PositionInWidget().x);
- EXPECT_EQ(200, filter_event->touches[1].PositionInWidget().y);
- EXPECT_EQ(100, filter_event->touches[1].PositionInScreen().x);
- EXPECT_EQ(200, filter_event->touches[1].PositionInScreen().y);
- EXPECT_EQ(20, filter_event->touches[1].radius_x);
- EXPECT_EQ(20, filter_event->touches[1].radius_y);
- }
-
- void FlushTouchEvent(WebInputEvent::Type type) {
- uint32_t touch_event_id = SendTouchEvent();
- SendTouchEventACK(type, INPUT_EVENT_ACK_STATE_CONSUMED, touch_event_id);
- ASSERT_TRUE(TouchEventQueueEmpty());
- ASSERT_NE(0u, process_->sink().message_count());
- }
-
- void ReleaseTouchPointAndAck(int index) {
- ReleaseTouchPoint(index);
- int release_event_id = SendTouchEvent();
- SendTouchEventACK(WebInputEvent::kTouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED,
- release_event_id);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LegacyInputRouterImplScaleTouchEventTest);
-};
-
-} // namespace
-
-TEST_F(LegacyInputRouterImplScaleTouchEventTest, ScaleTouchEventTest) {
- // Press
- PressTouchPoint(10, 20);
- PressTouchPoint(100, 200);
- FlushTouchEvent(WebInputEvent::kTouchStart);
-
- RunTouchEventTest("Press", WebTouchPoint::kStatePressed);
- ReleaseTouchPointAndAck(1);
- ReleaseTouchPointAndAck(0);
- EXPECT_EQ(3u, GetSentMessageCountAndResetSink());
-
- // Move
- PressTouchPoint(0, 0);
- PressTouchPoint(0, 0);
- FlushTouchEvent(WebInputEvent::kTouchStart);
- process_->sink().ClearMessages();
-
- MoveTouchPoint(0, 10, 20);
- MoveTouchPoint(1, 100, 200);
- FlushTouchEvent(WebInputEvent::kTouchMove);
- RunTouchEventTest("Move", WebTouchPoint::kStateMoved);
- ReleaseTouchPointAndAck(1);
- ReleaseTouchPointAndAck(0);
- EXPECT_EQ(3u, GetSentMessageCountAndResetSink());
-
- // Release
- PressTouchPoint(10, 20);
- PressTouchPoint(100, 200);
- FlushTouchEvent(WebInputEvent::kTouchMove);
- process_->sink().ClearMessages();
-
- ReleaseTouchPoint(0);
- ReleaseTouchPoint(1);
- FlushTouchEvent(WebInputEvent::kTouchEnd);
- RunTouchEventTest("Release", WebTouchPoint::kStateReleased);
-
- // Cancel
- PressTouchPoint(10, 20);
- PressTouchPoint(100, 200);
- FlushTouchEvent(WebInputEvent::kTouchStart);
- process_->sink().ClearMessages();
-
- CancelTouchPoint(0);
- CancelTouchPoint(1);
- FlushTouchEvent(WebInputEvent::kTouchCancel);
- RunTouchEventTest("Cancel", WebTouchPoint::kStateCancelled);
-}
-
-namespace {
-
-class LegacyInputRouterImplScaleGestureEventTest
- : public LegacyInputRouterImplScaleEventTest {
- public:
- LegacyInputRouterImplScaleGestureEventTest() {}
-
- WebGestureEvent BuildGestureEvent(WebInputEvent::Type type,
- const gfx::PointF& point) {
- WebGestureEvent event = SyntheticWebGestureEventBuilder::Build(
- type, blink::kWebGestureDeviceTouchpad);
- event.SetPositionInWidget(point);
- event.SetPositionInScreen(point);
- return event;
- }
-
- void TestTap(const std::string& name, WebInputEvent::Type type) {
- SCOPED_TRACE(name);
- const gfx::PointF orig(10, 20), scaled(20, 40);
- WebGestureEvent event = BuildGestureEvent(type, orig);
- event.data.tap.width = 30;
- event.data.tap.height = 40;
- SimulateGestureEvent(event);
- FlushGestureEvent(type);
-
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
- TestLocationInSentEvent(sent_event, orig, scaled);
- EXPECT_EQ(60, sent_event->data.tap.width);
- EXPECT_EQ(80, sent_event->data.tap.height);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- TestLocationInFilterEvent(filter_event, orig);
- EXPECT_EQ(30, filter_event->data.tap.width);
- EXPECT_EQ(40, filter_event->data.tap.height);
- process_->sink().ClearMessages();
- }
-
- void TestLongPress(const std::string& name, WebInputEvent::Type type) {
- const gfx::PointF orig(10, 20), scaled(20, 40);
- WebGestureEvent event = BuildGestureEvent(type, orig);
- event.data.long_press.width = 30;
- event.data.long_press.height = 40;
- SimulateGestureEvent(event);
- FlushGestureEvent(type);
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
- TestLocationInSentEvent(sent_event, orig, scaled);
- EXPECT_EQ(60, sent_event->data.long_press.width);
- EXPECT_EQ(80, sent_event->data.long_press.height);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- TestLocationInFilterEvent(filter_event, orig);
- EXPECT_EQ(30, filter_event->data.long_press.width);
- EXPECT_EQ(40, filter_event->data.long_press.height);
- process_->sink().ClearMessages();
- }
-
- void FlushGestureEvent(WebInputEvent::Type type) {
- SendInputEventACK(type, INPUT_EVENT_ACK_STATE_CONSUMED);
- ASSERT_NE(0u, process_->sink().message_count());
- }
-
- void TestLocationInSentEvent(const WebGestureEvent* sent_event,
- const gfx::PointF& orig,
- const gfx::PointF& scaled) {
- EXPECT_EQ(20, sent_event->PositionInWidget().x);
- EXPECT_EQ(40, sent_event->PositionInWidget().y);
- EXPECT_EQ(10, sent_event->PositionInScreen().x);
- EXPECT_EQ(20, sent_event->PositionInScreen().y);
- }
-
- void TestLocationInFilterEvent(const WebGestureEvent* filter_event,
- const gfx::PointF& point) {
- EXPECT_EQ(10, filter_event->PositionInWidget().x);
- EXPECT_EQ(20, filter_event->PositionInWidget().y);
- EXPECT_EQ(10, filter_event->PositionInScreen().x);
- EXPECT_EQ(20, filter_event->PositionInScreen().y);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LegacyInputRouterImplScaleGestureEventTest);
-};
-
-} // namespace
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureScrollUpdate) {
- SimulateGestureScrollUpdateEvent(10.f, 20, 0,
- blink::kWebGestureDeviceTouchpad);
- FlushGestureEvent(WebInputEvent::kGestureScrollUpdate);
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
-
- EXPECT_EQ(20.f, sent_event->data.scroll_update.delta_x);
- EXPECT_EQ(40.f, sent_event->data.scroll_update.delta_y);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- EXPECT_EQ(10.f, filter_event->data.scroll_update.delta_x);
- EXPECT_EQ(20.f, filter_event->data.scroll_update.delta_y);
-}
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureScrollBegin) {
- SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollBegin(
- 10.f, 20.f, blink::kWebGestureDeviceTouchscreen));
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
- EXPECT_EQ(20.f, sent_event->data.scroll_begin.delta_x_hint);
- EXPECT_EQ(40.f, sent_event->data.scroll_begin.delta_y_hint);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- EXPECT_EQ(10.f, filter_event->data.scroll_begin.delta_x_hint);
- EXPECT_EQ(20.f, filter_event->data.scroll_begin.delta_y_hint);
-}
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GesturePinchUpdate) {
- const gfx::PointF orig(10, 20), scaled(20, 40);
- SimulateGesturePinchUpdateEvent(1.5f, orig.x(), orig.y(), 0,
- blink::kWebGestureDeviceTouchpad);
- FlushGestureEvent(WebInputEvent::kGesturePinchUpdate);
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
- TestLocationInSentEvent(sent_event, orig, scaled);
- EXPECT_EQ(1.5f, sent_event->data.pinch_update.scale);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- TestLocationInFilterEvent(filter_event, orig);
- EXPECT_EQ(1.5f, filter_event->data.pinch_update.scale);
-}
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureTapDown) {
- const gfx::PointF orig(10, 20), scaled(20, 40);
- WebGestureEvent event =
- BuildGestureEvent(WebInputEvent::kGestureTapDown, orig);
- event.data.tap_down.width = 30;
- event.data.tap_down.height = 40;
- SimulateGestureEvent(event);
- // FlushGestureEvent(WebInputEvent::GestureTapDown);
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
- TestLocationInSentEvent(sent_event, orig, scaled);
- EXPECT_EQ(60, sent_event->data.tap_down.width);
- EXPECT_EQ(80, sent_event->data.tap_down.height);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- TestLocationInFilterEvent(filter_event, orig);
- EXPECT_EQ(30, filter_event->data.tap_down.width);
- EXPECT_EQ(40, filter_event->data.tap_down.height);
-}
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureTapOthers) {
- TestTap("GestureDoubleTap", WebInputEvent::kGestureDoubleTap);
- TestTap("GestureTap", WebInputEvent::kGestureTap);
- TestTap("GestureTapUnconfirmed", WebInputEvent::kGestureTapUnconfirmed);
-}
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureShowPress) {
- const gfx::PointF orig(10, 20), scaled(20, 40);
- WebGestureEvent event =
- BuildGestureEvent(WebInputEvent::kGestureShowPress, orig);
- event.data.show_press.width = 30;
- event.data.show_press.height = 40;
- SimulateGestureEvent(event);
-
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
- TestLocationInSentEvent(sent_event, orig, scaled);
- EXPECT_EQ(60, sent_event->data.show_press.width);
- EXPECT_EQ(80, sent_event->data.show_press.height);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- TestLocationInFilterEvent(filter_event, orig);
- EXPECT_EQ(30, filter_event->data.show_press.width);
- EXPECT_EQ(40, filter_event->data.show_press.height);
-}
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureLongPress) {
- TestLongPress("LongPress", WebInputEvent::kGestureLongPress);
- TestLongPress("LongPap", WebInputEvent::kGestureLongTap);
-}
-
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureTwoFingerTap) {
- WebGestureEvent event = BuildGestureEvent(WebInputEvent::kGestureTwoFingerTap,
- gfx::PointF(10, 20));
- event.data.two_finger_tap.first_finger_width = 30;
- event.data.two_finger_tap.first_finger_height = 40;
- SimulateGestureEvent(event);
-
- const WebGestureEvent* sent_event = GetSentWebInputEvent<WebGestureEvent>();
- EXPECT_EQ(20, sent_event->PositionInWidget().x);
- EXPECT_EQ(40, sent_event->PositionInWidget().y);
- EXPECT_EQ(60, sent_event->data.two_finger_tap.first_finger_width);
- EXPECT_EQ(80, sent_event->data.two_finger_tap.first_finger_height);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- EXPECT_EQ(10, filter_event->PositionInWidget().x);
- EXPECT_EQ(20, filter_event->PositionInWidget().y);
- EXPECT_EQ(30, filter_event->data.two_finger_tap.first_finger_width);
- EXPECT_EQ(40, filter_event->data.two_finger_tap.first_finger_height);
-}
-
-// Thie test is flaky on Fuchsia. crbug.com/807803
-#if defined(OS_FUCHSIA)
-#define MAYBE_GestureFlingStart DISABLED_GestureFlingStart
-#else
-#define MAYBE_GestureFlingStart GestureFlingStart
-#endif
-TEST_F(LegacyInputRouterImplScaleGestureEventTest, MAYBE_GestureFlingStart) {
- // Simulate a GSB since touchscreen flings must happen inside scroll.
- SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollBegin(
- 10.f, 20.f, blink::kWebGestureDeviceTouchscreen));
- process_->sink().ClearMessages();
-
- const gfx::PointF orig(10, 20), scaled(20, 40);
- WebGestureEvent event =
- BuildGestureEvent(WebInputEvent::kGestureFlingStart, orig);
- event.SetSourceDevice(blink::kWebGestureDeviceTouchscreen);
- event.data.fling_start.velocity_x = 30;
- event.data.fling_start.velocity_y = 40;
- SimulateGestureEvent(event);
- // Fling events don't get sent to the renderer.
- EXPECT_EQ(0u, process_->sink().message_count());
-
- // Progress the fling and check the first GestureScrollUpdate generated by
- // fling progress, note that |at(0)| is TouchScrollStarted.
- base::TimeTicks progress_time =
- base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(17);
- input_router_->ProgressFling(progress_time);
- EXPECT_EQ(2u, process_->sink().message_count());
- const WebGestureEvent* sent_event = static_cast<const WebGestureEvent*>(
- GetInputEventFromMessage(*process_->sink().GetMessageAt(1)));
- TestLocationInSentEvent(sent_event, orig, scaled);
- float sent_delta_x = sent_event->data.scroll_update.delta_x;
- float sent_delta_y = sent_event->data.scroll_update.delta_y;
- EXPECT_LT(0, sent_delta_x);
- EXPECT_LT(0, sent_delta_y);
-
- const WebGestureEvent* filter_event =
- GetFilterWebInputEvent<WebGestureEvent>();
- TestLocationInFilterEvent(filter_event, orig);
- EXPECT_FLOAT_EQ(sent_delta_x, 2 * filter_event->data.scroll_update.delta_x);
- EXPECT_FLOAT_EQ(sent_delta_y, 2 * filter_event->data.scroll_update.delta_y);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc b/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
deleted file mode 100644
index a620b5931fc..00000000000
--- a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2017 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/renderer_host/input/legacy_ipc_widget_input_handler.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/input/ime_text_span_conversions.h"
-#include "content/common/input_messages.h"
-
-namespace content {
-
-LegacyIPCWidgetInputHandler::LegacyIPCWidgetInputHandler(
- LegacyInputRouterImpl* input_router)
- : input_router_(input_router) {}
-LegacyIPCWidgetInputHandler::~LegacyIPCWidgetInputHandler() {}
-
-void LegacyIPCWidgetInputHandler::SetFocus(bool focused) {
- SendInput(std::make_unique<InputMsg_SetFocus>(input_router_->routing_id(),
- focused));
-}
-
-void LegacyIPCWidgetInputHandler::MouseCaptureLost() {}
-
-void LegacyIPCWidgetInputHandler::SetEditCommandsForNextKeyEvent(
- const std::vector<EditCommand>& commands) {
- SendInput(std::make_unique<InputMsg_SetEditCommandsForNextKeyEvent>(
- input_router_->routing_id(), commands));
-}
-
-void LegacyIPCWidgetInputHandler::CursorVisibilityChanged(bool visible) {
- SendInput(std::make_unique<InputMsg_CursorVisibilityChange>(
- input_router_->routing_id(), visible));
-}
-
-void LegacyIPCWidgetInputHandler::ImeSetComposition(
- const base::string16& text,
- const std::vector<ui::ImeTextSpan>& ui_ime_text_spans,
- const gfx::Range& range,
- int32_t start,
- int32_t end) {
- std::vector<blink::WebImeTextSpan> ime_text_spans =
- ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans);
- SendInput(std::make_unique<InputMsg_ImeSetComposition>(
- input_router_->routing_id(), text, ime_text_spans, range, start, end));
-}
-
-void LegacyIPCWidgetInputHandler::ImeCommitText(
- const base::string16& text,
- const std::vector<ui::ImeTextSpan>& ui_ime_text_spans,
- const gfx::Range& range,
- int32_t relative_cursor_position) {
- std::vector<blink::WebImeTextSpan> ime_text_spans =
- ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans);
- SendInput(std::make_unique<InputMsg_ImeCommitText>(
- input_router_->routing_id(), text, ime_text_spans, range,
- relative_cursor_position));
-}
-
-void LegacyIPCWidgetInputHandler::ImeFinishComposingText(bool keep_selection) {
- SendInput(std::make_unique<InputMsg_ImeFinishComposingText>(
- input_router_->routing_id(), keep_selection));
-}
-void LegacyIPCWidgetInputHandler::RequestTextInputStateUpdate() {
-#if defined(OS_ANDROID)
- SendInput(std::make_unique<InputMsg_RequestTextInputStateUpdate>(
- input_router_->routing_id()));
-#endif
-}
-
-void LegacyIPCWidgetInputHandler::RequestCompositionUpdates(
- bool immediate_request,
- bool monitor_request) {
- SendInput(std::make_unique<InputMsg_RequestCompositionUpdates>(
- input_router_->routing_id(), immediate_request, monitor_request));
-}
-
-void LegacyIPCWidgetInputHandler::SendInput(
- std::unique_ptr<IPC::Message> message) {
- input_router_->SendInput(std::move(message));
-}
-
-void LegacyIPCWidgetInputHandler::DispatchEvent(
- std::unique_ptr<content::InputEvent> event,
- DispatchEventCallback callback) {
- // We only expect these events to be called with the mojo enabled input
- // channel. The LegacyInputRouterImpl will handle sending the events
- // directly.
- NOTREACHED();
-}
-
-void LegacyIPCWidgetInputHandler::DispatchNonBlockingEvent(
- std::unique_ptr<content::InputEvent> event) {
- // We only expect these events to be called with the mojo enabled input
- // channel. The LegacyInputRouterImpl will handle sending the events
- // directly.
- NOTREACHED();
-}
-
-void LegacyIPCWidgetInputHandler::AttachSynchronousCompositor(
- mojom::SynchronousCompositorControlHostPtr control_host,
- mojom::SynchronousCompositorHostAssociatedPtrInfo host,
- mojom::SynchronousCompositorAssociatedRequest compositor_request) {
- NOTREACHED();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h b/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
deleted file mode 100644
index c4773667445..00000000000
--- a/chromium/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2017 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_RENDERER_HOST_INPUT_LEGACY_IPC_WIDGET_INPUT_HANDLER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_LEGACY_IPC_WIDGET_INPUT_HANDLER_H_
-
-#include "content/common/input/input_handler.mojom.h"
-
-namespace content {
-
-class LegacyInputRouterImpl;
-
-// An instance of a mojom::WidgetInputHandler based on chrome IPC.
-// This class is a temporary class to allow the input messages to
-// remain as Chrome IPC messages but progressively work at moving
-// them to mojo.
-class CONTENT_EXPORT LegacyIPCWidgetInputHandler
- : public mojom::WidgetInputHandler {
- public:
- explicit LegacyIPCWidgetInputHandler(LegacyInputRouterImpl* input_router);
- ~LegacyIPCWidgetInputHandler() override;
-
- // mojom::WidgetInputHandler overrides.
- void SetFocus(bool focused) override;
- void MouseCaptureLost() override;
- void SetEditCommandsForNextKeyEvent(
- const std::vector<EditCommand>& commands) override;
- void CursorVisibilityChanged(bool visible) override;
- void ImeSetComposition(const base::string16& text,
- const std::vector<ui::ImeTextSpan>& ime_text_spans,
- const gfx::Range& range,
- int32_t start,
- int32_t end) override;
- void ImeCommitText(const base::string16& text,
- const std::vector<ui::ImeTextSpan>& ime_text_spans,
- const gfx::Range& range,
- int32_t relative_cursor_position) override;
- void ImeFinishComposingText(bool keep_selection) override;
- void RequestTextInputStateUpdate() override;
- void RequestCompositionUpdates(bool immediate_request,
- bool monitor_request) override;
- void DispatchEvent(std::unique_ptr<content::InputEvent> event,
- DispatchEventCallback callback) override;
- void DispatchNonBlockingEvent(
- std::unique_ptr<content::InputEvent> event) override;
- void AttachSynchronousCompositor(
- mojom::SynchronousCompositorControlHostPtr control_host,
- mojom::SynchronousCompositorHostAssociatedPtrInfo host,
- mojom::SynchronousCompositorAssociatedRequest compositor_request)
- override;
-
- private:
- void SendInput(std::unique_ptr<IPC::Message> message);
-
- LegacyInputRouterImpl* input_router_;
-
- DISALLOW_COPY_AND_ASSIGN(LegacyIPCWidgetInputHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_LEGACY_IPC_WIDGET_INPUT_HANDLER_H_
diff --git a/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc b/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
index 4dc17f33d2b..3b1595d2e49 100644
--- a/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
@@ -158,7 +158,7 @@ class MainThreadEventQueueBrowserTest : public ContentBrowserTest {
GetWidgetHost(), blink::WebInputEvent::kTouchMove);
for (const auto& event : kEvents)
- GetWidgetHost()->ForwardEmulatedTouchEvent(event);
+ GetWidgetHost()->ForwardEmulatedTouchEvent(event, nullptr);
// Runs until we get the InputMsgAck callback.
EXPECT_EQ(INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING,
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
index c971609225e..33168e98cab 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -65,14 +65,21 @@ void MockInputRouterClient::DidStopFlinging() {
void MockInputRouterClient::DidStartScrollingViewport() {}
-void MockInputRouterClient::SetNeedsBeginFrameForFlingProgress() {}
-
void MockInputRouterClient::ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& latency_info) {
if (input_router_)
input_router_->SendGestureEvent(
GestureEventWithLatencyInfo(gesture_event, latency_info));
+
+ if (gesture_event.SourceDevice() != blink::kWebGestureDeviceTouchpad)
+ return;
+
+ if (gesture_event.GetType() == WebInputEvent::kGestureScrollBegin) {
+ is_wheel_scroll_in_progress_ = true;
+ } else if (gesture_event.GetType() == WebInputEvent::kGestureScrollEnd) {
+ is_wheel_scroll_in_progress_ = false;
+ }
}
void MockInputRouterClient::ForwardWheelEventWithLatencyInfo(
@@ -84,6 +91,10 @@ void MockInputRouterClient::ForwardWheelEventWithLatencyInfo(
}
}
+bool MockInputRouterClient::IsWheelScrollInProgress() {
+ return is_wheel_scroll_in_progress_;
+}
+
bool MockInputRouterClient::GetAndResetFilterEventCalled() {
bool filter_input_event_called = filter_input_event_called_;
filter_input_event_called_ = false;
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.h b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
index 057c571d914..8e161f5ff0e 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -9,6 +9,7 @@
#include <memory>
+#include "content/browser/renderer_host/input/fling_controller.h"
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/common/input/input_event.h"
#include "ui/events/blink/did_overscroll_params.h"
@@ -17,7 +18,8 @@ namespace content {
class InputRouter;
-class MockInputRouterClient : public InputRouterClient {
+class MockInputRouterClient : public InputRouterClient,
+ public FlingControllerSchedulerClient {
public:
MockInputRouterClient();
~MockInputRouterClient() override;
@@ -33,13 +35,14 @@ class MockInputRouterClient : public InputRouterClient {
void OnSetWhiteListedTouchAction(cc::TouchAction touch_action) override;
void DidStopFlinging() override;
void DidStartScrollingViewport() override;
- void SetNeedsBeginFrameForFlingProgress() override;
void ForwardWheelEventWithLatencyInfo(
const blink::WebMouseWheelEvent& wheel_event,
const ui::LatencyInfo& latency_info) override;
void ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& latency_info) override;
+ bool IsWheelScrollInProgress() override;
+ void SetMouseCapture(bool capture) override {}
bool GetAndResetFilterEventCalled();
ui::DidOverscrollParams GetAndResetOverscroll();
@@ -66,6 +69,12 @@ class MockInputRouterClient : public InputRouterClient {
return last_filter_event_->web_event.get();
}
+ // FlingControllerSchedulerClient
+ void ScheduleFlingProgress(
+ base::WeakPtr<FlingController> fling_controller) override {}
+ void DidStopFlingingOnBrowser(
+ base::WeakPtr<FlingController> fling_controller) override {}
+
private:
InputRouter* input_router_;
int in_flight_event_count_;
@@ -79,6 +88,8 @@ class MockInputRouterClient : public InputRouterClient {
ui::DidOverscrollParams overscroll_;
cc::TouchAction white_listed_touch_action_;
+
+ bool is_wheel_scroll_in_progress_ = false;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/motion_event_web.cc b/chromium/content/browser/renderer_host/input/motion_event_web.cc
index 1e9290c540e..7efdfac9ab5 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_web.cc
+++ b/chromium/content/browser/renderer_host/input/motion_event_web.cc
@@ -184,9 +184,7 @@ float MotionEventWeb::GetTiltY(size_t pointer_index) const {
}
base::TimeTicks MotionEventWeb::GetEventTime() const {
- return base::TimeTicks() +
- base::TimeDelta::FromMicroseconds(event_.TimeStampSeconds() *
- base::Time::kMicrosecondsPerSecond);
+ return event_.TimeStamp();
}
ui::MotionEvent::ToolType MotionEventWeb::GetToolType(
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
index 57993daaf3d..c3f4641e852 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
@@ -40,7 +40,6 @@ MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client,
: client_(client),
needs_scroll_begin_when_scroll_latching_disabled_(true),
needs_scroll_end_when_scroll_latching_disabled_(false),
- scroll_in_progress_(false),
enable_scroll_latching_(enable_scroll_latching),
enable_async_wheel_events_(
base::FeatureList::IsEnabled(features::kAsyncWheelEvents) &&
@@ -74,6 +73,38 @@ void MouseWheelEventQueue::QueueEvent(
LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", wheel_queue_.size());
}
+bool MouseWheelEventQueue::CanGenerateGestureScroll(
+ InputEventAckState ack_result) const {
+ if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) {
+ TRACE_EVENT_INSTANT0("input", "Wheel Event Consumed",
+ TRACE_EVENT_SCOPE_THREAD);
+ return false;
+ }
+
+ if (!ui::WebInputEventTraits::CanCauseScroll(
+ event_sent_for_gesture_ack_->event)) {
+ TRACE_EVENT_INSTANT0("input", "Wheel Event Cannot Cause Scroll",
+ TRACE_EVENT_SCOPE_THREAD);
+ return false;
+ }
+
+ if (event_sent_for_gesture_ack_->event.resending_plugin_id != -1) {
+ TRACE_EVENT_INSTANT0("input", "Wheel Event Resending Plugin Id Is Not -1",
+ TRACE_EVENT_SCOPE_THREAD);
+ return false;
+ }
+
+ if (scrolling_device_ != blink::kWebGestureDeviceUninitialized &&
+ scrolling_device_ != blink::kWebGestureDeviceTouchpad) {
+ TRACE_EVENT_INSTANT0("input",
+ "Autoscroll or Touchscreen Scroll In Progress",
+ TRACE_EVENT_SCOPE_THREAD);
+ return false;
+ }
+
+ return true;
+}
+
void MouseWheelEventQueue::ProcessMouseWheelAck(
InputEventAckSource ack_source,
InputEventAckState ack_result,
@@ -87,15 +118,10 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
ack_result);
// If event wasn't consumed then generate a gesture scroll for it.
- if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
- ui::WebInputEventTraits::CanCauseScroll(
- event_sent_for_gesture_ack_->event) &&
- event_sent_for_gesture_ack_->event.resending_plugin_id == -1 &&
- (scrolling_device_ == blink::kWebGestureDeviceUninitialized ||
- scrolling_device_ == blink::kWebGestureDeviceTouchpad)) {
+ if (CanGenerateGestureScroll(ack_result)) {
WebGestureEvent scroll_update(
WebInputEvent::kGestureScrollUpdate, WebInputEvent::kNoModifiers,
- event_sent_for_gesture_ack_->event.TimeStampSeconds(),
+ event_sent_for_gesture_ack_->event.TimeStamp(),
blink::kWebGestureDeviceTouchpad);
scroll_update.SetPositionInWidget(
@@ -181,7 +207,7 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
// For every GSU event record whether it is latched or not.
if (needs_update)
- RecordLatchingUmaMetric(scroll_in_progress_);
+ RecordLatchingUmaMetric(client_->IsWheelScrollInProgress());
if (enable_scroll_latching_) {
bool synthetic = event_sent_for_gesture_ack_->event.has_synthetic_phase;
@@ -190,22 +216,23 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
// Wheel event with phaseBegan must have non-zero deltas.
DCHECK(needs_update);
send_wheel_events_async_ = true;
- SendScrollBegin(scroll_update, synthetic);
+
+ if (!client_->IsWheelScrollInProgress())
+ SendScrollBegin(scroll_update, synthetic);
}
if (needs_update) {
// It is possible that the wheel event with phaseBegan is consumed and
// no GSB is sent.
- if (!scroll_in_progress_)
+ if (!client_->IsWheelScrollInProgress())
SendScrollBegin(scroll_update, synthetic);
ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL);
latency.AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
- 0);
+ ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0);
client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency);
}
- if (current_phase_ended && scroll_in_progress_) {
+ if (current_phase_ended && client_->IsWheelScrollInProgress()) {
// Send GSE when scroll latching is enabled, GSB is sent, and no fling
// is going to happen next.
SendScrollEnd(scroll_update, synthetic);
@@ -236,7 +263,7 @@ void MouseWheelEventQueue::ProcessMouseWheelAck(
ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL);
latency.AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL,
- 0, 0);
+ 0);
client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency);
}
@@ -266,12 +293,13 @@ void MouseWheelEventQueue::OnGestureScrollEvent(
blink::WebInputEvent::kGestureScrollBegin) {
scrolling_device_ = gesture_event.event.SourceDevice();
} else if (scrolling_device_ == gesture_event.event.SourceDevice() &&
- (gesture_event.event.GetType() ==
- blink::WebInputEvent::kGestureScrollEnd ||
- (gesture_event.event.GetType() ==
- blink::WebInputEvent::kGestureFlingStart &&
- scrolling_device_ != blink::kWebGestureDeviceTouchpad))) {
+ gesture_event.event.GetType() ==
+ blink::WebInputEvent::kGestureScrollEnd) {
scrolling_device_ = blink::kWebGestureDeviceUninitialized;
+ } else if (gesture_event.event.GetType() ==
+ blink::WebInputEvent::kGestureFlingStart) {
+ // With browser side fling we shouldn't reset scrolling_device_ on GFS since
+ // the fling_controller processes the GFS to generate and send GSU events.
}
}
@@ -307,12 +335,10 @@ void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event,
(synthetic && !needs_scroll_end_when_scroll_latching_disabled_) ||
needs_scroll_end_when_scroll_latching_disabled_);
- DCHECK(scroll_in_progress_);
- scroll_in_progress_ = false;
+ DCHECK(client_->IsWheelScrollInProgress());
WebGestureEvent scroll_end(update_event);
- scroll_end.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ scroll_end.SetTimeStamp(ui::EventTimeForNow());
scroll_end.SetType(WebInputEvent::kGestureScrollEnd);
scroll_end.resending_plugin_id = -1;
scroll_end.data.scroll_end.synthetic = synthetic;
@@ -336,8 +362,7 @@ void MouseWheelEventQueue::SendScrollBegin(
(synthetic && !needs_scroll_begin_when_scroll_latching_disabled_) ||
needs_scroll_begin_when_scroll_latching_disabled_);
- DCHECK(!scroll_in_progress_);
- scroll_in_progress_ = true;
+ DCHECK(!client_->IsWheelScrollInProgress());
WebGestureEvent scroll_begin(gesture_update);
scroll_begin.SetType(WebInputEvent::kGestureScrollBegin);
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
index 106f166df55..b7042a7f493 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
@@ -33,6 +33,7 @@ class CONTENT_EXPORT MouseWheelEventQueueClient {
virtual void OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
InputEventAckSource ack_source,
InputEventAckState ack_result) = 0;
+ virtual bool IsWheelScrollInProgress() = 0;
};
// A queue for throttling and coalescing mouse wheel events.
@@ -82,6 +83,10 @@ class CONTENT_EXPORT MouseWheelEventQueue {
bool synthetic);
void RecordLatchingUmaMetric(bool latched);
+ // True if gesture scroll events can be generated for the wheel event sent for
+ // ack.
+ bool CanGenerateGestureScroll(InputEventAckState ack_result) const;
+
MouseWheelEventQueueClient* client_;
base::circular_deque<std::unique_ptr<QueuedWebMouseWheelEvent>> wheel_queue_;
@@ -96,9 +101,6 @@ class CONTENT_EXPORT MouseWheelEventQueue {
// This variable is used only when scroll latching is disabled.
bool needs_scroll_end_when_scroll_latching_disabled_;
- // True when a GSB is sent and its corresponding GSE is not sent.
- bool scroll_in_progress_;
-
// True if the touchpad and wheel scroll latching flag is enabled.
bool enable_scroll_latching_;
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
index 7460716e0de..62bfefc9972 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
@@ -10,7 +10,6 @@
#include <utility>
#include "base/location.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/histogram_tester.h"
@@ -194,6 +193,11 @@ class MouseWheelEventQueueTest
WebGestureEvent* cloned_event = new WebGestureEvent();
std::unique_ptr<WebInputEvent> cloned_event_holder(cloned_event);
*cloned_event = event;
+ if (event.GetType() == WebInputEvent::kGestureScrollBegin) {
+ is_wheel_scroll_in_progress_ = true;
+ } else if (event.GetType() == WebInputEvent::kGestureScrollEnd) {
+ is_wheel_scroll_in_progress_ = false;
+ }
sent_events_.push_back(std::move(cloned_event_holder));
}
@@ -205,6 +209,10 @@ class MouseWheelEventQueueTest
last_acked_event_state_ = ack_result;
}
+ bool IsWheelScrollInProgress() override {
+ return is_wheel_scroll_in_progress_;
+ }
+
bool scroll_latching_enabled() { return scroll_latching_enabled_; }
protected:
@@ -344,7 +352,7 @@ class MouseWheelEventQueueTest
void SendGestureEvent(WebInputEvent::Type type) {
WebGestureEvent event(type, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()),
+ ui::EventTimeForNow(),
blink::kWebGestureDeviceTouchscreen);
queue_->OnGestureScrollEvent(
GestureEventWithLatencyInfo(event, ui::LatencyInfo()));
@@ -352,7 +360,8 @@ class MouseWheelEventQueueTest
static void RunTasksAndWait(base::TimeDelta delay) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), delay);
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
+ delay);
base::RunLoop().Run();
}
@@ -535,6 +544,7 @@ class MouseWheelEventQueueTest
bool scroll_latching_enabled_;
private:
+ bool is_wheel_scroll_in_progress_ = false;
base::test::ScopedFeatureList feature_list_;
};
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
index 85864f594da..d1daf8e1aa6 100644
--- a/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
+#include "base/trace_event/trace_event.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -23,6 +24,11 @@ void MouseWheelPhaseHandler::AddPhaseIfNeededAndScheduleEndEvent(
bool has_phase =
mouse_wheel_event.phase != blink::WebMouseWheelEvent::kPhaseNone ||
mouse_wheel_event.momentum_phase != blink::WebMouseWheelEvent::kPhaseNone;
+ TRACE_EVENT2("input",
+ "MouseWheelPhaseHandler::AddPhaseIfNeededAndScheduleEndEvent",
+ "has_phase", has_phase, "touchpad_scroll_phase_state",
+ touchpad_scroll_phase_state_);
+
if (has_phase) {
if (mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseEnded) {
// Don't send the wheel end event immediately, start a timer instead to
@@ -94,16 +100,25 @@ void MouseWheelPhaseHandler::DispatchPendingWheelEndEvent() {
if (!mouse_wheel_end_dispatch_timer_.IsRunning())
return;
+ TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler Dispatched",
+ TRACE_EVENT_SCOPE_THREAD);
base::Closure task = mouse_wheel_end_dispatch_timer_.user_task();
mouse_wheel_end_dispatch_timer_.Stop();
std::move(task).Run();
}
void MouseWheelPhaseHandler::IgnorePendingWheelEndEvent() {
+ if (!mouse_wheel_end_dispatch_timer_.IsRunning())
+ return;
+
+ TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler Ignored",
+ TRACE_EVENT_SCOPE_THREAD);
mouse_wheel_end_dispatch_timer_.Stop();
}
void MouseWheelPhaseHandler::ResetTouchpadScrollSequence() {
+ TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler Reset",
+ TRACE_EVENT_SCOPE_THREAD);
touchpad_scroll_phase_state_ = TOUCHPAD_SCROLL_STATE_UNKNOWN;
}
@@ -117,6 +132,8 @@ void MouseWheelPhaseHandler::SendWheelEndForTouchpadScrollingIfNeeded() {
bool should_route_event = widget_host->delegate() &&
widget_host->delegate()->GetInputEventRouter();
+ TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler Sent touchpad end",
+ TRACE_EVENT_SCOPE_THREAD);
SendSyntheticWheelEventWithPhaseEnded(should_route_event);
}
@@ -131,14 +148,17 @@ void MouseWheelPhaseHandler::TouchpadScrollingMayBegin() {
DispatchPendingWheelEndEvent();
}
+ TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler May Begin",
+ TRACE_EVENT_SCOPE_THREAD);
touchpad_scroll_phase_state_ = TOUCHPAD_SCROLL_MAY_BEGIN;
}
void MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded(
bool should_route_event) {
+ TRACE_EVENT0("input",
+ "MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded");
DCHECK(host_view_->wheel_scroll_latching_enabled());
- last_mouse_wheel_event_.SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ last_mouse_wheel_event_.SetTimeStamp(ui::EventTimeForNow());
last_mouse_wheel_event_.delta_x = 0;
last_mouse_wheel_event_.delta_y = 0;
last_mouse_wheel_event_.wheel_ticks_x = 0;
@@ -165,6 +185,8 @@ void MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded(
void MouseWheelPhaseHandler::ScheduleMouseWheelEndDispatching(
bool should_route_event,
const base::TimeDelta timeout) {
+ TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler timer started",
+ TRACE_EVENT_SCOPE_THREAD);
mouse_wheel_end_dispatch_timer_.Start(
FROM_HERE, timeout,
base::Bind(&MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded,
diff --git a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.cc b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
index cb692ca6b5d..fb399050cc7 100644
--- a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
@@ -75,7 +75,7 @@ void PassthroughTouchEventQueue::SendTouchCancelEventForTouchEvent(
WebTouchEventTraits::ResetTypeAndTouchStates(
WebInputEvent::kTouchCancel,
// TODO(rbyers): Shouldn't we use a fresh timestamp?
- event.event.TimeStampSeconds(), &event.event);
+ event.event.TimeStamp(), &event.event);
SendTouchEventImmediately(&event, false);
}
@@ -104,9 +104,9 @@ void PassthroughTouchEventQueue::PrependTouchScrollNotification() {
TRACE_EVENT0("input",
"PassthroughTouchEventQueue::PrependTouchScrollNotification");
- TouchEventWithLatencyInfo touch(
- WebInputEvent::kTouchScrollStarted, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()), LatencyInfo());
+ TouchEventWithLatencyInfo touch(WebInputEvent::kTouchScrollStarted,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow(), LatencyInfo());
touch.event.dispatch_type = WebInputEvent::kEventNonBlocking;
SendTouchEventImmediately(&touch, true);
}
diff --git a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
index 59148caf04b..0677a6df8f6 100644
--- a/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
@@ -12,7 +12,6 @@
#include "base/containers/circular_deque.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/scoped_task_environment.h"
@@ -135,7 +134,7 @@ class PassthroughTouchEventQueueTest : public testing::Test,
void SendGestureEvent(WebInputEvent::Type type) {
WebGestureEvent event(type, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ ui::EventTimeForNow());
queue_->OnGestureScrollEvent(
GestureEventWithLatencyInfo(event, ui::LatencyInfo()));
}
@@ -165,9 +164,8 @@ class PassthroughTouchEventQueueTest : public testing::Test,
void SendGestureEventAck(WebInputEvent::Type type,
InputEventAckState ack_result) {
- GestureEventWithLatencyInfo event(
- type, blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()), ui::LatencyInfo());
+ GestureEventWithLatencyInfo event(type, blink::WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow(), ui::LatencyInfo());
queue_->OnGestureEventAck(event, ack_result);
}
@@ -213,8 +211,7 @@ class PassthroughTouchEventQueueTest : public testing::Test,
touch_event_.touches[index].state = WebTouchPoint::kStateMoved;
touch_event_.moved_beyond_slop_region = true;
WebTouchEventTraits::ResetType(WebInputEvent::kTouchMove,
- touch_event_.TimeStampSeconds(),
- &touch_event_);
+ touch_event_.TimeStamp(), &touch_event_);
SendTouchEvent();
}
@@ -226,8 +223,7 @@ class PassthroughTouchEventQueueTest : public testing::Test,
touch_event_.touches[index].state = WebTouchPoint::kStateMoved;
touch_event_.moved_beyond_slop_region = true;
WebTouchEventTraits::ResetType(WebInputEvent::kTouchMove,
- touch_event_.TimeStampSeconds(),
- &touch_event_);
+ touch_event_.TimeStamp(), &touch_event_);
SendTouchEvent();
}
@@ -239,8 +235,7 @@ class PassthroughTouchEventQueueTest : public testing::Test,
touch_event_.touches[index].state = WebTouchPoint::kStateMoved;
touch_event_.moved_beyond_slop_region = true;
WebTouchEventTraits::ResetType(WebInputEvent::kTouchMove,
- touch_event_.TimeStampSeconds(),
- &touch_event_);
+ touch_event_.TimeStamp(), &touch_event_);
SendTouchEvent();
}
@@ -259,7 +254,8 @@ class PassthroughTouchEventQueueTest : public testing::Test,
}
void AdvanceTouchTime(double seconds) {
- touch_event_.SetTimeStampSeconds(touch_event_.TimeStampSeconds() + seconds);
+ touch_event_.SetTimeStamp(touch_event_.TimeStamp() +
+ base::TimeDelta::FromSecondsD(seconds));
}
void ResetTouchEvent() { touch_event_ = SyntheticWebTouchEvent(); }
@@ -315,7 +311,8 @@ class PassthroughTouchEventQueueTest : public testing::Test,
static void RunTasksAndWait(base::TimeDelta delay) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), delay);
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
+ delay);
base::RunLoop().Run();
}
@@ -699,9 +696,9 @@ TEST_F(PassthroughTouchEventQueueTest, AckWithFollowupEvents) {
// Create a touch event that will be queued synchronously by a touch ack.
// Note, this will be triggered by all subsequent touch acks.
- WebTouchEvent followup_event(
- WebInputEvent::kTouchMove, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebTouchEvent followup_event(WebInputEvent::kTouchMove,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
followup_event.touches_length = 1;
followup_event.touches[0].id = 0;
followup_event.touches[0].state = WebTouchPoint::kStateMoved;
@@ -786,9 +783,9 @@ TEST_F(PassthroughTouchEventQueueTest, SynchronousAcksInOrder) {
EXPECT_EQ(0U, GetAndResetAckedEventCount());
// Create a touch event that will be queued synchronously by a touch ack.
- WebTouchEvent followup_event(
- WebInputEvent::kTouchMove, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebTouchEvent followup_event(WebInputEvent::kTouchMove,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
followup_event.touches_length = 1;
followup_event.touches[0].id = 0;
followup_event.unique_touch_event_id = 100;
@@ -809,9 +806,9 @@ TEST_F(PassthroughTouchEventQueueTest, SynchronousAcksInOrder) {
// TouchEventQueue::QueueEvent() are properly handled.
TEST_F(PassthroughTouchEventQueueTest, ImmediateAckWithFollowupEvents) {
// Create a touch event that will be queued synchronously by a touch ack.
- WebTouchEvent followup_event(
- WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebTouchEvent followup_event(WebInputEvent::kTouchStart,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
followup_event.touches_length = 1;
followup_event.touches[0].id = 1;
followup_event.touches[0].state = WebTouchPoint::kStatePressed;
@@ -820,9 +817,9 @@ TEST_F(PassthroughTouchEventQueueTest, ImmediateAckWithFollowupEvents) {
// Now, enqueue a stationary touch that will not be forwarded. This should be
// immediately ack'ed with "NO_CONSUMER_EXISTS". The followup event should
// then be enqueued and immediately sent to the renderer.
- WebTouchEvent stationary_event(
- WebInputEvent::kTouchMove, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebTouchEvent stationary_event(WebInputEvent::kTouchMove,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
stationary_event.touches_length = 1;
stationary_event.touches[0].id = 1;
stationary_event.touches[0].state = WebTouchPoint::kStateStationary;
@@ -1143,9 +1140,9 @@ TEST_F(PassthroughTouchEventQueueTest, TouchTimeoutWithFollowupGesture) {
EXPECT_EQ(1U, GetAndResetSentEventCount());
// The cancelled sequence may turn into a scroll gesture.
- WebGestureEvent followup_scroll(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebGestureEvent followup_scroll(WebInputEvent::kGestureScrollBegin,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
SetFollowupEvent(followup_scroll);
// Delay the ack.
@@ -1200,9 +1197,9 @@ TEST_F(PassthroughTouchEventQueueTest,
EXPECT_EQ(1U, GetAndResetSentEventCount());
// The cancelled sequence may turn into a scroll gesture.
- WebGestureEvent followup_scroll(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebGestureEvent followup_scroll(WebInputEvent::kGestureScrollBegin,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
SetFollowupEvent(followup_scroll);
// Delay the ack.
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
index 929d3950ea8..185919454c6 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -33,104 +33,11 @@ ukm::SourceId GenerateUkmSourceId() {
return ukm_recorder ? ukm_recorder->GetNewSourceID() : ukm::kInvalidSourceId;
}
-// LatencyComponents generated in the renderer must have component IDs
-// provided to them by the browser process. This function adds the correct
-// component ID where necessary.
-void AddLatencyInfoComponentIds(LatencyInfo* latency,
- int64_t latency_component_id) {
- std::vector<std::pair<ui::LatencyComponentType, int64_t>> new_components_key;
- std::vector<LatencyInfo::LatencyComponent> new_components_value;
- for (const auto& lc : latency->latency_components()) {
- ui::LatencyComponentType component_type = lc.first.first;
- if (component_type == ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
- // Generate a new component entry with the correct component ID
- new_components_key.push_back(std::make_pair(component_type,
- latency_component_id));
- new_components_value.push_back(lc.second);
- }
- }
-
- // Remove the entries with invalid component IDs.
- latency->RemoveLatency(ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT);
-
- // Add newly generated components into the latency info
- for (size_t i = 0; i < new_components_key.size(); i++) {
- latency->AddLatencyNumberWithTimestamp(
- new_components_key[i].first,
- new_components_key[i].second,
- new_components_value[i].sequence_number,
- new_components_value[i].event_time,
- new_components_value[i].event_count);
- }
-}
-
-void RecordEQTAccuracy(base::TimeDelta queueing_time,
- base::TimeDelta expected_queueing_time) {
- float queueing_time_ms = queueing_time.InMillisecondsF();
-
- if (queueing_time_ms < 10) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.10ms",
- expected_queueing_time);
- }
-
- if (queueing_time_ms < 150) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.150ms",
- expected_queueing_time);
- }
-
- if (queueing_time_ms < 300) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.300ms",
- expected_queueing_time);
- }
-
- if (queueing_time_ms < 450) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.450ms",
- expected_queueing_time);
- }
-
- if (queueing_time_ms > 10) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.10ms",
- expected_queueing_time);
- }
-
- if (queueing_time_ms > 150) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.150ms",
- expected_queueing_time);
- }
-
- if (queueing_time_ms > 300) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.300ms",
- expected_queueing_time);
- }
-
- if (queueing_time_ms > 450) {
- UMA_HISTOGRAM_TIMES(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.450ms",
- expected_queueing_time);
- }
-}
-
} // namespace
RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker(
- bool metric_sampling,
RenderWidgetHostDelegate* delegate)
- : LatencyTracker(metric_sampling, GenerateUkmSourceId()),
+ : ukm_source_id_(GenerateUkmSourceId()),
last_event_id_(0),
latency_component_id_(0),
has_seen_first_gesture_scroll_update_(false),
@@ -199,10 +106,6 @@ void RenderWidgetHostLatencyTracker::ComputeInputLatencyHistograms(
UMA_HISTOGRAM_INPUT_LATENCY_MILLISECONDS(
"Event.Latency.QueueingTime." + event_name + default_action_status,
rwh_component, main_component);
-
- RecordEQTAccuracy(
- main_component.last_event_time - rwh_component.first_event_time,
- latency.expected_queueing_time_on_dispatch());
}
}
@@ -227,9 +130,9 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
OnEventStart(latency);
if (!set_url_for_ukm_ && render_widget_host_delegate_ &&
- ukm_source_id() != ukm::kInvalidSourceId) {
+ ukm_source_id_ != ukm::kInvalidSourceId) {
render_widget_host_delegate_->UpdateUrlForUkmSource(ukm::UkmRecorder::Get(),
- ukm_source_id());
+ ukm_source_id_);
set_url_for_ukm_ = true;
}
@@ -252,13 +155,11 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
latency_component_id_, nullptr);
DCHECK(!found_component);
- if (event.TimeStampSeconds() &&
+ if (!event.TimeStamp().is_null() &&
!latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
nullptr)) {
base::TimeTicks timestamp_now = base::TimeTicks::Now();
- base::TimeTicks timestamp_original =
- base::TimeTicks() +
- base::TimeDelta::FromSecondsD(event.TimeStampSeconds());
+ base::TimeTicks timestamp_original = event.TimeStamp();
// Timestamp from platform input can wrap, e.g. 32 bits timestamp
// for Xserver and Window MSG time will wrap about 49.6 days. Do a
@@ -270,14 +171,13 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
latency->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
0,
- 0,
timestamp_original,
1);
}
latency->AddLatencyNumberWithTraceName(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, latency_component_id_,
- ++last_event_id_, WebInputEvent::GetName(event.GetType()));
+ WebInputEvent::GetName(event.GetType()));
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
has_seen_first_gesture_scroll_update_ = false;
@@ -292,8 +192,8 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
has_seen_first_gesture_scroll_update_
? ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT
: ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- latency_component_id_, original_component.sequence_number,
- original_component.event_time, original_component.event_count);
+ latency_component_id_, original_component.event_time,
+ original_component.event_count);
}
has_seen_first_gesture_scroll_update_ = true;
@@ -323,25 +223,23 @@ void RenderWidgetHostLatencyTracker::OnInputEventAck(
}
}
- latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
+ latency->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0);
// If this event couldn't have caused a gesture event, and it didn't trigger
// rendering, we're done processing it. If the event got coalesced then
// terminate it as well.
if (!rendering_scheduled || latency->coalesced()) {
latency->AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, 0);
+ ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0);
}
ComputeInputLatencyHistograms(event.GetType(), latency_component_id_,
*latency, ack_result);
}
-void RenderWidgetHostLatencyTracker::OnSwapCompositorFrame(
- std::vector<LatencyInfo>* latencies) {
- DCHECK(latencies);
- for (LatencyInfo& latency : *latencies) {
- AddLatencyInfoComponentIds(&latency, latency_component_id_);
- }
+void RenderWidgetHostLatencyTracker::OnEventStart(ui::LatencyInfo* latency) {
+ static uint64_t global_trace_id = 0;
+ latency->set_trace_id(++global_trace_id);
+ latency->set_ukm_source_id(ukm_source_id_);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
index b0424d51890..5f51b9170ab 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
@@ -22,11 +22,9 @@ class RenderWidgetHostDelegate;
// Utility class for tracking the latency of events passing through
// a given RenderWidgetHost.
-class CONTENT_EXPORT RenderWidgetHostLatencyTracker
- : public ui::LatencyTracker {
+class CONTENT_EXPORT RenderWidgetHostLatencyTracker {
public:
- RenderWidgetHostLatencyTracker(bool metric_sampling,
- RenderWidgetHostDelegate* delegate);
+ RenderWidgetHostLatencyTracker(RenderWidgetHostDelegate* delegate);
virtual ~RenderWidgetHostLatencyTracker();
// Associates the latency tracker with a given route and process.
@@ -52,11 +50,6 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker
ui::LatencyInfo* latency,
InputEventAckState ack_result);
- // Populates renderer-created LatencyInfo entries with the appropriate latency
- // component id. Called when the RenderWidgetHost receives a compositor swap
- // update from the renderer.
- void OnSwapCompositorFrame(std::vector<ui::LatencyInfo>* latencies);
-
void reset_delegate() { render_widget_host_delegate_ = nullptr; }
// Returns the ID that uniquely describes this component to the latency
@@ -64,6 +57,9 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker
int64_t latency_component_id() const { return latency_component_id_; }
private:
+ void OnEventStart(ui::LatencyInfo* latency);
+
+ ukm::SourceId ukm_source_id_;
int64_t last_event_id_;
int64_t latency_component_id_;
bool has_seen_first_gesture_scroll_update_;
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
index e1cbac94ade..629d56804fd 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -34,23 +34,23 @@ void AddFakeComponentsWithTimeStamp(
ui::LatencyInfo* latency,
base::TimeTicks time_stamp) {
latency->AddLatencyNumberWithTimestamp(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
- 0, 0, time_stamp, 1);
+ 0, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0, time_stamp,
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, time_stamp,
1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, time_stamp, 1);
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, 0, time_stamp, 1);
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, time_stamp, 1);
latency->AddLatencyNumberWithTimestamp(
- ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, 0, 0, time_stamp, 1);
+ ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, 0, time_stamp, 1);
}
void AddFakeComponents(const RenderWidgetHostLatencyTracker& tracker,
ui::LatencyInfo* latency) {
latency->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker.latency_component_id(), 0, base::TimeTicks::Now(), 1);
+ tracker.latency_component_id(), base::TimeTicks::Now(), 1);
AddFakeComponentsWithTimeStamp(tracker, latency, base::TimeTicks::Now());
}
@@ -59,12 +59,12 @@ void AddRenderingScheduledComponent(ui::LatencyInfo* latency,
base::TimeTicks time_stamp) {
if (main) {
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0,
time_stamp, 1);
} else {
latency->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0,
time_stamp, 1);
}
}
@@ -121,6 +121,8 @@ class RenderWidgetHostLatencyTrackerTest
}
RenderWidgetHostLatencyTracker* tracker() { return tracker_.get(); }
+ ui::LatencyTracker* viz_tracker() { return &viz_tracker_; }
+
void ResetHistograms() {
histogram_tester_.reset(new base::HistogramTester());
}
@@ -132,9 +134,9 @@ class RenderWidgetHostLatencyTrackerTest
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
- tracker_ =
- std::make_unique<RenderWidgetHostLatencyTracker>(false, contents());
+ tracker_ = std::make_unique<RenderWidgetHostLatencyTracker>(contents());
tracker_->Initialize(kTestRoutingId, kTestProcessId);
+ viz_tracker_.DisableMetricSamplingForTesting();
}
void TearDown() override {
@@ -149,6 +151,7 @@ class RenderWidgetHostLatencyTrackerTest
const int kTestProcessId = 1;
std::unique_ptr<base::HistogramTester> histogram_tester_;
std::unique_ptr<RenderWidgetHostLatencyTracker> tracker_;
+ ui::LatencyTracker viz_tracker_;
RenderWidgetHostLatencyTrackerTestBrowserClient test_browser_client_;
ContentBrowserClient* old_browser_client_;
};
@@ -161,40 +164,42 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestValidEventTiming) {
latency_info.set_source_event_type(ui::SourceEventType::WHEEL);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, 0,
now + base::TimeDelta::FromMilliseconds(60), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0,
now + base::TimeDelta::FromMilliseconds(50), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0,
now + base::TimeDelta::FromMilliseconds(40), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, 0, 0,
+ ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, 0,
now + base::TimeDelta::FromMilliseconds(30), 1);
latency_info.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
now + base::TimeDelta::FromMilliseconds(20), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0,
now + base::TimeDelta::FromMilliseconds(10), 1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0, now, 1);
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, now, 1);
- tracker()->OnGpuSwapBuffersCompleted(latency_info);
+ viz_tracker()->OnGpuSwapBuffersCompleted(latency_info);
// When last_event_time of the end_component is less than the first_event_time
// of the start_component, zero is recorded instead of a negative value.
histogram_tester().ExpectUniqueSample(
"Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin2", 0, 1);
histogram_tester().ExpectUniqueSample(
+ "Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin4", 0, 1);
+ histogram_tester().ExpectUniqueSample(
"Event.Latency.Scroll.Wheel.TimeToScrollUpdateSwapBegin2", 0, 1);
histogram_tester().ExpectUniqueSample(
"Event.Latency.ScrollBegin.Wheel.TimeToHandled2_Impl", 0, 1);
@@ -220,11 +225,11 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) {
auto wheel = SyntheticWebMouseWheelEventBuilder::Build(
blink::WebMouseWheelEvent::kPhaseChanged);
base::TimeTicks now = base::TimeTicks::Now();
- wheel.SetTimeStampSeconds((now - base::TimeTicks()).InSecondsF());
+ wheel.SetTimeStamp(now);
ui::LatencyInfo wheel_latency(ui::SourceEventType::WHEEL);
wheel_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), 0, now, 1);
+ tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &wheel_latency, now);
AddRenderingScheduledComponent(&wheel_latency, rendering_on_main, now);
tracker()->OnInputEvent(wheel, &wheel_latency);
@@ -235,7 +240,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) {
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
tracker()->OnInputEventAck(wheel, &wheel_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- tracker()->OnGpuSwapBuffersCompleted(wheel_latency);
+ viz_tracker()->OnGpuSwapBuffersCompleted(wheel_latency);
// UKM metrics.
total_ukm_entry_count++;
@@ -246,10 +251,22 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) {
// UMA histograms.
EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollBegin."
+ "TimeToScrollUpdateSwapBegin2",
+ 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate."
+ "TimeToScrollUpdateSwapBegin2",
+ 0));
+ EXPECT_TRUE(
HistogramSizeEq("Event.Latency.ScrollBegin.Wheel."
"TimeToScrollUpdateSwapBegin2",
1));
EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollBegin.Wheel."
+ "TimeToScrollUpdateSwapBegin4",
+ 1));
+ EXPECT_TRUE(
HistogramSizeEq("Event.Latency.Scroll.Wheel."
"TimeToScrollUpdateSwapBegin2",
1));
@@ -258,6 +275,10 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) {
"TimeToScrollUpdateSwapBegin2",
0));
EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.Wheel."
+ "TimeToScrollUpdateSwapBegin4",
+ 0));
+ EXPECT_TRUE(
HistogramSizeEq("Event.Latency.ScrollBegin.Wheel.TimeToHandled2_Main",
rendering_on_main ? 1 : 0));
EXPECT_TRUE(
@@ -316,11 +337,11 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
auto wheel = SyntheticWebMouseWheelEventBuilder::Build(
blink::WebMouseWheelEvent::kPhaseChanged);
base::TimeTicks now = base::TimeTicks::Now();
- wheel.SetTimeStampSeconds((now - base::TimeTicks()).InSecondsF());
+ wheel.SetTimeStamp(now);
ui::LatencyInfo wheel_latency(ui::SourceEventType::WHEEL);
wheel_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), 0, now, 1);
+ tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &wheel_latency, now);
AddRenderingScheduledComponent(&wheel_latency, rendering_on_main, now);
tracker()->OnInputEvent(wheel, &wheel_latency);
@@ -331,7 +352,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
tracker()->OnInputEventAck(wheel, &wheel_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- tracker()->OnGpuSwapBuffersCompleted(wheel_latency);
+ viz_tracker()->OnGpuSwapBuffersCompleted(wheel_latency);
// UKM metrics.
total_ukm_entry_count++;
@@ -342,10 +363,22 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
// UMA histograms.
EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollBegin."
+ "TimeToScrollUpdateSwapBegin2",
+ 0));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate."
+ "TimeToScrollUpdateSwapBegin2",
+ 1));
+ EXPECT_TRUE(
HistogramSizeEq("Event.Latency.ScrollBegin.Wheel."
"TimeToScrollUpdateSwapBegin2",
0));
EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollBegin.Wheel."
+ "TimeToScrollUpdateSwapBegin4",
+ 0));
+ EXPECT_TRUE(
HistogramSizeEq("Event.Latency.Scroll.Wheel."
"TimeToScrollUpdateSwapBegin2",
1));
@@ -353,6 +386,10 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
HistogramSizeEq("Event.Latency.ScrollUpdate.Wheel."
"TimeToScrollUpdateSwapBegin2",
1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.Wheel."
+ "TimeToScrollUpdateSwapBegin4",
+ 1));
EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollBegin.Wheel.TimeToHandled2_Main", 0));
@@ -403,6 +440,65 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToScrollHistograms) {
}
}
+TEST_F(RenderWidgetHostLatencyTrackerTest, TestInertialToScrollHistograms) {
+ const GURL url(kUrl);
+ contents()->NavigateAndCommit(url);
+ for (bool rendering_on_main : {false, true}) {
+ ResetHistograms();
+ {
+ auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
+ 5.f, -5.f, 0, blink::kWebGestureDeviceTouchscreen);
+ base::TimeTicks now = base::TimeTicks::Now();
+ scroll.SetTimeStamp(now);
+ ui::LatencyInfo scroll_latency(ui::SourceEventType::INERTIAL);
+ scroll_latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ tracker()->latency_component_id(), now, 1);
+ AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
+ AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
+ tracker()->OnInputEvent(scroll, &scroll_latency);
+ EXPECT_TRUE(scroll_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), nullptr));
+ EXPECT_TRUE(scroll_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ tracker()->OnInputEventAck(scroll, &scroll_latency,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ viz_tracker()->OnGpuSwapBuffersCompleted(scroll_latency);
+ }
+
+ // UMA histograms.
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollInertial.Touch."
+ "TimeToScrollUpdateSwapBegin2",
+ 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollInertial.Touch."
+ "TimeToScrollUpdateSwapBegin4",
+ 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollInertial.Touch.TimeToHandled2_Main",
+ rendering_on_main ? 1 : 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollInertial.Touch.TimeToHandled2_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollInertial.Touch.HandledToRendererSwap2_Main",
+ rendering_on_main ? 1 : 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollInertial.Touch.HandledToRendererSwap2_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollInertial.Touch.RendererSwapToBrowserNotified2",
+ 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollInertial.Touch.BrowserNotifiedToBeforeGpuSwap2",
+ 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollInertial.Touch.GpuSwap2", 1));
+ }
+}
+
TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
const GURL url(kUrl);
contents()->NavigateAndCommit(url);
@@ -413,11 +509,11 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
5.f, -5.f, 0, blink::kWebGestureDeviceTouchscreen);
base::TimeTicks now = base::TimeTicks::Now();
- scroll.SetTimeStampSeconds((now - base::TimeTicks()).InSecondsF());
+ scroll.SetTimeStamp(now);
ui::LatencyInfo scroll_latency;
scroll_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), 0, now, 1);
+ tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
tracker()->OnInputEvent(scroll, &scroll_latency);
@@ -438,7 +534,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
base::TimeTicks now = base::TimeTicks::Now();
touch_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), 0, now, 1);
+ tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, now);
AddRenderingScheduledComponent(&touch_latency, rendering_on_main, now);
tracker()->OnInputEvent(touch, &touch_latency);
@@ -449,7 +545,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
tracker()->OnInputEventAck(touch, &touch_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- tracker()->OnGpuSwapBuffersCompleted(touch_latency);
+ viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency);
}
// UKM metrics.
@@ -460,11 +556,23 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) {
total_ukm_entry_count);
// UMA histograms.
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollBegin."
+ "TimeToScrollUpdateSwapBegin2",
+ 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate."
+ "TimeToScrollUpdateSwapBegin2",
+ 0));
EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin2", 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4", 1));
EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4", 0));
EXPECT_TRUE(
HistogramSizeEq("Event.Latency.ScrollBegin.Touch.TimeToHandled2_Main",
@@ -515,11 +623,11 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
5.f, -5.f, 0, blink::kWebGestureDeviceTouchscreen);
base::TimeTicks now = base::TimeTicks::Now();
- scroll.SetTimeStampSeconds((now - base::TimeTicks()).InSecondsF());
+ scroll.SetTimeStamp(now);
ui::LatencyInfo scroll_latency;
scroll_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), 0, now, 1);
+ tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &scroll_latency, now);
AddRenderingScheduledComponent(&scroll_latency, rendering_on_main, now);
tracker()->OnInputEvent(scroll, &scroll_latency);
@@ -540,7 +648,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
base::TimeTicks now = base::TimeTicks::Now();
touch_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker()->latency_component_id(), 0, now, 1);
+ tracker()->latency_component_id(), now, 1);
AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, now);
AddRenderingScheduledComponent(&touch_latency, rendering_on_main, now);
tracker()->OnInputEvent(touch, &touch_latency);
@@ -551,7 +659,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
tracker()->OnInputEventAck(touch, &touch_latency,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- tracker()->OnGpuSwapBuffersCompleted(touch_latency);
+ viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency);
}
// UKM metrics.
@@ -562,11 +670,23 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToScrollHistograms) {
total_ukm_entry_count);
// UMA histograms.
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollBegin."
+ "TimeToScrollUpdateSwapBegin2",
+ 0));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate."
+ "TimeToScrollUpdateSwapBegin2",
+ 1));
EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin2", 0));
EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4", 0));
+ EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", 1));
EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4", 1));
+ EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollBegin.Touch.TimeToHandled2_Main", 0));
EXPECT_TRUE(HistogramSizeEq(
"Event.Latency.ScrollBegin.Touch.TimeToHandled2_Impl", 0));
@@ -696,7 +816,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto scroll_begin = SyntheticWebGestureEventBuilder::BuildScrollBegin(
5, -5, blink::kWebGestureDeviceTouchscreen);
ui::LatencyInfo scroll_latency;
- scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
0);
tracker()->OnInputEvent(scroll_begin, &scroll_latency);
EXPECT_TRUE(
@@ -709,7 +829,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto first_scroll_update = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
5.f, -5.f, 0, blink::kWebGestureDeviceTouchscreen);
scroll_latency = ui::LatencyInfo();
- scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
0);
tracker()->OnInputEvent(first_scroll_update, &scroll_latency);
EXPECT_TRUE(
@@ -728,7 +848,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto scroll_update = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
-5.f, 5.f, 0, blink::kWebGestureDeviceTouchscreen);
scroll_latency = ui::LatencyInfo();
- scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
0);
tracker()->OnInputEvent(scroll_update, &scroll_latency);
EXPECT_TRUE(
@@ -765,19 +885,19 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[2]),
1);
@@ -812,19 +932,19 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchmove_timestamps_ms[2]),
1);
@@ -856,19 +976,19 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TouchBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchend_timestamps_ms[2]),
1);
@@ -959,19 +1079,19 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, KeyBlockingAndQueueingTime) {
fake_latency.set_source_event_type(ui::SourceEventType::KEY_PRESS);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(event_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(event_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(event_timestamps_ms[2]),
1);
@@ -1012,31 +1132,31 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, KeyEndToEndLatency) {
latency_info.set_trace_id(kTraceEventId);
latency_info.set_source_event_type(ui::SourceEventType::KEY_PRESS);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[0]),
1);
latency_info.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[0]),
1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[1]),
1);
latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMicroseconds(event_timestamps_microseconds[1]),
1);
- tracker()->OnGpuSwapBuffersCompleted(latency_info);
+ viz_tracker()->OnGpuSwapBuffersCompleted(latency_info);
EXPECT_THAT(
histogram_tester().GetAllSamples("Event.Latency.EndToEnd.KeyPress"),
@@ -1072,19 +1192,19 @@ TEST_F(RenderWidgetHostLatencyTrackerTest,
fake_latency.set_trace_id(kTraceEventId);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
base::TimeTicks() +
base::TimeDelta::FromMilliseconds(touchstart_timestamps_ms[2]),
1);
@@ -1143,17 +1263,17 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, WheelDuringMultiFingerTouch) {
fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
fake_latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0,
+ tracker()->latency_component_id(),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[0]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[1]),
1);
fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0,
base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[2]),
1);
@@ -1171,90 +1291,4 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, WheelDuringMultiFingerTouch) {
ElementsAre(Bucket(14, 1)));
}
-TEST_F(RenderWidgetHostLatencyTrackerTest, ExpectedQueueingTimeAccuracy) {
- // These numbers are sensitive to where the histogram buckets are.
- base::TimeTicks event_timestamp =
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(11);
- int expected_queueing_time_ms = 1;
- base::TimeDelta expected_queueing_time =
- base::TimeDelta::FromMilliseconds(expected_queueing_time_ms);
-
- for (float queueing_time_ms : {2, 15, 200, 400}) {
- base::TimeDelta queueing_time =
- base::TimeDelta::FromMilliseconds(queueing_time_ms);
- SyntheticWebTouchEvent event;
- // Touch start.
- event.PressPoint(1, 1);
-
- ui::LatencyInfo latency;
- latency.set_source_event_type(ui::SourceEventType::TOUCH);
- tracker()->OnInputEvent(event, &latency);
-
- ui::LatencyInfo fake_latency;
- fake_latency.set_trace_id(kTraceEventId);
- fake_latency.set_expected_queueing_time_on_dispatch(expected_queueing_time);
- fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
- fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker()->latency_component_id(), 0, event_timestamp, 1);
-
- fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0, 0,
- event_timestamp + queueing_time, 1);
-
- fake_latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0,
- event_timestamp + queueing_time, 1);
-
- // Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
- // overwriting components.
- tracker()->ComputeInputLatencyHistograms(
- event.GetType(), tracker()->latency_component_id(), fake_latency,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- tracker()->OnInputEventAck(event, &latency,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- }
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.10ms"),
- ElementsAre(Bucket(expected_queueing_time_ms, 1)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.150ms"),
- ElementsAre(Bucket(expected_queueing_time_ms, 2)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.300ms"),
- ElementsAre(Bucket(expected_queueing_time_ms, 3)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_LessThan.450ms"),
- ElementsAre(Bucket(expected_queueing_time_ms, 4)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.10ms"),
- ElementsAre(Bucket(expected_queueing_time_ms, 3)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.150ms"),
- ElementsAre(Bucket(expected_queueing_time_ms, 2)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.300ms"),
- ElementsAre(Bucket(expected_queueing_time_ms, 1)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "RendererScheduler."
- "ExpectedQueueingTimeWhenQueueingTime_GreaterThan.450ms"),
- ElementsAre());
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc b/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
index 3918ef2265a..156ca38da6e 100644
--- a/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -68,7 +68,7 @@ class ScrollLatencyBrowserTest : public ContentBrowserTest {
}
void WaitAFrame() {
- while (!GetWidgetHost()->ScheduleComposite())
+ while (!GetWidgetHost()->RequestRepaintForTesting())
GiveItSomeTime();
frame_observer_->Wait();
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index 544b8944583..33c478a33f8 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -151,6 +151,7 @@ class MockSyntheticGestureTarget : public SyntheticGestureTarget {
}
float GetTouchSlopInDips() const override { return kTouchSlopInDips; }
+ float GetSpanSlopInDips() const override { return 2 * kTouchSlopInDips; }
int GetMouseWheelMinimumGranularity() const override {
return kMouseWheelTickMultiplier;
@@ -340,10 +341,10 @@ class MockSyntheticTouchscreenPinchTouchTarget
switch (zoom_direction_) {
case ZOOM_IN:
return last_pointer_distance_ /
- (initial_pointer_distance_ + 2 * GetTouchSlopInDips());
+ (initial_pointer_distance_ + GetSpanSlopInDips());
case ZOOM_OUT:
return last_pointer_distance_ /
- (initial_pointer_distance_ - 2 * GetTouchSlopInDips());
+ (initial_pointer_distance_ - GetSpanSlopInDips());
case ZOOM_DIRECTION_UNKNOWN:
return 1.0f;
default:
@@ -465,16 +466,14 @@ class MockSyntheticTapTouchTarget : public MockSyntheticTapGestureTarget {
case NOT_STARTED:
EXPECT_EQ(touch_event.GetType(), WebInputEvent::kTouchStart);
position_ = gfx::PointF(touch_event.touches[0].PositionInWidget());
- start_time_ = base::TimeDelta::FromMilliseconds(
- static_cast<int64_t>(touch_event.TimeStampSeconds() * 1000));
+ start_time_ = touch_event.TimeStamp().since_origin();
state_ = STARTED;
break;
case STARTED:
EXPECT_EQ(touch_event.GetType(), WebInputEvent::kTouchEnd);
EXPECT_EQ(position_,
gfx::PointF(touch_event.touches[0].PositionInWidget()));
- stop_time_ = base::TimeDelta::FromMilliseconds(
- static_cast<int64_t>(touch_event.TimeStampSeconds() * 1000));
+ stop_time_ = touch_event.TimeStamp().since_origin();
state_ = FINISHED;
break;
case FINISHED:
@@ -499,8 +498,7 @@ class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget {
EXPECT_EQ(mouse_event.button, WebMouseEvent::Button::kLeft);
EXPECT_EQ(mouse_event.click_count, 1);
position_ = gfx::PointF(mouse_event.PositionInWidget());
- start_time_ = base::TimeDelta::FromMilliseconds(
- static_cast<int64_t>(mouse_event.TimeStampSeconds() * 1000));
+ start_time_ = mouse_event.TimeStamp().since_origin();
state_ = STARTED;
break;
case STARTED:
@@ -508,8 +506,7 @@ class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget {
EXPECT_EQ(mouse_event.button, WebMouseEvent::Button::kLeft);
EXPECT_EQ(mouse_event.click_count, 1);
EXPECT_EQ(position_, gfx::PointF(mouse_event.PositionInWidget()));
- stop_time_ = base::TimeDelta::FromMilliseconds(
- static_cast<int64_t>(mouse_event.TimeStampSeconds() * 1000));
+ stop_time_ = mouse_event.TimeStamp().since_origin();
state_ = FINISHED;
break;
case FINISHED:
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target.h
index e58c511faf8..ef7515968ee 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target.h
@@ -39,6 +39,10 @@ class CONTENT_EXPORT SyntheticGestureTarget {
// considered moving by the platform.
virtual float GetTouchSlopInDips() const = 0;
+ // Returns the maximum change in span (distance between touch points) in DIPs
+ // before being considered a pinch-zoom gesture by the platform.
+ virtual float GetSpanSlopInDips() const = 0;
+
// Returns the minimum number of DIPs two touch pointers have to be apart
// to perform a pinch-zoom.
virtual float GetMinScalingSpanInDips() const = 0;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
index e3b3cacd789..760ebcbfaab 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
@@ -67,11 +67,11 @@ void SyntheticGestureTargetAndroid::TouchSetScrollDeltas(int x,
void SyntheticGestureTargetAndroid::TouchInject(MotionEventAction action,
int pointer_count,
- int64_t time_in_ms) {
+ base::TimeTicks time) {
TRACE_EVENT0("input", "SyntheticGestureTargetAndroid::TouchInject");
JNIEnv* env = base::android::AttachCurrentThread();
Java_SyntheticGestureTarget_inject(env, java_ref_, action, pointer_count,
- time_in_ms);
+ time.since_origin().InMilliseconds());
}
void SyntheticGestureTargetAndroid::DispatchWebTouchEventToPlatform(
@@ -101,8 +101,7 @@ void SyntheticGestureTargetAndroid::DispatchWebTouchEventToPlatform(
point->id);
}
- TouchInject(action, num_touches,
- static_cast<int64_t>(web_touch.TimeStampSeconds() * 1000.0));
+ TouchInject(action, num_touches, web_touch.TimeStamp());
}
void SyntheticGestureTargetAndroid::DispatchWebMouseWheelEventToPlatform(
@@ -111,8 +110,7 @@ void SyntheticGestureTargetAndroid::DispatchWebMouseWheelEventToPlatform(
TouchSetScrollDeltas(web_wheel.PositionInWidget().x,
web_wheel.PositionInWidget().y, web_wheel.delta_x,
web_wheel.delta_y);
- TouchInject(MOTION_EVENT_ACTION_SCROLL, 1,
- static_cast<int64_t>(web_wheel.TimeStampSeconds() * 1000.0));
+ TouchInject(MOTION_EVENT_ACTION_SCROLL, 1, web_wheel.TimeStamp());
}
void SyntheticGestureTargetAndroid::DispatchWebMouseEventToPlatform(
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
index ed665bc581b..f96f715a12a 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
@@ -47,7 +47,7 @@ class SyntheticGestureTargetAndroid : public SyntheticGestureTargetBase {
void TouchSetScrollDeltas(int x, int y, int dx, int dy);
void TouchInject(MotionEventAction action,
int pointer_count,
- int64_t time_in_ms);
+ base::TimeTicks time);
ui::ViewAndroid* const view_;
base::android::ScopedJavaGlobalRef<jobject> java_ref_;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
index fe97e5f399c..c9b4679a367 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -80,8 +80,7 @@ void SyntheticGestureTargetAura::DispatchWebMouseWheelEventToPlatform(
.DispatchPendingWheelEndEvent();
return;
}
- base::TimeTicks timestamp =
- ui::EventTimeStampFromSeconds(web_wheel.TimeStampSeconds());
+ base::TimeTicks timestamp = web_wheel.TimeStamp();
ui::MouseWheelEvent wheel_event(
gfx::Vector2d(web_wheel.delta_x, web_wheel.delta_y), gfx::Point(),
gfx::Point(), timestamp, ui::EF_NONE, ui::EF_NONE);
@@ -99,6 +98,30 @@ void SyntheticGestureTargetAura::DispatchWebMouseWheelEventToPlatform(
return;
}
+void SyntheticGestureTargetAura::DispatchWebGestureEventToPlatform(
+ const blink::WebGestureEvent& web_gesture,
+ const ui::LatencyInfo& latency_info) {
+ DCHECK(blink::WebInputEvent::IsPinchGestureEventType(web_gesture.GetType()));
+ ui::EventType event_type = ui::WebEventTypeToEventType(web_gesture.GetType());
+ int flags = ui::WebEventModifiersToEventFlags(web_gesture.GetModifiers());
+
+ ui::GestureEventDetails pinch_details(event_type);
+ pinch_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD);
+ if (event_type == ui::ET_GESTURE_PINCH_UPDATE)
+ pinch_details.set_scale(web_gesture.data.pinch_update.scale);
+
+ ui::GestureEvent pinch_event(
+ web_gesture.PositionInWidget().x * device_scale_factor_,
+ web_gesture.PositionInWidget().y * device_scale_factor_, flags,
+ ui::EventTimeForNow(), pinch_details);
+
+ aura::Window* window = GetWindow();
+ pinch_event.ConvertLocationToTarget(window, window->GetRootWindow());
+
+ aura::EventInjector injector;
+ injector.Inject(window->GetHost(), &pinch_event);
+}
+
void SyntheticGestureTargetAura::DispatchWebMouseEventToPlatform(
const blink::WebMouseEvent& web_mouse_event,
const ui::LatencyInfo& latency_info) {
@@ -138,9 +161,12 @@ float SyntheticGestureTargetAura::GetTouchSlopInDips() const {
1;
}
+float SyntheticGestureTargetAura::GetSpanSlopInDips() const {
+ return ui::GestureConfiguration::GetInstance()->span_slop();
+}
+
float SyntheticGestureTargetAura::GetMinScalingSpanInDips() const {
- return ui::GestureConfiguration::GetInstance()
- ->min_distance_for_pinch_scroll_in_pixels();
+ return ui::GestureConfiguration::GetInstance()->min_scaling_span_in_pixels();
}
aura::Window* SyntheticGestureTargetAura::GetWindow() const {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
index fc5429e76c3..ca71247985d 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
@@ -28,6 +28,9 @@ class SyntheticGestureTargetAura : public SyntheticGestureTargetBase {
void DispatchWebMouseWheelEventToPlatform(
const blink::WebMouseWheelEvent& web_wheel,
const ui::LatencyInfo& latency_info) override;
+ void DispatchWebGestureEventToPlatform(
+ const blink::WebGestureEvent& web_gesture,
+ const ui::LatencyInfo& latency_info) override;
void DispatchWebMouseEventToPlatform(
const blink::WebMouseEvent& web_mouse,
const ui::LatencyInfo& latency_info) override;
@@ -38,6 +41,8 @@ class SyntheticGestureTargetAura : public SyntheticGestureTargetBase {
float GetTouchSlopInDips() const override;
+ float GetSpanSlopInDips() const override;
+
float GetMinScalingSpanInDips() const override;
private:
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
index 3691e3f563a..56c9d367e7e 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -18,6 +18,7 @@ using blink::WebTouchEvent;
using blink::WebTouchPoint;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
+using blink::WebGestureEvent;
namespace content {
namespace {
@@ -48,7 +49,7 @@ void SyntheticGestureTargetBase::DispatchInputEventToPlatform(
"type", WebInputEvent::GetName(event.GetType()));
ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
if (WebInputEvent::IsTouchEventType(event.GetType())) {
const WebTouchEvent& web_touch =
@@ -85,6 +86,19 @@ void SyntheticGestureTargetBase::DispatchInputEventToPlatform(
return;
}
DispatchWebMouseEventToPlatform(web_mouse, latency_info);
+ } else if (WebInputEvent::IsPinchGestureEventType(event.GetType())) {
+ const WebGestureEvent& web_pinch =
+ static_cast<const WebGestureEvent&>(event);
+ // Touchscreen pinches should be injected as touch events.
+ DCHECK_EQ(blink::kWebGestureDeviceTouchpad, web_pinch.SourceDevice());
+ if (event.GetType() == WebInputEvent::kGesturePinchBegin &&
+ !PointIsWithinContents(web_pinch.PositionInWidget().x,
+ web_pinch.PositionInWidget().y)) {
+ LOG(WARNING)
+ << "Pinch coordinates are not within content bounds on PinchBegin.";
+ return;
+ }
+ DispatchWebGestureEventToPlatform(web_pinch, latency_info);
} else {
NOTREACHED();
}
@@ -105,6 +119,12 @@ void SyntheticGestureTargetBase::DispatchWebMouseWheelEventToPlatform(
host_->ForwardWheelEventWithLatencyInfo(web_wheel, latency_info);
}
+void SyntheticGestureTargetBase::DispatchWebGestureEventToPlatform(
+ const blink::WebGestureEvent& web_gesture,
+ const ui::LatencyInfo& latency_info) {
+ host_->ForwardGestureEventWithLatencyInfo(web_gesture, latency_info);
+}
+
void SyntheticGestureTargetBase::DispatchWebMouseEventToPlatform(
const blink::WebMouseEvent& web_mouse,
const ui::LatencyInfo& latency_info) {
@@ -125,6 +145,12 @@ float SyntheticGestureTargetBase::GetTouchSlopInDips() const {
return kTouchSlopInDips;
}
+float SyntheticGestureTargetBase::GetSpanSlopInDips() const {
+ // * 2 because span is the distance between two touch points in a pinch-zoom
+ // gesture so we're accounting for movement in two points.
+ return 2.f * GetTouchSlopInDips();
+}
+
float SyntheticGestureTargetBase::GetMinScalingSpanInDips() const {
// The minimum scaling distance is only relevant for touch gestures and the
// base target doesn't support touch.
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
index 223644c74c8..9ebc02681ab 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
@@ -17,6 +17,7 @@ namespace blink {
class WebTouchEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
+class WebGestureEvent;
}
namespace content {
@@ -36,6 +37,10 @@ class SyntheticGestureTargetBase : public SyntheticGestureTarget {
const blink::WebMouseWheelEvent& web_wheel,
const ui::LatencyInfo& latency_info);
+ virtual void DispatchWebGestureEventToPlatform(
+ const blink::WebGestureEvent& web_gesture,
+ const ui::LatencyInfo& latency_info);
+
virtual void DispatchWebMouseEventToPlatform(
const blink::WebMouseEvent& web_mouse,
const ui::LatencyInfo& latency_info);
@@ -50,6 +55,8 @@ class SyntheticGestureTargetBase : public SyntheticGestureTarget {
float GetTouchSlopInDips() const override;
+ float GetSpanSlopInDips() const override;
+
float GetMinScalingSpanInDips() const override;
int GetMouseWheelMinimumGranularity() const override;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.h
index 4ecf50fbd15..ea9ec3ee0f0 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.h
@@ -18,8 +18,13 @@ class SyntheticGestureTargetMac : public SyntheticGestureTargetBase {
SyntheticGestureTargetMac(RenderWidgetHostImpl* host,
RenderWidgetHostViewCocoa* cocoa_view);
- // SyntheticGestureTarget:
- void DispatchInputEventToPlatform(const blink::WebInputEvent& event) override;
+ // SyntheticGestureTargetBase:
+ void DispatchWebTouchEventToPlatform(
+ const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency_info) override;
+ void DispatchWebGestureEventToPlatform(
+ const blink::WebGestureEvent& web_gesture,
+ const ui::LatencyInfo& latency_info) override;
private:
RenderWidgetHostViewCocoa* cocoa_view_;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm
index 71b3c5906b6..08d8639f6fd 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_mac.mm
@@ -81,54 +81,54 @@ SyntheticGestureTargetMac::SyntheticGestureTargetMac(
RenderWidgetHostViewCocoa* cocoa_view)
: SyntheticGestureTargetBase(host), cocoa_view_(cocoa_view) {}
-void SyntheticGestureTargetMac::DispatchInputEventToPlatform(
- const WebInputEvent& event) {
- if (WebInputEvent::IsGestureEventType(event.GetType())) {
- // Create an autorelease pool so that we clean up any synthetic events we
- // generate.
- base::mac::ScopedNSAutoreleasePool pool;
-
- const WebGestureEvent* gesture_event =
- static_cast<const WebGestureEvent*>(&event);
-
- switch (event.GetType()) {
- case WebInputEvent::kGesturePinchBegin: {
- id cocoa_event = [SyntheticPinchEvent
- eventWithMagnification:0.0f
- locationInWindow:NSMakePoint(
- gesture_event->PositionInWidget().x,
- gesture_event->PositionInWidget().y)
- phase:NSEventPhaseBegan];
- [cocoa_view_ handleBeginGestureWithEvent:cocoa_event];
- return;
- }
- case WebInputEvent::kGesturePinchEnd: {
- id cocoa_event = [SyntheticPinchEvent
- eventWithMagnification:0.0f
- locationInWindow:NSMakePoint(
- gesture_event->PositionInWidget().x,
- gesture_event->PositionInWidget().y)
- phase:NSEventPhaseEnded];
- [cocoa_view_ handleEndGestureWithEvent:cocoa_event];
- return;
- }
- case WebInputEvent::kGesturePinchUpdate: {
- id cocoa_event = [SyntheticPinchEvent
- eventWithMagnification:gesture_event->data.pinch_update.scale - 1.0f
- locationInWindow:NSMakePoint(
- gesture_event->PositionInWidget().x,
- gesture_event->PositionInWidget().y)
- phase:NSEventPhaseChanged];
- [cocoa_view_ magnifyWithEvent:cocoa_event];
- return;
- }
- default:
- break;
+void SyntheticGestureTargetMac::DispatchWebGestureEventToPlatform(
+ const WebGestureEvent& web_gesture,
+ const ui::LatencyInfo& latency_info) {
+ // Create an autorelease pool so that we clean up any synthetic events we
+ // generate.
+ base::mac::ScopedNSAutoreleasePool pool;
+
+ NSPoint content_local = NSMakePoint(
+ web_gesture.PositionInWidget().x,
+ [cocoa_view_ frame].size.height - web_gesture.PositionInWidget().y);
+ NSPoint location_in_window =
+ [cocoa_view_ convertPoint:content_local toView:nil];
+
+ switch (web_gesture.GetType()) {
+ case WebInputEvent::kGesturePinchBegin: {
+ id cocoa_event =
+ [SyntheticPinchEvent eventWithMagnification:0.0f
+ locationInWindow:location_in_window
+ phase:NSEventPhaseBegan];
+ [cocoa_view_ handleBeginGestureWithEvent:cocoa_event
+ isSyntheticallyInjected:YES];
+ return;
}
+ case WebInputEvent::kGesturePinchEnd: {
+ id cocoa_event =
+ [SyntheticPinchEvent eventWithMagnification:0.0f
+ locationInWindow:location_in_window
+ phase:NSEventPhaseEnded];
+ [cocoa_view_ handleEndGestureWithEvent:cocoa_event];
+ return;
+ }
+ case WebInputEvent::kGesturePinchUpdate: {
+ id cocoa_event = [SyntheticPinchEvent
+ eventWithMagnification:web_gesture.data.pinch_update.scale - 1.0f
+ locationInWindow:location_in_window
+ phase:NSEventPhaseChanged];
+ [cocoa_view_ magnifyWithEvent:cocoa_event];
+ return;
+ }
+ default:
+ NOTREACHED();
}
+}
- // This event wasn't handled yet, forward to the base class.
- SyntheticGestureTargetBase::DispatchInputEventToPlatform(event);
+void SyntheticGestureTargetMac::DispatchWebTouchEventToPlatform(
+ const blink::WebTouchEvent& web_touch,
+ const ui::LatencyInfo& latency_info) {
+ render_widget_host()->GetView()->InjectTouchEvent(web_touch, latency_info);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc b/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
index bdc58826bb6..2547e5d210c 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_mouse_driver.cc
@@ -16,7 +16,7 @@ SyntheticMouseDriver::~SyntheticMouseDriver() {}
void SyntheticMouseDriver::DispatchEvent(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp) {
- mouse_event_.SetTimeStampSeconds(ConvertTimestampToSeconds(timestamp));
+ mouse_event_.SetTimeStamp(timestamp);
if (mouse_event_.GetType() != blink::WebInputEvent::kUndefined) {
target->DispatchInputEventToPlatform(mouse_event_);
mouse_event_.SetType(blink::WebInputEvent::kUndefined);
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
index ed27b10655e..0c681c68c67 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
@@ -75,6 +75,11 @@ class MockSyntheticPointerActionTarget : public SyntheticGestureTarget {
return 0.0f;
}
+ float GetSpanSlopInDips() const override {
+ NOTIMPLEMENTED();
+ return 0.0f;
+ }
+
float GetMinScalingSpanInDips() const override {
NOTIMPLEMENTED();
return 0.0f;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.cc
index 38cfd5c9c75..d10f7160ea9 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.cc
@@ -30,10 +30,4 @@ std::unique_ptr<SyntheticPointerDriver> SyntheticPointerDriver::Create(
return std::unique_ptr<SyntheticPointerDriver>();
}
-// static
-double SyntheticPointerDriver::ConvertTimestampToSeconds(
- const base::TimeTicks& timestamp) {
- return (timestamp - base::TimeTicks()).InSecondsF();
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h b/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h
index b1b5e227b88..8ca1163b4e9 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_driver.h
@@ -43,9 +43,6 @@ class CONTENT_EXPORT SyntheticPointerDriver {
virtual bool UserInputCheck(
const SyntheticPointerActionParams& params) const = 0;
- protected:
- static double ConvertTimestampToSeconds(const base::TimeTicks& timestamp);
-
private:
DISALLOW_COPY_AND_ASSIGN(SyntheticPointerDriver);
};
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
index f946597a325..ea2c5eca311 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
@@ -23,10 +23,6 @@ gfx::Vector2dF ProjectScalarOntoVector(float scalar,
return gfx::ScaleVector2d(vector, scalar / vector.Length());
}
-double ConvertTimestampToSeconds(const base::TimeTicks& timestamp) {
- return (timestamp - base::TimeTicks()).InSecondsF();
-}
-
const int kDefaultSpeedInPixelsPerSec = 800;
} // namespace
@@ -270,7 +266,7 @@ void SyntheticSmoothMoveGesture::ForwardMouseWheelEvent(
current_move_segment_start_position_.y());
mouse_wheel_event.phase = phase;
- mouse_wheel_event.SetTimeStampSeconds(ConvertTimestampToSeconds(timestamp));
+ mouse_wheel_event.SetTimeStamp(timestamp);
target->DispatchInputEventToPlatform(mouse_wheel_event);
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
index 575d68bdd15..a8e14a2aff0 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_touch_driver.cc
@@ -21,7 +21,7 @@ SyntheticTouchDriver::~SyntheticTouchDriver() {}
void SyntheticTouchDriver::DispatchEvent(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp) {
- touch_event_.SetTimeStampSeconds(ConvertTimestampToSeconds(timestamp));
+ touch_event_.SetTimeStamp(timestamp);
if (touch_event_.GetType() != blink::WebInputEvent::kUndefined)
target->DispatchInputEventToPlatform(touch_event_);
touch_event_.ResetPoints();
diff --git a/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc
index ea87524552f..8e1401a1bcd 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc
@@ -122,16 +122,15 @@ void SyntheticTouchscreenPinchGesture::SetupCoordinatesAndStopTime(
// factor. Since we're moving both pointers at the same speed, each pointer's
// distance to the anchor is half the span.
float initial_distance_to_anchor, final_distance_to_anchor;
+ const float single_point_slop = target->GetSpanSlopInDips() / 2.0f;
if (params_.scale_factor > 1.0f) { // zooming in
initial_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f;
final_distance_to_anchor =
- (initial_distance_to_anchor + target->GetTouchSlopInDips()) *
- params_.scale_factor;
+ (initial_distance_to_anchor + single_point_slop) * params_.scale_factor;
} else { // zooming out
final_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f;
initial_distance_to_anchor =
- (final_distance_to_anchor / params_.scale_factor) +
- target->GetTouchSlopInDips();
+ (final_distance_to_anchor / params_.scale_factor) + single_point_slop;
}
start_y_0_ = params_.anchor.y() - initial_distance_to_anchor;
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc b/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc
index 5d14ea93e53..ff618b53157 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller.cc
@@ -6,102 +6,45 @@
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
namespace content {
-// The tapDownTimer is used to avoid waiting for an arbitrarily late fling
-// cancel ack. While the timer is running, if a fling cancel ack with
-// |Processed = false| arrives, all stashed gesture events get forwarded. If
-// the timer expires, the controller forwards stashed GestureTapDown only, and
-// drops the rest of the stashed events. The timer delay should be large enough
-// for a GestureLongPress to get stashed and forwarded if needed. It's still
-// possible for a GestureLongPress to arrive after the timer expiration. In
-// this case, it will be suppressed if the controller is in SUPPRESSING_TAPS
-// state.
-
TapSuppressionController::Config::Config()
: enabled(false),
max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)) {
- ui::GestureConfiguration* gesture_config =
- ui::GestureConfiguration::GetInstance();
- max_tap_gap_time = base::TimeDelta::FromMilliseconds(
- gesture_config->long_press_time_in_ms() + 50);
}
-TapSuppressionController::TapSuppressionController(
- TapSuppressionControllerClient* client,
- const Config& config)
- : client_(client),
- state_(config.enabled ? NOTHING : DISABLED),
- max_cancel_to_down_time_(config.max_cancel_to_down_time),
- max_tap_gap_time_(config.max_tap_gap_time) {
-}
+TapSuppressionController::TapSuppressionController(const Config& config)
+ : state_(config.enabled ? NOTHING : DISABLED),
+ max_cancel_to_down_time_(config.max_cancel_to_down_time) {}
TapSuppressionController::~TapSuppressionController() {}
-void TapSuppressionController::GestureFlingCancel() {
- switch (state_) {
- case DISABLED:
- break;
- case NOTHING:
- case GFC_IN_PROGRESS:
- case LAST_CANCEL_STOPPED_FLING:
- case SUPPRESSING_TAPS:
- state_ = GFC_IN_PROGRESS;
- break;
- case TAP_DOWN_STASHED:
- break;
- }
-}
-
-void TapSuppressionController::GestureFlingCancelAck(bool processed) {
+void TapSuppressionController::GestureFlingCancelStoppedFling() {
base::TimeTicks event_time = Now();
switch (state_) {
case DISABLED:
- case NOTHING:
case SUPPRESSING_TAPS:
break;
- case GFC_IN_PROGRESS:
- if (processed)
- fling_cancel_time_ = event_time;
+ case NOTHING:
+ fling_cancel_time_ = event_time;
state_ = LAST_CANCEL_STOPPED_FLING;
break;
- case TAP_DOWN_STASHED:
- if (!processed) {
- TRACE_EVENT0("browser",
- "TapSuppressionController::GestureFlingCancelAck");
- StopTapDownTimer();
- // If the fling cancel is not processed, forward all stashed
- // gesture events.
- client_->ForwardStashedGestureEvents();
- state_ = NOTHING;
- } // Else waiting for the timer to release the stashed tap down.
- break;
case LAST_CANCEL_STOPPED_FLING:
break;
}
}
-bool TapSuppressionController::ShouldDeferTapDown() {
+bool TapSuppressionController::ShouldSuppressTapDown() {
base::TimeTicks event_time = Now();
switch (state_) {
case DISABLED:
case NOTHING:
return false;
- case GFC_IN_PROGRESS:
- state_ = TAP_DOWN_STASHED;
- StartTapDownTimer(max_tap_gap_time_);
- return true;
- case TAP_DOWN_STASHED:
- NOTREACHED() << "TapDown on TAP_DOWN_STASHED state";
- state_ = NOTHING;
- return false;
case LAST_CANCEL_STOPPED_FLING:
if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) {
- state_ = TAP_DOWN_STASHED;
- StartTapDownTimer(max_tap_gap_time_);
+ state_ = SUPPRESSING_TAPS;
return true;
} else {
state_ = NOTHING;
@@ -120,16 +63,7 @@ bool TapSuppressionController::ShouldSuppressTapEnd() {
switch (state_) {
case DISABLED:
case NOTHING:
- case GFC_IN_PROGRESS:
return false;
- case TAP_DOWN_STASHED:
- // A tap cancel happens before long tap and two finger tap events. To
- // drop the latter events as well as the tap cancel, change the state
- // to "SUPPRESSING_TAPS" when the stashed tap down is dropped.
- state_ = SUPPRESSING_TAPS;
- StopTapDownTimer();
- client_->DropStashedTapDown();
- return true;
case LAST_CANCEL_STOPPED_FLING:
NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state";
return true;
@@ -143,36 +77,4 @@ base::TimeTicks TapSuppressionController::Now() {
return base::TimeTicks::Now();
}
-void TapSuppressionController::StartTapDownTimer(const base::TimeDelta& delay) {
- tap_down_timer_.Start(FROM_HERE, delay, this,
- &TapSuppressionController::TapDownTimerExpired);
-}
-
-void TapSuppressionController::StopTapDownTimer() {
- tap_down_timer_.Stop();
-}
-
-void TapSuppressionController::TapDownTimerExpired() {
- switch (state_) {
- case DISABLED:
- case NOTHING:
- case SUPPRESSING_TAPS:
- NOTREACHED() << "Timer fired on invalid state.";
- break;
- case GFC_IN_PROGRESS:
- case LAST_CANCEL_STOPPED_FLING:
- NOTREACHED() << "Timer fired on invalid state.";
- state_ = NOTHING;
- break;
- case TAP_DOWN_STASHED:
- TRACE_EVENT0("browser",
- "TapSuppressionController::TapDownTimerExpired");
- // When the timer expires, only forward the stashed tap down event, and
- // drop other stashed gesture events (show press or long press).
- client_->ForwardStashedTapDown();
- state_ = SUPPRESSING_TAPS;
- break;
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/tap_suppression_controller.h
index b238258b1c8..bcd8ba3ebfd 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller.h
@@ -12,8 +12,6 @@
namespace content {
-class TapSuppressionControllerClient;
-
// The core controller for suppression of taps (touchpad or touchscreen)
// immediately following a GestureFlingCancel event (caused by the same tap).
// Only taps of sufficient speed and within a specified time window after a
@@ -29,27 +27,19 @@ class CONTENT_EXPORT TapSuppressionController {
// The maximum time allowed between a GestureFlingCancel and its
// corresponding tap down.
base::TimeDelta max_cancel_to_down_time;
-
- // The maximum time allowed between a single tap's down and up events.
- base::TimeDelta max_tap_gap_time;
};
- TapSuppressionController(TapSuppressionControllerClient* client,
- const Config& config);
+ TapSuppressionController(const Config& config);
virtual ~TapSuppressionController();
- // Should be called whenever a GestureFlingCancel event is received.
- void GestureFlingCancel();
-
- // Should be called whenever an ACK for a GestureFlingCancel event is
- // received. |processed| is true when the GestureFlingCancel actually stopped
- // a fling and therefore should suppress the forwarding of the following tap.
- void GestureFlingCancelAck(bool processed);
+ // Should be called whenever a GestureFlingCancel actually stopped a fling and
+ // therefore the controller should suppress the forwarding of the following
+ // tap.
+ void GestureFlingCancelStoppedFling();
// Should be called whenever a tap down (touchpad or touchscreen) is received.
- // Returns true if the tap down should be deferred. The caller is responsible
- // for keeping the event for later release, if needed.
- bool ShouldDeferTapDown();
+ // Returns true if the tap down should be suppressed.
+ bool ShouldSuppressTapDown();
// Should be called whenever a tap ending event is received. Returns true if
// the tap event should be suppressed.
@@ -57,33 +47,23 @@ class CONTENT_EXPORT TapSuppressionController {
protected:
virtual base::TimeTicks Now();
- virtual void StartTapDownTimer(const base::TimeDelta& delay);
- virtual void StopTapDownTimer();
- void TapDownTimerExpired();
-
private:
friend class MockTapSuppressionController;
enum State {
DISABLED,
NOTHING,
- GFC_IN_PROGRESS,
- TAP_DOWN_STASHED,
LAST_CANCEL_STOPPED_FLING,
- // When the stashed TapDown event is dropped or forwarded due to tap down
- // timer expiration, the controller enters the SUPPRESSING_TAPS state.
- // This state shows that the controller will suppress LongTap,
- // TwoFingerTap, and TapCancel gesture events until the next tapDown event
- // arrives.
+ // When the stashed TapDown event is dropped, the controller enters the
+ // SUPPRESSING_TAPS state. This state shows that the controller will
+ // suppress LongTap, TwoFingerTap, and TapCancel gesture events until the
+ // next tapDown event arrives.
SUPPRESSING_TAPS,
};
- TapSuppressionControllerClient* client_;
- base::OneShotTimer tap_down_timer_;
State state_;
base::TimeDelta max_cancel_to_down_time_;
- base::TimeDelta max_tap_gap_time_;
// TODO(rjkroege): During debugging, the event times did not prove reliable.
// Replace the use of base::TimeTicks with an accurate event time when they
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h b/chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h
deleted file mode 100644
index 0b917a6af13..00000000000
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller_client.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 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_RENDERER_HOST_INPUT_TAP_SUPPRESSION_CONTROLLER_CLIENT_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TAP_SUPPRESSION_CONTROLLER_CLIENT_H_
-
-#include "base/macros.h"
-
-namespace content {
-
-// This class provides an interface for callbacks made by
-// TapSuppressionController.
-class TapSuppressionControllerClient {
- public:
- virtual ~TapSuppressionControllerClient() {}
-
- // Called whenever the deferred tap down (if saved) should be dropped totally.
- virtual void DropStashedTapDown() = 0;
-
- // Called whenever the deferred tap down and other gesture events (if saved)
- // should be forwarded to the renderer. The tap down (and possibly other
- // gesture events) should go back to normal path they were on before being
- // deferred.
- virtual void ForwardStashedGestureEvents() = 0;
-
- // Called whenever only the deferred tap down (if saved) should be forwarded
- // to the renderer. Other saved gesture events will be dropped.
- virtual void ForwardStashedTapDown() = 0;
-
- protected:
- TapSuppressionControllerClient() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TapSuppressionControllerClient);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TAP_SUPPRESSION_CONTROLLER_CLIENT_H_
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc b/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
index b064a5bfb57..3f23de8010a 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
@@ -7,57 +7,41 @@
#include <memory>
#include "base/macros.h"
-#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta;
namespace content {
-class MockTapSuppressionController : public TapSuppressionController,
- public TapSuppressionControllerClient {
+class MockTapSuppressionController : public TapSuppressionController {
public:
using TapSuppressionController::DISABLED;
using TapSuppressionController::NOTHING;
- using TapSuppressionController::GFC_IN_PROGRESS;
- using TapSuppressionController::TAP_DOWN_STASHED;
using TapSuppressionController::LAST_CANCEL_STOPPED_FLING;
using TapSuppressionController::SUPPRESSING_TAPS;
enum Action {
- NONE = 0,
- TAP_DOWN_DEFERRED = 1 << 0,
- TAP_DOWN_FORWARDED = 1 << 1,
- TAP_DOWN_DROPPED = 1 << 2,
- TAP_UP_SUPPRESSED = 1 << 3,
- TAP_UP_FORWARDED = 1 << 4,
- TAP_CANCEL_SUPPRESSED = 1 << 5,
- TAP_CANCEL_FORWARDED = 1 << 6,
- STASHED_TAP_DOWN_FORWARDED = 1 << 7,
+ NONE = 0,
+ TAP_DOWN_FORWARDED = 1 << 0,
+ TAP_DOWN_SUPPRESSED = 1 << 1,
+ TAP_UP_SUPPRESSED = 1 << 2,
+ TAP_UP_FORWARDED = 1 << 3,
};
MockTapSuppressionController(const TapSuppressionController::Config& config)
- : TapSuppressionController(this, config),
- last_actions_(NONE),
- time_(),
- timer_started_(false) {}
+ : TapSuppressionController(config), last_actions_(NONE), time_() {}
~MockTapSuppressionController() override {}
- void SendGestureFlingCancel() {
+ void NotifyGestureFlingCancelStoppedFling() {
last_actions_ = NONE;
- GestureFlingCancel();
- }
-
- void SendGestureFlingCancelAck(bool processed) {
- last_actions_ = NONE;
- GestureFlingCancelAck(processed);
+ GestureFlingCancelStoppedFling();
}
void SendTapDown() {
last_actions_ = NONE;
- if (ShouldDeferTapDown())
- last_actions_ |= TAP_DOWN_DEFERRED;
+ if (ShouldSuppressTapDown())
+ last_actions_ |= TAP_DOWN_SUPPRESSED;
else
last_actions_ |= TAP_DOWN_FORWARDED;
}
@@ -70,23 +54,9 @@ class MockTapSuppressionController : public TapSuppressionController,
last_actions_ |= TAP_UP_FORWARDED;
}
- void SendTapCancel() {
- bool stashed_tap_down_forwarded =
- last_actions_ & STASHED_TAP_DOWN_FORWARDED;
- last_actions_ = NONE;
- if (!stashed_tap_down_forwarded && ShouldSuppressTapEnd())
- last_actions_ |= TAP_CANCEL_SUPPRESSED;
- else
- last_actions_ |= TAP_CANCEL_FORWARDED;
- }
-
void AdvanceTime(const base::TimeDelta& delta) {
last_actions_ = NONE;
time_ += delta;
- if (timer_started_ && time_ >= timer_expiry_time_) {
- timer_started_ = false;
- TapDownTimerExpired();
- }
}
State state() { return state_; }
@@ -96,36 +66,17 @@ class MockTapSuppressionController : public TapSuppressionController,
protected:
base::TimeTicks Now() override { return time_; }
- void StartTapDownTimer(const base::TimeDelta& delay) override {
- timer_expiry_time_ = time_ + delay;
- timer_started_ = true;
- }
-
- void StopTapDownTimer() override { timer_started_ = false; }
private:
- // TapSuppressionControllerClient implementation
- void DropStashedTapDown() override { last_actions_ |= TAP_DOWN_DROPPED; }
-
- void ForwardStashedGestureEvents() override {
- last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
- }
-
- void ForwardStashedTapDown() override {
- last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
- }
// Hiding some derived public methods
- using TapSuppressionController::GestureFlingCancel;
- using TapSuppressionController::GestureFlingCancelAck;
- using TapSuppressionController::ShouldDeferTapDown;
+ using TapSuppressionController::GestureFlingCancelStoppedFling;
+ using TapSuppressionController::ShouldSuppressTapDown;
using TapSuppressionController::ShouldSuppressTapEnd;
int last_actions_;
base::TimeTicks time_;
- bool timer_started_;
- base::TimeTicks timer_expiry_time_;
DISALLOW_COPY_AND_ASSIGN(MockTapSuppressionController);
};
@@ -149,25 +100,17 @@ class TapSuppressionControllerTest : public testing::Test {
TapSuppressionController::Config config;
config.enabled = true;
config.max_cancel_to_down_time = base::TimeDelta::FromMilliseconds(10);
- config.max_tap_gap_time = base::TimeDelta::FromMilliseconds(10);
return config;
}
std::unique_ptr<MockTapSuppressionController> tap_suppression_controller_;
};
-// Test TapSuppressionController for when GestureFlingCancel Ack comes before
-// TapDown and everything happens without any delays.
+// Test TapSuppressionController for when GestureFlingCancel actually stops
+// fling and the tap down event arrives without any delay.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapFast) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
+ // Notify the controller that the GFC has stooped an active fling.
+ tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
@@ -175,158 +118,24 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapFast) {
// Send TapDown. This TapDown should be suppressed.
tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Send TapUp. This TapUp should be suppressed.
- tap_suppression_controller_->SendTapUp();
- EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
- MockTapSuppressionController::TAP_DOWN_DROPPED,
+ EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_SUPPRESSED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
-}
-
-// Test TapSuppressionController for when GestureFlingCancel Ack comes before
-// TapDown, but there is a small delay between TapDown and TapUp.
-TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapUp) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
- tap_suppression_controller_->state());
-
- // Send TapDown. This TapDown should be suppressed.
- tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Wait less than allowed delay between TapDown and TapUp, so they are still
- // considered a tap.
- tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(7));
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
// Send TapUp. This TapUp should be suppressed.
tap_suppression_controller_->SendTapUp();
- EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
- MockTapSuppressionController::TAP_DOWN_DROPPED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-}
-
-// Test TapSuppressionController for when GestureFlingCancel Ack comes before
-// TapDown, but there is a long delay between TapDown and TapUp.
-TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapUp) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send processed GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
- tap_suppression_controller_->state());
-
- // Send TapDown. This TapDown should be suppressed, for now.
- tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Wait more than allowed delay between TapDown and TapUp, so they are not
- // considered a tap. This should release the previously suppressed TapDown.
- tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
- EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-
- // Send TapUp. This TapUp should be still suppressed.
- // LongTap should be suppressed when the previously suppressed TapDown is
- // forwarded because of the timer expiration.
- tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
}
-// Test TapSuppressionController for when stashed TapDown gets forwarded.
-// The next TapCancel should be forwarded as well to maintain a valid input
-// stream.
-TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapCancel) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send processed GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
- tap_suppression_controller_->state());
-
- // Send TapDown. This TapDown should be suppressed, for now.
- tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Wait more than the delay for TapDown timer. This should release the
- // previously stashed TapDown.
- tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
- EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-
- // Send TapCancel. This TapCancel should be forwarded.
- // When a TapDown is forwarded because of the timer expiration, the next
- // TapCancel should get forwarded as well to maintain a valid input stream.
- tap_suppression_controller_->SendTapCancel();
- EXPECT_EQ(MockTapSuppressionController::TAP_CANCEL_FORWARDED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-}
-
-// Test TapSuppressionController for when GestureFlingCancel Ack comes before
-// TapDown, but there is a small delay between the Ack and TapDown.
+// Test TapSuppressionController for when GestureFlingCancel actually stops
+// fling but there is a small delay between the Ack and TapDown.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapDown) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
+ // Notify the controller that the GFC has stooped an active fling.
+ tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
@@ -342,32 +151,24 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapDown) {
// Send TapDown. This TapDown should be suppressed.
tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
+ EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_SUPPRESSED,
tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
+ EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should be suppressed.
tap_suppression_controller_->SendTapUp();
- EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
- MockTapSuppressionController::TAP_DOWN_DROPPED,
+ EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
}
-// Test TapSuppressionController for when GestureFlingCancel Ack comes before
-// TapDown, but there is a long delay between the Ack and TapDown.
+// Test TapSuppressionController for when GestureFlingCancel actually stops
+// fling but there is a long delay between the Ack and TapDown.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapDown) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
+ // Notify the controller that the GFC has stooped an active fling.
+ tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
@@ -396,155 +197,6 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapDown) {
tap_suppression_controller_->state());
}
-// Test TapSuppressionController for when unprocessed GestureFlingCancel Ack
-// comes after TapDown and everything happens without any delay.
-TEST_F(TapSuppressionControllerTest, GFCAckUnprocessedAfterTapFast) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send TapDown. This TapDown should be suppressed, for now.
- tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Send unprocessed GestureFlingCancel Ack. This should release the
- // previously suppressed TapDown.
- tap_suppression_controller_->SendGestureFlingCancelAck(false);
- EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::NOTHING,
- tap_suppression_controller_->state());
-
- // Send TapUp. This TapUp should not be suppressed.
- tap_suppression_controller_->SendTapUp();
- EXPECT_EQ(MockTapSuppressionController::TAP_UP_FORWARDED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::NOTHING,
- tap_suppression_controller_->state());
-}
-
-// Test TapSuppressionController for when processed GestureFlingCancel Ack comes
-// after TapDown and everything happens without any delay.
-TEST_F(TapSuppressionControllerTest, GFCAckProcessedAfterTapFast) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send TapDown. This TapDown should be suppressed.
- tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Send processed GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Send TapUp. This TapUp should be suppressed.
- tap_suppression_controller_->SendTapUp();
- EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
- MockTapSuppressionController::TAP_DOWN_DROPPED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-}
-
-// Test TapSuppressionController for when GestureFlingCancel Ack comes after
-// TapDown and there is a small delay between the Ack and TapUp.
-TEST_F(TapSuppressionControllerTest, GFCAckAfterTapInsufficientlyLateTapUp) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send TapDown. This TapDown should be suppressed.
- tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Send GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Wait less than allowed delay between TapDown and TapUp, so they are still
- // considered as a tap.
- tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(7));
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Send TapUp. This TapUp should be suppressed.
- tap_suppression_controller_->SendTapUp();
- EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
- MockTapSuppressionController::TAP_DOWN_DROPPED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-}
-
-// Test TapSuppressionController for when GestureFlingCancel Ack comes after
-// TapDown and there is a long delay between the Ack and TapUp.
-TEST_F(TapSuppressionControllerTest, GFCAckAfterTapSufficientlyLateTapUp) {
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
- tap_suppression_controller_->state());
-
- // Send TapDown. This TapDown should be suppressed, for now.
- tap_suppression_controller_->SendTapDown();
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Send GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
- tap_suppression_controller_->state());
-
- // Wait more than allowed delay between TapDown and TapUp, so they are not
- // considered as a tap. This should release the previously suppressed TapDown.
- tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
- EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-
- // Send TapUp. This TapUp should be still suppressed.
- // LongTap should be suppressed when the previously suppressed TapDown is
- // forwarded because of timer expiration.
- tap_suppression_controller_->SendTapUp();
- EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
- tap_suppression_controller_->state());
-}
-
// Test that no suppression occurs if the TapSuppressionController is disabled.
TEST_F(TapSuppressionControllerTest, NoSuppressionIfDisabled) {
TapSuppressionController::Config disabled_config;
@@ -552,15 +204,8 @@ TEST_F(TapSuppressionControllerTest, NoSuppressionIfDisabled) {
tap_suppression_controller_.reset(
new MockTapSuppressionController(disabled_config));
- // Send GestureFlingCancel.
- tap_suppression_controller_->SendGestureFlingCancel();
- EXPECT_EQ(MockTapSuppressionController::NONE,
- tap_suppression_controller_->last_actions());
- EXPECT_EQ(MockTapSuppressionController::DISABLED,
- tap_suppression_controller_->state());
-
// Send GestureFlingCancel Ack.
- tap_suppression_controller_->SendGestureFlingCancelAck(true);
+ tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::DISABLED,
diff --git a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
index 474c78dfe2d..f06e309f256 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -65,6 +65,64 @@ const char kTouchActionDataURL[] =
" document.title='ready';"
"</script>";
+const char kTouchActionURLWithOverlapArea[] =
+ "data:text/html;charset=utf-8,"
+ "<!DOCTYPE html>"
+ "<meta name='viewport' content='width=device-width'/>"
+ "<style>"
+ "html, body {"
+ " margin: 0;"
+ "}"
+ ".box {"
+ " box-sizing: border-box;"
+ " height: 100px;"
+ " width: 100px;"
+ " border: 2px solid blue;"
+ " position: absolute;"
+ " will-change: transform;"
+ "}"
+ ".spacer {"
+ " height: 10000px;"
+ " width: 10000px;"
+ "}"
+ ".ta-auto {"
+ " top: 52px;"
+ " left: 52px;"
+ " touch-action: auto;"
+ "}"
+ ".ta-pany {"
+ " top: 102px;"
+ " left: 2px;"
+ " touch-action: pan-y;"
+ "}"
+ ".ta-panx {"
+ " top: 2px;"
+ " left: 102px;"
+ " touch-action: pan-x;"
+ "}"
+ "</style>"
+ "<div class='box ta-panx'></div>"
+ "<div class='box ta-pany'></div>"
+ "<div class='box ta-auto'></div>"
+ "<div class=spacer></div>"
+ "<script>"
+ " document.title='ready';"
+ "</script>";
+
+void GiveItSomeTime(int t) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMilliseconds(t));
+ run_loop.Run();
+}
+
+constexpr base::TimeDelta kNoJankTime = base::TimeDelta::FromMilliseconds(0);
+constexpr base::TimeDelta kShortJankTime =
+ base::TimeDelta::FromMilliseconds(100);
+// 1200ms is larger than both desktop / mobile_touch_ack_timeout_delay in the
+// PassthroughTouchEventQueue, which ensures timeout to be triggered.
+constexpr base::TimeDelta kLongJankTime =
+ base::TimeDelta::FromMilliseconds(1200);
} // namespace
namespace content {
@@ -82,12 +140,12 @@ class TouchActionBrowserTest : public ContentBrowserTest {
void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
- runner_->Quit();
+ run_loop_->Quit();
}
protected:
- void LoadURL() {
- const GURL data_url(kTouchActionDataURL);
+ void LoadURL(const char* touch_action_url) {
+ const GURL data_url(touch_action_url);
NavigateToURL(shell(), data_url);
RenderWidgetHostImpl* host = GetWidgetHost();
@@ -129,6 +187,13 @@ class TouchActionBrowserTest : public ContentBrowserTest {
return value;
}
+ void JankMainThread(base::TimeDelta delta) {
+ std::string script = "var end = performance.now() + ";
+ script.append(std::to_string(delta.InMilliseconds()));
+ script.append("; while (performance.now() < end) ; ");
+ EXPECT_TRUE(content::ExecuteScript(shell(), script));
+ }
+
double ExecuteScriptAndExtractDouble(const std::string& script) {
double value = 0;
EXPECT_TRUE(content::ExecuteScriptAndExtractDouble(
@@ -140,24 +205,86 @@ class TouchActionBrowserTest : public ContentBrowserTest {
return ExecuteScriptAndExtractDouble("document.scrollingElement.scrollTop");
}
+ double GetScrollLeft() {
+ return ExecuteScriptAndExtractDouble(
+ "document.scrollingElement.scrollLeft");
+ }
+
+ bool URLLoaded() {
+ base::string16 ready_title(base::ASCIIToUTF16("ready"));
+ TitleWatcher watcher(shell()->web_contents(), ready_title);
+ const base::string16 title = watcher.WaitAndGetTitle();
+ return title == ready_title;
+ }
+
+ // In this test, we first jank the main thread for 1200ms. Then we let the
+ // first finger scroll along the x-direction, on a pan-y area, for 1 second.
+ // While the first finger is still scrolling, we let the second finger
+ // touching the same area and scroll along the same direction. We purposely
+ // trigger touch ack timeout for the first finger touch. All we need to ensure
+ // is that the second finger also scrolled.
+ void DoTwoFingerTouchScroll(
+ bool wait_until_scrolled,
+ const gfx::Vector2d& expected_scroll_position_after_scroll) {
+ SyntheticSmoothScrollGestureParams params1;
+ params1.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params1.anchor = gfx::PointF(25, 125);
+ params1.distances.push_back(gfx::Vector2dF(-5, 0));
+ params1.prevent_fling = true;
+ params1.speed_in_pixels_s = 5;
+
+ SyntheticSmoothScrollGestureParams params2;
+ params2.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params2.anchor = gfx::PointF(25, 125);
+ params2.distances.push_back(gfx::Vector2dF(-50, 0));
+
+ run_loop_ = std::make_unique<base::RunLoop>();
+
+ std::unique_ptr<SyntheticSmoothScrollGesture> gesture1(
+ new SyntheticSmoothScrollGesture(params1));
+ GetWidgetHost()->QueueSyntheticGesture(
+ std::move(gesture1),
+ base::BindOnce(&TouchActionBrowserTest::OnSyntheticGestureCompleted,
+ base::Unretained(this)));
+
+ JankMainThread(kLongJankTime);
+ GiveItSomeTime(800);
+
+ std::unique_ptr<SyntheticSmoothScrollGesture> gesture2(
+ new SyntheticSmoothScrollGesture(params2));
+ GetWidgetHost()->QueueSyntheticGesture(
+ std::move(gesture2),
+ base::BindOnce(&TouchActionBrowserTest::OnSyntheticGestureCompleted,
+ base::Unretained(this)));
+
+ // Runs until we get the OnSyntheticGestureCompleted callback
+ run_loop_->Run();
+ run_loop_.reset();
+
+ CheckScrollOffset(wait_until_scrolled,
+ expected_scroll_position_after_scroll);
+ }
+
// Generate touch events for a synthetic scroll from |point| for |distance|.
- // Returns true if the page scrolled by the desired amount, and false if
- // it didn't scroll at all.
- bool DoTouchScroll(const gfx::Point& point,
+ void DoTouchScroll(const gfx::Point& point,
const gfx::Vector2d& distance,
- bool wait_until_scrolled) {
+ bool wait_until_scrolled,
+ int expected_scroll_height_after_scroll,
+ const gfx::Vector2d& expected_scroll_position_after_scroll,
+ const base::TimeDelta& jank_time) {
+ DCHECK(URLLoaded());
EXPECT_EQ(0, GetScrollTop());
int scroll_height =
ExecuteScriptAndExtractInt("document.documentElement.scrollHeight");
- EXPECT_EQ(10200, scroll_height);
+ EXPECT_EQ(expected_scroll_height_after_scroll, scroll_height);
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.anchor = gfx::PointF(point);
params.distances.push_back(-distance);
- runner_ = new MessageLoopRunner();
+ run_loop_ = std::make_unique<base::RunLoop>();
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
@@ -166,33 +293,51 @@ class TouchActionBrowserTest : public ContentBrowserTest {
base::BindOnce(&TouchActionBrowserTest::OnSyntheticGestureCompleted,
base::Unretained(this)));
+ if (jank_time > base::TimeDelta::FromMilliseconds(0))
+ JankMainThread(jank_time);
+
// Runs until we get the OnSyntheticGestureCompleted callback
- runner_->Run();
- runner_ = nullptr;
+ run_loop_->Run();
+ run_loop_.reset();
- // Expect that the compositor scrolled at least one pixel while the
- // main thread was in a busy loop.
+ CheckScrollOffset(wait_until_scrolled,
+ expected_scroll_position_after_scroll);
+ }
+
+ private:
+ void CheckScrollOffset(
+ bool wait_until_scrolled,
+ const gfx::Vector2d& expected_scroll_position_after_scroll) {
gfx::Vector2dF default_scroll_offset;
+ gfx::Vector2dF root_scroll_offset =
+ frame_observer_->LastRenderFrameMetadata().root_scroll_offset.value_or(
+ default_scroll_offset);
+
+ // GetScrollTop() and GetScrollLeft() goes through the main thread, here
+ // we want to make sure that the compositor already scrolled before asking
+ // the main thread.
while (wait_until_scrolled &&
- frame_observer_->LastRenderFrameMetadata()
- .root_scroll_offset.value_or(default_scroll_offset)
- .y() < (distance.y() / 2)) {
+ (root_scroll_offset.y() <
+ expected_scroll_position_after_scroll.y() / 2 ||
+ root_scroll_offset.x() <
+ expected_scroll_position_after_scroll.x() / 2)) {
frame_observer_->WaitForMetadataChange();
+ root_scroll_offset =
+ frame_observer_->LastRenderFrameMetadata()
+ .root_scroll_offset.value_or(default_scroll_offset);
}
// Check the scroll offset
- double scroll_top = GetScrollTop();
- if (scroll_top == 0)
- return false;
+ int scroll_top = GetScrollTop();
+ int scroll_left = GetScrollLeft();
// Allow for 1px rounding inaccuracies for some screen sizes.
- EXPECT_LT(distance.y() / 2, scroll_top);
- return true;
+ EXPECT_LE(expected_scroll_position_after_scroll.y() / 2, scroll_top);
+ EXPECT_LE(expected_scroll_position_after_scroll.x() / 2, scroll_left);
}
- private:
std::unique_ptr<RenderFrameSubmissionObserver> frame_observer_;
- scoped_refptr<MessageLoopRunner> runner_;
+ std::unique_ptr<base::RunLoop> run_loop_;
DISALLOW_COPY_AND_ASSIGN(TouchActionBrowserTest);
};
@@ -209,10 +354,10 @@ class TouchActionBrowserTest : public ContentBrowserTest {
// Verify the test infrastructure works - we can touch-scroll the page and get a
// touchcancel as expected.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_DefaultAuto) {
- LoadURL();
+ LoadURL(kTouchActionDataURL);
- bool scrolled = DoTouchScroll(gfx::Point(50, 50), gfx::Vector2d(0, 45), true);
- EXPECT_TRUE(scrolled);
+ DoTouchScroll(gfx::Point(50, 50), gfx::Vector2d(0, 45), true, 10200,
+ gfx::Vector2d(0, 45), kNoJankTime);
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchstart"));
EXPECT_GE(ExecuteScriptAndExtractInt("eventCounts.touchmove"), 1);
@@ -229,11 +374,10 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_DefaultAuto) {
#define MAYBE_TouchActionNone TouchActionNone
#endif
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TouchActionNone) {
- LoadURL();
+ LoadURL(kTouchActionDataURL);
- bool scrolled =
- DoTouchScroll(gfx::Point(50, 150), gfx::Vector2d(0, 45), false);
- EXPECT_FALSE(scrolled);
+ DoTouchScroll(gfx::Point(50, 150), gfx::Vector2d(0, 45), false, 10200,
+ gfx::Vector2d(0, 0), kNoJankTime);
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchstart"));
EXPECT_GE(ExecuteScriptAndExtractInt("eventCounts.touchmove"), 1);
@@ -241,4 +385,127 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TouchActionNone) {
EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
}
+#if defined(OS_MACOSX)
+#define MAYBE_PanYMainThreadJanky DISABLED_PanYMainThreadJanky
+#else
+#define MAYBE_PanYMainThreadJanky PanYMainThreadJanky
+#endif
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanYMainThreadJanky) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(25, 125), gfx::Vector2d(0, 45), false, 10000,
+ gfx::Vector2d(0, 45), kShortJankTime);
+}
+
+#if defined(OS_MACOSX)
+#define MAYBE_PanXMainThreadJanky DISABLED_PanXMainThreadJanky
+#else
+#define MAYBE_PanXMainThreadJanky PanXMainThreadJanky
+#endif
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanXMainThreadJanky) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(125, 25), gfx::Vector2d(45, 0), false, 10000,
+ gfx::Vector2d(45, 0), kShortJankTime);
+}
+
+#if defined(OS_ANDROID)
+#define MAYBE_PanXAtYAreaWithTimeout PanXAtYAreaWithTimeout
+#else
+#define MAYBE_PanXAtYAreaWithTimeout DISABLED_PanXAtYAreaWithTimeout
+#endif
+// When touch ack timeout is triggered, the panx gesture will be allowed even
+// though we touch the pany area.
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanXAtYAreaWithTimeout) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(25, 125), gfx::Vector2d(45, 0), false, 10000,
+ gfx::Vector2d(45, 0), kLongJankTime);
+}
+
+#if defined(OS_ANDROID)
+#define MAYBE_TwoFingerPanXAtYAreaWithTimeout TwoFingerPanXAtYAreaWithTimeout
+#else
+#define MAYBE_TwoFingerPanXAtYAreaWithTimeout \
+ DISABLED_TwoFingerPanXAtYAreaWithTimeout
+#endif
+// When touch ack timeout is triggered, the panx gesture will be allowed even
+// though we touch the pany area.
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
+ MAYBE_TwoFingerPanXAtYAreaWithTimeout) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTwoFingerTouchScroll(false, gfx::Vector2d(20, 0));
+}
+
+#if defined(OS_MACOSX)
+#define MAYBE_PanXYMainThreadJanky DISABLED_PanXYMainThreadJanky
+#else
+#define MAYBE_PanXYMainThreadJanky PanXYMainThreadJanky
+#endif
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_PanXYMainThreadJanky) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(75, 60), gfx::Vector2d(45, 45), false, 10000,
+ gfx::Vector2d(45, 45), kShortJankTime);
+}
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+// Flaky: https://crbug.com/833015
+#define MAYBE_PanXYAtXAreaMainThreadJanky DISABLED_PanXYAtXAreaMainThreadJanky
+#else
+#define MAYBE_PanXYAtXAreaMainThreadJanky PanXYAtXAreaMainThreadJanky
+#endif
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
+ MAYBE_PanXYAtXAreaMainThreadJanky) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(125, 25), gfx::Vector2d(45, 45), false, 10000,
+ gfx::Vector2d(45, 0), kShortJankTime);
+}
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+// Flaky: https://crbug.com/833015
+#define MAYBE_PanXYAtYAreaMainThreadJanky DISABLED_PanXYAtYAreaMainThreadJanky
+#else
+#define MAYBE_PanXYAtYAreaMainThreadJanky PanXYAtYAreaMainThreadJanky
+#endif
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
+ MAYBE_PanXYAtYAreaMainThreadJanky) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(25, 125), gfx::Vector2d(45, 45), false, 10000,
+ gfx::Vector2d(0, 45), kShortJankTime);
+}
+
+#if defined(OS_MACOSX)
+#define MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky \
+ DISABLED_PanXYAtAutoYOverlapAreaMainThreadJanky
+#else
+#define MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky \
+ PanXYAtAutoYOverlapAreaMainThreadJanky
+#endif
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
+ MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(75, 125), gfx::Vector2d(45, 45), false, 10000,
+ gfx::Vector2d(0, 45), kShortJankTime);
+}
+
+#if defined(OS_MACOSX)
+#define MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky \
+ DISABLED_PanXYAtAutoXOverlapAreaMainThreadJanky
+#else
+#define MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky \
+ PanXYAtAutoXOverlapAreaMainThreadJanky
+#endif
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest,
+ MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky) {
+ LoadURL(kTouchActionURLWithOverlapArea);
+
+ DoTouchScroll(gfx::Point(125, 75), gfx::Vector2d(45, 45), false, 10000,
+ gfx::Vector2d(45, 0), kShortJankTime);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.cc b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
index d6e89f5aa5b..a7cd888a9cb 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.cc
@@ -41,9 +41,10 @@ TouchActionFilter::TouchActionFilter()
force_enable_zoom_(false),
allowed_touch_action_(cc::kTouchActionAuto) {}
-bool TouchActionFilter::FilterGestureEvent(WebGestureEvent* gesture_event) {
+FilterGestureEventResult TouchActionFilter::FilterGestureEvent(
+ WebGestureEvent* gesture_event) {
if (gesture_event->SourceDevice() != blink::kWebGestureDeviceTouchscreen)
- return false;
+ return FilterGestureEventResult::kFilterGestureEventAllowed;
// Filter for allowable touch actions first (eg. before the TouchEventQueue
// can decide to send a touch cancel event).
@@ -52,11 +53,13 @@ bool TouchActionFilter::FilterGestureEvent(WebGestureEvent* gesture_event) {
DCHECK(!suppress_manipulation_events_);
suppress_manipulation_events_ =
ShouldSuppressManipulation(*gesture_event);
- return suppress_manipulation_events_;
+ return suppress_manipulation_events_
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed;
case WebInputEvent::kGestureScrollUpdate:
if (suppress_manipulation_events_)
- return true;
+ return FilterGestureEventResult::kFilterGestureEventFiltered;
// Scrolls restricted to a specific axis shouldn't permit movement
// in the perpendicular axis.
@@ -94,17 +97,23 @@ bool TouchActionFilter::FilterGestureEvent(WebGestureEvent* gesture_event) {
gesture_event->SetType(WebInputEvent::kGestureScrollEnd);
}
}
- return FilterManipulationEventAndResetState();
+ return FilterManipulationEventAndResetState()
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed;
case WebInputEvent::kGestureScrollEnd:
ReportGestureEventFiltered(suppress_manipulation_events_);
- return FilterManipulationEventAndResetState();
+ return FilterManipulationEventAndResetState()
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed;
case WebInputEvent::kGesturePinchBegin:
case WebInputEvent::kGesturePinchUpdate:
case WebInputEvent::kGesturePinchEnd:
ReportGestureEventFiltered(suppress_manipulation_events_);
- return suppress_manipulation_events_;
+ return suppress_manipulation_events_
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed;
// The double tap gesture is a tap ending event. If a double tap gesture is
// filtered out, replace it with a tap event.
@@ -134,7 +143,7 @@ bool TouchActionFilter::FilterGestureEvent(WebGestureEvent* gesture_event) {
case WebInputEvent::kGestureTapCancel:
if (drop_current_tap_ending_event_) {
drop_current_tap_ending_event_ = false;
- return true;
+ return FilterGestureEventResult::kFilterGestureEventFiltered;
}
break;
@@ -148,7 +157,7 @@ bool TouchActionFilter::FilterGestureEvent(WebGestureEvent* gesture_event) {
break;
}
- return false;
+ return FilterGestureEventResult::kFilterGestureEventAllowed;
}
bool TouchActionFilter::FilterManipulationEventAndResetState() {
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter.h b/chromium/content/browser/renderer_host/input/touch_action_filter.h
index fd6d5e6cd0a..851d92e954b 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter.h
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter.h
@@ -18,6 +18,11 @@ namespace content {
class MockRenderWidgetHost;
+enum class FilterGestureEventResult {
+ kFilterGestureEventAllowed,
+ kFilterGestureEventFiltered
+};
+
// The TouchActionFilter is responsible for filtering scroll and pinch gesture
// events according to the CSS touch-action values the renderer has sent for
// each touch point.
@@ -26,11 +31,12 @@ class CONTENT_EXPORT TouchActionFilter {
public:
TouchActionFilter();
- // Returns true if the supplied gesture event should be dropped based on the
- // current touch-action state. Otherwise returns false, and possibly modifies
- // the event's directional parameters to make the event compatible with
- // the effective touch-action.
- bool FilterGestureEvent(blink::WebGestureEvent* gesture_event);
+ // Returns kFilterGestureEventFiltered if the supplied gesture event should be
+ // dropped based on the current touch-action state. Otherwise returns
+ // kFilterGestureEventAllowed, and possibly modifies the event's directional
+ // parameters to make the event compatible with the effective touch-action.
+ FilterGestureEventResult FilterGestureEvent(
+ blink::WebGestureEvent* gesture_event);
// Called when a set-touch-action message is received from the renderer
// for a touch start event that is currently in flight.
diff --git a/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
index 11e64ae5579..eadd374e19c 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_filter_unittest.cc
@@ -42,16 +42,19 @@ static void PanTest(cc::TouchAction action,
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(0, 0, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
}
{
@@ -61,12 +64,14 @@ static void PanTest(cc::TouchAction action,
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(expected_dx, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(expected_dy, scroll_update.data.scroll_update.delta_y);
@@ -77,13 +82,15 @@ static void PanTest(cc::TouchAction action,
WebGestureEvent scroll_update2 =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(-dx, -dy, 0,
kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update2));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update2),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(-expected_dx, scroll_update2.data.scroll_update.delta_x);
EXPECT_EQ(-expected_dy, scroll_update2.data.scroll_update.delta_y);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
fling_x, fling_y, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(expected_fling_x, fling_start.data.fling_start.velocity_x);
EXPECT_EQ(expected_fling_y, fling_start.data.fling_start.velocity_y);
}
@@ -96,16 +103,19 @@ static void PanTest(cc::TouchAction action,
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_y, scroll_x,
kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0,
kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(dx, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(dy, scroll_update.data.scroll_update.delta_y);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
}
@@ -123,13 +133,16 @@ static void PanTestForUnidirectionalTouchAction(cc::TouchAction action,
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(scroll_x, scroll_y,
kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(scroll_x, scroll_y,
0, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
}
{
@@ -140,13 +153,16 @@ static void PanTestForUnidirectionalTouchAction(cc::TouchAction action,
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-scroll_x, -scroll_y,
kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(-scroll_x, -scroll_y,
0, kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
{
@@ -157,13 +173,16 @@ static void PanTestForUnidirectionalTouchAction(cc::TouchAction action,
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(
-scroll_x - scroll_y, -scroll_x - scroll_y, kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(
-scroll_x - scroll_y, -scroll_x - scroll_y, 0, kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
}
@@ -184,62 +203,86 @@ TEST(TouchActionFilterTest, SimpleFilter) {
// No events filtered by default.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// cc::kTouchActionAuto doesn't cause any filtering.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// cc::kTouchActionNone filters out all scroll events, but no other events.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&tap));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
// When a new touch sequence begins, the state is reset.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Setting touch action doesn't impact any in-progress gestures.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// And the state is still cleared for the next gesture.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Changing the touch action during a gesture has no effect.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
TEST(TouchActionFilterTest, Fling) {
@@ -260,19 +303,26 @@ TEST(TouchActionFilterTest, Fling) {
// cc::kTouchActionNone filters out fling events.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(kFlingX, fling_start.data.fling_start.velocity_x);
EXPECT_EQ(kFlingY, fling_start.data.fling_start.velocity_y);
// touchpad flings aren't filtered.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pad_fling));
- EXPECT_TRUE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pad_fling),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
TEST(TouchActionFilterTest, PanLeft) {
@@ -364,18 +414,21 @@ TEST(TouchActionFilterTest, PanXY) {
filter.OnSetTouchAction(cc::kTouchActionPan);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0,
kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kDX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDY, scroll_update.data.scroll_update.delta_y);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kFlingX, fling_start.data.fling_start.velocity_x);
EXPECT_EQ(kFlingY, fling_start.data.fling_start.velocity_y);
}
@@ -386,18 +439,21 @@ TEST(TouchActionFilterTest, PanXY) {
filter.OnSetTouchAction(cc::kTouchActionPan);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0,
kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kDX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDY, scroll_update.data.scroll_update.delta_y);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(kFlingX, fling_start.data.fling_start.velocity_x);
EXPECT_EQ(kFlingY, fling_start.data.fling_start.velocity_y);
}
@@ -409,16 +465,19 @@ TEST(TouchActionFilterTest, PanXY) {
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice,
2);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
WebGestureEvent scroll_update =
SyntheticWebGestureEventBuilder::BuildScrollUpdate(kDX, kDY, 0,
kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, kFlingY, kSourceDevice);
- EXPECT_TRUE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
}
@@ -453,21 +512,28 @@ TEST(TouchActionFilterTest, MultiTouch) {
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
EXPECT_EQ(kDeltaX, scroll_update.data.scroll_update.delta_x);
EXPECT_EQ(kDeltaY, scroll_update.data.scroll_update.delta_y);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
// Intersection of PAN_X and PAN_Y is NONE.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionPanX);
filter.OnSetTouchAction(cc::kTouchActionPanY);
filter.OnSetTouchAction(cc::kTouchActionPan);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
class TouchActionFilterPinchTest : public testing::Test {
@@ -492,101 +558,168 @@ class TouchActionFilterPinchTest : public testing::Test {
// Pinch is allowed with touch-action: auto.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinch is not allowed with touch-action: none.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
// Pinch is not allowed with touch-action: pan-x pan-y except for force
// enable zoom.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionPan);
- EXPECT_NE(filter.FilterGestureEvent(&scroll_begin), force_enable_zoom);
- EXPECT_NE(filter.FilterGestureEvent(&pinch_begin), force_enable_zoom);
- EXPECT_NE(filter.FilterGestureEvent(&pinch_update), force_enable_zoom);
- EXPECT_NE(filter.FilterGestureEvent(&pinch_end), force_enable_zoom);
- EXPECT_NE(filter.FilterGestureEvent(&scroll_end), force_enable_zoom);
+ EXPECT_NE(filter.FilterGestureEvent(&scroll_begin),
+ force_enable_zoom
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_NE(filter.FilterGestureEvent(&pinch_begin),
+ force_enable_zoom
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_NE(filter.FilterGestureEvent(&pinch_update),
+ force_enable_zoom
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_NE(filter.FilterGestureEvent(&pinch_end),
+ force_enable_zoom
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_NE(filter.FilterGestureEvent(&scroll_end),
+ force_enable_zoom
+ ? FilterGestureEventResult::kFilterGestureEventFiltered
+ : FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinch is allowed with touch-action: manipulation.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionManipulation);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinch state is automatically reset at the end of a scroll.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Pinching is only computed at GestureScrollBegin time.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Once a pinch has started, any change in state won't affect the pinch
// gestures since it is computed in GestureScrollBegin.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Scrolling is allowed when two fingers are down.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// A pinch event sequence with only one pointer is equivalent to a scroll
// gesture, so disallowed as a pinch gesture.
scroll_begin.data.scroll_begin.pointer_count = 1;
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionPinchZoom);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
};
@@ -614,17 +747,22 @@ TEST(TouchActionFilterTest, DoubleTapWithTouchActionAuto) {
// Double tap is allowed with touch action auto.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
- EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(unconfirmed_tap.GetType(), WebInputEvent::kGestureTapUnconfirmed);
// The tap cancel will come as part of the next touch sequence.
filter.ResetTouchAction();
// Changing the touch action for the second tap doesn't effect the behaviour
// of the event.
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&tap_cancel));
- EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
- EXPECT_FALSE(filter.FilterGestureEvent(&double_tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_cancel),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&double_tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
}
TEST(TouchActionFilterTest, DoubleTap) {
@@ -642,16 +780,21 @@ TEST(TouchActionFilterTest, DoubleTap) {
// Double tap is disabled with any touch action other than auto.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionManipulation);
- EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
- EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTap, unconfirmed_tap.GetType());
// Changing the touch action for the second tap doesn't effect the behaviour
// of the event. The tap cancel will come as part of the next touch sequence.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionAuto);
- EXPECT_TRUE(filter.FilterGestureEvent(&tap_cancel));
- EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
- EXPECT_FALSE(filter.FilterGestureEvent(&double_tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_cancel),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&double_tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTap, double_tap.GetType());
}
@@ -667,10 +810,13 @@ TEST(TouchActionFilterTest, SingleTapWithTouchActionAuto) {
// Single tap is allowed with touch action auto.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
- EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap1));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap1),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTapUnconfirmed, unconfirmed_tap1.GetType());
- EXPECT_FALSE(filter.FilterGestureEvent(&tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
}
TEST(TouchActionFilterTest, SingleTap) {
@@ -686,10 +832,13 @@ TEST(TouchActionFilterTest, SingleTap) {
// With touch action other than auto, tap unconfirmed is turned into tap.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&tap_down));
- EXPECT_FALSE(filter.FilterGestureEvent(&unconfirmed_tap1));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap_down),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&unconfirmed_tap1),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureTap, unconfirmed_tap1.GetType());
- EXPECT_TRUE(filter.FilterGestureEvent(&tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
}
TEST(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
@@ -704,15 +853,19 @@ TEST(TouchActionFilterTest, TouchActionResetsOnResetTouchAction) {
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&tap));
+ EXPECT_EQ(filter.FilterGestureEvent(&tap),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
}
TEST(TouchActionFilterTest, TouchActionResetMidSequence) {
@@ -731,27 +884,39 @@ TEST(TouchActionFilterTest, TouchActionResetMidSequence) {
WebInputEvent::kGestureScrollEnd, kSourceDevice);
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
// Even though the allowed action is auto after the reset, the remaining
// scroll and pinch events should be suppressed.
filter.ResetTouchAction();
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_TRUE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_TRUE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventFiltered);
// A new scroll and pinch sequence should be allowed.
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_begin));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
// Resetting from auto to auto mid-stream should have no effect.
filter.ResetTouchAction();
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_update));
- EXPECT_FALSE(filter.FilterGestureEvent(&pinch_end));
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_end));
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_update),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&pinch_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_end),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
}
TEST(TouchActionFilterTest, ZeroVelocityFlingsConvertedToScrollEnd) {
@@ -766,11 +931,13 @@ TEST(TouchActionFilterTest, ZeroVelocityFlingsConvertedToScrollEnd) {
filter.OnSetTouchAction(cc::kTouchActionPanY);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-6, 7, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
kFlingX, 0, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, fling_start.GetType());
}
@@ -783,11 +950,13 @@ TEST(TouchActionFilterTest, ZeroVelocityFlingsConvertedToScrollEnd) {
filter.OnSetTouchAction(cc::kTouchActionPanX);
WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(-7, 6, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
WebGestureEvent fling_start = SyntheticWebGestureEventBuilder::BuildFling(
0, kFlingY, kSourceDevice);
- EXPECT_FALSE(filter.FilterGestureEvent(&fling_start));
+ EXPECT_EQ(filter.FilterGestureEvent(&fling_start),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
EXPECT_EQ(WebInputEvent::kGestureScrollEnd, fling_start.GetType());
}
}
@@ -802,7 +971,8 @@ TEST(TouchActionFilterTest, TouchpadScroll) {
// cc::kTouchActionNone filters out only touchscreen scroll events.
filter.ResetTouchAction();
filter.OnSetTouchAction(cc::kTouchActionNone);
- EXPECT_FALSE(filter.FilterGestureEvent(&scroll_begin));
+ EXPECT_EQ(filter.FilterGestureEvent(&scroll_begin),
+ FilterGestureEventResult::kFilterGestureEventAllowed);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index 8c110ea6985..e8aa3c16478 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -5,8 +5,10 @@
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "base/containers/queue.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/input/motion_event_web.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/common/input/web_touch_event_traits.h"
#include "content/grit/content_resources.h"
@@ -57,7 +59,8 @@ int ModifiersWithoutMouseButtons(const WebInputEvent& event) {
// Time between two consecutive mouse moves, during which second mouse move
// is not converted to touch.
-const double kMouseMoveDropIntervalSeconds = 5.f / 1000;
+constexpr base::TimeDelta kMouseMoveDropInterval =
+ base::TimeDelta::FromMilliseconds(5);
} // namespace
@@ -70,6 +73,7 @@ TouchEmulator::TouchEmulator(TouchEmulatorClient* client,
use_2x_cursors_(false),
emulated_stream_active_sequence_count_(0),
native_stream_active_sequence_count_(0),
+ last_emulated_start_target_(nullptr),
pending_taps_count_(0) {
DCHECK(client_);
ResetState();
@@ -84,7 +88,7 @@ TouchEmulator::~TouchEmulator() {
void TouchEmulator::ResetState() {
last_mouse_event_was_move_ = false;
- last_mouse_move_timestamp_ = 0;
+ last_mouse_move_timestamp_ = base::TimeTicks();
mouse_pressed_ = false;
shift_pressed_ = false;
suppress_next_fling_cancel_ = false;
@@ -174,7 +178,8 @@ gfx::SizeF TouchEmulator::InitCursorFromResource(
return gfx::ScaleSize(gfx::SizeF(cursor_image.Size()), 1.f / scale);
}
-bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
+bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event,
+ RenderWidgetHostViewBase* target_view) {
if (!enabled() || mode_ != Mode::kEmulatingTouchFromMouse)
return false;
@@ -191,12 +196,12 @@ bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
if (mouse_event.GetType() == WebInputEvent::kMouseMove) {
if (last_mouse_event_was_move_ &&
- mouse_event.TimeStampSeconds() <
- last_mouse_move_timestamp_ + kMouseMoveDropIntervalSeconds)
+ mouse_event.TimeStamp() <
+ last_mouse_move_timestamp_ + kMouseMoveDropInterval)
return true;
last_mouse_event_was_move_ = true;
- last_mouse_move_timestamp_ = mouse_event.TimeStampSeconds();
+ last_mouse_move_timestamp_ = mouse_event.TimeStamp();
} else {
last_mouse_event_was_move_ = false;
}
@@ -215,8 +220,11 @@ bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
return true;
}
- FillTouchEventAndPoint(mouse_event);
- HandleEmulatedTouchEvent(touch_event_);
+ gfx::PointF pos_in_root = mouse_event.PositionInWidget();
+ if (target_view)
+ pos_in_root = target_view->TransformPointToRootCoordSpaceF(pos_in_root);
+ FillTouchEventAndPoint(mouse_event, pos_in_root);
+ HandleEmulatedTouchEvent(touch_event_, target_view);
// Do not pass mouse events to the renderer.
return true;
@@ -269,7 +277,9 @@ bool TouchEmulator::HandleTouchEvent(const blink::WebTouchEvent& event) {
return false;
}
-bool TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
+bool TouchEmulator::HandleEmulatedTouchEvent(
+ blink::WebTouchEvent event,
+ RenderWidgetHostViewBase* target_view) {
DCHECK(gesture_provider_);
event.unique_touch_event_id = ui::GetNextTouchEventId();
auto result = gesture_provider_->OnTouchEvent(MotionEventWeb(event));
@@ -295,11 +305,13 @@ bool TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
return true;
}
- if (is_sequence_start)
+ if (is_sequence_start) {
emulated_stream_active_sequence_count_++;
+ last_emulated_start_target_ = target_view;
+ }
event.moved_beyond_slop_region = result.moved_beyond_slop_region;
- client_->ForwardEmulatedTouchEvent(event);
+ client_->ForwardEmulatedTouchEvent(event, target_view);
return false;
}
@@ -329,7 +341,8 @@ bool TouchEmulator::HandleTouchEventAck(
return false;
}
-void TouchEmulator::OnGestureEventAck(const WebGestureEvent& event) {
+void TouchEmulator::OnGestureEventAck(const WebGestureEvent& event,
+ RenderWidgetHostViewBase*) {
if (event.GetType() != WebInputEvent::kGestureTap)
return;
if (pending_taps_count_) {
@@ -338,10 +351,27 @@ void TouchEmulator::OnGestureEventAck(const WebGestureEvent& event) {
}
}
+void TouchEmulator::OnViewDestroyed(RenderWidgetHostViewBase* destroyed_view) {
+ if (destroyed_view != last_emulated_start_target_)
+ return;
+
+ last_emulated_start_target_ = nullptr;
+ emulated_stream_active_sequence_count_ = 0;
+}
+
void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
WebGestureEvent gesture_event =
ui::CreateWebGestureEventFromGestureEventData(gesture);
+ if (!gesture_event.unique_touch_event_id) {
+ // TODO(wjmaclean): Find out why the local GestureProvider puts id=0 on
+ // kGestureShowPress. This is a problem for RWHIER as it will cause it to
+ // attempt to re-target the event. There must be a nicer solution than
+ // setting the id to -1.
+ DCHECK(gesture_event.GetType() == blink::WebInputEvent::kGestureShowPress);
+ gesture_event.unique_touch_event_id = -1;
+ }
+
switch (gesture_event.GetType()) {
case WebInputEvent::kUndefined:
NOTREACHED() << "Undefined WebInputEvent type";
@@ -410,11 +440,12 @@ void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
}
void TouchEmulator::InjectTouchEvent(const blink::WebTouchEvent& event,
+ RenderWidgetHostViewBase* target_view,
base::OnceClosure callback) {
DCHECK(enabled() && mode_ == Mode::kInjectingTouchEvents);
touch_event_ = event;
injected_touch_completion_callbacks_.push(std::move(callback));
- if (HandleEmulatedTouchEvent(touch_event_))
+ if (HandleEmulatedTouchEvent(touch_event_, target_view))
OnInjectedTouchCompleted();
}
@@ -433,11 +464,10 @@ void TouchEmulator::CancelTouch() {
}
WebTouchEventTraits::ResetTypeAndTouchStates(
- WebInputEvent::kTouchCancel,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()), &touch_event_);
+ WebInputEvent::kTouchCancel, ui::EventTimeForNow(), &touch_event_);
DCHECK(gesture_provider_);
if (gesture_provider_->GetCurrentDownEvent())
- HandleEmulatedTouchEvent(touch_event_);
+ HandleEmulatedTouchEvent(touch_event_, last_emulated_start_target_);
}
void TouchEmulator::UpdateCursor() {
@@ -488,7 +518,7 @@ void TouchEmulator::PinchEnd(const WebGestureEvent& event) {
void TouchEmulator::ScrollEnd(const WebGestureEvent& event) {
WebGestureEvent scroll_event(
WebInputEvent::kGestureScrollEnd, ModifiersWithoutMouseButtons(event),
- event.TimeStampSeconds(), blink::kWebGestureDeviceTouchscreen);
+ event.TimeStamp(), blink::kWebGestureDeviceTouchscreen);
client_->ForwardEmulatedGestureEvent(scroll_event);
}
@@ -496,13 +526,14 @@ WebGestureEvent TouchEmulator::GetPinchGestureEvent(
WebInputEvent::Type type,
const WebInputEvent& original_event) {
WebGestureEvent event(type, ModifiersWithoutMouseButtons(original_event),
- original_event.TimeStampSeconds(),
+ original_event.TimeStamp(),
blink::kWebGestureDeviceTouchscreen);
event.SetPositionInWidget(pinch_anchor_);
return event;
}
-void TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
+void TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event,
+ const gfx::PointF& pos_in_root) {
WebInputEvent::Type eventType;
switch (mouse_event.GetType()) {
case WebInputEvent::kMouseDown:
@@ -522,15 +553,18 @@ void TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
touch_event_.touches_length = 1;
touch_event_.SetModifiers(ModifiersWithoutMouseButtons(mouse_event));
WebTouchEventTraits::ResetTypeAndTouchStates(
- eventType, mouse_event.TimeStampSeconds(), &touch_event_);
+ eventType, mouse_event.TimeStamp(), &touch_event_);
WebTouchPoint& point = touch_event_.touches[0];
point.id = 0;
point.radius_x = 0.5f * cursor_size_.width();
point.radius_y = 0.5f * cursor_size_.height();
point.force = eventType == WebInputEvent::kTouchEnd ? 0.f : 1.f;
point.rotation_angle = 0.f;
- point.SetPositionInWidget(mouse_event.PositionInWidget().x,
- mouse_event.PositionInWidget().y);
+ // We need to convert this to the root-view's coord space, otherwise the
+ // GestureRecognizer will potentially receive events for a moving widget,
+ // for example when scroll bubbling is taking place. The GestureRecognizer
+ // isn't designed to handle that.
+ point.SetPositionInWidget(pos_in_root);
point.SetPositionInScreen(mouse_event.PositionInScreen().x,
mouse_event.PositionInScreen().y);
point.tilt_x = 0;
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index 9c53f845f5d..c419968b6ef 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -26,6 +26,8 @@ class WebMouseWheelEvent;
namespace content {
+class RenderWidgetHostViewBase;
+
// Emulates touch input. See TouchEmulator::Mode for more details.
class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
public:
@@ -57,12 +59,17 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// Returns |true| if the event was consumed. Consumed event should not
// propagate any further.
// TODO(dgozman): maybe pass latency info together with events.
- bool HandleMouseEvent(const blink::WebMouseEvent& event);
+ bool HandleMouseEvent(const blink::WebMouseEvent& event,
+ RenderWidgetHostViewBase* target_view);
bool HandleMouseWheelEvent(const blink::WebMouseWheelEvent& event);
bool HandleKeyboardEvent(const blink::WebKeyboardEvent& event);
bool HandleTouchEvent(const blink::WebTouchEvent& event);
- void OnGestureEventAck(const blink::WebGestureEvent& event);
+ void OnGestureEventAck(const blink::WebGestureEvent& event,
+ RenderWidgetHostViewBase* target_view);
+
+ // Called to notify the TouchEmulator when a view is destroyed.
+ void OnViewDestroyed(RenderWidgetHostViewBase* destroyed_view);
// Returns |true| if the event ack was consumed. Consumed ack should not
// propagate any further.
@@ -72,6 +79,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// Injects a touch event to be processed for gestures and optionally
// forwarded to the client. Only works in kInjectingTouchEvents mode.
void InjectTouchEvent(const blink::WebTouchEvent& event,
+ RenderWidgetHostViewBase* target_view,
base::OnceClosure completion_callback);
// Cancel any touches, for example, when focus is lost.
@@ -92,7 +100,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// Whether we should convert scrolls into pinches.
bool InPinchGestureMode() const;
- void FillTouchEventAndPoint(const blink::WebMouseEvent& mouse_event);
+ void FillTouchEventAndPoint(const blink::WebMouseEvent& mouse_event,
+ const gfx::PointF& pos_in_root);
blink::WebGestureEvent GetPinchGestureEvent(
blink::WebInputEvent::Type type,
const blink::WebInputEvent& original_event);
@@ -106,7 +115,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// Offers the emulated event to |gesture_provider_|, conditionally forwarding
// it to the client if appropriate. Returns whether event was handled
// synchronously, and there will be no ack.
- bool HandleEmulatedTouchEvent(blink::WebTouchEvent event);
+ bool HandleEmulatedTouchEvent(blink::WebTouchEvent event,
+ RenderWidgetHostViewBase* target_view);
// Called when ack for injected touch has been received.
void OnInjectedTouchCompleted();
@@ -132,7 +142,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// These are used to drop extra mouse move events coming too quickly, so
// we don't handle too much touches in gesture provider.
bool last_mouse_event_was_move_;
- double last_mouse_move_timestamp_;
+ base::TimeTicks last_mouse_move_timestamp_;
bool mouse_pressed_;
bool shift_pressed_;
@@ -140,6 +150,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
blink::WebTouchEvent touch_event_;
int emulated_stream_active_sequence_count_;
int native_stream_active_sequence_count_;
+ RenderWidgetHostViewBase* last_emulated_start_target_;
// TODO(einbinder): this relies on synchronous tap gesture generation and does
// not work for any other gestures. We should switch to callbacks which go
// through touches and gestures once that's available.
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_client.h b/chromium/content/browser/renderer_host/input/touch_emulator_client.h
index 991e0e16d21..4f398b0ba8c 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_client.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_client.h
@@ -13,6 +13,8 @@
namespace content {
+class RenderWidgetHostViewBase;
+
// Emulates touch input with mouse and keyboard.
class CONTENT_EXPORT TouchEmulatorClient {
public:
@@ -20,7 +22,8 @@ class CONTENT_EXPORT TouchEmulatorClient {
virtual void ForwardEmulatedGestureEvent(
const blink::WebGestureEvent& event) = 0;
- virtual void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event) = 0;
+ virtual void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event,
+ RenderWidgetHostViewBase* target) = 0;
virtual void SetCursor(const WebCursor& cursor) = 0;
virtual void ShowContextMenuAtPoint(const gfx::Point& point,
const ui::MenuSourceType source_type) = 0;
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
index 4b3f9b0b069..85c3798da5b 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -34,15 +34,13 @@ class TouchEmulatorTest : public testing::Test,
TouchEmulatorTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI),
+ last_event_time_(base::TimeTicks::Now()),
+ event_time_delta_(base::TimeDelta::FromMilliseconds(100)),
shift_pressed_(false),
mouse_pressed_(false),
ack_touches_synchronously_(true),
last_mouse_x_(-1),
- last_mouse_y_(-1) {
- last_event_time_seconds_ =
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
- event_time_delta_seconds_ = 0.1;
- }
+ last_mouse_y_(-1) {}
~TouchEmulatorTest() override {}
@@ -64,7 +62,8 @@ class TouchEmulatorTest : public testing::Test,
forwarded_events_.push_back(event.GetType());
}
- void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event) override {
+ void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event,
+ RenderWidgetHostViewBase* target) override {
forwarded_events_.push_back(event.GetType());
EXPECT_EQ(1U, event.touches_length);
EXPECT_EQ(last_mouse_x_, event.touches[0].PositionInWidget().x);
@@ -113,17 +112,17 @@ class TouchEmulatorTest : public testing::Test,
return result;
}
- double GetNextEventTimeSeconds() {
- last_event_time_seconds_ += event_time_delta_seconds_;
- return last_event_time_seconds_;
+ base::TimeTicks GetNextEventTime() {
+ last_event_time_ += event_time_delta_;
+ return last_event_time_;
}
- void set_event_time_delta_seconds_(double delta) {
- event_time_delta_seconds_ = delta;
+ void set_event_time_delta(base::TimeDelta delta) {
+ event_time_delta_ = delta;
}
void SendKeyboardEvent(WebInputEvent::Type type) {
- WebKeyboardEvent event(type, modifiers(), GetNextEventTimeSeconds());
+ WebKeyboardEvent event(type, modifiers(), GetNextEventTime());
emulator()->HandleKeyboardEvent(event);
}
@@ -140,19 +139,19 @@ class TouchEmulatorTest : public testing::Test,
}
void SendMouseEvent(WebInputEvent::Type type, int x, int y) {
- WebMouseEvent event(type, modifiers(), GetNextEventTimeSeconds());
+ WebMouseEvent event(type, modifiers(), GetNextEventTime());
event.button = mouse_pressed_ ? WebMouseEvent::Button::kLeft
: WebMouseEvent::Button::kNoButton;
last_mouse_x_ = x;
last_mouse_y_ = y;
event.SetPositionInWidget(x, y);
event.SetPositionInScreen(x, y);
- emulator()->HandleMouseEvent(event);
+ emulator()->HandleMouseEvent(event, nullptr);
}
bool SendMouseWheelEvent() {
WebMouseWheelEvent event(WebInputEvent::kMouseWheel, modifiers(),
- GetNextEventTimeSeconds());
+ GetNextEventTime());
// Return whether mouse wheel is forwarded.
return !emulator()->HandleMouseWheelEvent(event);
}
@@ -200,7 +199,7 @@ class TouchEmulatorTest : public testing::Test,
WebTouchEvent MakeTouchEvent(WebInputEvent::Type type,
WebTouchPoint::State state, int x, int y) {
- WebTouchEvent event(type, modifiers(), GetNextEventTimeSeconds());
+ WebTouchEvent event(type, modifiers(), GetNextEventTime());
event.touches_length = 1;
event.touches[0].id = 0;
event.touches[0].state = state;
@@ -237,7 +236,7 @@ class TouchEmulatorTest : public testing::Test,
last_mouse_x_ = x;
last_mouse_y_ = y;
WebTouchEvent event = MakeTouchEvent(type, state, x, y);
- emulator()->InjectTouchEvent(event, base::OnceClosure());
+ emulator()->InjectTouchEvent(event, nullptr, base::OnceClosure());
}
void AckOldestTouchEvent() {
@@ -261,8 +260,8 @@ class TouchEmulatorTest : public testing::Test,
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<TouchEmulator> emulator_;
std::vector<WebInputEvent::Type> forwarded_events_;
- double last_event_time_seconds_;
- double event_time_delta_seconds_;
+ base::TimeTicks last_event_time_;
+ base::TimeDelta event_time_delta_;
bool shift_pressed_;
bool mouse_pressed_;
bool ack_touches_synchronously_;
@@ -450,7 +449,7 @@ TEST_F(TouchEmulatorTest, MouseMovesDropped) {
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
// Mouse move after mouse down is never dropped.
- set_event_time_delta_seconds_(0.001);
+ set_event_time_delta(base::TimeDelta::FromMilliseconds(1));
MouseDrag(200, 200);
EXPECT_EQ(
"TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate",
@@ -463,7 +462,7 @@ TEST_F(TouchEmulatorTest, MouseMovesDropped) {
EXPECT_EQ("", ExpectedEvents());
// Dispatching again.
- set_event_time_delta_seconds_(0.1);
+ set_event_time_delta(base::TimeDelta::FromMilliseconds(100));
MouseDrag(400, 200);
EXPECT_EQ(
"TouchMove GestureScrollUpdate",
diff --git a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
index 645bc4be2b5..f223edca1d7 100644
--- a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -47,7 +47,7 @@ const char kTouchEventDataURL[] =
"<body onload='setup();'>"
"<div id='first'></div><div id='second'></div><div id='third'></div>"
"<style>"
- " #first {"
+ " %23first {"
" position: absolute;"
" width: 100px;"
" height: 100px;"
@@ -56,7 +56,7 @@ const char kTouchEventDataURL[] =
" background-color: green;"
" -webkit-transform: translate3d(0, 0, 0);"
" }"
- " #second {"
+ " %23second {"
" position: absolute;"
" width: 100px;"
" height: 100px;"
@@ -65,7 +65,7 @@ const char kTouchEventDataURL[] =
" background-color: blue;"
" -webkit-transform: translate3d(0, 0, 0);"
" }"
- " #third {"
+ " %23third {"
" position: absolute;"
" width: 100px;"
" height: 100px;"
@@ -116,7 +116,7 @@ class TouchInputBrowserTest : public ContentBrowserTest {
host->GetView()->SetSize(gfx::Size(400, 400));
// The page is loaded in the renderer, wait for a new frame to arrive.
- while (!host->ScheduleComposite())
+ while (!host->RequestRepaintForTesting())
GiveItSomeTime();
}
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index cdc42a2d79f..c6ee3bdf7c2 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -549,8 +549,8 @@ IN_PROC_BROWSER_TEST_P(TouchSelectionControllerClientAuraSiteIsolationTest,
ui::TouchSelectionControllerTestApi selection_controller_test_api(
selection_controller);
- scoped_refptr<UpdateResizeParamsMessageFilter> filter =
- new UpdateResizeParamsMessageFilter();
+ scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter =
+ new SynchronizeVisualPropertiesMessageFilter();
root->current_frame_host()->GetProcess()->AddFilter(filter.get());
// Find the location of some text to select.
diff --git a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
index dac3af2bc7c..45d712ff6c1 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
+++ b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc
@@ -7,46 +7,18 @@
namespace content {
TouchpadTapSuppressionController::TouchpadTapSuppressionController(
- TouchpadTapSuppressionControllerClient* client,
const TapSuppressionController::Config& config)
- : client_(client), controller_(this, config) {
-}
+ : TapSuppressionController(config) {}
TouchpadTapSuppressionController::~TouchpadTapSuppressionController() {}
-void TouchpadTapSuppressionController::GestureFlingCancel() {
- controller_.GestureFlingCancel();
-}
-
-void TouchpadTapSuppressionController::GestureFlingCancelAck(bool processed) {
- controller_.GestureFlingCancelAck(processed);
-}
-
-bool TouchpadTapSuppressionController::ShouldDeferMouseDown(
+bool TouchpadTapSuppressionController::ShouldSuppressMouseDown(
const MouseEventWithLatencyInfo& event) {
- bool should_defer = controller_.ShouldDeferTapDown();
- if (should_defer)
- stashed_mouse_down_ = event;
- return should_defer;
+ return ShouldSuppressTapDown();
}
bool TouchpadTapSuppressionController::ShouldSuppressMouseUp() {
- return controller_.ShouldSuppressTapEnd();
-}
-
-void TouchpadTapSuppressionController::DropStashedTapDown() {
-}
-
-void TouchpadTapSuppressionController::ForwardStashedGestureEvents() {
- // Mouse downs are not handled by gesture event filter; so, they are
- // immediately forwarded to the renderer.
- client_->SendMouseEventImmediately(stashed_mouse_down_);
-}
-
-void TouchpadTapSuppressionController::ForwardStashedTapDown() {
- // Mouse downs are not handled by gesture event filter; so, they are
- // immediately forwarded to the renderer.
- client_->SendMouseEventImmediately(stashed_mouse_down_);
+ return ShouldSuppressTapEnd();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
index cbacd339366..66e00c45fc0 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
@@ -8,42 +8,23 @@
#include "base/macros.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/input/tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/web_input_event.h"
namespace content {
-class TapSuppressionController;
-
-class CONTENT_EXPORT TouchpadTapSuppressionControllerClient {
- public:
- virtual ~TouchpadTapSuppressionControllerClient() {}
- virtual void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& event) = 0;
-};
-
// Controls the suppression of touchpad taps immediately following the dispatch
// of a GestureFlingCancel event.
-class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
+class TouchpadTapSuppressionController : public TapSuppressionController {
public:
// The |client| must outlive the TouchpadTapSupressionController.
TouchpadTapSuppressionController(
- TouchpadTapSuppressionControllerClient* client,
const TapSuppressionController::Config& config);
~TouchpadTapSuppressionController() override;
- // Should be called on arrival of GestureFlingCancel events.
- void GestureFlingCancel();
-
- // Should be called on arrival of ACK for a GestureFlingCancel event.
- // |processed| is true if the GestureFlingCancel successfully stopped a fling.
- void GestureFlingCancelAck(bool processed);
-
// Should be called on arrival of MouseDown events. Returns true if the caller
- // should stop normal handling of the MouseDown. In this case, the caller is
- // responsible for saving the event for later use, if needed.
- bool ShouldDeferMouseDown(const MouseEventWithLatencyInfo& event);
+ // should stop normal handling of the MouseDown.
+ bool ShouldSuppressMouseDown(const MouseEventWithLatencyInfo& event);
// Should be called on arrival of MouseUp events. Returns true if the caller
// should stop normal handling of the MouseUp.
@@ -52,17 +33,6 @@ class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
private:
friend class MockRenderWidgetHost;
- // TapSuppressionControllerClient implementation.
- void DropStashedTapDown() override;
- void ForwardStashedGestureEvents() override;
- void ForwardStashedTapDown() override;
-
- TouchpadTapSuppressionControllerClient* client_;
- MouseEventWithLatencyInfo stashed_mouse_down_;
-
- // The core controller of tap suppression.
- TapSuppressionController controller_;
-
DISALLOW_COPY_AND_ASSIGN(TouchpadTapSuppressionController);
};
diff --git a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
index 58801cc276c..2372fb34aa7 100644
--- a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
+++ b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
@@ -13,60 +13,26 @@ using blink::WebInputEvent;
namespace content {
TouchscreenTapSuppressionController::TouchscreenTapSuppressionController(
- GestureEventQueue* geq,
const TapSuppressionController::Config& config)
- : gesture_event_queue_(geq),
- forward_next_tap_cancel_(false),
- controller_(this, config) {}
+ : TapSuppressionController(config) {}
TouchscreenTapSuppressionController::~TouchscreenTapSuppressionController() {}
-void TouchscreenTapSuppressionController::GestureFlingCancel() {
- controller_.GestureFlingCancel();
-}
-
-void TouchscreenTapSuppressionController::GestureFlingCancelAck(
- bool processed) {
- controller_.GestureFlingCancelAck(processed);
-}
-
bool TouchscreenTapSuppressionController::FilterTapEvent(
const GestureEventWithLatencyInfo& event) {
switch (event.event.GetType()) {
case WebInputEvent::kGestureTapDown:
- forward_next_tap_cancel_ = false;
- if (!controller_.ShouldDeferTapDown())
- return false;
- stashed_tap_down_.reset(new GestureEventWithLatencyInfo(event));
- return true;
+ return ShouldSuppressTapDown();
case WebInputEvent::kGestureShowPress:
- if (!stashed_tap_down_)
- return false;
- stashed_show_press_.reset(new GestureEventWithLatencyInfo(event));
- return true;
-
case WebInputEvent::kGestureLongPress:
- // It is possible that a GestureLongPress arrives after tapDownTimer
- // expiration, in this case it should still get filtered if the
- // controller suppresses the tap end events.
- if (!stashed_tap_down_)
- return controller_.ShouldSuppressTapEnd();
-
- stashed_long_press_.reset(new GestureEventWithLatencyInfo(event));
- return true;
-
case WebInputEvent::kGestureTapUnconfirmed:
- return !!stashed_tap_down_;
-
case WebInputEvent::kGestureTapCancel:
- return !forward_next_tap_cancel_ && controller_.ShouldSuppressTapEnd();
-
case WebInputEvent::kGestureTap:
case WebInputEvent::kGestureDoubleTap:
case WebInputEvent::kGestureLongTap:
case WebInputEvent::kGestureTwoFingerTap:
- return controller_.ShouldSuppressTapEnd();
+ return ShouldSuppressTapEnd();
default:
break;
@@ -74,31 +40,4 @@ bool TouchscreenTapSuppressionController::FilterTapEvent(
return false;
}
-void TouchscreenTapSuppressionController::DropStashedTapDown() {
- stashed_tap_down_.reset();
- stashed_show_press_.reset();
- stashed_long_press_.reset();
-}
-
-void TouchscreenTapSuppressionController::ForwardStashedGestureEvents() {
- DCHECK(stashed_tap_down_);
- ScopedGestureEvent tap_down = std::move(stashed_tap_down_);
- ScopedGestureEvent show_press = std::move(stashed_show_press_);
- ScopedGestureEvent long_press = std::move(stashed_long_press_);
- gesture_event_queue_->ForwardGestureEvent(*tap_down);
- if (show_press)
- gesture_event_queue_->ForwardGestureEvent(*show_press);
- if (long_press)
- gesture_event_queue_->ForwardGestureEvent(*long_press);
-}
-
-void TouchscreenTapSuppressionController::ForwardStashedTapDown() {
- DCHECK(stashed_tap_down_);
- ScopedGestureEvent tap_down = std::move(stashed_tap_down_);
- gesture_event_queue_->ForwardGestureEvent(*tap_down);
- stashed_show_press_.reset();
- stashed_long_press_.reset();
- forward_next_tap_cancel_ = true;
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
index 64f72a0d7a5..c7845e2fd6f 100644
--- a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
@@ -10,53 +10,22 @@
#include "base/macros.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/input/tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
namespace content {
-class GestureEventQueue;
-
// Controls the suppression of touchscreen taps immediately following the
// dispatch of a GestureFlingCancel event.
-class TouchscreenTapSuppressionController
- : public TapSuppressionControllerClient {
+class TouchscreenTapSuppressionController : public TapSuppressionController {
public:
TouchscreenTapSuppressionController(
- GestureEventQueue* geq,
const TapSuppressionController::Config& config);
~TouchscreenTapSuppressionController() override;
- // Should be called on arrival of GestureFlingCancel events.
- void GestureFlingCancel();
-
- // Should be called on arrival of ACK for a GestureFlingCancel event.
- // |processed| is true if the GestureFlingCancel successfully stopped a fling.
- void GestureFlingCancelAck(bool processed);
-
// Should be called on arrival of any tap-related events. Returns true if the
// caller should stop normal handling of the gesture.
bool FilterTapEvent(const GestureEventWithLatencyInfo& event);
private:
- // TapSuppressionControllerClient implementation.
- void DropStashedTapDown() override;
- void ForwardStashedGestureEvents() override;
- void ForwardStashedTapDown() override;
-
- GestureEventQueue* gesture_event_queue_;
-
- typedef std::unique_ptr<GestureEventWithLatencyInfo> ScopedGestureEvent;
- ScopedGestureEvent stashed_tap_down_;
- ScopedGestureEvent stashed_show_press_;
- ScopedGestureEvent stashed_long_press_;
-
- // This is true when the stashed GestureTapDown event gets forwarded. The
- // controller should forward the next GestureTapCancel as well to maintain a
- // valid input stream.
- bool forward_next_tap_cancel_;
-
- // The core controller of tap suppression.
- TapSuppressionController controller_;
DISALLOW_COPY_AND_ASSIGN(TouchscreenTapSuppressionController);
};
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
index 349b3f3d6ca..5a0fe4d5439 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc
@@ -7,6 +7,7 @@
#include <android/input.h>
#include "base/logging.h"
+#include "base/time/time.h"
#include "ui/events/android/key_event_utils.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
@@ -78,7 +79,7 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(
const base::android::JavaRef<jobject>& android_key_event,
WebInputEvent::Type type,
int modifiers,
- double time_sec,
+ base::TimeTicks time,
int keycode,
int scancode,
int unicode_character,
@@ -90,8 +91,7 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(
dom_code = ui::KeycodeConverter::NativeKeycodeToDomCode(scancode);
WebKeyboardEvent result(
- type, modifiers | ui::DomCodeToWebInputEventModifiers(dom_code),
- time_sec);
+ type, modifiers | ui::DomCodeToWebInputEventModifiers(dom_code), time);
result.windows_key_code = ui::LocatedToNonLocatedKeyboardCode(
ui::KeyboardCodeFromAndroidKeyCode(keycode));
result.native_key_code = keycode;
@@ -118,9 +118,8 @@ WebMouseEvent WebMouseEventBuilder::Build(
int action_button) {
DCHECK(WebInputEvent::IsMouseEventType(type));
int modifiers = motion_event.GetFlags();
- WebMouseEvent result(
- type, ui::EventFlagsToWebEventModifiers(modifiers),
- ui::EventTimeStampToSeconds(motion_event.GetEventTime()));
+ WebMouseEvent result(type, ui::EventFlagsToWebEventModifiers(modifiers),
+ motion_event.GetEventTime());
result.SetPositionInWidget(motion_event.GetX(0), motion_event.GetY(0));
result.SetPositionInScreen(motion_event.GetRawX(0), motion_event.GetRawY(0));
@@ -153,7 +152,7 @@ WebMouseWheelEvent WebMouseWheelEventBuilder::Build(
const ui::MotionEventAndroid& motion_event) {
WebMouseWheelEvent result(WebInputEvent::kMouseWheel,
WebInputEvent::kNoModifiers,
- motion_event.time_sec());
+ motion_event.GetEventTime());
result.SetPositionInWidget(motion_event.GetX(0), motion_event.GetY(0));
result.SetPositionInScreen(motion_event.GetRawX(0), motion_event.GetRawY(0));
result.button = WebMouseEvent::Button::kNoButton;
@@ -167,13 +166,12 @@ WebMouseWheelEvent WebMouseWheelEventBuilder::Build(
}
WebGestureEvent WebGestureEventBuilder::Build(WebInputEvent::Type type,
- double time_sec,
+ base::TimeTicks time,
float x,
float y) {
DCHECK(WebInputEvent::IsGestureEventType(type));
- WebGestureEvent result(type, WebInputEvent::kNoModifiers, time_sec,
+ WebGestureEvent result(type, WebInputEvent::kNoModifiers, time,
blink::kWebGestureDeviceTouchscreen);
-
result.SetPositionInWidget(gfx::PointF(x, y));
return result;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
index 9994384e284..78d2454a62f 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
@@ -8,6 +8,7 @@
#include <jni.h>
#include "base/android/scoped_java_ref.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/blink/public/platform/web_input_event.h"
@@ -38,7 +39,7 @@ class CONTENT_EXPORT WebKeyboardEventBuilder {
const base::android::JavaRef<jobject>& android_key_event,
blink::WebInputEvent::Type type,
int modifiers,
- double time_sec,
+ base::TimeTicks time,
int keycode,
int scancode,
int unicode_character,
@@ -48,7 +49,7 @@ class CONTENT_EXPORT WebKeyboardEventBuilder {
class WebGestureEventBuilder {
public:
static blink::WebGestureEvent Build(blink::WebInputEvent::Type type,
- double time_sec,
+ base::TimeTicks time,
float x,
float y);
};
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
index 387ed8237d3..9bf0d0f15f8 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
@@ -37,8 +37,9 @@ WebKeyboardEvent CreateFakeWebKeyboardEvent(JNIEnv* env,
ui::events::android::CreateKeyEvent(env, 0, key_code);
WebKeyboardEvent web_event = content::WebKeyboardEventBuilder::Build(
- env, keydown_event, WebKeyboardEvent::kKeyDown, web_modifier, 0, key_code,
- 0, unicode_character, false);
+ env, keydown_event, WebKeyboardEvent::kKeyDown, web_modifier,
+ blink::WebInputEvent::GetStaticTimeStampForTests(), key_code, 0,
+ unicode_character, false);
return web_event;
}
@@ -161,7 +162,8 @@ TEST(WebInputEventBuilderAndroidTest, LastChannelKey) {
// Synthetic key event should produce DomKey::UNIDENTIFIED.
TEST(WebInputEventBuilderAndroidTest, DomKeySyntheticEvent) {
WebKeyboardEvent web_event = content::WebKeyboardEventBuilder::Build(
- nullptr, nullptr, WebKeyboardEvent::kKeyDown, 0, 0, kCompositionKeyCode,
+ nullptr, nullptr, WebKeyboardEvent::kKeyDown, 0,
+ blink::WebInputEvent::GetStaticTimeStampForTests(), kCompositionKeyCode,
0, 0, false);
EXPECT_EQ(kCompositionKeyCode, web_event.native_key_code);
EXPECT_EQ(ui::KeyboardCode::VKEY_UNKNOWN, web_event.windows_key_code);
@@ -197,9 +199,9 @@ TEST(WebInputEventBuilderAndroidTest, CutCopyPasteKey) {
}
TEST(WebInputEventBuilderAndroidTest, WebMouseEventCoordinates) {
- const int event_time_ms = 5;
- base::TimeTicks event_time =
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(event_time_ms);
+ constexpr int kEventTimeMs = 5;
+ const base::TimeTicks event_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(kEventTimeMs);
ui::test::ScopedEventTestTickClock clock;
clock.SetNowTicks(event_time);
@@ -212,7 +214,7 @@ TEST(WebInputEventBuilderAndroidTest, WebMouseEventCoordinates) {
const float kPixToDip = 0.5f;
ui::MotionEventAndroid motion_event(
- AttachCurrentThread(), nullptr, kPixToDip, 0.f, 0.f, 0.f, event_time_ms,
+ AttachCurrentThread(), nullptr, kPixToDip, 0.f, 0.f, 0.f, kEventTimeMs,
AMOTION_EVENT_ACTION_DOWN, 1, 0, -1, 0, 1, AMETA_ALT_ON, raw_offset_x,
raw_offset_y, false, &p0, nullptr);
@@ -226,7 +228,7 @@ TEST(WebInputEventBuilderAndroidTest, WebMouseEventCoordinates) {
EXPECT_EQ(web_event.PositionInScreen().y,
(p0.pos_y_pixels + raw_offset_y) * kPixToDip);
EXPECT_EQ(web_event.button, blink::WebPointerProperties::Button::kLeft);
- EXPECT_EQ(web_event.TimeStampSeconds(), event_time_ms * 0.001);
+ EXPECT_EQ(web_event.TimeStamp(), event_time);
}
// TODO(crbug.com/781404): Add more tests for WebMouseEventBuilder
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
index db697391cf6..f2f2b661322 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
@@ -37,8 +37,10 @@
#include "base/mac/sdk_forward_declarations.h"
#include "base/strings/string_util.h"
+#include "base/time/time.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#import "ui/events/cocoa/cocoa_event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
@@ -217,10 +219,10 @@ blink::WebKeyboardEvent WebKeyboardEventBuilder::Build(NSEvent* event) {
if (([event type] != NSFlagsChanged) && [event isARepeat])
modifiers |= blink::WebInputEvent::kIsAutoRepeat;
- blink::WebKeyboardEvent result(ui::IsKeyUpEvent(event)
- ? blink::WebInputEvent::kKeyUp
- : blink::WebInputEvent::kRawKeyDown,
- modifiers, [event timestamp]);
+ blink::WebKeyboardEvent result(
+ ui::IsKeyUpEvent(event) ? blink::WebInputEvent::kKeyUp
+ : blink::WebInputEvent::kRawKeyDown,
+ modifiers, ui::EventTimeStampFromSeconds([event timestamp]));
result.windows_key_code =
ui::LocatedToNonLocatedKeyboardCode(ui::KeyboardCodeFromNSEvent(event));
result.native_key_code = [event keyCode];
@@ -330,7 +332,8 @@ blink::WebMouseEvent WebMouseEventBuilder::Build(
// NSMouseExited and NSMouseEntered events don't have deviceID.
// Therefore pen exit and enter events can't get correct id.
blink::WebMouseEvent result(event_type, ModifiersFromEvent(event),
- [event timestamp], 0);
+ ui::EventTimeStampFromSeconds([event timestamp]),
+ 0);
result.click_count = click_count;
result.button = button;
SetWebEventLocationFromEventInView(&result, event, view);
@@ -372,9 +375,9 @@ blink::WebMouseEvent WebMouseEventBuilder::Build(
blink::WebMouseWheelEvent WebMouseWheelEventBuilder::Build(
NSEvent* event,
NSView* view) {
- blink::WebMouseWheelEvent result(blink::WebInputEvent::kMouseWheel,
- ModifiersFromEvent(event),
- [event timestamp]);
+ blink::WebMouseWheelEvent result(
+ blink::WebInputEvent::kMouseWheel, ModifiersFromEvent(event),
+ ui::EventTimeStampFromSeconds([event timestamp]));
result.button = blink::WebMouseEvent::Button::kNoButton;
SetWebEventLocationFromEventInView(&result, event, view);
@@ -527,7 +530,7 @@ blink::WebGestureEvent WebGestureEventBuilder::Build(NSEvent* event,
result.SetPositionInScreen(temp.PositionInScreen());
result.SetModifiers(ModifiersFromEvent(event));
- result.SetTimeStampSeconds([event timestamp]);
+ result.SetTimeStamp(ui::EventTimeStampFromSeconds([event timestamp]));
result.SetSourceDevice(blink::kWebGestureDeviceTouchpad);
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
index 33429778f0f..48b6e1e8d3f 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
@@ -46,7 +46,7 @@ TEST(WebInputEventUtilTest, MotionEventConversion) {
WebTouchEvent expected_event(
WebInputEvent::kTouchStart,
WebInputEvent::kShiftKey | WebInputEvent::kAltKey,
- (event.GetEventTime() - base::TimeTicks()).InSecondsF());
+ event.GetEventTime());
expected_event.touches_length = 1;
WebTouchPoint expected_pointer;
expected_pointer.id = pointer.id;
@@ -107,8 +107,7 @@ TEST(WebInputEventUtilTest, ScrollUpdateConversion) {
ui::CreateWebGestureEventFromGestureEventData(event);
EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, web_event.GetType());
EXPECT_EQ(0, web_event.GetModifiers());
- EXPECT_EQ((timestamp - base::TimeTicks()).InSecondsF(),
- web_event.TimeStampSeconds());
+ EXPECT_EQ(timestamp, web_event.TimeStamp());
EXPECT_EQ(pos.x(), web_event.PositionInWidget().x);
EXPECT_EQ(pos.y(), web_event.PositionInWidget().y);
EXPECT_EQ(raw_pos.x(), web_event.PositionInScreen().x);
diff --git a/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc b/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
index 97b99a35fff..0aed4733809 100644
--- a/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
@@ -37,7 +37,7 @@ const char kWheelEventLatchingDataURL[] =
"body {"
" height: 10000px;"
"}"
- "#scrollableDiv {"
+ "%23scrollableDiv {"
" position: absolute;"
" left: 50px;"
" top: 100px;"
@@ -46,7 +46,7 @@ const char kWheelEventLatchingDataURL[] =
" overflow: scroll;"
" background: red;"
"}"
- "#nestedDiv {"
+ "%23nestedDiv {"
" width: 200px;"
" height: 8000px;"
" opacity: 0;"
@@ -118,7 +118,7 @@ class WheelScrollLatchingBrowserTest : public ContentBrowserTest {
host->GetView()->SetSize(gfx::Size(600, 600));
// The page is loaded in the renderer, wait for a new frame to arrive.
- while (!host->ScheduleComposite())
+ while (!host->RequestRepaintForTesting())
GiveItSomeTime();
}
int ExecuteScriptAndExtractInt(const std::string& script) {
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
index e09ded934c1..30b95a5dcd0 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -135,6 +135,8 @@ void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) {
::SetWindowPos(hwnd(), NULL, bounds_in_pixel.x(), bounds_in_pixel.y(),
bounds_in_pixel.width(), bounds_in_pixel.height(),
SWP_NOREDRAW);
+ if (direct_manipulation_helper_)
+ direct_manipulation_helper_->SetSize(bounds_in_pixel.size());
}
void LegacyRenderWidgetHostHWND::MoveCaretTo(const gfx::Rect& bounds) {
diff --git a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc
index 176150080e5..d01a24bd4bf 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.cc
@@ -265,10 +265,17 @@ void AudioInputDelegateImpl::OnSetVolume(double volume) {
audio_log_->OnSetVolume(volume);
}
+void AudioInputDelegateImpl::OnSetOutputDeviceForAec(
+ const std::string& raw_output_device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ controller_->SetOutputDeviceForAec(raw_output_device_id);
+ audio_log_->OnLogMessage("SetOutputDeviceForAec");
+}
+
void AudioInputDelegateImpl::SendCreatedNotification(bool initially_muted) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(foreign_socket_);
- subscriber_->OnStreamCreated(stream_id_, writer_->shared_memory(),
+ subscriber_->OnStreamCreated(stream_id_, writer_->TakeSharedMemoryRegion(),
std::move(foreign_socket_), initially_muted);
}
diff --git a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.h b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.h
index 76812c8dda7..2409ee983d5 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl.h
@@ -57,6 +57,8 @@ class CONTENT_EXPORT AudioInputDelegateImpl : public media::AudioInputDelegate {
int GetStreamId() override;
void OnRecordStream() override;
void OnSetVolume(double volume) override;
+ void OnSetOutputDeviceForAec(
+ const std::string& raw_output_device_id) override;
private:
AudioInputDelegateImpl(
diff --git a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc
index f1a04982a98..08c0d02dc82 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_delegate_impl_unittest.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
@@ -94,7 +93,7 @@ media::AudioInputStream* MakeInputStreamCallback(
class MockEventHandler : public media::AudioInputDelegate::EventHandler {
public:
void OnStreamCreated(int stream_id,
- const base::SharedMemory*,
+ base::ReadOnlySharedMemoryRegion,
std::unique_ptr<base::CancelableSyncSocket>,
bool initially_muted) override {
MockOnStreamCreated(stream_id, initially_muted);
@@ -109,10 +108,10 @@ class MockUserInputMonitor : public media::UserInputMonitor {
public:
MockUserInputMonitor() {}
- size_t GetKeyPressCount() const { return 0; }
+ uint32_t GetKeyPressCount() const override { return 0; }
- MOCK_METHOD0(StartKeyboardMonitoring, void());
- MOCK_METHOD0(StopKeyboardMonitoring, void());
+ MOCK_METHOD0(EnableKeyPressMonitoring, void());
+ MOCK_METHOD0(DisableKeyPressMonitoring, void());
};
class MockAudioInputStream : public media::AudioInputStream {
@@ -130,6 +129,7 @@ class MockAudioInputStream : public media::AudioInputStream {
MOCK_METHOD1(SetAutomaticGainControl, bool(bool));
MOCK_METHOD0(GetAutomaticGainControl, bool());
MOCK_METHOD0(IsMuted, bool());
+ MOCK_METHOD1(SetOutputDeviceForAec, void(const std::string&));
};
class MockMediaStreamProviderListener : public MediaStreamProviderListener {
@@ -156,7 +156,7 @@ class AudioInputDelegateTest : public testing::Test {
base::BindRepeating(&ExpectNoOutputStreamCreation));
}
- ~AudioInputDelegateTest() {
+ ~AudioInputDelegateTest() override {
audio_manager_.Shutdown();
// MediaStreamManager expects to outlive the IO thread.
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
index b9d9d305ad7..b22666bf9af 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -3,10 +3,10 @@
// found in the LICENSE file.
//
// AudioInputDeviceManager manages the audio input devices. In particular it
-// communicates with MediaStreamManager and AudioInputRendererHost on the
-// browser IO thread, handles queries like
+// communicates with MediaStreamManager and RenderFrameAudioInputStreamFactory
+// on the browser IO thread, handles queries like
// enumerate/open/close/GetOpenedDeviceById from MediaStreamManager and
-// GetOpenedDeviceById from AudioInputRendererHost.
+// GetOpenedDeviceById from RenderFrameAudioInputStreamFactory.
// The work for enumerate/open/close is handled asynchronously on Media Stream
// device thread, while GetOpenedDeviceById is synchronous on the IO thread.
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index ffd6d507f32..ffac149e26c 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -37,7 +37,7 @@ class MockAudioInputDeviceManagerListener
: public MediaStreamProviderListener {
public:
MockAudioInputDeviceManagerListener() {}
- virtual ~MockAudioInputDeviceManagerListener() {}
+ ~MockAudioInputDeviceManagerListener() override {}
MOCK_METHOD2(Opened, void(MediaStreamType, const int));
MOCK_METHOD2(Closed, void(MediaStreamType, const int));
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
deleted file mode 100644
index 6d613a96ad1..00000000000
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/memory/shared_memory.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/sync_socket.h"
-#include "build/build_config.h"
-#include "content/browser/bad_message.h"
-#include "content/browser/media/media_internals.h"
-#include "content/browser/renderer_host/media/audio_input_delegate_impl.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/public/browser/browser_thread.h"
-#include "media/audio/audio_manager.h"
-
-namespace content {
-
-namespace {
-
-void LogMessage(int stream_id, const std::string& msg, bool add_prefix) {
- std::ostringstream oss;
- oss << "[stream_id=" << stream_id << "] ";
- if (add_prefix)
- oss << "AIRH::";
- oss << msg;
- const std::string message = oss.str();
- content::MediaStreamManager::SendMessageToNativeLog(message);
- DVLOG(1) << message;
-}
-
-} // namespace
-
-AudioInputRendererHost::AudioInputRendererHost(
- int render_process_id,
- media::AudioManager* audio_manager,
- MediaStreamManager* media_stream_manager,
- AudioMirroringManager* audio_mirroring_manager,
- media::UserInputMonitor* user_input_monitor)
- : BrowserMessageFilter(AudioMsgStart),
- render_process_id_(render_process_id),
- audio_manager_(audio_manager),
- media_stream_manager_(media_stream_manager),
- audio_mirroring_manager_(audio_mirroring_manager),
- user_input_monitor_(user_input_monitor) {}
-
-AudioInputRendererHost::~AudioInputRendererHost() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(delegates_.empty());
-}
-
-void AudioInputRendererHost::OnChannelClosing() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Since the IPC sender is gone, close all audio streams.
- delegates_.clear();
-}
-
-void AudioInputRendererHost::OnDestruct() const {
- BrowserThread::DeleteOnIOThread::Destruct(this);
-}
-
-void AudioInputRendererHost::OnStreamCreated(
- int stream_id,
- const base::SharedMemory* shared_memory,
- std::unique_ptr<base::CancelableSyncSocket> socket,
- bool initially_muted) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(PeerHandle());
-
- // Once the audio stream is created then complete the creation process by
- // mapping shared memory and sharing with the renderer process.
- base::SharedMemoryHandle foreign_memory_handle =
- shared_memory->handle().Duplicate();
- if (!foreign_memory_handle.IsValid()) {
- // If we failed to map and share the shared memory then close the audio
- // stream and send an error message.
- DeleteDelegateOnError(stream_id, MEMORY_SHARING_FAILED);
- return;
- }
-
- base::CancelableSyncSocket::TransitDescriptor socket_transit_descriptor;
-
- // If we failed to prepare the sync socket for the renderer then we fail
- // the construction of audio input stream.
- if (!socket->PrepareTransitDescriptor(PeerHandle(),
- &socket_transit_descriptor)) {
- foreign_memory_handle.Close();
- DeleteDelegateOnError(stream_id, SYNC_SOCKET_ERROR);
- return;
- }
-
- LogMessage(stream_id,
- base::StringPrintf("DoCompleteCreation: IPC channel and stream "
- "are now open (initially%s muted)",
- initially_muted ? "" : " not"),
- true);
-
- Send(new AudioInputMsg_NotifyStreamCreated(stream_id, foreign_memory_handle,
- socket_transit_descriptor,
- initially_muted));
-}
-
-void AudioInputRendererHost::OnStreamError(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DeleteDelegateOnError(stream_id, AUDIO_INPUT_CONTROLLER_ERROR);
-}
-
-void AudioInputRendererHost::OnMuted(int stream_id, bool is_muted) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- Send(new AudioInputMsg_NotifyStreamMuted(stream_id, is_muted));
-}
-
-bool AudioInputRendererHost::OnMessageReceived(const IPC::Message& message) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(AudioInputRendererHost, message)
- IPC_MESSAGE_HANDLER(AudioInputHostMsg_CreateStream, OnCreateStream)
- IPC_MESSAGE_HANDLER(AudioInputHostMsg_RecordStream, OnRecordStream)
- IPC_MESSAGE_HANDLER(AudioInputHostMsg_CloseStream, OnCloseStream)
- IPC_MESSAGE_HANDLER(AudioInputHostMsg_SetVolume, OnSetVolume)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void AudioInputRendererHost::OnCreateStream(
- int stream_id,
- int render_frame_id,
- int session_id,
- const AudioInputHostMsg_CreateStream_Config& config) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (config.params.IsBitstreamFormat()) {
- // Bitstream formats are only supported for output.
- bad_message::ReceivedBadMessage(this,
- bad_message::AIRH_UNEXPECTED_BITSTREAM);
- return;
- }
-
-#if defined(OS_CHROMEOS)
- if (config.params.channel_layout() ==
- media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
- media_stream_manager_->audio_input_device_manager()
- ->RegisterKeyboardMicStream(
- base::BindOnce(&AudioInputRendererHost::DoCreateStream, this,
- stream_id, render_frame_id, session_id, config));
- return;
- }
-#endif
- DoCreateStream(stream_id, render_frame_id, session_id, config,
- AudioInputDeviceManager::KeyboardMicRegistration());
-}
-
-void AudioInputRendererHost::DoCreateStream(
- int stream_id,
- int render_frame_id,
- int session_id,
- const AudioInputHostMsg_CreateStream_Config& config,
- AudioInputDeviceManager::KeyboardMicRegistration
- keyboard_mic_registration) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- DCHECK_GT(render_frame_id, 0);
-
- // media::AudioParameters is validated in the deserializer.
- if (LookupById(stream_id)) {
- SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS);
- return;
- }
-
- media::mojom::AudioLogPtr audio_log_ptr =
- MediaInternals::GetInstance()->CreateMojoAudioLog(
- media::AudioLogFactory::AUDIO_INPUT_CONTROLLER, stream_id,
- render_process_id_, render_frame_id);
-
- std::unique_ptr<media::AudioInputDelegate> delegate =
- AudioInputDelegateImpl::Create(
- audio_manager_, audio_mirroring_manager_, user_input_monitor_,
- render_process_id_, render_frame_id,
- media_stream_manager_->audio_input_device_manager(),
- std::move(audio_log_ptr), std::move(keyboard_mic_registration),
- config.shared_memory_count, stream_id, session_id,
- config.automatic_gain_control, config.params, this);
-
- if (!delegate) {
- // Error was logged by AudioInputDelegateImpl::Create.
- Send(new AudioInputMsg_NotifyStreamError(stream_id));
-
- return;
- }
-
- delegates_.emplace(stream_id, std::move(delegate));
-}
-
-void AudioInputRendererHost::OnRecordStream(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- LogMessage(stream_id, "OnRecordStream", true);
-
- media::AudioInputDelegate* delegate = LookupById(stream_id);
- if (!delegate) {
- SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY);
- return;
- }
-
- delegate->OnRecordStream();
-}
-
-void AudioInputRendererHost::OnCloseStream(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- LogMessage(stream_id, "OnCloseStream", true);
-
- delegates_.erase(stream_id);
-}
-
-void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (volume < 0 || volume > 1) {
- bad_message::ReceivedBadMessage(this,
- bad_message::AIRH_VOLUME_OUT_OF_RANGE);
- return;
- }
-
- media::AudioInputDelegate* delegate = LookupById(stream_id);
- if (!delegate) {
- SendErrorMessage(stream_id, INVALID_AUDIO_ENTRY);
- return;
- }
-
- delegate->OnSetVolume(volume);
-}
-
-void AudioInputRendererHost::SendErrorMessage(
- int stream_id, ErrorCode error_code) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::string err_msg =
- base::StringPrintf("SendErrorMessage(error_code=%d)", error_code);
- LogMessage(stream_id, err_msg, true);
-
- Send(new AudioInputMsg_NotifyStreamError(stream_id));
-}
-
-void AudioInputRendererHost::DeleteDelegateOnError(int stream_id,
- ErrorCode error_code) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- SendErrorMessage(stream_id, error_code);
- delegates_.erase(stream_id);
-}
-
-media::AudioInputDelegate* AudioInputRendererHost::LookupById(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- AudioInputDelegateMap::iterator i = delegates_.find(stream_id);
- if (i != delegates_.end())
- return i->second.get();
- return nullptr;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
deleted file mode 100644
index 72a0778deb4..00000000000
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// AudioInputRendererHost serves audio related requests from audio capturer
-// which lives inside the render process and provide access to audio hardware.
-//
-// Create stream sequence (AudioInputController = AIC):
-//
-// AudioInputHostMsg_CreateStream -> OnCreateStream -> AIC::CreateLowLatency ->
-// <- AudioInputMsg_NotifyStreamCreated <- DoCompleteCreation <- OnCreated <-
-//
-// Close stream sequence:
-//
-// AudioInputHostMsg_CloseStream -> OnCloseStream -> AIC::Close ->
-//
-// This class is owned by RenderProcessHostImpl and instantiated on UI
-// thread. All other operations and method calls happen on IO thread, so we
-// need to be extra careful about the lifetime of this object.
-//
-// To ensure low latency audio, a SyncSocket pair is used to signal buffer
-// readiness without having to route messages using the IO thread.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/common/media/audio_messages.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "media/audio/audio_input_delegate.h"
-
-namespace media {
-class AudioManager;
-class UserInputMonitor;
-}
-
-namespace content {
-class AudioMirroringManager;
-class MediaStreamManager;
-
-class CONTENT_EXPORT AudioInputRendererHost
- : public BrowserMessageFilter,
- public media::AudioInputDelegate::EventHandler {
- public:
- // Error codes to make native logging more clear. These error codes are added
- // to generic error strings to provide a higher degree of details.
- // Changing these values can lead to problems when matching native debug
- // logs with the actual cause of error.
- enum ErrorCode {
- // Note: usage of many of these codes have been replaced with textual log
- // messages.
-
- // An unspecified error occured. Not used.
- // UNKNOWN_ERROR = 0,
-
- // Failed to look up audio intry for the provided stream id.
- INVALID_AUDIO_ENTRY = 1,
-
- // A stream with the specified stream id already exists.
- STREAM_ALREADY_EXISTS = 2,
-
- // The page does not have permission to open the specified capture device.
- PERMISSION_DENIED = 3,
-
- // Failed to create shared memory.
- // Obsolete.
- // SHARED_MEMORY_CREATE_FAILED = 4
-
- // Failed to initialize the AudioInputSyncWriter instance.
- // Obsolete.
- // SYNC_WRITER_INIT_FAILED = 5,
-
- // Failed to create native audio input stream.
- // Obsolete.
- // STREAM_CREATE_ERROR = 6,
-
- // Failed to map and share the shared memory.
- MEMORY_SHARING_FAILED = 7,
-
- // Unable to prepare the foreign socket handle.
- SYNC_SOCKET_ERROR = 8,
-
- // This error message comes from the AudioInputController instance.
- AUDIO_INPUT_CONTROLLER_ERROR = 9,
- };
-
- // Called from UI thread from the owner of this object.
- // |user_input_monitor| is used for typing detection and can be null.
- AudioInputRendererHost(int render_process_id,
- media::AudioManager* audio_manager,
- MediaStreamManager* media_stream_manager,
- AudioMirroringManager* audio_mirroring_manager,
- media::UserInputMonitor* user_input_monitor);
-
- // BrowserMessageFilter implementation.
- void OnChannelClosing() override;
- void OnDestruct() const override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- // AudioInputDelegate::EventHandler implementation.
- void OnStreamCreated(int stream_id,
- const base::SharedMemory* shared_memory,
- std::unique_ptr<base::CancelableSyncSocket> socket,
- bool initially_muted) override;
- void OnStreamError(int stream_id) override;
- void OnMuted(int stream_id, bool is_muted) override;
-
- protected:
- ~AudioInputRendererHost() override;
-
- private:
- friend class BrowserThread;
- friend class base::DeleteHelper<AudioInputRendererHost>;
-
- // Holds the stream_id -> delegate mapping.
- using AudioInputDelegateMap =
- base::flat_map<int, std::unique_ptr<media::AudioInputDelegate>>;
-
- // Methods called on IO thread ----------------------------------------------
-
- // Audio related IPC message handlers.
-
- // For ChromeOS: Checks if the stream should contain keyboard mic, if so
- // registers to AudioInputDeviceManager. Then calls DoCreateStream.
- // For non-ChromeOS: Just calls DoCreateStream.
- void OnCreateStream(int stream_id,
- int render_frame_id,
- int session_id,
- const AudioInputHostMsg_CreateStream_Config& config);
-
- // Creates an audio input stream with the specified format whose data is
- // consumed by an entity in the RenderFrame referenced by |render_frame_id|.
- // |session_id| is used to identify the device that should be used for the
- // stream. Upon success/failure, the peer is notified via the
- // NotifyStreamCreated message.
- void DoCreateStream(
- int stream_id,
- int render_frame_id,
- int session_id,
- const AudioInputHostMsg_CreateStream_Config& config,
- AudioInputDeviceManager::KeyboardMicRegistration registration);
-
- // Record the audio input stream referenced by |stream_id|.
- void OnRecordStream(int stream_id);
-
- // Close the audio stream referenced by |stream_id|.
- void OnCloseStream(int stream_id);
-
- // Set the volume of the audio stream referenced by |stream_id|.
- void OnSetVolume(int stream_id, double volume);
-
- // Complete the process of creating an audio input stream. This will set up
- // the shared memory or shared socket in low latency mode and send the
- // NotifyStreamCreated message to the peer.
- void DoCompleteCreation(int stream_id, bool initially_muted);
-
- // Handle error coming from audio stream.
- void DoHandleError(int stream_id);
-
- // Log audio level of captured audio stream.
- void DoLog(int stream_id, const std::string& message);
-
- // Notify renderer of a change to a stream's muted state.
- void DoNotifyMutedState(int stream_id, bool is_muted);
-
- // Send an error message to the renderer.
- void SendErrorMessage(int stream_id, ErrorCode error_code);
-
- void DeleteDelegateOnError(int stream_id, ErrorCode error_code);
-
- // A helper method to look up a AudioInputDelegate identified by |stream_id|.
- // Returns null if not found.
- media::AudioInputDelegate* LookupById(int stream_id);
-
- // ID of the RenderProcessHost that owns this instance.
- const int render_process_id_;
-
- media::AudioManager* audio_manager_;
-
- // Used to access to AudioInputDeviceManager.
- MediaStreamManager* media_stream_manager_;
-
- AudioMirroringManager* audio_mirroring_manager_;
-
- // Raw pointer of the UserInputMonitor.
- media::UserInputMonitor* const user_input_monitor_;
-
- // A map of stream IDs to audio sources.
- AudioInputDelegateMap delegates_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
deleted file mode 100644
index edfdea31c8c..00000000000
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
+++ /dev/null
@@ -1,529 +0,0 @@
-// Copyright 2016 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/renderer_host/media/audio_input_renderer_host.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/bad_message.h"
-#include "content/browser/media/capture/audio_mirroring_manager.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "media/audio/audio_device_description.h"
-#include "media/audio/audio_input_controller.h"
-#include "media/audio/audio_system_impl.h"
-#include "media/audio/fake_audio_log_factory.h"
-#include "media/audio/fake_audio_manager.h"
-#include "media/audio/test_audio_thread.h"
-#include "media/base/media_switches.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-using ::media::AudioInputController;
-using ::testing::_;
-using ::testing::Assign;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::Mock;
-using ::testing::NotNull;
-using ::testing::SaveArg;
-using ::testing::StrictMock;
-
-namespace content {
-
-namespace {
-
-const int kStreamId = 100;
-const int kRenderProcessId = 42;
-const int kRenderFrameId = 31415;
-const int kSharedMemoryCount = 11;
-const double kNewVolume = 0.618;
-const char kSecurityOrigin[] = "http://localhost";
-
-url::Origin SecurityOrigin() {
- return url::Origin::Create(GURL(kSecurityOrigin));
-}
-
-AudioInputHostMsg_CreateStream_Config DefaultConfig() {
- AudioInputHostMsg_CreateStream_Config config;
- config.params = media::AudioParameters::UnavailableDeviceParams();
- config.automatic_gain_control = false;
- config.shared_memory_count = kSharedMemoryCount;
- return config;
-}
-
-class MockRenderer {
- public:
- MOCK_METHOD4(NotifyStreamCreated,
- void(int /*stream_id*/,
- base::SharedMemoryHandle /*handle*/,
- base::SyncSocket::TransitDescriptor /*socket_desriptor*/,
- bool initially_muted));
- MOCK_METHOD1(NotifyStreamError, void(int /*stream_id*/));
- MOCK_METHOD0(WasShutDown, void());
-};
-
-// This class overrides Send to intercept the messages that the
-// AudioInputRendererHost sends to the renderer. They are sent to
-// the provided MockRenderer instead.
-class AudioInputRendererHostWithInterception : public AudioInputRendererHost {
- public:
- AudioInputRendererHostWithInterception(
- int render_process_id,
- media::AudioManager* audio_manager,
- MediaStreamManager* media_stream_manager,
- AudioMirroringManager* audio_mirroring_manager,
- media::UserInputMonitor* user_input_monitor,
- MockRenderer* renderer)
- : AudioInputRendererHost(render_process_id,
- audio_manager,
- media_stream_manager,
- audio_mirroring_manager,
- user_input_monitor),
- renderer_(renderer) {
- set_peer_process_for_testing(base::Process::Current());
- }
-
- protected:
- ~AudioInputRendererHostWithInterception() override = default;
-
- private:
- bool Send(IPC::Message* message) override {
- bool handled = true;
-
- IPC_BEGIN_MESSAGE_MAP(AudioInputRendererHostWithInterception, *message)
- IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamCreated,
- NotifyRendererStreamCreated)
- IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamError,
- NotifyRendererStreamError)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- EXPECT_TRUE(handled);
- delete message;
- return true;
- }
-
- void ShutdownForBadMessage() override { renderer_->WasShutDown(); }
-
- void NotifyRendererStreamCreated(
- int stream_id,
- base::SharedMemoryHandle handle,
- base::SyncSocket::TransitDescriptor socket_descriptor,
- bool initially_muted) {
- // It's difficult to check that the sync socket and shared memory is
- // valid in the gmock macros, so we check them here.
- EXPECT_NE(base::SyncSocket::UnwrapHandle(socket_descriptor),
- base::SyncSocket::kInvalidHandle);
- size_t length = handle.GetSize();
- base::SharedMemory memory(handle, /*read_only*/ true);
- EXPECT_TRUE(memory.Map(length));
- renderer_->NotifyStreamCreated(stream_id, handle, socket_descriptor,
- initially_muted);
- EXPECT_TRUE(memory.Unmap());
- memory.Close();
- }
-
- void NotifyRendererStreamError(int stream_id) {
- renderer_->NotifyStreamError(stream_id);
- }
-
- MockRenderer* renderer_;
-};
-
-class MockAudioInputController : public AudioInputController {
- public:
- MockAudioInputController(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- AudioInputController::SyncWriter* writer,
- media::AudioManager* audio_manager,
- AudioInputController::EventHandler* event_handler,
- media::UserInputMonitor* user_input_monitor,
- const media::AudioParameters& params,
- StreamType type)
- : AudioInputController(std::move(task_runner),
- event_handler,
- writer,
- user_input_monitor,
- params,
- type) {
- GetTaskRunnerForTesting()->PostTask(
- FROM_HERE,
- base::BindOnce(&AudioInputController::EventHandler::OnCreated,
- base::Unretained(event_handler), false));
- }
-
- EventHandler* handler() { return GetHandlerForTesting(); }
-
- void Close(base::OnceClosure cl) override {
- DidClose();
- // Hop to audio manager thread before calling task, since this is the real
- // behavior.
- GetTaskRunnerForTesting()->PostTaskAndReply(
- FROM_HERE, base::BindOnce([]() {}), std::move(cl));
- }
-
- MOCK_METHOD0(Record, void());
- MOCK_METHOD1(SetVolume, void(double));
-
- MOCK_METHOD0(DidClose, void());
-
- // AudioInputCallback impl, irrelevant to us.
- MOCK_METHOD4(
- OnData,
- void(media::AudioInputStream*, const media::AudioBus*, uint32_t, double));
- MOCK_METHOD1(OnError, void(media::AudioInputStream*));
-
- protected:
- ~MockAudioInputController() override = default;
-};
-
-class MockControllerFactory : public AudioInputController::Factory {
- public:
- using MockController = StrictMock<MockAudioInputController>;
-
- MockControllerFactory() {
- AudioInputController::set_factory_for_testing(this);
- }
-
- ~MockControllerFactory() override {
- AudioInputController::set_factory_for_testing(nullptr);
- }
-
- // AudioInputController::Factory implementation:
- AudioInputController* Create(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- AudioInputController::SyncWriter* sync_writer,
- media::AudioManager* audio_manager,
- AudioInputController::EventHandler* event_handler,
- media::AudioParameters params,
- media::UserInputMonitor* user_input_monitor,
- AudioInputController::StreamType type) override {
- ControllerCreated();
- scoped_refptr<MockController> controller =
- new MockController(task_runner, sync_writer, audio_manager,
- event_handler, user_input_monitor, params, type);
- controller_list_.push_back(controller);
- return controller.get();
- }
-
- MockController* controller(size_t i) {
- EXPECT_GT(controller_list_.size(), i);
- return controller_list_[i].get();
- }
-
- MOCK_METHOD0(ControllerCreated, void());
-
- private:
- std::vector<scoped_refptr<MockController>> controller_list_;
-};
-
-} // namespace
-
-class AudioInputRendererHostTest : public testing::Test {
- public:
- AudioInputRendererHostTest() {
- base::CommandLine* flags = base::CommandLine::ForCurrentProcess();
- flags->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
- flags->AppendSwitch(switches::kUseFakeUIForMediaStream);
-
- audio_manager_ = std::make_unique<media::FakeAudioManager>(
- std::make_unique<media::TestAudioThread>(), &log_factory_);
- audio_system_ =
- std::make_unique<media::AudioSystemImpl>(audio_manager_.get());
- media_stream_manager_ = std::make_unique<MediaStreamManager>(
- audio_system_.get(), audio_manager_->GetTaskRunner());
- airh_ = new AudioInputRendererHostWithInterception(
- kRenderProcessId, media::AudioManager::Get(),
- media_stream_manager_.get(), AudioMirroringManager::GetInstance(),
- nullptr, &renderer_);
- }
-
- ~AudioInputRendererHostTest() override {
- airh_->OnChannelClosing();
- base::RunLoop().RunUntilIdle();
-
- audio_manager_->Shutdown();
- }
-
- protected:
- // Makes device |device_id| with name |name| available to open with the
- // session id returned.
- int Open(const std::string& device_id, const std::string& name) {
- int session_id = media_stream_manager_->audio_input_device_manager()->Open(
- MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, device_id, name));
- base::RunLoop().RunUntilIdle();
- return session_id;
- }
-
- std::string GetRawNondefaultId() {
- std::string id;
- MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
- devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
-
- media_stream_manager_->media_devices_manager()->EnumerateDevices(
- devices_to_enumerate,
- base::Bind(
- [](std::string* id, const MediaDeviceEnumeration& result) {
- // Index 0 is default, so use 1.
- CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT]
- .size() > 1)
- << "Expected to have a nondefault device.";
- *id = result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT][1]
- .device_id;
- },
- base::Unretained(&id)));
- base::RunLoop().RunUntilIdle();
- return id;
- }
-
- media::FakeAudioLogFactory log_factory_;
- StrictMock<MockControllerFactory> controller_factory_;
- std::unique_ptr<MediaStreamManager> media_stream_manager_;
- TestBrowserThreadBundle thread_bundle_;
- std::unique_ptr<media::AudioManager> audio_manager_;
- std::unique_ptr<media::AudioSystem> audio_system_;
- StrictMock<MockRenderer> renderer_;
- scoped_refptr<AudioInputRendererHost> airh_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHostTest);
-};
-
-// Checks that a controller is created and a reply is sent when creating a
-// stream.
-TEST_F(AudioInputRendererHostTest, CreateWithDefaultDevice) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
-
- base::RunLoop().RunUntilIdle();
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
-}
-
-// If authorization hasn't been granted, only reply with an error and do
-// nothing else.
-TEST_F(AudioInputRendererHostTest, CreateWithoutAuthorization_Error) {
- EXPECT_CALL(renderer_, NotifyStreamError(kStreamId));
-
- int session_id = 0;
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-}
-
-// Like CreateWithDefaultDevice but with a nondefault device.
-TEST_F(AudioInputRendererHostTest, CreateWithNonDefaultDevice) {
- int session_id = Open("Nondefault device", GetRawNondefaultId());
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
-
- base::RunLoop().RunUntilIdle();
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
-}
-
-// Checks that stream is started when calling record.
-TEST_F(AudioInputRendererHostTest, CreateRecordClose) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), Record());
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
-
- airh_->OnMessageReceived(AudioInputHostMsg_RecordStream(kStreamId));
- base::RunLoop().RunUntilIdle();
- airh_->OnMessageReceived(AudioInputHostMsg_CloseStream(kStreamId));
- base::RunLoop().RunUntilIdle();
-}
-
-// In addition to the above, also check that a SetVolume message is propagated
-// to the controller.
-TEST_F(AudioInputRendererHostTest, CreateSetVolumeRecordClose) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), SetVolume(kNewVolume));
- EXPECT_CALL(*controller_factory_.controller(0), Record());
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
-
- airh_->OnMessageReceived(AudioInputHostMsg_SetVolume(kStreamId, kNewVolume));
- airh_->OnMessageReceived(AudioInputHostMsg_RecordStream(kStreamId));
- airh_->OnMessageReceived(AudioInputHostMsg_CloseStream(kStreamId));
-
- base::RunLoop().RunUntilIdle();
-}
-
-// Check that a too large volume is treated like a bad message and doesn't
-// reach the controller.
-TEST_F(AudioInputRendererHostTest, SetVolumeTooLarge_BadMessage) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
- EXPECT_CALL(renderer_, WasShutDown());
-
- airh_->OnMessageReceived(AudioInputHostMsg_SetVolume(kStreamId, 5));
-
- base::RunLoop().RunUntilIdle();
-}
-
-// Like above.
-TEST_F(AudioInputRendererHostTest, SetVolumeNegative_BadMessage) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
- EXPECT_CALL(renderer_, WasShutDown());
-
- airh_->OnMessageReceived(AudioInputHostMsg_SetVolume(kStreamId, -0.5));
-
- base::RunLoop().RunUntilIdle();
-}
-
-// Checks that a stream_id cannot be reused.
-TEST_F(AudioInputRendererHostTest, CreateTwice_Error) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(renderer_, NotifyStreamError(kStreamId));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
-}
-
-// Checks that when two streams are created, messages are routed to the correct
-// stream.
-TEST_F(AudioInputRendererHostTest, TwoStreams) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId + 1, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated()).Times(2);
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId + 1, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), Record());
- airh_->OnMessageReceived(AudioInputHostMsg_RecordStream(kStreamId));
- base::RunLoop().RunUntilIdle();
- EXPECT_CALL(*controller_factory_.controller(1), SetVolume(kNewVolume));
- airh_->OnMessageReceived(
- AudioInputHostMsg_SetVolume(kStreamId + 1, kNewVolume));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
- EXPECT_CALL(*controller_factory_.controller(1), DidClose());
-}
-
-// Checks that the stream is properly cleaned up and a notification is sent to
-// the renderer when the stream encounters an error.
-TEST_F(AudioInputRendererHostTest, Error_ClosesController) {
- int session_id =
- Open("Default device", media::AudioDeviceDescription::kDefaultDeviceId);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
-
- base::RunLoop().RunUntilIdle();
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
- EXPECT_CALL(renderer_, NotifyStreamError(kStreamId));
-
- controller_factory_.controller(0)->handler()->OnError(
- AudioInputController::UNKNOWN_ERROR);
-
- // Check Close expectation before the destructor.
- base::RunLoop().RunUntilIdle();
- Mock::VerifyAndClear(controller_factory_.controller(0));
-}
-
-// Checks that tab capture streams can be created.
-TEST_F(AudioInputRendererHostTest, TabCaptureStream) {
- StreamControls controls(/* request_audio */ true, /* request_video */ false);
- controls.audio.device_id = base::StringPrintf(
- "web-contents-media-stream://%d:%d", kRenderProcessId, kRenderFrameId);
- controls.audio.stream_source = kMediaStreamSourceTab;
- std::string request_label = media_stream_manager_->MakeMediaAccessRequest(
- kRenderProcessId, kRenderFrameId, 0, controls, SecurityOrigin(),
- base::BindOnce([](const MediaStreamDevices& devices,
- std::unique_ptr<MediaStreamUIProxy>) {}));
- base::RunLoop().RunUntilIdle();
- int session_id = Open("Tab capture", controls.audio.device_id);
-
- EXPECT_CALL(renderer_, NotifyStreamCreated(kStreamId, _, _, _));
- EXPECT_CALL(controller_factory_, ControllerCreated());
-
- airh_->OnMessageReceived(AudioInputHostMsg_CreateStream(
- kStreamId, kRenderFrameId, session_id, DefaultConfig()));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_CALL(*controller_factory_.controller(0), DidClose());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc
index 5468a9bd842..b92446bd173 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.cc
@@ -27,7 +27,8 @@ AudioInputStreamHandle::AudioInputStreamHandle(
media::MojoAudioInputStream::CreateDelegateCallback
create_delegate_callback,
DeleterCallback deleter_callback)
- : deleter_callback_(std::move(deleter_callback)),
+ : stream_id_(base::UnguessableToken::Create()),
+ deleter_callback_(std::move(deleter_callback)),
client_(std::move(client)),
stream_ptr_(),
stream_client_request_(),
@@ -49,6 +50,12 @@ AudioInputStreamHandle::~AudioInputStreamHandle() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
+void AudioInputStreamHandle::SetOutputDeviceForAec(
+ const std::string& raw_output_device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ stream_.SetOutputDeviceForAec(raw_output_device_id);
+}
+
void AudioInputStreamHandle::OnCreated(media::mojom::AudioDataPipePtr data_pipe,
bool initially_muted) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -57,7 +64,7 @@ void AudioInputStreamHandle::OnCreated(media::mojom::AudioDataPipePtr data_pipe,
<< "|deleter_callback_| was called, but |this| hasn't been destructed!";
client_->StreamCreated(std::move(stream_ptr_),
std::move(stream_client_request_),
- std::move(data_pipe), initially_muted);
+ std::move(data_pipe), initially_muted, stream_id_);
}
void AudioInputStreamHandle::CallDeleter() {
diff --git a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h
index 83f27e17a7b..0a30e0085d2 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_stream_handle.h
@@ -33,12 +33,16 @@ class CONTENT_EXPORT AudioInputStreamHandle {
~AudioInputStreamHandle();
+ const base::UnguessableToken& id() const { return stream_id_; }
+ void SetOutputDeviceForAec(const std::string& raw_output_device_id);
+
private:
void OnCreated(media::mojom::AudioDataPipePtr, bool initially_muted);
void CallDeleter();
SEQUENCE_CHECKER(sequence_checker_);
+ const base::UnguessableToken stream_id_;
DeleterCallback deleter_callback_;
mojom::RendererAudioInputStreamFactoryClientPtr client_;
media::mojom::AudioInputStreamPtr stream_ptr_;
diff --git a/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
index 2d2cd3c4b48..90be42dc659 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_stream_handle_unittest.cc
@@ -8,8 +8,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/memory/shared_memory.h"
-#include "base/memory/shared_memory_handle.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/sync_socket.h"
@@ -36,6 +35,7 @@ class FakeAudioInputDelegate : public media::AudioInputDelegate {
int GetStreamId() override { return 0; };
void OnRecordStream() override{};
void OnSetVolume(double volume) override{};
+ void OnSetOutputDeviceForAec(const std::string& output_device_id) override{};
private:
DISALLOW_COPY_AND_ASSIGN(FakeAudioInputDelegate);
@@ -46,10 +46,13 @@ class MockRendererAudioInputStreamFactoryClient
public:
MOCK_METHOD0(Created, void());
- void StreamCreated(media::mojom::AudioInputStreamPtr input_stream,
- media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::AudioDataPipePtr data_pipe,
- bool initially_muted) override {
+ void StreamCreated(
+ media::mojom::AudioInputStreamPtr input_stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::AudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override {
+ EXPECT_TRUE(stream_id.has_value());
input_stream_ = std::move(input_stream);
client_request_ = std::move(client_request);
Created();
@@ -89,11 +92,9 @@ class AudioInputStreamHandleTest : public Test {
EXPECT_TRUE(event_handler_);
const size_t kSize = 1234;
- base::SharedMemoryCreateOptions shmem_options;
- shmem_options.size = kSize;
- shmem_options.share_read_only = true;
- shared_memory_.Create(shmem_options);
- shared_memory_.Map(kSize);
+ shared_memory_region_ =
+ base::ReadOnlySharedMemoryRegion::Create(kSize).region;
+ EXPECT_TRUE(shared_memory_region_.IsValid());
EXPECT_TRUE(
base::CancelableSyncSocket::CreatePair(local_.get(), remote_.get()));
}
@@ -101,7 +102,8 @@ class AudioInputStreamHandleTest : public Test {
void SendCreatedNotification() {
const int kIrrelevantStreamId = 0;
const bool kInitiallyMuted = false;
- event_handler_->OnStreamCreated(kIrrelevantStreamId, &shared_memory_,
+ event_handler_->OnStreamCreated(kIrrelevantStreamId,
+ std::move(shared_memory_region_),
std::move(remote_), kInitiallyMuted);
}
@@ -128,7 +130,7 @@ class AudioInputStreamHandleTest : public Test {
media::AudioInputDelegate::EventHandler* event_handler_ = nullptr;
std::unique_ptr<AudioInputStreamHandle> handle_;
- base::SharedMemory shared_memory_;
+ base::ReadOnlySharedMemoryRegion shared_memory_region_;
std::unique_ptr<base::CancelableSyncSocket> local_;
std::unique_ptr<base::CancelableSyncSocket> remote_;
};
diff --git a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
index 83d47fd31e3..1b601ac380f 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/task_runner_util.h"
+#include "base/trace_event/trace_event.h"
#include "content/browser/media/media_devices_permission_checker.h"
#include "content/browser/media/media_devices_util.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
@@ -28,15 +29,14 @@ void CheckAccessOnUIThread(
int render_frame_id,
bool override_permissions,
bool permissions_override_value,
- base::OnceCallback<void(std::string, const url::Origin&, bool)> cb) {
+ base::OnceCallback<void(std::string, url::Origin, bool)> cb) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- const auto& salt_and_origin =
+ MediaDeviceSaltAndOrigin salt_and_origin =
GetMediaDeviceSaltAndOrigin(render_process_id, render_frame_id);
- std::string salt = salt_and_origin.first;
- const url::Origin& origin = salt_and_origin.second;
- if (!MediaStreamManager::IsOriginAllowed(render_process_id, origin)) {
+ if (!MediaStreamManager::IsOriginAllowed(render_process_id,
+ salt_and_origin.origin)) {
// In this case, it's likely a navigation has occurred while processing this
// request.
std::move(cb).Run(std::string(), url::Origin(), false);
@@ -46,18 +46,84 @@ void CheckAccessOnUIThread(
// Check that MediaStream device permissions have been granted for
// nondefault devices.
if (override_permissions) {
- std::move(cb).Run(std::move(salt), origin, permissions_override_value);
+ std::move(cb).Run(std::move(salt_and_origin.device_id_salt),
+ std::move(salt_and_origin.origin),
+ permissions_override_value);
return;
}
std::move(cb).Run(
- std::move(salt), origin,
+ std::move(salt_and_origin.device_id_salt),
+ std::move(salt_and_origin.origin),
MediaDevicesPermissionChecker().CheckPermissionOnUIThread(
MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, render_process_id, render_frame_id));
}
} // namespace
+class AudioOutputAuthorizationHandler::TraceScope {
+ public:
+ explicit TraceScope(const std::string& device_id) {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
+ "audio", "Audio output device authorization", this);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "Request for device", this,
+ "device id", device_id);
+ }
+
+ ~TraceScope() {
+ if (waiting_for_params_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "Getting audio parameters", this,
+ "cancelled", true);
+ }
+ if (checking_access_) {
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "Checking access", this,
+ "cancelled", true);
+ }
+ TRACE_EVENT_NESTABLE_ASYNC_END0("audio", "Request for device", this);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("audio",
+ "Audio output device authorization", this);
+ }
+
+ void SimpleEvent(const char* event) {
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("audio", event, this);
+ }
+
+ void UsingSessionId(int session_id, const std::string& device_id) {
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT2("audio", "Using session id", this,
+ "session id", session_id, "device id",
+ device_id);
+ }
+
+ void CheckAccessStart(const std::string& device_id) {
+ checking_access_ = true;
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "Checking access", this,
+ "device id", device_id);
+ }
+
+ void AccessChecked(bool has_access) {
+ checking_access_ = false;
+ TRACE_EVENT_NESTABLE_ASYNC_END1("audio", "Checking access", this,
+ "access granted", has_access);
+ }
+
+ void StartedGettingAudioParameters(const std::string& raw_device_id) {
+ waiting_for_params_ = true;
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("audio", "Getting audio parameters", this,
+ "device id", raw_device_id);
+ }
+
+ void FinishedGettingAudioParameters() {
+ waiting_for_params_ = false;
+ TRACE_EVENT_NESTABLE_ASYNC_END0("audio", "Getting audio parameters", this);
+ }
+
+ private:
+ bool checking_access_ = false;
+ bool waiting_for_params_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(TraceScope);
+};
+
AudioOutputAuthorizationHandler::AudioOutputAuthorizationHandler(
media::AudioSystem* audio_system,
MediaStreamManager* media_stream_manager,
@@ -81,8 +147,10 @@ void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
const std::string& device_id,
AuthorizationCompletedCallback cb) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto trace_scope = std::make_unique<TraceScope>(device_id);
if (!IsValidDeviceId(device_id)) {
+ trace_scope->SimpleEvent("Invalid device id");
std::move(cb).Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
media::AudioParameters::UnavailableDeviceParams(),
std::string(), std::string());
@@ -97,6 +165,7 @@ void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
media_stream_manager_->audio_input_device_manager()
->GetOpenedDeviceById(session_id);
if (device && device->matched_output_device_id) {
+ trace_scope->UsingSessionId(session_id, device->id);
// We don't need the origin for authorization in this case, but it's used
// for hashing the device id before sending it back to the renderer.
BrowserThread::PostTaskAndReplyWithResult(
@@ -104,8 +173,8 @@ void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
base::BindOnce(&GetMediaDeviceSaltAndOrigin, render_process_id_,
render_frame_id),
base::BindOnce(&AudioOutputAuthorizationHandler::HashDeviceId,
- weak_factory_.GetWeakPtr(), std::move(cb),
- *device->matched_output_device_id));
+ weak_factory_.GetWeakPtr(), std::move(trace_scope),
+ std::move(cb), *device->matched_output_device_id));
return;
}
// Otherwise, the default device is used.
@@ -113,20 +182,22 @@ void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
// The default device doesn't need authorization.
- GetDeviceParameters(std::move(cb),
+ GetDeviceParameters(std::move(trace_scope), std::move(cb),
media::AudioDeviceDescription::kDefaultDeviceId);
return;
}
+ trace_scope->CheckAccessStart(device_id);
// Check device permissions if nondefault device is requested.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(
- &CheckAccessOnUIThread, render_process_id_, render_frame_id,
- override_permissions_, permissions_override_value_,
- media::BindToCurrentLoop(base::BindOnce(
- &AudioOutputAuthorizationHandler::AccessChecked,
- weak_factory_.GetWeakPtr(), std::move(cb), device_id))));
+ base::BindOnce(&CheckAccessOnUIThread, render_process_id_,
+ render_frame_id, override_permissions_,
+ permissions_override_value_,
+ media::BindToCurrentLoop(base::BindOnce(
+ &AudioOutputAuthorizationHandler::AccessChecked,
+ weak_factory_.GetWeakPtr(), std::move(trace_scope),
+ std::move(cb), device_id))));
}
void AudioOutputAuthorizationHandler::OverridePermissionsForTesting(
@@ -145,27 +216,31 @@ void AudioOutputAuthorizationHandler::UMALogDeviceAuthorizationTime(
}
void AudioOutputAuthorizationHandler::HashDeviceId(
+ std::unique_ptr<TraceScope> trace_scope,
AuthorizationCompletedCallback cb,
const std::string& raw_device_id,
- const std::pair<std::string, url::Origin>& salt_and_origin) const {
+ const MediaDeviceSaltAndOrigin& salt_and_origin) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!raw_device_id.empty());
std::string hashed_device_id = GetHMACForMediaDeviceID(
- salt_and_origin.first, salt_and_origin.second, raw_device_id);
+ salt_and_origin.device_id_salt, salt_and_origin.origin, raw_device_id);
+ trace_scope->StartedGettingAudioParameters(raw_device_id);
audio_system_->GetOutputStreamParameters(
raw_device_id,
base::BindOnce(&AudioOutputAuthorizationHandler::DeviceParametersReceived,
- weak_factory_.GetWeakPtr(), std::move(cb),
- hashed_device_id, raw_device_id));
+ weak_factory_.GetWeakPtr(), std::move(trace_scope),
+ std::move(cb), hashed_device_id, raw_device_id));
}
void AudioOutputAuthorizationHandler::AccessChecked(
+ std::unique_ptr<TraceScope> trace_scope,
AuthorizationCompletedCallback cb,
const std::string& device_id,
std::string salt,
- const url::Origin& security_origin,
+ url::Origin security_origin,
bool has_access) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ trace_scope->AccessChecked(has_access);
if (!has_access) {
std::move(cb).Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
@@ -179,11 +254,13 @@ void AudioOutputAuthorizationHandler::AccessChecked(
media_stream_manager_->media_devices_manager()->EnumerateDevices(
devices_to_enumerate,
base::Bind(&AudioOutputAuthorizationHandler::TranslateDeviceID,
- weak_factory_.GetWeakPtr(), base::Passed(&cb), device_id,
- std::move(salt), security_origin));
+ weak_factory_.GetWeakPtr(), base::Passed(&trace_scope),
+ base::Passed(&cb), device_id, std::move(salt),
+ std::move(security_origin)));
}
void AudioOutputAuthorizationHandler::TranslateDeviceID(
+ std::unique_ptr<TraceScope> trace_scope,
AuthorizationCompletedCallback cb,
const std::string& device_id,
const std::string& salt,
@@ -191,32 +268,40 @@ void AudioOutputAuthorizationHandler::TranslateDeviceID(
const MediaDeviceEnumeration& enumeration) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!media::AudioDeviceDescription::IsDefaultDevice(device_id));
+
for (const MediaDeviceInfo& device_info :
enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
if (DoesMediaDeviceIDMatchHMAC(salt, security_origin, device_id,
device_info.device_id)) {
- GetDeviceParameters(std::move(cb), device_info.device_id);
+ GetDeviceParameters(std::move(trace_scope), std::move(cb),
+ device_info.device_id);
return;
}
}
+
+ trace_scope->SimpleEvent("Found no device matching device id");
std::move(cb).Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
media::AudioParameters::UnavailableDeviceParams(),
std::string(), std::string());
}
void AudioOutputAuthorizationHandler::GetDeviceParameters(
+ std::unique_ptr<TraceScope> trace_scope,
AuthorizationCompletedCallback cb,
const std::string& raw_device_id) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!raw_device_id.empty());
+
+ trace_scope->StartedGettingAudioParameters(raw_device_id);
audio_system_->GetOutputStreamParameters(
raw_device_id,
base::BindOnce(&AudioOutputAuthorizationHandler::DeviceParametersReceived,
- weak_factory_.GetWeakPtr(), std::move(cb), std::string(),
- raw_device_id));
+ weak_factory_.GetWeakPtr(), std::move(trace_scope),
+ std::move(cb), std::string(), raw_device_id));
}
void AudioOutputAuthorizationHandler::DeviceParametersReceived(
+ std::unique_ptr<TraceScope> trace_scope,
AuthorizationCompletedCallback cb,
const std::string& id_for_renderer,
const std::string& raw_device_id,
@@ -224,6 +309,9 @@ void AudioOutputAuthorizationHandler::DeviceParametersReceived(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!raw_device_id.empty());
DCHECK(!params || params->IsValid());
+
+ trace_scope->FinishedGettingAudioParameters();
+
std::move(cb).Run(
media::OUTPUT_DEVICE_STATUS_OK,
params.value_or(media::AudioParameters::UnavailableDeviceParams()),
diff --git a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.h b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.h
index 4cc2fdd8979..faf06ff1d3b 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.h
+++ b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler.h
@@ -65,27 +65,34 @@ class CONTENT_EXPORT AudioOutputAuthorizationHandler {
static void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time);
private:
- void HashDeviceId(
- AuthorizationCompletedCallback cb,
- const std::string& raw_device_id,
- const std::pair<std::string, url::Origin>& salt_and_origin) const;
+ // Helper class for recording traces.
+ class TraceScope;
+
+ void HashDeviceId(std::unique_ptr<TraceScope> trace_scope,
+ AuthorizationCompletedCallback cb,
+ const std::string& raw_device_id,
+ const MediaDeviceSaltAndOrigin& salt_and_origin) const;
- void AccessChecked(AuthorizationCompletedCallback cb,
+ void AccessChecked(std::unique_ptr<TraceScope> trace_scope,
+ AuthorizationCompletedCallback cb,
const std::string& device_id,
std::string salt,
- const url::Origin& security_origin,
+ url::Origin security_origin,
bool has_access) const;
- void TranslateDeviceID(AuthorizationCompletedCallback cb,
+ void TranslateDeviceID(std::unique_ptr<TraceScope> trace_scope,
+ AuthorizationCompletedCallback cb,
const std::string& device_id,
const std::string& salt,
const url::Origin& security_origin,
const MediaDeviceEnumeration& enumeration) const;
- void GetDeviceParameters(AuthorizationCompletedCallback cb,
+ void GetDeviceParameters(std::unique_ptr<TraceScope> trace_scope,
+ AuthorizationCompletedCallback cb,
const std::string& raw_device_id) const;
void DeviceParametersReceived(
+ std::unique_ptr<TraceScope> trace_scope,
AuthorizationCompletedCallback cb,
const std::string& device_id_for_renderer,
const std::string& raw_device_id,
diff --git a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
index eccbda52379..5a72602b62c 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
@@ -53,10 +53,8 @@ class TestBrowserContextWithRealURLRequestContextGetter
: public TestBrowserContext {
public:
TestBrowserContextWithRealURLRequestContextGetter() {
- request_context_ =
- base::MakeRefCounted<net::TrivialURLRequestContextGetter>(
- &context_,
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ request_context_ = base::MakeRefCounted<net::TestURLRequestContextGetter>(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
salt_ = TestBrowserContext::GetMediaDeviceIDSalt();
}
@@ -73,8 +71,7 @@ class TestBrowserContextWithRealURLRequestContextGetter
void set_media_device_id_salt(std::string salt) { salt_ = std::move(salt); }
private:
- net::TestURLRequestContext context_;
- scoped_refptr<net::URLRequestContextGetter> request_context_;
+ scoped_refptr<net::TestURLRequestContextGetter> request_context_;
std::string salt_;
};
diff --git a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc
index da2c826ccb8..81cd7e4f1f4 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl.cc
@@ -205,7 +205,7 @@ void AudioOutputDelegateImpl::OnSetVolume(double volume) {
void AudioOutputDelegateImpl::SendCreatedNotification() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- subscriber_->OnStreamCreated(stream_id_, reader_->shared_memory(),
+ subscriber_->OnStreamCreated(stream_id_, reader_->TakeSharedMemoryRegion(),
std::move(foreign_socket_));
}
diff --git a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
index f474636086a..62a7132a451 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
@@ -81,11 +81,12 @@ class MockObserver : public content::MediaObserver {
class MockEventHandler : public media::AudioOutputDelegate::EventHandler {
public:
- void OnStreamCreated(int stream_id,
- const base::SharedMemory* shared_memory,
- std::unique_ptr<base::CancelableSyncSocket> socket) {
+ void OnStreamCreated(
+ int stream_id,
+ base::UnsafeSharedMemoryRegion shared_memory_region,
+ std::unique_ptr<base::CancelableSyncSocket> socket) override {
EXPECT_EQ(stream_id, kStreamId);
- EXPECT_NE(shared_memory, nullptr);
+ EXPECT_TRUE(shared_memory_region.IsValid());
EXPECT_NE(socket.get(), nullptr);
GotOnStreamCreated();
}
@@ -160,7 +161,7 @@ class AudioOutputDelegateTest : public testing::Test {
mirroring_manager_.GetRemoveDiverterCallback());
}
- ~AudioOutputDelegateTest() { audio_manager_->Shutdown(); }
+ ~AudioOutputDelegateTest() override { audio_manager_->Shutdown(); }
mojo::StrongBindingPtr<media::mojom::AudioOutputStreamObserver>
CreateObserverBinding(
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
deleted file mode 100644
index 6637ebf3354..00000000000
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/audio_renderer_host.h"
-
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/lazy_instance.h"
-#include "base/metrics/histogram_macros.h"
-#include "build/build_config.h"
-#include "content/browser/bad_message.h"
-#include "content/browser/browser_main_loop.h"
-#include "content/browser/media/audio_stream_monitor.h"
-#include "content/browser/media/media_internals.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/audio_output_authorization_handler.h"
-#include "content/browser/renderer_host/media/audio_output_delegate_impl.h"
-#include "content/browser/renderer_host/media/audio_output_stream_observer_impl.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/common/media/audio_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/media_device_id.h"
-#include "content/public/browser/media_observer.h"
-#include "content/public/browser/render_frame_host.h"
-#include "media/audio/audio_device_description.h"
-#include "media/audio/audio_logging.h"
-#include "media/base/audio_bus.h"
-#include "media/base/limits.h"
-#include "media/mojo/interfaces/audio_logging.mojom.h"
-#include "media/mojo/interfaces/audio_output_stream.mojom.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-using media::AudioBus;
-using media::AudioManager;
-
-namespace content {
-
-namespace {
-
-// Check that the routing ID references a valid RenderFrameHost, and run
-// |callback| on the IO thread with true if the ID is valid.
-void ValidateRenderFrameId(int render_process_id,
- int render_frame_id,
- base::OnceCallback<void(bool)> callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- const bool frame_exists =
- !!RenderFrameHost::FromID(render_process_id, render_frame_id);
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::BindOnce(std::move(callback), frame_exists));
-}
-
-} // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// AudioRendererHost implementations.
-
-AudioRendererHost::AudioRendererHost(int render_process_id,
- media::AudioManager* audio_manager,
- media::AudioSystem* audio_system,
- MediaStreamManager* media_stream_manager)
- : BrowserMessageFilter(AudioMsgStart),
- render_process_id_(render_process_id),
- audio_manager_(audio_manager),
- media_stream_manager_(media_stream_manager),
- authorization_handler_(audio_system,
- media_stream_manager,
- render_process_id_) {
- DCHECK(audio_manager_);
-}
-
-AudioRendererHost::~AudioRendererHost() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(delegates_.empty());
-}
-
-void AudioRendererHost::OnChannelClosing() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- delegates_.clear();
-
- // Remove any authorizations for streams that were not yet created
- authorizations_.clear();
-}
-
-void AudioRendererHost::OnDestruct() const {
- BrowserThread::DeleteOnIOThread::Destruct(this);
-}
-
-void AudioRendererHost::OnStreamCreated(
- int stream_id,
- const base::SharedMemory* shared_memory,
- std::unique_ptr<base::CancelableSyncSocket> foreign_socket) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!PeerHandle()) {
- DLOG(WARNING) << "Renderer process handle is invalid.";
- OnStreamError(stream_id);
- return;
- }
-
- if (!LookupById(stream_id)) {
- OnStreamError(stream_id);
- return;
- }
-
- base::SyncSocket::TransitDescriptor socket_descriptor;
-
- base::SharedMemoryHandle foreign_memory_handle =
- shared_memory->handle().Duplicate();
- if (!(foreign_memory_handle.IsValid() &&
- foreign_socket->PrepareTransitDescriptor(PeerHandle(),
- &socket_descriptor))) {
- // Something went wrong in preparing the IPC handles.
- OnStreamError(stream_id);
- return;
- }
-
- Send(new AudioMsg_NotifyStreamCreated(stream_id, foreign_memory_handle,
- socket_descriptor));
-}
-
-void AudioRendererHost::OnStreamError(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- SendErrorMessage(stream_id);
- OnCloseStream(stream_id);
-}
-
-void AudioRendererHost::DidValidateRenderFrame(int stream_id, bool is_valid) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (is_valid)
- return;
-
- DLOG(WARNING) << "Render frame for stream (id=" << stream_id
- << ") no longer exists.";
- OnStreamError(stream_id);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// IPC Messages handler
-bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
- IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization,
- OnRequestDeviceAuthorization)
- IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void AudioRendererHost::OnRequestDeviceAuthorization(
- int stream_id,
- int render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const base::TimeTicks auth_start_time = base::TimeTicks::Now();
- DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
- << "(stream_id=" << stream_id
- << ", render_frame_id=" << render_frame_id
- << ", session_id=" << session_id << ", device_id=" << device_id
- << ", security_origin=" << security_origin << ")";
-
- if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
- return;
-
- authorizations_.insert(
- std::make_pair(stream_id, std::make_pair(false, std::string())));
-
- // Unretained is ok here since |this| owns |authorization_handler_| and
- // |authorization_handler_| owns the callback.
- authorization_handler_.RequestDeviceAuthorization(
- render_frame_id, session_id, device_id,
- base::BindOnce(&AudioRendererHost::AuthorizationCompleted,
- base::Unretained(this), stream_id, auth_start_time));
-}
-
-void AudioRendererHost::AuthorizationCompleted(
- int stream_id,
- base::TimeTicks auth_start_time,
- media::OutputDeviceStatus status,
- const media::AudioParameters& params,
- const std::string& raw_device_id,
- const std::string& device_id_for_renderer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- AudioOutputAuthorizationHandler::UMALogDeviceAuthorizationTime(
- auth_start_time);
-
- auto auth_data = authorizations_.find(stream_id);
- if (auth_data == authorizations_.end())
- return; // Stream was closed before finishing authorization
-
- if (status == media::OUTPUT_DEVICE_STATUS_OK) {
- auth_data->second.first = true;
- auth_data->second.second = raw_device_id;
- Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, status, params,
- device_id_for_renderer));
- } else {
- authorizations_.erase(auth_data);
- Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, status, media::AudioParameters::UnavailableDeviceParams(),
- std::string()));
- }
-}
-
-void AudioRendererHost::OnCreateStream(int stream_id,
- int render_frame_id,
- const media::AudioParameters& params) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream"
- << "(stream_id=" << stream_id << ")";
-
- // Determine whether to use the device_unique_id from an authorization, or an
- // empty string (i.e., when no previous authorization was requested, assume
- // default device).
- std::string device_unique_id;
- const auto& auth_data = authorizations_.find(stream_id);
- if (auth_data != authorizations_.end()) {
- if (!auth_data->second.first) {
- // The authorization for this stream is still pending, so it's an error
- // to create it now.
- content::bad_message::ReceivedBadMessage(
- this, bad_message::ARH_CREATED_STREAM_WITHOUT_AUTHORIZATION);
- return;
- }
- device_unique_id.swap(auth_data->second.second);
- authorizations_.erase(auth_data);
- }
-
- // Fail early if either of two sanity-checks fail:
- // 1. There should not yet exist an AudioOutputDelegate for the given
- // |stream_id| since the renderer may not create two streams with the
- // same ID.
- // 2. An out-of-range render frame ID was provided. Renderers must *always*
- // specify a valid render frame ID for each audio output they create, as
- // several browser-level features depend on this (e.g., OOM manager, UI
- // audio indicator, muting, audio capture).
- // Note: media::AudioParameters is validated in the deserializer, so there is
- // no need to check that here.
- if (LookupById(stream_id)) {
- SendErrorMessage(stream_id);
- return;
- }
- if (render_frame_id <= 0) {
- SendErrorMessage(stream_id);
- return;
- }
-
-#if !defined(OS_ANDROID)
- if (params.IsBitstreamFormat()) {
- // Bitstream formats are only supported on Android, and shouldn't be created
- // on other platforms.
- bad_message::ReceivedBadMessage(this,
- bad_message::ARH_UNEXPECTED_BITSTREAM);
- return;
- }
-#endif
-
- // Post a task to the UI thread to check that the |render_frame_id| references
- // a valid render frame. This validation is important for all the reasons
- // stated in the comments above. This does not block stream creation, but will
- // force-close the stream later if validation fails.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&ValidateRenderFrameId, render_process_id_,
- render_frame_id,
- base::BindOnce(&AudioRendererHost::DidValidateRenderFrame,
- this, stream_id)));
-
- MediaObserver* const media_observer =
- GetContentClient()->browser()->GetMediaObserver();
-
- media::mojom::AudioLogPtr audio_log_ptr =
- MediaInternals::GetInstance()->CreateMojoAudioLog(
- media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER, stream_id,
- render_process_id_, render_frame_id);
- audio_log_ptr->OnCreated(params, device_unique_id);
-
- media::mojom::AudioOutputStreamObserverPtr observer_ptr;
- mojo::MakeStrongBinding(std::make_unique<AudioOutputStreamObserverImpl>(
- render_process_id_, render_frame_id, stream_id),
- mojo::MakeRequest(&observer_ptr));
-
- auto delegate = AudioOutputDelegateImpl::Create(
- this, audio_manager_, std::move(audio_log_ptr), media_observer, stream_id,
- render_frame_id, render_process_id_, params, std::move(observer_ptr),
- device_unique_id);
- if (delegate)
- delegates_.push_back(std::move(delegate));
- else
- SendErrorMessage(stream_id);
-}
-
-void AudioRendererHost::OnPlayStream(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- media::AudioOutputDelegate* delegate = LookupById(stream_id);
- if (!delegate) {
- SendErrorMessage(stream_id);
- return;
- }
-
- delegate->OnPlayStream();
-}
-
-void AudioRendererHost::OnPauseStream(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- media::AudioOutputDelegate* delegate = LookupById(stream_id);
- if (!delegate) {
- SendErrorMessage(stream_id);
- return;
- }
-
- delegate->OnPauseStream();
-}
-
-void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- media::AudioOutputDelegate* delegate = LookupById(stream_id);
- if (!delegate) {
- SendErrorMessage(stream_id);
- return;
- }
-
- // Make sure the volume is valid.
- if (volume < 0 || volume > 1.0)
- return;
- delegate->OnSetVolume(volume);
-}
-
-void AudioRendererHost::SendErrorMessage(int stream_id) {
- Send(new AudioMsg_NotifyStreamError(stream_id));
-}
-
-void AudioRendererHost::OnCloseStream(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- authorizations_.erase(stream_id);
-
- auto i = LookupIteratorById(stream_id);
-
- // Prevent oustanding callbacks from attempting to close/delete the same
- // AudioOutputDelegate twice.
- if (i == delegates_.end())
- return;
-
- std::swap(*i, delegates_.back());
- delegates_.pop_back();
-}
-
-AudioRendererHost::AudioOutputDelegateVector::iterator
-AudioRendererHost::LookupIteratorById(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- return std::find_if(
- delegates_.begin(), delegates_.end(),
- [stream_id](const std::unique_ptr<media::AudioOutputDelegate>& d) {
- return d->GetStreamId() == stream_id;
- });
-}
-
-media::AudioOutputDelegate* AudioRendererHost::LookupById(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- auto i = LookupIteratorById(stream_id);
- return i != delegates_.end() ? i->get() : nullptr;
-}
-
-bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return authorizations_.find(stream_id) != authorizations_.end();
-}
-
-void AudioRendererHost::OverrideDevicePermissionsForTesting(bool has_access) {
- authorization_handler_.OverridePermissionsForTesting(has_access);
-}
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
deleted file mode 100644
index d981ae8e014..00000000000
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.h
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// AudioRendererHost serves audio related requests from AudioRenderer which
-// lives inside the render process and provide access to audio hardware.
-//
-// This class is owned by RenderProcessHostImpl, and instantiated on UI
-// thread, but all other operations and method calls happen on IO thread, so we
-// need to be extra careful about the lifetime of this object. AudioManager is a
-// singleton and created in IO thread, audio output streams are also created in
-// the IO thread, so we need to destroy them also in IO thread. After this class
-// is created, a task of OnInitialized() is posted on IO thread in which
-// singleton of AudioManager is created.
-//
-// Here's an example of a typical IPC dialog for audio:
-//
-// Renderer AudioRendererHost
-// | |
-// | RequestDeviceAuthorization > |
-// | < NotifyDeviceAuthorized |
-// | |
-// | CreateStream > |
-// | < NotifyStreamCreated |
-// | |
-// | PlayStream > |
-// | |
-// | PauseStream > |
-// | |
-// | PlayStream > |
-// | ... |
-// | CloseStream > |
-// v v
-// If there is an error at any point, a NotifyStreamError will
-// be sent. Otherwise, the renderer can assume that the actual state
-// of the output stream is consistent with the control signals it sends.
-
-// A SyncSocket pair is used to signal buffer readiness between processes.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "content/browser/renderer_host/media/audio_output_authorization_handler.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/render_process_host.h"
-#include "media/audio/audio_output_delegate.h"
-
-namespace base {
-class SharedMemory;
-class CancelableSyncSocket;
-}
-
-namespace media {
-class AudioManager;
-class AudioParameters;
-class AudioSystem;
-}
-
-namespace content {
-
-class MediaStreamManager;
-
-class CONTENT_EXPORT AudioRendererHost
- : public BrowserMessageFilter,
- public media::AudioOutputDelegate::EventHandler {
- public:
- // Called from UI thread from the owner of this object.
- AudioRendererHost(int render_process_id,
- media::AudioManager* audio_manager,
- media::AudioSystem* audio_system,
- MediaStreamManager* media_stream_manager);
-
- // BrowserMessageFilter implementation.
- void OnChannelClosing() override;
- void OnDestruct() const override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- // AudioOutputDelegate::EventHandler implementation
- void OnStreamCreated(
- int stream_id,
- const base::SharedMemory* shared_memory,
- std::unique_ptr<base::CancelableSyncSocket> foreign_socket) override;
- void OnStreamError(int stream_id) override;
-
- void OverrideDevicePermissionsForTesting(bool has_access);
-
- private:
- friend class AudioRendererHostTest;
- friend class BrowserThread;
- friend class base::DeleteHelper<AudioRendererHost>;
- friend class MockAudioRendererHost;
- friend class TestAudioRendererHost;
- FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, CreateMockStream);
- FRIEND_TEST_ALL_PREFIXES(AudioRendererHostTest, MockStreamDataConversation);
-
- using AudioOutputDelegateVector =
- std::vector<std::unique_ptr<media::AudioOutputDelegate>>;
-
- // The type of a function that is run on the UI thread to check whether the
- // routing IDs reference a valid RenderFrameHost. The function then runs
- // |callback| on the IO thread with true/false if valid/invalid.
- using ValidateRenderFrameIdFunction =
- void (*)(int render_process_id,
- int render_frame_id,
- base::OnceCallback<void(bool)> callback);
-
- ~AudioRendererHost() override;
-
- // Methods called on IO thread ----------------------------------------------
-
- // Audio related IPC message handlers.
-
- // Request permission to use an output device for use by a stream produced
- // in the RenderFrame referenced by |render_frame_id|.
- // |session_id| is used for unified IO to find out which input device to be
- // opened for the stream. For clients that do not use unified IO,
- // |session_id| will be ignored and the given |device_id| and
- // |security_origin| will be used to select the output device.
- // Upon completion of the process, the peer is notified with the device output
- // parameters via the NotifyDeviceAuthorized message.
- void OnRequestDeviceAuthorization(int stream_id,
- int render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
-
- void AuthorizationCompleted(int stream_id,
- base::TimeTicks auth_start_time,
- media::OutputDeviceStatus status,
- const media::AudioParameters& params,
- const std::string& raw_device_id,
- const std::string& device_id_for_renderer);
-
- // Creates an audio output stream with the specified format.
- // Upon success/failure, the peer is notified via the NotifyStreamCreated
- // message.
- void OnCreateStream(int stream_id,
- int render_frame_id,
- const media::AudioParameters& params);
-
- // Play the audio stream referenced by |stream_id|.
- void OnPlayStream(int stream_id);
-
- // Pause the audio stream referenced by |stream_id|.
- void OnPauseStream(int stream_id);
-
- // Close the audio stream referenced by |stream_id|.
- void OnCloseStream(int stream_id);
-
- // Set the volume of the audio stream referenced by |stream_id|.
- void OnSetVolume(int stream_id, double volume);
-
- // Helper methods.
-
- // Called after the |render_frame_id| provided to OnCreateStream() was
- // validated. When |is_valid| is false, this calls OnStreamError().
- void DidValidateRenderFrame(int stream_id, bool is_valid);
-
- // Updates status of stream for AudioStreamMonitor and updates
- // the number of playing streams.
- void StreamStateChanged(int stream_id, bool is_playing);
-
- // Send an error message to the renderer.
- void SendErrorMessage(int stream_id);
-
- // Helper methods to look up a AudioOutputDelegate identified by |stream_id|.
- // Returns delegates_.end() if not found.
- AudioOutputDelegateVector::iterator LookupIteratorById(int stream_id);
- // Returns nullptr if not found.
- media::AudioOutputDelegate* LookupById(int stream_id);
-
- // Helper method to check if the authorization procedure for stream
- // |stream_id| has started.
- bool IsAuthorizationStarted(int stream_id);
-
- // ID of the RenderProcessHost that owns this instance.
- const int render_process_id_;
-
- media::AudioManager* const audio_manager_;
-
- // Used to access to AudioInputDeviceManager.
- MediaStreamManager* media_stream_manager_;
-
- // Map of device authorizations for streams that are not yet created
- // The key is the stream ID, and the value is a pair. The pair's first element
- // is a bool that is true if the authorization process completes successfully.
- // The second element contains the unique ID of the authorized device.
- std::map<int, std::pair<bool, std::string>> authorizations_;
-
- AudioOutputAuthorizationHandler authorization_handler_;
-
- // A list of the current open streams.
- AudioOutputDelegateVector delegates_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioRendererHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
deleted file mode 100644
index e60a118f507..00000000000
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ /dev/null
@@ -1,628 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/audio_renderer_host.h"
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/sync_socket.h"
-#include "base/synchronization/lock.h"
-#include "content/browser/media/capture/audio_mirroring_manager.h"
-#include "content/browser/media/media_internals.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/common/media/audio_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/media_device_id.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_renderer_host.h"
-#include "ipc/ipc_message_utils.h"
-#include "media/audio/audio_system_impl.h"
-#include "media/audio/fake_audio_log_factory.h"
-#include "media/audio/fake_audio_manager.h"
-#include "media/audio/test_audio_thread.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/media_switches.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::Assign;
-using ::testing::AtLeast;
-using ::testing::DoAll;
-using ::testing::InvokeWithoutArgs;
-using ::testing::NotNull;
-
-namespace content {
-
-namespace {
-const int kStreamId = 50;
-const char kSecurityOrigin[] = "http://localhost";
-const char kDefaultDeviceId[] = "";
-const char kBadDeviceId[] =
- "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1";
-const char kInvalidDeviceId[] = "invalid-device-id";
-
-class MockAudioMirroringManager : public AudioMirroringManager {
- public:
- MockAudioMirroringManager() {}
- virtual ~MockAudioMirroringManager() {}
-
- MOCK_METHOD3(AddDiverter,
- void(int render_process_id,
- int render_frame_id,
- Diverter* diverter));
- MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
-};
-
-class FakeAudioManagerWithAssociations : public media::FakeAudioManager {
- public:
- explicit FakeAudioManagerWithAssociations(media::AudioLogFactory* factory)
- : FakeAudioManager(
- std::make_unique<media::TestAudioThread>(/*real thread*/ true),
- factory) {}
-
- void CreateDeviceAssociation(const std::string& input_device_id,
- const std::string& output_device_id) {
- // We shouldn't accidentally add hashed ids, since the audio manager
- // works with raw ids.
- EXPECT_FALSE(IsValidDeviceId(input_device_id));
- EXPECT_FALSE(IsValidDeviceId(output_device_id));
-
- base::AutoLock al(associations_lock_);
- associations_[input_device_id] = output_device_id;
- }
-
- std::string GetAssociatedOutputDeviceID(
- const std::string& input_id) override {
- base::AutoLock al(associations_lock_);
- auto it = associations_.find(input_id);
- return it == associations_.end() ? "" : it->second;
- }
-
- private:
- base::Lock associations_lock_;
- std::map<std::string, std::string> associations_;
-};
-
-} // namespace
-
-class MockAudioRendererHost : public AudioRendererHost {
- public:
- MockAudioRendererHost(base::RunLoop* auth_run_loop,
- int render_process_id,
- media::AudioManager* audio_manager,
- media::AudioSystem* audio_system,
- MediaStreamManager* media_stream_manager)
- : AudioRendererHost(render_process_id,
- audio_manager,
- audio_system,
- media_stream_manager),
- shared_memory_length_(0),
- auth_run_loop_(auth_run_loop) {}
-
- // A list of mock methods.
- MOCK_METHOD4(OnDeviceAuthorized,
- void(int stream_id,
- media::OutputDeviceStatus device_status,
- const media::AudioParameters& output_params,
- const std::string& matched_device_id));
- MOCK_METHOD1(WasNotifiedOfCreation, void(int stream_id));
- MOCK_METHOD1(WasNotifiedOfError, void(int stream_id));
-
- void ShutdownForBadMessage() override { bad_msg_count++; }
-
- int bad_msg_count = 0;
-
- private:
- virtual ~MockAudioRendererHost() {
- // Make sure all audio streams have been deleted.
- EXPECT_TRUE(delegates_.empty());
- }
-
- // This method is used to dispatch IPC messages to the renderer. We intercept
- // these messages here and dispatch to our mock methods to verify the
- // conversation between this object and the renderer.
- // Note: this means that file descriptors won't be duplicated,
- // leading to double-close errors from SyncSocket.
- // See crbug.com/647659.
- bool Send(IPC::Message* message) override {
- CHECK(message);
-
- // In this method we dispatch the messages to the according handlers as if
- // we are the renderer.
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
- IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized,
- OnNotifyDeviceAuthorized)
- IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
- OnNotifyStreamCreated)
- IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamError, OnNotifyStreamError)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- EXPECT_TRUE(handled);
-
- delete message;
- return true;
- }
-
- void OnNotifyDeviceAuthorized(int stream_id,
- media::OutputDeviceStatus device_status,
- const media::AudioParameters& output_params,
- const std::string& matched_device_id) {
- // Make sure we didn't leak a raw device id.
- EXPECT_TRUE(IsValidDeviceId(matched_device_id));
-
- OnDeviceAuthorized(stream_id, device_status, output_params,
- matched_device_id);
- auth_run_loop_->Quit();
- }
-
- void OnNotifyStreamCreated(
- int stream_id,
- base::SharedMemoryHandle handle,
- base::SyncSocket::TransitDescriptor socket_descriptor) {
- // Maps the shared memory.
- shared_memory_length_ = handle.GetSize();
- shared_memory_ = std::make_unique<base::SharedMemory>(handle, false);
- CHECK(shared_memory_->Map(shared_memory_length_));
- CHECK(shared_memory_->memory());
-
- // Create the SyncSocket using the handle.
- base::SyncSocket::Handle sync_socket_handle =
- base::SyncSocket::UnwrapHandle(socket_descriptor);
- sync_socket_ = std::make_unique<base::SyncSocket>(sync_socket_handle);
-
- // And then delegate the call to the mock method.
- WasNotifiedOfCreation(stream_id);
- }
-
- void OnNotifyStreamError(int stream_id) { WasNotifiedOfError(stream_id); }
-
- std::unique_ptr<base::SharedMemory> shared_memory_;
- std::unique_ptr<base::SyncSocket> sync_socket_;
- uint32_t shared_memory_length_;
- base::RunLoop* auth_run_loop_; // Used to wait for authorization.
-
- DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
-};
-
-class MockMediaStreamProviderListener : public MediaStreamProviderListener {
- public:
- MockMediaStreamProviderListener() {}
- ~MockMediaStreamProviderListener() override {}
-
- MOCK_METHOD2(Opened,
- void(MediaStreamType stream_type, int capture_session_id));
- void Closed(MediaStreamType stream_type, int capture_session_id) override {}
- void Aborted(MediaStreamType stream_type, int capture_session_id) override {}
-};
-
-class AudioRendererHostTest : public RenderViewHostTestHarness {
- public:
- AudioRendererHostTest() {}
- ~AudioRendererHostTest() override {}
-
- void SetUp() override {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kUseFakeDeviceForMediaStream);
-
- RenderViewHostTestHarness::SetUp();
- audio_manager_ =
- std::make_unique<FakeAudioManagerWithAssociations>(&log_factory_);
- audio_manager_->SetDiverterCallbacks(
- mirroring_manager_.GetAddDiverterCallback(),
- mirroring_manager_.GetRemoveDiverterCallback());
- audio_system_ =
- std::make_unique<media::AudioSystemImpl>(audio_manager_.get());
- media_stream_manager_ = std::make_unique<MediaStreamManager>(
- audio_system_.get(), audio_manager_->GetTaskRunner());
- auth_run_loop_ = std::make_unique<base::RunLoop>();
- host_ = base::MakeRefCounted<MockAudioRendererHost>(
- auth_run_loop_.get(), process()->GetID(), audio_manager_.get(),
- audio_system_.get(), media_stream_manager_.get());
-
- // Simulate IPC channel connected.
- host_->set_peer_process_for_testing(base::Process::Current());
-
- NavigateAndCommit(GURL(kSecurityOrigin));
- }
-
- void TearDown() override {
- // Simulate closing the IPC channel and give the audio thread time to close
- // the underlying streams.
- host_->OnChannelClosing();
-
- // Release the reference to the mock object. The object will be destructed
- // on message_loop_.
- host_ = nullptr;
-
- // Note: Shutdown is usually called after the IO thread is stopped, but in
- // this case it is not possible as we won't have a message loop at that
- // point.
- audio_manager_->Shutdown();
- RenderViewHostTestHarness::TearDown();
- }
-
- protected:
- void OverrideDevicePermissions(bool has_permissions) {
- host_->OverrideDevicePermissionsForTesting(has_permissions);
- }
-
- std::string GetNondefaultIdExpectedToPassPermissionsCheck() {
- base::RunLoop loop;
- std::string nondefault_id;
-
- MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
- devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
- media_stream_manager_->media_devices_manager()->EnumerateDevices(
- devices_to_enumerate,
- base::Bind(
- [](base::OnceClosure done, std::string* out,
- const MediaDeviceEnumeration& result) {
- // Index 0 is default, so use 1. Always exists because we use
- // fake devices.
- CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]
- .size() > 1)
- << "Expected to have a nondefault device.";
- *out = result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT][1]
- .device_id;
- std::move(done).Run();
- },
- loop.QuitClosure(), base::Unretained(&nondefault_id)));
-
- // Make sure nondefault_id is set before returning.
- loop.Run();
-
- return nondefault_id;
- }
-
- std::string GetNondefaultInputId() {
- base::RunLoop loop;
- std::string nondefault_id;
-
- MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
- devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
- media_stream_manager_->media_devices_manager()->EnumerateDevices(
- devices_to_enumerate,
- base::Bind(
- // Index 0 is default, so use 1. Always exists because we use
- // fake devices.
- [](base::OnceClosure done, std::string* out,
- const MediaDeviceEnumeration& result) {
- CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT]
- .size() > 1)
- << "Expected to have a nondefault device.";
- *out = result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT][1]
- .device_id;
- std::move(done).Run();
- },
- loop.QuitClosure(), base::Unretained(&nondefault_id)));
-
- // Make sure nondefault_id is set before returning.
- loop.Run();
-
- return nondefault_id;
- }
-
- void Create() {
- Create(kDefaultDeviceId, url::Origin::Create(GURL(kSecurityOrigin)), true,
- true);
- }
-
- void Create(const std::string& device_id,
- const url::Origin& security_origin,
- bool wait_for_auth,
- bool expect_onauthorized) {
- media::OutputDeviceStatus expected_device_status =
- device_id == kDefaultDeviceId ||
- device_id ==
- MediaStreamManager::GetHMACForMediaDeviceID(
- browser_context()->GetMediaDeviceIDSalt(),
- url::Origin::Create(GURL(kSecurityOrigin)),
- GetNondefaultIdExpectedToPassPermissionsCheck())
- ? media::OUTPUT_DEVICE_STATUS_OK
- : device_id == kBadDeviceId
- ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED
- : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND;
-
- if (expect_onauthorized) {
- EXPECT_CALL(*host_.get(),
- OnDeviceAuthorized(kStreamId, expected_device_status, _, _));
- }
-
- if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
- EXPECT_CALL(*host_.get(), WasNotifiedOfCreation(kStreamId));
- EXPECT_CALL(mirroring_manager_,
- AddDiverter(process()->GetID(), main_rfh()->GetRoutingID(),
- NotNull()))
- .RetiresOnSaturation();
- }
-
- // Send a create stream message to the audio output stream and wait until
- // we receive the created message.
- media::AudioParameters params(
- media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16,
- media::AudioParameters::kAudioCDSampleRate / 10);
- int session_id = 0;
-
- host_->OnRequestDeviceAuthorization(kStreamId, main_rfh()->GetRoutingID(),
- session_id, device_id, security_origin);
- if (wait_for_auth)
- auth_run_loop_->Run();
-
- if (!wait_for_auth ||
- expected_device_status == media::OUTPUT_DEVICE_STATUS_OK)
- host_->OnCreateStream(kStreamId, main_rfh()->GetRoutingID(), params);
-
- if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK)
- // At some point in the future, a corresponding RemoveDiverter() call must
- // be made.
- EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
- .RetiresOnSaturation();
- SyncWithAudioThread();
- }
-
- void CreateWithoutWaitingForAuth(const std::string& device_id) {
- Create(device_id, url::Origin::Create(GURL(kSecurityOrigin)), false, false);
- }
-
- void CreateWithInvalidRenderFrameId() {
- // When creating a stream with an invalid render frame ID, the host will
- // reply with a stream error message.
- EXPECT_CALL(*host_, WasNotifiedOfError(kStreamId));
-
- // However, validation does not block stream creation, so these method calls
- // might be made:
- EXPECT_CALL(*host_, WasNotifiedOfCreation(kStreamId)).Times(AtLeast(0));
- EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0));
- EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0));
-
- // Provide a seemingly-valid render frame ID; and it should be rejected when
- // AudioRendererHost calls ValidateRenderFrameId().
- const int kInvalidRenderFrameId = main_rfh()->GetRoutingID() + 1;
- const media::AudioParameters params(
- media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16,
- media::AudioParameters::kAudioCDSampleRate / 10);
- host_->OnCreateStream(kStreamId, kInvalidRenderFrameId, params);
- base::RunLoop().RunUntilIdle();
- }
-
- void CreateUnifiedStream(const url::Origin& security_origin) {
- std::string output_id = GetNondefaultIdExpectedToPassPermissionsCheck();
- std::string input_id = GetNondefaultInputId();
- std::string hashed_output_id = MediaStreamManager::GetHMACForMediaDeviceID(
- browser_context()->GetMediaDeviceIDSalt(),
- url::Origin::Create(GURL(kSecurityOrigin)), output_id);
- // Set up association between input and output so that the output
- // device gets selected when using session id:
- audio_manager_->CreateDeviceAssociation(input_id, output_id);
-
- // Authorize device for use and wait for completion.
- MockMediaStreamProviderListener listener;
- media_stream_manager_->audio_input_device_manager()->RegisterListener(
- &listener);
-
- int session_id = media_stream_manager_->audio_input_device_manager()->Open(
- MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, input_id,
- "Fake input device"));
-
- // Block for completion.
- base::RunLoop loop;
- EXPECT_CALL(listener, Opened(MEDIA_DEVICE_AUDIO_CAPTURE, session_id))
- .WillOnce(InvokeWithoutArgs(&loop, &base::RunLoop::Quit));
- loop.Run();
- media_stream_manager_->audio_input_device_manager()->UnregisterListener(
- &listener);
-
- // Send a create stream message to the audio output stream and wait until
- // we receive the created message.
- media::AudioParameters params(
- media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16,
- media::AudioParameters::kAudioCDSampleRate / 10);
-
- EXPECT_CALL(*host_.get(),
- OnDeviceAuthorized(kStreamId, media::OUTPUT_DEVICE_STATUS_OK, _,
- hashed_output_id))
- .Times(1);
- EXPECT_CALL(*host_.get(), WasNotifiedOfCreation(kStreamId));
- EXPECT_CALL(
- mirroring_manager_,
- AddDiverter(process()->GetID(), main_rfh()->GetRoutingID(), NotNull()))
- .RetiresOnSaturation();
- EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
- .RetiresOnSaturation();
-
- host_->OnRequestDeviceAuthorization(
- kStreamId, main_rfh()->GetRoutingID(), session_id,
- /*device id*/ std::string(), security_origin);
-
- auth_run_loop_->Run();
-
- host_->OnCreateStream(kStreamId, main_rfh()->GetRoutingID(), params);
-
- SyncWithAudioThread();
- }
-
- void Close() {
- // Send a message to AudioRendererHost to tell it we want to close the
- // stream.
- host_->OnCloseStream(kStreamId);
- SyncWithAudioThread();
- }
-
- void Play() {
- host_->OnPlayStream(kStreamId);
- SyncWithAudioThread();
- }
-
- void Pause() {
- host_->OnPauseStream(kStreamId);
- SyncWithAudioThread();
- }
-
- void SetVolume(double volume) {
- host_->OnSetVolume(kStreamId, volume);
- SyncWithAudioThread();
- }
-
- void SimulateError() {
- EXPECT_EQ(1u, host_->delegates_.size())
- << "Calls Create() before calling this method";
-
- // Expect an error signal sent through IPC.
- EXPECT_CALL(*host_.get(), WasNotifiedOfError(kStreamId));
-
- // Simulate an error sent from the audio device.
- host_->OnStreamError(kStreamId);
- SyncWithAudioThread();
-
- // Expect the audio stream record is removed.
- EXPECT_EQ(0u, host_->delegates_.size());
- }
-
- // SyncWithAudioThread() waits until all pending tasks on the audio thread
- // are executed while also processing pending task in message_loop_ on the
- // current thread. It is used to synchronize with the audio thread when we are
- // closing an audio stream.
- void SyncWithAudioThread() {
- base::RunLoop().RunUntilIdle();
-
- base::RunLoop run_loop;
- audio_manager_->GetTaskRunner()->PostTask(
- FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
- run_loop.Run();
- }
-
- void AssertBadMsgReported() {
- // Bad messages can be reported either directly to the RPH or through the
- // ARH, so we check both of them.
- EXPECT_EQ(process()->bad_msg_count() + host_->bad_msg_count, 1);
- }
-
- private:
- media::FakeAudioLogFactory log_factory_;
- std::unique_ptr<FakeAudioManagerWithAssociations> audio_manager_;
- std::unique_ptr<media::AudioSystem> audio_system_;
- std::unique_ptr<MediaStreamManager> media_stream_manager_;
- MockAudioMirroringManager mirroring_manager_;
- std::unique_ptr<base::RunLoop> auth_run_loop_;
- scoped_refptr<MockAudioRendererHost> host_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
-};
-
-TEST_F(AudioRendererHostTest, CreateAndClose) {
- Create();
- Close();
-}
-
-// Simulate the case where a stream is not properly closed.
-TEST_F(AudioRendererHostTest, CreateAndShutdown) {
- Create();
-}
-
-TEST_F(AudioRendererHostTest, CreatePlayAndClose) {
- Create();
- Play();
- Close();
-}
-
-TEST_F(AudioRendererHostTest, CreatePlayPauseAndClose) {
- Create();
- Play();
- Pause();
- Close();
-}
-
-TEST_F(AudioRendererHostTest, SetVolume) {
- Create();
- SetVolume(0.5);
- Play();
- Pause();
- Close();
-}
-
-// Simulate the case where a stream is not properly closed.
-TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) {
- Create();
- Play();
-}
-
-// Simulate the case where a stream is not properly closed.
-TEST_F(AudioRendererHostTest, CreatePlayPauseAndShutdown) {
- Create();
- Play();
- Pause();
-}
-
-TEST_F(AudioRendererHostTest, SimulateError) {
- Create();
- Play();
- SimulateError();
-}
-
-// Simulate the case when an error is generated on the browser process,
-// the audio device is closed but the render process try to close the
-// audio stream again.
-TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
- Create();
- Play();
- SimulateError();
- Close();
-}
-
-TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
- CreateUnifiedStream(url::Origin::Create(GURL(kSecurityOrigin)));
- Close();
-}
-
-TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) {
- Create(kBadDeviceId, url::Origin::Create(GURL(kSecurityOrigin)), true, true);
- Close();
-}
-
-TEST_F(AudioRendererHostTest, CreateAuthorizedDevice) {
- OverrideDevicePermissions(true);
- std::string id = GetNondefaultIdExpectedToPassPermissionsCheck();
- std::string hashed_id = MediaStreamManager::GetHMACForMediaDeviceID(
- browser_context()->GetMediaDeviceIDSalt(),
- url::Origin::Create(GURL(kSecurityOrigin)), id);
- Create(hashed_id, url::Origin::Create(GURL(kSecurityOrigin)), true, true);
- Close();
-}
-
-TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) {
- CreateWithoutWaitingForAuth(kBadDeviceId);
- Close();
- AssertBadMsgReported();
-}
-
-TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
- Create(kInvalidDeviceId, url::Origin::Create(GURL(kSecurityOrigin)), true,
- true);
- Close();
-}
-
-TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) {
- CreateWithInvalidRenderFrameId();
- Close();
-}
-
-// TODO(hclam): Add tests for data conversation in low latency mode.
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_service_listener.cc b/chromium/content/browser/renderer_host/media/audio_service_listener.cc
new file mode 100644
index 00000000000..08157dce240
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener.cc
@@ -0,0 +1,206 @@
+// 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/renderer_host/media/audio_service_listener.h"
+
+#include <utility>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/default_tick_clock.h"
+#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/child_process_termination_info.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+
+namespace content {
+
+AudioServiceListener::Metrics::Metrics(const base::TickClock* clock)
+ : clock_(clock), initial_downtime_start_(clock_->NowTicks()) {}
+
+AudioServiceListener::Metrics::~Metrics() = default;
+
+void AudioServiceListener::Metrics::ServiceAlreadyRunning() {
+ LogServiceStartStatus(ServiceStartStatus::kAlreadyStarted);
+ started_ = clock_->NowTicks();
+ initial_downtime_start_ = base::TimeTicks();
+}
+
+void AudioServiceListener::Metrics::ServiceCreated() {
+ DCHECK(created_.is_null());
+ created_ = clock_->NowTicks();
+}
+
+void AudioServiceListener::Metrics::ServiceStarted() {
+ started_ = clock_->NowTicks();
+
+ // |created_| is uninitialized if OnServiceCreated() was called before the
+ // listener is initialized with OnInit() call.
+ if (!created_.is_null()) {
+ LogServiceStartStatus(ServiceStartStatus::kSuccess);
+ UMA_HISTOGRAM_TIMES("Media.AudioService.ObservedStartupTime",
+ started_ - created_);
+ created_ = base::TimeTicks();
+ }
+
+ if (!initial_downtime_start_.is_null()) {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioService.ObservedInitialDowntime",
+ started_ - initial_downtime_start_,
+ base::TimeDelta(), base::TimeDelta::FromDays(7),
+ 50);
+ initial_downtime_start_ = base::TimeTicks();
+ }
+
+ if (!stopped_.is_null()) {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioService.ObservedDowntime2",
+ started_ - stopped_, base::TimeDelta(),
+ base::TimeDelta::FromDays(7), 50);
+ stopped_ = base::TimeTicks();
+ }
+}
+
+void AudioServiceListener::Metrics::ServiceFailedToStart() {
+ LogServiceStartStatus(ServiceStartStatus::kFailure);
+ created_ = base::TimeTicks();
+}
+
+void AudioServiceListener::Metrics::ServiceStopped() {
+ stopped_ = clock_->NowTicks();
+
+ DCHECK(!started_.is_null());
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioService.ObservedUptime",
+ stopped_ - started_, base::TimeDelta(),
+ base::TimeDelta::FromDays(7), 50);
+ started_ = base::TimeTicks();
+}
+
+void AudioServiceListener::Metrics::ServiceProcessTerminated(
+ Metrics::ServiceProcessTerminationStatus status) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.AudioService.ObservedProcessTerminationStatus", status);
+}
+
+void AudioServiceListener::Metrics::LogServiceStartStatus(
+ Metrics::ServiceStartStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("Media.AudioService.ObservedStartStatus", status);
+}
+
+AudioServiceListener::AudioServiceListener(
+ std::unique_ptr<service_manager::Connector> connector)
+ : binding_(this),
+ metrics_(base::DefaultTickClock::GetInstance()) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (!connector)
+ return; // Happens in unittests.
+
+ service_manager::mojom::ServiceManagerPtr service_manager;
+ connector->BindInterface(service_manager::mojom::kServiceName,
+ &service_manager);
+ service_manager::mojom::ServiceManagerListenerPtr listener;
+ service_manager::mojom::ServiceManagerListenerRequest request(
+ mojo::MakeRequest(&listener));
+ service_manager->AddListener(std::move(listener));
+ binding_.Bind(std::move(request));
+ BrowserChildProcessObserver::Add(this);
+}
+
+AudioServiceListener::~AudioServiceListener() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ BrowserChildProcessObserver::Remove(this);
+}
+
+base::ProcessId AudioServiceListener::GetProcessId() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ return process_id_;
+}
+
+void AudioServiceListener::OnInit(
+ std::vector<service_manager::mojom::RunningServiceInfoPtr>
+ running_services) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ for (const service_manager::mojom::RunningServiceInfoPtr& instance :
+ running_services) {
+ if (instance->identity.name() == audio::mojom::kServiceName) {
+ process_id_ = instance->pid;
+ metrics_.ServiceAlreadyRunning();
+ break;
+ }
+ }
+}
+
+void AudioServiceListener::OnServiceCreated(
+ service_manager::mojom::RunningServiceInfoPtr service) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (service->identity.name() != audio::mojom::kServiceName)
+ return;
+ metrics_.ServiceCreated();
+}
+
+void AudioServiceListener::OnServiceStarted(
+ const ::service_manager::Identity& identity,
+ uint32_t pid) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (identity.name() != audio::mojom::kServiceName)
+ return;
+ process_id_ = pid;
+ metrics_.ServiceStarted();
+}
+
+void AudioServiceListener::OnServicePIDReceived(
+ const ::service_manager::Identity& identity,
+ uint32_t pid) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (identity.name() != audio::mojom::kServiceName)
+ return;
+ process_id_ = pid;
+}
+
+void AudioServiceListener::OnServiceFailedToStart(
+ const ::service_manager::Identity& identity) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (identity.name() != audio::mojom::kServiceName)
+ return;
+ metrics_.ServiceFailedToStart();
+}
+
+void AudioServiceListener::OnServiceStopped(
+ const ::service_manager::Identity& identity) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (identity.name() != audio::mojom::kServiceName)
+ return;
+ metrics_.ServiceStopped();
+}
+
+void AudioServiceListener::BrowserChildProcessHostDisconnected(
+ const ChildProcessData& data) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (base::GetProcId(data.handle) != process_id_)
+ return;
+ process_id_ = base::kNullProcessId;
+ metrics_.ServiceProcessTerminated(
+ Metrics::ServiceProcessTerminationStatus::kDisconnect);
+}
+
+void AudioServiceListener::BrowserChildProcessCrashed(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (base::GetProcId(data.handle) != process_id_)
+ return;
+ process_id_ = base::kNullProcessId;
+ metrics_.ServiceProcessTerminated(
+ Metrics::ServiceProcessTerminationStatus::kCrash);
+}
+
+void AudioServiceListener::BrowserChildProcessKilled(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+ if (base::GetProcId(data.handle) != process_id_)
+ return;
+ process_id_ = base::kNullProcessId;
+ metrics_.ServiceProcessTerminated(
+ Metrics::ServiceProcessTerminationStatus::kKill);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_service_listener.h b/chromium/content/browser/renderer_host/media/audio_service_listener.h
new file mode 100644
index 00000000000..60623985912
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener.h
@@ -0,0 +1,129 @@
+// 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_RENDERER_HOST_MEDIA_AUDIO_SERVICE_LISTENER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_SERVICE_LISTENER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/process/process_handle.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_child_process_observer.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/mojom/service_manager.mojom.h"
+
+namespace base {
+class TickClock;
+}
+
+namespace content {
+
+struct ChildProcessData;
+
+class CONTENT_EXPORT AudioServiceListener
+ : public service_manager::mojom::ServiceManagerListener,
+ public BrowserChildProcessObserver {
+ public:
+ class CONTENT_EXPORT Metrics {
+ public:
+ // Matches histogram enum AudioServiceStartStatus, entries (except kMaxEnum)
+ // must not be renumbered.
+ enum class ServiceStartStatus {
+ kAlreadyStarted = 0,
+ kSuccess = 1,
+ kFailure = 2,
+ kMaxValue = kFailure,
+ };
+
+ // Matches histogram enum AudioServiceProcessTerminationStatus, entries
+ // (except kMaxEnum) must not be renumbered.
+ enum class ServiceProcessTerminationStatus {
+ kDisconnect = 0,
+ kCrash = 1,
+ kKill = 2,
+ kMaxValue = kKill,
+ };
+
+ explicit Metrics(const base::TickClock* clock);
+ ~Metrics();
+
+ void ServiceAlreadyRunning();
+ void ServiceCreated();
+ void ServiceFailedToStart();
+ void ServiceStarted();
+ void ServiceStopped();
+ void ServiceProcessTerminated(ServiceProcessTerminationStatus status);
+
+ private:
+ void LogServiceStartStatus(ServiceStartStatus status);
+
+ const base::TickClock* clock_;
+ base::TimeTicks initial_downtime_start_;
+ base::TimeTicks created_;
+ base::TimeTicks started_;
+ base::TimeTicks stopped_;
+ DISALLOW_COPY_AND_ASSIGN(Metrics);
+ };
+
+ explicit AudioServiceListener(
+ std::unique_ptr<service_manager::Connector> connector);
+ ~AudioServiceListener() override;
+
+ base::ProcessId GetProcessId() const;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(AudioServiceListenerTest,
+ OnInitWithoutAudioService_ProcessIdNull);
+ FRIEND_TEST_ALL_PREFIXES(AudioServiceListenerTest,
+ OnInitWithAudioService_ProcessIdNotNull);
+ FRIEND_TEST_ALL_PREFIXES(AudioServiceListenerTest,
+ OnAudioServiceCreated_ProcessIdNotNull);
+ FRIEND_TEST_ALL_PREFIXES(
+ AudioServiceListenerTest,
+ AudioProcessDisconnected_LogProcessTerminationStatus_ProcessIdNull);
+ FRIEND_TEST_ALL_PREFIXES(
+ AudioServiceListenerTest,
+ AudioProcessCrashed_LogProcessTerminationStatus_ProcessIdNull);
+ FRIEND_TEST_ALL_PREFIXES(
+ AudioServiceListenerTest,
+ AudioProcessKilled_LogProcessTerminationStatus_ProcessIdNull);
+ FRIEND_TEST_ALL_PREFIXES(AudioServiceListenerTest,
+ StartService_LogStartStatus);
+
+ // service_manager::mojom::ServiceManagerListener implementation.
+ void OnInit(std::vector<service_manager::mojom::RunningServiceInfoPtr>
+ running_services) override;
+ void OnServiceCreated(
+ service_manager::mojom::RunningServiceInfoPtr service) override;
+ void OnServiceStarted(const ::service_manager::Identity& identity,
+ uint32_t pid) override;
+ void OnServicePIDReceived(const ::service_manager::Identity& identity,
+ uint32_t pid) override;
+ void OnServiceFailedToStart(
+ const ::service_manager::Identity& identity) override;
+ void OnServiceStopped(const ::service_manager::Identity& identity) override;
+
+ // BrowserChildProcessObserver implementation.
+ void BrowserChildProcessHostDisconnected(const ChildProcessData& data) final;
+ void BrowserChildProcessCrashed(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) final;
+ void BrowserChildProcessKilled(const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) final;
+
+ mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_;
+ base::ProcessId process_id_ = base::kNullProcessId;
+ Metrics metrics_;
+ SEQUENCE_CHECKER(owning_sequence_);
+
+ DISALLOW_COPY_AND_ASSIGN(AudioServiceListener);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_SERVICE_LISTENER_H_
diff --git a/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc b/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
new file mode 100644
index 00000000000..2afcfb7833b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/audio_service_listener_unittest.cc
@@ -0,0 +1,248 @@
+// 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/renderer_host/media/audio_service_listener.h"
+
+#include <utility>
+
+#include "base/process/kill.h"
+#include "base/test/histogram_tester.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/child_process_termination_info.h"
+#include "content/public/common/process_type.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/identity.h"
+#include "services/service_manager/public/mojom/service_manager.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using RunningServiceInfoPtr = service_manager::mojom::RunningServiceInfoPtr;
+
+namespace content {
+
+namespace {
+
+RunningServiceInfoPtr MakeTestServiceInfo(
+ const service_manager::Identity& identity,
+ uint32_t pid) {
+ RunningServiceInfoPtr info(service_manager::mojom::RunningServiceInfo::New());
+ info->identity = identity;
+ info->pid = pid;
+ return info;
+}
+
+} // namespace
+
+struct AudioServiceListenerMetricsTest : public testing::Test {
+ AudioServiceListenerMetricsTest() {
+ test_clock.SetNowTicks(base::TimeTicks::Now());
+ }
+
+ base::SimpleTestTickClock test_clock;
+ base::HistogramTester histogram_tester;
+};
+
+TEST_F(AudioServiceListenerMetricsTest,
+ ServiceCreatedStartedStopped_LogsStartupTime_LogsUptime) {
+ AudioServiceListener::Metrics metrics(&test_clock);
+ metrics.ServiceCreated();
+ test_clock.Advance(base::TimeDelta::FromMilliseconds(42));
+ metrics.ServiceStarted();
+ histogram_tester.ExpectTimeBucketCount(
+ "Media.AudioService.ObservedStartupTime",
+ base::TimeDelta::FromMilliseconds(42), 1);
+ test_clock.Advance(base::TimeDelta::FromDays(2));
+ metrics.ServiceStopped();
+ histogram_tester.ExpectTimeBucketCount("Media.AudioService.ObservedUptime",
+ base::TimeDelta::FromDays(2), 1);
+
+ test_clock.Advance(base::TimeDelta::FromHours(5));
+ metrics.ServiceCreated();
+ metrics.ServiceStarted();
+ histogram_tester.ExpectTimeBucketCount("Media.AudioService.ObservedDowntime2",
+ base::TimeDelta::FromHours(5), 1);
+}
+
+TEST_F(AudioServiceListenerMetricsTest,
+ CreateMetricsStartService_LogsInitialDowntime) {
+ AudioServiceListener::Metrics metrics(&test_clock);
+ test_clock.Advance(base::TimeDelta::FromHours(12));
+ metrics.ServiceStarted();
+ histogram_tester.ExpectTimeBucketCount(
+ "Media.AudioService.ObservedInitialDowntime",
+ base::TimeDelta::FromHours(12), 1);
+}
+
+TEST_F(AudioServiceListenerMetricsTest,
+ ServiceAlreadyRunningStopService_LogsUptime) {
+ AudioServiceListener::Metrics metrics(&test_clock);
+ metrics.ServiceAlreadyRunning();
+ test_clock.Advance(base::TimeDelta::FromMinutes(42));
+ metrics.ServiceStopped();
+ histogram_tester.ExpectTimeBucketCount("Media.AudioService.ObservedUptime",
+ base::TimeDelta::FromMinutes(42), 1);
+}
+
+TEST_F(AudioServiceListenerMetricsTest,
+ ServiceAlreadyRunningCreateService_LogsStartupTime) {
+ AudioServiceListener::Metrics metrics(&test_clock);
+ metrics.ServiceAlreadyRunning();
+ test_clock.Advance(base::TimeDelta::FromMilliseconds(2));
+ metrics.ServiceCreated();
+ test_clock.Advance(base::TimeDelta::FromMilliseconds(20));
+ metrics.ServiceStarted();
+ histogram_tester.ExpectTimeBucketCount(
+ "Media.AudioService.ObservedStartupTime",
+ base::TimeDelta::FromMilliseconds(20), 1);
+}
+
+// Check that if service was already started and ServiceStarted() is called,
+// ObservedStartupTime and ObservedInitialDowntime are not logged and start time
+// is reset.
+TEST_F(AudioServiceListenerMetricsTest,
+ ServiceAlreadyRunningStartService_ResetStartTime) {
+ AudioServiceListener::Metrics metrics(&test_clock);
+ metrics.ServiceAlreadyRunning();
+ test_clock.Advance(base::TimeDelta::FromMilliseconds(20));
+ metrics.ServiceStarted();
+ histogram_tester.ExpectTotalCount("Media.AudioService.ObservedStartupTime",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "Media.AudioService.ObservedInitialDowntime", 0);
+ test_clock.Advance(base::TimeDelta::FromMilliseconds(200));
+ metrics.ServiceStopped();
+ histogram_tester.ExpectTimeBucketCount("Media.AudioService.ObservedUptime",
+ base::TimeDelta::FromMilliseconds(200),
+ 1);
+}
+
+TEST(AudioServiceListenerTest, StartService_LogStartStatus) {
+ base::HistogramTester histogram_tester;
+ AudioServiceListener audio_service_listener(nullptr);
+ service_manager::Identity audio_service_identity(audio::mojom::kServiceName);
+ constexpr base::ProcessId pid(42);
+
+ std::vector<RunningServiceInfoPtr> instances;
+ instances.push_back(MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnInit(std::move(instances));
+ histogram_tester.ExpectBucketCount(
+ "Media.AudioService.ObservedStartStatus",
+ static_cast<int>(
+ AudioServiceListener::Metrics::ServiceStartStatus::kAlreadyStarted),
+ 1);
+ audio_service_listener.OnServiceStopped(audio_service_identity);
+
+ audio_service_listener.OnServiceCreated(
+ MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnServiceStarted(audio_service_identity, pid);
+ histogram_tester.ExpectBucketCount(
+ "Media.AudioService.ObservedStartStatus",
+ static_cast<int>(
+ AudioServiceListener::Metrics::ServiceStartStatus::kSuccess),
+ 1);
+ audio_service_listener.OnServiceStopped(audio_service_identity);
+
+ audio_service_listener.OnServiceCreated(
+ MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnServiceFailedToStart(audio_service_identity);
+ histogram_tester.ExpectBucketCount(
+ "Media.AudioService.ObservedStartStatus",
+ static_cast<int>(
+ AudioServiceListener::Metrics::ServiceStartStatus::kFailure),
+ 1);
+}
+
+TEST(AudioServiceListenerTest, OnInitWithoutAudioService_ProcessIdNull) {
+ AudioServiceListener audio_service_listener(nullptr);
+ service_manager::Identity id("id1");
+ constexpr base::ProcessId pid(42);
+ std::vector<RunningServiceInfoPtr> instances;
+ instances.push_back(MakeTestServiceInfo(id, pid));
+ audio_service_listener.OnInit(std::move(instances));
+ EXPECT_EQ(base::kNullProcessId, audio_service_listener.GetProcessId());
+}
+
+TEST(AudioServiceListenerTest, OnInitWithAudioService_ProcessIdNotNull) {
+ AudioServiceListener audio_service_listener(nullptr);
+ service_manager::Identity audio_service_identity(audio::mojom::kServiceName);
+ constexpr base::ProcessId pid(42);
+ std::vector<RunningServiceInfoPtr> instances;
+ instances.push_back(MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnInit(std::move(instances));
+ EXPECT_EQ(pid, audio_service_listener.GetProcessId());
+}
+
+TEST(AudioServiceListenerTest, OnAudioServiceCreated_ProcessIdNotNull) {
+ AudioServiceListener audio_service_listener(nullptr);
+ service_manager::Identity audio_service_identity(audio::mojom::kServiceName);
+ constexpr base::ProcessId pid(42);
+ audio_service_listener.OnServiceCreated(
+ MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnServiceStarted(audio_service_identity, pid);
+ EXPECT_EQ(pid, audio_service_listener.GetProcessId());
+}
+
+TEST(AudioServiceListenerTest,
+ AudioProcessDisconnected_LogProcessTerminationStatus_ProcessIdNull) {
+ base::HistogramTester histogram_tester;
+ AudioServiceListener audio_service_listener(nullptr);
+ service_manager::Identity audio_service_identity(audio::mojom::kServiceName);
+ base::ProcessHandle handle = base::GetCurrentProcessHandle();
+ base::ProcessId pid = base::GetCurrentProcId();
+ audio_service_listener.OnServiceCreated(
+ MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnServiceStarted(audio_service_identity, pid);
+ ChildProcessData data(content::ProcessType::PROCESS_TYPE_UTILITY);
+ data.handle = handle;
+ audio_service_listener.BrowserChildProcessHostDisconnected(data);
+ histogram_tester.ExpectUniqueSample(
+ "Media.AudioService.ObservedProcessTerminationStatus",
+ AudioServiceListener::Metrics::ServiceProcessTerminationStatus::
+ kDisconnect,
+ 1);
+ EXPECT_EQ(base::kNullProcessId, audio_service_listener.GetProcessId());
+}
+
+TEST(AudioServiceListenerTest,
+ AudioProcessCrashed_LogProcessTerminationStatus_ProcessIdNull) {
+ base::HistogramTester histogram_tester;
+ AudioServiceListener audio_service_listener(nullptr);
+ service_manager::Identity audio_service_identity(audio::mojom::kServiceName);
+ base::ProcessHandle handle = base::GetCurrentProcessHandle();
+ base::ProcessId pid = base::GetCurrentProcId();
+ audio_service_listener.OnServiceCreated(
+ MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnServiceStarted(audio_service_identity, pid);
+ ChildProcessData data(content::ProcessType::PROCESS_TYPE_UTILITY);
+ data.handle = handle;
+ audio_service_listener.BrowserChildProcessCrashed(
+ data, content::ChildProcessTerminationInfo());
+ histogram_tester.ExpectUniqueSample(
+ "Media.AudioService.ObservedProcessTerminationStatus",
+ AudioServiceListener::Metrics::ServiceProcessTerminationStatus::kCrash,
+ 1);
+ EXPECT_EQ(base::kNullProcessId, audio_service_listener.GetProcessId());
+}
+
+TEST(AudioServiceListenerTest,
+ AudioProcessKilled_LogProcessTerminationStatus_ProcessIdNull) {
+ base::HistogramTester histogram_tester;
+ AudioServiceListener audio_service_listener(nullptr);
+ service_manager::Identity audio_service_identity(audio::mojom::kServiceName);
+ base::ProcessHandle handle = base::GetCurrentProcessHandle();
+ base::ProcessId pid = base::GetCurrentProcId();
+ audio_service_listener.OnServiceCreated(
+ MakeTestServiceInfo(audio_service_identity, pid));
+ audio_service_listener.OnServiceStarted(audio_service_identity, pid);
+ ChildProcessData data(content::ProcessType::PROCESS_TYPE_UTILITY);
+ data.handle = handle;
+ audio_service_listener.BrowserChildProcessKilled(
+ data, content::ChildProcessTerminationInfo());
+ histogram_tester.ExpectUniqueSample(
+ "Media.AudioService.ObservedProcessTerminationStatus",
+ AudioServiceListener::Metrics::ServiceProcessTerminationStatus::kKill, 1);
+ EXPECT_EQ(base::kNullProcessId, audio_service_listener.GetProcessId());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc b/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
index 7a2844ab539..628044df907 100644
--- a/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
+++ b/chromium/content/browser/renderer_host/media/in_process_launched_video_capture_device.cc
@@ -7,6 +7,7 @@
#include "base/bind_helpers.h"
#include "base/metrics/histogram_macros.h"
#include "content/public/browser/browser_thread.h"
+#include "media/media_buildflags.h"
#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID)
#include "content/browser/media/capture/desktop_capture_device.h"
@@ -145,8 +146,7 @@ void InProcessLaunchedVideoCaptureDevice::
gfx::NativeViewId window_id,
base::OnceClosure done_cb) {
DCHECK(device_task_runner_->BelongsToCurrentThread());
-#if defined(ENABLE_SCREEN_CAPTURE) && BUILDFLAG(ENABLE_WEBRTC) && \
- !defined(OS_ANDROID)
+#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID)
DesktopCaptureDevice* desktop_device =
static_cast<DesktopCaptureDevice*>(device);
desktop_device->SetNotificationWindowId(window_id);
diff --git a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
index 934e7ba490d..3e68e40eed4 100644
--- a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
+++ b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -27,11 +27,9 @@
#else
#include "content/browser/media/capture/web_contents_video_capture_device.h"
#if defined(USE_AURA)
-#include "content/browser/media/capture/desktop_capture_device_aura.h"
+#include "content/browser/media/capture/aura_window_video_capture_device.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
#include "content/browser/media/capture/desktop_capture_device.h"
-#endif
#endif // defined(OS_ANDROID)
#endif // defined(ENABLE_SCREEN_CAPTURE)
@@ -129,6 +127,13 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
case MEDIA_DESKTOP_VIDEO_CAPTURE: {
const DesktopMediaID desktop_id = DesktopMediaID::Parse(device_id);
+ if (desktop_id.is_null()) {
+ DLOG(ERROR) << "Desktop media ID is null";
+ start_capture_closure =
+ base::BindOnce(std::move(after_start_capture_callback), nullptr);
+ break;
+ }
+
#if !defined(OS_ANDROID)
if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
after_start_capture_callback = base::BindOnce(
@@ -154,6 +159,19 @@ void InProcessVideoCaptureDeviceLauncher::LaunchDeviceAsync(
break;
}
#endif // !defined(OS_ANDROID)
+
+#if defined(USE_AURA)
+ if (desktop_id.aura_id != DesktopMediaID::kNullId) {
+ start_capture_closure = base::BindOnce(
+ &InProcessVideoCaptureDeviceLauncher::
+ DoStartAuraWindowCaptureOnDeviceThread,
+ base::Unretained(this), desktop_id, params, std::move(receiver),
+ std::move(after_start_capture_callback));
+ break;
+ }
+#endif // defined(USE_AURA)
+
+ // All cases other than tab capture or Aura desktop/window capture.
start_capture_closure = base::BindOnce(
&InProcessVideoCaptureDeviceLauncher::
DoStartDesktopCaptureOnDeviceThread,
@@ -284,6 +302,41 @@ void InProcessVideoCaptureDeviceLauncher::DoStartTabCaptureOnDeviceThread(
}
#endif // !defined(OS_ANDROID)
+#if defined(USE_AURA)
+void InProcessVideoCaptureDeviceLauncher::
+ DoStartAuraWindowCaptureOnDeviceThread(
+ const DesktopMediaID& device_id,
+ const media::VideoCaptureParams& params,
+ std::unique_ptr<media::VideoFrameReceiver> receiver,
+ ReceiveDeviceCallback result_callback) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
+ DCHECK(device_task_runner_->BelongsToCurrentThread());
+
+ auto video_capture_device =
+ std::make_unique<AuraWindowVideoCaptureDevice>(device_id);
+ if (video_capture_device) {
+ video_capture_device->AllocateAndStartWithReceiver(params,
+ std::move(receiver));
+ switch (device_id.type) {
+ case DesktopMediaID::TYPE_SCREEN:
+ IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED);
+ IncrementDesktopCaptureCounter(
+ device_id.audio_share ? SCREEN_CAPTURER_CREATED_WITH_AUDIO
+ : SCREEN_CAPTURER_CREATED_WITHOUT_AUDIO);
+ break;
+ case DesktopMediaID::TYPE_WINDOW:
+ IncrementDesktopCaptureCounter(WINDOW_CAPTURER_CREATED);
+ break;
+ case DesktopMediaID::TYPE_NONE:
+ case DesktopMediaID::TYPE_WEB_CONTENTS:
+ NOTREACHED();
+ break;
+ }
+ }
+ std::move(result_callback).Run(std::move(video_capture_device));
+}
+#endif // defined(USE_AURA)
+
void InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread(
const DesktopMediaID& desktop_id,
const media::VideoCaptureParams& params,
@@ -291,24 +344,14 @@ void InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread(
ReceiveDeviceCallback result_callback) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(device_task_runner_->BelongsToCurrentThread());
-
- if (desktop_id.is_null()) {
- DLOG(ERROR) << "Desktop media ID is null";
- std::move(result_callback).Run(nullptr);
- return;
- }
+ DCHECK(!desktop_id.is_null());
std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
#if defined(OS_ANDROID)
video_capture_device = std::make_unique<ScreenCaptureDeviceAndroid>();
#else
-#if defined(USE_AURA)
- video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id);
-#endif // defined(USE_AURA)
-#if BUILDFLAG(ENABLE_WEBRTC)
if (!video_capture_device)
video_capture_device = DesktopCaptureDevice::Create(desktop_id);
-#endif // BUILDFLAG(ENABLE_WEBRTC)
#endif // defined (OS_ANDROID)
if (video_capture_device)
diff --git a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
index dfc21c8be97..b2919080aff 100644
--- a/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
+++ b/chromium/content/browser/renderer_host/media/in_process_video_capture_device_launcher.h
@@ -71,6 +71,12 @@ class InProcessVideoCaptureDeviceLauncher : public VideoCaptureDeviceLauncher {
std::unique_ptr<media::VideoFrameReceiver> receiver,
ReceiveDeviceCallback result_callback);
+ void DoStartAuraWindowCaptureOnDeviceThread(
+ const DesktopMediaID& device_id,
+ const media::VideoCaptureParams& params,
+ std::unique_ptr<media::VideoFrameReceiver> receiver,
+ ReceiveDeviceCallback result_callback);
+
void DoStartDesktopCaptureOnDeviceThread(
const DesktopMediaID& desktop_id,
const media::VideoCaptureParams& params,
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
index 07bcb4cd97b..6818c2288c5 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -72,7 +72,6 @@ MediaDevicesDispatcherHost::MediaDevicesDispatcherHost(
MediaStreamManager* media_stream_manager)
: render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
- group_id_salt_base_(BrowserContext::CreateRandomMediaDeviceIDSalt()),
media_stream_manager_(media_stream_manager),
num_pending_audio_input_parameters_(0),
weak_factory_(this) {
@@ -112,9 +111,8 @@ void MediaDevicesDispatcherHost::EnumerateDevices(
devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = request_audio_output;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
- render_process_id_, render_frame_id_, group_id_salt_base_,
- devices_to_enumerate, request_video_input_capabilities,
- std::move(client_callback));
+ render_process_id_, render_frame_id_, devices_to_enumerate,
+ request_video_input_capabilities, std::move(client_callback));
}
void MediaDevicesDispatcherHost::GetVideoInputCapabilities(
@@ -175,68 +173,64 @@ void MediaDevicesDispatcherHost::AddMediaDevicesListener(
devices_to_subscribe[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = subscribe_video_input;
devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = subscribe_audio_output;
- uint32_t subscription_id =
- media_stream_manager_->media_devices_manager()
- ->SubscribeDeviceChangeNotifications(
- render_process_id_, render_frame_id_, group_id_salt_base_,
- devices_to_subscribe, std::move(listener));
+ uint32_t subscription_id = media_stream_manager_->media_devices_manager()
+ ->SubscribeDeviceChangeNotifications(
+ render_process_id_, render_frame_id_,
+ devices_to_subscribe, std::move(listener));
subscription_ids_.push_back(subscription_id);
}
void MediaDevicesDispatcherHost::GetDefaultVideoInputDeviceID(
GetVideoInputCapabilitiesCallback client_callback,
- const std::pair<std::string, url::Origin>& salt_and_origin) {
+ MediaDeviceSaltAndOrigin salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
GetDefaultMediaDeviceID(
MEDIA_DEVICE_TYPE_VIDEO_INPUT, render_process_id_, render_frame_id_,
base::Bind(&MediaDevicesDispatcherHost::GotDefaultVideoInputDeviceID,
weak_factory_.GetWeakPtr(), base::Passed(&client_callback),
- salt_and_origin.first, salt_and_origin.second));
+ std::move(salt_and_origin)));
}
void MediaDevicesDispatcherHost::GotDefaultVideoInputDeviceID(
GetVideoInputCapabilitiesCallback client_callback,
- std::string device_id_salt,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
const std::string& default_device_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- media_stream_manager_->video_capture_manager()->EnumerateDevices(
+ MediaDevicesManager::BoolDeviceTypes requested_types;
+ // Also request audio devices to make sure the heuristic to determine
+ // the video group ID works.
+ requested_types[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+ media_stream_manager_->media_devices_manager()->EnumerateDevices(
+ requested_types,
base::Bind(&MediaDevicesDispatcherHost::FinalizeGetVideoInputCapabilities,
weak_factory_.GetWeakPtr(), base::Passed(&client_callback),
- std::move(device_id_salt), security_origin,
- std::move(default_device_id)));
+ std::move(salt_and_origin), std::move(default_device_id)));
}
void MediaDevicesDispatcherHost::FinalizeGetVideoInputCapabilities(
GetVideoInputCapabilitiesCallback client_callback,
- const std::string& device_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
const std::string& default_device_id,
- const media::VideoCaptureDeviceDescriptors& device_descriptors) {
+ const MediaDeviceEnumeration& enumeration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities;
- for (const auto& descriptor : device_descriptors) {
- std::string hmac_device_id = GetHMACForMediaDeviceID(
- device_id_salt, security_origin, descriptor.device_id);
+ for (const auto& device_info : enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) {
+ std::string hmac_device_id =
+ GetHMACForMediaDeviceID(salt_and_origin.device_id_salt,
+ salt_and_origin.origin, device_info.device_id);
+ std::string hmac_group_id =
+ GetHMACForMediaDeviceID(salt_and_origin.group_id_salt,
+ salt_and_origin.origin, device_info.group_id);
blink::mojom::VideoInputDeviceCapabilitiesPtr capabilities =
blink::mojom::VideoInputDeviceCapabilities::New();
capabilities->device_id = std::move(hmac_device_id);
+ capabilities->group_id = std::move(hmac_group_id);
capabilities->formats =
media_stream_manager_->media_devices_manager()->GetVideoInputFormats(
- descriptor.device_id, true /* try_in_use_first */);
- capabilities->facing_mode = descriptor.facing;
-#if defined(OS_ANDROID)
- // On Android, the facing mode is not available in the |facing| field,
- // but is available as part of the label.
- // TODO(guidou): Remove this code once the |facing| field is supported
- // on Android. See http://crbug.com/672856.
- if (descriptor.GetNameAndModel().find("front") != std::string::npos)
- capabilities->facing_mode = media::MEDIA_VIDEO_FACING_USER;
- else if (descriptor.GetNameAndModel().find("back") != std::string::npos)
- capabilities->facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
-#endif
- if (descriptor.device_id == default_device_id) {
+ device_info.device_id, true /* try_in_use_first */);
+ capabilities->facing_mode = device_info.video_facing;
+ if (device_info.device_id == default_device_id) {
video_input_capabilities.insert(video_input_capabilities.begin(),
std::move(capabilities));
} else {
@@ -267,12 +261,13 @@ void MediaDevicesDispatcherHost::EnumerateVideoDevicesForFormats(
GetVideoInputDeviceFormatsCallback client_callback,
const std::string& device_id,
bool try_in_use_first,
- const std::pair<std::string, url::Origin>& salt_and_origin) {
+ const MediaDeviceSaltAndOrigin& salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
media_stream_manager_->video_capture_manager()->EnumerateDevices(base::Bind(
&MediaDevicesDispatcherHost::FinalizeGetVideoInputDeviceFormats,
weak_factory_.GetWeakPtr(), base::Passed(&client_callback), device_id,
- try_in_use_first, salt_and_origin.first, salt_and_origin.second));
+ try_in_use_first, salt_and_origin.device_id_salt,
+ salt_and_origin.origin));
}
void MediaDevicesDispatcherHost::FinalizeGetVideoInputDeviceFormats(
@@ -304,11 +299,11 @@ struct MediaDevicesDispatcherHost::AudioInputCapabilitiesRequest {
void MediaDevicesDispatcherHost::GetDefaultAudioInputDeviceID(
GetAudioInputCapabilitiesCallback client_callback,
- const std::pair<std::string, url::Origin>& salt_and_origin) {
+ const MediaDeviceSaltAndOrigin& salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
pending_audio_input_capabilities_requests_.push_back(
- AudioInputCapabilitiesRequest{salt_and_origin.first,
- salt_and_origin.second,
+ AudioInputCapabilitiesRequest{salt_and_origin.device_id_salt,
+ salt_and_origin.origin,
std::move(client_callback)});
if (pending_audio_input_capabilities_requests_.size() > 1U)
return;
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h
index 6098e6167c8..f112b464de8 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host.h
@@ -63,24 +63,22 @@ class CONTENT_EXPORT MediaDevicesDispatcherHost
void GetDefaultVideoInputDeviceID(
GetVideoInputCapabilitiesCallback client_callback,
- const std::pair<std::string, url::Origin>& salt_and_origin);
+ MediaDeviceSaltAndOrigin salt_and_origin);
void GotDefaultVideoInputDeviceID(
GetVideoInputCapabilitiesCallback client_callback,
- std::string device_id_salt,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
const std::string& default_device_id);
void FinalizeGetVideoInputCapabilities(
GetVideoInputCapabilitiesCallback client_callback,
- const std::string& device_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
const std::string& default_device_id,
- const media::VideoCaptureDeviceDescriptors& device_descriptors);
+ const MediaDeviceEnumeration& enumeration);
void GetDefaultAudioInputDeviceID(
GetAudioInputCapabilitiesCallback client_callback,
- const std::pair<std::string, url::Origin>& salt_and_origin);
+ const MediaDeviceSaltAndOrigin& salt_and_origin);
void GotDefaultAudioInputDeviceID(const std::string& default_device_id);
@@ -101,7 +99,7 @@ class CONTENT_EXPORT MediaDevicesDispatcherHost
GetVideoInputDeviceFormatsCallback client_callback,
const std::string& device_id,
bool try_in_use_first,
- const std::pair<std::string, url::Origin>& salt_and_origin);
+ const MediaDeviceSaltAndOrigin& salt_and_origin);
void FinalizeGetVideoInputDeviceFormats(
GetVideoInputDeviceFormatsCallback client_callback,
const std::string& device_id,
@@ -113,11 +111,6 @@ class CONTENT_EXPORT MediaDevicesDispatcherHost
// The following const fields can be accessed on any thread.
const int render_process_id_;
const int render_frame_id_;
- // This value is combined with the device ID salt to produce a salt for group
- // IDs that, unlike the device ID salt, is not persistent across browsing
- // sessions, but like the device ID salt, is reset when the user clears
- // browsing data.
- const std::string group_id_salt_base_;
// The following fields can only be accessed on the IO thread.
MediaStreamManager* media_stream_manager_;
diff --git a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
index 0647a6d80eb..228ef4575cb 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -375,9 +375,10 @@ class MediaDevicesDispatcherHostTest : public testing::TestWithParam<GURL> {
}
}
- std::pair<std::string, url::Origin> GetSaltAndOrigin(int /* process_id */,
- int /* frame_id */) {
- return std::make_pair(browser_context_->GetMediaDeviceIDSalt(), origin_);
+ MediaDeviceSaltAndOrigin GetSaltAndOrigin(int /* process_id */,
+ int /* frame_id */) {
+ return MediaDeviceSaltAndOrigin(browser_context_->GetMediaDeviceIDSalt(),
+ "fake_group_id_salt", origin_);
}
// The order of these members is important on teardown:
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager.cc b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
index ff76d268e72..93c8f2ba585 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.cc
@@ -10,8 +10,10 @@
#include <algorithm>
#include <string>
+#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
+#include "base/sequence_checker.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_checker.h"
@@ -20,11 +22,18 @@
#include "content/browser/media/media_devices_permission_checker.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/browser/service_manager/service_manager_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_system.h"
#include "media/base/media_switches.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/public/mojom/device_notifications.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/identity.h"
+#include "services/service_manager/public/mojom/connector.mojom-shared.h"
#if defined(OS_MACOSX)
#include "base/bind_helpers.h"
@@ -110,42 +119,53 @@ bool IsRealAudioDeviceID(const std::string& device_id) {
!media::AudioDeviceDescription::IsCommunicationsDevice(device_id);
}
+static bool EqualDeviceAndGroupID(const MediaDeviceInfo& lhs,
+ const MediaDeviceInfo& rhs) {
+ return lhs == rhs && lhs.group_id == rhs.group_id;
+}
+
} // namespace
std::string GuessVideoGroupID(const MediaDeviceInfoArray& audio_infos,
const MediaDeviceInfo& video_info) {
- std::string video_label = VideoLabelWithoutModelID(video_info.label);
+ const std::string video_label = VideoLabelWithoutModelID(video_info.label);
// If |video_label| is very small, do not guess in order to avoid false
// positives.
if (video_label.size() <= 3)
return video_info.device_id;
- std::function<bool(const MediaDeviceInfo&)>
- video_label_is_included_in_audio_label =
- [&video_label](const MediaDeviceInfo& audio_info) {
+ base::RepeatingCallback<bool(const MediaDeviceInfo&)>
+ video_label_is_included_in_audio_label = base::BindRepeating(
+ [](const std::string& video_label,
+ const MediaDeviceInfo& audio_info) {
return audio_info.label.find(video_label) != std::string::npos;
- };
+ },
+ base::ConstRef(video_label));
- bool video_has_usb_model = LabelHasUSBModel(video_info.label);
+ const bool video_has_usb_model = LabelHasUSBModel(video_info.label);
std::string video_usb_model = video_has_usb_model
? GetUSBModelFromLabel(video_info.label)
: std::string();
- std::function<bool(const MediaDeviceInfo&)> usb_model_matches =
- [video_has_usb_model,
- &video_usb_model](const MediaDeviceInfo& audio_info) {
- return video_has_usb_model && LabelHasUSBModel(audio_info.label)
- ? video_usb_model == GetUSBModelFromLabel(audio_info.label)
- : false;
- };
-
- for (auto* lambda :
+ base::RepeatingCallback<bool(const MediaDeviceInfo&)> usb_model_matches =
+ base::BindRepeating(
+ [](bool video_has_usb_model, const std::string& video_usb_model,
+ const MediaDeviceInfo& audio_info) {
+ return video_has_usb_model && LabelHasUSBModel(audio_info.label)
+ ? video_usb_model ==
+ GetUSBModelFromLabel(audio_info.label)
+ : false;
+ },
+ video_has_usb_model, base::ConstRef(video_usb_model));
+
+ for (auto* callback :
{&video_label_is_included_in_audio_label, &usb_model_matches}) {
// The label for the default and communication audio devices may contain the
// same label as the real devices, so they should be ignored when trying to
// find unique matches.
- auto real_device_matches = [lambda](const MediaDeviceInfo& audio_info) {
- return IsRealAudioDeviceID(audio_info.device_id) && (*lambda)(audio_info);
+ auto real_device_matches = [callback](const MediaDeviceInfo& audio_info) {
+ return IsRealAudioDeviceID(audio_info.device_id) &&
+ (*callback).Run(audio_info);
};
auto it_first = std::find_if(audio_infos.begin(), audio_infos.end(),
real_device_matches);
@@ -246,12 +266,10 @@ class MediaDevicesManager::CacheInfo {
MediaDevicesManager::SubscriptionRequest::SubscriptionRequest(
int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& subscribe_types,
blink::mojom::MediaDevicesListenerPtr listener)
: render_process_id(render_process_id),
render_frame_id(render_frame_id),
- group_id_salt_base(group_id_salt_base),
subscribe_types(subscribe_types),
listener(std::move(listener)) {}
@@ -264,6 +282,81 @@ MediaDevicesManager::SubscriptionRequest&
MediaDevicesManager::SubscriptionRequest::operator=(SubscriptionRequest&&) =
default;
+class MediaDevicesManager::AudioServiceDeviceListener
+ : public audio::mojom::DeviceListener {
+ public:
+ explicit AudioServiceDeviceListener(service_manager::Connector* connector)
+ : binding_(this), weak_factory_(this) {
+ TryConnectToService(connector);
+ }
+ ~AudioServiceDeviceListener() override = default;
+
+ void DevicesChanged() override {
+ auto* system_monitor = base::SystemMonitor::Get();
+ if (system_monitor)
+ system_monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
+ }
+
+ private:
+ void TryConnectToService(service_manager::Connector* connector) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Check if the service manager is managing the audio service.
+ connector->QueryService(
+ service_manager::Identity(audio::mojom::kServiceName),
+ base::BindOnce(&AudioServiceDeviceListener::ServiceQueried,
+ weak_factory_.GetWeakPtr(), connector));
+ }
+
+ void ServiceQueried(service_manager::Connector* connector,
+ service_manager::mojom::ConnectResult connect_result,
+ const std::string& ignore) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Do not connect if the service manager is not managing the audio service.
+ if (connect_result != service_manager::mojom::ConnectResult::SUCCEEDED) {
+ LOG(WARNING) << "Audio service not available: " << connect_result;
+ return;
+ }
+ DoConnectToService(connector);
+ }
+
+ void DoConnectToService(service_manager::Connector* connector) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!mojo_audio_device_notifier_);
+ DCHECK(!binding_);
+ connector->BindInterface(audio::mojom::kServiceName,
+ mojo::MakeRequest(&mojo_audio_device_notifier_));
+ mojo_audio_device_notifier_.set_connection_error_handler(base::BindOnce(
+ &MediaDevicesManager::AudioServiceDeviceListener::OnConnectionError,
+ weak_factory_.GetWeakPtr(), connector));
+ audio::mojom::DeviceListenerPtr audio_device_listener_ptr;
+ binding_.Bind(mojo::MakeRequest(&audio_device_listener_ptr));
+ mojo_audio_device_notifier_->RegisterListener(
+ std::move(audio_device_listener_ptr));
+ }
+
+ void OnConnectionError(service_manager::Connector* connector) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ mojo_audio_device_notifier_.reset();
+ binding_.Close();
+
+ // Resetting the error handler in a posted task since doing it synchronously
+ // results in a browser crash. See https://crbug.com/845142.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&AudioServiceDeviceListener::TryConnectToService,
+ weak_factory_.GetWeakPtr(), connector));
+ }
+
+ mojo::Binding<audio::mojom::DeviceListener> binding_;
+ audio::mojom::DeviceNotifierPtr mojo_audio_device_notifier_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<AudioServiceDeviceListener> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioServiceDeviceListener);
+};
+
MediaDevicesManager::MediaDevicesManager(
media::AudioSystem* audio_system,
const scoped_refptr<VideoCaptureManager>& video_capture_manager,
@@ -312,7 +405,6 @@ void MediaDevicesManager::EnumerateDevices(
void MediaDevicesManager::EnumerateDevices(
int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback) {
@@ -324,17 +416,17 @@ void MediaDevicesManager::EnumerateDevices(
render_frame_id),
base::BindOnce(&MediaDevicesManager::CheckPermissionsForEnumerateDevices,
weak_factory_.GetWeakPtr(), render_process_id,
- render_frame_id, group_id_salt_base, requested_types,
+ render_frame_id, requested_types,
request_video_input_capabilities, std::move(callback)));
}
uint32_t MediaDevicesManager::SubscribeDeviceChangeNotifications(
int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& subscribe_types,
blink::mojom::MediaDevicesListenerPtr listener) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ StartMonitoring();
uint32_t subscription_id = ++last_subscription_id_;
blink::mojom::MediaDevicesListenerPtr media_devices_listener =
std::move(listener);
@@ -342,9 +434,9 @@ uint32_t MediaDevicesManager::SubscribeDeviceChangeNotifications(
base::BindOnce(&MediaDevicesManager::UnsubscribeDeviceChangeNotifications,
weak_factory_.GetWeakPtr(), subscription_id));
subscriptions_.emplace(
- subscription_id, SubscriptionRequest(render_process_id, render_frame_id,
- group_id_salt_base, subscribe_types,
- std::move(media_devices_listener)));
+ subscription_id,
+ SubscriptionRequest(render_process_id, render_frame_id, subscribe_types,
+ std::move(media_devices_listener)));
return subscription_id;
}
@@ -384,6 +476,22 @@ void MediaDevicesManager::StartMonitoring() {
return;
#endif
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ if (base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess)) {
+ DCHECK(!audio_service_device_listener_);
+ if (!connector_) {
+ auto* connector = ServiceManagerContext::GetConnectorForIOThread();
+ // |connector| can be null on unit tests.
+ if (!connector)
+ return;
+
+ connector_ = connector->Clone();
+ }
+
+ audio_service_device_listener_ =
+ std::make_unique<AudioServiceDeviceListener>(connector_.get());
+ }
+#endif
monitoring_started_ = true;
base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
@@ -418,6 +526,7 @@ void MediaDevicesManager::StopMonitoring() {
if (!monitoring_started_)
return;
base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
+ audio_service_device_listener_.reset();
monitoring_started_ = false;
for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i)
SetCachePolicy(static_cast<MediaDeviceType>(i), CachePolicy::NO_CACHE);
@@ -505,81 +614,70 @@ void MediaDevicesManager::SetPermissionChecker(
void MediaDevicesManager::CheckPermissionsForEnumerateDevices(
int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
- const std::pair<std::string, url::Origin>& salt_and_origin) {
+ MediaDeviceSaltAndOrigin salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
permission_checker_->CheckPermissions(
requested_types, render_process_id, render_frame_id,
base::BindOnce(&MediaDevicesManager::OnPermissionsCheckDone,
- weak_factory_.GetWeakPtr(), group_id_salt_base,
- requested_types, request_video_input_capabilities,
- std::move(callback), salt_and_origin.first,
- salt_and_origin.second));
+ weak_factory_.GetWeakPtr(), requested_types,
+ request_video_input_capabilities, std::move(callback),
+ std::move(salt_and_origin)));
}
void MediaDevicesManager::OnPermissionsCheckDone(
- const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
- const std::string& device_id_salt,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
const MediaDevicesManager::BoolDeviceTypes& has_permissions) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // The video-capture subsystem currently does not support group IDs.
+ // If video input devices are requested, also request audio input devices in
+ // order to be able to use an heuristic that guesses group IDs for video
+ // devices by finding matches in audio input devices.
+ // TODO(crbug.com/627793): Remove |internal_requested_types| and use
+ // |requested_types| directly when video capture supports group IDs.
+ BoolDeviceTypes internal_requested_types;
+ internal_requested_types[MEDIA_DEVICE_TYPE_AUDIO_INPUT] =
+ requested_types[MEDIA_DEVICE_TYPE_AUDIO_INPUT] ||
+ requested_types[MEDIA_DEVICE_TYPE_VIDEO_INPUT];
+ internal_requested_types[MEDIA_DEVICE_TYPE_VIDEO_INPUT] =
+ requested_types[MEDIA_DEVICE_TYPE_VIDEO_INPUT];
+ internal_requested_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] =
+ requested_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT];
+
EnumerateDevices(
- requested_types,
+ internal_requested_types,
base::BindRepeating(&MediaDevicesManager::OnDevicesEnumerated,
- weak_factory_.GetWeakPtr(), group_id_salt_base,
- requested_types, request_video_input_capabilities,
- base::Passed(&callback), device_id_salt,
- security_origin, has_permissions));
+ weak_factory_.GetWeakPtr(), requested_types,
+ request_video_input_capabilities,
+ base::Passed(&callback), std::move(salt_and_origin),
+ has_permissions));
}
void MediaDevicesManager::OnDevicesEnumerated(
- const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
- const std::string& device_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
const MediaDevicesManager::BoolDeviceTypes& has_permissions,
const MediaDeviceEnumeration& enumeration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- std::string group_id_salt = group_id_salt_base + device_id_salt;
const bool video_input_capabilities_requested =
has_permissions[MEDIA_DEVICE_TYPE_VIDEO_INPUT] &&
request_video_input_capabilities;
- MediaDeviceInfoArray video_device_infos =
- enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT];
- for (auto& video_device_info : video_device_infos) {
- video_device_info.group_id = GuessVideoGroupID(
- enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT], video_device_info);
- }
-
std::vector<MediaDeviceInfoArray> result(NUM_MEDIA_DEVICE_TYPES);
for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
if (!requested_types[i])
continue;
- if (i == MEDIA_DEVICE_TYPE_VIDEO_INPUT) {
- for (const auto& device_info : video_device_infos) {
- MediaDeviceInfo translated_device_info = TranslateMediaDeviceInfo(
- has_permissions[i], device_id_salt, group_id_salt, security_origin,
- device_info);
- if (video_input_capabilities_requested)
- translated_device_info.video_facing = device_info.video_facing;
- result[i].push_back(translated_device_info);
- }
- } else {
- for (const auto& device_info : enumeration[i]) {
- result[i].push_back(TranslateMediaDeviceInfo(
- has_permissions[i], device_id_salt, group_id_salt, security_origin,
- device_info));
- }
+ for (const auto& device_info : enumeration[i]) {
+ result[i].push_back(TranslateMediaDeviceInfo(
+ has_permissions[i], salt_and_origin, device_info));
}
}
@@ -601,16 +699,6 @@ MediaDevicesManager::ComputeVideoInputCapabilities(
capabilities->formats = GetVideoInputFormats(device_info.device_id,
false /* try_in_use_first */);
capabilities->facing_mode = device_info.video_facing;
-#if defined(OS_ANDROID)
- // On Android, the facing mode is not available in the |facing| field,
- // but is available as part of the label.
- // TODO(guidou): Remove this code once the |facing| field is supported
- // on Android. See http://crbug.com/672856.
- if (device_info.label.find("front") != std::string::npos)
- capabilities->facing_mode = media::MEDIA_VIDEO_FACING_USER;
- else if (device_info.label.find("back") != std::string::npos)
- capabilities->facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
-#endif
video_input_capabilities.push_back(std::move(capabilities));
}
return video_input_capabilities;
@@ -708,19 +796,35 @@ void MediaDevicesManager::DevicesEnumerated(
void MediaDevicesManager::UpdateSnapshot(
MediaDeviceType type,
- const MediaDeviceInfoArray& new_snapshot) {
+ const MediaDeviceInfoArray& new_snapshot,
+ bool ignore_group_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(IsValidMediaDeviceType(type));
- // Only cache the device list when the device list has been changed.
bool need_update_device_change_subscribers = false;
MediaDeviceInfoArray& old_snapshot = current_snapshot_[type];
+ if (old_snapshot.size() != new_snapshot.size() &&
+ (type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
+ type == MEDIA_DEVICE_TYPE_VIDEO_INPUT)) {
+ StopRemovedDevices(type, new_snapshot);
+ }
+
+ // Update the cached snapshot and send notifications only if the device list
+ // has changed.
if (old_snapshot.size() != new_snapshot.size() ||
!std::equal(new_snapshot.begin(), new_snapshot.end(),
- old_snapshot.begin())) {
- if (type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
- type == MEDIA_DEVICE_TYPE_VIDEO_INPUT) {
+ old_snapshot.begin(),
+ ignore_group_id ? operator== : EqualDeviceAndGroupID)) {
+ // Prevent sending notifications until group IDs are updated using
+ // a heuristic in ProcessRequests().
+ // TODO(crbug.com/627793): Remove |is_video_with_group_ids| and the
+ // corresponding checks when the video-capture subsystem supports
+ // group IDs.
+ bool is_video_with_good_group_ids =
+ type == MEDIA_DEVICE_TYPE_VIDEO_INPUT &&
+ (new_snapshot.size() == 0 || !new_snapshot[0].group_id.empty());
+ if (type == MEDIA_DEVICE_TYPE_AUDIO_INPUT || is_video_with_good_group_ids) {
NotifyMediaStreamManager(type, new_snapshot);
}
@@ -728,7 +832,8 @@ void MediaDevicesManager::UpdateSnapshot(
// result, since it is not due to an actual device change.
need_update_device_change_subscribers =
has_seen_result_[type] &&
- (old_snapshot.size() != 0 || new_snapshot.size() != 0);
+ (old_snapshot.size() != 0 || new_snapshot.size() != 0) &&
+ (type != MEDIA_DEVICE_TYPE_VIDEO_INPUT || is_video_with_good_group_ids);
current_snapshot_[type] = new_snapshot;
}
@@ -738,6 +843,21 @@ void MediaDevicesManager::UpdateSnapshot(
void MediaDevicesManager::ProcessRequests() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Populate the group ID field for video devices using a heuristic that looks
+ // for device coincidences with audio input devices.
+ // TODO(crbug.com/627793): Remove this once the video-capture subsystem
+ // supports group IDs.
+ if (has_seen_result_[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) {
+ MediaDeviceInfoArray video_devices =
+ current_snapshot_[MEDIA_DEVICE_TYPE_VIDEO_INPUT];
+ for (auto& video_device_info : video_devices) {
+ video_device_info.group_id = GuessVideoGroupID(
+ current_snapshot_[MEDIA_DEVICE_TYPE_AUDIO_INPUT], video_device_info);
+ }
+ UpdateSnapshot(MEDIA_DEVICE_TYPE_VIDEO_INPUT, video_devices,
+ false /* ignore_group_id */);
+ }
+
requests_.erase(std::remove_if(requests_.begin(), requests_.end(),
[this](const EnumerationRequest& request) {
if (IsEnumerationRequestReady(request)) {
@@ -779,7 +899,7 @@ void MediaDevicesManager::HandleDevicesChanged(MediaDeviceType type) {
DoEnumerateDevices(type);
}
-void MediaDevicesManager::NotifyMediaStreamManager(
+void MediaDevicesManager::StopRemovedDevices(
MediaDeviceType type,
const MediaDeviceInfoArray& new_snapshot) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -800,6 +920,17 @@ void MediaDevicesManager::NotifyMediaStreamManager(
if (it == new_snapshot.end())
media_stream_manager_->StopRemovedDevice(type, old_device_info);
}
+}
+
+void MediaDevicesManager::NotifyMediaStreamManager(
+ MediaDeviceType type,
+ const MediaDeviceInfoArray& new_snapshot) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
+ type == MEDIA_DEVICE_TYPE_VIDEO_INPUT);
+
+ if (!media_stream_manager_)
+ return;
media_stream_manager_->NotifyDevicesChanged(type, new_snapshot);
}
@@ -832,22 +963,20 @@ void MediaDevicesManager::CheckPermissionForDeviceChange(
int render_frame_id,
MediaDeviceType type,
const MediaDeviceInfoArray& device_infos,
- const std::pair<std::string, url::Origin>& salt_and_origin) {
+ MediaDeviceSaltAndOrigin salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
permission_checker_->CheckPermission(
type, render_process_id, render_frame_id,
base::BindOnce(&MediaDevicesManager::NotifyDeviceChange,
weak_factory_.GetWeakPtr(), subscription_id, type,
- device_infos, salt_and_origin.first,
- salt_and_origin.second));
+ device_infos, std::move(salt_and_origin)));
}
void MediaDevicesManager::NotifyDeviceChange(
uint32_t subscription_id,
MediaDeviceType type,
const MediaDeviceInfoArray& device_infos,
- std::string device_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
bool has_permission) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(IsValidMediaDeviceType(type));
@@ -856,10 +985,8 @@ void MediaDevicesManager::NotifyDeviceChange(
return;
const SubscriptionRequest& request = it->second;
- std::string group_id_salt = request.group_id_salt_base + device_id_salt;
request.listener->OnDevicesChanged(
- type, TranslateMediaDeviceInfoArray(has_permission, device_id_salt,
- group_id_salt, security_origin,
+ type, TranslateMediaDeviceInfoArray(has_permission, salt_and_origin,
device_infos));
}
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager.h b/chromium/content/browser/renderer_host/media/media_devices_manager.h
index 27eb038bbb9..c0f7ae1262a 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager.h
@@ -30,6 +30,10 @@ namespace media {
class AudioSystem;
}
+namespace service_manager {
+class Connector;
+}
+
namespace content {
class MediaDevicesPermissionChecker;
@@ -81,11 +85,9 @@ class CONTENT_EXPORT MediaDevicesManager
// types and reports the results to |callback|. The enumeration results are
// translated for use by the renderer process and frame identified with
// |render_process_id| and |render_frame_id|, based on the frame origin's
- // permissions, an internal media-device salt, and the given
- // |group_id_salt_base|.
+ // permissions, an internal media-device salts.
void EnumerateDevices(int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback);
@@ -93,7 +95,6 @@ class CONTENT_EXPORT MediaDevicesManager
uint32_t SubscribeDeviceChangeNotifications(
int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& subscribe_types,
blink::mojom::MediaDevicesListenerPtr listener);
void UnsubscribeDeviceChangeNotifications(uint32_t subscription_id);
@@ -146,7 +147,6 @@ class CONTENT_EXPORT MediaDevicesManager
struct SubscriptionRequest {
SubscriptionRequest(int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& subscribe_types,
blink::mojom::MediaDevicesListenerPtr listener);
SubscriptionRequest(SubscriptionRequest&&);
@@ -156,7 +156,6 @@ class CONTENT_EXPORT MediaDevicesManager
int render_process_id;
int render_frame_id;
- std::string group_id_salt_base;
BoolDeviceTypes subscribe_types;
blink::mojom::MediaDevicesListenerPtr listener;
};
@@ -179,26 +178,21 @@ class CONTENT_EXPORT MediaDevicesManager
void CheckPermissionsForEnumerateDevices(
int render_process_id,
int render_frame_id,
- const std::string& group_id_salt_base,
const BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
- const std::pair<std::string, url::Origin>& salt_and_origin);
+ MediaDeviceSaltAndOrigin salt_and_origin);
void OnPermissionsCheckDone(
- const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
- const std::string& device_id_salt,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
const MediaDevicesManager::BoolDeviceTypes& has_permissions);
void OnDevicesEnumerated(
- const std::string& group_id_salt_base,
const MediaDevicesManager::BoolDeviceTypes& requested_types,
bool request_video_input_capabilities,
EnumerateDevicesCallback callback,
- const std::string& device_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
const MediaDevicesManager::BoolDeviceTypes& has_permissions,
const MediaDeviceEnumeration& enumeration);
@@ -222,28 +216,29 @@ class CONTENT_EXPORT MediaDevicesManager
void DevicesEnumerated(MediaDeviceType type,
const MediaDeviceInfoArray& snapshot);
void UpdateSnapshot(MediaDeviceType type,
- const MediaDeviceInfoArray& new_snapshot);
+ const MediaDeviceInfoArray& new_snapshot,
+ bool ignore_group_id = true);
void ProcessRequests();
bool IsEnumerationRequestReady(const EnumerationRequest& request_info);
// Helpers to handle device-change notification.
void HandleDevicesChanged(MediaDeviceType type);
+ void StopRemovedDevices(MediaDeviceType type,
+ const MediaDeviceInfoArray& new_snapshot);
void NotifyMediaStreamManager(MediaDeviceType type,
const MediaDeviceInfoArray& new_snapshot);
void NotifyDeviceChangeSubscribers(MediaDeviceType type,
const MediaDeviceInfoArray& snapshot);
- void CheckPermissionForDeviceChange(
- uint32_t subscription_id,
- int render_process_id,
- int render_frame_id,
- MediaDeviceType type,
- const MediaDeviceInfoArray& device_infos,
- const std::pair<std::string, url::Origin>& salt_and_origin);
+ void CheckPermissionForDeviceChange(uint32_t subscription_id,
+ int render_process_id,
+ int render_frame_id,
+ MediaDeviceType type,
+ const MediaDeviceInfoArray& device_infos,
+ MediaDeviceSaltAndOrigin salt_and_origin);
void NotifyDeviceChange(uint32_t subscription_id,
MediaDeviceType type,
const MediaDeviceInfoArray& device_infos,
- std::string device_id_salt,
- const url::Origin& security_origin,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
bool has_permission);
#if defined(OS_MACOSX)
@@ -275,6 +270,11 @@ class CONTENT_EXPORT MediaDevicesManager
// Callback used to obtain the current device ID salt and security origin.
MediaDeviceSaltAndOriginCallback salt_and_origin_callback_;
+ std::unique_ptr<service_manager::Connector> connector_;
+
+ class AudioServiceDeviceListener;
+ std::unique_ptr<AudioServiceDeviceListener> audio_service_device_listener_;
+
base::WeakPtrFactory<MediaDevicesManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaDevicesManager);
diff --git a/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
index 79302f2c9a9..761b26e26cd 100644
--- a/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_devices_manager_unittest.cc
@@ -46,10 +46,11 @@ const int kNumCalls = 3;
const auto kIgnoreLogMessageCB = base::BindRepeating([](const std::string&) {});
-std::pair<std::string, url::Origin> GetSaltAndOrigin(int /* process_id */,
- int /* frame_id */) {
- return std::make_pair(std::string("fake_media_device_salt"),
- url::Origin::Create(GURL("https://test.com")));
+MediaDeviceSaltAndOrigin GetSaltAndOrigin(int /* process_id */,
+ int /* frame_id */) {
+ return MediaDeviceSaltAndOrigin(
+ "fake_media_device_salt", "fake_group_id_salt",
+ url::Origin::Create(GURL("https://test.com")));
}
// This class mocks the audio manager and overrides some methods to ensure that
@@ -90,13 +91,13 @@ class MockAudioManager : public media::FakeAudioManager {
media::AudioParameters GetDefaultOutputStreamParameters() override {
return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
+ media::CHANNEL_LAYOUT_STEREO, 48000, 128);
}
media::AudioParameters GetOutputStreamParameters(
const std::string& device_id) override {
return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
+ media::CHANNEL_LAYOUT_STEREO, 48000, 128);
}
void SetNumAudioOutputDevices(size_t num_devices) {
@@ -148,6 +149,15 @@ class MockMediaDevicesListener : public blink::mojom::MediaDevicesListener {
mojo::BindingSet<blink::mojom::MediaDevicesListener> bindings_;
};
+void VerifyDeviceAndGroupID(const std::vector<MediaDeviceInfoArray>& array) {
+ for (const auto& device_infos : array) {
+ for (const auto& device_info : device_infos) {
+ EXPECT_FALSE(device_info.device_id.empty());
+ EXPECT_FALSE(device_info.group_id.empty());
+ }
+ }
+}
+
} // namespace
class MediaDevicesManagerTest : public ::testing::Test {
@@ -161,6 +171,12 @@ class MediaDevicesManagerTest : public ::testing::Test {
void EnumerateCallback(base::RunLoop* run_loop,
const MediaDeviceEnumeration& result) {
+ for (int i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) {
+ for (const auto& device_info : result[i]) {
+ EXPECT_FALSE(device_info.device_id.empty());
+ EXPECT_FALSE(device_info.group_id.empty());
+ }
+ }
MockCallback(result);
run_loop->Quit();
}
@@ -522,9 +538,7 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
audio_input_devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
uint32_t audio_input_subscription_id =
media_devices_manager_->SubscribeDeviceChangeNotifications(
- kRenderProcessId, kRenderFrameId,
- std::string("fake_group_id_salt_base"),
- audio_input_devices_to_subscribe,
+ kRenderProcessId, kRenderFrameId, audio_input_devices_to_subscribe,
listener_audio_input.CreateInterfacePtrAndBind());
MockMediaDevicesListener listener_video_input;
@@ -532,9 +546,7 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
video_input_devices_to_subscribe[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
uint32_t video_input_subscription_id =
media_devices_manager_->SubscribeDeviceChangeNotifications(
- kRenderProcessId, kRenderFrameId,
- std::string("fake_group_id_salt_base"),
- video_input_devices_to_subscribe,
+ kRenderProcessId, kRenderFrameId, video_input_devices_to_subscribe,
listener_video_input.CreateInterfacePtrAndBind());
MockMediaDevicesListener listener_audio_output;
@@ -542,9 +554,7 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
audio_output_devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
uint32_t audio_output_subscription_id =
media_devices_manager_->SubscribeDeviceChangeNotifications(
- kRenderProcessId, kRenderFrameId,
- std::string("fake_group_id_salt_base"),
- audio_output_devices_to_subscribe,
+ kRenderProcessId, kRenderFrameId, audio_output_devices_to_subscribe,
listener_audio_output.CreateInterfacePtrAndBind());
MockMediaDevicesListener listener_all;
@@ -553,8 +563,8 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
all_devices_to_subscribe[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
all_devices_to_subscribe[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
media_devices_manager_->SubscribeDeviceChangeNotifications(
- kRenderProcessId, kRenderFrameId, std::string("fake_group_id_salt_base"),
- all_devices_to_subscribe, listener_all.CreateInterfacePtrAndBind());
+ kRenderProcessId, kRenderFrameId, all_devices_to_subscribe,
+ listener_all.CreateInterfacePtrAndBind());
MediaDeviceInfoArray notification_audio_input;
MediaDeviceInfoArray notification_video_input;
@@ -602,6 +612,10 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
EXPECT_EQ(num_audio_input_devices, notification_all_audio_input.size());
EXPECT_EQ(num_video_input_devices, notification_all_video_input.size());
EXPECT_EQ(num_audio_output_devices, notification_all_audio_output.size());
+ VerifyDeviceAndGroupID(
+ {notification_audio_input, notification_video_input,
+ notification_audio_output, notification_all_audio_input,
+ notification_all_video_input, notification_all_audio_output});
media_devices_manager_->UnsubscribeDeviceChangeNotifications(
audio_input_subscription_id);
@@ -626,6 +640,9 @@ TEST_F(MediaDevicesManagerTest, SubscribeDeviceChanges) {
EXPECT_EQ(num_audio_input_devices, notification_all_audio_input.size());
EXPECT_EQ(num_video_input_devices, notification_all_video_input.size());
EXPECT_EQ(num_audio_output_devices, notification_all_audio_output.size());
+ VerifyDeviceAndGroupID({notification_all_audio_input,
+ notification_all_video_input,
+ notification_all_audio_output});
}
TEST_F(MediaDevicesManagerTest, GuessVideoGroupID) {
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index 17593bdbf27..9f623c4c883 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -126,19 +126,18 @@ void MediaStreamDispatcherHost::DoGenerateStream(
const StreamControls& controls,
bool user_gesture,
GenerateStreamCallback callback,
- const std::pair<std::string, url::Origin>& salt_and_origin) {
+ MediaDeviceSaltAndOrigin salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!MediaStreamManager::IsOriginAllowed(render_process_id_,
- salt_and_origin.second)) {
+ salt_and_origin.origin)) {
std::move(callback).Run(MEDIA_DEVICE_INVALID_SECURITY_ORIGIN, std::string(),
MediaStreamDevices(), MediaStreamDevices());
return;
}
media_stream_manager_->GenerateStream(
- render_process_id_, render_frame_id_, salt_and_origin.first,
- page_request_id, controls, salt_and_origin.second, user_gesture,
- std::move(callback),
+ render_process_id_, render_frame_id_, page_request_id, controls,
+ std::move(salt_and_origin), user_gesture, std::move(callback),
base::BindRepeating(&MediaStreamDispatcherHost::OnDeviceStopped,
weak_factory_.GetWeakPtr()));
}
@@ -178,19 +177,18 @@ void MediaStreamDispatcherHost::DoOpenDevice(
const std::string& device_id,
MediaStreamType type,
OpenDeviceCallback callback,
- const std::pair<std::string, url::Origin>& salt_and_origin) {
+ MediaDeviceSaltAndOrigin salt_and_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!MediaStreamManager::IsOriginAllowed(render_process_id_,
- salt_and_origin.second)) {
+ salt_and_origin.origin)) {
std::move(callback).Run(false /* success */, std::string(),
MediaStreamDevice());
return;
}
media_stream_manager_->OpenDevice(
- render_process_id_, render_frame_id_, salt_and_origin.first,
- page_request_id, device_id, type, salt_and_origin.second,
- std::move(callback),
+ render_process_id_, render_frame_id_, page_request_id, device_id, type,
+ std::move(salt_and_origin), std::move(callback),
base::BindRepeating(&MediaStreamDispatcherHost::OnDeviceStopped,
weak_factory_.GetWeakPtr()));
}
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
index fecd1b184f7..1144a334122 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -17,10 +17,6 @@
#include "content/common/media/media_stream_controls.h"
#include "mojo/public/cpp/bindings/binding_set.h"
-namespace url {
-class Origin;
-}
-
namespace content {
class MediaStreamManager;
@@ -72,17 +68,16 @@ class CONTENT_EXPORT MediaStreamDispatcherHost
bool is_secure) override;
void OnStreamStarted(const std::string& label) override;
- void DoGenerateStream(
- int32_t request_id,
- const StreamControls& controls,
- bool user_gesture,
- GenerateStreamCallback callback,
- const std::pair<std::string, url::Origin>& salt_and_origin);
+ void DoGenerateStream(int32_t request_id,
+ const StreamControls& controls,
+ bool user_gesture,
+ GenerateStreamCallback callback,
+ MediaDeviceSaltAndOrigin salt_and_origin);
void DoOpenDevice(int32_t request_id,
const std::string& device_id,
MediaStreamType type,
OpenDeviceCallback callback,
- const std::pair<std::string, url::Origin>& salt_and_origin);
+ MediaDeviceSaltAndOrigin salt_and_origin);
void OnDeviceStopped(const std::string& label,
const MediaStreamDevice& device);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index e7f85c17584..688ce189a4a 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -123,7 +123,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
base::Unretained(this)));
}
- void OnStreamStarted(const std::string& label) {
+ void OnStreamStarted(const std::string& label) override {
MediaStreamDispatcherHost::OnStreamStarted(label);
}
@@ -307,9 +307,10 @@ class MediaStreamDispatcherHostTest : public testing::Test {
void TearDown() override { host_.reset(); }
- std::pair<std::string, url::Origin> GetSaltAndOrigin(int /* process_id */,
- int /* frame_id */) {
- return std::make_pair(browser_context_->GetMediaDeviceIDSalt(), origin_);
+ MediaDeviceSaltAndOrigin GetSaltAndOrigin(int /* process_id */,
+ int /* frame_id */) {
+ return MediaDeviceSaltAndOrigin(browser_context_->GetMediaDeviceIDSalt(),
+ "fake_group_id_salt", origin_);
}
protected:
@@ -350,12 +351,11 @@ class MediaStreamDispatcherHostTest : public testing::Test {
int page_request_id,
const StreamControls& controls,
MediaStreamRequestResult expected_result) {
- base::RunLoop run_loop;
- EXPECT_CALL(*host_,
- OnStreamGenerationFailure(page_request_id, expected_result));
- host_->OnGenerateStream(page_request_id, controls,
- run_loop.QuitClosure());
- run_loop.Run();
+ base::RunLoop run_loop;
+ EXPECT_CALL(*host_,
+ OnStreamGenerationFailure(page_request_id, expected_result));
+ host_->OnGenerateStream(page_request_id, controls, run_loop.QuitClosure());
+ run_loop.Run();
}
void OpenVideoDeviceAndWaitForResult(int page_request_id,
@@ -696,8 +696,9 @@ TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) {
std::string stream_request_label = host_->label_;
MediaStreamDevice video_device = host_->video_devices_.front();
- ASSERT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
- stream_request_label).size());
+ ASSERT_EQ(
+ 1u, media_stream_manager_->GetDevicesOpenedByRequest(stream_request_label)
+ .size());
// Open the same device by Pepper.
OpenVideoDeviceAndWaitForResult(kPageRequestId, video_device.id);
@@ -706,10 +707,12 @@ TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) {
// Stop the device in the MediaStream.
host_->OnStopStreamDevice(video_device.id, video_device.session_id);
- EXPECT_EQ(0u, media_stream_manager_->GetDevicesOpenedByRequest(
- stream_request_label).size());
- EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
- open_device_request_label).size());
+ EXPECT_EQ(
+ 0u, media_stream_manager_->GetDevicesOpenedByRequest(stream_request_label)
+ .size());
+ EXPECT_EQ(1u, media_stream_manager_
+ ->GetDevicesOpenedByRequest(open_device_request_label)
+ .size());
}
TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) {
@@ -721,12 +724,14 @@ TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) {
std::string request_label1 = host_->label_;
MediaStreamDevice video_device = host_->video_devices_.front();
// Expect that 1 audio and 1 video device has been opened.
- EXPECT_EQ(2u, media_stream_manager_->GetDevicesOpenedByRequest(
- request_label1).size());
+ EXPECT_EQ(
+ 2u,
+ media_stream_manager_->GetDevicesOpenedByRequest(request_label1).size());
host_->OnStopStreamDevice(video_device.id, video_device.session_id);
- EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest(
- request_label1).size());
+ EXPECT_EQ(
+ 1u,
+ media_stream_manager_->GetDevicesOpenedByRequest(request_label1).size());
GenerateStreamAndWaitForResult(kPageRequestId, controls);
std::string request_label2 = host_->label_;
@@ -856,14 +861,21 @@ TEST_F(MediaStreamDispatcherHostTest, Salt) {
EXPECT_EQ(host_->video_devices_.size(), 1u);
const std::string label1 = host_->label_;
const std::string device_id1 = host_->video_devices_.front().id;
+ EXPECT_TRUE(host_->video_devices_.front().group_id.has_value());
+ const std::string group_id1 = *host_->video_devices_.front().group_id;
+ EXPECT_FALSE(group_id1.empty());
const int session_id1 = host_->video_devices_.front().session_id;
// Generate second stream.
OpenVideoDeviceAndWaitForResult(kPageRequestId, device_id1);
const std::string device_id2 = host_->opened_device_.id;
+ EXPECT_TRUE(host_->opened_device_.group_id.has_value());
+ const std::string group_id2 = *host_->opened_device_.group_id;
+ EXPECT_FALSE(group_id2.empty());
const int session_id2 = host_->opened_device_.session_id;
const std::string label2 = host_->label_;
EXPECT_EQ(device_id1, device_id2);
+ EXPECT_EQ(group_id1, group_id2);
EXPECT_NE(session_id1, session_id2);
EXPECT_NE(label1, label2);
@@ -874,6 +886,7 @@ TEST_F(MediaStreamDispatcherHostTest, Salt) {
// Last open device ID and session are from the second stream.
EXPECT_EQ(session_id2, host_->opened_device_.session_id);
EXPECT_EQ(device_id2, host_->opened_device_.id);
+ EXPECT_EQ(group_id2, host_->opened_device_.group_id);
}
}; // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
index 19a1e6b3e2e..6f59da110bf 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -30,6 +30,7 @@
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
+#include "content/browser/renderer_host/media/audio_service_listener.h"
#include "content/browser/renderer_host/media/in_process_video_capture_provider.h"
#include "content/browser/renderer_host/media/media_capture_devices_impl.h"
#include "content/browser/renderer_host/media/media_devices_manager.h"
@@ -81,7 +82,8 @@ std::string RandomLabel() {
// U+007E. That causes problems with searching for labels in bots, so we use a
// safe alphanumeric subset |kAlphabet|.
// [1] http://dev.w3.org/2011/webrtc/editor/webrtc.html
- static const char kAlphabet[] = "0123456789"
+ static const char kAlphabet[] =
+ "0123456789"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const size_t kRfc4122LengthLabel = 36u;
@@ -140,19 +142,19 @@ void ParseStreamType(const StreamControls& controls,
switches::kDisableAudioSupportForDesktopShare);
if (controls.audio.requested) {
if (!controls.audio.stream_source.empty()) {
- // This is tab or screen capture.
- if (controls.audio.stream_source == kMediaStreamSourceTab) {
- *audio_type = MEDIA_TAB_AUDIO_CAPTURE;
- } else if (controls.audio.stream_source == kMediaStreamSourceSystem) {
- *audio_type = MEDIA_DESKTOP_AUDIO_CAPTURE;
- } else if (audio_support_flag_for_desktop_share &&
- controls.audio.stream_source == kMediaStreamSourceDesktop) {
- *audio_type = MEDIA_DESKTOP_AUDIO_CAPTURE;
- }
- } else {
- // This is normal audio device capture.
- *audio_type = MEDIA_DEVICE_AUDIO_CAPTURE;
- }
+ // This is tab or screen capture.
+ if (controls.audio.stream_source == kMediaStreamSourceTab) {
+ *audio_type = MEDIA_TAB_AUDIO_CAPTURE;
+ } else if (controls.audio.stream_source == kMediaStreamSourceSystem) {
+ *audio_type = MEDIA_DESKTOP_AUDIO_CAPTURE;
+ } else if (audio_support_flag_for_desktop_share &&
+ controls.audio.stream_source == kMediaStreamSourceDesktop) {
+ *audio_type = MEDIA_DESKTOP_AUDIO_CAPTURE;
+ }
+ } else {
+ // This is normal audio device capture.
+ *audio_type = MEDIA_DEVICE_AUDIO_CAPTURE;
+ }
}
if (controls.video.requested) {
if (!controls.video.stream_source.empty()) {
@@ -255,7 +257,6 @@ void SendVideoCaptureLogMessage(const std::string& message) {
} // namespace
-
// MediaStreamManager::DeviceRequest represents a request to either enumerate
// available devices or open one or more devices.
// TODO(perkj): MediaStreamManager still needs refactoring. I propose we create
@@ -268,20 +269,18 @@ class MediaStreamManager::DeviceRequest {
int requesting_process_id,
int requesting_frame_id,
int page_request_id,
- const url::Origin& security_origin,
bool user_gesture,
MediaStreamRequestType request_type,
const StreamControls& controls,
- const std::string& salt,
+ MediaDeviceSaltAndOrigin salt_and_origin,
DeviceStoppedCallback device_stopped_cb = DeviceStoppedCallback())
: requesting_process_id(requesting_process_id),
requesting_frame_id(requesting_frame_id),
page_request_id(page_request_id),
- security_origin(security_origin),
user_gesture(user_gesture),
request_type(request_type),
controls(controls),
- salt(salt),
+ salt_and_origin(std::move(salt_and_origin)),
device_stopped_cb(std::move(device_stopped_cb)),
state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED),
audio_type_(MEDIA_NO_SERVICE),
@@ -292,8 +291,7 @@ class MediaStreamManager::DeviceRequest {
~DeviceRequest() { RunMojoCallbacks(); }
void SetAudioType(MediaStreamType audio_type) {
- DCHECK(IsAudioInputMediaType(audio_type) ||
- audio_type == MEDIA_NO_SERVICE);
+ DCHECK(IsAudioInputMediaType(audio_type) || audio_type == MEDIA_NO_SERVICE);
audio_type_ = audio_type;
}
@@ -315,7 +313,7 @@ class MediaStreamManager::DeviceRequest {
target_frame_id_ = requesting_frame_id;
ui_request_.reset(new MediaStreamRequest(
requesting_process_id, requesting_frame_id, page_request_id,
- security_origin.GetURL(), user_gesture, request_type,
+ salt_and_origin.origin.GetURL(), user_gesture, request_type,
requested_audio_device_id, requested_video_device_id, audio_type_,
video_type_, controls.disable_local_echo));
}
@@ -329,7 +327,7 @@ class MediaStreamManager::DeviceRequest {
target_frame_id_ = target_render_frame_id;
ui_request_.reset(new MediaStreamRequest(
target_render_process_id, target_render_frame_id, page_request_id,
- security_origin.GetURL(), user_gesture, request_type, "", "",
+ salt_and_origin.origin.GetURL(), user_gesture, request_type, "", "",
audio_type_, video_type_, controls.disable_local_echo));
}
@@ -357,13 +355,13 @@ class MediaStreamManager::DeviceRequest {
for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; ++i) {
media_observer->OnMediaRequestStateChanged(
target_process_id_, target_frame_id_, page_request_id,
- security_origin.GetURL(), static_cast<MediaStreamType>(i),
+ salt_and_origin.origin.GetURL(), static_cast<MediaStreamType>(i),
new_state);
}
} else {
media_observer->OnMediaRequestStateChanged(
target_process_id_, target_frame_id_, page_request_id,
- security_origin.GetURL(), stream_type, new_state);
+ salt_and_origin.origin.GetURL(), stream_type, new_state);
}
}
@@ -410,15 +408,13 @@ class MediaStreamManager::DeviceRequest {
// An ID the render frame provided to identify this request.
const int page_request_id;
- const url::Origin security_origin;
-
const bool user_gesture;
const MediaStreamRequestType request_type;
const StreamControls controls;
- const std::string salt;
+ const MediaDeviceSaltAndOrigin salt_and_origin;
MediaStreamDevices devices;
@@ -474,9 +470,6 @@ MediaStreamManager::MediaStreamManager(
scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
std::unique_ptr<VideoCaptureProvider> video_capture_provider)
: audio_system_(audio_system),
-#if defined(OS_WIN)
- video_capture_thread_("VideoCaptureThread"),
-#endif
fake_ui_factory_() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeUIForMediaStream)) {
@@ -490,14 +483,25 @@ MediaStreamManager::MediaStreamManager(
if (!video_capture_provider) {
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner =
+#if defined(OS_WIN)
+ // Windows unconditionally requires its own thread (see below).
+ nullptr;
+#else
+ // Share the provided |audio_task_runner| if it's non-null.
std::move(audio_task_runner);
+#endif
+
+ if (!device_task_runner) {
+ video_capture_thread_.emplace("VideoCaptureThread");
#if defined(OS_WIN)
- // Use an STA Video Capture Thread to try to avoid crashes on enumeration of
- // buggy third party Direct Show modules, http://crbug.com/428958.
- video_capture_thread_.init_com_with_mta(false);
- CHECK(video_capture_thread_.Start());
- device_task_runner = video_capture_thread_.task_runner();
+ // Use an STA Video Capture Thread to try to avoid crashes on enumeration
+ // of buggy third party Direct Show modules, http://crbug.com/428958.
+ video_capture_thread_->init_com_with_mta(false);
#endif
+ CHECK(video_capture_thread_->Start());
+ device_task_runner = video_capture_thread_->task_runner();
+ }
+
if (base::FeatureList::IsEnabled(features::kMojoVideoCapture)) {
video_capture_provider = std::make_unique<VideoCaptureProviderSwitcher>(
std::make_unique<ServiceVideoCaptureProvider>(
@@ -521,6 +525,12 @@ MediaStreamManager::MediaStreamManager(
}
InitializeMaybeAsync(std::move(video_capture_provider));
+ // May be null in tests.
+ if (ServiceManagerConnection::GetForProcess()) {
+ audio_service_listener_ = std::make_unique<AudioServiceListener>(
+ ServiceManagerConnection::GetForProcess()->GetConnector()->Clone());
+ }
+
base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
// BrowserMainLoop always creates the PowerMonitor instance before creating
// MediaStreamManager, but power_monitor may be NULL in unit tests.
@@ -547,11 +557,16 @@ VideoCaptureManager* MediaStreamManager::video_capture_manager() {
}
AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // May be called on any thread, provided that we are not in shutdown.
DCHECK(audio_input_device_manager_.get());
return audio_input_device_manager_.get();
}
+AudioServiceListener* MediaStreamManager::audio_service_listener() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return audio_service_listener_.get();
+}
+
MediaDevicesManager* MediaStreamManager::media_devices_manager() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// nullptr might be returned during shutdown.
@@ -588,9 +603,11 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DeviceRequest* request = new DeviceRequest(
- render_process_id, render_frame_id, page_request_id, security_origin,
- false, // user gesture
- MEDIA_DEVICE_ACCESS, controls, std::string());
+ render_process_id, render_frame_id, page_request_id,
+ false /* user gesture */, MEDIA_DEVICE_ACCESS, controls,
+ MediaDeviceSaltAndOrigin{std::string() /* salt */,
+ std::string() /* group_id_salt */,
+ security_origin});
const std::string& label = AddRequest(request);
@@ -609,20 +626,19 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
void MediaStreamManager::GenerateStream(
int render_process_id,
int render_frame_id,
- const std::string& salt,
int page_request_id,
const StreamControls& controls,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
bool user_gesture,
GenerateStreamCallback generate_stream_cb,
DeviceStoppedCallback device_stopped_cb) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "GenerateStream()";
- DeviceRequest* request =
- new DeviceRequest(render_process_id, render_frame_id, page_request_id,
- security_origin, user_gesture, MEDIA_GENERATE_STREAM,
- controls, salt, std::move(device_stopped_cb));
+ DeviceRequest* request = new DeviceRequest(
+ render_process_id, render_frame_id, page_request_id, user_gesture,
+ MEDIA_GENERATE_STREAM, controls, std::move(salt_and_origin),
+ std::move(device_stopped_cb));
const std::string& label = AddRequest(request);
@@ -632,7 +648,7 @@ void MediaStreamManager::GenerateStream(
// The test callback is responsible to verify whether the |controls| is
// as expected. Then we need to finish getUserMedia and let Javascript
// access the result.
- if (generate_stream_test_callback_.Run(controls)) {
+ if (std::move(generate_stream_test_callback_).Run(controls)) {
FinalizeGenerateStream(label, request);
} else {
FinalizeRequestFailed(label, request, MEDIA_DEVICE_INVALID_STATE);
@@ -667,11 +683,11 @@ void MediaStreamManager::CancelRequest(int render_process_id,
void MediaStreamManager::CancelRequest(const std::string& label) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "CancelRequest({label = " << label << "})";
+ DVLOG(1) << "CancelRequest({label = " << label << "})";
DeviceRequest* request = FindRequest(label);
if (!request) {
// The request does not exist.
- LOG(ERROR) << "The request with label = " << label << " does not exist.";
+ LOG(ERROR) << "The request with label = " << label << " does not exist.";
return;
}
@@ -790,7 +806,7 @@ void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
DVLOG(1) << "CloseDevice("
- << "{type = " << type << "} "
+ << "{type = " << type << "} "
<< "{session_id = " << session_id << "})";
GetDeviceManager(type)->Close(session_id);
@@ -808,17 +824,16 @@ void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
void MediaStreamManager::OpenDevice(int render_process_id,
int render_frame_id,
- const std::string& salt,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
OpenDeviceCallback open_device_cb,
DeviceStoppedCallback device_stopped_cb) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
type == MEDIA_DEVICE_VIDEO_CAPTURE);
- DVLOG(1) << "OpenDevice ({page_request_id = " << page_request_id << "})";
+ DVLOG(1) << "OpenDevice ({page_request_id = " << page_request_id << "})";
StreamControls controls;
if (IsAudioInputMediaType(type)) {
controls.audio.requested = true;
@@ -830,10 +845,9 @@ void MediaStreamManager::OpenDevice(int render_process_id,
NOTREACHED();
}
DeviceRequest* request = new DeviceRequest(
- render_process_id, render_frame_id, page_request_id, security_origin,
- false, // user gesture
- MEDIA_OPEN_DEVICE_PEPPER_ONLY, controls, salt,
- std::move(device_stopped_cb));
+ render_process_id, render_frame_id, page_request_id,
+ false /* user gesture */, MEDIA_OPEN_DEVICE_PEPPER_ONLY, controls,
+ std::move(salt_and_origin), std::move(device_stopped_cb));
const std::string& label = AddRequest(request);
@@ -887,7 +901,8 @@ void MediaStreamManager::StopRemovedDevice(
const DeviceRequest* request = labeled_request.second;
for (const MediaStreamDevice& device : request->devices) {
const std::string source_id = GetHMACForMediaDeviceID(
- request->salt, request->security_origin, media_device_info.device_id);
+ request->salt_and_origin.device_id_salt,
+ request->salt_and_origin.origin, media_device_info.device_id);
if (device.id == source_id && device.type == stream_type) {
session_ids.push_back(device.session_id);
if (request->device_stopped_cb) {
@@ -907,15 +922,16 @@ void MediaStreamManager::StopRemovedDevice(
.c_str());
}
-bool MediaStreamManager::PickDeviceId(const std::string& salt,
- const url::Origin& security_origin,
- const TrackControls& controls,
- const MediaDeviceInfoArray& devices,
- std::string* device_id) const {
+bool MediaStreamManager::PickDeviceId(
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
+ const TrackControls& controls,
+ const MediaDeviceInfoArray& devices,
+ std::string* device_id) const {
if (controls.device_id.empty())
return true;
- if (!GetDeviceIDFromHMAC(salt, security_origin, controls.device_id, devices,
+ if (!GetDeviceIDFromHMAC(salt_and_origin.device_id_salt,
+ salt_and_origin.origin, controls.device_id, devices,
device_id)) {
LOG(WARNING) << "Invalid device ID = " << controls.device_id;
return false;
@@ -929,11 +945,11 @@ bool MediaStreamManager::GetRequestedDeviceCaptureId(
const MediaDeviceInfoArray& devices,
std::string* device_id) const {
if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
- return PickDeviceId(request->salt, request->security_origin,
- request->controls.audio, devices, device_id);
+ return PickDeviceId(request->salt_and_origin, request->controls.audio,
+ devices, device_id);
} else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) {
- return PickDeviceId(request->salt, request->security_origin,
- request->controls.video, devices, device_id);
+ return PickDeviceId(request->salt_and_origin, request->controls.video,
+ devices, device_id);
} else {
NOTREACHED();
}
@@ -945,8 +961,14 @@ void MediaStreamManager::TranslateDeviceIdToSourceId(
MediaStreamDevice* device) {
if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
- device->id = GetHMACForMediaDeviceID(request->salt,
- request->security_origin, device->id);
+ device->id =
+ GetHMACForMediaDeviceID(request->salt_and_origin.device_id_salt,
+ request->salt_and_origin.origin, device->id);
+ if (device->group_id) {
+ device->group_id = GetHMACForMediaDeviceID(
+ request->salt_and_origin.group_id_salt,
+ request->salt_and_origin.origin, *device->group_id);
+ }
}
}
@@ -992,8 +1014,8 @@ std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
return unique_label;
}
-MediaStreamManager::DeviceRequest*
-MediaStreamManager::FindRequest(const std::string& label) const {
+MediaStreamManager::DeviceRequest* MediaStreamManager::FindRequest(
+ const std::string& label) const {
for (const LabeledDeviceRequest& labeled_request : requests_) {
if (labeled_request.first == label)
return labeled_request.second;
@@ -1101,17 +1123,13 @@ void MediaStreamManager::SetupRequest(const std::string& label) {
const bool is_web_contents_capture = audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
video_type == MEDIA_TAB_VIDEO_CAPTURE;
if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
- FinalizeRequestFailed(label,
- request,
- MEDIA_DEVICE_TAB_CAPTURE_FAILURE);
+ FinalizeRequestFailed(label, request, MEDIA_DEVICE_TAB_CAPTURE_FAILURE);
return;
}
const bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
- FinalizeRequestFailed(label,
- request,
- MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE);
+ FinalizeRequestFailed(label, request, MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE);
return;
}
@@ -1251,7 +1269,8 @@ bool MediaStreamManager::FindExistingRequestedDevice(
DCHECK(existing_request_state);
std::string source_id = GetHMACForMediaDeviceID(
- new_request.salt, new_request.security_origin, new_device.id);
+ new_request.salt_and_origin.device_id_salt,
+ new_request.salt_and_origin.origin, new_device.id);
for (const LabeledDeviceRequest& labeled_request : requests_) {
const DeviceRequest* request = labeled_request.second;
@@ -1379,7 +1398,7 @@ void MediaStreamManager::InitializeMaybeAsync(
// We want to be notified of IO message loop destruction to delete the thread
// and the device managers.
- base::MessageLoop::current()->AddDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
video_capture_manager_ =
new VideoCaptureManager(std::move(video_capture_provider),
@@ -1393,7 +1412,7 @@ void MediaStreamManager::InitializeMaybeAsync(
void MediaStreamManager::Opened(MediaStreamType stream_type,
int capture_session_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "Opened({stream_type = " << stream_type << "} "
+ DVLOG(1) << "Opened({stream_type = " << stream_type << "} "
<< "{capture_session_id = " << capture_session_id << "})";
// Find the request(s) containing this device and mark it as used.
@@ -1441,7 +1460,7 @@ void MediaStreamManager::HandleRequestDone(const std::string& label,
DeviceRequest* request) {
DCHECK(RequestDone(*request));
DVLOG(1) << "HandleRequestDone("
- << ", {label = " << label << "})";
+ << ", {label = " << label << "})";
switch (request->request_type) {
case MEDIA_OPEN_DEVICE_PEPPER_ONLY:
@@ -1497,7 +1516,7 @@ void MediaStreamManager::DevicesEnumerated(
void MediaStreamManager::Aborted(MediaStreamType stream_type,
int capture_session_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "Aborted({stream_type = " << stream_type << "} "
+ DVLOG(1) << "Aborted({stream_type = " << stream_type << "} "
<< "{capture_session_id = " << capture_session_id << "})";
StopDevice(stream_type, capture_session_id);
}
@@ -1556,7 +1575,7 @@ void MediaStreamManager::HandleAccessRequestResponse(
MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "HandleAccessRequestResponse("
- << ", {label = " << label << "})";
+ << ", {label = " << label << "})";
DeviceRequest* request = FindRequest(label);
if (!request) {
@@ -1598,9 +1617,9 @@ void MediaStreamManager::HandleAccessRequestResponse(
if (sample_rate <= 0 || sample_rate > 96000)
sample_rate = 44100;
- media::AudioParameters params(
- device.input.format(), media::CHANNEL_LAYOUT_STEREO, sample_rate,
- device.input.bits_per_sample(), device.input.frames_per_buffer());
+ media::AudioParameters params(device.input.format(),
+ media::CHANNEL_LAYOUT_STEREO, sample_rate,
+ device.input.frames_per_buffer());
params.set_effects(device.input.effects());
params.set_mic_positions(device.input.mic_positions());
DCHECK(params.IsValid());
@@ -1863,9 +1882,10 @@ MediaStreamDevices MediaStreamManager::ConvertToMediaStreamDevices(
MediaStreamType stream_type,
const MediaDeviceInfoArray& device_infos) {
MediaStreamDevices devices;
- for (const auto& info : device_infos)
+ for (const auto& info : device_infos) {
devices.emplace_back(stream_type, info.device_id, info.label,
- info.video_facing);
+ info.video_facing, info.group_id);
+ }
if (stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
return devices;
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.h b/chromium/content/browser/renderer_host/media/media_stream_manager.h
index 262cd2bda8d..82fee09f21e 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -37,10 +37,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/optional.h"
#include "base/power_monitor/power_observer.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
+#include "content/browser/media/media_devices_util.h"
#include "content/browser/renderer_host/media/media_devices_manager.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/common/content_export.h"
@@ -61,6 +64,7 @@ class Origin;
namespace content {
class AudioInputDeviceManager;
+class AudioServiceListener;
class FakeMediaStreamUIProxy;
class MediaStreamUIProxy;
class VideoCaptureManager;
@@ -71,7 +75,7 @@ class VideoCaptureProvider;
// using callbacks.
class CONTENT_EXPORT MediaStreamManager
: public MediaStreamProviderListener,
- public base::MessageLoop::DestructionObserver,
+ public base::MessageLoopCurrent::DestructionObserver,
public base::PowerObserver {
public:
// Callback to deliver the result of a media access request.
@@ -96,13 +100,16 @@ class CONTENT_EXPORT MediaStreamManager
// Callback for testing.
using GenerateStreamTestCallback =
- base::Callback<bool(const StreamControls&)>;
+ base::OnceCallback<bool(const StreamControls&)>;
// Adds |message| to native logs for outstanding device requests, for use by
// render processes hosts whose corresponding render processes are requesting
// logging from webrtcLoggingPrivate API. Safe to call from any thread.
static void SendMessageToNativeLog(const std::string& message);
+ // |audio_task_runner| passed to constructors is the task runner used by audio
+ // system when it runs in-process; it's null if audio runs out of process.
+
MediaStreamManager(
media::AudioSystem* audio_system,
scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner);
@@ -122,6 +129,9 @@ class CONTENT_EXPORT MediaStreamManager
// Used to access AudioInputDeviceManager.
AudioInputDeviceManager* audio_input_device_manager();
+ // Used to access AudioServiceListener, must be called on IO thread.
+ AudioServiceListener* audio_service_listener();
+
// Used to access MediaDevicesManager.
MediaDevicesManager* media_devices_manager();
@@ -158,10 +168,9 @@ class CONTENT_EXPORT MediaStreamManager
// is set to receive device stopped notifications.
void GenerateStream(int render_process_id,
int render_frame_id,
- const std::string& salt,
int page_request_id,
const StreamControls& controls,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
bool user_gesture,
GenerateStreamCallback generate_stream_cb,
DeviceStoppedCallback device_stopped_cb);
@@ -190,11 +199,10 @@ class CONTENT_EXPORT MediaStreamManager
// request is identified using string returned to the caller.
void OpenDevice(int render_process_id,
int render_frame_id,
- const std::string& salt,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
- const url::Origin& security_origin,
+ MediaDeviceSaltAndOrigin salt_and_origin,
OpenDeviceCallback open_device_cb,
DeviceStoppedCallback device_stopped_cb);
@@ -228,12 +236,10 @@ class CONTENT_EXPORT MediaStreamManager
// This object gets deleted on the UI thread after the IO thread has been
// destroyed. So we need to know when IO thread is being destroyed so that
- // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally
- // this is handled by
- // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop.
- // But for some tests which use TestBrowserThreadBundle, we need to call
- // WillDestroyCurrentMessageLoop explicitly because the notification happens
- // too late. (see http://crbug.com/247525#c14).
+ // we can delete VideoCaptureManager and AudioInputDeviceManager.
+ // Note: In tests it is sometimes necessary to invoke this explicitly when
+ // using TestBrowserThreadBundle because the notification happens too late.
+ // (see http://crbug.com/247525#c14).
void WillDestroyCurrentMessageLoop() override;
// Sends log messages to the render process hosts whose corresponding render
@@ -323,8 +329,7 @@ class CONTENT_EXPORT MediaStreamManager
// Helpers.
// Checks if all devices that was requested in the request identififed by
// |label| has been opened and set the request state accordingly.
- void HandleRequestDone(const std::string& label,
- DeviceRequest* request);
+ void HandleRequestDone(const std::string& label, DeviceRequest* request);
// Stop the use of the device associated with |session_id| of type |type| in
// all |requests_|. The device is removed from the request. If a request
/// doesn't use any devices as a consequence, the request is deleted.
@@ -395,8 +400,7 @@ class CONTENT_EXPORT MediaStreamManager
// valid alternate device ID.
// Returns false if the required device ID is present and invalid.
// Otherwise, if no valid device is found, device_id is unchanged.
- bool PickDeviceId(const std::string& salt,
- const url::Origin& security_origin,
+ bool PickDeviceId(const MediaDeviceSaltAndOrigin& salt_and_origin,
const TrackControls& controls,
const MediaDeviceInfoArray& devices,
std::string* device_id) const;
@@ -418,7 +422,8 @@ class CONTENT_EXPORT MediaStreamManager
gfx::NativeViewId window_id);
// Runs on the IO thread and does the actual [un]registration of callbacks.
- void DoNativeLogCallbackRegistration(int renderer_host_id,
+ void DoNativeLogCallbackRegistration(
+ int renderer_host_id,
const base::Callback<void(const std::string&)>& callback);
void DoNativeLogCallbackUnregistration(int renderer_host_id);
@@ -438,9 +443,12 @@ class CONTENT_EXPORT MediaStreamManager
media::AudioSystem* const audio_system_; // not owned
scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_;
scoped_refptr<VideoCaptureManager> video_capture_manager_;
-#if defined(OS_WIN)
- base::Thread video_capture_thread_;
-#endif
+
+ // Not initialized on Mac (if not in tests), since the main thread is used.
+ // Always initialized on Windows.
+ // On other platforms, initialized when no audio task runner is provided in
+ // the constructor.
+ base::Optional<base::Thread> video_capture_thread_;
std::unique_ptr<MediaDevicesManager> media_devices_manager_;
@@ -453,6 +461,8 @@ class CONTENT_EXPORT MediaStreamManager
// Maps render process hosts to log callbacks. Used on the IO thread.
std::map<int, base::Callback<void(const std::string&)>> log_callbacks_;
+ std::unique_ptr<AudioServiceListener> audio_service_listener_;
+
GenerateStreamTestCallback generate_stream_test_callback_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamManager);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index 3f169d3d485..14d12b8b1a9 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -22,6 +22,7 @@
#include "content/public/browser/media_observer.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_service_manager_context.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_system_impl.h"
#include "media/audio/fake_audio_log_factory.h"
@@ -108,13 +109,13 @@ class MockAudioManager : public AudioManagerPlatform {
media::AudioParameters GetDefaultOutputStreamParameters() override {
return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
+ media::CHANNEL_LAYOUT_STEREO, 48000, 128);
}
media::AudioParameters GetOutputStreamParameters(
const std::string& device_id) override {
return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
+ media::CHANNEL_LAYOUT_STEREO, 48000, 128);
}
void SetNumAudioOutputDevices(size_t num_devices) {
@@ -166,6 +167,7 @@ class MediaStreamManagerTest : public ::testing::Test {
std::make_unique<media::AudioSystemImpl>(audio_manager_.get());
auto video_capture_provider = std::make_unique<MockVideoCaptureProvider>();
video_capture_provider_ = video_capture_provider.get();
+ service_manager_context_ = std::make_unique<TestServiceManagerContext>();
media_stream_manager_ = std::make_unique<MediaStreamManager>(
audio_system_.get(), audio_manager_->GetTaskRunner(),
std::move(video_capture_provider));
@@ -183,7 +185,10 @@ class MediaStreamManagerTest : public ::testing::Test {
}));
}
- ~MediaStreamManagerTest() override { audio_manager_->Shutdown(); }
+ ~MediaStreamManagerTest() override {
+ audio_manager_->Shutdown();
+ service_manager_context_.reset();
+ }
MOCK_METHOD1(Response, void(int index));
void ResponseCallback(int index,
@@ -210,7 +215,7 @@ class MediaStreamManagerTest : public ::testing::Test {
}
// media_stream_manager_ needs to outlive thread_bundle_ because it is a
- // MessageLoop::DestructionObserver. audio_manager_ needs to outlive
+ // MessageLoopCurrent::DestructionObserver. audio_manager_ needs to outlive
// thread_bundle_ because it uses the underlying message loop.
std::unique_ptr<MediaStreamManager> media_stream_manager_;
std::unique_ptr<MockMediaObserver> media_observer_;
@@ -222,6 +227,8 @@ class MediaStreamManagerTest : public ::testing::Test {
base::RunLoop run_loop_;
private:
+ std::unique_ptr<TestServiceManagerContext> service_manager_context_;
+
DISALLOW_COPY_AND_ASSIGN(MediaStreamManagerTest);
};
diff --git a/chromium/content/browser/renderer_host/media/mock_video_capture_provider.h b/chromium/content/browser/renderer_host/media/mock_video_capture_provider.h
index 34d15c74957..f55304da8a2 100644
--- a/chromium/content/browser/renderer_host/media/mock_video_capture_provider.h
+++ b/chromium/content/browser/renderer_host/media/mock_video_capture_provider.h
@@ -85,7 +85,7 @@ class MockLaunchedVideoCaptureDevice : public LaunchedVideoCaptureDevice {
void SetPhotoOptions(
media::mojom::PhotoSettingsPtr settings,
- media::VideoCaptureDevice::SetPhotoOptionsCallback callback) {
+ media::VideoCaptureDevice::SetPhotoOptionsCallback callback) override {
DoSetPhotoOptions(&settings, &callback);
}
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
new file mode 100644
index 00000000000..0252b256dbd
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.cc
@@ -0,0 +1,237 @@
+// Copyright 2017 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/renderer_host/media/old_render_frame_audio_input_stream_factory.h"
+
+#include <utility>
+
+#include "base/feature_list.h"
+#include "base/task_runner_util.h"
+#include "content/browser/media/media_devices_permission_checker.h"
+#include "content/browser/media/media_internals.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/public/browser/media_device_id.h"
+#include "content/public/common/content_features.h"
+#include "media/base/audio_parameters.h"
+
+namespace content {
+namespace {
+void CheckPermissionAndGetSaltAndOrigin(
+ const std::string& output_device_id,
+ int render_process_id,
+ int render_frame_id,
+ base::OnceCallback<void(const MediaDeviceSaltAndOrigin&)> cb) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auto salt_and_origin =
+ GetMediaDeviceSaltAndOrigin(render_process_id, render_frame_id);
+
+ // Check permissions for everything but the default device
+ if (!media::AudioDeviceDescription::IsDefaultDevice(output_device_id) &&
+ !MediaDevicesPermissionChecker().CheckPermissionOnUIThread(
+ MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, render_process_id, render_frame_id)) {
+ // If we're not allowed to use the device, don't call |cb|.
+ return;
+ }
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(cb), salt_and_origin));
+}
+
+void OldEnumerateOutputDevices(
+ MediaDevicesManager* media_devices_manager,
+ base::RepeatingCallback<
+ void(const MediaDeviceSaltAndOrigin& salt_and_origin,
+ const MediaDeviceEnumeration& devices)> cb,
+ const MediaDeviceSaltAndOrigin& salt_and_origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ MediaDevicesManager::BoolDeviceTypes device_types;
+ device_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
+ media_devices_manager->EnumerateDevices(
+ device_types, base::BindRepeating(cb, salt_and_origin));
+}
+
+} // namespace
+
+// static
+std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>
+RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
+ OldRenderFrameAudioInputStreamFactory::CreateDelegateCallback
+ create_delegate_callback,
+ content::MediaStreamManager* media_stream_manager,
+ int render_process_id,
+ int render_frame_id,
+ mojom::RendererAudioInputStreamFactoryRequest request) {
+ std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>
+ handle(new RenderFrameAudioInputStreamFactoryHandle(
+ std::move(create_delegate_callback), media_stream_manager,
+ render_process_id, render_frame_id));
+ // Unretained is safe since |*handle| must be posted to the IO thread prior to
+ // deletion.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&RenderFrameAudioInputStreamFactoryHandle::Init,
+ base::Unretained(handle.get()), std::move(request)));
+ return handle;
+}
+
+RenderFrameAudioInputStreamFactoryHandle::
+ ~RenderFrameAudioInputStreamFactoryHandle() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+RenderFrameAudioInputStreamFactoryHandle::
+ RenderFrameAudioInputStreamFactoryHandle(
+ OldRenderFrameAudioInputStreamFactory::CreateDelegateCallback
+ create_delegate_callback,
+ MediaStreamManager* media_stream_manager,
+ int render_process_id,
+ int render_frame_id)
+ : impl_(std::move(create_delegate_callback),
+ media_stream_manager,
+ render_process_id,
+ render_frame_id),
+ binding_(&impl_) {}
+
+void RenderFrameAudioInputStreamFactoryHandle::Init(
+ mojom::RendererAudioInputStreamFactoryRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ binding_.Bind(std::move(request));
+}
+
+OldRenderFrameAudioInputStreamFactory::OldRenderFrameAudioInputStreamFactory(
+ CreateDelegateCallback create_delegate_callback,
+ MediaStreamManager* media_stream_manager,
+ int render_process_id,
+ int render_frame_id)
+ : create_delegate_callback_(std::move(create_delegate_callback)),
+ media_stream_manager_(media_stream_manager),
+ render_process_id_(render_process_id),
+ render_frame_id_(render_frame_id),
+ weak_ptr_factory_(this) {
+ DCHECK(create_delegate_callback_);
+ // No thread-hostile state has been initialized yet, so we don't have to bind
+ // to this specific thread.
+}
+
+OldRenderFrameAudioInputStreamFactory::
+ ~OldRenderFrameAudioInputStreamFactory() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void OldRenderFrameAudioInputStreamFactory::CreateStream(
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
+ int32_t session_id,
+ const media::AudioParameters& audio_params,
+ bool automatic_gain_control,
+ uint32_t shared_memory_count) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+#if defined(OS_CHROMEOS)
+ if (audio_params.channel_layout() ==
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
+ media_stream_manager_->audio_input_device_manager()
+ ->RegisterKeyboardMicStream(base::BindOnce(
+ &OldRenderFrameAudioInputStreamFactory::DoCreateStream,
+ weak_ptr_factory_.GetWeakPtr(), std::move(client), session_id,
+ audio_params, automatic_gain_control, shared_memory_count));
+ return;
+ }
+#endif
+ DoCreateStream(std::move(client), session_id, audio_params,
+ automatic_gain_control, shared_memory_count,
+ AudioInputDeviceManager::KeyboardMicRegistration());
+}
+
+void OldRenderFrameAudioInputStreamFactory::DoCreateStream(
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
+ int session_id,
+ const media::AudioParameters& audio_params,
+ bool automatic_gain_control,
+ uint32_t shared_memory_count,
+ AudioInputDeviceManager::KeyboardMicRegistration
+ keyboard_mic_registration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int stream_id = ++next_stream_id_;
+
+ media::mojom::AudioLogPtr audio_log_ptr =
+ MediaInternals::GetInstance()->CreateMojoAudioLog(
+ media::AudioLogFactory::AUDIO_INPUT_CONTROLLER, stream_id,
+ render_process_id_, render_frame_id_);
+
+ // Unretained is safe since |this| owns |streams_|.
+ streams_.insert(std::make_unique<AudioInputStreamHandle>(
+ std::move(client),
+ base::BindOnce(
+ create_delegate_callback_,
+ base::Unretained(media_stream_manager_->audio_input_device_manager()),
+ std::move(audio_log_ptr), std::move(keyboard_mic_registration),
+ shared_memory_count, stream_id, session_id, automatic_gain_control,
+ audio_params),
+ base::BindOnce(&OldRenderFrameAudioInputStreamFactory::RemoveStream,
+ weak_ptr_factory_.GetWeakPtr())));
+}
+
+void OldRenderFrameAudioInputStreamFactory::AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!IsValidDeviceId(output_device_id))
+ return;
+
+ if (media::AudioDeviceDescription::IsDefaultDevice(output_device_id)) {
+ for (const auto& stream : streams_) {
+ if (stream->id() == input_stream_id) {
+ stream->SetOutputDeviceForAec(output_device_id);
+ return;
+ }
+ }
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ CheckPermissionAndGetSaltAndOrigin, output_device_id,
+ render_process_id_, render_frame_id_,
+ base::BindOnce(
+ &OldEnumerateOutputDevices,
+ media_stream_manager_->media_devices_manager(),
+ base::BindRepeating(&OldRenderFrameAudioInputStreamFactory::
+ TranslateAndSetOutputDeviceForAec,
+ weak_ptr_factory_.GetWeakPtr(),
+ input_stream_id, output_device_id))));
+ }
+}
+
+void OldRenderFrameAudioInputStreamFactory::TranslateAndSetOutputDeviceForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
+ const MediaDeviceEnumeration& device_array) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::string raw_output_device_id;
+ for (const auto& device_info : device_array[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
+ if (MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+ salt_and_origin.device_id_salt, salt_and_origin.origin,
+ output_device_id, device_info.device_id)) {
+ raw_output_device_id = device_info.device_id;
+ }
+ }
+ if (!raw_output_device_id.empty()) {
+ for (const auto& stream : streams_) {
+ if (stream->id() == input_stream_id) {
+ stream->SetOutputDeviceForAec(raw_output_device_id);
+ return;
+ }
+ }
+ }
+}
+
+void OldRenderFrameAudioInputStreamFactory::RemoveStream(
+ AudioInputStreamHandle* stream) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ streams_.erase(stream);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h
new file mode 100644
index 00000000000..629b75e508b
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory.h
@@ -0,0 +1,149 @@
+// Copyright 2017 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_RENDERER_HOST_MEDIA_OLD_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_OLD_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/containers/flat_set.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "content/browser/media/media_devices_util.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
+#include "content/browser/renderer_host/media/audio_input_stream_handle.h"
+#include "content/browser/renderer_host/media/media_devices_manager.h"
+#include "content/common/content_export.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "content/public/browser/browser_thread.h"
+#include "media/audio/audio_input_delegate.h"
+#include "media/mojo/interfaces/audio_logging.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace media {
+class AudioParameters;
+} // namespace media
+
+namespace content {
+
+class MediaStreamManager;
+
+// Handles a RendererAudioInputStreamFactory request for a render frame host,
+// using the provided RendererAudioInputStreamFactoryContext. This class may
+// be constructed on any thread, but must be used on the IO thread after that,
+// and also destructed on the IO thread. It is being
+// replaced by RenderFrameAudioInputStreamFactory, which forwards stream
+// requests to the audio service (https://crbug.com/830493).
+class CONTENT_EXPORT OldRenderFrameAudioInputStreamFactory
+ : public mojom::RendererAudioInputStreamFactory {
+ public:
+ using CreateDelegateCallback =
+ base::RepeatingCallback<std::unique_ptr<media::AudioInputDelegate>(
+ AudioInputDeviceManager* audio_input_device_manager,
+ media::mojom::AudioLogPtr audio_log,
+ AudioInputDeviceManager::KeyboardMicRegistration
+ keyboard_mic_registration,
+ uint32_t shared_memory_count,
+ int stream_id,
+ int session_id,
+ bool automatic_gain_control,
+ const media::AudioParameters& parameters,
+ media::AudioInputDelegate::EventHandler* event_handler)>;
+
+ OldRenderFrameAudioInputStreamFactory(
+ CreateDelegateCallback create_delegate_callback,
+ MediaStreamManager* media_stream_manager,
+ int render_process_id,
+ int render_frame_id);
+
+ ~OldRenderFrameAudioInputStreamFactory() override;
+
+ private:
+ using InputStreamSet = base::flat_set<std::unique_ptr<AudioInputStreamHandle>,
+ base::UniquePtrComparator>;
+
+ // mojom::RendererAudioInputStreamFactory implementation.
+ void CreateStream(mojom::RendererAudioInputStreamFactoryClientPtr client,
+ int32_t session_id,
+ const media::AudioParameters& audio_params,
+ bool automatic_gain_control,
+ uint32_t shared_memory_count) override;
+
+ void DoCreateStream(mojom::RendererAudioInputStreamFactoryClientPtr client,
+ int session_id,
+ const media::AudioParameters& audio_params,
+ bool automatic_gain_control,
+ uint32_t shared_memory_count,
+ AudioInputDeviceManager::KeyboardMicRegistration
+ keyboard_mic_registration);
+
+ void AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id) override;
+
+ void TranslateAndSetOutputDeviceForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
+ const MediaDeviceEnumeration& devices);
+
+ void RemoveStream(AudioInputStreamHandle* input_stream);
+
+ const CreateDelegateCallback create_delegate_callback_;
+ MediaStreamManager* media_stream_manager_;
+ const int render_process_id_;
+ const int render_frame_id_;
+
+ InputStreamSet streams_;
+ int next_stream_id_ = 0;
+
+ base::WeakPtrFactory<OldRenderFrameAudioInputStreamFactory> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OldRenderFrameAudioInputStreamFactory);
+};
+
+// This class is a convenient bundle of factory and binding.
+// It can be created on any thread, but should be destroyed on the IO thread
+// (hence the DeleteOnIOThread pointer).
+class CONTENT_EXPORT RenderFrameAudioInputStreamFactoryHandle {
+ public:
+ static std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>
+ CreateFactory(OldRenderFrameAudioInputStreamFactory::CreateDelegateCallback
+ create_delegate_callback,
+ MediaStreamManager* media_stream_manager,
+ int render_process_id,
+ int render_frame_id,
+ mojom::RendererAudioInputStreamFactoryRequest request);
+
+ ~RenderFrameAudioInputStreamFactoryHandle();
+
+ private:
+ RenderFrameAudioInputStreamFactoryHandle(
+ OldRenderFrameAudioInputStreamFactory::CreateDelegateCallback
+ create_delegate_callback,
+ MediaStreamManager* media_stream_manager,
+ int render_process_id,
+ int render_frame_id);
+
+ void Init(mojom::RendererAudioInputStreamFactoryRequest request);
+
+ OldRenderFrameAudioInputStreamFactory impl_;
+ mojo::Binding<mojom::RendererAudioInputStreamFactory> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioInputStreamFactoryHandle);
+};
+
+using UniqueAudioInputStreamFactoryPtr =
+ std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>;
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_OLD_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
new file mode 100644
index 00000000000..206fa9c9755
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc
@@ -0,0 +1,176 @@
+// Copyright 2017 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/renderer_host/media/old_render_frame_audio_input_stream_factory.h"
+
+#include <limits>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/sync_socket.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/audio/audio_system_impl.h"
+#include "media/audio/mock_audio_manager.h"
+#include "media/audio/test_audio_thread.h"
+#include "media/base/audio_parameters.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+using testing::Test;
+
+const size_t kShmemSize = 1234;
+const int kSessionId = 234;
+const bool kAGC = false;
+const uint32_t kSharedMemoryCount = 345;
+const int kSampleFrequency = 44100;
+const int kSamplesPerBuffer = kSampleFrequency / 100;
+const bool kInitiallyMuted = false;
+const int kRenderProcessID = -1;
+const int kRenderFrameID = MSG_ROUTING_NONE;
+
+media::AudioParameters GetTestAudioParameters() {
+ return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
+ kSamplesPerBuffer);
+}
+
+class FakeAudioInputDelegate : public media::AudioInputDelegate {
+ public:
+ FakeAudioInputDelegate() {}
+
+ ~FakeAudioInputDelegate() override {}
+
+ int GetStreamId() override { return 0; };
+ void OnRecordStream() override{};
+ void OnSetVolume(double volume) override{};
+ void OnSetOutputDeviceForAec(const std::string& output_device_id) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeAudioInputDelegate);
+};
+
+class FakeAudioInputStreamClient : public media::mojom::AudioInputStreamClient {
+ public:
+ void OnMutedStateChanged(bool is_muted) override {}
+ void OnError() override {}
+};
+
+class MockRendererAudioInputStreamFactoryClient
+ : public mojom::RendererAudioInputStreamFactoryClient {
+ public:
+ MOCK_METHOD0(Created, void());
+
+ void StreamCreated(
+ media::mojom::AudioInputStreamPtr input_stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::AudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override {
+ EXPECT_TRUE(stream_id.has_value());
+ Created();
+ }
+};
+
+// Creates a fake delegate and saves the provided event handler in
+// |event_handler_out|.
+std::unique_ptr<media::AudioInputDelegate> CreateFakeDelegate(
+ media::AudioInputDelegate::EventHandler** event_handler_out,
+ AudioInputDeviceManager* audio_input_device_manager,
+ media::mojom::AudioLogPtr audio_log,
+ AudioInputDeviceManager::KeyboardMicRegistration keyboard_mic_registration,
+ uint32_t shared_memory_count,
+ int stream_id,
+ int session_id,
+ bool automatic_gain_control,
+ const media::AudioParameters& parameters,
+ media::AudioInputDelegate::EventHandler* event_handler) {
+ *event_handler_out = event_handler;
+ return std::make_unique<FakeAudioInputDelegate>();
+}
+
+} // namespace
+
+class OldOldRenderFrameAudioInputStreamFactoryTest : public testing::Test {
+ public:
+ OldOldRenderFrameAudioInputStreamFactoryTest()
+ : thread_bundle_(base::in_place),
+ audio_manager_(std::make_unique<media::TestAudioThread>()),
+ audio_system_(&audio_manager_),
+ media_stream_manager_(&audio_system_, audio_manager_.GetTaskRunner()),
+ client_binding_(&client_, mojo::MakeRequest(&client_ptr_)),
+ factory_handle_(RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
+ base::BindRepeating(&CreateFakeDelegate, &event_handler_),
+ &media_stream_manager_,
+ kRenderProcessID,
+ kRenderFrameID,
+ mojo::MakeRequest(&factory_ptr_))) {}
+
+ ~OldOldRenderFrameAudioInputStreamFactoryTest() override {
+ audio_manager_.Shutdown();
+
+ // UniqueAudioInputStreamFactoryPtr uses DeleteOnIOThread and must run
+ // before |thread_bundle_| tear down.
+ factory_handle_.reset();
+
+ // Shutdown BrowserThread::IO before tearing down members.
+ thread_bundle_.reset();
+ }
+
+ // |thread_bundle_| needs to be up before the members below (as they use
+ // BrowserThreads for their initialization) but then needs to be torn down
+ // before them as some verify they're town down in a single-threaded
+ // environment (while
+ // !BrowserThread::IsThreadInitiaslized(BrowserThread::IO)).
+ base::Optional<TestBrowserThreadBundle> thread_bundle_;
+
+ // These members need to be torn down after |thread_bundle_|.
+ media::MockAudioManager audio_manager_;
+ media::AudioSystemImpl audio_system_;
+ MediaStreamManager media_stream_manager_;
+
+ mojom::RendererAudioInputStreamFactoryPtr factory_ptr_;
+ media::mojom::AudioInputStreamPtr stream_ptr_;
+ MockRendererAudioInputStreamFactoryClient client_;
+ mojom::RendererAudioInputStreamFactoryClientPtr client_ptr_;
+ media::AudioInputDelegate::EventHandler* event_handler_ = nullptr;
+ mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> client_binding_;
+ UniqueAudioInputStreamFactoryPtr factory_handle_;
+};
+
+TEST_F(OldOldRenderFrameAudioInputStreamFactoryTest, CreateStream) {
+ factory_ptr_->CreateStream(std::move(client_ptr_), kSessionId,
+ GetTestAudioParameters(), kAGC,
+ kSharedMemoryCount);
+
+ // Wait for delegate to be created and |event_handler| set.
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(event_handler_);
+ auto shared_memory = base::ReadOnlySharedMemoryRegion::Create(kShmemSize);
+ auto local = std::make_unique<base::CancelableSyncSocket>();
+ auto remote = std::make_unique<base::CancelableSyncSocket>();
+ ASSERT_TRUE(
+ base::CancelableSyncSocket::CreatePair(local.get(), remote.get()));
+ event_handler_->OnStreamCreated(/*stream_id, irrelevant*/ 0,
+ std::move(shared_memory.region),
+ std::move(remote), kInitiallyMuted);
+
+ EXPECT_CALL(client_, Created());
+ base::RunLoop().RunUntilIdle();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.cc
new file mode 100644
index 00000000000..df02e54c4e6
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.cc
@@ -0,0 +1,140 @@
+// Copyright 2017 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/renderer_host/media/old_render_frame_audio_output_stream_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/task_runner_util.h"
+#include "content/browser/renderer_host/media/audio_output_authorization_handler.h"
+#include "content/browser/renderer_host/media/audio_output_stream_observer_impl.h"
+#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h"
+#include "content/public/browser/render_frame_host.h"
+#include "media/base/audio_parameters.h"
+#include "media/mojo/services/mojo_audio_output_stream_provider.h"
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace content {
+
+// static
+std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>
+RenderFrameAudioOutputStreamFactoryHandle::CreateFactory(
+ RendererAudioOutputStreamFactoryContext* context,
+ int render_frame_id,
+ mojom::RendererAudioOutputStreamFactoryRequest request) {
+ std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>
+ handle(new RenderFrameAudioOutputStreamFactoryHandle(context,
+ render_frame_id));
+ // Unretained is safe since |*handle| must be posted to the IO thread prior to
+ // deletion.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&RenderFrameAudioOutputStreamFactoryHandle::Init,
+ base::Unretained(handle.get()), std::move(request)));
+ return handle;
+}
+
+RenderFrameAudioOutputStreamFactoryHandle::
+ ~RenderFrameAudioOutputStreamFactoryHandle() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+RenderFrameAudioOutputStreamFactoryHandle::
+ RenderFrameAudioOutputStreamFactoryHandle(
+ RendererAudioOutputStreamFactoryContext* context,
+ int render_frame_id)
+ : impl_(render_frame_id, context), binding_(&impl_) {}
+
+void RenderFrameAudioOutputStreamFactoryHandle::Init(
+ mojom::RendererAudioOutputStreamFactoryRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ binding_.Bind(std::move(request));
+}
+
+OldRenderFrameAudioOutputStreamFactory::OldRenderFrameAudioOutputStreamFactory(
+ int render_frame_id,
+ RendererAudioOutputStreamFactoryContext* context)
+ : render_frame_id_(render_frame_id),
+ context_(context),
+ weak_ptr_factory_(this) {
+ DCHECK(context_);
+}
+
+OldRenderFrameAudioOutputStreamFactory::
+ ~OldRenderFrameAudioOutputStreamFactory() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ UMA_HISTOGRAM_EXACT_LINEAR("Media.Audio.OutputStreamsCanceledByBrowser",
+ stream_providers_.size(), 50);
+ // Make sure to close all streams.
+ stream_providers_.clear();
+}
+
+void OldRenderFrameAudioOutputStreamFactory::RequestDeviceAuthorization(
+ media::mojom::AudioOutputStreamProviderRequest stream_provider_request,
+ int32_t session_id,
+ const std::string& device_id,
+ RequestDeviceAuthorizationCallback callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const base::TimeTicks auth_start_time = base::TimeTicks::Now();
+
+ context_->RequestDeviceAuthorization(
+ render_frame_id_, session_id, device_id,
+ base::BindOnce(
+ &OldRenderFrameAudioOutputStreamFactory::AuthorizationCompleted,
+ weak_ptr_factory_.GetWeakPtr(), auth_start_time,
+ std::move(stream_provider_request), std::move(callback)));
+}
+
+void OldRenderFrameAudioOutputStreamFactory::AuthorizationCompleted(
+ base::TimeTicks auth_start_time,
+ media::mojom::AudioOutputStreamProviderRequest request,
+ RequestDeviceAuthorizationCallback callback,
+ media::OutputDeviceStatus status,
+ const media::AudioParameters& params,
+ const std::string& raw_device_id,
+ const std::string& device_id_for_renderer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ AudioOutputAuthorizationHandler::UMALogDeviceAuthorizationTime(
+ auth_start_time);
+
+ if (status != media::OUTPUT_DEVICE_STATUS_OK) {
+ std::move(callback).Run(media::OutputDeviceStatus(status),
+ media::AudioParameters::UnavailableDeviceParams(),
+ std::string());
+ return;
+ }
+
+ int stream_id = next_stream_id_++;
+ std::unique_ptr<media::mojom::AudioOutputStreamObserver> observer =
+ std::make_unique<AudioOutputStreamObserverImpl>(
+ context_->GetRenderProcessId(), render_frame_id_, stream_id);
+ // Since |context_| outlives |this| and |this| outlives |stream_providers_|,
+ // unretained is safe.
+ stream_providers_.insert(
+ std::make_unique<media::MojoAudioOutputStreamProvider>(
+ std::move(request),
+ base::BindOnce(
+ &RendererAudioOutputStreamFactoryContext::CreateDelegate,
+ base::Unretained(context_), raw_device_id, render_frame_id_,
+ stream_id),
+ base::BindOnce(&OldRenderFrameAudioOutputStreamFactory::RemoveStream,
+ base::Unretained(this)),
+ std::move(observer)));
+
+ std::move(callback).Run(media::OutputDeviceStatus(status), params,
+ device_id_for_renderer);
+}
+
+void OldRenderFrameAudioOutputStreamFactory::RemoveStream(
+ media::mojom::AudioOutputStreamProvider* stream_provider) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ stream_providers_.erase(stream_provider);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.h b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.h
new file mode 100644
index 00000000000..f0d241319c5
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.h
@@ -0,0 +1,109 @@
+// Copyright 2017 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_RENDERER_HOST_MEDIA_OLD_RENDER_FRAME_AUDIO_OUTPUT_STREAM_FACTORY_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_OLD_RENDER_FRAME_AUDIO_OUTPUT_STREAM_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "content/common/content_export.h"
+#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace content {
+
+class RendererAudioOutputStreamFactoryContext;
+
+// Handles a RendererAudioOutputStreamFactory request for a render frame host,
+// using the provided RendererAudioOutputStreamFactoryContext. This class may
+// be constructed on any thread, but must be used on the IO thread after that.
+// This class is used for creating streams hosted by the browser. It is being
+// replaced by RenderFrameAudioOutputStreamFactory, which forwards stream
+// requests to the audio service (https://crbug.com/830493).
+class CONTENT_EXPORT OldRenderFrameAudioOutputStreamFactory
+ : public mojom::RendererAudioOutputStreamFactory {
+ public:
+ OldRenderFrameAudioOutputStreamFactory(
+ int render_frame_id,
+ RendererAudioOutputStreamFactoryContext* context);
+
+ ~OldRenderFrameAudioOutputStreamFactory() override;
+
+ private:
+ using OutputStreamProviderSet =
+ base::flat_set<std::unique_ptr<media::mojom::AudioOutputStreamProvider>,
+ base::UniquePtrComparator>;
+
+ // mojom::RendererAudioOutputStreamFactory implementation.
+ void RequestDeviceAuthorization(
+ media::mojom::AudioOutputStreamProviderRequest stream_provider,
+ int32_t session_id,
+ const std::string& device_id,
+ RequestDeviceAuthorizationCallback callback) override;
+
+ // Here, the |raw_device_id| is used to create the stream, and
+ // |device_id_for_renderer| is nonempty in the case when the renderer
+ // requested a device using a |session_id|, to let it know which device was
+ // chosen. This id is hashed.
+ void AuthorizationCompleted(
+ base::TimeTicks auth_start_time,
+ media::mojom::AudioOutputStreamProviderRequest request,
+ RequestDeviceAuthorizationCallback callback,
+ media::OutputDeviceStatus status,
+ const media::AudioParameters& params,
+ const std::string& raw_device_id,
+ const std::string& device_id_for_renderer);
+
+ void RemoveStream(media::mojom::AudioOutputStreamProvider* stream_provider);
+
+ const int render_frame_id_;
+ RendererAudioOutputStreamFactoryContext* const context_;
+
+ // The stream providers will contain the corresponding streams.
+ OutputStreamProviderSet stream_providers_;
+
+ // All streams require IDs. Use a counter to generate them.
+ int next_stream_id_ = 0;
+
+ base::WeakPtrFactory<OldRenderFrameAudioOutputStreamFactory>
+ weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OldRenderFrameAudioOutputStreamFactory);
+};
+
+// This class is a convenient bundle of factory and binding.
+class CONTENT_EXPORT RenderFrameAudioOutputStreamFactoryHandle {
+ public:
+ static std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>
+ CreateFactory(RendererAudioOutputStreamFactoryContext* context,
+ int render_frame_id,
+ mojom::RendererAudioOutputStreamFactoryRequest request);
+
+ ~RenderFrameAudioOutputStreamFactoryHandle();
+
+ private:
+ RenderFrameAudioOutputStreamFactoryHandle(
+ RendererAudioOutputStreamFactoryContext* context,
+ int render_frame_id);
+
+ void Init(mojom::RendererAudioOutputStreamFactoryRequest request);
+
+ OldRenderFrameAudioOutputStreamFactory impl_;
+ mojo::Binding<mojom::RendererAudioOutputStreamFactory> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioOutputStreamFactoryHandle);
+};
+
+using UniqueAudioOutputStreamFactoryPtr =
+ std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
+ BrowserThread::DeleteOnIOThread>;
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_OLD_RENDER_FRAME_AUDIO_OUTPUT_STREAM_FACTORY_H_
diff --git a/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc
new file mode 100644
index 00000000000..94a1fb4c25a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc
@@ -0,0 +1,337 @@
+// Copyright 2017 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/renderer_host/media/old_render_frame_audio_output_stream_factory.h"
+
+#include <limits>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/run_loop.h"
+#include "base/sync_socket.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h"
+#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/base/audio_parameters.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+using testing::Test;
+using AudioOutputStreamFactory = mojom::RendererAudioOutputStreamFactory;
+using AudioOutputStreamFactoryPtr =
+ mojo::InterfacePtr<AudioOutputStreamFactory>;
+using AudioOutputStreamFactoryRequest =
+ mojo::InterfaceRequest<AudioOutputStreamFactory>;
+using AudioOutputStream = media::mojom::AudioOutputStream;
+using AudioOutputStreamPtr = mojo::InterfacePtr<AudioOutputStream>;
+using AudioOutputStreamRequest = mojo::InterfaceRequest<AudioOutputStream>;
+using AudioOutputStreamProviderClient =
+ media::mojom::AudioOutputStreamProviderClient;
+using AudioOutputStreamProviderClientPtr =
+ mojo::InterfacePtr<AudioOutputStreamProviderClient>;
+using AudioOutputStreamProviderClientRequest =
+ mojo::InterfaceRequest<AudioOutputStreamProviderClient>;
+using AudioOutputStreamProvider = media::mojom::AudioOutputStreamProvider;
+using AudioOutputStreamProviderPtr =
+ mojo::InterfacePtr<AudioOutputStreamProvider>;
+using AudioOutputStreamProviderRequest =
+ mojo::InterfaceRequest<AudioOutputStreamProvider>;
+
+const int kStreamId = 0;
+const int kNoSessionId = 0;
+const int kRenderProcessId = 42;
+const int kRenderFrameId = 24;
+const int kSampleFrequency = 44100;
+const int kSamplesPerBuffer = kSampleFrequency / 100;
+const char kSalt[] = "salt";
+
+media::AudioParameters GetTestAudioParameters() {
+ return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
+ kSamplesPerBuffer);
+}
+
+class MockAudioOutputDelegate : public media::AudioOutputDelegate {
+ public:
+ // |on_destruction| can be used to observe the destruction of the delegate.
+ explicit MockAudioOutputDelegate(
+ base::OnceClosure on_destruction = base::OnceClosure())
+ : on_destruction_(std::move(on_destruction)) {}
+
+ ~MockAudioOutputDelegate() override {
+ if (on_destruction_)
+ std::move(on_destruction_).Run();
+ }
+
+ MOCK_METHOD0(GetStreamId, int());
+ MOCK_METHOD0(OnPlayStream, void());
+ MOCK_METHOD0(OnPauseStream, void());
+ MOCK_METHOD1(OnSetVolume, void(double));
+
+ private:
+ base::OnceClosure on_destruction_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockAudioOutputDelegate);
+};
+
+class MockContext : public RendererAudioOutputStreamFactoryContext {
+ public:
+ explicit MockContext(bool auth_ok) : salt_(kSalt), auth_ok_(auth_ok) {}
+
+ ~MockContext() override { EXPECT_EQ(nullptr, delegate_); }
+
+ int GetRenderProcessId() const override { return kRenderProcessId; }
+
+ void RequestDeviceAuthorization(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ AuthorizationCompletedCallback cb) const override {
+ EXPECT_EQ(render_frame_id, kRenderFrameId);
+ EXPECT_EQ(session_id, 0);
+ if (auth_ok_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(cb),
+ media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
+ GetTestAudioParameters(), "default", std::string()));
+ return;
+ }
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(cb),
+ media::OutputDeviceStatus::
+ OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
+ media::AudioParameters::UnavailableDeviceParams(),
+ std::string(), std::string()));
+ }
+
+ // The event handler for the delegate will be stored at
+ // |*event_handler_location| when the delegate is created.
+ void PrepareDelegateForCreation(
+ std::unique_ptr<media::AudioOutputDelegate> delegate,
+ media::AudioOutputDelegate::EventHandler** event_handler_location) {
+ EXPECT_EQ(nullptr, delegate_);
+ EXPECT_EQ(nullptr, delegate_event_handler_location_);
+ delegate_ = std::move(delegate);
+ delegate_event_handler_location_ = event_handler_location;
+ }
+
+ std::unique_ptr<media::AudioOutputDelegate> CreateDelegate(
+ const std::string& unique_device_id,
+ int render_frame_id,
+ int stream_id,
+ const media::AudioParameters& params,
+ media::mojom::AudioOutputStreamObserverPtr stream_observer,
+ media::AudioOutputDelegate::EventHandler* handler) override {
+ EXPECT_NE(nullptr, delegate_);
+ EXPECT_NE(nullptr, delegate_event_handler_location_);
+ *delegate_event_handler_location_ = handler;
+ delegate_event_handler_location_ = nullptr;
+ return std::move(delegate_);
+ }
+
+ AudioOutputStreamFactoryPtr CreateFactory() {
+ DCHECK(!factory_);
+ AudioOutputStreamFactoryPtr ret;
+ factory_ = std::make_unique<OldRenderFrameAudioOutputStreamFactory>(
+ kRenderFrameId, this);
+ factory_binding_ = std::make_unique<
+ mojo::Binding<mojom::RendererAudioOutputStreamFactory>>(
+ factory_.get(), mojo::MakeRequest(&ret));
+ return ret;
+ }
+
+ private:
+ const std::string salt_;
+ const bool auth_ok_;
+ std::unique_ptr<OldRenderFrameAudioOutputStreamFactory> factory_;
+ std::unique_ptr<mojo::Binding<mojom::RendererAudioOutputStreamFactory>>
+ factory_binding_;
+ std::unique_ptr<media::AudioOutputDelegate> delegate_;
+ media::AudioOutputDelegate::EventHandler** delegate_event_handler_location_ =
+ nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(MockContext);
+};
+
+class MockClient : public AudioOutputStreamProviderClient {
+ public:
+ MockClient() : provider_client_binding_(this) {}
+ ~MockClient() override {}
+
+ AudioOutputStreamProviderClientPtr MakeProviderClientPtr() {
+ AudioOutputStreamProviderClientPtr p;
+ provider_client_binding_.Bind(mojo::MakeRequest(&p));
+ return p;
+ }
+
+ void Created(AudioOutputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe) override {
+ was_called_ = true;
+ stream_ = std::move(stream);
+ }
+
+ bool was_called() { return was_called_; }
+
+ MOCK_METHOD0(OnError, void());
+
+ private:
+ mojo::Binding<AudioOutputStreamProviderClient> provider_client_binding_;
+ AudioOutputStreamPtr stream_;
+ bool was_called_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(MockClient);
+};
+
+void AuthCallback(media::OutputDeviceStatus* status_out,
+ media::AudioParameters* params_out,
+ std::string* id_out,
+ media::OutputDeviceStatus status,
+ const media::AudioParameters& params,
+ const std::string& id) {
+ *status_out = status;
+ *params_out = params;
+ *id_out = id;
+}
+
+} // namespace
+
+// This test authorizes and creates a stream, and checks that
+// 1. the ProviderClient callback is called with appropriate parameters.
+// 2. the AudioOutputDelegate is created.
+// 3. when the delegate calls OnStreamCreated, this is propagated to the client.
+TEST(OldRenderFrameAudioOutputStreamFactoryTest, CreateStream) {
+ content::TestBrowserThreadBundle thread_bundle;
+ AudioOutputStreamProviderPtr provider;
+ MockClient client;
+ media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
+ auto factory_context = std::make_unique<MockContext>(true);
+ factory_context->PrepareDelegateForCreation(
+ std::make_unique<MockAudioOutputDelegate>(), &event_handler);
+ AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
+
+ media::OutputDeviceStatus status;
+ media::AudioParameters params;
+ std::string id;
+ factory_ptr->RequestDeviceAuthorization(
+ mojo::MakeRequest(&provider), kNoSessionId, "default",
+ base::BindOnce(&AuthCallback, base::Unretained(&status),
+ base::Unretained(&params), base::Unretained(&id)));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_OK);
+ EXPECT_EQ(params.AsHumanReadableString(),
+ GetTestAudioParameters().AsHumanReadableString());
+ EXPECT_TRUE(id.empty());
+
+ provider->Acquire(params, client.MakeProviderClientPtr());
+ base::RunLoop().RunUntilIdle();
+ ASSERT_NE(event_handler, nullptr);
+
+ base::UnsafeSharedMemoryRegion shared_memory_region =
+ base::UnsafeSharedMemoryRegion::Create(100);
+ ASSERT_TRUE(shared_memory_region.IsValid());
+
+ auto local = std::make_unique<base::CancelableSyncSocket>();
+ auto remote = std::make_unique<base::CancelableSyncSocket>();
+ ASSERT_TRUE(
+ base::CancelableSyncSocket::CreatePair(local.get(), remote.get()));
+ event_handler->OnStreamCreated(kStreamId, std::move(shared_memory_region),
+ std::move(remote));
+
+ base::RunLoop().RunUntilIdle();
+ // Make sure we got the callback from creating stream.
+ EXPECT_TRUE(client.was_called());
+}
+
+TEST(OldRenderFrameAudioOutputStreamFactoryTest, NotAuthorized_Denied) {
+ content::TestBrowserThreadBundle thread_bundle;
+ AudioOutputStreamProviderPtr output_provider;
+ auto factory_context = std::make_unique<MockContext>(false);
+ AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
+
+ media::OutputDeviceStatus status;
+ media::AudioParameters params;
+ std::string id;
+ factory_ptr->RequestDeviceAuthorization(
+ mojo::MakeRequest(&output_provider), kNoSessionId, "default",
+ base::BindOnce(&AuthCallback, base::Unretained(&status),
+ base::Unretained(&params), base::Unretained(&id)));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED);
+ EXPECT_TRUE(id.empty());
+}
+
+TEST(OldRenderFrameAudioOutputStreamFactoryTest,
+ ConnectionError_DeletesStream) {
+ content::TestBrowserThreadBundle thread_bundle;
+ AudioOutputStreamProviderPtr provider;
+ MockClient client;
+ bool delegate_is_destructed = false;
+ media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
+ auto factory_context = std::make_unique<MockContext>(true);
+ factory_context->PrepareDelegateForCreation(
+ std::make_unique<MockAudioOutputDelegate>(
+ base::BindOnce([](bool* destructed) { *destructed = true; },
+ &delegate_is_destructed)),
+ &event_handler);
+ AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
+
+ factory_ptr->RequestDeviceAuthorization(
+ mojo::MakeRequest(&provider), kNoSessionId, "default",
+ base::BindOnce([](media::OutputDeviceStatus status,
+ const media::AudioParameters& params,
+ const std::string& id) {}));
+ base::RunLoop().RunUntilIdle();
+
+ provider->Acquire(GetTestAudioParameters(), client.MakeProviderClientPtr());
+ base::RunLoop().RunUntilIdle();
+ ASSERT_NE(event_handler, nullptr);
+ EXPECT_FALSE(delegate_is_destructed);
+ provider.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(delegate_is_destructed);
+}
+
+TEST(OldRenderFrameAudioOutputStreamFactoryTest, DelegateError_DeletesStream) {
+ content::TestBrowserThreadBundle thread_bundle;
+ AudioOutputStreamProviderPtr provider;
+ MockClient client;
+ bool delegate_is_destructed = false;
+ media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
+ auto factory_context = std::make_unique<MockContext>(true);
+ factory_context->PrepareDelegateForCreation(
+ std::make_unique<MockAudioOutputDelegate>(
+ base::BindOnce([](bool* destructed) { *destructed = true; },
+ &delegate_is_destructed)),
+ &event_handler);
+ AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
+
+ factory_ptr->RequestDeviceAuthorization(
+ mojo::MakeRequest(&provider), kNoSessionId, "default",
+ base::BindOnce([](media::OutputDeviceStatus status,
+ const media::AudioParameters& params,
+ const std::string& id) {}));
+ base::RunLoop().RunUntilIdle();
+
+ provider->Acquire(GetTestAudioParameters(), client.MakeProviderClientPtr());
+ base::RunLoop().RunUntilIdle();
+ ASSERT_NE(event_handler, nullptr);
+ EXPECT_FALSE(delegate_is_destructed);
+ event_handler->OnStreamError(kStreamId);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(delegate_is_destructed);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
index 2af4e2a6839..7a264cbd8cd 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 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.
@@ -6,86 +6,82 @@
#include <utility>
-#include "base/feature_list.h"
-#include "base/task_runner_util.h"
-#include "content/browser/media/media_internals.h"
+#include "base/trace_event/trace_event.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
+#include "content/browser/media/forwarding_audio_stream_factory.h"
+#include "content/browser/media/media_devices_permission_checker.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/public/common/content_features.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/media_device_id.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents_media_capture_id.h"
+#include "content/public/common/media_stream_request.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_input_device.h"
#include "media/base/audio_parameters.h"
namespace content {
-// static
-std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>
-RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
- RenderFrameAudioInputStreamFactory::CreateDelegateCallback
- create_delegate_callback,
- content::MediaStreamManager* media_stream_manager,
- int render_process_id,
- int render_frame_id,
- mojom::RendererAudioInputStreamFactoryRequest request) {
- std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>
- handle(new RenderFrameAudioInputStreamFactoryHandle(
- std::move(create_delegate_callback), media_stream_manager,
- render_process_id, render_frame_id));
- // Unretained is safe since |*handle| must be posted to the IO thread prior to
- // deletion.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&RenderFrameAudioInputStreamFactoryHandle::Init,
- base::Unretained(handle.get()), std::move(request)));
- return handle;
+namespace {
+
+void LookUpDeviceAndRespondIfFound(
+ scoped_refptr<AudioInputDeviceManager> audio_input_device_manager,
+ int32_t session_id,
+ base::OnceCallback<void(const MediaStreamDevice&)> response) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const MediaStreamDevice* device =
+ audio_input_device_manager->GetOpenedDeviceById(session_id);
+ if (device) {
+ // Copies device.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(response), *device));
+ }
}
-RenderFrameAudioInputStreamFactoryHandle::
- ~RenderFrameAudioInputStreamFactoryHandle() {
+void EnumerateOutputDevices(MediaStreamManager* media_stream_manager,
+ MediaDevicesManager::EnumerationCallback cb) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ MediaDevicesManager::BoolDeviceTypes device_types;
+ device_types[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
+ media_stream_manager->media_devices_manager()->EnumerateDevices(device_types,
+ cb);
}
-RenderFrameAudioInputStreamFactoryHandle::
- RenderFrameAudioInputStreamFactoryHandle(
- RenderFrameAudioInputStreamFactory::CreateDelegateCallback
- create_delegate_callback,
- MediaStreamManager* media_stream_manager,
- int render_process_id,
- int render_frame_id)
- : impl_(std::move(create_delegate_callback),
- media_stream_manager,
- render_process_id,
- render_frame_id),
- binding_(&impl_) {}
-
-void RenderFrameAudioInputStreamFactoryHandle::Init(
- mojom::RendererAudioInputStreamFactoryRequest request) {
+void TranslateDeviceId(const std::string& device_id,
+ const MediaDeviceSaltAndOrigin& salt_and_origin,
+ base::RepeatingCallback<void(const std::string&)> cb,
+ const MediaDeviceEnumeration& device_array) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- binding_.Bind(std::move(request));
+ for (const auto& device_info : device_array[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
+ if (MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+ salt_and_origin.device_id_salt, salt_and_origin.origin, device_id,
+ device_info.device_id)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(cb), device_info.device_id));
+ break;
+ }
+ }
+ // If we're unable to translate the device id, |cb| will not be run.
}
+} // namespace
+
RenderFrameAudioInputStreamFactory::RenderFrameAudioInputStreamFactory(
- CreateDelegateCallback create_delegate_callback,
- MediaStreamManager* media_stream_manager,
- int render_process_id,
- int render_frame_id)
- : create_delegate_callback_(std::move(create_delegate_callback)),
- media_stream_manager_(media_stream_manager),
- render_process_id_(render_process_id),
- render_frame_id_(render_frame_id),
+ mojom::RendererAudioInputStreamFactoryRequest request,
+ scoped_refptr<AudioInputDeviceManager> audio_input_device_manager,
+ RenderFrameHost* render_frame_host)
+ : binding_(this, std::move(request)),
+ audio_input_device_manager_(std::move(audio_input_device_manager)),
+ render_frame_host_(render_frame_host),
weak_ptr_factory_(this) {
- DCHECK(create_delegate_callback_);
- // No thread-hostile state has been initialized yet, so we don't have to bind
- // to this specific thread.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
RenderFrameAudioInputStreamFactory::~RenderFrameAudioInputStreamFactory() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-// static
-bool RenderFrameAudioInputStreamFactory::UseMojoFactories() {
- return base::FeatureList::IsEnabled(
- features::kUseMojoAudioInputStreamFactory);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
void RenderFrameAudioInputStreamFactory::CreateStream(
@@ -94,58 +90,126 @@ void RenderFrameAudioInputStreamFactory::CreateStream(
const media::AudioParameters& audio_params,
bool automatic_gain_control,
uint32_t shared_memory_count) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ TRACE_EVENT_INSTANT1("audio",
+ "RenderFrameAudioInputStreamFactory::CreateStream",
+ TRACE_EVENT_SCOPE_THREAD, "session id", session_id);
-#if defined(OS_CHROMEOS)
- if (audio_params.channel_layout() ==
- media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
- media_stream_manager_->audio_input_device_manager()
- ->RegisterKeyboardMicStream(base::BindOnce(
- &RenderFrameAudioInputStreamFactory::DoCreateStream,
- weak_ptr_factory_.GetWeakPtr(), std::move(client), session_id,
- audio_params, automatic_gain_control, shared_memory_count));
- return;
- }
-#endif
- DoCreateStream(std::move(client), session_id, audio_params,
- automatic_gain_control, shared_memory_count,
- AudioInputDeviceManager::KeyboardMicRegistration());
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &LookUpDeviceAndRespondIfFound, audio_input_device_manager_,
+ session_id,
+ base::BindOnce(&RenderFrameAudioInputStreamFactory::
+ CreateStreamAfterLookingUpDevice,
+ weak_ptr_factory_.GetWeakPtr(), std::move(client),
+ audio_params, automatic_gain_control,
+ shared_memory_count)));
}
-void RenderFrameAudioInputStreamFactory::DoCreateStream(
+void RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice(
mojom::RendererAudioInputStreamFactoryClientPtr client,
- int session_id,
const media::AudioParameters& audio_params,
bool automatic_gain_control,
uint32_t shared_memory_count,
- AudioInputDeviceManager::KeyboardMicRegistration
- keyboard_mic_registration) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- int stream_id = ++next_stream_id_;
-
- media::mojom::AudioLogPtr audio_log_ptr =
- MediaInternals::GetInstance()->CreateMojoAudioLog(
- media::AudioLogFactory::AUDIO_INPUT_CONTROLLER, stream_id,
- render_process_id_, render_frame_id_);
+ const MediaStreamDevice& device) {
+ TRACE_EVENT1(
+ "audio",
+ "RenderFrameAudioInputStreamFactory::CreateStreamAfterLookingUpDevice",
+ "device id", device.id);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ ForwardingAudioStreamFactory* factory =
+ ForwardingAudioStreamFactory::ForFrame(render_frame_host_);
+ if (!factory)
+ return;
- // Unretained is safe since |this| owns |streams_|.
- streams_.insert(std::make_unique<AudioInputStreamHandle>(
- std::move(client),
- base::BindOnce(
- create_delegate_callback_,
- base::Unretained(media_stream_manager_->audio_input_device_manager()),
- std::move(audio_log_ptr), std::move(keyboard_mic_registration),
- shared_memory_count, stream_id, session_id, automatic_gain_control,
- audio_params),
- base::BindOnce(&RenderFrameAudioInputStreamFactory::RemoveStream,
- weak_ptr_factory_.GetWeakPtr())));
+ WebContentsMediaCaptureId capture_id;
+ if (WebContentsMediaCaptureId::Parse(device.id, &capture_id)) {
+ // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker
+ // window, we do not mute the source audio.
+ // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute
+ // the source audio.
+ // TODO(qiangchen): Analyze audio constraints to make a duplicating or
+ // diverting decision. It would give web developer more flexibility.
+
+ RenderFrameHost* source_host = RenderFrameHost::FromID(
+ capture_id.render_process_id, capture_id.main_render_frame_id);
+ if (!source_host) {
+ // The source of the capture has already been destroyed, so fail early.
+ return;
+ }
+
+ factory->CreateLoopbackStream(
+ render_frame_host_, source_host, audio_params, shared_memory_count,
+ capture_id.disable_local_echo, std::move(client));
+
+ if (device.type == MEDIA_DESKTOP_AUDIO_CAPTURE)
+ IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
+ } else {
+ factory->CreateInputStream(render_frame_host_, device.id, audio_params,
+ shared_memory_count, automatic_gain_control,
+ std::move(client));
+
+ // Only count for captures from desktop media picker dialog and system loop
+ // back audio.
+ if (device.type == MEDIA_DESKTOP_AUDIO_CAPTURE &&
+ (media::AudioDeviceDescription::IsLoopbackDevice(device.id))) {
+ IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
+ }
+ }
}
-void RenderFrameAudioInputStreamFactory::RemoveStream(
- AudioInputStreamHandle* stream) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+void RenderFrameAudioInputStreamFactory::AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!IsValidDeviceId(output_device_id))
+ return;
+
+ ForwardingAudioStreamFactory* factory =
+ ForwardingAudioStreamFactory::ForFrame(render_frame_host_);
+ if (!factory)
+ return;
+
+ const int process_id = render_frame_host_->GetProcess()->GetID();
+ const int frame_id = render_frame_host_->GetRoutingID();
+ auto salt_and_origin = GetMediaDeviceSaltAndOrigin(process_id, frame_id);
+
+ // Check permissions for everything but the default device
+ if (!media::AudioDeviceDescription::IsDefaultDevice(output_device_id) &&
+ !MediaDevicesPermissionChecker().CheckPermissionOnUIThread(
+ MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, process_id, frame_id)) {
+ return;
+ }
+
+ if (media::AudioDeviceDescription::IsDefaultDevice(output_device_id) ||
+ media::AudioDeviceDescription::IsCommunicationsDevice(output_device_id)) {
+ factory->AssociateInputAndOutputForAec(input_stream_id, output_device_id);
+ } else {
+ auto* media_stream_manager =
+ BrowserMainLoop::GetInstance()->media_stream_manager();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ EnumerateOutputDevices, media_stream_manager,
+ base::BindRepeating(
+ &TranslateDeviceId, output_device_id, salt_and_origin,
+ base::BindRepeating(&RenderFrameAudioInputStreamFactory::
+ AssociateTranslatedOutputDeviceForAec,
+ weak_ptr_factory_.GetWeakPtr(),
+ input_stream_id))));
+ }
+}
- streams_.erase(stream);
+void RenderFrameAudioInputStreamFactory::AssociateTranslatedOutputDeviceForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& raw_output_device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ ForwardingAudioStreamFactory* factory =
+ ForwardingAudioStreamFactory::ForFrame(render_frame_host_);
+ if (factory)
+ factory->AssociateInputAndOutputForAec(input_stream_id,
+ raw_output_device_id);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h
index 530591f726a..a4597568026 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h
@@ -1,4 +1,4 @@
-// Copyright 2017 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.
@@ -6,22 +6,14 @@
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
#include <cstdint>
-#include <memory>
-#include <string>
-#include "base/callback.h"
-#include "base/containers/flat_set.h"
-#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
+#include "base/memory/scoped_refptr.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/audio_input_stream_handle.h"
#include "content/common/content_export.h"
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
-#include "content/public/browser/browser_thread.h"
-#include "media/audio/audio_input_delegate.h"
-#include "media/mojo/interfaces/audio_logging.mojom.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/common/media_stream_request.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace media {
@@ -30,7 +22,8 @@ class AudioParameters;
namespace content {
-class MediaStreamManager;
+class AudioInputDeviceManager;
+class RenderFrameHost;
// Handles a RendererAudioInputStreamFactory request for a render frame host,
// using the provided RendererAudioInputStreamFactoryContext. This class may
@@ -39,33 +32,14 @@ class MediaStreamManager;
class CONTENT_EXPORT RenderFrameAudioInputStreamFactory
: public mojom::RendererAudioInputStreamFactory {
public:
- using CreateDelegateCallback =
- base::RepeatingCallback<std::unique_ptr<media::AudioInputDelegate>(
- AudioInputDeviceManager* audio_input_device_manager,
- media::mojom::AudioLogPtr audio_log,
- AudioInputDeviceManager::KeyboardMicRegistration
- keyboard_mic_registration,
- uint32_t shared_memory_count,
- int stream_id,
- int session_id,
- bool automatic_gain_control,
- const media::AudioParameters& parameters,
- media::AudioInputDelegate::EventHandler* event_handler)>;
-
RenderFrameAudioInputStreamFactory(
- CreateDelegateCallback create_delegate_callback,
- MediaStreamManager* media_stream_manager,
- int render_process_id,
- int render_frame_id);
+ mojom::RendererAudioInputStreamFactoryRequest request,
+ scoped_refptr<AudioInputDeviceManager> audio_input_device_manager,
+ RenderFrameHost* render_frame_host);
~RenderFrameAudioInputStreamFactory() override;
- static bool UseMojoFactories();
-
private:
- using InputStreamSet = base::flat_set<std::unique_ptr<AudioInputStreamHandle>,
- base::UniquePtrComparator>;
-
// mojom::RendererAudioInputStreamFactory implementation.
void CreateStream(mojom::RendererAudioInputStreamFactoryClientPtr client,
int32_t session_id,
@@ -73,65 +47,30 @@ class CONTENT_EXPORT RenderFrameAudioInputStreamFactory
bool automatic_gain_control,
uint32_t shared_memory_count) override;
- void DoCreateStream(mojom::RendererAudioInputStreamFactoryClientPtr client,
- int session_id,
- const media::AudioParameters& audio_params,
- bool automatic_gain_control,
- uint32_t shared_memory_count,
- AudioInputDeviceManager::KeyboardMicRegistration
- keyboard_mic_registration);
+ void CreateStreamAfterLookingUpDevice(
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
+ const media::AudioParameters& audio_params,
+ bool automatic_gain_control,
+ uint32_t shared_memory_count,
+ const MediaStreamDevice& device);
- void RemoveStream(AudioInputStreamHandle* input_stream);
+ void AssociateInputAndOutputForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id) override;
- const CreateDelegateCallback create_delegate_callback_;
- MediaStreamManager* media_stream_manager_;
- const int render_process_id_;
- const int render_frame_id_;
+ void AssociateTranslatedOutputDeviceForAec(
+ const base::UnguessableToken& input_stream_id,
+ const std::string& raw_output_device_id);
- InputStreamSet streams_;
- int next_stream_id_ = 0;
+ const mojo::Binding<RendererAudioInputStreamFactory> binding_;
+ const scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_;
+ RenderFrameHost* const render_frame_host_;
base::WeakPtrFactory<RenderFrameAudioInputStreamFactory> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioInputStreamFactory);
};
-// This class is a convenient bundle of factory and binding.
-// It can be created on any thread, but should be destroyed on the IO thread
-// (hence the DeleteOnIOThread pointer).
-class CONTENT_EXPORT RenderFrameAudioInputStreamFactoryHandle {
- public:
- static std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>
- CreateFactory(RenderFrameAudioInputStreamFactory::CreateDelegateCallback
- create_delegate_callback,
- MediaStreamManager* media_stream_manager,
- int render_process_id,
- int render_frame_id,
- mojom::RendererAudioInputStreamFactoryRequest request);
-
- ~RenderFrameAudioInputStreamFactoryHandle();
-
- private:
- RenderFrameAudioInputStreamFactoryHandle(
- RenderFrameAudioInputStreamFactory::CreateDelegateCallback
- create_delegate_callback,
- MediaStreamManager* media_stream_manager,
- int render_process_id,
- int render_frame_id);
-
- void Init(mojom::RendererAudioInputStreamFactoryRequest request);
-
- RenderFrameAudioInputStreamFactory impl_;
- mojo::Binding<mojom::RendererAudioInputStreamFactory> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioInputStreamFactoryHandle);
-};
-
-using UniqueAudioInputStreamFactoryPtr =
- std::unique_ptr<RenderFrameAudioInputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>;
-
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_INPUT_STREAM_FACTORY_H_
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc
index 135e6c4bc90..312193601b3 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc
@@ -1,178 +1,278 @@
-// Copyright 2017 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.
#include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
-#include <limits>
+#include <memory>
+#include <string>
#include <utility>
#include "base/bind.h"
-#include "base/memory/shared_memory.h"
-#include "base/memory/shared_memory_handle.h"
-#include "base/optional.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/sync_socket.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
+#include "content/browser/media/forwarding_audio_stream_factory.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_media_capture_id.h"
+#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/test_service_manager_context.h"
+#include "content/public/test/test_utils.h"
#include "media/audio/audio_system_impl.h"
-#include "media/audio/mock_audio_manager.h"
+#include "media/audio/fake_audio_log_factory.h"
+#include "media/audio/fake_audio_manager.h"
#include "media/audio/test_audio_thread.h"
#include "media/base/audio_parameters.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/system/platform_handle.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/audio/public/cpp/fake_stream_factory.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
-namespace {
-
-using testing::Test;
-
-const size_t kShmemSize = 1234;
-const int kSessionId = 234;
-const bool kAGC = false;
-const uint32_t kSharedMemoryCount = 345;
-const int kSampleFrequency = 44100;
-const int kBitsPerSample = 16;
-const int kSamplesPerBuffer = kSampleFrequency / 100;
-const bool kInitiallyMuted = false;
-const int kRenderProcessID = -1;
-const int kRenderFrameID = MSG_ROUTING_NONE;
-
-media::AudioParameters GetTestAudioParameters() {
- return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
- kBitsPerSample, kSamplesPerBuffer);
-}
-
-class FakeAudioInputDelegate : public media::AudioInputDelegate {
+class RenderFrameAudioInputStreamFactoryTest
+ : public RenderViewHostTestHarness {
public:
- FakeAudioInputDelegate() {}
+ RenderFrameAudioInputStreamFactoryTest()
+ : RenderViewHostTestHarness(),
+ test_service_manager_context_(
+ std::make_unique<TestServiceManagerContext>()),
+ audio_manager_(std::make_unique<media::TestAudioThread>(),
+ &log_factory_),
+ audio_system_(media::AudioSystemImpl::CreateInstance()),
+ media_stream_manager_(std::make_unique<MediaStreamManager>(
+ audio_system_.get(),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))) {}
- ~FakeAudioInputDelegate() override {}
+ ~RenderFrameAudioInputStreamFactoryTest() override {}
- int GetStreamId() override { return 0; };
- void OnRecordStream() override{};
- void OnSetVolume(double volume) override{};
+ void SetUp() override {
+ RenderViewHostTestHarness::SetUp();
+ RenderFrameHostTester::For(main_rfh())->InitializeRenderFrameIfNeeded();
- private:
- DISALLOW_COPY_AND_ASSIGN(FakeAudioInputDelegate);
-};
+ // Set up the ForwardingAudioStreamFactory.
+ service_manager::Connector::TestApi connector_test_api(
+ ForwardingAudioStreamFactory::ForFrame(main_rfh())
+ ->get_connector_for_testing());
+ connector_test_api.OverrideBinderForTesting(
+ service_manager::Identity(audio::mojom::kServiceName),
+ audio::mojom::StreamFactory::Name_,
+ base::BindRepeating(
+ &RenderFrameAudioInputStreamFactoryTest::BindFactory,
+ base::Unretained(this)));
-class FakeAudioInputStreamClient : public media::mojom::AudioInputStreamClient {
- public:
- void OnMutedStateChanged(bool is_muted) override {}
- void OnError() override {}
-};
+ base::RunLoop().RunUntilIdle();
+ }
-class MockRendererAudioInputStreamFactoryClient
- : public mojom::RendererAudioInputStreamFactoryClient {
- public:
- MOCK_METHOD0(Created, void());
+ void TearDown() override {
+ audio_manager_.Shutdown();
+ test_service_manager_context_.reset();
+ RenderViewHostTestHarness::TearDown();
+ }
- void StreamCreated(media::mojom::AudioInputStreamPtr input_stream,
- media::mojom::AudioInputStreamClientRequest client_request,
- media::mojom::AudioDataPipePtr data_pipe,
- bool initially_muted) override {
- Created();
+ void BindFactory(mojo::ScopedMessagePipeHandle factory_request) {
+ audio_service_stream_factory_.binding_.Bind(
+ audio::mojom::StreamFactoryRequest(std::move(factory_request)));
}
-};
-// Creates a fake delegate and saves the provided event handler in
-// |event_handler_out|.
-std::unique_ptr<media::AudioInputDelegate> CreateFakeDelegate(
- media::AudioInputDelegate::EventHandler** event_handler_out,
- AudioInputDeviceManager* audio_input_device_manager,
- media::mojom::AudioLogPtr audio_log,
- AudioInputDeviceManager::KeyboardMicRegistration keyboard_mic_registration,
- uint32_t shared_memory_count,
- int stream_id,
- int session_id,
- bool automatic_gain_control,
- const media::AudioParameters& parameters,
- media::AudioInputDelegate::EventHandler* event_handler) {
- *event_handler_out = event_handler;
- return std::make_unique<FakeAudioInputDelegate>();
-}
+ class MockStreamFactory : public audio::FakeStreamFactory {
+ public:
+ MockStreamFactory() : binding_(this) {}
+ ~MockStreamFactory() override {}
-} // namespace
+ void CreateInputStream(
+ media::mojom::AudioInputStreamRequest stream_request,
+ media::mojom::AudioInputStreamClientPtr client,
+ media::mojom::AudioInputStreamObserverPtr observer,
+ media::mojom::AudioLogPtr log,
+ const std::string& device_id,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ bool enable_agc,
+ mojo::ScopedSharedBufferHandle key_press_count_buffer,
+ CreateInputStreamCallback created_callback) override {
+ last_created_callback = std::move(created_callback);
+ }
-class RenderFrameAudioInputStreamFactoryTest : public testing::Test {
- public:
- RenderFrameAudioInputStreamFactoryTest()
- : thread_bundle_(base::in_place),
- audio_manager_(std::make_unique<media::TestAudioThread>()),
- audio_system_(&audio_manager_),
- media_stream_manager_(&audio_system_, audio_manager_.GetTaskRunner()),
- client_binding_(&client_, mojo::MakeRequest(&client_ptr_)),
- factory_handle_(RenderFrameAudioInputStreamFactoryHandle::CreateFactory(
- base::BindRepeating(&CreateFakeDelegate, &event_handler_),
- &media_stream_manager_,
- kRenderProcessID,
- kRenderFrameID,
- mojo::MakeRequest(&factory_ptr_))) {}
-
- ~RenderFrameAudioInputStreamFactoryTest() override {
- audio_manager_.Shutdown();
+ void CreateLoopbackStream(
+ media::mojom::AudioInputStreamRequest stream_request,
+ media::mojom::AudioInputStreamClientPtr client,
+ media::mojom::AudioInputStreamObserverPtr observer,
+ const media::AudioParameters& params,
+ uint32_t shared_memory_count,
+ const base::UnguessableToken& group_id,
+ CreateLoopbackStreamCallback created_callback) override {
+ last_created_loopback_callback = std::move(created_callback);
+ }
+
+ CreateInputStreamCallback last_created_callback;
+ CreateLoopbackStreamCallback last_created_loopback_callback;
+
+ mojo::Binding<audio::mojom::StreamFactory> binding_;
+ };
- // UniqueAudioInputStreamFactoryPtr uses DeleteOnIOThread and must run
- // before |thread_bundle_| tear down.
- factory_handle_.reset();
+ class FakeRendererAudioInputStreamFactoryClient
+ : public mojom::RendererAudioInputStreamFactoryClient {
+ public:
+ void StreamCreated(
+ media::mojom::AudioInputStreamPtr stream,
+ media::mojom::AudioInputStreamClientRequest client_request,
+ media::mojom::AudioDataPipePtr data_pipe,
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override {}
+ };
- // Shutdown BrowserThread::IO before tearing down members.
- thread_bundle_.reset();
+ AudioInputDeviceManager* audio_input_device_manager() {
+ return media_stream_manager_->audio_input_device_manager();
}
- // |thread_bundle_| needs to be up before the members below (as they use
- // BrowserThreads for their initialization) but then needs to be torn down
- // before them as some verify they're town down in a single-threaded
- // environment (while
- // !BrowserThread::IsThreadInitiaslized(BrowserThread::IO)).
- base::Optional<TestBrowserThreadBundle> thread_bundle_;
-
- // These members need to be torn down after |thread_bundle_|.
- media::MockAudioManager audio_manager_;
- media::AudioSystemImpl audio_system_;
- MediaStreamManager media_stream_manager_;
-
- mojom::RendererAudioInputStreamFactoryPtr factory_ptr_;
- media::mojom::AudioInputStreamPtr stream_ptr_;
- MockRendererAudioInputStreamFactoryClient client_;
- mojom::RendererAudioInputStreamFactoryClientPtr client_ptr_;
- media::AudioInputDelegate::EventHandler* event_handler_ = nullptr;
- mojo::Binding<mojom::RendererAudioInputStreamFactoryClient> client_binding_;
- UniqueAudioInputStreamFactoryPtr factory_handle_;
+ class StreamOpenedWaiter : public MediaStreamProviderListener {
+ public:
+ explicit StreamOpenedWaiter(scoped_refptr<AudioInputDeviceManager> aidm,
+ base::OnceClosure callback)
+ : aidm_(aidm), cb_(std::move(callback)) {
+ aidm->RegisterListener(this);
+ }
+
+ ~StreamOpenedWaiter() override { aidm_->UnregisterListener(this); }
+
+ void Opened(MediaStreamType stream_type, int capture_session_id) override {
+ std::move(cb_).Run();
+ }
+ void Closed(MediaStreamType stream_type, int capture_session_id) override {}
+ void Aborted(MediaStreamType stream_type, int capture_session_id) override {
+ }
+
+ private:
+ scoped_refptr<AudioInputDeviceManager> aidm_;
+ base::OnceClosure cb_;
+ };
+
+ void CallOpenWithTestDeviceAndStoreSessionIdOnIO(int* session_id) {
+ *session_id = audio_input_device_manager()->Open(
+ MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, kDeviceId, kDeviceName));
+ }
+
+ const media::AudioParameters kParams =
+ media::AudioParameters::UnavailableDeviceParams();
+ const std::string kDeviceId = "test id";
+ const std::string kDeviceName = "test name";
+ const bool kAGC = false;
+ const uint32_t kSharedMemoryCount = 123;
+ MockStreamFactory audio_service_stream_factory_;
+ std::unique_ptr<TestServiceManagerContext> test_service_manager_context_;
+ media::FakeAudioLogFactory log_factory_;
+ media::FakeAudioManager audio_manager_;
+ std::unique_ptr<media::AudioSystem> audio_system_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
};
-TEST_F(RenderFrameAudioInputStreamFactoryTest, CreateStream) {
- factory_ptr_->CreateStream(std::move(client_ptr_), kSessionId,
- GetTestAudioParameters(), kAGC,
- kSharedMemoryCount);
+TEST_F(RenderFrameAudioInputStreamFactoryTest, ConstructDestruct) {
+ mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
+ audio_input_device_manager(),
+ main_rfh());
+}
+
+TEST_F(RenderFrameAudioInputStreamFactoryTest,
+ CreateOpenedStream_ForwardsCall) {
+ mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
+ audio_input_device_manager(),
+ main_rfh());
- // Wait for delegate to be created and |event_handler| set.
+ int session_id = audio_input_device_manager()->Open(
+ MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, kDeviceId, kDeviceName));
base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(event_handler_);
- base::SharedMemoryCreateOptions shmem_options;
- shmem_options.size = kShmemSize;
- shmem_options.share_read_only = true;
- base::SharedMemory shared_memory;
- shared_memory.Create(shmem_options);
- shared_memory.Map(kShmemSize);
- auto local = std::make_unique<base::CancelableSyncSocket>();
- auto remote = std::make_unique<base::CancelableSyncSocket>();
- ASSERT_TRUE(
- base::CancelableSyncSocket::CreatePair(local.get(), remote.get()));
- event_handler_->OnStreamCreated(/*stream_id, irrelevant*/ 0, &shared_memory,
- std::move(remote), kInitiallyMuted);
-
- EXPECT_CALL(client_, Created());
+
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ mojo::MakeRequest(&client);
+ factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
+ kSharedMemoryCount);
+
base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(!!audio_service_stream_factory_.last_created_callback);
+}
+
+TEST_F(RenderFrameAudioInputStreamFactoryTest,
+ CreateWebContentsCapture_ForwardsCall) {
+ std::unique_ptr<WebContents> source_contents = CreateTestWebContents();
+ mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
+ audio_input_device_manager(),
+ main_rfh());
+
+ RenderFrameHost* main_frame = source_contents->GetMainFrame();
+ WebContentsMediaCaptureId capture_id(main_frame->GetProcess()->GetID(),
+ main_frame->GetRoutingID());
+ int session_id = audio_input_device_manager()->Open(MediaStreamDevice(
+ MEDIA_TAB_AUDIO_CAPTURE, capture_id.ToString(), kDeviceName));
+ base::RunLoop().RunUntilIdle();
+
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ mojo::MakeRequest(&client);
+ factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
+ kSharedMemoryCount);
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(!!audio_service_stream_factory_.last_created_loopback_callback);
+}
+
+TEST_F(RenderFrameAudioInputStreamFactoryTest,
+ CreateWebContentsCaptureAfterCaptureSourceDestructed_Fails) {
+ std::unique_ptr<WebContents> source_contents = CreateTestWebContents();
+ mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
+ audio_input_device_manager(),
+ main_rfh());
+
+ RenderFrameHost* main_frame = source_contents->GetMainFrame();
+ WebContentsMediaCaptureId capture_id(main_frame->GetProcess()->GetID(),
+ main_frame->GetRoutingID());
+ int session_id = audio_input_device_manager()->Open(MediaStreamDevice(
+ MEDIA_TAB_AUDIO_CAPTURE, capture_id.ToString(), kDeviceName));
+ base::RunLoop().RunUntilIdle();
+
+ source_contents.reset();
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ mojo::MakeRequest(&client);
+ factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
+ kSharedMemoryCount);
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(!!audio_service_stream_factory_.last_created_loopback_callback);
+}
+
+TEST_F(RenderFrameAudioInputStreamFactoryTest,
+ CreateStreamWithoutValidSessionId_Fails) {
+ mojom::RendererAudioInputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioInputStreamFactory factory(mojo::MakeRequest(&factory_ptr),
+ audio_input_device_manager(),
+ main_rfh());
+
+ int session_id = 123;
+ mojom::RendererAudioInputStreamFactoryClientPtr client;
+ mojo::MakeRequest(&client);
+
+ factory_ptr->CreateStream(std::move(client), session_id, kParams, kAGC,
+ kSharedMemoryCount);
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(!!audio_service_stream_factory_.last_created_callback);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc
index 3f012c443ad..00642ad3fe9 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc
@@ -1,95 +1,124 @@
-// Copyright 2017 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.
#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
-#include <memory>
#include <utility>
-#include "base/metrics/histogram_macros.h"
-#include "base/task_runner_util.h"
+#include "base/trace_event/trace_event.h"
+#include "content/browser/media/forwarding_audio_stream_factory.h"
#include "content/browser/renderer_host/media/audio_output_authorization_handler.h"
-#include "content/browser/renderer_host/media/audio_output_stream_observer_impl.h"
-#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h"
#include "content/public/browser/render_frame_host.h"
-#include "media/base/audio_parameters.h"
-#include "media/mojo/services/mojo_audio_output_stream_provider.h"
-#include "mojo/public/cpp/bindings/message.h"
+#include "content/public/browser/render_process_host.h"
+#include "media/base/bind_to_current_loop.h"
namespace content {
-// static
-std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>
-RenderFrameAudioOutputStreamFactoryHandle::CreateFactory(
- RendererAudioOutputStreamFactoryContext* context,
- int render_frame_id,
- mojom::RendererAudioOutputStreamFactoryRequest request) {
- std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>
- handle(new RenderFrameAudioOutputStreamFactoryHandle(context,
- render_frame_id));
- // Unretained is safe since |*handle| must be posted to the IO thread prior to
- // deletion.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&RenderFrameAudioOutputStreamFactoryHandle::Init,
- base::Unretained(handle.get()), std::move(request)));
- return handle;
-}
+// This class implements media::mojom::AudioOutputStreamProvider for a single
+// streams and cleans itself up (using the |owner| pointer) when done.
+class RenderFrameAudioOutputStreamFactory::ProviderImpl final
+ : public media::mojom::AudioOutputStreamProvider {
+ public:
+ ProviderImpl(media::mojom::AudioOutputStreamProviderRequest request,
+ RenderFrameAudioOutputStreamFactory* owner,
+ const std::string& device_id)
+ : owner_(owner),
+ device_id_(device_id),
+ binding_(this, std::move(request)) {
+ DCHECK(owner_);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Unretained is safe since |this| owns |binding_|.
+ binding_.set_connection_error_handler(
+ base::BindOnce(&ProviderImpl::Done, base::Unretained(this)));
+ }
-RenderFrameAudioOutputStreamFactoryHandle::
- ~RenderFrameAudioOutputStreamFactoryHandle() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
+ ~ProviderImpl() final { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
+
+ void Acquire(
+ const media::AudioParameters& params,
+ media::mojom::AudioOutputStreamProviderClientPtr provider_client) final {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ TRACE_EVENT1("audio",
+ "RenderFrameAudioOutputStreamFactory::ProviderImpl::Acquire",
+ "raw device id", device_id_);
+
+ RenderFrameHost* frame = owner_->frame_;
+ ForwardingAudioStreamFactory* factory =
+ ForwardingAudioStreamFactory::ForFrame(frame);
+ if (factory) {
+ // It's possible that |frame| has already been destroyed, in which case we
+ // don't need to create a stream. In this case, the renderer will get a
+ // connection error since |provider_client| is dropped.
+ factory->CreateOutputStream(frame, device_id_, params,
+ std::move(provider_client));
+ }
+
+ // Since the stream creation has been propagated, |this| is no longer
+ // needed.
+ Done();
+ }
-RenderFrameAudioOutputStreamFactoryHandle::
- RenderFrameAudioOutputStreamFactoryHandle(
- RendererAudioOutputStreamFactoryContext* context,
- int render_frame_id)
- : impl_(render_frame_id, context), binding_(&impl_) {}
+ void Done() { owner_->DeleteProvider(this); }
-void RenderFrameAudioOutputStreamFactoryHandle::Init(
- mojom::RendererAudioOutputStreamFactoryRequest request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- binding_.Bind(std::move(request));
-}
+ private:
+ RenderFrameAudioOutputStreamFactory* const owner_;
+ const std::string device_id_;
+
+ mojo::Binding<media::mojom::AudioOutputStreamProvider> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProviderImpl);
+};
RenderFrameAudioOutputStreamFactory::RenderFrameAudioOutputStreamFactory(
- int render_frame_id,
- RendererAudioOutputStreamFactoryContext* context)
- : render_frame_id_(render_frame_id),
- context_(context),
+ RenderFrameHost* frame,
+ media::AudioSystem* audio_system,
+ MediaStreamManager* media_stream_manager,
+ mojom::RendererAudioOutputStreamFactoryRequest request)
+ : binding_(this, std::move(request)),
+ frame_(frame),
+ authorization_handler_(
+ new AudioOutputAuthorizationHandler(audio_system,
+ media_stream_manager,
+ frame_->GetProcess()->GetID())),
weak_ptr_factory_(this) {
- DCHECK(context_);
- // No thread-hostile state has been initialized yet, so we don't have to bind
- // to this specific thread.
- thread_checker_.DetachFromThread();
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
RenderFrameAudioOutputStreamFactory::~RenderFrameAudioOutputStreamFactory() {
- DCHECK(thread_checker_.CalledOnValidThread());
- UMA_HISTOGRAM_EXACT_LINEAR("Media.Audio.OutputStreamsCanceledByBrowser",
- stream_providers_.size(), 50);
- // Make sure to close all streams.
- stream_providers_.clear();
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
void RenderFrameAudioOutputStreamFactory::RequestDeviceAuthorization(
- media::mojom::AudioOutputStreamProviderRequest stream_provider_request,
+ media::mojom::AudioOutputStreamProviderRequest provider_request,
int32_t session_id,
const std::string& device_id,
RequestDeviceAuthorizationCallback callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- const base::TimeTicks auth_start_time = base::TimeTicks::Now();
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ TRACE_EVENT2(
+ "audio",
+ "RenderFrameAudioOutputStreamFactory::RequestDeviceAuthorization",
+ "device id", device_id, "session_id", session_id);
- context_->RequestDeviceAuthorization(
- render_frame_id_, session_id, device_id,
- base::BindOnce(
+ const base::TimeTicks auth_start_time = base::TimeTicks::Now();
+ // TODO(https://crbug.com/837625): This thread hopping is suboptimal since
+ // AudioOutputAuthorizationHandler was made to be used on the IO thread.
+ // Make AudioOutputAuthorizationHandler work on the UI thread instead.
+ AudioOutputAuthorizationHandler::AuthorizationCompletedCallback
+ completed_callback = media::BindToCurrentLoop(base::BindOnce(
&RenderFrameAudioOutputStreamFactory::AuthorizationCompleted,
weak_ptr_factory_.GetWeakPtr(), auth_start_time,
- std::move(stream_provider_request), std::move(callback)));
+ std::move(provider_request), std::move(callback)));
+
+ // Unretained is safe since |authorization_handler_| is deleted on the IO
+ // thread.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &AudioOutputAuthorizationHandler::RequestDeviceAuthorization,
+ base::Unretained(authorization_handler_.get()),
+ frame_->GetRoutingID(), session_id, device_id,
+ std::move(completed_callback)));
}
void RenderFrameAudioOutputStreamFactory::AuthorizationCompleted(
@@ -100,43 +129,29 @@ void RenderFrameAudioOutputStreamFactory::AuthorizationCompleted(
const media::AudioParameters& params,
const std::string& raw_device_id,
const std::string& device_id_for_renderer) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ TRACE_EVENT2("audio",
+ "RenderFrameAudioOutputStreamFactory::AuthorizationCompleted",
+ "raw device id", raw_device_id, "status", status);
+
AudioOutputAuthorizationHandler::UMALogDeviceAuthorizationTime(
auth_start_time);
- if (status != media::OUTPUT_DEVICE_STATUS_OK) {
- std::move(callback).Run(media::OutputDeviceStatus(status),
- media::AudioParameters::UnavailableDeviceParams(),
- std::string());
- return;
- }
+ // If |status| is not OK, this call will be considered as an error signal by
+ // the renderer.
+ std::move(callback).Run(status, params, device_id_for_renderer);
- int stream_id = next_stream_id_++;
- std::unique_ptr<media::mojom::AudioOutputStreamObserver> observer =
- std::make_unique<AudioOutputStreamObserverImpl>(
- context_->GetRenderProcessId(), render_frame_id_, stream_id);
- // Since |context_| outlives |this| and |this| outlives |stream_providers_|,
- // unretained is safe.
- stream_providers_.insert(
- std::make_unique<media::MojoAudioOutputStreamProvider>(
- std::move(request),
- base::BindOnce(
- &RendererAudioOutputStreamFactoryContext::CreateDelegate,
- base::Unretained(context_), raw_device_id, render_frame_id_,
- stream_id),
- base::BindOnce(&RenderFrameAudioOutputStreamFactory::RemoveStream,
- base::Unretained(this)),
- std::move(observer)));
-
- std::move(callback).Run(media::OutputDeviceStatus(status), params,
- device_id_for_renderer);
+ if (status == media::OUTPUT_DEVICE_STATUS_OK) {
+ stream_providers_.insert(std::make_unique<ProviderImpl>(
+ std::move(request), this, std::move(raw_device_id)));
+ }
}
-void RenderFrameAudioOutputStreamFactory::RemoveStream(
+void RenderFrameAudioOutputStreamFactory::DeleteProvider(
media::mojom::AudioOutputStreamProvider* stream_provider) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- stream_providers_.erase(stream_provider);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ size_t deleted = stream_providers_.erase(stream_provider);
+ DCHECK_EQ(1u, deleted);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h
index 8f42b902591..fbc229bdd8b 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h
@@ -1,4 +1,4 @@
-// Copyright 2017 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.
@@ -10,36 +10,55 @@
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
-#include "base/threading/thread_checker.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
#include "content/public/browser/browser_thread.h"
+#include "media/base/output_device_info.h"
#include "mojo/public/cpp/bindings/binding.h"
+namespace media {
+class AudioSystem;
+class AudioParameters;
+} // namespace media
+
namespace content {
-class RendererAudioOutputStreamFactoryContext;
+class AudioOutputAuthorizationHandler;
+class MediaStreamManager;
+class RenderFrameHost;
-// Handles a RendererAudioOutputStreamFactory request for a render frame host,
-// using the provided RendererAudioOutputStreamFactoryContext. This class may
-// be constructed on any thread, but must be used on the IO thread after that.
+// This class, which lives on the UI thread, takes care of stream requests from
+// a render frame. It verifies that the stream creation is allowed and then
+// forwards the request to the appropriate ForwardingAudioStreamFactory.
class CONTENT_EXPORT RenderFrameAudioOutputStreamFactory
: public mojom::RendererAudioOutputStreamFactory {
public:
RenderFrameAudioOutputStreamFactory(
- int render_frame_id,
- RendererAudioOutputStreamFactoryContext* context);
+ RenderFrameHost* frame,
+ media::AudioSystem* audio_system,
+ MediaStreamManager* media_stream_manager,
+ mojom::RendererAudioOutputStreamFactoryRequest request);
~RenderFrameAudioOutputStreamFactory() override;
+ size_t current_number_of_providers_for_testing() {
+ return stream_providers_.size();
+ }
+
private:
+ class ProviderImpl;
+ friend class ProviderImpl; // For DeleteProvider.
+
using OutputStreamProviderSet =
base::flat_set<std::unique_ptr<media::mojom::AudioOutputStreamProvider>,
base::UniquePtrComparator>;
// mojom::RendererAudioOutputStreamFactory implementation.
void RequestDeviceAuthorization(
- media::mojom::AudioOutputStreamProviderRequest stream_provider,
+ media::mojom::AudioOutputStreamProviderRequest provider_request,
int32_t session_id,
const std::string& device_id,
RequestDeviceAuthorizationCallback callback) override;
@@ -57,51 +76,26 @@ class CONTENT_EXPORT RenderFrameAudioOutputStreamFactory
const std::string& raw_device_id,
const std::string& device_id_for_renderer);
- void RemoveStream(media::mojom::AudioOutputStreamProvider* stream_provider);
+ void DeleteProvider(media::mojom::AudioOutputStreamProvider* stream_provider);
- const int render_frame_id_;
- RendererAudioOutputStreamFactoryContext* const context_;
- base::ThreadChecker thread_checker_;
+ const mojo::Binding<mojom::RendererAudioOutputStreamFactory> binding_;
+ RenderFrameHost* const frame_;
+ const std::unique_ptr<AudioOutputAuthorizationHandler,
+ BrowserThread::DeleteOnIOThread>
+ authorization_handler_;
- // The stream providers will contain the corresponding streams.
+ // The OutputStreamProviders for authorized streams are kept here while
+ // waiting for the renderer to finish creating the stream, and destructed
+ // afterwards.
OutputStreamProviderSet stream_providers_;
- // All streams require IDs. Use a counter to generate them.
- int next_stream_id_ = 0;
-
+ // Weak pointers are used to cancel device authorizations that are in flight
+ // while |this| is destructed.
base::WeakPtrFactory<RenderFrameAudioOutputStreamFactory> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioOutputStreamFactory);
};
-// This class is a convenient bundle of factory and binding.
-class CONTENT_EXPORT RenderFrameAudioOutputStreamFactoryHandle {
- public:
- static std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>
- CreateFactory(RendererAudioOutputStreamFactoryContext* context,
- int render_frame_id,
- mojom::RendererAudioOutputStreamFactoryRequest request);
-
- ~RenderFrameAudioOutputStreamFactoryHandle();
-
- private:
- RenderFrameAudioOutputStreamFactoryHandle(
- RendererAudioOutputStreamFactoryContext* context,
- int render_frame_id);
-
- void Init(mojom::RendererAudioOutputStreamFactoryRequest request);
-
- RenderFrameAudioOutputStreamFactory impl_;
- mojo::Binding<mojom::RendererAudioOutputStreamFactory> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderFrameAudioOutputStreamFactoryHandle);
-};
-
-using UniqueAudioOutputStreamFactoryPtr =
- std::unique_ptr<RenderFrameAudioOutputStreamFactoryHandle,
- BrowserThread::DeleteOnIOThread>;
-
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_RENDER_FRAME_AUDIO_OUTPUT_STREAM_FACTORY_H_
diff --git a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
index 58404d6d4e9..837204a6d62 100644
--- a/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
@@ -1,344 +1,262 @@
-// Copyright 2017 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.
#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
-#include <limits>
+#include <memory>
#include <utility>
#include "base/bind.h"
-#include "base/memory/shared_memory.h"
-#include "base/memory/shared_memory_handle.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/sync_socket.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/unguessable_token.h"
+#include "content/browser/media/forwarding_audio_stream_factory.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h"
-#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/test_service_manager_context.h"
+#include "media/audio/audio_system_impl.h"
+#include "media/audio/fake_audio_log_factory.h"
+#include "media/audio/fake_audio_manager.h"
+#include "media/audio/test_audio_thread.h"
#include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/system/platform_handle.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/audio/public/cpp/fake_stream_factory.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/public/mojom/stream_factory.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace content {
-
-namespace {
-
-using testing::Test;
-using AudioOutputStreamFactory = mojom::RendererAudioOutputStreamFactory;
-using AudioOutputStreamFactoryPtr =
- mojo::InterfacePtr<AudioOutputStreamFactory>;
-using AudioOutputStreamFactoryRequest =
- mojo::InterfaceRequest<AudioOutputStreamFactory>;
-using AudioOutputStream = media::mojom::AudioOutputStream;
-using AudioOutputStreamPtr = mojo::InterfacePtr<AudioOutputStream>;
-using AudioOutputStreamRequest = mojo::InterfaceRequest<AudioOutputStream>;
-using AudioOutputStreamClient = media::mojom::AudioOutputStreamClient;
-using AudioOutputStreamClientPtr = mojo::InterfacePtr<AudioOutputStreamClient>;
-using AudioOutputStreamClientRequest =
- mojo::InterfaceRequest<AudioOutputStreamClient>;
-using AudioOutputStreamProvider = media::mojom::AudioOutputStreamProvider;
-using AudioOutputStreamProviderPtr =
- mojo::InterfacePtr<AudioOutputStreamProvider>;
-using AudioOutputStreamProviderRequest =
- mojo::InterfaceRequest<AudioOutputStreamProvider>;
-
-const int kStreamId = 0;
-const int kNoSessionId = 0;
-const int kRenderProcessId = 42;
-const int kRenderFrameId = 24;
-const int kSampleFrequency = 44100;
-const int kBitsPerSample = 16;
-const int kSamplesPerBuffer = kSampleFrequency / 100;
-const char kSalt[] = "salt";
-
-media::AudioParameters GetTestAudioParameters() {
- return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
- kBitsPerSample, kSamplesPerBuffer);
-}
+using ::testing::_;
+using ::testing::Test;
+using ::testing::Mock;
+using ::testing::Ne;
+using ::testing::StrictMock;
-class MockAudioOutputDelegate : public media::AudioOutputDelegate {
- public:
- // |on_destruction| can be used to observe the destruction of the delegate.
- explicit MockAudioOutputDelegate(
- base::OnceClosure on_destruction = base::OnceClosure())
- : on_destruction_(std::move(on_destruction)) {}
-
- ~MockAudioOutputDelegate() {
- if (on_destruction_)
- std::move(on_destruction_).Run();
- }
-
- MOCK_METHOD0(GetStreamId, int());
- MOCK_METHOD0(OnPlayStream, void());
- MOCK_METHOD0(OnPauseStream, void());
- MOCK_METHOD1(OnSetVolume, void(double));
-
- private:
- base::OnceClosure on_destruction_;
-
- DISALLOW_COPY_AND_ASSIGN(MockAudioOutputDelegate);
-};
+namespace content {
-class MockContext : public RendererAudioOutputStreamFactoryContext {
+class RenderFrameAudioOutputStreamFactoryTest
+ : public RenderViewHostTestHarness {
public:
- explicit MockContext(bool auth_ok) : salt_(kSalt), auth_ok_(auth_ok) {}
-
- ~MockContext() override { EXPECT_EQ(nullptr, delegate_); }
-
- int GetRenderProcessId() const override { return kRenderProcessId; }
-
- void RequestDeviceAuthorization(
- int render_frame_id,
- int session_id,
- const std::string& device_id,
- AuthorizationCompletedCallback cb) const override {
- EXPECT_EQ(render_frame_id, kRenderFrameId);
- EXPECT_EQ(session_id, 0);
- if (auth_ok_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(cb),
- media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
- GetTestAudioParameters(), "default", std::string()));
- return;
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(cb),
- media::OutputDeviceStatus::
- OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
- media::AudioParameters::UnavailableDeviceParams(),
- std::string(), std::string()));
+ RenderFrameAudioOutputStreamFactoryTest()
+ : test_service_manager_context_(
+ std::make_unique<TestServiceManagerContext>()),
+ audio_manager_(std::make_unique<media::TestAudioThread>(),
+ &log_factory_),
+ audio_system_(media::AudioSystemImpl::CreateInstance()),
+ media_stream_manager_(std::make_unique<MediaStreamManager>(
+ audio_system_.get(),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))) {}
+
+ ~RenderFrameAudioOutputStreamFactoryTest() override {}
+
+ void SetUp() override {
+ RenderViewHostTestHarness::SetUp();
+ RenderFrameHostTester::For(main_rfh())->InitializeRenderFrameIfNeeded();
+
+ // Set up the ForwardingAudioStreamFactory.
+ service_manager::Connector::TestApi connector_test_api(
+ ForwardingAudioStreamFactory::ForFrame(main_rfh())
+ ->get_connector_for_testing());
+ connector_test_api.OverrideBinderForTesting(
+ service_manager::Identity(audio::mojom::kServiceName),
+ audio::mojom::StreamFactory::Name_,
+ base::BindRepeating(
+ &RenderFrameAudioOutputStreamFactoryTest::BindFactory,
+ base::Unretained(this)));
+
+ base::RunLoop().RunUntilIdle();
}
- // The event handler for the delegate will be stored at
- // |*event_handler_location| when the delegate is created.
- void PrepareDelegateForCreation(
- std::unique_ptr<media::AudioOutputDelegate> delegate,
- media::AudioOutputDelegate::EventHandler** event_handler_location) {
- EXPECT_EQ(nullptr, delegate_);
- EXPECT_EQ(nullptr, delegate_event_handler_location_);
- delegate_ = std::move(delegate);
- delegate_event_handler_location_ = event_handler_location;
+ void TearDown() override {
+ audio_manager_.Shutdown();
+ test_service_manager_context_.reset();
+ RenderViewHostTestHarness::TearDown();
}
- std::unique_ptr<media::AudioOutputDelegate> CreateDelegate(
- const std::string& unique_device_id,
- int render_frame_id,
- int stream_id,
- const media::AudioParameters& params,
- media::mojom::AudioOutputStreamObserverPtr stream_observer,
- media::AudioOutputDelegate::EventHandler* handler) override {
- EXPECT_NE(nullptr, delegate_);
- EXPECT_NE(nullptr, delegate_event_handler_location_);
- *delegate_event_handler_location_ = handler;
- delegate_event_handler_location_ = nullptr;
- return std::move(delegate_);
+ void BindFactory(mojo::ScopedMessagePipeHandle factory_request) {
+ audio_service_stream_factory_.binding_.Bind(
+ audio::mojom::StreamFactoryRequest(std::move(factory_request)));
}
- AudioOutputStreamFactoryPtr CreateFactory() {
- DCHECK(!factory_);
- AudioOutputStreamFactoryPtr ret;
- factory_ = std::make_unique<RenderFrameAudioOutputStreamFactory>(
- kRenderFrameId, this);
- factory_binding_ = std::make_unique<
- mojo::Binding<mojom::RendererAudioOutputStreamFactory>>(
- factory_.get(), mojo::MakeRequest(&ret));
- return ret;
- }
+ class MockStreamFactory : public audio::FakeStreamFactory {
+ public:
+ MockStreamFactory() {}
+ ~MockStreamFactory() override {}
+
+ void CreateOutputStream(
+ media::mojom::AudioOutputStreamRequest stream_request,
+ media::mojom::AudioOutputStreamObserverAssociatedPtrInfo observer_info,
+ media::mojom::AudioLogPtr log,
+ const std::string& output_device_id,
+ const media::AudioParameters& params,
+ const base::UnguessableToken& group_id,
+ CreateOutputStreamCallback created_callback) override {
+ last_created_callback = std::move(created_callback);
+ }
- private:
- const std::string salt_;
- const bool auth_ok_;
- std::unique_ptr<RenderFrameAudioOutputStreamFactory> factory_;
- std::unique_ptr<mojo::Binding<mojom::RendererAudioOutputStreamFactory>>
- factory_binding_;
- std::unique_ptr<media::AudioOutputDelegate> delegate_;
- media::AudioOutputDelegate::EventHandler** delegate_event_handler_location_ =
- nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(MockContext);
+ CreateOutputStreamCallback last_created_callback;
+ };
+
+ using MockAuthorizationCallback = StrictMock<
+ base::MockCallback<base::OnceCallback<void(media::OutputDeviceStatus,
+ const media::AudioParameters&,
+ const std::string&)>>>;
+
+ const char* kDefaultDeviceId = "default";
+ const char* kDeviceId =
+ "111122223333444455556666777788889999aaaabbbbccccddddeeeeffff";
+ const media::AudioParameters kParams =
+ media::AudioParameters::UnavailableDeviceParams();
+ const int kNoSessionId = 0;
+ MockStreamFactory audio_service_stream_factory_;
+ std::unique_ptr<TestServiceManagerContext> test_service_manager_context_;
+ media::FakeAudioLogFactory log_factory_;
+ media::FakeAudioManager audio_manager_;
+ std::unique_ptr<media::AudioSystem> audio_system_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
};
-class MockClient : public AudioOutputStreamClient {
- public:
- MockClient() {}
- ~MockClient() override {}
-
- void StreamCreated(media::mojom::AudioDataPipePtr data_pipe) {
- was_called_ = true;
- }
+TEST_F(RenderFrameAudioOutputStreamFactoryTest, ConstructDestruct) {
+ mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioOutputStreamFactory factory(main_rfh(), audio_system_.get(),
+ media_stream_manager_.get(),
+ mojo::MakeRequest(&factory_ptr));
+}
- bool was_called() { return was_called_; }
+TEST_F(RenderFrameAudioOutputStreamFactoryTest,
+ RequestDeviceAuthorizationForDefaultDevice_StatusOk) {
+ mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioOutputStreamFactory factory(main_rfh(), audio_system_.get(),
+ media_stream_manager_.get(),
+ mojo::MakeRequest(&factory_ptr));
- MOCK_METHOD0(OnError, void());
+ media::mojom::AudioOutputStreamProviderPtr provider_ptr;
+ MockAuthorizationCallback mock_callback;
+ factory_ptr->RequestDeviceAuthorization(mojo::MakeRequest(&provider_ptr),
+ kNoSessionId, kDefaultDeviceId,
+ mock_callback.Get());
- private:
- bool was_called_ = false;
+ EXPECT_CALL(mock_callback,
+ Run(media::OUTPUT_DEVICE_STATUS_OK, _, std::string()));
- DISALLOW_COPY_AND_ASSIGN(MockClient);
-};
+ base::RunLoop().RunUntilIdle();
-void AuthCallback(media::OutputDeviceStatus* status_out,
- media::AudioParameters* params_out,
- std::string* id_out,
- media::OutputDeviceStatus status,
- const media::AudioParameters& params,
- const std::string& id) {
- *status_out = status;
- *params_out = params;
- *id_out = id;
+ EXPECT_EQ(1u, factory.current_number_of_providers_for_testing());
}
-} // namespace
-
-// This test authorizes and creates a stream, and checks that
-// 1. the authorization callback is called with appropriate parameters.
-// 2. the AudioOutputDelegate is created.
-// 3. when the delegate calls OnStreamCreated, this is propagated to the client.
-TEST(RenderFrameAudioOutputStreamFactoryTest, CreateStream) {
- content::TestBrowserThreadBundle thread_bundle;
- AudioOutputStreamProviderPtr provider;
- AudioOutputStreamPtr output_stream;
- MockClient client;
- AudioOutputStreamClientPtr client_ptr;
- mojo::Binding<AudioOutputStreamClient> client_binding(
- &client, mojo::MakeRequest(&client_ptr));
- media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
- auto factory_context = std::make_unique<MockContext>(true);
- factory_context->PrepareDelegateForCreation(
- std::make_unique<MockAudioOutputDelegate>(), &event_handler);
- AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
-
- media::OutputDeviceStatus status;
- media::AudioParameters params;
- std::string id;
- factory_ptr->RequestDeviceAuthorization(
- mojo::MakeRequest(&provider), kNoSessionId, "default",
- base::BindOnce(&AuthCallback, base::Unretained(&status),
- base::Unretained(&params), base::Unretained(&id)));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_OK);
- EXPECT_EQ(params.AsHumanReadableString(),
- GetTestAudioParameters().AsHumanReadableString());
- EXPECT_TRUE(id.empty());
-
- provider->Acquire(
- mojo::MakeRequest(&output_stream), std::move(client_ptr), params,
- base::BindOnce(&MockClient::StreamCreated, base::Unretained(&client)));
- base::RunLoop().RunUntilIdle();
- ASSERT_NE(event_handler, nullptr);
+TEST_F(
+ RenderFrameAudioOutputStreamFactoryTest,
+ RequestDeviceAuthorizationForDefaultDeviceAndDestroyProviderPtr_CleansUp) {
+ mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioOutputStreamFactory factory(main_rfh(), audio_system_.get(),
+ media_stream_manager_.get(),
+ mojo::MakeRequest(&factory_ptr));
- base::SharedMemory shared_memory;
- ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(100));
+ media::mojom::AudioOutputStreamProviderPtr provider_ptr;
+ MockAuthorizationCallback mock_callback;
+ factory_ptr->RequestDeviceAuthorization(mojo::MakeRequest(&provider_ptr),
+ kNoSessionId, kDefaultDeviceId,
+ mock_callback.Get());
+ provider_ptr.reset();
- auto local = std::make_unique<base::CancelableSyncSocket>();
- auto remote = std::make_unique<base::CancelableSyncSocket>();
- ASSERT_TRUE(
- base::CancelableSyncSocket::CreatePair(local.get(), remote.get()));
- event_handler->OnStreamCreated(kStreamId, &shared_memory, std::move(remote));
+ EXPECT_CALL(mock_callback,
+ Run(media::OUTPUT_DEVICE_STATUS_OK, _, std::string()));
base::RunLoop().RunUntilIdle();
- // Make sure we got the callback from creating stream.
- EXPECT_TRUE(client.was_called());
+
+ EXPECT_EQ(0u, factory.current_number_of_providers_for_testing());
}
-TEST(RenderFrameAudioOutputStreamFactoryTest, NotAuthorized_Denied) {
- content::TestBrowserThreadBundle thread_bundle;
- AudioOutputStreamProviderPtr output_provider;
- auto factory_context = std::make_unique<MockContext>(false);
- AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
-
- media::OutputDeviceStatus status;
- media::AudioParameters params;
- std::string id;
- factory_ptr->RequestDeviceAuthorization(
- mojo::MakeRequest(&output_provider), kNoSessionId, "default",
- base::BindOnce(&AuthCallback, base::Unretained(&status),
- base::Unretained(&params), base::Unretained(&id)));
+TEST_F(
+ RenderFrameAudioOutputStreamFactoryTest,
+ RequestDeviceAuthorizationForNondefaultDeviceWithoutAuthorization_Fails) {
+ mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioOutputStreamFactory factory(main_rfh(), audio_system_.get(),
+ media_stream_manager_.get(),
+ mojo::MakeRequest(&factory_ptr));
+
+ media::mojom::AudioOutputStreamProviderPtr provider_ptr;
+ MockAuthorizationCallback mock_callback;
+ factory_ptr->RequestDeviceAuthorization(mojo::MakeRequest(&provider_ptr),
+ kNoSessionId, kDeviceId,
+ mock_callback.Get());
+
+ EXPECT_CALL(mock_callback,
+ Run(Ne(media::OUTPUT_DEVICE_STATUS_OK), _, std::string()));
+
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED);
- EXPECT_TRUE(id.empty());
+
+ EXPECT_EQ(0u, factory.current_number_of_providers_for_testing());
}
-TEST(RenderFrameAudioOutputStreamFactoryTest, ConnectionError_DeletesStream) {
- content::TestBrowserThreadBundle thread_bundle;
- AudioOutputStreamProviderPtr provider;
- AudioOutputStreamPtr output_stream;
- MockClient client;
- AudioOutputStreamClientPtr client_ptr;
- mojo::Binding<AudioOutputStreamClient> client_binding(
- &client, mojo::MakeRequest(&client_ptr));
- bool delegate_is_destructed = false;
- media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
- auto factory_context = std::make_unique<MockContext>(true);
- factory_context->PrepareDelegateForCreation(
- std::make_unique<MockAudioOutputDelegate>(
- base::BindOnce([](bool* destructed) { *destructed = true; },
- &delegate_is_destructed)),
- &event_handler);
- AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
-
- factory_ptr->RequestDeviceAuthorization(
- mojo::MakeRequest(&provider), kNoSessionId, "default",
- base::BindOnce([](media::OutputDeviceStatus status,
- const media::AudioParameters& params,
- const std::string& id) {}));
- base::RunLoop().RunUntilIdle();
+TEST_F(RenderFrameAudioOutputStreamFactoryTest,
+ CreateStream_CreatesStreamAndFreesProvider) {
+ mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioOutputStreamFactory factory(main_rfh(), audio_system_.get(),
+ media_stream_manager_.get(),
+ mojo::MakeRequest(&factory_ptr));
+
+ media::mojom::AudioOutputStreamProviderPtr provider_ptr;
+ MockAuthorizationCallback mock_callback;
+ factory_ptr->RequestDeviceAuthorization(mojo::MakeRequest(&provider_ptr),
+ kNoSessionId, kDefaultDeviceId,
+ mock_callback.Get());
+ {
+ media::mojom::AudioOutputStreamProviderClientPtr client;
+ mojo::MakeRequest(&client);
+ provider_ptr->Acquire(kParams, std::move(client));
+ }
+
+ audio::mojom::StreamFactory::CreateOutputStreamCallback created_callback;
+ EXPECT_CALL(mock_callback,
+ Run(media::OUTPUT_DEVICE_STATUS_OK, _, std::string()));
- provider->Acquire(
- mojo::MakeRequest(&output_stream), std::move(client_ptr),
- GetTestAudioParameters(),
- base::BindOnce(&MockClient::StreamCreated, base::Unretained(&client)));
- base::RunLoop().RunUntilIdle();
- ASSERT_NE(event_handler, nullptr);
- EXPECT_FALSE(delegate_is_destructed);
- output_stream.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(delegate_is_destructed);
+
+ EXPECT_TRUE(!!audio_service_stream_factory_.last_created_callback);
+ EXPECT_EQ(0u, factory.current_number_of_providers_for_testing());
}
-TEST(RenderFrameAudioOutputStreamFactoryTest, DelegateError_DeletesStream) {
- content::TestBrowserThreadBundle thread_bundle;
- AudioOutputStreamProviderPtr provider;
- AudioOutputStreamPtr output_stream;
- MockClient client;
- AudioOutputStreamClientPtr client_ptr;
- mojo::Binding<AudioOutputStreamClient> client_binding(
- &client, mojo::MakeRequest(&client_ptr));
- bool delegate_is_destructed = false;
- media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
- auto factory_context = std::make_unique<MockContext>(true);
- factory_context->PrepareDelegateForCreation(
- std::make_unique<MockAudioOutputDelegate>(
- base::BindOnce([](bool* destructed) { *destructed = true; },
- &delegate_is_destructed)),
- &event_handler);
- AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
-
- factory_ptr->RequestDeviceAuthorization(
- mojo::MakeRequest(&provider), kNoSessionId, "default",
- base::BindOnce([](media::OutputDeviceStatus status,
- const media::AudioParameters& params,
- const std::string& id) {}));
- base::RunLoop().RunUntilIdle();
+TEST_F(RenderFrameAudioOutputStreamFactoryTest,
+ CreateStreamAfterFactoryDestruction_Fails) {
+ media::mojom::AudioOutputStreamProviderPtr provider_ptr;
+ MockAuthorizationCallback mock_callback;
+
+ {
+ mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
+ RenderFrameAudioOutputStreamFactory factory(
+ main_rfh(), audio_system_.get(), media_stream_manager_.get(),
+ mojo::MakeRequest(&factory_ptr));
+
+ factory_ptr->RequestDeviceAuthorization(mojo::MakeRequest(&provider_ptr),
+ kNoSessionId, kDefaultDeviceId,
+ mock_callback.Get());
+
+ audio::mojom::StreamFactory::CreateOutputStreamCallback created_callback;
+ EXPECT_CALL(mock_callback,
+ Run(media::OUTPUT_DEVICE_STATUS_OK, _, std::string()));
+ base::RunLoop().RunUntilIdle();
+ }
+ // Now factory is destructed. Trying to create a stream should fail.
+ {
+ media::mojom::AudioOutputStreamProviderClientPtr client;
+ mojo::MakeRequest(&client);
+ provider_ptr->Acquire(kParams, std::move(client));
+ }
- provider->Acquire(
- mojo::MakeRequest(&output_stream), std::move(client_ptr),
- GetTestAudioParameters(),
- base::BindOnce(&MockClient::StreamCreated, base::Unretained(&client)));
base::RunLoop().RunUntilIdle();
- ASSERT_NE(event_handler, nullptr);
- EXPECT_FALSE(delegate_is_destructed);
- event_handler->OnStreamError(kStreamId);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(delegate_is_destructed);
+
+ EXPECT_FALSE(!!audio_service_stream_factory_.last_created_callback);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h b/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h
index 554574016cb..923752d31ce 100644
--- a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h
+++ b/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h
@@ -21,6 +21,8 @@ namespace content {
// RendererAudioOutputStreamFactoryContext provides functions common to all
// AudioOutputFactory instances for a single renderer process.
+// Not needed after switching to serving audio streams with the audio service
+// (https://crbug.com/830493).
class CONTENT_EXPORT RendererAudioOutputStreamFactoryContext {
public:
virtual ~RendererAudioOutputStreamFactoryContext() {}
diff --git a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc b/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc
index cd8ca99ea4c..cfeb1aa582c 100644
--- a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc
+++ b/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc
@@ -9,7 +9,6 @@
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/audio_output_delegate_impl.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_features.h"
#include "media/audio/audio_system.h"
@@ -75,10 +74,4 @@ RendererAudioOutputStreamFactoryContextImpl::CreateDelegate(
std::move(stream_observer), unique_device_id);
}
-// static
-bool RendererAudioOutputStreamFactoryContextImpl::UseMojoFactories() {
- return base::FeatureList::IsEnabled(
- features::kUseMojoAudioOutputStreamFactory);
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h b/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h
index 95e5ec5af79..63069469aff 100644
--- a/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h
+++ b/chromium/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h
@@ -9,7 +9,7 @@
#include <string>
#include "content/browser/renderer_host/media/audio_output_authorization_handler.h"
-#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h"
+#include "content/browser/renderer_host/media/old_render_frame_audio_output_stream_factory.h"
#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h"
#include "content/public/browser/browser_thread.h"
@@ -40,6 +40,8 @@ class MediaStreamManager;
// |
// media::MojoAudioOutputStream
//
+// Not needed after switching to serving audio streams with the audio service
+// (https://crbug.com/830493).
class CONTENT_EXPORT RendererAudioOutputStreamFactoryContextImpl
: public RendererAudioOutputStreamFactoryContext {
public:
@@ -69,8 +71,6 @@ class CONTENT_EXPORT RendererAudioOutputStreamFactoryContextImpl
media::mojom::AudioOutputStreamObserverPtr stream_observer,
media::AudioOutputDelegate::EventHandler* handler) override;
- static bool UseMojoFactories();
-
private:
// Used for hashing the device_id.
media::AudioSystem* const audio_system_;
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
index aa6c2037393..f54b3f57900 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
@@ -37,11 +37,18 @@ class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
DoGetDeviceInfos(callback);
}
- void AddVirtualDevice(const media::VideoCaptureDeviceInfo& device_info,
- video_capture::mojom::ProducerPtr producer,
- video_capture::mojom::VirtualDeviceRequest
- virtual_device_request) override {
- DoAddVirtualDevice(device_info, producer.get(), &virtual_device_request);
+ void AddSharedMemoryVirtualDevice(
+ const media::VideoCaptureDeviceInfo& device_info,
+ video_capture::mojom::ProducerPtr producer,
+ video_capture::mojom::SharedMemoryVirtualDeviceRequest virtual_device)
+ override {
+ DoAddVirtualDevice(device_info, producer.get(), &virtual_device);
+ }
+
+ void AddTextureVirtualDevice(const media::VideoCaptureDeviceInfo& device_info,
+ video_capture::mojom::TextureVirtualDeviceRequest
+ virtual_device) override {
+ NOTIMPLEMENTED();
}
MOCK_METHOD1(DoGetDeviceInfos, void(GetDeviceInfosCallback& callback));
@@ -49,11 +56,11 @@ class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
void(const std::string& device_id,
video_capture::mojom::DeviceRequest* device_request,
CreateDeviceCallback& callback));
- MOCK_METHOD3(
- DoAddVirtualDevice,
- void(const media::VideoCaptureDeviceInfo& device_info,
- video_capture::mojom::ProducerProxy* producer,
- video_capture::mojom::VirtualDeviceRequest* virtual_device_request));
+ MOCK_METHOD3(DoAddVirtualDevice,
+ void(const media::VideoCaptureDeviceInfo& device_info,
+ video_capture::mojom::ProducerProxy* producer,
+ video_capture::mojom::SharedMemoryVirtualDeviceRequest*
+ virtual_device_request));
};
class MockVideoCaptureDeviceLauncherCallbacks
diff --git a/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc b/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
index d1dc91e616c..6a683e5f5d1 100644
--- a/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
@@ -59,11 +59,17 @@ class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
CreateDeviceCallback callback) override {
DoCreateDevice(device_id, &device_request, callback);
}
- void AddVirtualDevice(const media::VideoCaptureDeviceInfo& device_info,
- video_capture::mojom::ProducerPtr producer,
- video_capture::mojom::VirtualDeviceRequest
- virtual_device_request) override {
- DoAddVirtualDevice(device_info, producer.get(), &virtual_device_request);
+ void AddSharedMemoryVirtualDevice(
+ const media::VideoCaptureDeviceInfo& device_info,
+ video_capture::mojom::ProducerPtr producer,
+ video_capture::mojom::SharedMemoryVirtualDeviceRequest virtual_device)
+ override {
+ DoAddVirtualDevice(device_info, producer.get(), &virtual_device);
+ }
+ void AddTextureVirtualDevice(const media::VideoCaptureDeviceInfo& device_info,
+ video_capture::mojom::TextureVirtualDeviceRequest
+ virtual_device) override {
+ NOTIMPLEMENTED();
}
MOCK_METHOD1(DoGetDeviceInfos, void(GetDeviceInfosCallback& callback));
@@ -71,11 +77,11 @@ class MockDeviceFactory : public video_capture::mojom::DeviceFactory {
void(const std::string& device_id,
video_capture::mojom::DeviceRequest* device_request,
CreateDeviceCallback& callback));
- MOCK_METHOD3(
- DoAddVirtualDevice,
- void(const media::VideoCaptureDeviceInfo& device_info,
- video_capture::mojom::ProducerProxy* producer,
- video_capture::mojom::VirtualDeviceRequest* virtual_device_request));
+ MOCK_METHOD3(DoAddVirtualDevice,
+ void(const media::VideoCaptureDeviceInfo& device_info,
+ video_capture::mojom::ProducerProxy* producer,
+ video_capture::mojom::SharedMemoryVirtualDeviceRequest*
+ virtual_device_request));
};
class MockVideoCaptureDeviceLauncherCallbacks
diff --git a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
index c03c46d7d78..59b89dc83ae 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -35,9 +35,9 @@ static const float kFrameRateToRequest = 15.0f;
class MockVideoCaptureControllerEventHandler
: public VideoCaptureControllerEventHandler {
public:
- MOCK_METHOD4(DoOnBufferCreated,
+ MOCK_METHOD4(DoOnNewBuffer,
void(VideoCaptureControllerID id,
- mojo::ScopedSharedBufferHandle* handle,
+ media::mojom::VideoBufferHandlePtr* buffer_handle,
int length,
int buffer_id));
MOCK_METHOD2(OnBufferDestroyed,
@@ -52,11 +52,11 @@ class MockVideoCaptureControllerEventHandler
MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID));
MOCK_METHOD1(OnStoppedUsingGpuDecode, void(VideoCaptureControllerID));
- void OnBufferCreated(VideoCaptureControllerID id,
- mojo::ScopedSharedBufferHandle handle,
- int length,
- int buffer_id) override {
- DoOnBufferCreated(id, &handle, length, buffer_id);
+ void OnNewBuffer(VideoCaptureControllerID id,
+ media::mojom::VideoBufferHandlePtr buffer_handle,
+ int length,
+ int buffer_id) override {
+ DoOnNewBuffer(id, &buffer_handle, length, buffer_id);
}
};
@@ -99,7 +99,6 @@ struct TestParams {
struct FrameInfo {
gfx::Size size;
media::VideoPixelFormat pixel_format;
- media::VideoPixelStorage storage_type;
base::TimeDelta timestamp;
};
@@ -254,8 +253,16 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest, StartAndImmediatelyStop) {
run_loop.Run();
}
+// Flaky on MSAN. https://crbug.com/840294
+#if defined(MEMORY_SANITIZER)
+#define MAYBE_ReceiveFramesFromFakeCaptureDevice \
+ DISABLED_ReceiveFramesFromFakeCaptureDevice
+#else
+#define MAYBE_ReceiveFramesFromFakeCaptureDevice \
+ ReceiveFramesFromFakeCaptureDevice
+#endif
IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
- ReceiveFramesFromFakeCaptureDevice) {
+ MAYBE_ReceiveFramesFromFakeCaptureDevice) {
#if defined(OS_ANDROID)
// TODO(chfremer): This test case is flaky on Android. Find out cause of
// flakiness and then re-enable. See https://crbug.com/709039.
@@ -310,7 +317,7 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
must_wait_for_gpu_decode_to_start = false;
}));
}
- EXPECT_CALL(mock_controller_event_handler_, DoOnBufferCreated(_, _, _, _))
+ EXPECT_CALL(mock_controller_event_handler_, DoOnNewBuffer(_, _, _, _))
.Times(AtLeast(1));
EXPECT_CALL(mock_controller_event_handler_, OnBufferReady(_, _, _))
.WillRepeatedly(Invoke(
@@ -319,7 +326,6 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
const media::mojom::VideoFrameInfoPtr& frame_info) {
FrameInfo received_frame_info;
received_frame_info.pixel_format = frame_info->pixel_format;
- received_frame_info.storage_type = frame_info->storage_type;
received_frame_info.size = frame_info->coded_size;
received_frame_info.timestamp = frame_info->timestamp;
received_frame_infos.emplace_back(received_frame_info);
@@ -350,7 +356,6 @@ IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
bool first_frame = true;
for (const auto& frame_info : received_frame_infos) {
EXPECT_EQ(params_.GetPixelFormatToUse(), frame_info.pixel_format);
- EXPECT_EQ(media::VideoPixelStorage::CPU, frame_info.storage_type);
EXPECT_EQ(params_.resolution_to_use, frame_info.size);
// Timestamps are expected to increase
if (!first_frame)
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
index 8ed10adda5c..773dbcc181a 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -28,15 +28,8 @@
namespace content {
-struct PixelFormatAndStorage {
- media::VideoPixelFormat pixel_format;
- media::VideoPixelStorage pixel_storage;
-};
-
-static const PixelFormatAndStorage kCapturePixelFormatAndStorages[] = {
- {media::PIXEL_FORMAT_I420, media::VideoPixelStorage::CPU},
- {media::PIXEL_FORMAT_ARGB, media::VideoPixelStorage::CPU},
- {media::PIXEL_FORMAT_Y16, media::VideoPixelStorage::CPU},
+static const media::VideoPixelFormat kCapturePixelFormats[] = {
+ media::PIXEL_FORMAT_I420, media::PIXEL_FORMAT_ARGB, media::PIXEL_FORMAT_Y16,
};
static const int kTestBufferPoolSize = 3;
@@ -46,7 +39,7 @@ static const int kTestBufferPoolSize = 3;
// with some context that is specific to renderer_host/media, and therefore
// this test must live here and not in media/capture/video.
class VideoCaptureBufferPoolTest
- : public testing::TestWithParam<PixelFormatAndStorage> {
+ : public testing::TestWithParam<media::VideoPixelFormat> {
protected:
// This is a generic Buffer tracker
class Buffer {
@@ -76,21 +69,17 @@ class VideoCaptureBufferPoolTest
expected_dropped_id_ = expected_dropped_id;
}
- std::unique_ptr<Buffer> ReserveBuffer(
- const gfx::Size& dimensions,
- PixelFormatAndStorage format_and_storage) {
+ std::unique_ptr<Buffer> ReserveBuffer(const gfx::Size& dimensions,
+ media::VideoPixelFormat pixel_format) {
// To verify that ReserveBuffer always sets |buffer_id_to_drop|,
// initialize it to something different than the expected value.
int buffer_id_to_drop = ~expected_dropped_id_;
- DVLOG(1) << media::VideoCaptureFormat::PixelStorageToString(
- format_and_storage.pixel_storage) << " "
- << media::VideoPixelFormatToString(format_and_storage.pixel_format)
- << " " << dimensions.ToString();
+ DVLOG(1) << media::VideoPixelFormatToString(pixel_format) << " "
+ << dimensions.ToString();
const int arbitrary_frame_feedback_id = 0;
- const int buffer_id = pool_->ReserveForProducer(
- dimensions, format_and_storage.pixel_format,
- format_and_storage.pixel_storage, arbitrary_frame_feedback_id,
- &buffer_id_to_drop);
+ const int buffer_id = pool_->ReserveForProducer(dimensions, pixel_format,
+ arbitrary_frame_feedback_id,
+ &buffer_id_to_drop);
if (buffer_id == media::VideoCaptureBufferPool::kInvalidId)
return std::unique_ptr<Buffer>();
EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop);
@@ -103,10 +92,9 @@ class VideoCaptureBufferPoolTest
std::unique_ptr<Buffer> ResurrectLastBuffer(
const gfx::Size& dimensions,
- PixelFormatAndStorage format_and_storage) {
- const int buffer_id = pool_->ResurrectLastForProducer(
- dimensions, format_and_storage.pixel_format,
- format_and_storage.pixel_storage);
+ media::VideoPixelFormat pixel_format) {
+ const int buffer_id =
+ pool_->ResurrectLastForProducer(dimensions, pixel_format);
if (buffer_id == media::VideoCaptureBufferPool::kInvalidId)
return std::unique_ptr<Buffer>();
return std::unique_ptr<Buffer>(new Buffer(
@@ -124,10 +112,8 @@ class VideoCaptureBufferPoolTest
TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
const gfx::Size size_lo = gfx::Size(10, 10);
const gfx::Size size_hi = gfx::Size(21, 33);
- const media::VideoCaptureFormat format_lo(
- size_lo, 0.0, GetParam().pixel_format, GetParam().pixel_storage);
- const media::VideoCaptureFormat format_hi(
- size_hi, 0.0, GetParam().pixel_format, GetParam().pixel_storage);
+ const media::VideoCaptureFormat format_lo(size_lo, 0.0, GetParam());
+ const media::VideoCaptureFormat format_hi(size_hi, 0.0, GetParam());
// Reallocation won't happen for the first part of the test.
ExpectDroppedId(media::VideoCaptureBufferPool::kInvalidId);
@@ -352,13 +338,11 @@ TEST_P(VideoCaptureBufferPoolTest, DoesNotResurrectIfPropertiesNotMatched) {
// Expect that the buffer cannot be resurrected if the pixel format does not
// match.
- PixelFormatAndStorage altered_format_or_storage = GetParam();
- altered_format_or_storage.pixel_format =
- (altered_format_or_storage.pixel_format == media::PIXEL_FORMAT_I420
- ? media::PIXEL_FORMAT_ARGB
- : media::PIXEL_FORMAT_I420);
- resurrected =
- ResurrectLastBuffer(gfx::Size(10, 10), altered_format_or_storage);
+ media::VideoPixelFormat altered_format = GetParam();
+ altered_format =
+ (altered_format == media::PIXEL_FORMAT_I420 ? media::PIXEL_FORMAT_ARGB
+ : media::PIXEL_FORMAT_I420);
+ resurrected = ResurrectLastBuffer(gfx::Size(10, 10), altered_format);
ASSERT_EQ(nullptr, resurrected.get());
// Finally, check that the buffer CAN be resurrected if all properties match.
@@ -410,6 +394,6 @@ TEST_P(VideoCaptureBufferPoolTest, AvoidsClobberingForResurrectingLastBuffer) {
INSTANTIATE_TEST_CASE_P(,
VideoCaptureBufferPoolTest,
- testing::ValuesIn(kCapturePixelFormatAndStorages));
+ testing::ValuesIn(kCapturePixelFormats));
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.cc b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
index 8d2cc05ab2c..26a225d1b9f 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -111,13 +111,13 @@ VideoCaptureController::BufferContext::BufferContext(
int buffer_context_id,
int buffer_id,
media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer,
- mojo::ScopedSharedBufferHandle handle)
+ media::mojom::VideoBufferHandlePtr buffer_handle)
: buffer_context_id_(buffer_context_id),
buffer_id_(buffer_id),
is_retired_(false),
frame_feedback_id_(0),
consumer_feedback_observer_(consumer_feedback_observer),
- buffer_handle_(std::move(handle)),
+ buffer_handle_(std::move(buffer_handle)),
max_consumer_utilization_(
media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded),
consumer_hold_count_(0) {}
@@ -157,16 +157,29 @@ void VideoCaptureController::BufferContext::DecreaseConsumerCount() {
}
}
-mojo::ScopedSharedBufferHandle
-VideoCaptureController::BufferContext::CloneHandle() {
- // Special behavior here: If the handle was already read-only, the Clone()
- // call here will maintain that read-only permission. If it was read-write,
- // the cloned handle will have read-write permission.
- //
- // TODO(crbug.com/797470): We should be able to demote read-write to read-only
- // permissions when Clone()'ing handles. Currently, this causes a crash.
- return buffer_handle_->Clone(
- mojo::SharedBufferHandle::AccessMode::READ_WRITE);
+media::mojom::VideoBufferHandlePtr
+VideoCaptureController::BufferContext::CloneBufferHandle() {
+ // Unable to use buffer_handle_->Clone(), because shared_buffer does not
+ // support the copy constructor.
+ media::mojom::VideoBufferHandlePtr result =
+ media::mojom::VideoBufferHandle::New();
+ if (buffer_handle_->is_shared_buffer_handle()) {
+ // Special behavior here: If the handle was already read-only, the Clone()
+ // call here will maintain that read-only permission. If it was read-write,
+ // the cloned handle will have read-write permission.
+ //
+ // TODO(crbug.com/797470): We should be able to demote read-write to
+ // read-only permissions when Clone()'ing handles. Currently, this causes a
+ // crash.
+ result->set_shared_buffer_handle(
+ buffer_handle_->get_shared_buffer_handle()->Clone(
+ mojo::SharedBufferHandle::AccessMode::READ_WRITE));
+ } else if (buffer_handle_->is_mailbox_handles()) {
+ result->set_mailbox_handles(buffer_handle_->get_mailbox_handles()->Clone());
+ } else {
+ NOTREACHED() << "Unexpected video buffer handle type";
+ }
+ return result;
}
VideoCaptureController::VideoCaptureController(
@@ -212,8 +225,7 @@ void VideoCaptureController::AddClient(
// report an error immediately and punt.
if (!params.IsValid() ||
!(params.requested_format.pixel_format == media::PIXEL_FORMAT_I420 ||
- params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16) ||
- params.requested_format.pixel_storage != media::VideoPixelStorage::CPU) {
+ params.requested_format.pixel_format == media::PIXEL_FORMAT_Y16)) {
// Crash in debug builds since the renderer should not have asked for
// invalid or unsupported parameters.
LOG(DFATAL) << "Invalid or unsupported video capture parameters requested: "
@@ -383,16 +395,15 @@ VideoCaptureController::GetVideoCaptureFormat() const {
return video_capture_format_;
}
-void VideoCaptureController::OnNewBufferHandle(
- int buffer_id,
- std::unique_ptr<media::VideoCaptureDevice::Client::Buffer::HandleProvider>
- handle_provider) {
+void VideoCaptureController::OnNewBuffer(
+ int32_t buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(FindUnretiredBufferContextFromBufferId(buffer_id) ==
buffer_contexts_.end());
- buffer_contexts_.emplace_back(
- next_buffer_context_id_++, buffer_id, launched_device_.get(),
- handle_provider->GetHandleForInterProcessTransit(true /* read only */));
+ buffer_contexts_.emplace_back(next_buffer_context_id_++, buffer_id,
+ launched_device_.get(),
+ std::move(buffer_handle));
}
void VideoCaptureController::OnFrameReadyInBuffer(
@@ -423,11 +434,10 @@ void VideoCaptureController::OnFrameReadyInBuffer(
client->known_buffer_context_ids.push_back(buffer_context_id);
const size_t mapped_size =
media::VideoCaptureFormat(frame_info->coded_size, 0.0f,
- frame_info->pixel_format,
- frame_info->storage_type)
+ frame_info->pixel_format)
.ImageAllocationSize();
- client->event_handler->OnBufferCreated(
- client->controller_id, buffer_context_iter->CloneHandle(),
+ client->event_handler->OnNewBuffer(
+ client->controller_id, buffer_context_iter->CloneBufferHandle(),
mapped_size, buffer_context_id);
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.h b/chromium/content/browser/renderer_host/media/video_capture_controller.h
index 78a96b7c18d..62c39fa7901 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -99,10 +99,8 @@ class CONTENT_EXPORT VideoCaptureController
bool has_received_frames() const { return has_received_frames_; }
// Implementation of media::VideoFrameReceiver interface:
- void OnNewBufferHandle(
- int buffer_id,
- std::unique_ptr<media::VideoCaptureDevice::Client::Buffer::HandleProvider>
- handle_provider) override;
+ void OnNewBuffer(int32_t buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle) override;
void OnFrameReadyInBuffer(
int buffer_id,
int frame_feedback_id,
@@ -156,13 +154,16 @@ class CONTENT_EXPORT VideoCaptureController
int buffer_context_id,
int buffer_id,
media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer,
- mojo::ScopedSharedBufferHandle handle);
+ media::mojom::VideoBufferHandlePtr buffer_handle);
~BufferContext();
BufferContext(BufferContext&& other);
BufferContext& operator=(BufferContext&& other);
int buffer_context_id() const { return buffer_context_id_; }
int buffer_id() const { return buffer_id_; }
bool is_retired() const { return is_retired_; }
+ const media::mojom::VideoBufferHandlePtr& buffer_handle() const {
+ return buffer_handle_;
+ }
void set_is_retired() { is_retired_ = true; }
void set_frame_feedback_id(int id) { frame_feedback_id_ = id; }
void set_consumer_feedback_observer(
@@ -179,7 +180,7 @@ class CONTENT_EXPORT VideoCaptureController
void IncreaseConsumerCount();
void DecreaseConsumerCount();
bool HasConsumers() const { return consumer_hold_count_ > 0; }
- mojo::ScopedSharedBufferHandle CloneHandle();
+ media::mojom::VideoBufferHandlePtr CloneBufferHandle();
private:
int buffer_context_id_;
@@ -187,7 +188,7 @@ class CONTENT_EXPORT VideoCaptureController
bool is_retired_;
int frame_feedback_id_;
media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer_;
- mojo::ScopedSharedBufferHandle buffer_handle_;
+ media::mojom::VideoBufferHandlePtr buffer_handle_;
double max_consumer_utilization_;
int consumer_hold_count_;
std::unique_ptr<
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
index 674a8b5f534..4cac4888331 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -35,11 +35,10 @@ class CONTENT_EXPORT VideoCaptureControllerEventHandler {
// An Error has occurred in the VideoCaptureDevice.
virtual void OnError(VideoCaptureControllerID id) = 0;
- // A buffer has been newly created.
- virtual void OnBufferCreated(VideoCaptureControllerID id,
- mojo::ScopedSharedBufferHandle handle,
- int length,
- int buffer_id) = 0;
+ virtual void OnNewBuffer(VideoCaptureControllerID id,
+ media::mojom::VideoBufferHandlePtr buffer_handle,
+ int length,
+ int buffer_id) = 0;
// A previously created buffer has been freed and will no longer be used.
virtual void OnBufferDestroyed(VideoCaptureControllerID id,
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
index f9f188c99c8..cb0e9112390 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -73,10 +73,10 @@ class MockVideoCaptureControllerEventHandler
MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID));
void OnError(VideoCaptureControllerID id) override { DoError(id); }
- void OnBufferCreated(VideoCaptureControllerID id,
- mojo::ScopedSharedBufferHandle handle,
- int length,
- int buffer_id) override {
+ void OnNewBuffer(VideoCaptureControllerID id,
+ media::mojom::VideoBufferHandlePtr buffer_handle,
+ int length,
+ int buffer_id) override {
DoBufferCreated(id, buffer_id);
}
void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {
@@ -319,9 +319,9 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
const int arbitrary_frame_feedback_id = 101;
ASSERT_EQ(0.0, device_client_->GetBufferPoolUtilization());
media::VideoCaptureDevice::Client::Buffer buffer =
- device_client_->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id);
+ device_client_->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id);
ASSERT_TRUE(buffer.is_valid());
auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess();
ASSERT_EQ(1.0 / kPoolSize, device_client_->GetBufferPoolUtilization());
@@ -365,9 +365,9 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// delay. This shouldn't affect anything.
const int arbitrary_frame_feedback_id_2 = 102;
media::VideoCaptureDevice::Client::Buffer buffer2 =
- device_client_->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id_2);
+ device_client_->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id_2);
ASSERT_TRUE(buffer2.is_valid());
auto buffer2_access = buffer2.handle_provider->GetHandleForInProcessAccess();
memset(buffer2_access->data(), buffer_no++, buffer2_access->mapped_size());
@@ -414,9 +414,9 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
for (int i = 0; i < kPoolSize; i++) {
const int arbitrary_frame_feedback_id = 200 + i;
media::VideoCaptureDevice::Client::Buffer buffer =
- device_client_->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id);
+ device_client_->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id);
ASSERT_TRUE(buffer.is_valid());
auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess();
memset(buffer_access->data(), buffer_no++, buffer_access->mapped_size());
@@ -426,9 +426,9 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
}
// ReserveOutputBuffer ought to fail now, because the pool is depleted.
ASSERT_FALSE(device_client_
- ->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id)
+ ->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id)
.is_valid());
// The new client needs to be notified of the creation of |kPoolSize| buffers;
@@ -465,9 +465,9 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
controller_->StopSession(300);
// Queue up another buffer.
media::VideoCaptureDevice::Client::Buffer buffer3 =
- device_client_->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id);
+ device_client_->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id);
ASSERT_TRUE(buffer3.is_valid());
auto buffer3_access = buffer3.handle_provider->GetHandleForInProcessAccess();
memset(buffer3_access->data(), buffer_no++, buffer3_access->mapped_size());
@@ -476,9 +476,9 @@ TEST_P(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
arbitrary_timestamp_);
media::VideoCaptureDevice::Client::Buffer buffer4 =
- device_client_->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id);
+ device_client_->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id);
{
// Kill A2 via session close (posts a task to disconnect, but A2 must not
// be sent either of these two buffers).
@@ -534,13 +534,12 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
Mock::VerifyAndClearExpectations(client_b_.get());
media::VideoCaptureFormat device_format(
- capture_resolution, arbitrary_frame_rate_, media::PIXEL_FORMAT_I420,
- media::VideoPixelStorage::CPU);
+ capture_resolution, arbitrary_frame_rate_, media::PIXEL_FORMAT_I420);
const int arbitrary_frame_feedback_id = 101;
media::VideoCaptureDevice::Client::Buffer buffer =
- device_client_->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id);
+ device_client_->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id);
device_client_->OnIncomingCapturedBuffer(std::move(buffer), device_format,
arbitrary_reference_time_,
arbitrary_timestamp_);
@@ -572,9 +571,9 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
gfx::Size(10, 10), arbitrary_frame_rate_, media::PIXEL_FORMAT_I420);
const int arbitrary_frame_feedback_id = 101;
media::VideoCaptureDevice::Client::Buffer buffer =
- device_client_->ReserveOutputBuffer(
- device_format.frame_size, device_format.pixel_format,
- device_format.pixel_storage, arbitrary_frame_feedback_id);
+ device_client_->ReserveOutputBuffer(device_format.frame_size,
+ device_format.pixel_format,
+ arbitrary_frame_feedback_id);
ASSERT_TRUE(buffer.is_valid());
device_client_->OnError(FROM_HERE, "Test Error");
@@ -634,11 +633,11 @@ TEST_F(VideoCaptureControllerTest, FrameFeedbackIsReportedForSequenceOfFrames) {
if (frame_index < kTestFrameSequenceLength / 2) {
buffer = device_client_->ReserveOutputBuffer(
arbitrary_format.frame_size, arbitrary_format.pixel_format,
- arbitrary_format.pixel_storage, stub_frame_feedback_id);
+ stub_frame_feedback_id);
} else {
buffer = device_client_->ResurrectLastOutputBuffer(
arbitrary_format.frame_size, arbitrary_format.pixel_format,
- arbitrary_format.pixel_storage, stub_frame_feedback_id);
+ stub_frame_feedback_id);
}
ASSERT_TRUE(buffer.is_valid());
device_client_->OnIncomingCapturedBuffer(
diff --git a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
index 521eb91840e..f97690233f2 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -176,7 +177,6 @@ void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
media::mojom::VideoFrameInfo::New();
out_frame_info->timestamp = timestamp;
out_frame_info->pixel_format = media::PIXEL_FORMAT_I420;
- out_frame_info->storage_type = media::VideoPixelStorage::CPU;
out_frame_info->coded_size = dimensions;
out_frame_info->visible_rect = gfx::Rect(dimensions);
out_frame_info->metadata = out_frame->metadata()->GetInternalValues().Clone();
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.cc b/chromium/content/browser/renderer_host/media/video_capture_host.cc
index c362c364707..209d64c83db 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -13,7 +13,6 @@
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
-#include "mojo/common/values_struct_traits.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace content {
@@ -114,17 +113,18 @@ void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id) {
controller_id));
}
-void VideoCaptureHost::OnBufferCreated(VideoCaptureControllerID controller_id,
- mojo::ScopedSharedBufferHandle handle,
- int length,
- int buffer_id) {
+void VideoCaptureHost::OnNewBuffer(
+ VideoCaptureControllerID controller_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle,
+ int length,
+ int buffer_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (controllers_.find(controller_id) == controllers_.end())
return;
if (base::ContainsKey(device_id_to_observer_map_, controller_id)) {
- device_id_to_observer_map_[controller_id]->OnBufferCreated(
- buffer_id, std::move(handle));
+ device_id_to_observer_map_[controller_id]->OnNewBuffer(
+ buffer_id, std::move(buffer_handle));
}
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.h b/chromium/content/browser/renderer_host/media/video_capture_host.h
index 6a9fe208d3b..d19c4ad5b20 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -54,10 +54,10 @@ class CONTENT_EXPORT VideoCaptureHost
// VideoCaptureControllerEventHandler implementation.
void OnError(VideoCaptureControllerID id) override;
- void OnBufferCreated(VideoCaptureControllerID id,
- mojo::ScopedSharedBufferHandle handle,
- int length,
- int buffer_id) override;
+ void OnNewBuffer(VideoCaptureControllerID id,
+ media::mojom::VideoBufferHandlePtr buffer_handle,
+ int length,
+ int buffer_id) override;
void OnBufferDestroyed(VideoCaptureControllerID id,
int buffer_id) override;
void OnBufferReady(
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.h b/chromium/content/browser/renderer_host/media/video_capture_manager.h
index 908b205b7df..0604c90425d 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/observer_list.h"
#include "base/process/process_handle.h"
#include "base/threading/thread_checker.h"
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index d02c7104d74..5816d1b3803 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -142,7 +142,7 @@ class WrappedDeviceFactory : public media::FakeVideoCaptureDeviceFactory {
class MockMediaStreamProviderListener : public MediaStreamProviderListener {
public:
MockMediaStreamProviderListener() {}
- ~MockMediaStreamProviderListener() {}
+ ~MockMediaStreamProviderListener() override {}
MOCK_METHOD2(Opened, void(MediaStreamType, int));
MOCK_METHOD2(Closed, void(MediaStreamType, int));
@@ -156,9 +156,10 @@ class MockFrameObserver : public VideoCaptureControllerEventHandler {
MOCK_METHOD1(OnStarted, void(VideoCaptureControllerID id));
MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID id));
- void OnBufferCreated(VideoCaptureControllerID id,
- mojo::ScopedSharedBufferHandle handle,
- int length, int buffer_id) override {}
+ void OnNewBuffer(VideoCaptureControllerID id,
+ media::mojom::VideoBufferHandlePtr buffer_handle,
+ int length,
+ int buffer_id) override {}
void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {}
void OnBufferReady(
VideoCaptureControllerID id,
diff --git a/chromium/content/browser/renderer_host/media/video_capture_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
index 3eb79dba90a..6cebba5ed0f 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -153,10 +153,11 @@ class VideoCaptureTest : public testing::Test,
{
base::RunLoop run_loop;
media_stream_manager_->OpenDevice(
- render_process_id, render_frame_id,
- browser_context_.GetMediaDeviceIDSalt(), page_request_id,
+ render_process_id, render_frame_id, page_request_id,
video_devices[0].device_id, MEDIA_DEVICE_VIDEO_CAPTURE,
- security_origin,
+ MediaDeviceSaltAndOrigin{browser_context_.GetMediaDeviceIDSalt(),
+ browser_context_.GetMediaDeviceIDSalt(),
+ security_origin},
base::BindOnce(&VideoCaptureTest::OnDeviceOpened,
base::Unretained(this), run_loop.QuitClosure()),
MediaStreamManager::DeviceStoppedCallback());
@@ -176,11 +177,11 @@ class VideoCaptureTest : public testing::Test,
protected:
// media::mojom::VideoCaptureObserver implementation.
MOCK_METHOD1(OnStateChanged, void(media::mojom::VideoCaptureState));
- void OnBufferCreated(int32_t buffer_id,
- mojo::ScopedSharedBufferHandle handle) override {
- DoOnBufferCreated(buffer_id);
+ void OnNewBuffer(int32_t buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle) override {
+ DoOnNewBuffer(buffer_id);
}
- MOCK_METHOD1(DoOnBufferCreated, void(int32_t));
+ MOCK_METHOD1(DoOnNewBuffer, void(int32_t));
void OnBufferReady(int32_t buffer_id,
media::mojom::VideoFrameInfoPtr info) override {
DoOnBufferReady(buffer_id);
@@ -196,7 +197,7 @@ class VideoCaptureTest : public testing::Test,
EXPECT_CALL(*this,
OnStateChanged(media::mojom::VideoCaptureState::STARTED));
- EXPECT_CALL(*this, DoOnBufferCreated(_))
+ EXPECT_CALL(*this, DoOnNewBuffer(_))
.Times(AnyNumber())
.WillRepeatedly(Return());
EXPECT_CALL(*this, DoOnBufferReady(_))
@@ -298,7 +299,7 @@ class VideoCaptureTest : public testing::Test,
}
// |media_stream_manager_| needs to outlive |thread_bundle_| because it is a
- // MessageLoop::DestructionObserver.
+ // MessageLoopCurrent::DestructionObserver.
std::unique_ptr<MediaStreamManager> media_stream_manager_;
const content::TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<media::AudioManager> audio_manager_;
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
index 1ebfab212ea..83ffef0cd75 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
@@ -14,14 +14,7 @@ namespace content {
NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
int modifiers,
base::TimeTicks timestamp)
- : NativeWebKeyboardEvent(type,
- modifiers,
- ui::EventTimeStampToSeconds(timestamp)) {}
-
-NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
- int modifiers,
- double timestampSeconds)
- : WebKeyboardEvent(type, modifiers, timestampSeconds),
+ : WebKeyboardEvent(type, modifiers, timestamp),
os_event(nullptr),
skip_in_browser(false) {}
@@ -35,7 +28,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
const base::android::JavaRef<jobject>& android_key_event,
blink::WebInputEvent::Type type,
int modifiers,
- double time_secs,
+ base::TimeTicks timestamp,
int keycode,
int scancode,
int unicode_character,
@@ -44,7 +37,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
android_key_event,
type,
modifiers,
- time_secs,
+ timestamp,
keycode,
scancode,
unicode_character,
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
index 0c626b7e663..7c416533c4a 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_aura.cc
@@ -73,10 +73,7 @@ class TranslatedKeyEvent : public ui::KeyEvent {
type, static_cast<ui::KeyboardCode>(web_event.windows_key_code),
ui::KeycodeConverter::NativeKeycodeToDomCode(web_event.native_key_code),
WebEventModifiersToEventFlags(web_event.GetModifiers()),
- web_event.dom_key,
- base::TimeTicks() +
- base::TimeDelta::FromSecondsD(web_event.TimeStampSeconds()),
- is_char);
+ web_event.dom_key, web_event.TimeStamp(), is_char);
}
private:
@@ -101,14 +98,7 @@ namespace content {
NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
int modifiers,
base::TimeTicks timestamp)
- : NativeWebKeyboardEvent(type,
- modifiers,
- ui::EventTimeStampToSeconds(timestamp)) {}
-
-NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
- int modifiers,
- double timestampSeconds)
- : WebKeyboardEvent(type, modifiers, timestampSeconds),
+ : WebKeyboardEvent(type, modifiers, timestamp),
os_event(nullptr),
skip_in_browser(false) {}
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm b/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
index 55ad0ee5ef2..8e074b8eb7c 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_mac.mm
@@ -43,14 +43,7 @@ size_t WebKeyboardEventTextLength(const blink::WebUChar* text) {
NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
int modifiers,
base::TimeTicks timestamp)
- : NativeWebKeyboardEvent(type,
- modifiers,
- ui::EventTimeStampToSeconds(timestamp)) {}
-
-NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
- int modifiers,
- double timestampSeconds)
- : WebKeyboardEvent(type, modifiers, timestampSeconds),
+ : WebKeyboardEvent(type, modifiers, timestamp),
os_event(NULL),
skip_in_browser(false) {}
@@ -82,7 +75,8 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(
os_event = [[NSEvent keyEventWithType:type
location:NSZeroPoint
modifierFlags:flags
- timestamp:web_event.TimeStampSeconds()
+ timestamp:ui::EventTimeStampToSeconds(
+ web_event.TimeStamp())
windowNumber:[[native_view window] windowNumber]
context:nil
characters:text
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc
deleted file mode 100644
index e9e7e1b0e91..00000000000
--- a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2016 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/renderer_host/offscreen_canvas_provider_impl.h"
-
-#include "base/bind.h"
-#include "components/viz/host/host_frame_sink_manager.h"
-#include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
-
-namespace content {
-
-OffscreenCanvasProviderImpl::OffscreenCanvasProviderImpl(
- viz::HostFrameSinkManager* host_frame_sink_manager,
- uint32_t renderer_client_id)
- : host_frame_sink_manager_(host_frame_sink_manager),
- renderer_client_id_(renderer_client_id) {}
-
-OffscreenCanvasProviderImpl::~OffscreenCanvasProviderImpl() = default;
-
-void OffscreenCanvasProviderImpl::Add(
- blink::mojom::OffscreenCanvasProviderRequest request) {
- bindings_.AddBinding(this, std::move(request));
-}
-
-void OffscreenCanvasProviderImpl::CreateOffscreenCanvasSurface(
- const viz::FrameSinkId& parent_frame_sink_id,
- const viz::FrameSinkId& frame_sink_id,
- blink::mojom::OffscreenCanvasSurfaceClientPtr client) {
- // TODO(kylechar): Kill the renderer too.
- if (parent_frame_sink_id.client_id() != renderer_client_id_) {
- DLOG(ERROR) << "Invalid parent client id " << parent_frame_sink_id;
- return;
- }
- if (frame_sink_id.client_id() != renderer_client_id_) {
- DLOG(ERROR) << "Invalid client id " << frame_sink_id;
- return;
- }
-
- auto destroy_callback = base::BindOnce(
- &OffscreenCanvasProviderImpl::DestroyOffscreenCanvasSurface,
- base::Unretained(this), frame_sink_id);
-
- canvas_map_[frame_sink_id] = std::make_unique<OffscreenCanvasSurfaceImpl>(
- host_frame_sink_manager_, parent_frame_sink_id, frame_sink_id,
- std::move(client), std::move(destroy_callback));
-}
-
-void OffscreenCanvasProviderImpl::CreateCompositorFrameSink(
- const viz::FrameSinkId& frame_sink_id,
- viz::mojom::CompositorFrameSinkClientPtr client,
- viz::mojom::CompositorFrameSinkRequest request) {
- // TODO(kylechar): Kill the renderer too.
- if (frame_sink_id.client_id() != renderer_client_id_) {
- DLOG(ERROR) << "Invalid client id " << frame_sink_id;
- return;
- }
-
- auto iter = canvas_map_.find(frame_sink_id);
- if (iter == canvas_map_.end()) {
- DLOG(ERROR) << "No OffscreenCanvasSurfaceImpl for " << frame_sink_id;
- return;
- }
-
- iter->second->CreateCompositorFrameSink(std::move(client),
- std::move(request));
-}
-
-void OffscreenCanvasProviderImpl::DestroyOffscreenCanvasSurface(
- viz::FrameSinkId frame_sink_id) {
- canvas_map_.erase(frame_sink_id);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h b/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h
deleted file mode 100644
index 9248dfeabbb..00000000000
--- a/chromium/content/browser/renderer_host/offscreen_canvas_provider_impl.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2016 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_RENDERER_HOST_OFFSCREEN_CANVAS_PROVIDER_IMPL_H_
-#define CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_PROVIDER_IMPL_H_
-
-#include <memory>
-
-#include "base/containers/flat_map.h"
-#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "third_party/blink/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h"
-
-namespace viz {
-class HostFrameSinkManager;
-}
-
-namespace content {
-
-class OffscreenCanvasSurfaceImpl;
-
-// Creates OffscreenCanvasSurfaces and CompositorFrameSinks for a renderer.
-class CONTENT_EXPORT OffscreenCanvasProviderImpl
- : public blink::mojom::OffscreenCanvasProvider {
- public:
- OffscreenCanvasProviderImpl(
- viz::HostFrameSinkManager* host_frame_sink_manager,
- uint32_t renderer_client_id);
- ~OffscreenCanvasProviderImpl() override;
-
- void Add(blink::mojom::OffscreenCanvasProviderRequest request);
-
- // blink::mojom::OffscreenCanvasProvider implementation.
- void CreateOffscreenCanvasSurface(
- const viz::FrameSinkId& parent_frame_sink_id,
- const viz::FrameSinkId& frame_sink_id,
- blink::mojom::OffscreenCanvasSurfaceClientPtr client) override;
- void CreateCompositorFrameSink(
- const viz::FrameSinkId& frame_sink_id,
- viz::mojom::CompositorFrameSinkClientPtr client,
- viz::mojom::CompositorFrameSinkRequest request) override;
-
- private:
- friend class OffscreenCanvasProviderImplTest;
-
- // Destroys the |canvas_map_| entry for |frame_sink_id|. Provided as a
- // callback to each OffscreenCanvasSurfaceImpl so they can destroy themselves.
- void DestroyOffscreenCanvasSurface(viz::FrameSinkId frame_sink_id);
-
- viz::HostFrameSinkManager* const host_frame_sink_manager_;
-
- // FrameSinkIds for offscreen canvas must use the renderer client id.
- const uint32_t renderer_client_id_;
-
- mojo::BindingSet<blink::mojom::OffscreenCanvasProvider> bindings_;
-
- base::flat_map<viz::FrameSinkId, std::unique_ptr<OffscreenCanvasSurfaceImpl>>
- canvas_map_;
-
- DISALLOW_COPY_AND_ASSIGN(OffscreenCanvasProviderImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_OFFSCREEN_CANVAS_PROVIDER_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/overscroll_configuration.cc b/chromium/content/browser/renderer_host/overscroll_configuration.cc
index 51b4e0dbd72..34496b12ac8 100644
--- a/chromium/content/browser/renderer_host/overscroll_configuration.cc
+++ b/chromium/content/browser/renderer_host/overscroll_configuration.cc
@@ -29,6 +29,10 @@ const float kThresholdStartTouchscreen = 50.f;
bool g_is_touchpad_overscroll_history_navigation_enabled_initialized = false;
bool g_touchpad_overscroll_history_navigation_enabled = false;
+// On Windows, we only process 0.3 second inertial events then cancel the
+// overscroll if it is not completed yet.
+int g_max_inertial_events_before_overscroll_cancellation_in_ms = 300;
+
float GetStartThresholdMultiplier() {
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
if (!cmd->HasSwitch(switches::kOverscrollStartThreshold))
@@ -148,4 +152,11 @@ void OverscrollConfig::ResetTouchpadOverscrollHistoryNavigationEnabled() {
g_is_touchpad_overscroll_history_navigation_enabled_initialized = false;
}
+// static
+base::TimeDelta
+OverscrollConfig::MaxInertialEventsBeforeOverscrollCancellation() {
+ return base::TimeDelta::FromMilliseconds(
+ g_max_inertial_events_before_overscroll_cancellation_in_ms);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index 48656300248..a4bb1af79d3 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -17,6 +17,11 @@ namespace content {
namespace {
+// Minimum amount of time after an actual scroll after which a pull-to-refresh
+// can start.
+constexpr base::TimeDelta kPullToRefreshCoolOffDelay =
+ base::TimeDelta::FromMilliseconds(600);
+
bool IsGestureEventFromTouchpad(const blink::WebInputEvent& event) {
DCHECK(blink::WebInputEvent::IsGestureEventType(event.GetType()));
const blink::WebGestureEvent& gesture =
@@ -24,6 +29,16 @@ bool IsGestureEventFromTouchpad(const blink::WebInputEvent& event) {
return gesture.SourceDevice() == blink::kWebGestureDeviceTouchpad;
}
+bool IsGestureScrollUpdateInertialEvent(const blink::WebInputEvent& event) {
+ if (event.GetType() != blink::WebInputEvent::kGestureScrollUpdate)
+ return false;
+
+ const blink::WebGestureEvent& gesture =
+ static_cast<const blink::WebGestureEvent&>(event);
+ return gesture.data.scroll_update.inertial_phase ==
+ blink::WebGestureEvent::kMomentumPhase;
+}
+
float ClampAbsoluteValue(float value, float max_abs) {
DCHECK_LT(0.f, max_abs);
return std::max(-max_abs, std::min(value, max_abs));
@@ -81,21 +96,11 @@ bool OverscrollController::ShouldProcessEvent(
bool OverscrollController::ShouldIgnoreInertialEvent(
const blink::WebInputEvent& event) const {
- if (!ignore_following_inertial_events_ ||
- event.GetType() != blink::WebInputEvent::kGestureScrollUpdate) {
- return false;
+ return ignore_following_inertial_events_ &&
+ IsGestureScrollUpdateInertialEvent(event);
}
- const blink::WebGestureEvent& gesture =
- static_cast<const blink::WebGestureEvent&>(event);
- return gesture.data.scroll_update.inertial_phase ==
- blink::WebGestureEvent::kMomentumPhase;
-}
-
bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
- if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
- ignore_following_inertial_events_ = false;
-
if (!ShouldProcessEvent(event))
return false;
@@ -104,8 +109,20 @@ bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
if (event.GetType() == blink::WebInputEvent::kMouseWheel)
return false;
- if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
- event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
+ ignore_following_inertial_events_ = false;
+ first_inertial_event_time_.reset();
+ time_since_last_ignored_scroll_ =
+ event.TimeStamp() - last_ignored_scroll_time_;
+ // Will handle events when processing ACKs to ensure the correct order.
+ return false;
+ }
+
+ if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
+ if (scroll_state_ == ScrollState::CONTENT_CONSUMING ||
+ overscroll_ignored_) {
+ last_ignored_scroll_time_ = event.TimeStamp();
+ }
// Will handle events when processing ACKs to ensure the correct order.
return false;
}
@@ -366,10 +383,29 @@ bool OverscrollController::ProcessEventForOverscroll(
case blink::WebInputEvent::kGestureScrollUpdate: {
const blink::WebGestureEvent& gesture =
static_cast<const blink::WebGestureEvent&>(event);
+ bool is_gesture_scroll_update_inertial_event =
+ IsGestureScrollUpdateInertialEvent(event);
event_processed = ProcessOverscroll(
gesture.data.scroll_update.delta_x,
gesture.data.scroll_update.delta_y,
- gesture.SourceDevice() == blink::kWebGestureDeviceTouchpad);
+ gesture.SourceDevice() == blink::kWebGestureDeviceTouchpad,
+ is_gesture_scroll_update_inertial_event);
+ if (is_gesture_scroll_update_inertial_event) {
+ // Record the timestamp of first inertial event.
+ if (!first_inertial_event_time_) {
+ first_inertial_event_time_ = event.TimeStamp();
+ break;
+ }
+ base::TimeDelta inertial_event_interval =
+ event.TimeStamp() - first_inertial_event_time_.value();
+ if (inertial_event_interval >=
+ OverscrollConfig::MaxInertialEventsBeforeOverscrollCancellation()) {
+ ignore_following_inertial_events_ = true;
+ // Reset overscroll state if fling didn't complete the overscroll
+ // gesture within the first 20 inertial events.
+ Cancel();
+ }
+ }
break;
}
case blink::WebInputEvent::kGestureFlingStart: {
@@ -409,10 +445,15 @@ bool OverscrollController::ProcessEventForOverscroll(
bool OverscrollController::ProcessOverscroll(float delta_x,
float delta_y,
- bool is_touchpad) {
+ bool is_touchpad,
+ bool is_inertial) {
if (scroll_state_ == ScrollState::CONTENT_CONSUMING)
return false;
+ // Do not start overscroll for inertial events.
+ if (overscroll_mode_ == OVERSCROLL_NONE && is_inertial)
+ return false;
+
overscroll_delta_x_ += delta_x;
overscroll_delta_y_ += delta_y;
@@ -473,7 +514,9 @@ bool OverscrollController::ProcessOverscroll(float delta_x,
if (ptr_mode == OverscrollConfig::PullToRefreshMode::kDisabled ||
(ptr_mode ==
OverscrollConfig::PullToRefreshMode::kEnabledTouchschreen &&
- is_touchpad)) {
+ is_touchpad) ||
+ time_since_last_ignored_scroll_ < kPullToRefreshCoolOffDelay) {
+ overscroll_ignored_ = true;
new_mode = OVERSCROLL_NONE;
}
}
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index a76a633aada..dbc94c174bd 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -7,6 +7,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/optional.h"
+#include "base/time/time.h"
#include "cc/input/overscroll_behavior.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
@@ -111,7 +113,10 @@ class CONTENT_EXPORT OverscrollController {
// and the over scroll amount (i.e. |overscroll_mode_|, |overscroll_delta_x_|
// and |overscroll_delta_y_|). Returns true if overscroll was handled by the
// delegate.
- bool ProcessOverscroll(float delta_x, float delta_y, bool is_touchpad);
+ bool ProcessOverscroll(float delta_x,
+ float delta_y,
+ bool is_touchpad,
+ bool is_inertial);
// Completes the desired action from the current gesture.
void CompleteAction();
@@ -161,10 +166,30 @@ class CONTENT_EXPORT OverscrollController {
bool wheel_scroll_latching_enabled_;
// A inertial scroll (fling) event may complete an overscroll gesture and
- // navigate to a new page, but the inertial scroll can continue to generate
- // scroll-update events. These events need to be ignored.
+ // navigate to a new page or cancel the overscroll animation. In both cases
+ // inertial scroll can continue to generate scroll-update events. These events
+ // need to be ignored.
bool ignore_following_inertial_events_ = false;
+ // Specifies whether last overscroll was ignored, either due to a command line
+ // flag or because cool off period had not passed.
+ bool overscroll_ignored_ = false;
+
+ // Timestamp for the end of the last ignored scroll sequence.
+ base::TimeTicks last_ignored_scroll_time_;
+
+ // Time between the end of the last ignored scroll sequence and the beginning
+ // of the current one.
+ base::TimeDelta time_since_last_ignored_scroll_;
+
+ // On Windows, we don't generate the inertial events (fling) but receive them
+ // from Win API. In some cases, we get a long tail of inertial events for a
+ // couple of seconds. The overscroll animation feels like stuck in these
+ // cases. So we only process 0.3 second inertial events then cancel the
+ // overscroll if it is not completed yet.
+ // Timestamp for the first inertial event (fling) in current stream.
+ base::Optional<base::TimeTicks> first_inertial_event_time_;
+
DISALLOW_COPY_AND_ASSIGN(OverscrollController);
};
diff --git a/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc b/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
index f69b0e29faf..166d1fe359d 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller_unittest.cc
@@ -50,10 +50,12 @@ class OverscrollControllerTest : public ::testing::Test {
// Creates and sends a gesture event to the overscroll controller. Returns
// |true| if the event is consumed by the overscroll controller.
bool SimulateGestureEvent(blink::WebInputEvent::Type type,
- blink::WebGestureDevice source_device) {
+ blink::WebGestureDevice source_device,
+ base::TimeTicks timestamp) {
DCHECK(!current_event_);
current_event_ = std::make_unique<blink::WebGestureEvent>(
SyntheticWebGestureEventBuilder::Build(type, source_device));
+ current_event_->SetTimeStamp(timestamp);
return controller_->WillHandleEvent(*current_event_);
}
@@ -63,10 +65,12 @@ class OverscrollControllerTest : public ::testing::Test {
bool SimulateGestureScrollUpdate(float dx,
float dy,
blink::WebGestureDevice device,
+ base::TimeTicks timestamp,
bool inertial_update) {
DCHECK(!current_event_);
auto event = std::make_unique<blink::WebGestureEvent>(
SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, device));
+ event->SetTimeStamp(timestamp);
if (inertial_update) {
event->data.scroll_update.inertial_phase =
blink::WebGestureEvent::kMomentumPhase;
@@ -79,11 +83,13 @@ class OverscrollControllerTest : public ::testing::Test {
// Returns |true| if the event is consumed by the overscroll controller.
bool SimulateGestureFlingStart(float velocity_x,
float velocity_y,
- blink::WebGestureDevice device) {
+ blink::WebGestureDevice device,
+ base::TimeTicks timestamp) {
DCHECK(!current_event_);
current_event_ = std::make_unique<blink::WebGestureEvent>(
SyntheticWebGestureEventBuilder::BuildFling(velocity_x, velocity_y,
device));
+ current_event_->SetTimeStamp(timestamp);
return controller_->WillHandleEvent(*current_event_);
}
@@ -121,13 +127,16 @@ class OverscrollControllerTest : public ::testing::Test {
// Tests that if a mouse-wheel is consumed by content before overscroll is
// initiated, overscroll will not initiate anymore.
TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
+ const base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
// Simulate a mouse-wheel, ACK it as not processed, simulate the corresponding
// gesture scroll-update event, and ACK it as not processed. Since it is not
// passing the start threshold, no overscroll should happen.
EXPECT_FALSE(SimulateMouseWheel(10, 0));
SimulateAck(false);
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 10, 0, blink::kWebGestureDeviceTouchpad, false));
+ 10, 0, blink::kWebGestureDeviceTouchpad, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
@@ -150,7 +159,7 @@ TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
EXPECT_FALSE(SimulateMouseWheel(100, 0));
SimulateAck(false);
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 100, 0, blink::kWebGestureDeviceTouchpad, false));
+ 100, 0, blink::kWebGestureDeviceTouchpad, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
@@ -162,12 +171,16 @@ TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
// ignore the following inertial scroll events until new sequence start.
TEST_F(OverscrollControllerTest,
InertialGestureScrollUpdateCompletesOverscroll) {
+ const base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchpad));
+ blink::kWebGestureDeviceTouchpad,
+ timestamp));
SimulateAck(false);
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 200, 0, blink::kWebGestureDeviceTouchpad, false));
+ 200, 0, blink::kWebGestureDeviceTouchpad, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
@@ -176,7 +189,7 @@ TEST_F(OverscrollControllerTest,
// Inertial update event complete the overscroll action.
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 100, 0, blink::kWebGestureDeviceTouchpad, true));
+ 100, 0, blink::kWebGestureDeviceTouchpad, timestamp, true));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
@@ -185,7 +198,76 @@ TEST_F(OverscrollControllerTest,
// Next Inertial update event would be consumed by overscroll controller.
EXPECT_TRUE(SimulateGestureScrollUpdate(
- 100, 0, blink::kWebGestureDeviceTouchpad, true));
+ 100, 0, blink::kWebGestureDeviceTouchpad, timestamp, true));
+}
+
+// Ensure inertial gesture scroll update can not start overscroll.
+TEST_F(OverscrollControllerTest, InertialGSUsDoNotStartOverscroll) {
+ base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+ // Inertial update event complete the overscroll action.
+ EXPECT_FALSE(SimulateGestureScrollUpdate(
+ 100, 0, blink::kWebGestureDeviceTouchpad, timestamp, true));
+ SimulateAck(false);
+ EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+ EXPECT_EQ(OverscrollSource::NONE, controller_source());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+}
+
+// After 300ms inertial gesture scroll updates, overscroll must get cancelled
+// if not completed.
+TEST_F(OverscrollControllerTest, OnlyProcessLimitedInertialGSUEvents) {
+ base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchpad,
+ timestamp));
+ SimulateAck(false);
+
+ EXPECT_FALSE(SimulateGestureScrollUpdate(
+ 61, 0, blink::kWebGestureDeviceTouchpad, timestamp, false));
+ SimulateAck(false);
+ EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
+ EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
+ EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ // First inertial.
+ timestamp += base::TimeDelta::FromSeconds(1);
+ EXPECT_TRUE(SimulateGestureScrollUpdate(
+ 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true));
+ SimulateAck(true);
+ EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
+ EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
+ EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ // Not cancel in 10ms.
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+ EXPECT_TRUE(SimulateGestureScrollUpdate(
+ 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true));
+ SimulateAck(true);
+ EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
+ EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
+ EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ // Cancel after 300ms.
+ timestamp += base::TimeDelta::FromMilliseconds(291);
+ EXPECT_TRUE(SimulateGestureScrollUpdate(
+ 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true));
+ SimulateAck(true);
+ EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+ EXPECT_EQ(OverscrollSource::NONE, controller_source());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ // Next event should be ignored.
+ timestamp += base::TimeDelta::FromMilliseconds(100);
+ EXPECT_TRUE(SimulateGestureScrollUpdate(
+ 1, 0, blink::kWebGestureDeviceTouchpad, timestamp, true));
}
// Verifies that when pull-to-refresh is disabled, it is not triggered for
@@ -194,42 +276,62 @@ TEST_F(OverscrollControllerTest, PullToRefreshDisabled) {
ScopedPullToRefreshMode scoped_mode(
OverscrollConfig::PullToRefreshMode::kDisabled);
+ base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchpad,
+ timestamp));
+ SimulateAck(false);
+
// Simulate a touchpad gesture scroll-update event that passes the start
// threshold and ACK it as not processed. Pull-to-refresh should not be
// triggered.
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 0, 80, blink::kWebGestureDeviceTouchpad, false));
+ 0, 80, blink::kWebGestureDeviceTouchpad, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
// Simulate a touchpad zero-velocity fling-start which would normally end
// pull-to-refresh, and ACK it as not processed. Nothing should happen.
- EXPECT_FALSE(
- SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad));
+ EXPECT_FALSE(SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad,
+ timestamp));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
+ SimulateAck(false);
+
// Simulate a touchscreen gesture scroll-update event that passes the start
// threshold and ACK it as not processed. Pull-to-refresh should not be
// triggered.
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 0, 80, blink::kWebGestureDeviceTouchscreen, false));
+ 0, 80, blink::kWebGestureDeviceTouchscreen, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
// Simulate a touchscreen gesture scroll-end which would normally end
// pull-to-refresh, and ACK it as not processed. Nothing should happen.
EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen));
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
@@ -243,40 +345,60 @@ TEST_F(OverscrollControllerTest, PullToRefreshEnabled) {
ScopedPullToRefreshMode scoped_mode(
OverscrollConfig::PullToRefreshMode::kEnabled);
+ base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchpad,
+ timestamp));
+ SimulateAck(false);
+
// Simulate a touchpad gesture scroll-update event that passes the start
// threshold and ACK it as not processed. Pull-to-refresh should be triggered.
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 0, 80, blink::kWebGestureDeviceTouchpad, false));
+ 0, 80, blink::kWebGestureDeviceTouchpad, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_SOUTH, controller_mode());
EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
EXPECT_EQ(OVERSCROLL_SOUTH, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
// Simulate a touchpad zero-velocity fling-start and ACK it as not processed..
// It should abort pull-to-refresh.
- EXPECT_FALSE(
- SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad));
+ EXPECT_FALSE(SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad,
+ timestamp));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
+ SimulateAck(false);
+
// Simulate a touchscreen gesture scroll-update event that passes the start
// threshold and ACK it as not processed. Pull-to-refresh should be triggered.
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 0, 80, blink::kWebGestureDeviceTouchscreen, false));
+ 0, 80, blink::kWebGestureDeviceTouchscreen, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_SOUTH, controller_mode());
EXPECT_EQ(OverscrollSource::TOUCHSCREEN, controller_source());
EXPECT_EQ(OVERSCROLL_SOUTH, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
// Simulate a touchscreen gesture scroll-end and ACK it as not processed. It
// should abort pull-to-refresh.
EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen));
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
@@ -290,41 +412,61 @@ TEST_F(OverscrollControllerTest, PullToRefreshEnabledTouchscreen) {
ScopedPullToRefreshMode scoped_mode(
OverscrollConfig::PullToRefreshMode::kEnabledTouchschreen);
+ base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchpad,
+ timestamp));
+ SimulateAck(false);
+
// Simulate a touchpad gesture scroll-update event that passes the start
// threshold and ACK it as not processed. Pull-to-refresh should not be
// triggered.
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 0, 80, blink::kWebGestureDeviceTouchpad, false));
+ 0, 80, blink::kWebGestureDeviceTouchpad, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
// Simulate a touchpad zero-velocity fling-start which would normally end
// pull-to-refresh, and ACK it as not processed. Nothing should happen.
- EXPECT_FALSE(
- SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad));
+ EXPECT_FALSE(SimulateGestureFlingStart(0, 0, blink::kWebGestureDeviceTouchpad,
+ timestamp));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
+ SimulateAck(false);
+
// Simulate a touchscreen gesture scroll-update event that passes the start
// threshold and ACK it as not processed. Pull-to-refresh should be triggered.
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 0, 80, blink::kWebGestureDeviceTouchscreen, false));
+ 0, 80, blink::kWebGestureDeviceTouchscreen, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_SOUTH, controller_mode());
EXPECT_EQ(OverscrollSource::TOUCHSCREEN, controller_source());
EXPECT_EQ(OVERSCROLL_SOUTH, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+ timestamp += base::TimeDelta::FromSeconds(1);
+
// Simulate a touchscreen gesture scroll-end and ACK it as not processed. It
// should abort pull-to-refresh.
EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
- blink::kWebGestureDeviceTouchscreen));
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
@@ -339,8 +481,12 @@ TEST_F(OverscrollControllerTest, DisableTouchpadOverscrollHistoryNavigation) {
feature_list.InitAndDisableFeature(
features::kTouchpadOverscrollHistoryNavigation);
ASSERT_FALSE(OverscrollConfig::TouchpadOverscrollHistoryNavigationEnabled());
+
+ const base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
EXPECT_FALSE(SimulateGestureScrollUpdate(
- 200, 0, blink::kWebGestureDeviceTouchpad, false));
+ 200, 0, blink::kWebGestureDeviceTouchpad, timestamp, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
@@ -349,4 +495,76 @@ TEST_F(OverscrollControllerTest, DisableTouchpadOverscrollHistoryNavigation) {
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
}
+// Verifies that if an overscroll happens before cool off period after a page
+// scroll, it does not trigger pull-to-refresh.
+TEST_F(OverscrollControllerTest, PullToRefreshCoolOff) {
+ ScopedPullToRefreshMode scoped_mode(
+ OverscrollConfig::PullToRefreshMode::kEnabled);
+
+ base::TimeTicks timestamp =
+ blink::WebInputEvent::GetStaticTimeStampForTests();
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
+ SimulateAck(false);
+
+ // Simulate a touchscreen gesture scroll-update event that passes the start
+ // threshold and ACK it as not processed. Pull-to-refresh should not be
+ // triggered.
+ EXPECT_FALSE(SimulateGestureScrollUpdate(
+ 0, 80, blink::kWebGestureDeviceTouchscreen, timestamp, false));
+ SimulateAck(true);
+ EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+ EXPECT_EQ(OverscrollSource::NONE, controller_source());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ timestamp += base::TimeDelta::FromSeconds(1);
+
+ // Simulate a touchscreen gesture scroll-end which would normally end
+ // pull-to-refresh, and ACK it as not processed. Nothing should happen.
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
+ SimulateAck(false);
+ EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+ EXPECT_EQ(OverscrollSource::NONE, controller_source());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ // Next scroll should happen before cool off period is finished, so that it
+ // does not trigger pull-to-refresh.
+ timestamp += base::TimeDelta::FromSecondsD(0.5);
+
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
+ SimulateAck(false);
+
+ // Simulate a touchscreen gesture scroll-update event that passes the start
+ // threshold and ACK it as not processed. Pull-to-refresh should not be
+ // triggered.
+ EXPECT_FALSE(SimulateGestureScrollUpdate(
+ 0, 80, blink::kWebGestureDeviceTouchscreen, timestamp, false));
+ SimulateAck(false);
+ EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+ EXPECT_EQ(OverscrollSource::NONE, controller_source());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+ timestamp += base::TimeDelta::FromSeconds(1);
+
+ // Simulate a touchscreen gesture scroll-end which would normally end
+ // pull-to-refresh, and ACK it as not processed. Nothing should happen.
+ EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollEnd,
+ blink::kWebGestureDeviceTouchscreen,
+ timestamp));
+ SimulateAck(false);
+ EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+ EXPECT_EQ(OverscrollSource::NONE, controller_source());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
index 992a67ecd34..f330cdd3f55 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.h
@@ -122,7 +122,6 @@ class CONTENT_EXPORT P2PSocketHost {
enum State {
STATE_UNINITIALIZED,
STATE_CONNECTING,
- STATE_TLS_CONNECTING,
STATE_OPEN,
STATE_ERROR,
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
index 12ead42db0e..5a5ba5d953b 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -127,11 +127,15 @@ bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
const net::SSLConfig ssl_config;
socket_ = proxy_resolving_socket_factory_->CreateSocket(
ssl_config, GURL("https://" + dest_host_port_pair.ToString()),
- false /*use_tls*/);
+ IsTlsClientSocket(type_));
- int status = socket_->Connect(
- base::Bind(&P2PSocketHostTcpBase::OnConnected,
- base::Unretained(this)));
+ if (IsPseudoTlsClientSocket(type_)) {
+ socket_ =
+ std::make_unique<jingle_glue::FakeSSLClientSocket>(std::move(socket_));
+ }
+
+ int status = socket_->Connect(base::BindOnce(
+ &P2PSocketHostTcpBase::OnConnected, base::Unretained(this)));
if (status != net::ERR_IO_PENDING) {
// We defer execution of ProcessConnectDone instead of calling it
// directly here as the caller may not expect an error/close to
@@ -149,7 +153,7 @@ void P2PSocketHostTcpBase::OnError() {
socket_.reset();
if (state_ == STATE_UNINITIALIZED || state_ == STATE_CONNECTING ||
- state_ == STATE_TLS_CONNECTING || state_ == STATE_OPEN) {
+ state_ == STATE_OPEN) {
message_sender_->Send(new P2PMsg_OnError(id_));
}
@@ -166,84 +170,6 @@ void P2PSocketHostTcpBase::OnConnected(int result) {
return;
}
- if (IsTlsClientSocket(type_)) {
- state_ = STATE_TLS_CONNECTING;
- StartTls();
- } else if (IsPseudoTlsClientSocket(type_)) {
- std::unique_ptr<net::StreamSocket> transport_socket = std::move(socket_);
- socket_.reset(
- new jingle_glue::FakeSSLClientSocket(std::move(transport_socket)));
- state_ = STATE_TLS_CONNECTING;
- int status = socket_->Connect(
- base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
- base::Unretained(this)));
- if (status != net::ERR_IO_PENDING) {
- ProcessTlsSslConnectDone(status);
- }
- } else {
- // If we are not doing TLS, we are ready to send data now.
- // In case of TLS, SignalConnect will be sent only after TLS handshake is
- // successful. So no buffering will be done at socket handlers if any
- // packets sent before that by the application.
- OnOpen();
- }
-}
-
-void P2PSocketHostTcpBase::StartTls() {
- DCHECK_EQ(state_, STATE_TLS_CONNECTING);
- DCHECK(socket_.get());
-
- std::unique_ptr<net::ClientSocketHandle> socket_handle(
- new net::ClientSocketHandle());
- socket_handle->SetSocket(std::move(socket_));
-
- const net::URLRequestContext* url_request_context =
- url_context_->GetURLRequestContext();
- net::SSLClientSocketContext context(
- url_request_context->cert_verifier(),
- nullptr, /* TODO(rkn): ChannelIDService is not thread safe. */
- url_request_context->transport_security_state(),
- url_request_context->cert_transparency_verifier(),
- url_request_context->ct_policy_enforcer(),
- std::string() /* TODO(rsleevi): Ensure a proper unique shard. */);
-
- // Default ssl config.
- const net::SSLConfig ssl_config;
- net::HostPortPair dest_host_port_pair;
-
- // Calling net::HostPortPair::FromIPEndPoint will crash if the IP address is
- // empty.
- if (!remote_address_.ip_address.address().empty()) {
- net::HostPortPair::FromIPEndPoint(remote_address_.ip_address);
- } else {
- dest_host_port_pair.set_port(remote_address_.ip_address.port());
- }
- if (!remote_address_.hostname.empty())
- dest_host_port_pair.set_host(remote_address_.hostname);
-
- net::ClientSocketFactory* socket_factory =
- net::ClientSocketFactory::GetDefaultFactory();
- DCHECK(socket_factory);
-
- socket_ = socket_factory->CreateSSLClientSocket(
- std::move(socket_handle), dest_host_port_pair, ssl_config, context);
- int status = socket_->Connect(
- base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
- base::Unretained(this)));
-
- if (status != net::ERR_IO_PENDING) {
- ProcessTlsSslConnectDone(status);
- }
-}
-
-void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) {
- DCHECK_NE(status, net::ERR_IO_PENDING);
- DCHECK_EQ(state_, STATE_TLS_CONNECTING);
- if (status != net::OK) {
- LOG(WARNING) << "Error from connecting TLS socket, status=" << status;
- OnError();
- return;
- }
OnOpen();
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
index 79d2ac0735e..6031e5d70a6 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
@@ -91,10 +91,6 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
friend class P2PSocketHostTcpTestBase;
friend class P2PSocketHostTcpServerTest;
- // SSL/TLS connection functions.
- void StartTls();
- void ProcessTlsSslConnectDone(int status);
-
void DidCompleteRead(int result);
void DoRead();
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
index 1e30a679d17..9b249463ff4 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
@@ -13,7 +13,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "content/browser/renderer_host/p2p/socket_host.h"
#include "content/common/content_export.h"
#include "content/common/p2p_socket_type.h"
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
index 6853bbffef4..37dd69132e0 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
@@ -11,9 +11,14 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/sys_byteorder.h"
+#include "base/test/scoped_task_environment.h"
#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
+#include "jingle/glue/fake_ssl_client_socket.h"
+#include "net/socket/socket_test_util.h"
#include "net/socket/stream_socket.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/url_request_test_util.h"
+#include "services/network/proxy_resolving_client_socket_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -466,4 +471,113 @@ TEST_F(P2PSocketHostStunTcpTest, AsyncWrites) {
EXPECT_EQ(expected_data, sent_data_);
}
+// When pseudo-tls is used (e.g. for P2P_SOCKET_SSLTCP_CLIENT),
+// network::ProxyResolvingClientSocket::Connect() won't be called twice.
+// Regression test for crbug.com/840797.
+TEST(P2PSocketHostTcpWithPseudoTlsTest, Basic) {
+ base::test::ScopedTaskEnvironment scoped_task_environment(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ MockIPCSender sender;
+ EXPECT_CALL(
+ sender,
+ Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
+ .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
+
+ net::TestURLRequestContext context(true);
+ net::MockClientSocketFactory mock_socket_factory;
+ context.set_client_socket_factory(&mock_socket_factory);
+ context.Init();
+ network::ProxyResolvingClientSocketFactory factory(&mock_socket_factory,
+ &context);
+
+ base::StringPiece ssl_client_hello =
+ jingle_glue::FakeSSLClientSocket::GetSslClientHello();
+ base::StringPiece ssl_server_hello =
+ jingle_glue::FakeSSLClientSocket::GetSslServerHello();
+ net::MockRead reads[] = {
+ net::MockRead(net::ASYNC, ssl_server_hello.data(),
+ ssl_server_hello.size()),
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ net::MockWrite writes[] = {net::MockWrite(
+ net::SYNCHRONOUS, ssl_client_hello.data(), ssl_client_hello.size())};
+ net::StaticSocketDataProvider data_provider(reads, writes);
+ net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234);
+ data_provider.set_connect_data(
+ net::MockConnect(net::SYNCHRONOUS, net::OK, server_addr));
+ mock_socket_factory.AddSocketDataProvider(&data_provider);
+
+ P2PSocketHostTcp host(&sender, 0 /*socket_id*/, P2P_SOCKET_SSLTCP_CLIENT,
+ nullptr, &factory);
+ P2PHostAndIPEndPoint dest;
+ dest.ip_address = server_addr;
+ bool success = host.Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0),
+ 0, 0, dest);
+ EXPECT_TRUE(success);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+class P2PSocketHostTcpWithTlsTest
+ : public testing::TestWithParam<std::tuple<net::IoMode, P2PSocketType>> {};
+
+INSTANTIATE_TEST_CASE_P(
+ /* no prefix */,
+ P2PSocketHostTcpWithTlsTest,
+ ::testing::Combine(::testing::Values(net::SYNCHRONOUS, net::ASYNC),
+ ::testing::Values(P2P_SOCKET_TLS_CLIENT,
+ P2P_SOCKET_STUN_TLS_CLIENT)));
+
+// Tests that if a socket type satisfies IsTlsClientSocket(), TLS connection is
+// established.
+TEST_P(P2PSocketHostTcpWithTlsTest, Basic) {
+ base::test::ScopedTaskEnvironment scoped_task_environment(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ MockIPCSender sender;
+ EXPECT_CALL(
+ sender,
+ Send(MatchMessage(static_cast<uint32_t>(P2PMsg_OnSocketCreated::ID))))
+ .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
+
+ net::TestURLRequestContext context(true);
+ net::MockClientSocketFactory mock_socket_factory;
+ context.set_client_socket_factory(&mock_socket_factory);
+ context.Init();
+ network::ProxyResolvingClientSocketFactory factory(&mock_socket_factory,
+ &context);
+ const net::IoMode io_mode = std::get<0>(GetParam());
+ const P2PSocketType socket_type = std::get<1>(GetParam());
+ // OnOpen() calls DoRead(), so populate the mock socket with a pending read.
+ net::MockRead reads[] = {
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ net::StaticSocketDataProvider data_provider(
+ reads, base::span<const net::MockWrite>());
+ net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234);
+ data_provider.set_connect_data(
+ net::MockConnect(io_mode, net::OK, server_addr));
+ net::SSLSocketDataProvider ssl_socket_provider(io_mode, net::OK);
+ mock_socket_factory.AddSocketDataProvider(&data_provider);
+ mock_socket_factory.AddSSLSocketDataProvider(&ssl_socket_provider);
+
+ std::unique_ptr<P2PSocketHostTcpBase> host;
+ if (socket_type == P2P_SOCKET_STUN_TLS_CLIENT) {
+ host = std::make_unique<P2PSocketHostStunTcp>(
+ &sender, 0 /*socket_id*/, socket_type, nullptr, &factory);
+ } else {
+ host = std::make_unique<P2PSocketHostTcp>(&sender, 0 /*socket_id*/,
+ socket_type, nullptr, &factory);
+ }
+ P2PHostAndIPEndPoint dest;
+ dest.ip_address = server_addr;
+ bool success = host->Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0),
+ 0, 0, dest);
+ EXPECT_TRUE(success);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+ EXPECT_TRUE(ssl_socket_provider.ConnectDataConsumed());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
index 389ed2bfeec..6c18bea987b 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
@@ -44,9 +44,7 @@ void FakeSocket::AppendInputData(const char* data, int data_size) {
memcpy(read_buffer_->data(), &input_data_[0] + input_pos_, result);
input_pos_ += result;
read_buffer_ = nullptr;
- net::CompletionCallback cb = read_callback_;
- read_callback_.Reset();
- std::move(cb).Run(result);
+ std::move(read_callback_).Run(result);
}
}
@@ -58,8 +56,9 @@ void FakeSocket::SetLocalAddress(const net::IPEndPoint& local_address) {
local_address_ = local_address;
}
-int FakeSocket::Read(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback) {
+int FakeSocket::Read(net::IOBuffer* buf,
+ int buf_len,
+ net::CompletionOnceCallback callback) {
DCHECK(buf);
if (input_pos_ < static_cast<int>(input_data_.size())){
int result = std::min(buf_len,
@@ -71,7 +70,7 @@ int FakeSocket::Read(net::IOBuffer* buf, int buf_len,
read_pending_ = true;
read_buffer_ = buf;
read_buffer_size_ = buf_len;
- read_callback_ = callback;
+ read_callback_ = std::move(callback);
return net::ERR_IO_PENDING;
}
}
@@ -79,7 +78,7 @@ int FakeSocket::Read(net::IOBuffer* buf, int buf_len,
int FakeSocket::Write(
net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback,
+ net::CompletionOnceCallback callback,
const net::NetworkTrafficAnnotationTag& /*traffic_annotation*/) {
DCHECK(buf);
DCHECK(!write_pending_);
@@ -88,7 +87,8 @@ int FakeSocket::Write(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&FakeSocket::DoAsyncWrite, base::Unretained(this),
- scoped_refptr<net::IOBuffer>(buf), buf_len, callback));
+ scoped_refptr<net::IOBuffer>(buf), buf_len,
+ std::move(callback)));
write_pending_ = true;
return net::ERR_IO_PENDING;
}
@@ -100,15 +100,16 @@ int FakeSocket::Write(
return buf_len;
}
-void FakeSocket::DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len,
- const net::CompletionCallback& callback) {
+void FakeSocket::DoAsyncWrite(scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ net::CompletionOnceCallback callback) {
write_pending_ = false;
if (written_data_) {
written_data_->insert(written_data_->end(),
buf->data(), buf->data() + buf_len);
}
- callback.Run(buf_len);
+ std::move(callback).Run(buf_len);
}
int FakeSocket::SetReceiveBufferSize(int32_t size) {
@@ -121,7 +122,7 @@ int FakeSocket::SetSendBufferSize(int32_t size) {
return net::ERR_NOT_IMPLEMENTED;
}
-int FakeSocket::Connect(const net::CompletionCallback& callback) {
+int FakeSocket::Connect(net::CompletionOnceCallback callback) {
return 0;
}
@@ -152,14 +153,6 @@ const net::NetLogWithSource& FakeSocket::NetLog() const {
return net_log_;
}
-void FakeSocket::SetSubresourceSpeculation() {
- NOTREACHED();
-}
-
-void FakeSocket::SetOmniboxSpeculation() {
- NOTREACHED();
-}
-
bool FakeSocket::WasEverUsed() const {
return true;
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
index a1d2398be2a..296aab86dc0 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
@@ -29,7 +29,7 @@ const uint16_t kTestPort2 = 543;
class MockIPCSender : public IPC::Sender {
public:
MockIPCSender();
- virtual ~MockIPCSender();
+ ~MockIPCSender() override;
MOCK_METHOD1(Send, bool(IPC::Message* msg));
};
@@ -49,23 +49,21 @@ class FakeSocket : public net::StreamSocket {
// net::Socket implementation.
int Read(net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback) override;
+ net::CompletionOnceCallback callback) override;
int Write(
net::IOBuffer* buf,
int buf_len,
- const net::CompletionCallback& callback,
+ net::CompletionOnceCallback callback,
const net::NetworkTrafficAnnotationTag& traffic_annotation) override;
int SetReceiveBufferSize(int32_t size) override;
int SetSendBufferSize(int32_t size) override;
- int Connect(const net::CompletionCallback& callback) override;
+ int Connect(net::CompletionOnceCallback callback) override;
void Disconnect() override;
bool IsConnected() const override;
bool IsConnectedAndIdle() const override;
int GetPeerAddress(net::IPEndPoint* address) const override;
int GetLocalAddress(net::IPEndPoint* address) const override;
const net::NetLogWithSource& NetLog() const override;
- void SetSubresourceSpeculation() override;
- void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
bool WasAlpnNegotiated() const override;
net::NextProto GetNegotiatedProtocol() const override;
@@ -78,13 +76,14 @@ class FakeSocket : public net::StreamSocket {
void ApplySocketTag(const net::SocketTag& tag) override {}
private:
- void DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len,
- const net::CompletionCallback& callback);
+ void DoAsyncWrite(scoped_refptr<net::IOBuffer> buf,
+ int buf_len,
+ net::CompletionOnceCallback callback);
bool read_pending_;
scoped_refptr<net::IOBuffer> read_buffer_;
int read_buffer_size_;
- net::CompletionCallback read_callback_;
+ net::CompletionOnceCallback read_callback_;
std::string input_data_;
int input_pos_;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
index 9ff284aef8d..d4398740213 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -17,7 +17,6 @@
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "content/browser/renderer_host/p2p/socket_host.h"
#include "content/common/content_export.h"
#include "content/common/p2p_socket_type.h"
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
index cdc4ab29cde..628f9c9bab7 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
@@ -7,7 +7,7 @@
#include <string.h>
#include "base/files/file_path.h"
-#include "base/files/file_util_proxy.h"
+#include "base/files/file_util.h"
#include "base/task_scheduler/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -20,6 +20,43 @@
namespace content {
+namespace {
+
+struct GetFileInfoResults {
+ base::File::Error error;
+ base::File::Info info;
+};
+
+using GetFileInfoCallback =
+ base::OnceCallback<void(base::File::Error, const base::File::Info&)>;
+
+GetFileInfoResults DoGetFileInfo(const base::FilePath& path) {
+ GetFileInfoResults results;
+ if (!base::PathExists(path)) {
+ results.error = base::File::FILE_ERROR_NOT_FOUND;
+ return results;
+ }
+ results.error = base::GetFileInfo(path, &results.info)
+ ? base::File::FILE_OK
+ : base::File::FILE_ERROR_FAILED;
+ return results;
+}
+
+void SendGetFileInfoResults(GetFileInfoCallback callback,
+ const GetFileInfoResults& results) {
+ std::move(callback).Run(results.error, results.info);
+}
+
+base::File::Error CallTouchFile(const base::FilePath& path,
+ PP_Time last_access_time,
+ PP_Time last_modified_time) {
+ bool result = base::TouchFile(path, ppapi::PPTimeToTime(last_access_time),
+ ppapi::PPTimeToTime(last_modified_time));
+ return result ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED;
+}
+
+} // namespace
+
PepperExternalFileRefBackend::PepperExternalFileRefBackend(
ppapi::host::PpapiHost* host,
int render_process_id,
@@ -46,9 +83,9 @@ int32_t PepperExternalFileRefBackend::Touch(
PP_Time last_access_time,
PP_Time last_modified_time) {
IPC::Message reply_msg = PpapiPluginMsg_FileRef_TouchReply();
- base::FileUtilProxy::Touch(
- task_runner_.get(), path_, ppapi::PPTimeToTime(last_access_time),
- ppapi::PPTimeToTime(last_modified_time),
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(), FROM_HERE,
+ BindOnce(&CallTouchFile, path_, last_access_time, last_modified_time),
base::BindOnce(&PepperExternalFileRefBackend::DidFinish,
weak_factory_.GetWeakPtr(), reply_context, reply_msg));
return PP_OK_COMPLETIONPENDING;
@@ -69,10 +106,12 @@ int32_t PepperExternalFileRefBackend::Rename(
int32_t PepperExternalFileRefBackend::Query(
ppapi::host::ReplyMessageContext reply_context) {
- bool ok = base::FileUtilProxy::GetFileInfo(
- task_runner_.get(), path_,
- base::BindOnce(&PepperExternalFileRefBackend::GetMetadataComplete,
- weak_factory_.GetWeakPtr(), reply_context));
+ bool ok = base::PostTaskAndReplyWithResult(
+ task_runner_.get(), FROM_HERE, base::BindOnce(&DoGetFileInfo, path_),
+ base::BindOnce(
+ &SendGetFileInfoResults,
+ base::BindOnce(&PepperExternalFileRefBackend::GetMetadataComplete,
+ weak_factory_.GetWeakPtr(), reply_context)));
DCHECK(ok);
return PP_OK_COMPLETIONPENDING;
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
index 259f1102674..dd9483958d0 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
@@ -8,8 +8,8 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/files/file_util_proxy.h"
#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
@@ -49,7 +49,7 @@ PepperFileIOHost::UIThreadStuff GetUIThreadStuffForInternalFileSystems(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
if (host) {
- stuff.resolved_render_process_id = base::GetProcId(host->GetHandle());
+ stuff.resolved_render_process_id = host->GetProcess().Pid();
StoragePartition* storage_partition = host->GetStoragePartition();
if (storage_partition)
stuff.file_system_context = storage_partition->GetFileSystemContext();
@@ -62,7 +62,7 @@ base::ProcessId GetResolvedRenderProcessId(int render_process_id) {
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
if (!host)
return base::kNullProcessId;
- return base::GetProcId(host->GetHandle());
+ return host->GetProcess().Pid();
}
bool GetPluginAllowedToCallRequestOSFileHandle(int render_process_id,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
index dd79a645761..94059da48e9 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.cc
@@ -7,12 +7,12 @@
#include "base/bind.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "device/gamepad/gamepad_service.h"
+#include "device/gamepad/gamepad_shared_buffer.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/shared_impl/ppb_gamepad_shared.h"
namespace content {
@@ -72,7 +72,7 @@ void PepperGamepadHost::GotUserGesture(
gamepad_service_->DuplicateSharedMemoryHandle();
context.params.AppendHandle(ppapi::proxy::SerializedHandle(
- handle, sizeof(ppapi::ContentGamepadHardwareBuffer)));
+ handle, sizeof(device::GamepadHardwareBuffer)));
host()->SendReply(context, PpapiPluginMsg_Gamepad_SendMemory());
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
index fa5ef9ee30f..abe26a38266 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
@@ -16,12 +16,12 @@
#include "content/browser/renderer_host/pepper/browser_ppapi_host_test.h"
#include "device/gamepad/gamepad_shared_buffer.h"
#include "device/gamepad/gamepad_test_helpers.h"
+#include "device/gamepad/public/cpp/gamepads.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/proxy/gamepad_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_message_params.h"
-#include "ppapi/shared_impl/ppb_gamepad_shared.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -48,84 +48,8 @@ class PepperGamepadHostTest : public testing::Test,
DISALLOW_COPY_AND_ASSIGN(PepperGamepadHostTest);
};
-inline ptrdiff_t AddressDiff(const void* a, const void* b) {
- return static_cast<const char*>(a) - static_cast<const char*>(b);
-}
-
} // namespace
-// Validate the memory layout of the Pepper proxy struct matches the content
-// one. The proxy can't depend on content so has a duplicate definition. This
-// code can see both definitions so we do the validation here.
-TEST_F(PepperGamepadHostTest, ValidateHardwareBuffersMatch) {
- // Hardware buffer.
- static_assert(sizeof(ppapi::ContentGamepadHardwareBuffer) ==
- sizeof(device::GamepadHardwareBuffer),
- "gamepad hardware buffers must match");
- ppapi::ContentGamepadHardwareBuffer ppapi_buf;
- device::GamepadHardwareBuffer content_buf;
- EXPECT_EQ(AddressDiff(&content_buf.seqlock, &content_buf),
- AddressDiff(&ppapi_buf.sequence, &ppapi_buf));
- EXPECT_EQ(AddressDiff(&content_buf.data, &content_buf),
- AddressDiff(&ppapi_buf.buffer, &ppapi_buf));
-}
-
-TEST_F(PepperGamepadHostTest, ValidateGamepadsMatch) {
- // Gamepads.
- static_assert(sizeof(ppapi::WebKitGamepads) == sizeof(device::Gamepads),
- "gamepads data must match");
- ppapi::WebKitGamepads ppapi_gamepads;
- device::Gamepads web_gamepads;
-
- // See comment below on storage & the EXPECT macro.
- size_t webkit_items_length_cap = device::Gamepads::kItemsLengthCap;
- size_t ppapi_items_length_cap = ppapi::WebKitGamepads::kItemsLengthCap;
- EXPECT_EQ(webkit_items_length_cap, ppapi_items_length_cap);
-
- for (size_t i = 0; i < webkit_items_length_cap; i++) {
- EXPECT_EQ(AddressDiff(&web_gamepads.items[0], &web_gamepads),
- AddressDiff(&ppapi_gamepads.items[0], &ppapi_gamepads));
- }
-}
-
-TEST_F(PepperGamepadHostTest, ValidateGamepadMatch) {
- // Gamepad.
- static_assert(sizeof(ppapi::WebKitGamepad) == sizeof(device::Gamepad),
- "gamepad data must match");
- ppapi::WebKitGamepad ppapi_gamepad;
- device::Gamepad web_gamepad;
-
- // Using EXPECT seems to force storage for the parameter, which the constants
- // in the WebKit/PPAPI headers don't have. So we have to use temporaries
- // before comparing them.
- size_t webkit_id_length_cap = device::Gamepad::kIdLengthCap;
- size_t ppapi_id_length_cap = ppapi::WebKitGamepad::kIdLengthCap;
- EXPECT_EQ(webkit_id_length_cap, ppapi_id_length_cap);
-
- size_t webkit_axes_length_cap = device::Gamepad::kAxesLengthCap;
- size_t ppapi_axes_length_cap = ppapi::WebKitGamepad::kAxesLengthCap;
- EXPECT_EQ(webkit_axes_length_cap, ppapi_axes_length_cap);
-
- size_t webkit_buttons_length_cap = device::Gamepad::kButtonsLengthCap;
- size_t ppapi_buttons_length_cap = ppapi::WebKitGamepad::kButtonsLengthCap;
- EXPECT_EQ(webkit_buttons_length_cap, ppapi_buttons_length_cap);
-
- EXPECT_EQ(AddressDiff(&web_gamepad.connected, &web_gamepad),
- AddressDiff(&ppapi_gamepad.connected, &ppapi_gamepad));
- EXPECT_EQ(AddressDiff(&web_gamepad.id, &web_gamepad),
- AddressDiff(&ppapi_gamepad.id, &ppapi_gamepad));
- EXPECT_EQ(AddressDiff(&web_gamepad.timestamp, &web_gamepad),
- AddressDiff(&ppapi_gamepad.timestamp, &ppapi_gamepad));
- EXPECT_EQ(AddressDiff(&web_gamepad.axes_length, &web_gamepad),
- AddressDiff(&ppapi_gamepad.axes_length, &ppapi_gamepad));
- EXPECT_EQ(AddressDiff(&web_gamepad.axes, &web_gamepad),
- AddressDiff(&ppapi_gamepad.axes, &ppapi_gamepad));
- EXPECT_EQ(AddressDiff(&web_gamepad.buttons_length, &web_gamepad),
- AddressDiff(&ppapi_gamepad.buttons_length, &ppapi_gamepad));
- EXPECT_EQ(AddressDiff(&web_gamepad.buttons, &web_gamepad),
- AddressDiff(&ppapi_gamepad.buttons, &ppapi_gamepad));
-}
-
TEST_F(PepperGamepadHostTest, WaitForReply) {
device::Gamepads default_data;
memset(&default_data, 0, sizeof(device::Gamepads));
@@ -172,17 +96,16 @@ TEST_F(PepperGamepadHostTest, WaitForReply) {
// Validate the shared memory.
base::SharedMemory shared_memory(reply_handle, true);
- EXPECT_TRUE(shared_memory.Map(sizeof(ppapi::ContentGamepadHardwareBuffer)));
- const ppapi::ContentGamepadHardwareBuffer* buffer =
- static_cast<const ppapi::ContentGamepadHardwareBuffer*>(
- shared_memory.memory());
+ EXPECT_TRUE(shared_memory.Map(sizeof(device::GamepadHardwareBuffer)));
+ const device::GamepadHardwareBuffer* buffer =
+ static_cast<const device::GamepadHardwareBuffer*>(shared_memory.memory());
EXPECT_EQ(button_down_data.items[0].buttons_length,
- buffer->buffer.items[0].buttons_length);
- for (size_t i = 0; i < ppapi::WebKitGamepad::kButtonsLengthCap; i++) {
+ buffer->data.items[0].buttons_length);
+ for (size_t i = 0; i < device::Gamepad::kButtonsLengthCap; i++) {
EXPECT_EQ(button_down_data.items[0].buttons[i].value,
- buffer->buffer.items[0].buttons[i].value);
+ buffer->data.items[0].buttons[i].value);
EXPECT_EQ(button_down_data.items[0].buttons[i].pressed,
- buffer->buffer.items[0].buttons[i].pressed);
+ buffer->data.items[0].buttons[i].pressed);
}
// Duplicate requests should be denied.
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
index ea6cf498c36..e4d4f5df2c4 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/files/file_util.h"
-#include "base/files/file_util_proxy.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
index 464dcbd4767..c9a8d3fd8c6 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
@@ -91,11 +91,9 @@ int32_t PepperTrueTypeFontLinux::GetTableTags(std::vector<uint32_t>* tags) {
// Get the 2 byte numTables field at an offset of 4 in the font.
uint8_t num_tables_buf[2];
size_t output_length = sizeof(num_tables_buf);
- if (!GetFontTable(fd_.get(),
- 0 /* tag */,
- 4 /* offset */,
- reinterpret_cast<uint8_t*>(&num_tables_buf),
- &output_length))
+ if (!content::GetFontTable(fd_.get(), 0 /* tag */, 4 /* offset */,
+ reinterpret_cast<uint8_t*>(&num_tables_buf),
+ &output_length))
return PP_ERROR_FAILED;
DCHECK(output_length == sizeof(num_tables_buf));
// Font data is stored in big-endian order.
@@ -107,11 +105,9 @@ int32_t PepperTrueTypeFontLinux::GetTableTags(std::vector<uint32_t>* tags) {
output_length = num_tables * kTableEntrySize;
std::unique_ptr<uint8_t[]> table_entries(new uint8_t[output_length]);
// Get the table directory entries, which follow the font header.
- if (!GetFontTable(fd_.get(),
- 0 /* tag */,
- kFontHeaderSize /* offset */,
- table_entries.get(),
- &output_length))
+ if (!content::GetFontTable(fd_.get(), 0 /* tag */,
+ kFontHeaderSize /* offset */, table_entries.get(),
+ &output_length))
return PP_ERROR_FAILED;
DCHECK(output_length == num_tables * kTableEntrySize);
@@ -138,16 +134,15 @@ int32_t PepperTrueTypeFontLinux::GetTable(uint32_t table_tag,
size_t table_size = 0;
// Tags are byte swapped on Linux.
table_tag = base::ByteSwap(table_tag);
- if (!GetFontTable(fd_.get(), table_tag, offset, nullptr, &table_size))
+ if (!content::GetFontTable(fd_.get(), table_tag, offset, nullptr,
+ &table_size))
return PP_ERROR_FAILED;
// Only retrieve as much as the caller requested.
table_size = std::min(table_size, static_cast<size_t>(max_data_length));
data->resize(table_size);
- if (!GetFontTable(fd_.get(),
- table_tag,
- offset,
- reinterpret_cast<uint8_t*>(&(*data)[0]),
- &table_size))
+ if (!content::GetFontTable(fd_.get(), table_tag, offset,
+ reinterpret_cast<uint8_t*>(&(*data)[0]),
+ &table_size))
return PP_ERROR_FAILED;
return base::checked_cast<int32_t>(table_size);
diff --git a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
index 0596302ce3a..1d6fb4c9621 100644
--- a/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
+++ b/chromium/content/browser/renderer_host/pepper/ssl_context_helper.cc
@@ -35,7 +35,7 @@ net::CTVerifier* SSLContextHelper::GetCertTransparencyVerifier() {
net::CTPolicyEnforcer* SSLContextHelper::GetCTPolicyEnforcer() {
if (!ct_policy_enforcer_)
- ct_policy_enforcer_.reset(new net::CTPolicyEnforcer());
+ ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer());
return ct_policy_enforcer_.get();
}
diff --git a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
index d16a615e8ef..025702c926a 100644
--- a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
+++ b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.cc
@@ -10,8 +10,10 @@
namespace content {
RenderFrameMetadataProviderImpl::RenderFrameMetadataProviderImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
FrameTokenMessageQueue* frame_token_message_queue)
- : frame_token_message_queue_(frame_token_message_queue),
+ : task_runner_(task_runner),
+ frame_token_message_queue_(frame_token_message_queue),
render_frame_metadata_observer_client_binding_(this),
weak_factory_(this) {}
@@ -30,8 +32,8 @@ void RenderFrameMetadataProviderImpl::Bind(
mojom::RenderFrameMetadataObserverPtr observer) {
render_frame_metadata_observer_ptr_ = std::move(observer);
render_frame_metadata_observer_client_binding_.Close();
- render_frame_metadata_observer_client_binding_.Bind(
- std::move(client_request));
+ render_frame_metadata_observer_client_binding_.Bind(std::move(client_request),
+ task_runner_);
}
void RenderFrameMetadataProviderImpl::ReportAllFrameSubmissionsForTesting(
@@ -66,6 +68,12 @@ void RenderFrameMetadataProviderImpl::SetLastRenderFrameMetadataForTest(
void RenderFrameMetadataProviderImpl::OnRenderFrameMetadataChanged(
uint32_t frame_token,
const cc::RenderFrameMetadata& metadata) {
+ if (metadata.local_surface_id != last_local_surface_id_) {
+ last_local_surface_id_ = metadata.local_surface_id;
+ for (Observer& observer : observers_)
+ observer.OnLocalSurfaceIdChanged(metadata);
+ }
+
// Both RenderFrameMetadataProviderImpl and FrameTokenMessageQueue are owned
// by the same RenderWidgetHostImpl. During shutdown the queue is cleared
// without running the callbacks.
diff --git a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h
index 48ab561549b..ff93d903d41 100644
--- a/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h
+++ b/chromium/content/browser/renderer_host/render_frame_metadata_provider_impl.h
@@ -27,7 +27,8 @@ class CONTENT_EXPORT RenderFrameMetadataProviderImpl
: public RenderFrameMetadataProvider,
public mojom::RenderFrameMetadataObserverClient {
public:
- explicit RenderFrameMetadataProviderImpl(
+ RenderFrameMetadataProviderImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
FrameTokenMessageQueue* frame_token_message_queue);
~RenderFrameMetadataProviderImpl() override;
@@ -67,6 +68,10 @@ class CONTENT_EXPORT RenderFrameMetadataProviderImpl
cc::RenderFrameMetadata last_render_frame_metadata_;
+ base::Optional<viz::LocalSurfaceId> last_local_surface_id_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
// Not owned.
FrameTokenMessageQueue* const frame_token_message_queue_;
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index c12556a65ba..765a4664465 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -40,7 +40,6 @@
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/resource_context_impl.h"
-#include "content/common/cache_storage/cache_storage_types.h"
#include "content/common/content_constants_internal.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/common/view_messages.h"
@@ -88,23 +87,6 @@ namespace {
const uint32_t kRenderFilteredMessageClasses[] = {ViewMsgStart};
-#if defined(OS_MACOSX)
-void ResizeHelperHandleMsgOnUIThread(int render_process_id,
- const IPC::Message& message) {
- RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
- if (host)
- host->OnMessageReceived(message);
-}
-
-void ResizeHelperPostMsgToUIThread(int render_process_id,
- const IPC::Message& msg) {
- ui::WindowResizeHelperMac::Get()->task_runner()->PostDelayedTask(
- FROM_HERE,
- base::Bind(ResizeHelperHandleMsgOnUIThread, render_process_id, msg),
- base::TimeDelta());
-}
-#endif
-
void NoOpCacheStorageErrorCallback(CacheStorageCacheHandle cache_handle,
CacheStorageError error) {}
@@ -144,13 +126,6 @@ RenderMessageFilter::~RenderMessageFilter() {
bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message)
-#if defined(OS_MACOSX)
- // On Mac, ViewHostMsg_ResizeOrRepaint_ACK needs to be handled in a nested
- // message loop during resize.
- IPC_MESSAGE_HANDLER_GENERIC(
- ViewHostMsg_ResizeOrRepaint_ACK,
- ResizeHelperPostMsgToUIThread(render_process_id_, message))
-#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvents, OnMediaLogEvents)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -267,7 +242,8 @@ void RenderMessageFilter::DidGenerateCacheableMetadataInCacheStorage(
memcpy(buf->data(), &data.front(), data.size());
cache_storage_context_->cache_manager()->OpenCache(
- cache_storage_origin, cache_storage_cache_name,
+ cache_storage_origin, CacheStorageOwner::kCacheAPI,
+ cache_storage_cache_name,
base::BindOnce(&RenderMessageFilter::OnCacheStorageOpenCallback,
weak_ptr_factory_.GetWeakPtr(), url,
expected_response_time, buf, data.size()));
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index d6dad3d8e72..d22da30d122 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -19,7 +19,6 @@
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "components/viz/common/resources/shared_bitmap_manager.h"
-#include "content/common/cache_storage/cache_storage_types.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/public/browser/browser_associated_interface.h"
#include "content/public/browser/browser_message_filter.h"
diff --git a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
index 820687c3cb7..a2106f21629 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -17,6 +17,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
@@ -77,8 +78,7 @@ class RenderProcessHostTest : public ContentBrowserTest,
// RenderProcessHostObserver:
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override {
+ const ChildProcessTerminationInfo& info) override {
++process_exits_;
if (!process_exit_callback_.is_null())
process_exit_callback_.Run();
@@ -499,8 +499,7 @@ class RenderProcessHostObserverCounter : public RenderProcessHostObserver {
}
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override {
+ const ChildProcessTerminationInfo& info) override {
DCHECK(observing_);
DCHECK_EQ(host, observed_host_);
exited_count_++;
@@ -596,8 +595,7 @@ class ShellCloser : public RenderProcessHostObserver {
protected:
// RenderProcessHostObserver:
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override {
+ const ChildProcessTerminationInfo& info) override {
logging_string_->append("ShellCloser::RenderProcessExited ");
shell_->Close();
}
@@ -620,8 +618,7 @@ class ObserverLogger : public RenderProcessHostObserver {
protected:
// RenderProcessHostObserver:
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override {
+ const ChildProcessTerminationInfo& info) override {
logging_string_->append("ObserverLogger::RenderProcessExited ");
}
@@ -710,22 +707,22 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessOnBadMojoMessage) {
rph->RemoveObserver(this);
}
-class MediaStopObserver : public WebContentsObserver {
+class AudioStartObserver : public WebContentsObserver {
public:
- MediaStopObserver(WebContents* web_contents, base::Closure quit_closure)
+ AudioStartObserver(WebContents* web_contents,
+ base::OnceClosure audible_closure)
: WebContentsObserver(web_contents),
- quit_closure_(std::move(quit_closure)) {}
- ~MediaStopObserver() override {}
-
- void MediaStoppedPlaying(
- const WebContentsObserver::MediaPlayerInfo& media_info,
- const WebContentsObserver::MediaPlayerId& id,
- WebContentsObserver::MediaStoppedReason reason) override {
- quit_closure_.Run();
+ audible_closure_(std::move(audible_closure)) {}
+ ~AudioStartObserver() override {}
+
+ // WebContentsObserver:
+ void OnAudioStateChanged(bool audible) override {
+ if (audible && audible_closure_)
+ std::move(audible_closure_).Run();
}
private:
- base::Closure quit_closure_;
+ base::OnceClosure audible_closure_;
};
// Tests that audio stream counts (used for process priority calculations) are
@@ -743,18 +740,21 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
embedded_test_server()->ServeFilesFromSourceDirectory(
media::GetTestDataPath());
ASSERT_TRUE(embedded_test_server()->Start());
- NavigateToURL(shell(), embedded_test_server()->GetURL("/sfx_s16le.wav"));
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("/webaudio_oscillator.html"));
RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
shell()->web_contents()->GetMainFrame()->GetProcess());
{
- // Wait for media playback to complete. We use the stop signal instead of
- // the start signal here since the start signal does not mean the audio
- // has actually started playing yet. Whereas the stop signal is sent before
- // the audio device is actually torn down.
+ // Start audio and wait for it to become audible.
base::RunLoop run_loop;
- MediaStopObserver stop_observer(shell()->web_contents(),
- run_loop.QuitClosure());
+ AudioStartObserver observer(shell()->web_contents(),
+ run_loop.QuitClosure());
+
+ std::string result;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractString(shell(), "StartOscillator();", &result))
+ << "Failed to execute javascript.";
run_loop.Run();
// No point in running the rest of the test if this is wrong.
@@ -815,19 +815,6 @@ class CaptureStreamRenderProcessHostTest : public RenderProcessHostTest {
}
};
-// These tests contain WebRTC calls and cannot be run when it isn't enabled.
-#if !BUILDFLAG(ENABLE_WEBRTC)
-#define GetUserMediaIncrementsVideoCaptureStreams \
- DISABLED_GetUserMediaIncrementsVideoCaptureStreams
-#define StopResetsVideoCaptureStreams DISABLED_StopResetsVideoCaptureStreams
-#define KillProcessZerosVideoCaptureStreams \
- DISABLED_KillProcessZerosVideoCaptureStreams
-#define GetUserMediaAudioOnlyIncrementsMediaStreams \
- DISABLED_GetUserMediaAudioOnlyIncrementsMediaStreams
-#define KillProcessZerosAudioCaptureStreams \
- DISABLED_KillProcessZerosAudioCaptureStreams
-#endif // BUILDFLAG(ENABLE_WEBRTC)
-
// Tests that video capture stream count increments when getUserMedia() is
// called.
IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
@@ -1055,6 +1042,38 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
rph->RemoveObserver(this);
}
+// This test verifies properties of RenderProcessHostImpl *before* Init method
+// is called.
+IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ConstructedButNotInitializedYet) {
+ RenderProcessHost* process = RenderProcessHostImpl::CreateRenderProcessHost(
+ ShellContentBrowserClient::Get()->browser_context(), nullptr, nullptr,
+ false /* is_for_guests_only */);
+
+ // Just verifying that the arguments of CreateRenderProcessHost got processed
+ // correctly.
+ EXPECT_EQ(ShellContentBrowserClient::Get()->browser_context(),
+ process->GetBrowserContext());
+ EXPECT_FALSE(process->IsForGuestsOnly());
+
+ // There should be no OS process before Init() method is called.
+ EXPECT_FALSE(process->HasConnection());
+ EXPECT_FALSE(process->IsReady());
+ EXPECT_FALSE(process->GetProcess().IsValid());
+ EXPECT_EQ(base::kNullProcessHandle, process->GetProcess().Handle());
+
+ // TODO(lukasza): https://crbug.com/813045: RenderProcessHost shouldn't have
+ // an associated IPC channel (and shouldn't accumulate IPC messages) unless
+ // the Init() method was called and the RPH either has connection to an actual
+ // OS process or is currently attempting to spawn the OS process. After this
+ // bug is fixed the 1st test assertion below should be reversed (unsure about
+ // the 2nd one).
+ EXPECT_TRUE(process->GetChannel());
+ EXPECT_TRUE(process->GetRendererInterface());
+
+ // Cleanup the resources acquired by the test.
+ process->Cleanup();
+}
+
// This test verifies that a fast shutdown is possible for a starting process.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, FastShutdownForStartingProcess) {
RenderProcessHost* process = RenderProcessHostImpl::CreateRenderProcessHost(
@@ -1062,6 +1081,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, FastShutdownForStartingProcess) {
false /* is_for_guests_only */);
process->Init();
EXPECT_TRUE(process->FastShutdownIfPossible());
+ process->Cleanup();
}
} // namespace
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.cc b/chromium/content/browser/renderer_host/render_process_host_impl.cc
index dadd00f56a0..5ccfa4398c7 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -64,7 +64,6 @@
#include "components/metrics/single_sample_metrics.h"
#include "components/tracing/common/tracing_switches.h"
#include "components/viz/common/switches.h"
-#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "content/browser/appcache/appcache_dispatcher_host.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_fetch/background_fetch_context.h"
@@ -90,7 +89,7 @@
#include "content/browser/fileapi/fileapi_message_filter.h"
#include "content/browser/frame_host/render_frame_message_filter.h"
#include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_client.h"
+#include "content/browser/gpu/gpu_client_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/histogram_controller.h"
@@ -104,20 +103,18 @@
#include "content/browser/media/midi_host.h"
#include "content/browser/memory/memory_coordinator_impl.h"
#include "content/browser/mime_registry_impl.h"
-#include "content/browser/notifications/notification_message_filter.h"
#include "content/browser/payments/payment_manager.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
#include "content/browser/push_messaging/push_messaging_manager.h"
#include "content/browser/renderer_host/clipboard_host_impl.h"
+#include "content/browser/renderer_host/embedded_frame_sink_provider_impl.h"
#include "content/browser/renderer_host/file_utilities_host_impl.h"
-#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
-#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
-#include "content/browser/renderer_host/media/render_frame_audio_input_stream_factory.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
-#include "content/browser/renderer_host/offscreen_canvas_provider_impl.h"
+#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
#include "content/browser/renderer_host/render_message_filter.h"
@@ -131,16 +128,17 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/site_instance_impl.h"
-#include "content/browser/speech/speech_recognition_dispatcher_host.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/tracing/trace_message_filter.h"
+#include "content/browser/webrtc/webrtc_internals.h"
#include "content/browser/websockets/websocket_manager.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/content_switches_internal.h"
#include "content/common/frame_messages.h"
#include "content/common/in_process_child_thread_params.h"
+#include "content/common/media/aec_dump_messages.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/common/navigation_subresource_loader_params.h"
#include "content/common/resource_messages.h"
@@ -157,20 +155,19 @@
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/site_isolation_policy.h"
+#include "content/public/browser/webrtc_log.h"
#include "content/public/common/bind_interface_helpers.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/connection_filter.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_channel_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
-#include "content/public/common/zygote_buildflags.h"
#include "device/gamepad/gamepad_haptics_manager.h"
#include "device/gamepad/gamepad_monitor.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -206,6 +203,7 @@
#include "services/service_manager/runner/common/client_util.h"
#include "services/service_manager/runner/common/switches.h"
#include "services/service_manager/sandbox/switches.h"
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
#include "storage/browser/fileapi/sandbox_file_system_backend.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/public/public_buildflags.h"
@@ -253,20 +251,12 @@
#include "content/browser/media/key_system_support_impl.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h"
-#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
-#include "content/browser/webrtc/webrtc_internals.h"
-#include "content/common/media/aec_dump_messages.h"
-#include "content/public/browser/webrtc_log.h"
-#endif
-
#if BUILDFLAG(USE_MINIKIN_HYPHENATION)
#include "content/browser/hyphenation/hyphenation_impl.h"
#endif
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
-#include "content/public/common/zygote_handle.h"
+#include "services/service_manager/zygote/common/zygote_handle.h" // nogncheck
#endif
#if defined(OS_WIN)
@@ -292,10 +282,8 @@ const char kSiteProcessMapKeyName[] = "content_site_process_map";
RenderProcessHost::AnalyzeHungRendererFunction g_analyze_hung_renderer =
nullptr;
-#if BUILDFLAG(ENABLE_WEBRTC)
const base::FilePath::CharType kAecDumpFileNameAddition[] =
FILE_PATH_LITERAL("aec_dump");
-#endif
void CacheShaderInfo(int32_t id, base::FilePath path) {
if (GetShaderCacheFactorySingleton())
@@ -331,8 +319,6 @@ void GetContexts(
GetRequestContext(request_context, media_request_context, resource_type);
}
-#if BUILDFLAG(ENABLE_WEBRTC)
-
// Creates a file used for handing over to the renderer.
IPC::PlatformFileForTransit CreateFileForProcess(base::FilePath file_path) {
base::File dump_file(file_path,
@@ -348,8 +334,6 @@ IPC::PlatformFileForTransit CreateFileForProcess(base::FilePath file_path) {
// Allow us to only run the trial in the first renderer.
bool has_done_stun_trials = false;
-#endif
-
// Globally tracks all existing RenderProcessHostImpl instances.
//
// TODO(https://crbug.com/813045): Remove this.
@@ -487,14 +471,14 @@ class RendererSandboxedProcessLauncherDelegate
#endif // OS_WIN
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
- ZygoteHandle GetZygote() override {
+ service_manager::ZygoteHandle GetZygote() override {
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
base::CommandLine::StringType renderer_prefix =
browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
if (!renderer_prefix.empty())
return nullptr;
- return GetGenericZygote();
+ return service_manager::GetGenericZygote();
}
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
@@ -584,7 +568,7 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
RenderProcessHost* MaybeTakeSpareRenderProcessHost(
BrowserContext* browser_context,
- SiteInstance* site_instance,
+ SiteInstanceImpl* site_instance,
bool is_for_guests_only) {
// Give embedder a chance to disable using a spare RenderProcessHost for
// certain SiteInstances. Some navigations, such as to NTP or extensions,
@@ -592,10 +576,13 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
// launch time, but this cannot be done for spare RenderProcessHosts, which
// are started before it is known which navigation might use them. So, a
// spare RenderProcessHost should not be used in such cases.
- bool should_use_spare =
+ bool embedder_allows_spare_usage =
GetContentClient()->browser()->ShouldUseSpareRenderProcessHost(
browser_context, site_instance->GetSiteURL());
+ bool site_instance_allows_spare_usage =
+ site_instance->CanAssociateWithSpareProcess();
+
// Get the StoragePartition for |site_instance|. Note that this might be
// different than the default StoragePartition for |browser_context|.
StoragePartition* site_storage =
@@ -612,8 +599,10 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
action = SpareProcessMaybeTakeAction::kMismatchedBrowserContext;
else if (site_storage != spare_render_process_host_->GetStoragePartition())
action = SpareProcessMaybeTakeAction::kMismatchedStoragePartition;
- else if (!should_use_spare)
+ else if (!embedder_allows_spare_usage)
action = SpareProcessMaybeTakeAction::kRefusedByEmbedder;
+ else if (!site_instance_allows_spare_usage)
+ action = SpareProcessMaybeTakeAction::kRefusedBySiteInstance;
else
action = SpareProcessMaybeTakeAction::kSpareTaken;
UMA_HISTOGRAM_ENUMERATION(
@@ -624,7 +613,8 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
if (spare_render_process_host_ &&
browser_context == spare_render_process_host_->GetBrowserContext() &&
site_storage == spare_render_process_host_->GetStoragePartition() &&
- !is_for_guests_only && should_use_spare) {
+ !is_for_guests_only && embedder_allows_spare_usage &&
+ site_instance_allows_spare_usage) {
CHECK(spare_render_process_host_->HostHasNotBeenUsed());
// If the spare process ends up getting killed, the spare manager should
@@ -705,8 +695,7 @@ class SpareRenderProcessHostManager : public RenderProcessHostObserver {
// sufficient from correctness perspective.
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int unused_exit_code) override {
+ const ChildProcessTerminationInfo& info) override {
if (host == spare_render_process_host_)
CleanupSpareRenderProcessHost();
}
@@ -901,7 +890,7 @@ class SiteProcessCountTracker : public base::SupportsUserData::Data,
std::map<ProcessID, Count>& counts_per_process = result->second;
--counts_per_process[render_process_host_id];
- DCHECK(counts_per_process[render_process_host_id] >= 0);
+ DCHECK_GE(counts_per_process[render_process_host_id], 0);
if (counts_per_process[render_process_host_id] == 0)
counts_per_process.erase(render_process_host_id);
@@ -1278,13 +1267,7 @@ size_t RenderProcessHost::GetMaxRendererProcessCount() {
// On Android we don't maintain a limit of renderer process hosts - we are
// happy with keeping a lot of these, as long as the number of live renderer
// processes remains reasonable, and on Android the OS takes care of that.
- // TODO(boliu): This is a short term workaround before ChildProcessLauncher
- // can actively kill child processes in LRU order. Bug and process is tracked
- // in crbug.com/693484. Note this workaround is not perfect and still has
- // corner case problems.
- static const size_t kNumRendererSlots =
- ChildProcessLauncher::GetNumberOfRendererSlots();
- return kNumRendererSlots;
+ return std::numeric_limits<size_t>::max();
#endif
#if defined(OS_CHROMEOS)
// On Chrome OS new renderer processes are very cheap and there's no OS
@@ -1435,8 +1418,6 @@ RenderProcessHostImpl::RenderProcessHostImpl(
instance_weak_factory_(
new base::WeakPtrFactory<RenderProcessHostImpl>(this)),
frame_sink_provider_(id_),
- shared_bitmap_allocation_notifier_impl_(
- viz::ServerSharedBitmapManager::current()),
weak_factory_(this) {
for (size_t i = 0; i < kNumKeepAliveClients; i++)
keep_alive_client_count_[i] = 0;
@@ -1470,7 +1451,7 @@ RenderProcessHostImpl::RenderProcessHostImpl(
InitializeChannelProxy();
if (!base::FeatureList::IsEnabled(features::kMash))
- gpu_client_.reset(new GpuClient(GetID()));
+ gpu_client_.reset(new GpuClientImpl(GetID()));
GetMemoryDumpProvider().AddHost(this);
}
@@ -1600,11 +1581,14 @@ bool RenderProcessHostImpl::Init() {
}
#if !defined(OS_MACOSX)
- // Intentionally delay the hang monitor creation after the first renderer
- // is created. On Mac audio thread is the UI thread, a hang monitor is not
- // necessary or recommended.
- media::AudioManager::StartHangMonitorIfNeeded(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ if (!BrowserMainLoop::GetInstance()->AudioServiceOutOfProcess()) {
+ DCHECK(BrowserMainLoop::GetInstance()->audio_manager());
+ // Intentionally delay the hang monitor creation after the first renderer
+ // is created. On Mac audio thread is the UI thread, a hang monitor is not
+ // necessary or recommended.
+ media::AudioManager::StartHangMonitorIfNeeded(
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+ }
#endif // !defined(OS_MACOSX)
#if defined(OS_ANDROID)
@@ -1680,6 +1664,8 @@ bool RenderProcessHostImpl::Init() {
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
}
+ GetRendererInterface()->SetUserAgent(GetContentClient()->GetUserAgent());
+
is_initialized_ = true;
init_time_ = base::TimeTicks::Now();
return true;
@@ -1792,9 +1778,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
MediaInternals* media_internals = MediaInternals::GetInstance();
// Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
// from guests.
- scoped_refptr<BrowserPluginMessageFilter> bp_message_filter(
- new BrowserPluginMessageFilter(GetID()));
- AddFilter(bp_message_filter.get());
+ bp_message_filter_ = new BrowserPluginMessageFilter(GetID());
+ AddFilter(bp_message_filter_.get());
scoped_refptr<net::URLRequestContextGetter> request_context(
storage_partition_impl_->GetURLRequestContext());
@@ -1840,38 +1825,16 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(resource_message_filter_.get());
- media::AudioManager* audio_manager =
- BrowserMainLoop::GetInstance()->audio_manager();
- MediaStreamManager* media_stream_manager =
- BrowserMainLoop::GetInstance()->media_stream_manager();
- if (!RenderFrameAudioInputStreamFactory::UseMojoFactories()) {
- AddFilter(base::MakeRefCounted<AudioInputRendererHost>(
- GetID(), audio_manager, media_stream_manager,
- AudioMirroringManager::GetInstance(),
- BrowserMainLoop::GetInstance()->user_input_monitor())
- .get());
- }
- if (!RendererAudioOutputStreamFactoryContextImpl::UseMojoFactories()) {
- AddFilter(base::MakeRefCounted<AudioRendererHost>(
- GetID(), audio_manager,
- BrowserMainLoop::GetInstance()->audio_system(),
- media_stream_manager)
- .get());
- }
AddFilter(
new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_service()));
AddFilter(new DOMStorageMessageFilter(
storage_partition_impl_->GetDOMStorageContext()));
-#if BUILDFLAG(ENABLE_WEBRTC)
peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
AddFilter(peer_connection_tracker_host_.get());
-#endif
#if BUILDFLAG(ENABLE_PLUGINS)
AddFilter(new PepperRendererConnection(GetID()));
#endif
- AddFilter(new SpeechRecognitionDispatcherHost(
- GetID(), storage_partition_impl_->GetURLRequestContext()));
AddFilter(new FileAPIMessageFilter(
GetID(), storage_partition_impl_->GetURLRequestContext(),
storage_partition_impl_->GetFileSystemContext(),
@@ -1881,17 +1844,15 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(new TextInputClientMessageFilter());
#endif
- scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter =
- new ServiceWorkerDispatcherHost(GetID(), resource_context);
+ auto service_worker_filter =
+ base::MakeRefCounted<ServiceWorkerDispatcherHost>(GetID());
service_worker_filter->Init(
storage_partition_impl_->GetServiceWorkerContext());
AddFilter(service_worker_filter.get());
-#if BUILDFLAG(ENABLE_WEBRTC)
p2p_socket_dispatcher_host_ = new P2PSocketDispatcherHost(
resource_context, request_context.get());
AddFilter(p2p_socket_dispatcher_host_.get());
-#endif
AddFilter(new TraceMessageFilter(GetID()));
AddFilter(new ResolveProxyMsgHelper(request_context.get()));
@@ -1899,18 +1860,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context(
static_cast<ServiceWorkerContextWrapper*>(
storage_partition_impl_->GetServiceWorkerContext()));
- notification_message_filter_ = new NotificationMessageFilter(
- GetID(), storage_partition_impl_->GetPlatformNotificationContext(),
- resource_context, service_worker_context, browser_context);
- AddFilter(notification_message_filter_.get());
-
-#if defined(OS_ANDROID)
- if (!base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- synchronous_compositor_filter_ =
- new SynchronousCompositorBrowserFilter(GetID());
- AddFilter(synchronous_compositor_filter_.get());
- }
-#endif
}
void RenderProcessHostImpl::BindCacheStorage(
@@ -1933,6 +1882,27 @@ void RenderProcessHostImpl::BindCacheStorage(
origin));
}
+void RenderProcessHostImpl::CancelProcessShutdownDelayForUnload() {
+ if (IsKeepAliveRefCountDisabled())
+ return;
+ DecrementKeepAliveRefCount(RenderProcessHost::KeepAliveClientType::kUnload);
+}
+
+void RenderProcessHostImpl::DelayProcessShutdownForUnload(
+ const base::TimeDelta& timeout) {
+ // No need to delay shutdown if the process is already shutting down.
+ if (IsKeepAliveRefCountDisabled() || deleting_soon_ || fast_shutdown_started_)
+ return;
+
+ IncrementKeepAliveRefCount(RenderProcessHost::KeepAliveClientType::kUnload);
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &RenderProcessHostImpl::CancelProcessShutdownDelayForUnload,
+ weak_factory_.GetWeakPtr()),
+ timeout);
+}
+
void RenderProcessHostImpl::RegisterMojoInterfaces() {
auto registry = std::make_unique<service_manager::BinderRegistry>();
@@ -1946,7 +1916,7 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
AddUIThreadInterface(
registry.get(),
- base::Bind(&RenderProcessHostImpl::CreateOffscreenCanvasProvider,
+ base::Bind(&RenderProcessHostImpl::CreateEmbeddedFrameSinkProvider,
base::Unretained(this)));
AddUIThreadInterface(registry.get(),
@@ -1960,11 +1930,6 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
AddUIThreadInterface(
registry.get(),
- base::Bind(&RenderProcessHostImpl::BindSharedBitmapAllocationNotifier,
- base::Unretained(this)));
-
- AddUIThreadInterface(
- registry.get(),
base::Bind(&BackgroundSyncContext::CreateService,
base::Unretained(
storage_partition_impl_->GetBackgroundSyncContext())));
@@ -1991,9 +1956,9 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
scoped_refptr<ChromeBlobStorageContext> blob_storage_context =
ChromeBlobStorageContext::GetFor(browser_context);
- AddUIThreadInterface(
- registry.get(),
- base::Bind(&ClipboardHostImpl::Create, std::move(blob_storage_context)));
+ AddUIThreadInterface(registry.get(),
+ base::BindRepeating(&ClipboardHostImpl::Create,
+ std::move(blob_storage_context)));
media::VideoDecodePerfHistory* video_perf_history =
GetBrowserContext()->GetVideoDecodePerfHistory();
@@ -2024,7 +1989,7 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
// |gpu_client_| outlives the registry, because its destruction is posted to
// IO thread from the destructor of |this|.
registry->AddInterface(
- base::Bind(&GpuClient::Add, base::Unretained(gpu_client_.get())));
+ base::Bind(&GpuClientImpl::Add, base::Unretained(gpu_client_.get())));
}
registry->AddInterface(
@@ -2044,11 +2009,9 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE}));
-#if BUILDFLAG(ENABLE_WEBRTC)
registry->AddInterface(base::BindRepeating(
&RenderProcessHostImpl::CreateMediaStreamTrackMetricsHost,
base::Unretained(this)));
-#endif
registry->AddInterface(
base::Bind(&metrics::CreateSingleSampleMetricsProvider));
@@ -2066,8 +2029,6 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
AddUIThreadInterface(registry.get(), base::Bind(&FieldTrialRecorder::Create));
associated_interfaces_.reset(new AssociatedInterfaceRegistryImpl());
- GetContentClient()->browser()->ExposeInterfacesToRenderer(
- registry.get(), associated_interfaces_.get(), this);
blink::AssociatedInterfaceRegistry* associated_registry =
associated_interfaces_.get();
associated_registry->AddInterface(base::Bind(
@@ -2090,6 +2051,14 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
registry->AddInterface(base::BindRepeating(&KeySystemSupportImpl::Create));
#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
+ // ---- Please do not register interfaces below this line ------
+ //
+ // This call should be done after registering all interfaces above, so that
+ // embedder can override any interfaces. The fact that registry calls
+ // the last registration for the name allows us to easily override interfaces.
+ GetContentClient()->browser()->ExposeInterfacesToRenderer(
+ registry.get(), associated_interfaces_.get(), this);
+
ServiceManagerConnection* service_manager_connection =
BrowserContext::GetServiceManagerConnectionFor(browser_context_);
if (connection_filter_id_ !=
@@ -2140,16 +2109,17 @@ void RenderProcessHostImpl::GetBlobURLLoaderFactory(
std::move(request));
}
-void RenderProcessHostImpl::CreateOffscreenCanvasProvider(
- blink::mojom::OffscreenCanvasProviderRequest request) {
+void RenderProcessHostImpl::CreateEmbeddedFrameSinkProvider(
+ blink::mojom::EmbeddedFrameSinkProviderRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!offscreen_canvas_provider_) {
+ if (!embedded_frame_sink_provider_) {
// The client id gets converted to a uint32_t in FrameSinkId.
uint32_t renderer_client_id = base::checked_cast<uint32_t>(id_);
- offscreen_canvas_provider_ = std::make_unique<OffscreenCanvasProviderImpl>(
- GetHostFrameSinkManager(), renderer_client_id);
+ embedded_frame_sink_provider_ =
+ std::make_unique<EmbeddedFrameSinkProviderImpl>(
+ GetHostFrameSinkManager(), renderer_client_id);
}
- offscreen_canvas_provider_->Add(std::move(request));
+ embedded_frame_sink_provider_->Add(std::move(request));
}
void RenderProcessHostImpl::BindFrameSinkProvider(
@@ -2163,11 +2133,6 @@ void RenderProcessHostImpl::BindCompositingModeReporter(
std::move(request));
}
-void RenderProcessHostImpl::BindSharedBitmapAllocationNotifier(
- viz::mojom::SharedBitmapAllocationNotifierRequest request) {
- shared_bitmap_allocation_notifier_impl_.Bind(std::move(request));
-}
-
void RenderProcessHostImpl::CreateStoragePartitionService(
mojom::StoragePartitionServiceRequest request) {
if (g_create_storage_partition) {
@@ -2189,19 +2154,19 @@ void RenderProcessHostImpl::CreateURLLoaderFactory(
NOTREACHED();
return;
}
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = id_;
+ // TODO(lukasza): https://crbug.com/792546: Start using CORB.
+ params->is_corb_enabled = false;
storage_partition_impl_->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(request), id_);
+ std::move(request), std::move(params));
}
int RenderProcessHostImpl::GetNextRoutingID() {
return widget_helper_->GetNextRoutingID();
}
-void RenderProcessHostImpl::ResumeDeferredNavigation(
- const GlobalRequestID& request_id) {
- widget_helper_->ResumeDeferredNavigation(request_id);
-}
-
void RenderProcessHostImpl::BindInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
@@ -2282,6 +2247,10 @@ void RenderProcessHostImpl::RecordKeepAliveDuration(
UMA_HISTOGRAM_LONG_TIMES(
"BrowserRenderProcessHost.KeepAliveDuration.Fetch", end - start);
break;
+ case RenderProcessHost::KeepAliveClientType::kUnload:
+ UMA_HISTOGRAM_LONG_TIMES(
+ "BrowserRenderProcessHost.KeepAliveDuration.Unload", end - start);
+ break;
}
}
@@ -2439,7 +2408,7 @@ int RenderProcessHostImpl::VisibleClientCount() const {
return visible_clients_;
}
-unsigned int RenderProcessHostImpl::GetFrameDepthForTesting() const {
+unsigned int RenderProcessHostImpl::GetFrameDepth() const {
return frame_depth_;
}
@@ -2454,6 +2423,8 @@ RenderProcessHostImpl::GetRendererAudioOutputStreamFactoryContext() {
if (!audio_output_stream_factory_context_) {
media::AudioManager* audio_manager =
BrowserMainLoop::GetInstance()->audio_manager();
+ DCHECK(audio_manager) << "AudioManager is not instantiated: running the "
+ "audio service out of process?";
MediaStreamManager* media_stream_manager =
BrowserMainLoop::GetInstance()->media_stream_manager();
media::AudioSystem* audio_system =
@@ -2477,12 +2448,18 @@ void RenderProcessHostImpl::OnMediaStreamRemoved() {
}
// static
-void RenderProcessHostImpl::set_render_process_host_factory(
+void RenderProcessHostImpl::set_render_process_host_factory_for_testing(
const RenderProcessHostFactory* rph_factory) {
g_render_process_host_factory_ = rph_factory;
}
// static
+const RenderProcessHostFactory*
+RenderProcessHostImpl::get_render_process_host_factory_for_testing() {
+ return g_render_process_host_factory_;
+}
+
+// static
void RenderProcessHostImpl::AddFrameWithSite(
BrowserContext* browser_context,
RenderProcessHost* render_process_host,
@@ -2586,6 +2563,11 @@ bool RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() {
// Spare renderer actually hurts performance on low-memory devices. See
// https://crbug.com/843775 for more details.
+ //
+ // The comparison below is using 1077 rather than 1024 because 1) this helps
+ // ensure that devices with exactly 1GB of RAM won't get included because of
+ // inaccuracies or off-by-one errors and 2) this is the bucket boundary in
+ // Memory.Stats.Win.TotalPhys2.
if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 1077)
return false;
@@ -2629,12 +2611,11 @@ static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
if (IsMainFrameBeforeActivationEnabled())
command_line->AppendSwitch(cc::switches::kEnableMainFrameBeforeActivation);
- if (IsCheckerImagingEnabled())
- command_line->AppendSwitch(cc::switches::kEnableCheckerImaging);
-
// Slimming Paint v2 implies layer lists in the renderer.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableSlimmingPaintV2)) {
+ switches::kEnableSlimmingPaintV2) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBlinkGenPropertyTrees)) {
command_line->AppendSwitch(cc::switches::kEnableLayerLists);
}
}
@@ -2677,8 +2658,9 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
AppendCompositorCommandLineFlags(command_line);
- command_line->AppendSwitchASCII(switches::kServiceRequestChannelToken,
- child_connection_->service_token());
+ command_line->AppendSwitchASCII(
+ service_manager::switches::kServiceRequestChannelToken,
+ child_connection_->service_token());
command_line->AppendSwitchASCII(switches::kRendererClientId,
std::to_string(GetID()));
}
@@ -2692,6 +2674,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
network::switches::kNoReferrers,
service_manager::switches::kDisableInProcessStackTraces,
service_manager::switches::kDisableSeccompFilterSandbox,
+ service_manager::switches::kNoSandbox,
+#if defined(OS_MACOSX)
+ // Allow this to be set when invoking the browser and relayed along.
+ service_manager::switches::kEnableSandboxLogging,
+#endif
switches::kAgcStartupMinVolume,
switches::kAecRefinedAdaptiveFilter,
switches::kAllowLoopbackInPeerConnection,
@@ -2711,8 +2698,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisablePreferCompositingToLCDText,
switches::kDisableDatabases,
switches::kDisableFileSystem,
+ switches::kDisableFrameRateLimit,
switches::kDisableGpuMemoryBufferVideoFrames,
- switches::kDisableGpuVsync,
switches::kDisableImageAnimationResync,
switches::kDisableLowResTiling,
switches::kDisableHistogramCustomizer,
@@ -2737,8 +2724,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableWebGLImageChromium,
switches::kDomAutomationController,
switches::kEnableAutomation,
+ switches::kEnableBlinkGenPropertyTrees,
switches::kEnableExperimentalWebPlatformFeatures,
- switches::kEnableHeapProfiling,
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
switches::kEnableGpuMemoryBufferVideoFrames,
@@ -2754,7 +2741,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnablePreciseMemoryInfo,
switches::kEnablePrintBrowser,
switches::kEnablePreferCompositingToLCDText,
- switches::kEnableRasterDecoder,
switches::kEnableRGBA4444Textures,
switches::kEnableSkiaBenchmarking,
switches::kEnableSlimmingPaintV175,
@@ -2782,7 +2768,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kMaxUntiledLayerHeight,
switches::kMSEAudioBufferSizeLimit,
switches::kMSEVideoBufferSizeLimit,
- switches::kNoSandbox,
switches::kNoZygote,
switches::kOverridePluginPowerSaverForTesting,
switches::kPassiveListenersDefault,
@@ -2806,7 +2791,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kUseGL,
switches::kUseGpuInTests,
switches::kUseMobileUserAgent,
- switches::kUseSkiaRenderer,
switches::kV,
switches::kVideoThreads,
switches::kVideoUnderflowThresholdMs,
@@ -2815,11 +2799,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
cc::switches::kAlwaysRequestPresentationTime,
cc::switches::kCheckDamageEarly,
+ cc::switches::kDisableCheckerImaging,
cc::switches::kDisableCompositedAntialiasing,
cc::switches::kDisableThreadedAnimation,
cc::switches::kEnableGpuBenchmarking,
cc::switches::kEnableLayerLists,
- cc::switches::kEnableTileCompression,
cc::switches::kShowCompositedLayerBorders,
cc::switches::kShowFPSCounter,
cc::switches::kShowLayerAnimationBounds,
@@ -2839,7 +2823,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if BUILDFLAG(ENABLE_RUNTIME_MEDIA_RENDERER_SELECTION)
switches::kDisableMojoRenderer,
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
switches::kDisableWebRtcHWDecoding,
switches::kDisableWebRtcHWEncoding,
switches::kEnableWebRtcSrtpAesGcm,
@@ -2847,7 +2830,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableWebRtcStunOrigin,
switches::kEnforceWebRtcIPPermissionCheck,
switches::kWebRtcMaxCaptureFramerate,
-#endif
switches::kEnableLowEndDeviceMode,
switches::kDisableLowEndDeviceMode,
switches::kDisallowNonExactResourceReuse,
@@ -2856,10 +2838,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kOrderfileMemoryOptimization,
switches::kRendererWaitForJavaDebugger,
#endif
-#if defined(OS_MACOSX)
- // Allow this to be set when invoking the browser and relayed along.
- switches::kEnableSandboxLogging,
-#endif
#if defined(OS_WIN)
service_manager::switches::kDisableWin32kLockDown,
switches::kEnableWin7WebRtcHWH264Decoding,
@@ -2880,7 +2858,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(renderer_cmd);
BrowserChildProcessHostImpl::CopyTraceStartupFlags(renderer_cmd);
-#if BUILDFLAG(ENABLE_WEBRTC)
// Only run the Stun trials in the first renderer.
if (!has_done_stun_trials &&
browser_cmd.HasSwitch(switches::kWebRtcStunProbeTrialParameter)) {
@@ -2890,7 +2867,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
browser_cmd.GetSwitchValueASCII(
switches::kWebRtcStunProbeTrialParameter));
}
-#endif
// Disable databases in incognito mode.
if (GetBrowserContext()->IsOffTheRecord() &&
@@ -2934,8 +2910,8 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// --no-sandbox in official builds because that would bypass the bad_flgs
// prompt.
if (renderer_cmd->HasSwitch(switches::kRendererStartupDialog) &&
- !renderer_cmd->HasSwitch(switches::kNoSandbox)) {
- renderer_cmd->AppendSwitch(switches::kNoSandbox);
+ !renderer_cmd->HasSwitch(service_manager::switches::kNoSandbox)) {
+ renderer_cmd->AppendSwitch(service_manager::switches::kNoSandbox);
}
#endif
@@ -2943,20 +2919,27 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
CopyFeatureSwitch(browser_cmd, renderer_cmd, switches::kDisableBlinkFeatures);
}
-base::ProcessHandle RenderProcessHostImpl::GetHandle() const {
- if (run_renderer_in_process())
- return base::GetCurrentProcessHandle();
+const base::Process& RenderProcessHostImpl::GetProcess() const {
+ if (run_renderer_in_process()) {
+ // This is a sentinel object used for this process in single process mode.
+ static const base::NoDestructor<base::Process> self(
+ base::Process::Current());
+ return *self;
+ }
- if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
- return base::kNullProcessHandle;
+ if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) {
+ // This is a sentinel for "no process".
+ static const base::NoDestructor<base::Process> null_process;
+ return *null_process;
+ }
- return child_process_launcher_->GetProcess().Handle();
+ return child_process_launcher_->GetProcess();
}
bool RenderProcessHostImpl::IsReady() const {
// The process launch result (that sets GetHandle()) and the channel
// connection (that sets channel_connected_) can happen in either order.
- return GetHandle() && channel_connected_;
+ return GetProcess().Handle() && channel_connected_;
}
bool RenderProcessHostImpl::Shutdown(int exit_code) {
@@ -3047,13 +3030,11 @@ bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
OnUserMetricsRecordAction)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK)
-#if BUILDFLAG(ENABLE_WEBRTC)
IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer,
OnRegisterAecDumpConsumer)
IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer,
OnUnregisterAecDumpConsumer)
IPC_MESSAGE_HANDLER(AudioProcessingMsg_Aec3Enabled, OnAec3Enabled)
-#endif
// Adding single handlers for your service here is fine, but once your
// service needs more than one handler, please extract them into a new
// message filter and add that filter to CreateMessageFilters().
@@ -3183,13 +3164,11 @@ void RenderProcessHostImpl::Cleanup() {
if (!listeners_.IsEmpty() || keep_alive_ref_count_ != 0)
return;
-#if BUILDFLAG(ENABLE_WEBRTC)
if (is_initialized_) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&WebRtcLog::ClearLogMessageCallback, GetID()));
}
-#endif
if (!keep_alive_start_time_.is_null()) {
UMA_HISTOGRAM_LONG_TIMES("BrowserRenderProcessHost.KeepAliveDuration",
@@ -3207,9 +3186,14 @@ void RenderProcessHostImpl::Cleanup() {
// will be destroyed a bit later. Observers shouldn't rely on this process
// anymore.
if (HasConnection()) {
+ // Populates Android-only fields and closes the underlying base::Process.
+ ChildProcessTerminationInfo info =
+ child_process_launcher_->GetChildTerminationInfo(
+ false /* already_dead */);
+ info.status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
+ info.exit_code = 0;
for (auto& observer : observers_) {
- observer.RenderProcessExited(
- this, base::TERMINATION_STATUS_NORMAL_TERMINATION, 0);
+ observer.RenderProcessExited(this, info);
}
}
for (auto& observer : observers_)
@@ -3299,7 +3283,6 @@ void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) {
FilterURL(this, empty_allowed, url);
}
-#if BUILDFLAG(ENABLE_WEBRTC)
void RenderProcessHostImpl::EnableAudioDebugRecordings(
const base::FilePath& file) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -3370,7 +3353,6 @@ void RenderProcessHostImpl::SetWebRtcEventLogOutput(int lid, bool enabled) {
Send(new PeerConnectionTracker_StopEventLog(lid));
}
}
-#endif // BUILDFLAG(ENABLE_WEBRTC)
IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
return channel_.get();
@@ -3622,6 +3604,12 @@ bool RenderProcessHost::ShouldUseProcessPerSite(BrowserContext* browser_context,
if (command_line.HasSwitch(switches::kProcessPerSite))
return true;
+ // Error pages should use process-per-site model, as it is useful to
+ // consolidate them to minimize resource usage and there is no security
+ // drawback to combining them all in the same process.
+ if (url.SchemeIs(kChromeErrorScheme))
+ return true;
+
// We want to consolidate particular sites like WebUI even when we are using
// the process-per-tab or process-per-site-instance models.
// Note: DevTools pages have WebUI type but should not reuse the same host.
@@ -3805,7 +3793,7 @@ void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() {
}
// Get handle to the renderer process. Stop if there is none.
- base::ProcessHandle destination = GetHandle();
+ base::ProcessHandle destination = GetProcess().Handle();
if (destination == base::kNullProcessHandle)
return;
@@ -3831,8 +3819,9 @@ void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() {
mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite));
}
-void RenderProcessHostImpl::ProcessDied(bool already_dead,
- RendererClosedDetails* known_details) {
+void RenderProcessHostImpl::ProcessDied(
+ bool already_dead,
+ ChildProcessTerminationInfo* known_info) {
// Our child process has died. If we didn't expect it, it's a crash.
// In any case, we need to let everyone know it's gone.
// The OnChannelError notification can fire multiple times due to nested sync
@@ -3848,33 +3837,29 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
// child_process_launcher_ can be NULL in single process mode or if fast
// termination happened.
- base::TerminationStatus status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
- int exit_code = 0;
- if (known_details) {
- status = known_details->status;
- exit_code = known_details->exit_code;
+ ChildProcessTerminationInfo info;
+ info.exit_code = 0;
+ if (known_info) {
+ info = *known_info;
} else if (child_process_launcher_.get()) {
- status = child_process_launcher_->GetChildTerminationStatus(already_dead,
- &exit_code);
- if (already_dead && status == base::TERMINATION_STATUS_STILL_RUNNING) {
+ info = child_process_launcher_->GetChildTerminationInfo(already_dead);
+ if (already_dead && info.status == base::TERMINATION_STATUS_STILL_RUNNING) {
// May be in case of IPC error, if it takes long time for renderer
// to exit. Child process will be killed in any case during
// child_process_launcher_.reset(). Make sure we will not broadcast
// FrameHostMsg_RenderProcessGone with status
// TERMINATION_STATUS_STILL_RUNNING, since this will break WebContentsImpl
// logic.
- status = base::TERMINATION_STATUS_PROCESS_CRASHED;
+ info.status = base::TERMINATION_STATUS_PROCESS_CRASHED;
// TODO(siggi): Remove this once https://crbug.com/806661 is resolved.
#if defined(OS_WIN)
- if (exit_code == WAIT_TIMEOUT && g_analyze_hung_renderer)
+ if (info.exit_code == WAIT_TIMEOUT && g_analyze_hung_renderer)
g_analyze_hung_renderer(child_process_launcher_->GetProcess());
#endif
}
}
- RendererClosedDetails details(status, exit_code);
-
child_process_launcher_.reset();
is_dead_ = true;
// Make sure no IPCs or mojo calls from the old process get dispatched after
@@ -3887,9 +3872,9 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
within_process_died_observer_ = true;
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_CLOSED, Source<RenderProcessHost>(this),
- Details<RendererClosedDetails>(&details));
+ Details<ChildProcessTerminationInfo>(&info));
for (auto& observer : observers_)
- observer.RenderProcessExited(this, status, exit_code);
+ observer.RenderProcessExited(this, info);
within_process_died_observer_ = false;
RemoveUserData(kSessionStorageHolderKey);
@@ -3897,7 +3882,7 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
base::IDMap<IPC::Listener*>::iterator iter(&listeners_);
while (!iter.IsAtEnd()) {
iter.GetCurrentValue()->OnMessageReceived(FrameHostMsg_RenderProcessGone(
- iter.GetCurrentKey(), static_cast<int>(status), exit_code));
+ iter.GetCurrentKey(), static_cast<int>(info.status), info.exit_code));
iter.Advance();
}
@@ -3915,8 +3900,6 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
compositing_mode_reporter_.reset();
- shared_bitmap_allocation_notifier_impl_.ChildDied();
-
HistogramController::GetInstance()->NotifyChildDied<RenderProcessHost>(this);
// This object is not deleted at this point and might be reused later.
// TODO(darin): clean this up
@@ -3930,6 +3913,9 @@ void RenderProcessHostImpl::ResetIPC() {
associated_interface_provider_bindings_.CloseAllBindings();
associated_interfaces_.reset();
+ // Destroy all embedded CompositorFrameSinks.
+ embedded_frame_sink_provider_.reset();
+
// If RenderProcessHostImpl is reused, the next renderer will send a new
// request for FrameSinkProvider so make sure frame_sink_provider_ is ready
// for that.
@@ -4040,6 +4026,13 @@ void RenderProcessHostImpl::UpdateProcessPriorityInputs() {
}
bool inputs_changed = new_visible_widgets_count != visible_clients_;
+#if defined(OS_ANDROID)
+ // OS_ANDROID in order to maintain the workaround on desktop to avoid
+ // backgrounding a new process. See the comment in OnProcessLaunched and
+ // https://crbug.com/560446. Only android uses frame_depth for now, so
+ // not a huge change.
+ inputs_changed = inputs_changed || frame_depth_ != new_frame_depth;
+#endif
visible_clients_ = new_visible_widgets_count;
frame_depth_ = new_frame_depth;
#if defined(OS_ANDROID)
@@ -4192,15 +4185,13 @@ void RenderProcessHostImpl::OnProcessLaunched() {
}
GetProcessResourceCoordinator()->SetLaunchTime(base::Time::Now());
- GetProcessResourceCoordinator()->SetPID(base::GetProcId(GetHandle()));
+ GetProcessResourceCoordinator()->SetPID(GetProcess().Pid());
-#if BUILDFLAG(ENABLE_WEBRTC)
WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
if (webrtc_internals->IsAudioDebugRecordingsEnabled()) {
EnableAudioDebugRecordings(
webrtc_internals->GetAudioDebugRecordingsFilePath());
}
-#endif
}
void RenderProcessHostImpl::OnProcessLaunchFailed(int error_code) {
@@ -4210,9 +4201,10 @@ void RenderProcessHostImpl::OnProcessLaunchFailed(int error_code) {
if (deleting_soon_)
return;
- RendererClosedDetails details{base::TERMINATION_STATUS_LAUNCH_FAILED,
- error_code};
- ProcessDied(true, &details);
+ ChildProcessTerminationInfo info;
+ info.status = base::TERMINATION_STATUS_LAUNCH_FAILED;
+ info.exit_code = error_code;
+ ProcessDied(true, &info);
}
void RenderProcessHostImpl::OnUserMetricsRecordAction(
@@ -4300,7 +4292,6 @@ RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
return nullptr;
}
-#if BUILDFLAG(ENABLE_WEBRTC)
void RenderProcessHostImpl::CreateMediaStreamTrackMetricsHost(
mojom::MediaStreamTrackMetricsHostRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -4368,7 +4359,7 @@ void RenderProcessHostImpl::SendDisableAecDumpToRenderer() {
base::FilePath RenderProcessHostImpl::GetAecDumpFilePathWithExtensions(
const base::FilePath& file) {
- return file.AddExtension(IntToStringType(base::GetProcId(GetHandle())))
+ return file.AddExtension(IntToStringType(GetProcess().Pid()))
.AddExtension(kAecDumpFileNameAddition);
}
@@ -4390,7 +4381,6 @@ void RenderProcessHostImpl::OnAec3Enabled() {
if (!aec3_set_callback_.is_null())
std::move(aec3_set_callback_).Run(true, std::string());
}
-#endif // BUILDFLAG(ENABLE_WEBRTC)
void RenderProcessHostImpl::RecomputeAndUpdateWebKitPreferences() {
// We are updating all widgets including swapped out ones.
@@ -4416,11 +4406,6 @@ void RenderProcessHostImpl::OnMojoError(int render_process_id,
bad_message::RPH_MOJO_PROCESS_ERROR);
}
-viz::SharedBitmapAllocationNotifierImpl*
-RenderProcessHostImpl::GetSharedBitmapAllocationNotifier() {
- return &shared_bitmap_allocation_notifier_impl_;
-}
-
void RenderProcessHostImpl::GetBrowserHistogram(
const std::string& name,
BrowserHistogramCallback callback) {
@@ -4444,4 +4429,9 @@ void RenderProcessHostImpl::GetBrowserHistogram(
std::move(callback).Run(histogram_json);
}
+void RenderProcessHostImpl::SetBrowserPluginMessageFilterSubFilterForTesting(
+ scoped_refptr<BrowserMessageFilter> message_filter) const {
+ bp_message_filter_->SetSubFilterForTesting(std::move(message_filter));
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.h b/chromium/content/browser/renderer_host/render_process_host_impl.h
index 5f6fd5d4c8c..b418b4c8a0a 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -25,13 +25,12 @@
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "build/build_config.h"
-#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
#include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/renderer_host/embedded_frame_sink_provider_impl.h"
#include "content/browser/renderer_host/frame_sink_provider_impl.h"
#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h"
-#include "content/browser/renderer_host/offscreen_canvas_provider_impl.h"
#include "content/common/associated_interface_registry_impl.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/child_control.mojom.h"
@@ -61,7 +60,6 @@
#include "ui/gl/gpu_switching_observer.h"
#if defined(OS_ANDROID)
-#include "content/browser/android/synchronous_compositor_browser_filter.h"
#include "content/public/browser/android/child_process_importance.h"
#endif
@@ -72,11 +70,13 @@ class SharedPersistentMemoryAllocator;
}
namespace content {
+class BrowserPluginMessageFilter;
class ChildConnection;
-class GpuClient;
+class GpuClientImpl;
class IndexedDBDispatcherHost;
class InProcessChildThreadParams;
-class NotificationMessageFilter;
+class MediaStreamTrackMetricsHost;
+class P2PSocketDispatcherHost;
class PermissionServiceContext;
class PeerConnectionTrackerHost;
class PushMessagingManager;
@@ -90,11 +90,7 @@ class SiteInstance;
class SiteInstanceImpl;
class StoragePartition;
class StoragePartitionImpl;
-
-#if BUILDFLAG(ENABLE_WEBRTC)
-class MediaStreamTrackMetricsHost;
-class P2PSocketDispatcherHost;
-#endif
+struct ChildProcessTerminationInfo;
typedef base::Thread* (*RendererMainThreadFactoryFunction)(
const InProcessChildThreadParams& params);
@@ -153,13 +149,13 @@ class CONTENT_EXPORT RenderProcessHostImpl
void ShutdownForBadMessage(CrashReportMode crash_report_mode) override;
void UpdateClientPriority(PriorityClient* client) override;
int VisibleClientCount() const override;
- unsigned int GetFrameDepthForTesting() const override;
+ unsigned int GetFrameDepth() const override;
bool IsForGuestsOnly() const override;
StoragePartition* GetStoragePartition() const override;
bool Shutdown(int exit_code) override;
bool FastShutdownIfPossible(size_t page_count = 0,
bool skip_unload_handlers = false) override;
- base::ProcessHandle GetHandle() const override;
+ const base::Process& GetProcess() const override;
bool IsReady() const override;
BrowserContext* GetBrowserContext() const override;
bool InSameStoragePartition(StoragePartition* partition) const override;
@@ -182,7 +178,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
bool FastShutdownStarted() const override;
base::TimeDelta GetChildProcessIdleTime() const override;
void FilterURL(bool empty_allowed, GURL* url) override;
-#if BUILDFLAG(ENABLE_WEBRTC)
void EnableAudioDebugRecordings(const base::FilePath& file) override;
void DisableAudioDebugRecordings() override;
void SetEchoCanceller3(
@@ -193,8 +188,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
bool outgoing,
const WebRtcRtpPacketCallback& packet_callback) override;
void SetWebRtcEventLogOutput(int lid, bool enabled) override;
-#endif
- void ResumeDeferredNavigation(const GlobalRequestID& request_id) override;
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
const service_manager::Identity& GetChildIdentity() const override;
@@ -220,6 +213,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
void SetIsUsed() override;
bool HostHasNotBeenUsed() override;
+ void BindCacheStorage(blink::mojom::CacheStorageRequest request,
+ const url::Origin& origin) override;
mojom::RouteProvider* GetRemoteRouteProvider();
@@ -311,7 +306,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
kMismatchedStoragePartition = 2,
kRefusedByEmbedder = 3,
kSpareTaken = 4,
- kMaxValue = kSpareTaken
+ kRefusedBySiteInstance = 5,
+ kMaxValue = kRefusedBySiteInstance
};
static base::MessageLoop* GetInProcessRendererThreadForTesting();
@@ -335,15 +331,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
return render_frame_message_filter_.get();
}
- NotificationMessageFilter* notification_message_filter() const {
- return notification_message_filter_.get();
- }
-
-#if defined(OS_ANDROID)
- SynchronousCompositorBrowserFilter* synchronous_compositor_filter() const {
- return synchronous_compositor_filter_.get();
- }
-#endif
+ void SetBrowserPluginMessageFilterSubFilterForTesting(
+ scoped_refptr<BrowserMessageFilter> message_filter) const;
void set_is_for_guests_only_for_testing(bool is_for_guests_only) {
is_for_guests_only_ = is_for_guests_only;
@@ -365,12 +354,17 @@ class CONTENT_EXPORT RenderProcessHostImpl
void OnMediaStreamRemoved() override;
int get_media_stream_count_for_testing() const { return media_stream_count_; }
- // Sets the global factory used to create new RenderProcessHosts. It may be
- // nullptr, in which case the default RenderProcessHost will be created (this
- // is the behavior if you don't call this function). The factory must be set
- // back to nullptr before it's destroyed; ownership is not transferred.
- static void set_render_process_host_factory(
+ // Sets the global factory used to create new RenderProcessHosts in unit
+ // tests. It may be nullptr, in which case the default RenderProcessHost will
+ // be created (this is the behavior if you don't call this function). The
+ // factory must be set back to nullptr before it's destroyed; ownership is not
+ // transferred.
+ static void set_render_process_host_factory_for_testing(
const RenderProcessHostFactory* rph_factory);
+ // Gets the global factory used to create new RenderProcessHosts in unit
+ // tests.
+ static const RenderProcessHostFactory*
+ get_render_process_host_factory_for_testing();
// Tracks which sites frames are hosted in which RenderProcessHosts.
static void AddFrameWithSite(BrowserContext* browser_context,
@@ -391,9 +385,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
RenderProcessHost* render_process_host,
const GURL& site_url);
- viz::SharedBitmapAllocationNotifierImpl* GetSharedBitmapAllocationNotifier()
- override;
-
// Return the spare RenderProcessHost, if it exists. There is at most one
// globally-used spare RenderProcessHost at any time.
static RenderProcessHost* GetSpareRenderProcessHostForTesting();
@@ -411,10 +402,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
bool is_initialized() const { return is_initialized_; }
- // Binds Mojo request to Mojo implementation CacheStorageDispatcherHost
- // instance, binding is sent to IO thread.
- void BindCacheStorage(blink::mojom::CacheStorageRequest request,
- const url::Origin& origin);
+ // Ensures that this process is kept alive for the specified amount of time.
+ // This is used to ensure that unload handlers have a chance to execute
+ // before the process shuts down.
+ void DelayProcessShutdownForUnload(const base::TimeDelta& timeout);
protected:
// A proxy for our IPC::Channel that lives on the IO thread.
@@ -486,13 +477,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
void BindRouteProvider(mojom::RouteProviderAssociatedRequest request);
- void CreateOffscreenCanvasProvider(
- blink::mojom::OffscreenCanvasProviderRequest request);
+ void CreateEmbeddedFrameSinkProvider(
+ blink::mojom::EmbeddedFrameSinkProviderRequest request);
void BindFrameSinkProvider(mojom::FrameSinkProviderRequest request);
void BindCompositingModeReporter(
viz::mojom::CompositingModeReporterRequest request);
- void BindSharedBitmapAllocationNotifier(
- viz::mojom::SharedBitmapAllocationNotifierRequest request);
void CreateStoragePartitionService(
mojom::StoragePartitionServiceRequest request);
void CreateRendererHost(mojom::RendererHostAssociatedRequest request);
@@ -529,7 +518,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
void CreateSharedRendererHistogramAllocator();
// Handle termination of our process.
- void ProcessDied(bool already_dead, RendererClosedDetails* known_details);
+ void ProcessDied(bool already_dead,
+ ChildProcessTerminationInfo* known_details);
// Destroy all objects that can cause methods to be invoked on this object or
// any other that hang off it.
@@ -566,7 +556,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
BrowserContext* browser_context,
const GURL& site_url);
-#if BUILDFLAG(ENABLE_WEBRTC)
void CreateMediaStreamDispatcherHost(
MediaStreamManager* media_stream_manager,
mojom::MediaStreamDispatcherHostRequest request);
@@ -585,7 +574,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
base::FilePath GetAecDumpFilePathWithExtensions(const base::FilePath& file);
base::SequencedTaskRunner& GetAecDumpFileTaskRunner();
void OnAec3Enabled();
-#endif
static void OnMojoError(int render_process_id, const std::string& error);
@@ -620,6 +608,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
}
+ // Callback to unblock process shutdown after waiting for unload handlers to
+ // execute.
+ void CancelProcessShutdownDelayForUnload();
+
std::unique_ptr<mojo::edk::OutgoingBrokerClientInvitation>
broker_client_invitation_;
@@ -633,7 +625,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
// TODO(panicker): Remove these after investigation in
// https://crbug.com/823482.
- static const size_t kNumKeepAliveClients = 3;
+ static const size_t kNumKeepAliveClients = 4;
size_t keep_alive_client_count_[kNumKeepAliveClients];
base::TimeTicks keep_alive_client_start_time_[kNumKeepAliveClients];
@@ -687,14 +679,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<RenderFrameMessageFilter> render_frame_message_filter_;
- // The filter for Web Notification messages coming from the renderer. Holds a
- // closure per notification that must be freed when the notification closes.
- scoped_refptr<NotificationMessageFilter> notification_message_filter_;
-
-#if defined(OS_ANDROID)
- scoped_refptr<SynchronousCompositorBrowserFilter>
- synchronous_compositor_filter_;
-#endif
+ // The filter for messages coming from the browser plugin.
+ scoped_refptr<BrowserPluginMessageFilter> bp_message_filter_;
// Used in single-process mode.
std::unique_ptr<base::Thread> in_process_renderer_;
@@ -769,7 +755,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
BrowserThread::DeleteOnIOThread>
audio_output_stream_factory_context_;
-#if BUILDFLAG(ENABLE_WEBRTC)
scoped_refptr<P2PSocketDispatcherHost> p2p_socket_dispatcher_host_;
// Must be accessed on UI thread.
@@ -783,7 +768,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
std::unique_ptr<MediaStreamTrackMetricsHost, BrowserThread::DeleteOnIOThread>
media_stream_track_metrics_host_;
-#endif
// Forwards messages between WebRTCInternals in the browser process
// and PeerConnectionTracker in the renderer process.
@@ -819,11 +803,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
#endif
scoped_refptr<ResourceMessageFilter> resource_message_filter_;
- std::unique_ptr<GpuClient, BrowserThread::DeleteOnIOThread> gpu_client_;
+ std::unique_ptr<GpuClientImpl, BrowserThread::DeleteOnIOThread> gpu_client_;
std::unique_ptr<PushMessagingManager, BrowserThread::DeleteOnIOThread>
push_messaging_manager_;
- std::unique_ptr<OffscreenCanvasProviderImpl> offscreen_canvas_provider_;
+ std::unique_ptr<EmbeddedFrameSinkProviderImpl> embedded_frame_sink_provider_;
mojom::ChildControlPtr child_control_interface_;
mojom::RouteProviderAssociatedPtr remote_route_provider_;
@@ -846,9 +830,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
std::unique_ptr<mojo::Binding<viz::mojom::CompositingModeReporter>>
compositing_mode_reporter_;
- viz::SharedBitmapAllocationNotifierImpl
- shared_bitmap_allocation_notifier_impl_;
-
base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
diff --git a/chromium/content/browser/renderer_host/render_view_host_impl.cc b/chromium/content/browser/renderer_host/render_view_host_impl.cc
index ff1e068349c..e8aa2e41e8a 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -15,7 +15,6 @@
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/json/json_reader.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
@@ -51,7 +50,6 @@
#include "content/common/inter_process_time_ticks_converter.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/common/renderer.mojom.h"
-#include "content/common/speech_recognition_messages.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/ax_event_notification_details.h"
@@ -337,17 +335,15 @@ bool RenderViewHostImpl::CreateRenderView(
params->has_committed_real_load =
main_rfh->frame_tree_node()->has_committed_real_load();
}
- params->enable_auto_resize = GetWidget()->auto_resize_enabled();
- params->min_size = GetWidget()->min_size_for_auto_resize();
- params->max_size = GetWidget()->max_size_for_auto_resize();
params->page_zoom_level = delegate_->GetPendingPageZoomLevel();
params->devtools_main_frame_token = devtools_frame_token;
// GuestViews in the same StoragePartition need to find each other's frames.
params->renderer_wide_named_frame_lookup =
GetSiteInstance()->GetSiteURL().SchemeIs(kGuestScheme);
- GetWidget()->GetResizeParams(&params->initial_size);
- GetWidget()->SetInitialRenderSizeParams(params->initial_size);
+ bool needs_ack = false;
+ GetWidget()->GetVisualProperties(&params->visual_properties, &needs_ack);
+ GetWidget()->SetInitialVisualProperties(params->visual_properties, needs_ack);
GetProcess()->GetRendererInterface()->CreateView(std::move(params));
@@ -562,10 +558,8 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
prefs.background_video_track_optimization_enabled =
base::FeatureList::IsEnabled(media::kBackgroundVideoTrackOptimization);
- if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo) &&
- base::FeatureList::IsEnabled(media::kPictureInPicture)) {
- prefs.picture_in_picture_enabled = true;
- }
+ prefs.picture_in_picture_enabled =
+ base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo);
GetContentClient()->browser()->OverrideWebkitPrefs(this, &prefs);
return prefs;
@@ -627,14 +621,14 @@ void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
delegate_->Close(this);
}
-void RenderViewHostImpl::RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {
+void RenderViewHostImpl::RenderProcessExited(
+ RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) {
if (!GetWidget()->renderer_initialized())
return;
- GetWidget()->RendererExited(status, exit_code);
- delegate_->RenderViewTerminated(this, status, exit_code);
+ GetWidget()->RendererExited(info.status, info.exit_code);
+ delegate_->RenderViewTerminated(this, info.status, info.exit_code);
}
bool RenderViewHostImpl::Send(IPC::Message* msg) {
@@ -725,8 +719,7 @@ void RenderViewHostImpl::RenderWidgetWillSetIsLoading(bool is_loading) {
}
bool RenderViewHostImpl::SuddenTerminationAllowed() const {
- return sudden_termination_allowed_ ||
- GetProcess()->SuddenTerminationAllowed();
+ return sudden_termination_allowed_;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/content/browser/renderer_host/render_view_host_impl.h b/chromium/content/browser/renderer_host/render_view_host_impl.h
index 890215a944a..f80c4c4330b 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -113,8 +113,7 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// RenderProcessHostObserver implementation
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override;
+ const ChildProcessTerminationInfo& info) override;
void set_delegate(RenderViewHostDelegate* d) {
CHECK(d); // http://crbug.com/82827
diff --git a/chromium/content/browser/renderer_host/render_view_host_unittest.cc b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
index 4127d8bdf82..5a0fe447e12 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -197,7 +197,7 @@ TEST_F(RenderViewHostTest, DragEnteredFileURLsStillBlocked) {
TEST_F(RenderViewHostTest, MessageWithBadHistoryItemFiles) {
base::FilePath file_path;
- EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file_path));
file_path = file_path.AppendASCII("foo");
EXPECT_EQ(0, process()->bad_msg_count());
test_rvh()->TestOnUpdateStateWithFile(file_path);
@@ -221,7 +221,7 @@ void SetBadFilePath(const GURL& url,
TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
GURL url("http://www.google.com");
base::FilePath file_path;
- EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file_path));
file_path = file_path.AppendASCII("bar");
auto set_bad_file_path_callback = base::Bind(SetBadFilePath, url, file_path);
@@ -280,13 +280,15 @@ class TestSaveImageFromDataURL : public RenderFrameMessageFilter {
protected:
~TestSaveImageFromDataURL() override {}
- void DownloadUrl(int render_view_id,
- int render_frame_id,
- const GURL& url,
- const Referrer& referrer,
- const url::Origin& initiator,
- const base::string16& suggested_name,
- const bool use_prompt) const override {
+ void DownloadUrl(
+ int render_view_id,
+ int render_frame_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const url::Origin& initiator,
+ const base::string16& suggested_name,
+ const bool use_prompt,
+ blink::mojom::BlobURLTokenPtrInfo blob_url_token) const override {
url_string_ = url.spec();
is_downloaded_ = true;
}
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.cc b/chromium/content/browser/renderer_host/render_widget_helper.cc
index 6a7e9eef132..c54233d8e1c 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.cc
+++ b/chromium/content/browser/renderer_host/render_widget_helper.cc
@@ -68,19 +68,6 @@ RenderWidgetHelper* RenderWidgetHelper::FromProcessHostID(
return (ci == g_widget_helpers.Get().end())? NULL : ci->second;
}
-void RenderWidgetHelper::ResumeDeferredNavigation(
- const GlobalRequestID& request_id) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&RenderWidgetHelper::OnResumeDeferredNavigation, this,
- request_id));
-}
-
-void RenderWidgetHelper::OnResumeDeferredNavigation(
- const GlobalRequestID& request_id) {
- resource_dispatcher_host_->ResumeDeferredNavigation(request_id);
-}
-
void RenderWidgetHelper::CreateNewWidget(int opener_id,
blink::WebPopupType popup_type,
mojom::WidgetPtr widget,
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.h b/chromium/content/browser/renderer_host/render_widget_helper.h
index 1fcb3097084..30012c94a8c 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.h
+++ b/chromium/content/browser/renderer_host/render_widget_helper.h
@@ -48,13 +48,6 @@ class RenderWidgetHelper
// store in a scoped_refptr.
static RenderWidgetHelper* FromProcessHostID(int render_process_host_id);
- // UI THREAD ONLY -----------------------------------------------------------
-
- // These two functions provide the backend implementation of the
- // corresponding functions in RenderProcessHost. See those declarations
- // for documentation.
- void ResumeDeferredNavigation(const GlobalRequestID& request_id);
-
// IO THREAD ONLY -----------------------------------------------------------
void CreateNewWidget(int opener_id,
blink::WebPopupType popup_type,
@@ -82,14 +75,6 @@ class RenderWidgetHelper
int32_t route_id,
mojom::WidgetPtrInfo widget);
- // Called on the IO thread to resume a paused navigation in the network
- // stack without transferring it to a new renderer process.
- void OnResumeDeferredNavigation(const GlobalRequestID& request_id);
-
- // Called on the IO thread to resume a navigation paused immediately after
- // receiving response headers.
- void OnResumeResponseDeferredAtStart(const GlobalRequestID& request_id);
-
int render_process_id_;
// The next routing id to use.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
index b55f1f1d126..2b5a683eb0c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
+
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -13,17 +15,25 @@
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "content/browser/bad_message.h"
+#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/latency/latency_info.h"
namespace content {
@@ -79,8 +89,8 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest,
// Submit the frame and expect the renderer to be instantly killed.
auto* const host = RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
RenderProcessHostKillWaiter waiter(host->GetProcess());
- host->SubmitCompositorFrame(viz::LocalSurfaceId(), std::move(frame), nullptr,
- 0);
+ host->SubmitCompositorFrame(viz::LocalSurfaceId(), std::move(frame),
+ base::nullopt, 0);
base::Optional<bad_message::BadMessageReason> result = waiter.Wait();
ASSERT_TRUE(result.has_value());
EXPECT_EQ(bad_message::RWH_COPY_REQUEST_ATTEMPT, *result);
@@ -92,4 +102,272 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest,
EXPECT_TRUE(did_receive_aborted_copy_result);
}
+class TestInputEventObserver : public RenderWidgetHost::InputEventObserver {
+ public:
+ using EventTypeVector = std::vector<blink::WebInputEvent::Type>;
+
+ ~TestInputEventObserver() override {}
+
+ void OnInputEvent(const blink::WebInputEvent& event) override {
+ dispatched_events_.push_back(event.GetType());
+ }
+
+ void OnInputEventAck(InputEventAckSource source,
+ InputEventAckState state,
+ const blink::WebInputEvent& event) override {
+ if (blink::WebInputEvent::IsTouchEventType(event.GetType()))
+ acked_touch_event_type_ = event.GetType();
+ }
+
+ EventTypeVector GetAndResetDispatchedEventTypes() {
+ EventTypeVector new_event_types;
+ std::swap(new_event_types, dispatched_events_);
+ return new_event_types;
+ }
+
+ blink::WebInputEvent::Type acked_touch_event_type() const {
+ return acked_touch_event_type_;
+ }
+
+ private:
+ EventTypeVector dispatched_events_;
+ blink::WebInputEvent::Type acked_touch_event_type_;
+};
+
+class RenderWidgetHostTouchEmulatorBrowserTest
+ : public RenderWidgetHostBrowserTest {
+ public:
+ RenderWidgetHostTouchEmulatorBrowserTest()
+ : view_(nullptr),
+ host_(nullptr),
+ router_(nullptr),
+ last_simulated_event_time_(ui::EventTimeForNow()),
+ simulated_event_time_delta_(base::TimeDelta::FromMilliseconds(100)) {}
+
+ void SetUpOnMainThread() override {
+ RenderWidgetHostBrowserTest::SetUpOnMainThread();
+
+ NavigateToURL(shell(),
+ GURL("data:text/html,<!doctype html>"
+ "<body style='background-color: red;'></body>"));
+
+ view_ = static_cast<RenderWidgetHostViewBase*>(
+ shell()->web_contents()->GetRenderWidgetHostView());
+ host_ = static_cast<RenderWidgetHostImpl*>(view_->GetRenderWidgetHost());
+ router_ = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetInputEventRouter();
+ ASSERT_TRUE(router_);
+ }
+
+ base::TimeTicks GetNextSimulatedEventTime() {
+ last_simulated_event_time_ += simulated_event_time_delta_;
+ return last_simulated_event_time_;
+ }
+
+ void SimulateRoutedMouseEvent(blink::WebInputEvent::Type type,
+ int x,
+ int y,
+ int modifiers,
+ bool pressed) {
+ blink::WebMouseEvent event =
+ SyntheticWebMouseEventBuilder::Build(type, x, y, modifiers);
+ if (pressed)
+ event.button = blink::WebMouseEvent::Button::kLeft;
+ event.SetTimeStamp(GetNextSimulatedEventTime());
+ router_->RouteMouseEvent(view_, &event, ui::LatencyInfo());
+ }
+
+ RenderWidgetHostImpl* host() { return host_; }
+
+ private:
+ RenderWidgetHostViewBase* view_;
+ RenderWidgetHostImpl* host_;
+ RenderWidgetHostInputEventRouter* router_;
+
+ base::TimeTicks last_simulated_event_time_;
+ base::TimeDelta simulated_event_time_delta_;
+};
+
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest,
+ TouchEmulator) {
+ // All touches will be immediately acked instead of sending them to the
+ // renderer since the test page does not have a touch handler.
+ host()->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
+
+ TestInputEventObserver observer;
+ host()->AddInputEventObserver(&observer);
+
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 10, 0, false);
+ TestInputEventObserver::EventTypeVector dispatched_events =
+ observer.GetAndResetDispatchedEventTypes();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // Mouse press becomes touch start which in turn becomes tap.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseDown, 10, 10, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapDown, dispatched_events[1]);
+
+ // Mouse drag generates touch move, cancels tap and starts scroll.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 30, 0, true);
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(4u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapCancel, dispatched_events[1]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollBegin, dispatched_events[2]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollUpdate, dispatched_events[3]);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+ EXPECT_EQ(0u, observer.GetAndResetDispatchedEventTypes().size());
+
+ // Mouse drag with shift becomes pinch.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 35,
+ blink::WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchBegin, dispatched_events[1]);
+
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 50,
+ blink::WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchUpdate, dispatched_events[1]);
+
+ // Mouse drag without shift becomes scroll again.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 60, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(3u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchEnd, dispatched_events[1]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollUpdate, dispatched_events[2]);
+
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 70, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollUpdate, dispatched_events[1]);
+
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseUp, 10, 70, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchEnd, observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchEnd, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollEnd, dispatched_events[1]);
+
+ // Mouse move does nothing.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 80, 0, false);
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ EXPECT_EQ(0u, dispatched_events.size());
+
+ // Another mouse down continues scroll.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseDown, 10, 80, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapDown, dispatched_events[1]);
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 100, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(4u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapCancel, dispatched_events[1]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollBegin, dispatched_events[2]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollUpdate, dispatched_events[3]);
+ EXPECT_EQ(0u, observer.GetAndResetDispatchedEventTypes().size());
+
+ // Another pinch.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 110,
+ blink::WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ EXPECT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchBegin, dispatched_events[1]);
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 120,
+ blink::WebInputEvent::kShiftKey, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ EXPECT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchUpdate, dispatched_events[1]);
+
+ // Turn off emulation during a pinch.
+ host()->GetTouchEmulator()->Disable();
+ EXPECT_EQ(blink::WebInputEvent::kTouchCancel,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(3u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchCancel, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGesturePinchEnd, dispatched_events[1]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollEnd, dispatched_events[2]);
+
+ // Mouse event should pass untouched.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 10,
+ blink::WebInputEvent::kShiftKey, true);
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(1u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kMouseMove, dispatched_events[0]);
+
+ // Turn on emulation.
+ host()->GetTouchEmulator()->Enable(
+ TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::GENERIC_MOBILE);
+
+ // Another touch.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseDown, 10, 10, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchStart, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapDown, dispatched_events[1]);
+
+ // Scroll.
+ SimulateRoutedMouseEvent(blink::WebInputEvent::kMouseMove, 10, 30, 0, true);
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove,
+ observer.acked_touch_event_type());
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(4u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchMove, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureTapCancel, dispatched_events[1]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollBegin, dispatched_events[2]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollUpdate, dispatched_events[3]);
+ EXPECT_EQ(0u, observer.GetAndResetDispatchedEventTypes().size());
+
+ // Turn off emulation during a scroll.
+ host()->GetTouchEmulator()->Disable();
+ EXPECT_EQ(blink::WebInputEvent::kTouchCancel,
+ observer.acked_touch_event_type());
+
+ dispatched_events = observer.GetAndResetDispatchedEventTypes();
+ ASSERT_EQ(2u, dispatched_events.size());
+ EXPECT_EQ(blink::WebInputEvent::kTouchCancel, dispatched_events[0]);
+ EXPECT_EQ(blink::WebInputEvent::kGestureScrollEnd, dispatched_events[1]);
+
+ host()->RemoveInputEventObserver(&observer);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.h b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
index 680b1e81320..f8a97cb4381 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -15,7 +15,7 @@
#include "content/common/drag_event_source_info.h"
#include "content/public/common/drop_data.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
+#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/gfx/native_widget_types.h"
@@ -77,8 +77,7 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// The contents auto-resized and the container should match it.
virtual void ResizeDueToAutoResize(RenderWidgetHostImpl* render_widget_host,
- const gfx::Size& new_size,
- uint64_t sequence_number) {}
+ const gfx::Size& new_size) {}
// Callback to give the browser a chance to handle the specified keyboard
// event before sending it to the renderer. See enum for details on return
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.cc b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
index 97ca37d843b..213f32e0891 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -48,11 +48,10 @@
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/display_util.h"
-#include "content/browser/renderer_host/frame_metadata_util.h"
#include "content/browser/renderer_host/frame_token_message_queue.h"
+#include "content/browser/renderer_host/input/fling_scheduler.h"
#include "content/browser/renderer_host/input/input_router_config_helper.h"
#include "content/browser/renderer_host/input/input_router_impl.h"
-#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
@@ -71,9 +70,9 @@
#include "content/common/frame_messages.h"
#include "content/common/input/sync_compositor_messages.h"
#include "content/common/input_messages.h"
-#include "content/common/resize_params.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
+#include "content/common/visual_properties.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/keyboard_event_processing_result.h"
@@ -82,6 +81,7 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_metadata_provider.h"
#include "content/public/browser/render_widget_host_iterator.h"
+#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
@@ -105,9 +105,6 @@
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/dom_code.h"
-#include "ui/events/keycodes/dom/keycode_converter.h"
-#include "ui/events/keycodes/keyboard_code_conversion.h"
-#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
@@ -122,6 +119,7 @@
#endif
#if defined(OS_MACOSX)
+#include "content/browser/renderer_host/input/fling_scheduler_mac.h"
#include "content/public/common/service_manager_connection.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
@@ -143,7 +141,7 @@ using blink::WebTextDirection;
namespace content {
namespace {
-bool g_check_for_pending_resize_ack = true;
+bool g_check_for_pending_visual_properties_ack = true;
// <process id, routing id>
using RenderWidgetHostID = std::pair<int32_t, int32_t>;
@@ -192,7 +190,7 @@ inline blink::WebGestureEvent CreateScrollBeginForWrapping(
blink::WebGestureEvent wrap_gesture_scroll_begin(
blink::WebInputEvent::kGestureScrollBegin, gesture_event.GetModifiers(),
- gesture_event.TimeStampSeconds(), gesture_event.SourceDevice());
+ gesture_event.TimeStamp(), gesture_event.SourceDevice());
wrap_gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0;
wrap_gesture_scroll_begin.data.scroll_begin.delta_y_hint = 0;
wrap_gesture_scroll_begin.resending_plugin_id =
@@ -209,7 +207,7 @@ inline blink::WebGestureEvent CreateScrollEndForWrapping(
blink::WebGestureEvent wrap_gesture_scroll_end(
blink::WebInputEvent::kGestureScrollEnd, gesture_event.GetModifiers(),
- gesture_event.TimeStampSeconds(), gesture_event.SourceDevice());
+ gesture_event.TimeStamp(), gesture_event.SourceDevice());
wrap_gesture_scroll_end.resending_plugin_id =
gesture_event.resending_plugin_id;
wrap_gesture_scroll_end.data.scroll_end.delta_units =
@@ -323,6 +321,8 @@ class UnboundWidgetInputHandler : public mojom::WidgetInputHandler {
}
};
+base::LazyInstance<UnboundWidgetInputHandler>::Leaky g_unbound_input_handler =
+ LAZY_INSTANCE_INITIALIZER;
} // namespace
///////////////////////////////////////////////////////////////////////////////
@@ -342,8 +342,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
clock_(base::DefaultTickClock::GetInstance()),
is_loading_(false),
is_hidden_(hidden),
- repaint_ack_pending_(false),
- resize_ack_pending_(false),
+ visual_properties_ack_pending_(false),
auto_resize_enabled_(false),
waiting_for_screen_rects_ack_(false),
needs_repainting_on_restore_(false),
@@ -360,7 +359,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
is_last_unlocked_by_target_(false),
has_touch_handler_(false),
is_in_touchpad_gesture_fling_(false),
- latency_tracker_(true, delegate_),
+ latency_tracker_(delegate_),
next_browser_snapshot_id_(1),
owned_by_render_frame_host_(false),
is_focused_(false),
@@ -372,10 +371,22 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
compositor_frame_sink_binding_(this),
frame_token_message_queue_(
std::make_unique<FrameTokenMessageQueue>(this)),
- render_frame_metadata_provider_(frame_token_message_queue_.get()),
+ render_frame_metadata_provider_(
+#if defined(OS_MACOSX)
+ ui::WindowResizeHelperMac::Get()->task_runner(),
+#else
+ base::ThreadTaskRunnerHandle::Get(),
+#endif
+ frame_token_message_queue_.get()),
frame_sink_id_(base::checked_cast<uint32_t>(process_->GetID()),
base::checked_cast<uint32_t>(routing_id_)),
weak_factory_(this) {
+#if defined(OS_MACOSX)
+ auto fling_scheduler = std::make_unique<FlingSchedulerMac>(this);
+ fling_scheduler_ = std::move(fling_scheduler);
+#else
+ fling_scheduler_ = std::make_unique<FlingScheduler>(this);
+#endif
CHECK(delegate_);
CHECK_NE(MSG_ROUTING_NONE, routing_id_);
DCHECK(base::TaskScheduler::GetInstance())
@@ -387,12 +398,10 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
CHECK(result.second) << "Inserting a duplicate item!";
process_->AddRoute(routing_id_, this);
process_->AddWidget(this);
- process_->GetSharedBitmapAllocationNotifier()->AddObserver(this);
latency_tracker_.Initialize(routing_id_, GetProcess()->GetID());
SetupInputRouter();
- touch_emulator_.reset();
SetWidget(std::move(widget));
const auto* command_line = base::CommandLine::ForCurrentProcess();
@@ -412,9 +421,11 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
enable_viz_ = base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
delegate_->RenderWidgetCreated(this);
+ render_frame_metadata_provider_.AddObserver(this);
}
RenderWidgetHostImpl::~RenderWidgetHostImpl() {
+ render_frame_metadata_provider_.RemoveObserver(this);
if (!destroyed_)
Destroy(false);
}
@@ -514,15 +525,9 @@ const viz::FrameSinkId& RenderWidgetHostImpl::GetFrameSinkId() const {
return frame_sink_id_;
}
-void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
- resize_ack_pending_ = false;
- if (repaint_ack_pending_) {
- TRACE_EVENT_ASYNC_END0(
- "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
- }
- repaint_ack_pending_ = false;
- if (old_resize_params_)
- old_resize_params_->new_size = gfx::Size();
+void RenderWidgetHostImpl::ResetSentVisualProperties() {
+ visual_properties_ack_pending_ = false;
+ old_visual_properties_.reset();
}
void RenderWidgetHostImpl::SendScreenRects() {
@@ -565,7 +570,7 @@ void RenderWidgetHostImpl::Init() {
renderer_initialized_ = true;
SendScreenRects();
- WasResized();
+ SynchronizeVisualProperties();
if (owner_delegate_)
owner_delegate_->RenderWidgetDidInit();
@@ -601,13 +606,8 @@ bool RenderWidgetHostImpl::IsLoading() const {
bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
// Only process most messages if the RenderWidget is alive.
- if (!renderer_initialized()) {
- // SetNeedsBeginFrame messages are only sent by the renderer once and so
- // should never be dropped.
- if (msg.type() == SyncCompositorHostMsg_SetNeedsBeginFrames::ID && view_)
- return view_->OnMessageReceived(msg);
+ if (!renderer_initialized())
return false;
- }
if (owner_delegate_ && owner_delegate_->OnMessageReceived(msg))
return true;
@@ -616,14 +616,11 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostImpl, msg)
IPC_MESSAGE_HANDLER(FrameHostMsg_RenderProcessGone, OnRenderProcessGone)
IPC_MESSAGE_HANDLER(FrameHostMsg_HittestData, OnHittestData)
- IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
- OnImeCancelComposition)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateScreenRects_ACK,
OnUpdateScreenRectsAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ResizeOrRepaint_ACK, OnResizeOrRepaintACK)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(ViewHostMsg_AutoscrollStart, OnAutoscrollStart)
IPC_MESSAGE_HANDLER(ViewHostMsg_AutoscrollFling, OnAutoscrollFling)
@@ -636,8 +633,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnShowDisambiguationPopup)
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
OnSelectionBoundsChanged)
- IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
- OnImeCompositionRangeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
@@ -678,6 +673,10 @@ void RenderWidgetHostImpl::WasHidden() {
TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::WasHidden");
is_hidden_ = true;
+ // Unthrottle SynchronizeVisualProperties IPCs so that the first call after
+ // show goes through immediately.
+ visual_properties_ack_pending_ = false;
+
// Don't bother reporting hung state when we aren't active.
StopHangMonitorTimeout();
@@ -693,6 +692,8 @@ void RenderWidgetHostImpl::WasHidden() {
NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
Source<RenderWidgetHost>(this),
Details<bool>(&is_visible));
+ for (auto& observer : observers_)
+ observer.RenderWidgetHostVisibilityChanged(this, false);
}
void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
@@ -721,23 +722,29 @@ void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
Source<RenderWidgetHost>(this),
Details<bool>(&is_visible));
+ for (auto& observer : observers_)
+ observer.RenderWidgetHostVisibilityChanged(this, true);
// It's possible for our size to be out of sync with the renderer. The
// following is one case that leads to this:
- // 1. WasResized -> Send ViewMsg_Resize to render
- // 2. WasResized -> do nothing as resize_ack_pending_ is true
+ // 1. SynchronizeVisualProperties -> Send ViewMsg_SynchronizeVisualProperties
+ // to render.
+ // 2. SynchronizeVisualProperties -> do nothing as
+ // sync_visual_props_ack_pending_ is true
// 3. WasHidden
- // 4. OnResizeOrRepaintACK from (1) processed. Does NOT invoke WasResized as
- // view is hidden. Now renderer/browser out of sync with what they think
- // size is.
- // By invoking WasResized the renderer is updated as necessary. WasResized
- // does nothing if the sizes are already in sync.
+ // 4. OnResizeOrRepaintACK from (1) processed. Does NOT invoke
+ // SynchronizeVisualProperties as view is hidden. Now renderer/browser out
+ // of sync with what they think size is.
+ // By invoking SynchronizeVisualProperties the renderer is updated as
+ // necessary. SynchronizeVisualProperties does nothing if the sizes are
+ // already in sync.
//
// TODO: ideally ViewMsg_WasShown would take a size. This way, the renderer
// could handle both the restore and resize at once. This isn't that big a
// deal as RenderWidget::WasShown delays updating, so that the resize from
- // WasResized is usually processed before the renderer is painted.
- WasResized();
+ // SynchronizeVisualProperties is usually processed before the renderer is
+ // painted.
+ SynchronizeVisualProperties();
}
#if defined(OS_ANDROID)
@@ -749,148 +756,171 @@ void RenderWidgetHostImpl::SetImportance(ChildProcessImportance importance) {
}
#endif
-bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
- *resize_params = ResizeParams();
+bool RenderWidgetHostImpl::GetVisualProperties(
+ VisualProperties* visual_properties,
+ bool* needs_ack) {
+ *visual_properties = VisualProperties();
- GetScreenInfo(&resize_params->screen_info);
+ GetScreenInfo(&visual_properties->screen_info);
if (delegate_) {
- resize_params->is_fullscreen_granted =
+ visual_properties->is_fullscreen_granted =
delegate_->IsFullscreenForCurrentTab();
- resize_params->display_mode = delegate_->GetDisplayMode(this);
+ visual_properties->display_mode = delegate_->GetDisplayMode(this);
} else {
- resize_params->is_fullscreen_granted = false;
- resize_params->display_mode = blink::kWebDisplayModeBrowser;
+ visual_properties->is_fullscreen_granted = false;
+ visual_properties->display_mode = blink::kWebDisplayModeBrowser;
}
- resize_params->auto_resize_enabled = auto_resize_enabled_;
- resize_params->min_size_for_auto_resize = min_size_for_auto_resize_;
- resize_params->max_size_for_auto_resize = max_size_for_auto_resize_;
- resize_params->auto_resize_sequence_number =
- last_auto_resize_response_number_;
+ visual_properties->auto_resize_enabled = auto_resize_enabled_;
+ visual_properties->min_size_for_auto_resize = min_size_for_auto_resize_;
+ visual_properties->max_size_for_auto_resize = max_size_for_auto_resize_;
if (view_) {
- resize_params->new_size = view_->GetRequestedRendererSize();
- resize_params->compositor_viewport_pixel_size =
+ visual_properties->new_size = view_->GetRequestedRendererSize();
+ visual_properties->capture_sequence_number =
+ view_->GetCaptureSequenceNumber();
+ visual_properties->compositor_viewport_pixel_size =
view_->GetCompositorViewportPixelSize();
- resize_params->top_controls_height = view_->GetTopControlsHeight();
- resize_params->bottom_controls_height = view_->GetBottomControlsHeight();
+ visual_properties->top_controls_height = view_->GetTopControlsHeight();
+ visual_properties->bottom_controls_height =
+ view_->GetBottomControlsHeight();
if (IsUseZoomForDSFEnabled()) {
- float device_scale = resize_params->screen_info.device_scale_factor;
- resize_params->top_controls_height *= device_scale;
- resize_params->bottom_controls_height *= device_scale;
+ float device_scale = visual_properties->screen_info.device_scale_factor;
+ visual_properties->top_controls_height *= device_scale;
+ visual_properties->bottom_controls_height *= device_scale;
}
- resize_params->browser_controls_shrink_blink_size =
+ visual_properties->browser_controls_shrink_blink_size =
view_->DoBrowserControlsShrinkBlinkSize();
- resize_params->visible_viewport_size = view_->GetVisibleViewportSize();
+ visual_properties->visible_viewport_size = view_->GetVisibleViewportSize();
// TODO(ccameron): GetLocalSurfaceId is not synchronized with the device
// scale factor of the surface. Fix this.
viz::LocalSurfaceId local_surface_id = view_->GetLocalSurfaceId();
if (local_surface_id.is_valid())
- resize_params->local_surface_id = local_surface_id;
+ visual_properties->local_surface_id = local_surface_id;
}
- resize_params->content_source_id = current_content_source_id_;
-
if (screen_orientation_type_for_testing_) {
- resize_params->screen_info.orientation_type =
+ visual_properties->screen_info.orientation_type =
*screen_orientation_type_for_testing_;
}
if (screen_orientation_angle_for_testing_) {
- resize_params->screen_info.orientation_angle =
+ visual_properties->screen_info.orientation_angle =
*screen_orientation_angle_for_testing_;
}
const bool size_changed =
- !old_resize_params_ ||
- old_resize_params_->auto_resize_enabled !=
- resize_params->auto_resize_enabled ||
- (old_resize_params_->auto_resize_enabled &&
- (old_resize_params_->min_size_for_auto_resize !=
- resize_params->min_size_for_auto_resize ||
- old_resize_params_->max_size_for_auto_resize !=
- resize_params->max_size_for_auto_resize ||
- old_resize_params_->auto_resize_sequence_number !=
- resize_params->auto_resize_sequence_number)) ||
- (!old_resize_params_->auto_resize_enabled &&
- (old_resize_params_->new_size != resize_params->new_size ||
- (old_resize_params_->compositor_viewport_pixel_size.IsEmpty() &&
- !resize_params->compositor_viewport_pixel_size.IsEmpty())));
+ !old_visual_properties_ ||
+ old_visual_properties_->auto_resize_enabled !=
+ visual_properties->auto_resize_enabled ||
+ (old_visual_properties_->auto_resize_enabled &&
+ (old_visual_properties_->min_size_for_auto_resize !=
+ visual_properties->min_size_for_auto_resize ||
+ old_visual_properties_->max_size_for_auto_resize !=
+ visual_properties->max_size_for_auto_resize)) ||
+ (!old_visual_properties_->auto_resize_enabled &&
+ (old_visual_properties_->new_size != visual_properties->new_size ||
+ (old_visual_properties_->compositor_viewport_pixel_size.IsEmpty() &&
+ !visual_properties->compositor_viewport_pixel_size.IsEmpty())));
+
+ viz::LocalSurfaceId old_parent_local_surface_id =
+ old_visual_properties_
+ ? old_visual_properties_->local_surface_id.value_or(
+ viz::LocalSurfaceId())
+ : viz::LocalSurfaceId();
+
+ viz::LocalSurfaceId new_parent_local_surface_id =
+ visual_properties->local_surface_id.value_or(viz::LocalSurfaceId());
+
+ const bool parent_local_surface_id_changed =
+ !old_visual_properties_ ||
+ old_parent_local_surface_id.parent_sequence_number() !=
+ new_parent_local_surface_id.parent_sequence_number() ||
+ old_parent_local_surface_id.embed_token() !=
+ new_parent_local_surface_id.embed_token();
bool dirty =
- size_changed ||
- old_resize_params_->screen_info != resize_params->screen_info ||
- old_resize_params_->compositor_viewport_pixel_size !=
- resize_params->compositor_viewport_pixel_size ||
- old_resize_params_->is_fullscreen_granted !=
- resize_params->is_fullscreen_granted ||
- old_resize_params_->display_mode != resize_params->display_mode ||
- old_resize_params_->top_controls_height !=
- resize_params->top_controls_height ||
- old_resize_params_->browser_controls_shrink_blink_size !=
- resize_params->browser_controls_shrink_blink_size ||
- old_resize_params_->bottom_controls_height !=
- resize_params->bottom_controls_height ||
- old_resize_params_->visible_viewport_size !=
- resize_params->visible_viewport_size ||
- (enable_surface_synchronization_ &&
- old_resize_params_->content_source_id !=
- resize_params->content_source_id) ||
- (enable_surface_synchronization_ &&
- old_resize_params_->local_surface_id != resize_params->local_surface_id);
-
- // We don't expect to receive an ACK when the requested size or the physical
- // backing size is empty, or when the main viewport size didn't change.
- resize_params->needs_resize_ack =
- !auto_resize_enabled_ && g_check_for_pending_resize_ack &&
- !resize_params->new_size.IsEmpty() &&
- !resize_params->compositor_viewport_pixel_size.IsEmpty() &&
- (size_changed || next_resize_needs_resize_ack_) &&
- (!enable_surface_synchronization_ ||
- (resize_params->local_surface_id.has_value() &&
- resize_params->local_surface_id->is_valid()));
+ size_changed || parent_local_surface_id_changed ||
+ old_visual_properties_->screen_info != visual_properties->screen_info ||
+ old_visual_properties_->compositor_viewport_pixel_size !=
+ visual_properties->compositor_viewport_pixel_size ||
+ old_visual_properties_->is_fullscreen_granted !=
+ visual_properties->is_fullscreen_granted ||
+ old_visual_properties_->display_mode != visual_properties->display_mode ||
+ old_visual_properties_->top_controls_height !=
+ visual_properties->top_controls_height ||
+ old_visual_properties_->browser_controls_shrink_blink_size !=
+ visual_properties->browser_controls_shrink_blink_size ||
+ old_visual_properties_->bottom_controls_height !=
+ visual_properties->bottom_controls_height ||
+ old_visual_properties_->visible_viewport_size !=
+ visual_properties->visible_viewport_size ||
+ old_visual_properties_->capture_sequence_number !=
+ visual_properties->capture_sequence_number;
+
+ // We should throttle sending updated VisualProperties to the renderer to
+ // the rate of commit. This ensures we don't overwhelm the renderer with
+ // visual updates faster than it can keep up. |needs_ack| corresponds to
+ // cases where a commit is expected.
+ *needs_ack = g_check_for_pending_visual_properties_ack &&
+ !visual_properties->auto_resize_enabled &&
+ !visual_properties->new_size.IsEmpty() &&
+ !visual_properties->compositor_viewport_pixel_size.IsEmpty() &&
+ visual_properties->local_surface_id && size_changed;
return dirty;
}
-void RenderWidgetHostImpl::SetInitialRenderSizeParams(
- const ResizeParams& resize_params) {
- resize_ack_pending_ = resize_params.needs_resize_ack;
+void RenderWidgetHostImpl::SetInitialVisualProperties(
+ const VisualProperties& visual_properties,
+ bool needs_ack) {
+ visual_properties_ack_pending_ = needs_ack;
+ old_visual_properties_ =
+ std::make_unique<VisualProperties>(visual_properties);
+}
- old_resize_params_ = std::make_unique<ResizeParams>(resize_params);
+bool RenderWidgetHostImpl::SynchronizeVisualProperties() {
+ return SynchronizeVisualProperties(false);
}
-void RenderWidgetHostImpl::WasResized() {
- WasResized(false);
+void RenderWidgetHostImpl::SynchronizeVisualPropertiesIgnoringPendingAck() {
+ visual_properties_ack_pending_ = false;
+ SynchronizeVisualProperties();
}
-void RenderWidgetHostImpl::WasResized(bool scroll_focused_node_into_view) {
+bool RenderWidgetHostImpl::SynchronizeVisualProperties(
+ bool scroll_focused_node_into_view) {
// Skip if the |delegate_| has already been detached because
// it's web contents is being deleted.
- if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
- !view_->HasSize() || !renderer_initialized_ || !delegate_ ||
- last_auto_resize_request_number_ != last_auto_resize_response_number_) {
- return;
+ if (visual_properties_ack_pending_ || !process_->HasConnection() || !view_ ||
+ !view_->HasSize() || !renderer_initialized_ || !delegate_) {
+ return false;
}
- std::unique_ptr<ResizeParams> params(new ResizeParams);
- if (!GetResizeParams(params.get()))
- return;
- params->scroll_focused_node_into_view = scroll_focused_node_into_view;
+ std::unique_ptr<VisualProperties> visual_properties(new VisualProperties);
+ bool needs_ack = false;
+ if (!GetVisualProperties(visual_properties.get(), &needs_ack))
+ return false;
+ visual_properties->scroll_focused_node_into_view =
+ scroll_focused_node_into_view;
- ScreenInfo screen_info = params->screen_info;
+ ScreenInfo screen_info = visual_properties->screen_info;
bool width_changed =
- !old_resize_params_ ||
- old_resize_params_->new_size.width() != params->new_size.width();
- if (Send(new ViewMsg_Resize(routing_id_, *params))) {
- resize_ack_pending_ = params->needs_resize_ack;
- next_resize_needs_resize_ack_ = false;
- old_resize_params_.swap(params);
+ !old_visual_properties_ || old_visual_properties_->new_size.width() !=
+ visual_properties->new_size.width();
+ bool sent_visual_properties = false;
+ if (Send(new ViewMsg_SynchronizeVisualProperties(routing_id_,
+ *visual_properties))) {
+ visual_properties_ack_pending_ = needs_ack;
+ old_visual_properties_.swap(visual_properties);
+ sent_visual_properties = true;
}
if (delegate_)
delegate_->RenderWidgetWasResized(this, screen_info, width_changed);
+
+ return sent_visual_properties;
}
void RenderWidgetHostImpl::GotFocus() {
@@ -940,8 +970,8 @@ void RenderWidgetHostImpl::SetPageFocus(bool focused) {
if (IsKeyboardLocked())
UnlockKeyboard();
- if (touch_emulator_)
- touch_emulator_->CancelTouch();
+ if (auto* touch_emulator = GetExistingTouchEmulator())
+ touch_emulator->CancelTouch();
} else if (keyboard_lock_allowed_) {
LockKeyboard();
}
@@ -955,8 +985,8 @@ void RenderWidgetHostImpl::SetPageFocus(bool focused) {
}
void RenderWidgetHostImpl::LostCapture() {
- if (touch_emulator_)
- touch_emulator_->CancelTouch();
+ if (auto* touch_emulator = GetExistingTouchEmulator())
+ touch_emulator->CancelTouch();
GetWidgetInputHandler()->MouseCaptureLost();
@@ -996,7 +1026,7 @@ void RenderWidgetHostImpl::PauseForPendingResizeOrRepaints() {
return;
// Do not pause if there is not a paint or resize already coming.
- if (!repaint_ack_pending_ && !resize_ack_pending_)
+ if (!visual_properties_ack_pending_)
return;
// OnResizeOrRepaintACK posts a task to the default TaskRunner in auto-resize,
@@ -1051,19 +1081,11 @@ void RenderWidgetHostImpl::PauseForPendingResizeOrRepaints() {
}
#endif
-bool RenderWidgetHostImpl::ScheduleComposite() {
- if (is_hidden_ || current_size_.IsEmpty() || repaint_ack_pending_ ||
- resize_ack_pending_) {
+bool RenderWidgetHostImpl::RequestRepaintForTesting() {
+ if (!view_)
return false;
- }
- // Send out a request to the renderer to paint the view if required.
- repaint_start_time_ = clock_->NowTicks();
- repaint_ack_pending_ = true;
- TRACE_EVENT_ASYNC_BEGIN0(
- "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
- Send(new ViewMsg_Repaint(routing_id_, current_size_));
- return true;
+ return view_->RequestRepaintForTesting();
}
void RenderWidgetHostImpl::ProcessIgnoreInputEventsChanged(
@@ -1112,10 +1134,9 @@ void RenderWidgetHostImpl::DidNavigate(uint32_t next_source_id) {
if (enable_surface_synchronization_) {
// Resize messages before navigation are not acked, so reset
- // |resize_ack_pending_| and make sure the next resize will be acked if the
- // last resize before navigation was supposed to be acked.
- next_resize_needs_resize_ack_ = resize_ack_pending_;
- resize_ack_pending_ = false;
+ // |visual_properties_ack_pending_| and make sure the next resize will be
+ // acked if the last resize before navigation was supposed to be acked.
+ visual_properties_ack_pending_ = false;
if (view_)
view_->DidNavigate();
} else {
@@ -1166,8 +1187,11 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
if (ShouldDropInputEvents())
return;
- if (touch_emulator_ && touch_emulator_->HandleMouseEvent(mouse_event))
+ auto* touch_emulator = GetExistingTouchEmulator();
+ if (touch_emulator &&
+ touch_emulator->HandleMouseEvent(mouse_event, GetView())) {
return;
+ }
MouseEventWithLatencyInfo mouse_with_latency(mouse_event, latency);
DispatchInputEventWithLatencyInfo(mouse_event, &mouse_with_latency.latency);
@@ -1189,7 +1213,8 @@ void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
if (ShouldDropInputEvents())
return;
- if (touch_emulator_ && touch_emulator_->HandleMouseWheelEvent(wheel_event))
+ auto* touch_emulator = GetExistingTouchEmulator();
+ if (touch_emulator && touch_emulator->HandleMouseWheelEvent(wheel_event))
return;
MouseWheelEventWithLatencyInfo wheel_with_latency(wheel_event, latency);
@@ -1330,12 +1355,11 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
}
void RenderWidgetHostImpl::ForwardEmulatedTouchEvent(
- const blink::WebTouchEvent& touch_event) {
+ const blink::WebTouchEvent& touch_event,
+ RenderWidgetHostViewBase* target) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardEmulatedTouchEvent");
- ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
- TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
- DispatchInputEventWithLatencyInfo(touch_event, &touch_with_latency.latency);
- input_router_->SendTouchEvent(touch_with_latency);
+ ForwardTouchEventWithLatencyInfo(touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
}
void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
@@ -1347,15 +1371,6 @@ void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
// ignored if appropriate in FilterInputEvent().
TouchEventWithLatencyInfo touch_with_latency(touch_event, latency);
- if (touch_emulator_ &&
- touch_emulator_->HandleTouchEvent(touch_with_latency.event)) {
- if (view_) {
- view_->ProcessAckedTouchEvent(
- touch_with_latency, INPUT_EVENT_ACK_STATE_CONSUMED);
- }
- return;
- }
-
DispatchInputEventWithLatencyInfo(touch_event, &touch_with_latency.latency);
input_router_->SendTouchEvent(touch_with_latency);
}
@@ -1437,6 +1452,9 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
switch (delegate_->PreHandleKeyboardEvent(key_event)) {
case KeyboardEventProcessingResult::HANDLED:
return;
+ case KeyboardEventProcessingResult::HANDLED_WANTS_KEY_UP:
+ suppress_events_until_keydown_ = false;
+ return;
#if defined(USE_AURA)
case KeyboardEventProcessingResult::HANDLED_DONT_UPDATE_EVENT:
if (update_event)
@@ -1454,7 +1472,8 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
suppress_events_until_keydown_ = false;
}
- if (touch_emulator_ && touch_emulator_->HandleKeyboardEvent(key_event))
+ auto* touch_emulator = GetExistingTouchEmulator();
+ if (touch_emulator && touch_emulator->HandleKeyboardEvent(key_event))
return;
NativeWebKeyboardEventWithLatencyInfo key_event_with_latency(key_event,
latency);
@@ -1462,8 +1481,8 @@ void RenderWidgetHostImpl::ForwardKeyboardEventWithCommands(
DispatchInputEventWithLatencyInfo(key_event, &key_event_with_latency.latency);
// TODO(foolip): |InputRouter::SendKeyboardEvent()| may filter events, in
// which the commands will be treated as belonging to the next key event.
- // InputMsg_SetEditCommandsForNextKeyEvent should only be sent if
- // InputMsg_HandleInputEvent is, but has to be sent first.
+ // WidgetInputHandler::SetEditCommandsForNextKeyEvent should only be sent if
+ // WidgetInputHandler::DispatchEvent is, but has to be sent first.
// https://crbug.com/684298
if (commands && !commands->empty()) {
GetWidgetInputHandler()->SetEditCommandsForNextKeyEvent(*commands);
@@ -1507,7 +1526,7 @@ int64_t RenderWidgetHostImpl::GetLatencyComponentId() const {
// static
void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
- g_check_for_pending_resize_ack = false;
+ g_check_for_pending_visual_properties_ack = false;
}
void RenderWidgetHostImpl::AddKeyPressEventCallback(
@@ -1552,6 +1571,14 @@ void RenderWidgetHostImpl::RemoveInputEventObserver(
input_event_observers_.RemoveObserver(observer);
}
+void RenderWidgetHostImpl::AddObserver(RenderWidgetHostObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void RenderWidgetHostImpl::RemoveObserver(RenderWidgetHostObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
void RenderWidgetHostImpl::GetScreenInfo(ScreenInfo* result) {
TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::GetScreenInfo");
if (view_)
@@ -1666,18 +1693,28 @@ mojom::WidgetInputHandler* RenderWidgetHostImpl::GetWidgetInputHandler() {
return associated_widget_input_handler_.get();
if (widget_input_handler_)
return widget_input_handler_.get();
- return legacy_widget_input_handler_.get();
+ // TODO(dtapuska): Remove the need for the unbound interface. It is
+ // possible that a RVHI may make calls to a WidgetInputHandler when
+ // the main frame is remote. This is because of ordering issues during
+ // widget shutdown, so we present an UnboundWidgetInputHandler had
+ // DLOGS the message calls.
+ return g_unbound_input_handler.Pointer();
}
void RenderWidgetHostImpl::NotifyScreenInfoChanged() {
// The resize message (which may not happen immediately) will carry with it
// the screen info as well as the new size (if the screen has changed scale
// factor).
- WasResized();
+ SynchronizeVisualProperties();
- if (touch_emulator_) {
- touch_emulator_->SetDeviceScaleFactor(GetScaleFactorForView(view_.get()));
- }
+ // The device scale factor will be same for all the views contained by the
+ // MainFrame, so just set it once.
+ if (delegate_ && !delegate_->IsWidgetForMainFrame(this))
+ return;
+
+ // The delegate may not have an input event router in tests.
+ if (auto* touch_emulator = GetExistingTouchEmulator())
+ touch_emulator->SetDeviceScaleFactor(GetScaleFactorForView(view_.get()));
}
void RenderWidgetHostImpl::GetSnapshotFromBrowser(
@@ -1687,8 +1724,7 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser(
if (from_surface) {
pending_surface_browser_snapshots_.insert(std::make_pair(id, callback));
ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT,
- 0, id);
+ latency_info.AddSnapshot(GetLatencyComponentId(), id);
Send(new ViewMsg_ForceRedraw(GetRoutingID(), latency_info));
return;
}
@@ -1700,10 +1736,10 @@ void RenderWidgetHostImpl::GetSnapshotFromBrowser(
if (pending_browser_snapshots_.empty())
GetWakeLock()->RequestWakeLock();
#endif
+ // TODO(nzolghadr): Remove the duplication here and the if block just above.
pending_browser_snapshots_.insert(std::make_pair(id, callback));
ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT, 0,
- id);
+ latency_info.AddSnapshot(GetLatencyComponentId(), id);
Send(new ViewMsg_ForceRedraw(GetRoutingID(), latency_info));
}
@@ -1812,8 +1848,7 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
suppress_events_until_keydown_ = false;
// Reset some fields in preparation for recovering from a crash.
- ResetSizeAndRepaintPendingFlags();
- current_size_.SetSize(0, 0);
+ ResetSentVisualProperties();
// After the renderer crashes, the view is destroyed and so the
// RenderWidgetHost cannot track its visibility anymore. We assume such
// RenderWidgetHost to be invisible for the sake of internal accounting - be
@@ -1937,6 +1972,8 @@ void RenderWidgetHostImpl::Destroy(bool also_delete) {
DCHECK(!destroyed_);
destroyed_ = true;
+ for (auto& observer : observers_)
+ observer.RenderWidgetHostDestroyed(this);
NotificationService::current()->Notify(
NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, Source<RenderWidgetHost>(this),
NotificationService::NoDetails());
@@ -1956,7 +1993,6 @@ void RenderWidgetHostImpl::Destroy(bool also_delete) {
for (const auto& id : owned_bitmaps_)
viz::ServerSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
- process_->GetSharedBitmapAllocationNotifier()->RemoveObserver(this);
process_->RemoveWidget(this);
process_->RemoveRoute(routing_id_);
g_routing_id_widget_map.Get().erase(
@@ -2001,12 +2037,12 @@ void RenderWidgetHostImpl::ClearDisplayedGraphics() {
void RenderWidgetHostImpl::OnGpuSwapBuffersCompletedInternal(
const ui::LatencyInfo& latency_info) {
- ui::LatencyInfo::LatencyComponent window_snapshot_component;
- if (latency_info.FindLatency(ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT,
- GetLatencyComponentId(),
- &window_snapshot_component)) {
- int sequence_number =
- static_cast<int>(window_snapshot_component.sequence_number);
+ // Note that a compromised renderer can send LatencyInfo to a
+ // RenderWidgetHostImpl other than its own. Be mindful of security
+ // implications of the code you add here.
+ if (latency_info.Snapshots().find(GetLatencyComponentId()) !=
+ latency_info.Snapshots().end()) {
+ int snapshot_id = latency_info.Snapshots().at(GetLatencyComponentId());
#if defined(OS_MACOSX) || defined(OS_WIN)
// On Mac, when using CoreAnimation, or Win32 when using GDI, there is a
// delay between when content is drawn to the screen, and when the
@@ -2016,14 +2052,12 @@ void RenderWidgetHostImpl::OnGpuSwapBuffersCompletedInternal(
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::Bind(&RenderWidgetHostImpl::WindowSnapshotReachedScreen,
- weak_factory_.GetWeakPtr(), sequence_number),
+ weak_factory_.GetWeakPtr(), snapshot_id),
TimeDelta::FromSecondsD(1. / 6));
#else
- WindowSnapshotReachedScreen(sequence_number);
+ WindowSnapshotReachedScreen(snapshot_id);
#endif
}
-
- latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
}
void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
@@ -2129,79 +2163,33 @@ void RenderWidgetHostImpl::DidDeleteSharedBitmap(
owned_bitmaps_.erase(id);
}
-void RenderWidgetHostImpl::OnResizeOrRepaintACK(
- const ViewHostMsg_ResizeOrRepaint_ACK_Params& params) {
- TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::OnResizeOrRepaintACK");
- TimeTicks paint_start = clock_->NowTicks();
+void RenderWidgetHostImpl::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
+ TRACE_EVENT0("renderer_host",
+ "RenderWidgetHostImpl::DidUpdateVisualProperties");
// Update our knowledge of the RenderWidget's size.
- current_size_ = params.view_size;
-
- bool is_resize_ack =
- ViewHostMsg_ResizeOrRepaint_ACK_Flags::is_resize_ack(params.flags);
-
- // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
- // that will end up reaching GetBackingStore.
- if (is_resize_ack) {
- DCHECK(!g_check_for_pending_resize_ack || resize_ack_pending_);
- resize_ack_pending_ = false;
- }
-
- bool is_repaint_ack =
- ViewHostMsg_ResizeOrRepaint_ACK_Flags::is_repaint_ack(params.flags);
- if (is_repaint_ack) {
- DCHECK(repaint_ack_pending_);
- TRACE_EVENT_ASYNC_END0(
- "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
- repaint_ack_pending_ = false;
- TimeDelta delta = clock_->NowTicks() - repaint_start_time_;
- UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta);
- }
-
- DCHECK(!params.view_size.IsEmpty());
-
- DidCompleteResizeOrRepaint(params, paint_start);
-
- last_auto_resize_request_number_ = params.sequence_number;
-
- if (auto_resize_enabled_) {
- bool post_callback = new_auto_size_.IsEmpty();
- new_auto_size_ = params.view_size;
- if (post_callback) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&RenderWidgetHostImpl::DelayedAutoResized,
- weak_factory_.GetWeakPtr()));
- }
- }
-
- // Log the time delta for processing a paint message. On platforms that don't
- // support asynchronous painting, this is equivalent to
- // MPArch.RWH_TotalPaintTime.
- TimeDelta delta = clock_->NowTicks() - paint_start;
- UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgResizeOrRepaintACK", delta);
-}
+ DCHECK(!metadata.viewport_size_in_pixels.IsEmpty());
-void RenderWidgetHostImpl::DidCompleteResizeOrRepaint(
- const ViewHostMsg_ResizeOrRepaint_ACK_Params& params,
- const TimeTicks& paint_start) {
- TRACE_EVENT0("renderer_host",
- "RenderWidgetHostImpl::DidCompleteResizeOrRepaint");
+ visual_properties_ack_pending_ = false;
NotificationService::current()->Notify(
- NOTIFICATION_RENDER_WIDGET_HOST_DID_COMPLETE_RESIZE_OR_REPAINT,
+ NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_VISUAL_PROPERTIES,
Source<RenderWidgetHost>(this), NotificationService::NoDetails());
- // We don't need to update the view if the view is hidden. We must do this
- // early return after the ACK is sent, however, or the renderer will not send
- // us more data.
- if (is_hidden_)
+ if (!view_ || is_hidden_)
return;
- // If we got a resize ack, then perhaps we have another resize to send?
- bool is_resize_ack =
- ViewHostMsg_ResizeOrRepaint_ACK_Flags::is_resize_ack(params.flags);
- if (is_resize_ack)
- WasResized();
+ viz::ScopedSurfaceIdAllocator scoped_allocator =
+ view_->DidUpdateVisualProperties(metadata);
+
+ if (auto_resize_enabled_ && delegate_) {
+ // TODO(fsamuel): The fact that we translate the viewport_size from pixels
+ // to DIP is concerning. This could result in invariants violations.
+ gfx::Size viewport_size_in_dip = gfx::ScaleToCeiledSize(
+ metadata.viewport_size_in_pixels, 1.f / metadata.device_scale_factor);
+ delegate_->ResizeDueToAutoResize(this, viewport_size_in_dip);
+ }
}
void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
@@ -2209,6 +2197,7 @@ void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
}
void RenderWidgetHostImpl::OnAutoscrollStart(const gfx::PointF& position) {
+ GetView()->OnAutoscrollStart();
WebGestureEvent scroll_begin = SyntheticWebGestureEventBuilder::Build(
WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceSyntheticAutoscroll);
@@ -2246,11 +2235,19 @@ void RenderWidgetHostImpl::OnAutoscrollEnd() {
}
TouchEmulator* RenderWidgetHostImpl::GetTouchEmulator() {
- if (!touch_emulator_) {
- touch_emulator_.reset(
- new TouchEmulator(this, GetScaleFactorForView(view_.get())));
+ if (!delegate_ || !delegate_->GetInputEventRouter())
+ return nullptr;
+
+ return delegate_->GetInputEventRouter()->GetTouchEmulator();
+}
+
+TouchEmulator* RenderWidgetHostImpl::GetExistingTouchEmulator() {
+ if (!delegate_ || !delegate_->GetInputEventRouter() ||
+ !delegate_->GetInputEventRouter()->has_touch_emulator()) {
+ return nullptr;
}
- return touch_emulator_.get();
+
+ return delegate_->GetInputEventRouter()->GetTouchEmulator();
}
void RenderWidgetHostImpl::OnTextInputStateChanged(
@@ -2271,6 +2268,15 @@ void RenderWidgetHostImpl::OnImeCancelComposition() {
view_->ImeCancelComposition();
}
+bool RenderWidgetHostImpl::IsWheelScrollInProgress() {
+ return is_in_gesture_scroll_[blink::kWebGestureDeviceTouchpad];
+}
+
+void RenderWidgetHostImpl::SetMouseCapture(bool capture) {
+ if (delegate_)
+ delegate_->GetInputEventRouter()->SetMouseCaptureTarget(GetView(), capture);
+}
+
void RenderWidgetHostImpl::OnInvalidFrameToken(uint32_t frame_token) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RWH_INVALID_FRAME_TOKEN);
@@ -2322,25 +2328,27 @@ void RenderWidgetHostImpl::OnUnlockMouse() {
is_last_unlocked_by_target_ = true;
}
-void RenderWidgetHostImpl::RequestKeyboardLock(
- base::Optional<base::flat_set<int>> keys_to_lock) {
+bool RenderWidgetHostImpl::RequestKeyboardLock(
+ base::Optional<base::flat_set<ui::DomCode>> codes) {
if (!delegate_) {
CancelKeyboardLock();
- return;
+ return false;
}
- DCHECK(!keys_to_lock.has_value() || !keys_to_lock.value().empty());
- keyboard_keys_to_lock_ = std::move(keys_to_lock);
+ DCHECK(!codes.has_value() || !codes.value().empty());
+ keyboard_keys_to_lock_ = std::move(codes);
keyboard_lock_requested_ = true;
- const int esc_native_key_code =
- ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::ESCAPE);
const bool esc_requested =
!keyboard_keys_to_lock_.has_value() ||
- base::ContainsKey(keyboard_keys_to_lock_.value(), esc_native_key_code);
+ base::ContainsKey(keyboard_keys_to_lock_.value(), ui::DomCode::ESCAPE);
- if (!delegate_->RequestKeyboardLock(this, esc_requested))
+ if (!delegate_->RequestKeyboardLock(this, esc_requested)) {
CancelKeyboardLock();
+ return false;
+ }
+
+ return true;
}
void RenderWidgetHostImpl::CancelKeyboardLock() {
@@ -2354,6 +2362,13 @@ void RenderWidgetHostImpl::CancelKeyboardLock() {
keyboard_keys_to_lock_.reset();
}
+base::flat_map<std::string, std::string>
+RenderWidgetHostImpl::GetKeyboardLayoutMap() {
+ if (!view_)
+ return {};
+ return view_->GetKeyboardLayoutMap();
+}
+
void RenderWidgetHostImpl::OnShowDisambiguationPopup(
const gfx::Rect& rect_pixels,
const gfx::Size& size,
@@ -2545,8 +2560,10 @@ void RenderWidgetHostImpl::OnGestureEventAck(
for (auto& input_event_observer : input_event_observers_)
input_event_observer.OnInputEventAck(ack_source, ack_result, event.event);
- if (touch_emulator_)
- touch_emulator_->OnGestureEventAck(event.event);
+ // If the TouchEmulator didn't exist when this GestureEvent was sent, we
+ // shouldn't create it here.
+ if (auto* touch_emulator = GetExistingTouchEmulator())
+ touch_emulator->OnGestureEventAck(event.event, GetView());
if (view_)
view_->GestureEventAck(event.event, ack_result);
@@ -2560,8 +2577,9 @@ void RenderWidgetHostImpl::OnTouchEventAck(
for (auto& input_event_observer : input_event_observers_)
input_event_observer.OnInputEventAck(ack_source, ack_result, event.event);
- if (touch_emulator_ &&
- touch_emulator_->HandleTouchEventAck(event.event, ack_result)) {
+ auto* touch_emulator = GetExistingTouchEmulator();
+ if (touch_emulator &&
+ touch_emulator->HandleTouchEventAck(event.event, ack_result)) {
return;
}
@@ -2617,38 +2635,11 @@ void RenderWidgetHostImpl::GotResponseToKeyboardLockRequest(bool allowed) {
UnlockKeyboard();
}
-void RenderWidgetHostImpl::DelayedAutoResized() {
- gfx::Size new_size = new_auto_size_;
- // Clear the new_auto_size_ since the empty value is used as a flag to
- // indicate that no callback is in progress (i.e. without this line
- // DelayedAutoResized will not get called again).
- new_auto_size_.SetSize(0, 0);
- if (!auto_resize_enabled_)
- return;
-
- if (view_) {
- viz::ScopedSurfaceIdAllocator scoped_allocator =
- view_->ResizeDueToAutoResize(new_size,
- last_auto_resize_request_number_);
-
- if (delegate_) {
- delegate_->ResizeDueToAutoResize(this, new_size,
- last_auto_resize_request_number_);
- }
- }
-}
-
void RenderWidgetHostImpl::DetachDelegate() {
delegate_ = nullptr;
latency_tracker_.reset_delegate();
}
-void RenderWidgetHostImpl::DidAllocateLocalSurfaceIdForAutoResize(
- uint64_t sequence_number) {
- last_auto_resize_response_number_ = sequence_number;
- WasResized();
-}
-
void RenderWidgetHostImpl::DidReceiveRendererFrame() {
view_->DidReceiveRendererFrame();
}
@@ -2737,27 +2728,35 @@ void RenderWidgetHostImpl::OnSnapshotReceived(int snapshot_id,
}
// static
+void RenderWidgetHostImpl::NotifyCorrespondingRenderWidgetHost(
+ int64_t frame_id,
+ std::set<RenderWidgetHostImpl*>& notified_hosts,
+ const ui::LatencyInfo& latency_info) {
+ // Matches with GetLatencyComponentId.
+ int routing_id = frame_id & 0xffffffff;
+ int process_id = (frame_id >> 32) & 0xffffffff;
+ RenderWidgetHost* rwh = RenderWidgetHost::FromID(process_id, routing_id);
+ if (!rwh)
+ return;
+ RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
+ if (notified_hosts.insert(rwhi).second)
+ rwhi->OnGpuSwapBuffersCompletedInternal(latency_info);
+}
+
+// static
void RenderWidgetHostImpl::OnGpuSwapBuffersCompleted(
const std::vector<ui::LatencyInfo>& latency_info) {
for (size_t i = 0; i < latency_info.size(); i++) {
std::set<RenderWidgetHostImpl*> rwhi_set;
for (const auto& lc : latency_info[i].latency_components()) {
if (lc.first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
- lc.first.first == ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT ||
- lc.first.first == ui::TAB_SHOW_COMPONENT) {
- // Matches with GetLatencyComponentId
- int routing_id = lc.first.second & 0xffffffff;
- int process_id = (lc.first.second >> 32) & 0xffffffff;
- RenderWidgetHost* rwh =
- RenderWidgetHost::FromID(process_id, routing_id);
- if (!rwh) {
- continue;
- }
- RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
- if (rwhi_set.insert(rwhi).second)
- rwhi->OnGpuSwapBuffersCompletedInternal(latency_info[i]);
- }
+ lc.first.first == ui::TAB_SHOW_COMPONENT)
+ NotifyCorrespondingRenderWidgetHost(lc.first.second, rwhi_set,
+ latency_info[i]);
}
+ for (const auto& snapshot : latency_info[i].Snapshots())
+ NotifyCorrespondingRenderWidgetHost(snapshot.first, rwhi_set,
+ latency_info[i]);
}
}
@@ -2791,13 +2790,7 @@ void RenderWidgetHostImpl::RequestCompositionUpdates(bool immediate_request,
void RenderWidgetHostImpl::RequestCompositorFrameSink(
viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request,
- viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client,
- mojom::RenderFrameMetadataObserverClientRequest
- render_frame_metadata_observer_client_request,
- mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer) {
- render_frame_metadata_provider_.Bind(
- std::move(render_frame_metadata_observer_client_request),
- std::move(render_frame_metadata_observer));
+ viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client) {
if (enable_viz_) {
// Connects the viz process end of CompositorFrameSink message pipes. The
// renderer compositor may request a new CompositorFrameSink on context
@@ -2833,6 +2826,15 @@ void RenderWidgetHostImpl::RequestCompositorFrameSink(
renderer_compositor_frame_sink_ = std::move(compositor_frame_sink_client);
}
+void RenderWidgetHostImpl::RegisterRenderFrameMetadataObserver(
+ mojom::RenderFrameMetadataObserverClientRequest
+ render_frame_metadata_observer_client_request,
+ mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer) {
+ render_frame_metadata_provider_.Bind(
+ std::move(render_frame_metadata_observer_client_request),
+ std::move(render_frame_metadata_observer));
+}
+
bool RenderWidgetHostImpl::HasGestureStopped() {
return !input_router_->HasPendingEvents();
}
@@ -2851,10 +2853,19 @@ void RenderWidgetHostImpl::SetWantsAnimateOnlyBeginFrames() {
view_->SetWantsAnimateOnlyBeginFrames();
}
+void RenderWidgetHostImpl::SubmitCompositorFrameSync(
+ const viz::LocalSurfaceId& local_surface_id,
+ viz::CompositorFrame frame,
+ base::Optional<viz::HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ const SubmitCompositorFrameSyncCallback callback) {
+ NOTIMPLEMENTED();
+}
+
void RenderWidgetHostImpl::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list,
+ base::Optional<viz::HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
"SubmitCompositorFrame", local_surface_id.hash());
@@ -2914,29 +2925,6 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
return;
}
- uint32_t max_sequence_number = 0;
- for (const auto& resource : frame.resource_list) {
- max_sequence_number =
- std::max(max_sequence_number, resource.shared_bitmap_sequence_number);
- }
-
- // If the CompositorFrame references SharedBitmaps that we are not aware of,
- // defer the submission until they are registered.
- uint32_t last_registered_sequence_number =
- GetProcess()->GetSharedBitmapAllocationNotifier()->last_sequence_number();
- if (max_sequence_number > last_registered_sequence_number) {
- saved_frame_.frame = std::move(frame);
- saved_frame_.local_surface_id = local_surface_id;
- saved_frame_.max_shared_bitmap_sequence_number = max_sequence_number;
- saved_frame_.hit_test_region_list = std::move(hit_test_region_list);
- TRACE_EVENT_ASYNC_BEGIN2("renderer_host", "PauseCompositorFrameSink", this,
- "LastRegisteredSequenceNumber",
- last_registered_sequence_number,
- "RequiredSequenceNumber", max_sequence_number);
- compositor_frame_sink_binding_.PauseIncomingMethodCallProcessing();
- return;
- }
-
last_local_surface_id_ = local_surface_id;
last_surface_properties_ = new_surface_properties;
@@ -2947,13 +2935,6 @@ void RenderWidgetHostImpl::SubmitCompositorFrame(
last_frame_metadata_ = frame.metadata.Clone();
- latency_tracker_.OnSwapCompositorFrame(&frame.metadata.latency_info);
-
- bool is_mobile_optimized = IsMobileOptimizedFrame(frame.metadata);
- input_router_->NotifySiteIsMobileOptimized(is_mobile_optimized);
- if (touch_emulator_)
- touch_emulator_->SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
-
if (enable_surface_synchronization_) {
if (view_) {
// If Surface Synchronization is on, then |new_content_rendering_timeout_|
@@ -3031,47 +3012,14 @@ device::mojom::WakeLock* RenderWidgetHostImpl::GetWakeLock() {
}
#endif
-void RenderWidgetHostImpl::OnSharedBitmapAllocatedByChild(
- uint32_t sequence_number) {
- if (saved_frame_.local_surface_id.is_valid() &&
- sequence_number >= saved_frame_.max_shared_bitmap_sequence_number) {
- bool tracing_enabled;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(
- TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), &tracing_enabled);
- SubmitCompositorFrame(
- saved_frame_.local_surface_id, std::move(saved_frame_.frame),
- std::move(saved_frame_.hit_test_region_list),
- tracing_enabled ? clock_->NowTicks().since_origin().InMicroseconds()
- : 0);
- saved_frame_.local_surface_id = viz::LocalSurfaceId();
- compositor_frame_sink_binding_.ResumeIncomingMethodCallProcessing();
- TRACE_EVENT_ASYNC_END0("renderer_host", "PauseCompositorFrameSink", this);
- }
-}
-
void RenderWidgetHostImpl::SetupInputRouter() {
in_flight_event_count_ = 0;
StopHangMonitorTimeout();
associated_widget_input_handler_ = nullptr;
widget_input_handler_ = nullptr;
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- input_router_.reset(
- new InputRouterImpl(this, this, GetInputRouterConfigForPlatform()));
- // TODO(dtapuska): Remove the need for the unbound interface. It is
- // possible that a RVHI may make calls to a WidgetInputHandler when
- // the main frame is remote. This is because of ordering issues during
- // widget shutdown, so we present an UnboundWidgetInputHandler had
- // DLOGS the message calls.
- legacy_widget_input_handler_ =
- std::make_unique<UnboundWidgetInputHandler>();
- } else {
- input_router_.reset(new LegacyInputRouterImpl(
- process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
- legacy_widget_input_handler_ =
- std::make_unique<LegacyIPCWidgetInputHandler>(
- static_cast<LegacyInputRouterImpl*>(input_router_.get()));
- }
+ input_router_.reset(new InputRouterImpl(this, this, fling_scheduler_.get(),
+ GetInputRouterConfigForPlatform()));
// input_router_ recreated, need to update the force_enable_zoom_ state.
input_router_->SetForceEnableZoom(force_enable_zoom_);
@@ -3089,10 +3037,8 @@ void RenderWidgetHostImpl::SetForceEnableZoom(bool enabled) {
void RenderWidgetHostImpl::SetWidgetInputHandler(
mojom::WidgetInputHandlerAssociatedPtr widget_input_handler,
mojom::WidgetInputHandlerHostRequest host_request) {
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- associated_widget_input_handler_ = std::move(widget_input_handler);
- input_router_->BindHost(std::move(host_request), true);
- }
+ associated_widget_input_handler_ = std::move(widget_input_handler);
+ input_router_->BindHost(std::move(host_request), true);
}
void RenderWidgetHostImpl::SetInputTargetClient(
@@ -3101,7 +3047,7 @@ void RenderWidgetHostImpl::SetInputTargetClient(
}
void RenderWidgetHostImpl::SetWidget(mojom::WidgetPtr widget) {
- if (widget && base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
+ if (widget) {
// If we have a bound handler ensure that we destroy the old input router.
if (widget_input_handler_.get())
SetupInputRouter();
@@ -3115,10 +3061,9 @@ void RenderWidgetHostImpl::SetWidget(mojom::WidgetPtr widget) {
}
}
-void RenderWidgetHostImpl::ProgressFling(TimeTicks current_time) {
+void RenderWidgetHostImpl::ProgressFlingIfNeeded(TimeTicks current_time) {
browser_fling_needs_begin_frame_ = false;
- if (input_router_)
- input_router_->ProgressFling(current_time);
+ fling_scheduler_->ProgressFlingOnBeginFrameIfneeded(current_time);
}
void RenderWidgetHostImpl::DidReceiveFirstFrameAfterNavigation() {
@@ -3132,10 +3077,11 @@ void RenderWidgetHostImpl::DidReceiveFirstFrameAfterNavigation() {
}
void RenderWidgetHostImpl::ForceFirstFrameAfterNavigationTimeout() {
- if (did_receive_first_frame_after_navigation_)
+ if (did_receive_first_frame_after_navigation_ ||
+ !new_content_rendering_timeout_) {
return;
- if (new_content_rendering_timeout_)
- new_content_rendering_timeout_->Stop();
+ }
+ new_content_rendering_timeout_->Stop();
ClearDisplayedGraphics();
}
@@ -3156,7 +3102,7 @@ void RenderWidgetHostImpl::SetScreenOrientationForTesting(
ScreenOrientationValues type) {
screen_orientation_angle_for_testing_ = angle;
screen_orientation_type_for_testing_ = type;
- WasResized();
+ SynchronizeVisualProperties();
}
// TODO(ericrk): On Android, with surface synchronization enabled, we need to
@@ -3196,8 +3142,8 @@ bool RenderWidgetHostImpl::LockKeyboard() {
// KeyboardLock can be activated and deactivated several times per request,
// for example when a fullscreen tab loses and gains focus multiple times,
// so we need to retain a copy of the keys requested.
- base::Optional<base::flat_set<int>> copy_of_keys = keyboard_keys_to_lock_;
- return view_->LockKeyboard(std::move(copy_of_keys));
+ base::Optional<base::flat_set<ui::DomCode>> copy = keyboard_keys_to_lock_;
+ return view_->LockKeyboard(std::move(copy));
}
void RenderWidgetHostImpl::UnlockKeyboard() {
@@ -3205,4 +3151,18 @@ void RenderWidgetHostImpl::UnlockKeyboard() {
view_->UnlockKeyboard();
}
+void RenderWidgetHostImpl::OnRenderFrameMetadataChanged() {
+ bool is_mobile_optimized =
+ render_frame_metadata_provider_.LastRenderFrameMetadata()
+ .is_mobile_optimized;
+ input_router_->NotifySiteIsMobileOptimized(is_mobile_optimized);
+ if (auto* touch_emulator = GetExistingTouchEmulator())
+ touch_emulator->SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
+}
+
+void RenderWidgetHostImpl::OnLocalSurfaceIdChanged(
+ const cc::RenderFrameMetadata& metadata) {
+ DidUpdateVisualProperties(metadata);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.h b/chromium/content/browser/renderer_host/render_widget_host_impl.h
index e3f95d8623a..316385180c6 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -30,13 +30,12 @@
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "build/build_config.h"
+#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/frame_token_message_queue.h"
#include "content/browser/renderer_host/input/input_disposition_handler.h"
#include "content/browser/renderer_host/input/input_router_impl.h"
-#include "content/browser/renderer_host/input/legacy_ipc_widget_input_handler.h"
#include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
@@ -59,7 +58,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
+#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_types.h"
@@ -77,7 +76,6 @@
class SkBitmap;
struct FrameHostMsg_HittestData_Params;
struct ViewHostMsg_SelectionBounds_Params;
-struct ViewHostMsg_ResizeOrRepaint_ACK_Params;
namespace blink {
class WebInputEvent;
@@ -94,9 +92,14 @@ class Range;
class Vector2dF;
}
+namespace ui {
+enum class DomCode;
+}
+
namespace content {
class BrowserAccessibilityManager;
+class FlingScheduler;
class InputRouter;
class MockRenderWidgetHost;
class RenderWidgetHostOwnerDelegate;
@@ -105,7 +108,7 @@ class TimeoutMonitor;
class TouchEmulator;
class WebCursor;
struct EditCommand;
-struct ResizeParams;
+struct VisualProperties;
struct ScreenInfo;
struct TextInputState;
@@ -120,8 +123,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
public TouchEmulatorClient,
public SyntheticGestureController::Delegate,
public viz::mojom::CompositorFrameSink,
- public viz::SharedBitmapAllocationObserver,
- public IPC::Listener {
+ public IPC::Listener,
+ public RenderFrameMetadataProvider::Observer {
public:
// |routing_id| must not be MSG_ROUTING_NONE.
// If this object outlives |delegate|, DetachDelegate() must be called when
@@ -193,7 +196,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void RestartHangMonitorTimeoutIfNecessary() override;
bool IsCurrentlyUnresponsive() const override;
void SetIgnoreInputEvents(bool ignore_input_events) override;
- void WasResized() override;
+ bool SynchronizeVisualProperties() override;
void AddKeyPressEventCallback(const KeyPressEventCallback& callback) override;
void RemoveKeyPressEventCallback(
const KeyPressEventCallback& callback) override;
@@ -203,6 +206,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderWidgetHost::InputEventObserver* observer) override;
void RemoveInputEventObserver(
RenderWidgetHost::InputEventObserver* observer) override;
+ void AddObserver(RenderWidgetHostObserver* observer) override;
+ void RemoveObserver(RenderWidgetHostObserver* observer) override;
void GetScreenInfo(content::ScreenInfo* result) override;
// |drop_data| must have been filtered. The embedder should call
// FilterDropData before passing the drop data to RWHI.
@@ -261,8 +266,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderWidgetHostDelegate* delegate() const { return delegate_; }
- bool empty() const { return current_size_.IsEmpty(); }
-
// Called when a renderer object already been created for this host, and we
// just need to be attached to it. Used for window.open, <select> dropdown
// menus, and other times when the renderer initiates creating an object.
@@ -359,12 +362,14 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void PauseForPendingResizeOrRepaints();
#endif
- bool resize_ack_pending_for_testing() { return resize_ack_pending_; }
+ bool visual_properties_ack_pending_for_testing() {
+ return visual_properties_ack_pending_;
+ }
- // GPU accelerated version of GetBackingStore function. This will
- // trigger a re-composite to the view. It may fail if a resize is pending, or
- // if a composite has already been requested and not acked yet.
- bool ScheduleComposite();
+ // Requests the generation of a new CompositorFrame from the renderer.
+ // It will return false if the renderer is not ready (e.g. there's an
+ // in flight change).
+ bool RequestRepaintForTesting();
// Called by the RenderProcessHost to handle the case when the process
// changed its state of ignoring input events.
@@ -412,8 +417,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// TouchEmulatorClient implementation.
void ForwardEmulatedGestureEvent(
const blink::WebGestureEvent& gesture_event) override;
- void ForwardEmulatedTouchEvent(
- const blink::WebTouchEvent& touch_event) override;
+ void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& touch_event,
+ RenderWidgetHostViewBase* target) override;
void SetCursor(const WebCursor& cursor) override;
void ShowContextMenuAtPoint(const gfx::Point& point,
const ui::MenuSourceType source_type) override;
@@ -496,12 +501,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// mode.
void GotResponseToKeyboardLockRequest(bool allowed);
- // Resets state variables related to tracking pending size and painting.
- //
- // We need to reset these flags when we want to repaint the contents of
- // browser plugin in this RWH. Resetting these flags will ensure we ignore
- // any previous pending acks that are not relevant upon repaint.
- void ResetSizeAndRepaintPendingFlags();
+ // Resets state variables related to tracking pending updates to visual
+ // properties.
+ void ResetSentVisualProperties();
void DetachDelegate();
@@ -522,10 +524,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
return max_size_for_auto_resize_;
}
- // Called to notify the RenderWidget that a viz::LocalSurfaceId was allocated
- // for the auto-resize request specified by |sequence_number|.
- void DidAllocateLocalSurfaceIdForAutoResize(uint64_t sequence_number);
-
void DidReceiveRendererFrame();
// Returns the ID that uniquely describes this component to the latency
@@ -561,17 +559,24 @@ class CONTENT_EXPORT RenderWidgetHostImpl
const gfx::Size& min_size,
const gfx::Size& max_size);
- // Fills in the |resize_params| struct.
+ // Fills in the |visual_properties| struct.
// Returns |false| if the update is redundant, |true| otherwise.
- bool GetResizeParams(ResizeParams* resize_params);
+ bool GetVisualProperties(VisualProperties* visual_properties,
+ bool* needs_ack);
+
+ // Sets the |visual_properties| that were sent to the renderer bundled with
+ // the request to create a new RenderWidget.
+ void SetInitialVisualProperties(const VisualProperties& visual_properties,
+ bool needs_ack);
- // Sets the |resize_params| that were sent to the renderer bundled with the
- // request to create a new RenderWidget.
- void SetInitialRenderSizeParams(const ResizeParams& resize_params);
+ // Pushes updated visual properties to the renderer as well as whether the
+ // focused node should be scrolled into view.
+ bool SynchronizeVisualProperties(bool scroll_focused_node_into_view);
- // The RenderWidget was resized and whether the focused node should be
- // scrolled into view.
- void WasResized(bool scroll_focused_node_into_view);
+ // Similar to SynchronizeVisualProperties(), but performed even if
+ // |visual_properties_ack_pending_| is set. Used to guarantee that the
+ // latest visual properties are sent to the renderer before another IPC.
+ void SynchronizeVisualPropertiesIgnoringPendingAck();
// Called when we receive a notification indicating that the renderer process
// is gone. This will reset our state so that our state will be consistent if
@@ -606,7 +611,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void RequestCompositorFrameSink(
viz::mojom::CompositorFrameSinkRequest compositor_frame_sink_request,
- viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client,
+ viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client);
+
+ void RegisterRenderFrameMetadataObserver(
mojom::RenderFrameMetadataObserverClientRequest
render_frame_metadata_observer_client_request,
mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer);
@@ -615,10 +622,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
return last_frame_metadata_;
}
- uint64_t last_auto_resize_request_number() const {
- return last_auto_resize_request_number_;
- }
-
RenderFrameMetadataProviderImpl* render_frame_metadata_provider() {
return &render_frame_metadata_provider_;
}
@@ -631,8 +634,14 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list,
+ base::Optional<viz::HitTestRegionList> hit_test_region_list,
uint64_t submit_time) override;
+ void SubmitCompositorFrameSync(
+ const viz::LocalSurfaceId& local_surface_id,
+ viz::CompositorFrame frame,
+ base::Optional<viz::HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ const SubmitCompositorFrameSyncCallback callback) override;
void DidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
const viz::SharedBitmapId& id) override;
@@ -664,15 +673,18 @@ class CONTENT_EXPORT RenderWidgetHostImpl
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) override;
void OnImeCancelComposition() override;
+ bool IsWheelScrollInProgress() override;
+ void SetMouseCapture(bool capture) override;
// FrameTokenMessageQueue::Client:
void OnInvalidFrameToken(uint32_t frame_token) override;
void OnMessageDispatchError(const IPC::Message& message) override;
void OnProcessSwapMessage(const IPC::Message& message) override;
- void ProgressFling(base::TimeTicks current_time);
+ void ProgressFlingIfNeeded(base::TimeTicks current_time);
void StopFling();
bool FlingCancellationIsDeferred() const;
+ void SetNeedsBeginFrameForFlingProgress();
void DidReceiveFirstFrameAfterNavigation();
@@ -689,9 +701,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl
ScreenOrientationValues type);
// Requests Keyboard lock. Note: the lock may not take effect until later.
- // If |keys_to_lock| has no value then all keys will be locked, otherwise only
- // the keys specified will be intercepted and routed to the web page.
- void RequestKeyboardLock(base::Optional<base::flat_set<int>> keys_to_lock);
+ // If |codes| has no value then all keys will be locked, otherwise only the
+ // keys specified will be intercepted and routed to the web page.
+ // Returns true if the lock request was successfully registered.
+ bool RequestKeyboardLock(base::Optional<base::flat_set<ui::DomCode>> codes);
// Cancels a previous keyboard lock request.
void CancelKeyboardLock();
@@ -699,6 +712,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Indicates whether keyboard lock is active.
bool IsKeyboardLocked() const;
+ // Returns the keyboard layout mapping.
+ base::flat_map<std::string, std::string> GetKeyboardLayoutMap();
+
+ void DidStopFlinging() override;
+
void GetContentRenderingTimeoutFrom(RenderWidgetHostImpl* other);
protected:
@@ -746,18 +764,43 @@ class CONTENT_EXPORT RenderWidgetHostImpl
private:
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
DontPostponeHangMonitorTimeout);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, HiddenPaint);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, RendererExitedNoDrag);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
StopAndStartHangMonitorTimeout);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest,
ShorterDelayHangMonitorTimeout);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostTest, SynchronizeVisualProperties);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, AutoResizeWithScale);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
AutoResizeWithBrowserInitiatedResize);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, Resize);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewChildFrameTest,
+ ChildFrameAutoResizeUpdate);
FRIEND_TEST_ALL_PREFIXES(DevToolsManagerTest,
NoUnresponsiveDialogInInspectedContents);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ ChildAllocationAcceptedInParent);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ ConflictingAllocationsResolve);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewMacTest,
+ ChildAllocationAcceptedInParent);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewMacTest,
+ ConflictingAllocationsResolve);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ ResizeAndCrossProcessPostMessagePreserveOrder);
friend class MockRenderWidgetHost;
+ friend class OverscrollNavigationOverlayTest;
friend class TestRenderViewHost;
+ friend bool TestChildOrGuestAutoresize(bool,
+ RenderProcessHost*,
+ RenderWidgetHost*);
+
+ // Helper for notifying corresponding RenderWidgetHosts
+ static void NotifyCorrespondingRenderWidgetHost(
+ int64_t frame_id,
+ std::set<RenderWidgetHostImpl*>&,
+ const ui::LatencyInfo&);
// Tell this object to destroy itself. If |also_delete| is specified, the
// destructor is called as well.
@@ -782,8 +825,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void OnRequestMove(const gfx::Rect& pos);
void OnSetTooltipText(const base::string16& tooltip_text,
blink::WebTextDirection text_direction_hint);
- void OnResizeOrRepaintACK(
- const ViewHostMsg_ResizeOrRepaint_ACK_Params& params);
void OnSetCursor(const WebCursor& cursor);
void OnAutoscrollStart(const gfx::PointF& position);
void OnAutoscrollFling(const gfx::Vector2dF& velocity);
@@ -810,10 +851,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void OnFrameSwapMessagesReceived(uint32_t frame_token,
std::vector<IPC::Message> messages);
- // Called after resize or repaint has completed in the renderer.
- void DidCompleteResizeOrRepaint(
- const ViewHostMsg_ResizeOrRepaint_ACK_Params& params,
- const base::TimeTicks& paint_start);
+ // Called when visual properties have changed in the renderer.
+ void DidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
// Give key press listeners a chance to handle this key press. This allow
// widgets that don't have focus to still handle key presses.
@@ -827,20 +866,14 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void DecrementInFlightEventCount(InputEventAckSource ack_source) override;
void OnHasTouchEventHandlers(bool has_handlers) override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
- void DidStopFlinging() override;
void DidStartScrollingViewport() override;
void OnSetWhiteListedTouchAction(
cc::TouchAction white_listed_touch_action) override {}
- void SetNeedsBeginFrameForFlingProgress() override;
// Dispatch input events with latency information
void DispatchInputEventWithLatencyInfo(const blink::WebInputEvent& event,
ui::LatencyInfo* latency);
- // Called when there is a new auto resize (using a post to avoid a stack
- // which may get in recursive loops).
- void DelayedAutoResized();
-
void WindowSnapshotReachedScreen(int snapshot_id);
void OnSnapshotFromSurfaceReceived(int snapshot_id,
@@ -864,9 +897,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// responsive.
void StopHangMonitorTimeout();
- // viz::SharedBitmapAllocationObserver implementation.
- void OnSharedBitmapAllocatedByChild(
- uint32_t last_shared_bitmap_sequence_number) override;
void SetupInputRouter();
bool SurfacePropertiesMismatch(
@@ -883,6 +913,17 @@ class CONTENT_EXPORT RenderWidgetHostImpl
device::mojom::WakeLock* GetWakeLock();
#endif
+ // RenderFrameMetadataProvider::Observer implementation.
+ void OnRenderFrameMetadataChanged() override;
+ void OnRenderFrameSubmission() override {}
+ void OnLocalSurfaceIdChanged(
+ const cc::RenderFrameMetadata& metadata) override;
+
+ // Returns a pointer to the touch emulator serving this host, but only if it
+ // already exists; calling this function will not force creation of a
+ // TouchEmulator.
+ TouchEmulator* GetExistingTouchEmulator();
+
// true if a renderer has once been valid. We use this flag to display a sad
// tab only when we lose our renderer and not if a paint occurs during
// initialization.
@@ -924,20 +965,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
ChildProcessImportance importance_ = ChildProcessImportance::NORMAL;
#endif
- // Set if we are waiting for a repaint ack for the view.
- bool repaint_ack_pending_;
-
- // True when waiting for RESIZE_ACK.
- bool resize_ack_pending_;
+ // True when waiting for visual_properties_ack.
+ bool visual_properties_ack_pending_;
- // The current size of the RenderWidget.
- gfx::Size current_size_;
-
- // Resize information that was most recently sent to the renderer.
- std::unique_ptr<ResizeParams> old_resize_params_;
-
- // The next auto resize to send.
- gfx::Size new_auto_size_;
+ // Visual properties that were most recently sent to the renderer.
+ std::unique_ptr<VisualProperties> old_visual_properties_;
// True if the render widget host should track the render widget's size as
// opposed to visa versa.
@@ -949,9 +981,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// The maximum size for the render widget if auto-resize is enabled.
gfx::Size max_size_for_auto_resize_;
- uint64_t last_auto_resize_request_number_ = 0ul;
- uint64_t last_auto_resize_response_number_ = 0ul;
-
bool waiting_for_screen_rects_ack_;
gfx::Rect last_view_screen_rect_;
gfx::Rect last_window_screen_rect_;
@@ -966,6 +995,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
base::ObserverList<RenderWidgetHost::InputEventObserver>
input_event_observers_;
+ // The observers watching us.
+ base::ObserverList<RenderWidgetHostObserver> observers_;
+
// If true, then we should repaint when restoring even if we have a
// backingstore. This flag is set to true if we receive a paint message
// while is_hidden_ to true. Even though we tell the render widget to hide
@@ -1015,7 +1047,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
bool allow_privileged_mouse_lock_;
// Stores the keyboard keys to lock while waiting for a pending lock request.
- base::Optional<base::flat_set<int>> keyboard_keys_to_lock_;
+ base::Optional<base::flat_set<ui::DomCode>> keyboard_keys_to_lock_;
bool keyboard_lock_requested_ = false;
bool keyboard_lock_allowed_ = false;
@@ -1037,8 +1069,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
std::unique_ptr<SyntheticGestureController> synthetic_gesture_controller_;
- std::unique_ptr<TouchEmulator> touch_emulator_;
-
// Receives and handles all input events.
std::unique_ptr<InputRouter> input_router_;
@@ -1126,8 +1156,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
struct {
viz::LocalSurfaceId local_surface_id;
viz::CompositorFrame frame;
- uint32_t max_shared_bitmap_sequence_number = 0;
- viz::mojom::HitTestRegionListPtr hit_test_region_list;
+ base::Optional<viz::HitTestRegionList> hit_test_region_list;
} saved_frame_;
bool enable_surface_synchronization_ = false;
@@ -1140,7 +1169,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// a |widget_input_handler_|.
mojom::WidgetInputHandlerAssociatedPtr associated_widget_input_handler_;
mojom::WidgetInputHandlerPtr widget_input_handler_;
- std::unique_ptr<mojom::WidgetInputHandler> legacy_widget_input_handler_;
viz::mojom::InputTargetClientPtr input_target_client_;
base::Optional<uint16_t> screen_orientation_angle_for_testing_;
@@ -1151,14 +1179,14 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// ownership of the bitmaps with these ids to avoid leaking them.
std::set<viz::SharedBitmapId> owned_bitmaps_;
- bool next_resize_needs_resize_ack_ = false;
-
bool force_enable_zoom_ = false;
RenderFrameMetadataProviderImpl render_frame_metadata_provider_;
const viz::FrameSinkId frame_sink_id_;
+ std::unique_ptr<FlingScheduler> fling_scheduler_;
+
bool did_receive_first_frame_after_navigation_ = true;
base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc
index d9f001f9ff0..1ff58114735 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -11,17 +11,18 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "components/viz/common/features.h"
+#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/renderer_host/cursor_manager.h"
+#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/frame_messages.h"
-#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/base/layout.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -39,16 +40,16 @@ void TransformEventTouchPositions(blink::WebTouchEvent* event,
}
}
-blink::WebGestureEvent DummyGestureScrollUpdate(double timeStampSeconds) {
+blink::WebGestureEvent DummyGestureScrollUpdate(base::TimeTicks time_stamp) {
return blink::WebGestureEvent(blink::WebInputEvent::kGestureScrollUpdate,
- blink::WebInputEvent::kNoModifiers,
- timeStampSeconds);
+ blink::WebInputEvent::kNoModifiers, time_stamp);
}
viz::HitTestQuery* GetHitTestQuery(
viz::HostFrameSinkManager* host_frame_sink_manager,
const viz::FrameSinkId& frame_sink_id) {
- DCHECK(frame_sink_id.is_valid());
+ if (!frame_sink_id.is_valid())
+ return nullptr;
const auto& display_hit_test_query_map =
host_frame_sink_manager->display_hit_test_query();
const auto iter = display_hit_test_query_map.find(frame_sink_id);
@@ -61,10 +62,22 @@ gfx::PointF ComputePointInRootInPixels(
const gfx::PointF& point,
content::RenderWidgetHostViewBase* root_view,
float device_scale_factor) {
- gfx::PointF point_in_root = point + root_view->GetOffsetFromRootSurface();
+ gfx::PointF point_in_root = point;
+ root_view->TransformPointToRootSurface(&point_in_root);
return gfx::ConvertPointToPixel(device_scale_factor, point_in_root);
}
+bool IsMouseButtonDown(const blink::WebMouseEvent& event) {
+ constexpr int mouse_button_modifiers =
+ blink::WebInputEvent::kLeftButtonDown |
+ blink::WebInputEvent::kMiddleButtonDown |
+ blink::WebInputEvent::kRightButtonDown |
+ blink::WebInputEvent::kBackButtonDown |
+ blink::WebInputEvent::kForwardButtonDown;
+
+ return event.GetModifiers() & mouse_button_modifiers;
+}
+
} // anonymous namespace
namespace content {
@@ -86,6 +99,9 @@ void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
}
}
+ if (touch_emulator_)
+ touch_emulator_->OnViewDestroyed(view);
+
if (view == touch_target_.target) {
touch_target_.target = nullptr;
active_touches_ = 0;
@@ -180,8 +196,11 @@ bool RenderWidgetHostInputEventRouter::HittestDelegate::AcceptHitTarget(
}
RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
- : last_mouse_move_target_(nullptr),
+ : touchscreen_gesture_target_in_map_(false),
+ last_mouse_move_target_(nullptr),
last_mouse_move_root_view_(nullptr),
+ last_emulated_event_root_view_(nullptr),
+ last_device_scale_factor_(1.f),
active_touches_(0),
in_touchscreen_gesture_pinch_(false),
gesture_pinch_did_send_scroll_begin_(false),
@@ -200,30 +219,27 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindMouseEventTarget(
const blink::WebMouseEvent& event) const {
RenderWidgetHostViewBase* target = nullptr;
bool needs_transform_point = true;
+ bool latched_target = true;
if (root_view->IsMouseLocked()) {
target = root_view->host()->delegate()->GetMouseLockWidget()->GetView();
}
- constexpr int mouse_button_modifiers =
- blink::WebInputEvent::kLeftButtonDown |
- blink::WebInputEvent::kMiddleButtonDown |
- blink::WebInputEvent::kRightButtonDown |
- blink::WebInputEvent::kBackButtonDown |
- blink::WebInputEvent::kForwardButtonDown;
+ // Ignore mouse_capture_target_ if there are no mouse buttons currently down
+ // because this is only for the purpose of dragging.
if (!target && mouse_capture_target_.target &&
- event.GetType() != blink::WebInputEvent::kMouseDown &&
(event.GetType() == blink::WebInputEvent::kMouseUp ||
- event.GetModifiers() & mouse_button_modifiers)) {
+ IsMouseButtonDown(event))) {
target = mouse_capture_target_.target;
}
gfx::PointF transformed_point;
if (!target) {
+ latched_target = false;
auto result = FindViewAtLocation(
root_view, event.PositionInWidget(), event.PositionInScreen(),
viz::EventSource::MOUSE, &transformed_point);
if (result.should_query_view) {
- return {result.view, true, transformed_point};
+ return {result.view, true, transformed_point, latched_target};
}
target = result.view;
// |transformed_point| is already transformed.
@@ -231,13 +247,13 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindMouseEventTarget(
}
if (needs_transform_point) {
- if (!TransformPointToTargetCoordSpace(
- root_view, target, event.PositionInWidget(), &transformed_point,
+ if (!root_view->TransformPointToCoordSpaceForView(
+ event.PositionInWidget(), target, &transformed_point,
viz::EventSource::MOUSE)) {
- return {nullptr, false, base::nullopt};
+ return {nullptr, false, base::nullopt, latched_target};
}
}
- return {target, false, transformed_point};
+ return {target, false, transformed_point, latched_target};
}
RenderWidgetTargetResult
@@ -248,12 +264,12 @@ RenderWidgetHostInputEventRouter::FindMouseWheelEventTarget(
gfx::PointF transformed_point;
if (root_view->IsMouseLocked()) {
target = root_view->host()->delegate()->GetMouseLockWidget()->GetView();
- if (!TransformPointToTargetCoordSpace(
- root_view, target, event.PositionInWidget(), &transformed_point,
+ if (!root_view->TransformPointToCoordSpaceForView(
+ event.PositionInWidget(), target, &transformed_point,
viz::EventSource::MOUSE)) {
- return {nullptr, false, base::nullopt};
+ return {nullptr, false, base::nullopt, true};
}
- return {target, false, transformed_point};
+ return {target, false, transformed_point, true};
}
if (root_view->wheel_scroll_latching_enabled()) {
@@ -261,17 +277,17 @@ RenderWidgetHostInputEventRouter::FindMouseWheelEventTarget(
auto result = FindViewAtLocation(
root_view, event.PositionInWidget(), event.PositionInScreen(),
viz::EventSource::MOUSE, &transformed_point);
- return {result.view, result.should_query_view, transformed_point};
+ return {result.view, result.should_query_view, transformed_point, false};
}
// For non-begin events, the target found for the previous phaseBegan is
// used.
- return {nullptr, false, base::nullopt};
+ return {nullptr, false, base::nullopt, true};
}
auto result = FindViewAtLocation(root_view, event.PositionInWidget(),
event.PositionInScreen(),
viz::EventSource::MOUSE, &transformed_point);
- return {result.view, result.should_query_view, transformed_point};
+ return {result.view, result.should_query_view, transformed_point, false};
}
RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
@@ -284,7 +300,7 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
// hit testing.
if (owner_map_.size() <= 1) {
*transformed_point = point;
- return {root_view, false, *transformed_point};
+ return {root_view, false, *transformed_point, false};
}
viz::FrameSinkId frame_sink_id;
@@ -293,7 +309,7 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
viz::HitTestQuery* query = GetHitTestQuery(GetHostFrameSinkManager(),
root_view->GetRootFrameSinkId());
if (!query)
- return {root_view, false, base::nullopt};
+ return {root_view, false, base::nullopt, false};
// |point_in_screen| is in the coordinate space of of the screen, but the
// display HitTestQuery does a hit test in the coordinate space of the root
// window. The following translation should account for that discrepancy.
@@ -311,7 +327,7 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
} else {
*transformed_point = point;
}
- if (target.flags & viz::mojom::kHitTestAsk)
+ if (target.flags & viz::HitTestRegionFlags::kHitTestAsk)
query_renderer = true;
} else {
// The hittest delegate is used to reject hittesting quads based on extra
@@ -334,7 +350,7 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
*transformed_point = point;
}
- return {view, query_renderer, *transformed_point};
+ return {view, query_renderer, *transformed_point, false};
}
void RenderWidgetHostInputEventRouter::RouteMouseEvent(
@@ -355,10 +371,24 @@ void RenderWidgetHostInputEventRouter::DispatchMouseEvent(
if (!target)
return;
- if (mouse_event.GetType() == blink::WebInputEvent::kMouseUp)
+ // Implicitly release any capture when a MouseUp arrives, so that if any
+ // events arrive before the renderer can explicitly release capture, we can
+ // target those correctly. This also releases if there are no mouse buttons
+ // down, which is to protect against problems that can occur on some
+ // platforms where MouseUps are not received when the mouse cursor is off the
+ // browser window.
+ // Also, this is strictly necessary for touch emulation.
+ if (mouse_event.GetType() == blink::WebInputEvent::kMouseUp ||
+ !IsMouseButtonDown(mouse_event))
mouse_capture_target_.target = nullptr;
- else if (mouse_event.GetType() == blink::WebInputEvent::kMouseDown)
+
+ // When touch emulation is active, mouse events have to act like touch
+ // events, which requires that there be implicit capture between MouseDown
+ // and MouseUp.
+ if (mouse_event.GetType() == blink::WebInputEvent::kMouseDown &&
+ touch_emulator_ && touch_emulator_->enabled()) {
mouse_capture_target_.target = target;
+ }
DCHECK(target_location.has_value());
blink::WebMouseEvent event = mouse_event;
@@ -370,7 +400,7 @@ void RenderWidgetHostInputEventRouter::DispatchMouseEvent(
// notify the CursorManager that it might need to change the cursor.
if ((event.GetType() == blink::WebInputEvent::kMouseLeave ||
event.GetType() == blink::WebInputEvent::kMouseMove) &&
- target != last_mouse_move_target_) {
+ target != last_mouse_move_target_ && !root_view->IsMouseLocked()) {
SendMouseEnterOrLeaveEvents(mouse_event, target, root_view);
if (root_view->GetCursorManager())
root_view->GetCursorManager()->UpdateViewUnderCursor(target);
@@ -416,7 +446,7 @@ void RenderWidgetHostInputEventRouter::DispatchMouseWheelEvent(
// the wheel target view is destroyed and the wheel end event won't get
// processed.
blink::WebGestureEvent fake_scroll_update =
- DummyGestureScrollUpdate(mouse_wheel_event.TimeStampSeconds());
+ DummyGestureScrollUpdate(mouse_wheel_event.TimeStamp());
fake_scroll_update.SetSourceDevice(blink::kWebGestureDeviceTouchpad);
SendGestureScrollEnd(bubbling_gesture_scroll_target_.target,
fake_scroll_update);
@@ -527,7 +557,7 @@ RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindTouchEventTarget(
// Tests may call this without an initial TouchStart, so check event type
// explicitly here.
if (active_touches_ || event.GetType() != blink::WebInputEvent::kTouchStart)
- return {nullptr, false, base::nullopt};
+ return {nullptr, false, base::nullopt, true};
active_touches_ += CountChangedTouchPoints(event);
gfx::PointF original_point = gfx::PointF(event.touches[0].PositionInWidget());
@@ -587,9 +617,8 @@ void RenderWidgetHostInputEventRouter::DispatchTouchEvent(
if (is_sequence_start) {
if (touch_target_.target == bubbling_gesture_scroll_target_.target) {
- SendGestureScrollEnd(
- bubbling_gesture_scroll_target_.target,
- DummyGestureScrollUpdate(touch_event.TimeStampSeconds()));
+ SendGestureScrollEnd(bubbling_gesture_scroll_target_.target,
+ DummyGestureScrollUpdate(touch_event.TimeStamp()));
CancelScrollBubbling(bubbling_gesture_scroll_target_.target);
}
}
@@ -694,8 +723,8 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
// new compositor surface. The SurfaceID for that might not have
// propagated to its embedding surface, which makes it impossible to
// compute the transformation for it
- if (!TransformPointToTargetCoordSpace(
- root_view, view, event.PositionInWidget(), &transformed_point,
+ if (!root_view->TransformPointToCoordSpaceForView(
+ event.PositionInWidget(), view, &transformed_point,
viz::EventSource::MOUSE)) {
transformed_point = gfx::PointF();
}
@@ -708,9 +737,9 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
if (common_ancestor && common_ancestor != target) {
blink::WebMouseEvent mouse_move(event);
mouse_move.SetType(blink::WebInputEvent::kMouseMove);
- if (!TransformPointToTargetCoordSpace(
- root_view, common_ancestor, event.PositionInWidget(),
- &transformed_point, viz::EventSource::MOUSE)) {
+ if (!root_view->TransformPointToCoordSpaceForView(
+ event.PositionInWidget(), common_ancestor, &transformed_point,
+ viz::EventSource::MOUSE)) {
transformed_point = gfx::PointF();
}
mouse_move.SetPositionInWidget(transformed_point.x(),
@@ -724,8 +753,8 @@ void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
continue;
blink::WebMouseEvent mouse_enter(event);
mouse_enter.SetType(blink::WebInputEvent::kMouseMove);
- if (!TransformPointToTargetCoordSpace(
- root_view, view, event.PositionInWidget(), &transformed_point,
+ if (!root_view->TransformPointToCoordSpaceForView(
+ event.PositionInWidget(), view, &transformed_point,
viz::EventSource::MOUSE)) {
transformed_point = gfx::PointF();
}
@@ -944,8 +973,7 @@ void RenderWidgetHostInputEventRouter::SendGestureScrollEnd(
const blink::WebGestureEvent& event) {
blink::WebGestureEvent scroll_end(event);
scroll_end.SetType(blink::WebInputEvent::kGestureScrollEnd);
- scroll_end.SetTimeStampSeconds(
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF());
+ scroll_end.SetTimeStamp(base::TimeTicks::Now());
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin:
DCHECK(view->wheel_scroll_latching_enabled());
@@ -1046,7 +1074,7 @@ RenderWidgetHostInputEventRouter::FindTouchscreenGestureEventTarget(
// target we could just return nullptr for pinch events, but since we know
// where they are going we return the correct target.
if (blink::WebInputEvent::IsPinchGestureEventType(gesture_event.GetType()))
- return {root_view, false, base::nullopt};
+ return {root_view, false, gesture_event.PositionInWidget(), true};
// Android sends gesture events that have no corresponding touch sequence, so
// these we hit-test explicitly.
@@ -1061,7 +1089,16 @@ RenderWidgetHostInputEventRouter::FindTouchscreenGestureEventTarget(
// Remaining gesture events will defer to the gesture event target queue
// during dispatch.
- return {nullptr, false, base::nullopt};
+ return {nullptr, false, base::nullopt, true};
+}
+
+bool RenderWidgetHostInputEventRouter::IsViewInMap(
+ const RenderWidgetHostViewBase* view) const {
+ for (auto entry : owner_map_) {
+ if (entry.second == view)
+ return true;
+ }
+ return false;
}
void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
@@ -1150,6 +1187,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
// RenderWidgetTargeter. These gesture events should always have a
// unique_touch_event_id of 0.
touchscreen_gesture_target_.target = target;
+ touchscreen_gesture_target_in_map_ = IsViewInMap(target);
base::debug::SetCrashKeyString(target_source_key, "touch_id=0");
touchscreen_gesture_target_.delta =
target_location.has_value()
@@ -1176,19 +1214,21 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
// don't worry about the fact we're ignoring |result.should_query_view|, as
// this is the best we can do until we fix https://crbug.com/595422.
touchscreen_gesture_target_.target = result.view;
+ touchscreen_gesture_target_in_map_ = IsViewInMap(result.view);
base::debug::SetCrashKeyString(target_source_key, "no_matching_id");
touchscreen_gesture_target_.delta = transformed_point - original_point;
} else if (is_gesture_start) {
touchscreen_gesture_target_ = gesture_target_it->second;
touchscreen_gesture_target_map_.erase(gesture_target_it);
+ touchscreen_gesture_target_in_map_ =
+ IsViewInMap(touchscreen_gesture_target_.target);
// Abort any scroll bubbling in progress to avoid double entry.
if (touchscreen_gesture_target_.target &&
touchscreen_gesture_target_.target ==
bubbling_gesture_scroll_target_.target) {
- SendGestureScrollEnd(
- bubbling_gesture_scroll_target_.target,
- DummyGestureScrollUpdate(gesture_event.TimeStampSeconds()));
+ SendGestureScrollEnd(bubbling_gesture_scroll_target_.target,
+ DummyGestureScrollUpdate(gesture_event.TimeStamp()));
CancelScrollBubbling(bubbling_gesture_scroll_target_.target);
}
}
@@ -1208,6 +1248,21 @@ void RenderWidgetHostInputEventRouter::DispatchTouchscreenGestureEvent(
base::debug::SetCrashKeyString(
target_ptr_key,
base::StringPrintf("%p", touchscreen_gesture_target_.target));
+ static auto* root_ptr_key = base::debug::AllocateCrashKeyString(
+ "touchscreen-gesture-root-ptr", base::debug::CrashKeySize::Size64);
+ base::debug::SetCrashKeyString(root_ptr_key,
+ base::StringPrintf("%p", root_view));
+ static auto* target_ptr_in_map_key = base::debug::AllocateCrashKeyString(
+ "touchscreen-gesture-target-in-map", base::debug::CrashKeySize::Size32);
+ base::debug::SetCrashKeyString(
+ target_ptr_in_map_key,
+ touchscreen_gesture_target_in_map_ ? "true" : "false");
+ static auto* map_size_key = base::debug::AllocateCrashKeyString(
+ "touchscreen-gesture-map-size", base::debug::CrashKeySize::Size32);
+ base::debug::SetCrashKeyString(
+ map_size_key,
+ base::StringPrintf("%u", static_cast<int>(owner_map_.size())));
+
touchscreen_gesture_target_.target->ProcessGestureEvent(event, latency);
}
@@ -1225,7 +1280,7 @@ RenderWidgetHostInputEventRouter::FindTouchpadGestureEventTarget(
const blink::WebGestureEvent& event) const {
if (event.GetType() != blink::WebInputEvent::kGesturePinchBegin &&
event.GetType() != blink::WebInputEvent::kGestureFlingStart) {
- return {nullptr, false, base::nullopt};
+ return {nullptr, false, base::nullopt, true};
}
gfx::PointF transformed_point;
@@ -1265,7 +1320,7 @@ void RenderWidgetHostInputEventRouter::DispatchTouchpadGestureEvent(
bubbling_gesture_scroll_target_.target) {
SendGestureScrollEnd(
bubbling_gesture_scroll_target_.target,
- DummyGestureScrollUpdate(touchpad_gesture_event.TimeStampSeconds()));
+ DummyGestureScrollUpdate(touchpad_gesture_event.TimeStamp()));
CancelScrollBubbling(bubbling_gesture_scroll_target_.target);
}
}
@@ -1283,6 +1338,18 @@ void RenderWidgetHostInputEventRouter::DispatchTouchpadGestureEvent(
touchpad_gesture_target_.target->ProcessGestureEvent(gesture_event, latency);
}
+RenderWidgetHostViewBase*
+RenderWidgetHostInputEventRouter::FindViewFromFrameSinkId(
+ const viz::FrameSinkId& frame_sink_id) const {
+ // TODO(kenrb): There should be a better way to handle hit tests to surfaces
+ // that are no longer valid for hit testing. See https://crbug.com/790044.
+ auto iter = owner_map_.find(frame_sink_id);
+ // If the point hit a Surface whose namspace is no longer in the map, then
+ // it likely means the RenderWidgetHostView has been destroyed but its
+ // parent frame has not sent a new compositor frame since that happened.
+ return iter == owner_map_.end() ? nullptr : iter->second;
+}
+
std::vector<RenderWidgetHostView*>
RenderWidgetHostInputEventRouter::GetRenderWidgetHostViewsForTests() const {
std::vector<RenderWidgetHostView*> hosts;
@@ -1297,59 +1364,6 @@ RenderWidgetHostInputEventRouter::GetRenderWidgetTargeterForTests() {
return event_targeter_.get();
}
-bool RenderWidgetHostInputEventRouter::TransformPointToTargetCoordSpace(
- RenderWidgetHostViewBase* root_view,
- RenderWidgetHostViewBase* target,
- const gfx::PointF& point,
- gfx::PointF* transformed_point,
- viz::EventSource source) const {
- if (root_view == target) {
- *transformed_point = point;
- return true;
- }
-
- if (!use_viz_hit_test_) {
- return root_view->TransformPointToCoordSpaceForView(point, target,
- transformed_point);
- }
-
- viz::HitTestQuery* query = GetHitTestQuery(GetHostFrameSinkManager(),
- root_view->GetRootFrameSinkId());
- if (!query)
- return false;
-
- std::vector<viz::FrameSinkId> target_ancestors;
- target_ancestors.push_back(target->GetFrameSinkId());
- RenderWidgetHostViewBase* cur_view = target;
- while (cur_view->IsRenderWidgetHostViewChildFrame()) {
- if (cur_view->IsRenderWidgetHostViewGuest()) {
- cur_view = static_cast<RenderWidgetHostViewGuest*>(cur_view)
- ->GetOwnerRenderWidgetHostView();
- } else {
- cur_view = static_cast<RenderWidgetHostViewChildFrame*>(cur_view)
- ->GetParentView();
- }
- if (!cur_view)
- return false;
- target_ancestors.push_back(cur_view->GetFrameSinkId());
- }
- DCHECK_EQ(cur_view, root_view);
- target_ancestors.push_back(root_view->GetRootFrameSinkId());
-
- float device_scale_factor = root_view->GetDeviceScaleFactor();
- DCHECK_GT(device_scale_factor, 0.0f);
- gfx::PointF point_in_root_in_pixels =
- ComputePointInRootInPixels(point, root_view, device_scale_factor);
- if (!query->TransformLocationForTarget(source, target_ancestors,
- point_in_root_in_pixels,
- transformed_point)) {
- return false;
- }
- *transformed_point =
- gfx::ConvertPointToDIP(device_scale_factor, *transformed_point);
- return true;
-}
-
RenderWidgetTargetResult
RenderWidgetHostInputEventRouter::FindTargetSynchronously(
RenderWidgetHostViewBase* root_view,
@@ -1400,8 +1414,18 @@ void RenderWidgetHostInputEventRouter::DispatchEventToTarget(
return;
}
if (blink::WebInputEvent::IsTouchEventType(event.GetType())) {
- DispatchTouchEvent(root_view, target,
- static_cast<const blink::WebTouchEvent&>(event), latency,
+ auto& touch_event = static_cast<const blink::WebTouchEvent&>(event);
+ TouchEventWithLatencyInfo touch_with_latency(touch_event, latency);
+ if (touch_emulator_ &&
+ touch_emulator_->HandleTouchEvent(touch_with_latency.event)) {
+ // We cheat a litle bit here, and assume that we know that even if the
+ // target is a RenderWidgetHostViewChildFrame, that it would only try to
+ // forward the ack to the root view anyways, so we send it there directly.
+ root_view->ProcessAckedTouchEvent(touch_with_latency,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ return;
+ }
+ DispatchTouchEvent(root_view, target, touch_event, latency,
target_location);
return;
}
@@ -1423,16 +1447,81 @@ void RenderWidgetHostInputEventRouter::DispatchEventToTarget(
NOTREACHED();
}
-RenderWidgetHostViewBase*
-RenderWidgetHostInputEventRouter::FindViewFromFrameSinkId(
- const viz::FrameSinkId& frame_sink_id) const {
- // TODO(kenrb): There should be a better way to handle hit tests to surfaces
- // that are no longer valid for hit testing. See https://crbug.com/790044.
- auto iter = owner_map_.find(frame_sink_id);
- // If the point hit a Surface whose namspace is no longer in the map, then
- // it likely means the RenderWidgetHostView has been destroyed but its
- // parent frame has not sent a new compositor frame since that happened.
- return iter == owner_map_.end() ? nullptr : iter->second;
+TouchEmulator* RenderWidgetHostInputEventRouter::GetTouchEmulator() {
+ if (!touch_emulator_)
+ touch_emulator_.reset(new TouchEmulator(this, last_device_scale_factor_));
+
+ return touch_emulator_.get();
+}
+
+void RenderWidgetHostInputEventRouter::ForwardEmulatedGestureEvent(
+ const blink::WebGestureEvent& event) {
+ TRACE_EVENT0("input",
+ "RenderWidgetHostInputEventRouter::ForwardEmulatedGestureEvent");
+ DCHECK(last_emulated_event_root_view_);
+ DispatchTouchscreenGestureEvent(last_emulated_event_root_view_, nullptr,
+ event, ui::LatencyInfo(),
+ event.PositionInWidget());
+}
+
+void RenderWidgetHostInputEventRouter::ForwardEmulatedTouchEvent(
+ const blink::WebTouchEvent& event,
+ RenderWidgetHostViewBase* target) {
+ TRACE_EVENT0("input",
+ "RenderWidgetHostInputEventRouter::ForwardEmulatedTouchEvent");
+ // Here we re-use the last root view we saw for a mouse move event, or fall
+ // back to using |target| as the root_view if we haven't seen a mouse event;
+ // this latter case only happens for injected touch events.
+ // TODO(wjmaclean): Why doesn't this class just track its root view?
+ DCHECK(IsViewInMap(static_cast<RenderWidgetHostViewBase*>(target)));
+ last_emulated_event_root_view_ =
+ last_mouse_move_root_view_ ? last_mouse_move_root_view_ : target;
+
+ if (event.GetType() == blink::WebInputEvent::kTouchStart)
+ active_touches_ += CountChangedTouchPoints(event);
+ blink::WebFloatPoint position_in_widget = event.touches[0].PositionInWidget();
+ gfx::PointF transformed_point = target->TransformRootPointToViewCoordSpace(
+ gfx::PointF(position_in_widget.x, position_in_widget.y));
+ DispatchTouchEvent(last_emulated_event_root_view_, target, event,
+ ui::LatencyInfo(), transformed_point);
+}
+
+void RenderWidgetHostInputEventRouter::SetCursor(const WebCursor& cursor) {
+ if (!last_mouse_move_root_view_)
+ return;
+
+ last_device_scale_factor_ =
+ last_mouse_move_root_view_->current_device_scale_factor();
+ if (auto* cursor_manager = last_mouse_move_root_view_->GetCursorManager()) {
+ for (auto it : owner_map_)
+ cursor_manager->UpdateCursor(it.second, cursor);
+ }
+}
+
+void RenderWidgetHostInputEventRouter::ShowContextMenuAtPoint(
+ const gfx::Point& point,
+ const ui::MenuSourceType source_type) {
+ DCHECK(last_mouse_move_target_);
+
+ auto* rwhi = static_cast<RenderWidgetHostImpl*>(
+ last_mouse_move_target_->GetRenderWidgetHost());
+ DCHECK(rwhi);
+ rwhi->ShowContextMenuAtPoint(point, source_type);
+}
+
+void RenderWidgetHostInputEventRouter::SetMouseCaptureTarget(
+ RenderWidgetHostViewBase* target,
+ bool capture) {
+ if (touch_emulator_ && touch_emulator_->enabled())
+ return;
+
+ if (capture) {
+ mouse_capture_target_.target = target;
+ return;
+ }
+
+ if (mouse_capture_target_.target == target)
+ mouse_capture_target_.target = nullptr;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
index 415a6d5c36a..9d766924b89 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -18,6 +18,7 @@
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/host/hit_test/hit_test_query.h"
#include "components/viz/service/surfaces/surface_hittest_delegate.h"
+#include "content/browser/renderer_host/input/touch_emulator_client.h"
#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
#include "content/browser/renderer_host/render_widget_targeter.h"
#include "content/common/content_export.h"
@@ -48,6 +49,7 @@ class RenderWidgetHostImpl;
class RenderWidgetHostView;
class RenderWidgetHostViewBase;
class RenderWidgetTargeter;
+class TouchEmulator;
// Class owned by WebContentsImpl for the purpose of directing input events
// to the correct RenderWidgetHost on pages with multiple RenderWidgetHosts.
@@ -57,7 +59,8 @@ class RenderWidgetTargeter;
// forwards the event to the owning RWHV of the returned Surface ID.
class CONTENT_EXPORT RenderWidgetHostInputEventRouter
: public RenderWidgetHostViewBaseObserver,
- public RenderWidgetTargeter::Delegate {
+ public RenderWidgetTargeter::Delegate,
+ public TouchEmulatorClient {
public:
RenderWidgetHostInputEventRouter();
~RenderWidgetHostInputEventRouter() final;
@@ -95,6 +98,11 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
void OnHittestData(const FrameHostMsg_HittestData_Params& params);
+ TouchEmulator* GetTouchEmulator();
+ // Since GetTouchEmulator will lazily create a touch emulator, the following
+ // accessor allows testing for its existence without causing it to be created.
+ bool has_touch_emulator() const { return touch_emulator_.get(); }
+
// Returns the RenderWidgetHostImpl inside the |root_view| at |point| where
// |point| is with respect to |root_view|'s coordinates. If a RWHI is found,
// the value of |transformed_point| is the coordinate of the point with
@@ -105,9 +113,26 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const gfx::PointF& point,
gfx::PointF* transformed_point);
+ // RenderWidgetTargeter::Delegate:
+ RenderWidgetHostViewBase* FindViewFromFrameSinkId(
+ const viz::FrameSinkId& frame_sink_id) const override;
+
+ // Allows a target to claim or release capture of mouse events.
+ void SetMouseCaptureTarget(RenderWidgetHostViewBase* target,
+ bool captures_dragging);
+
std::vector<RenderWidgetHostView*> GetRenderWidgetHostViewsForTests() const;
RenderWidgetTargeter* GetRenderWidgetTargeterForTests();
+ // TouchEmulatorClient:
+ void ForwardEmulatedGestureEvent(
+ const blink::WebGestureEvent& event) override;
+ void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event,
+ RenderWidgetHostViewBase* target) override;
+ void SetCursor(const WebCursor& cursor) override;
+ void ShowContextMenuAtPoint(const gfx::Point& point,
+ const ui::MenuSourceType source_type) override;
+
private:
struct HittestData {
bool ignored_for_hittest;
@@ -146,6 +171,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
viz::EventSource source,
gfx::PointF* transformed_point) const;
+ bool IsViewInMap(const RenderWidgetHostViewBase* view) const;
void RouteTouchscreenGestureEvent(RenderWidgetHostViewBase* root_view,
blink::WebGestureEvent* event,
const ui::LatencyInfo& latency);
@@ -246,13 +272,14 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency,
const base::Optional<gfx::PointF>& target_location) override;
- RenderWidgetHostViewBase* FindViewFromFrameSinkId(
- const viz::FrameSinkId& frame_sink_id) const override;
FrameSinkIdOwnerMap owner_map_;
TargetMap touchscreen_gesture_target_map_;
TargetData touch_target_;
TargetData touchscreen_gesture_target_;
+ // The following variable is temporary, for diagnosis of
+ // https://crbug.com/824774.
+ bool touchscreen_gesture_target_in_map_;
TargetData touchpad_gesture_target_;
TargetData bubbling_gesture_scroll_target_;
TargetData first_bubbling_scroll_target_;
@@ -266,6 +293,11 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
RenderWidgetHostViewBase* last_mouse_move_target_;
RenderWidgetHostViewBase* last_mouse_move_root_view_;
+ // Tracked for the purpose of providing a root_view when dispatching emulated
+ // touch/gesture events.
+ RenderWidgetHostViewBase* last_emulated_event_root_view_;
+ float last_device_scale_factor_;
+
int active_touches_;
// Keep track of when we are between GesturePinchBegin and GesturePinchEnd
// inclusive, as we need to route these events (and anything in between) to
@@ -278,6 +310,8 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
std::unique_ptr<RenderWidgetTargeter> event_targeter_;
bool use_viz_hit_test_ = false;
+ std::unique_ptr<TouchEmulator> touch_emulator_;
+
base::WeakPtrFactory<RenderWidgetHostInputEventRouter> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
index 78c2efb7792..f25a7637f5c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -105,7 +105,8 @@ class MockRootRenderWidgetHostView : public TestRenderWidgetHostView {
bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) override {
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY) override {
return true;
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
index e0ffad96974..3761be5f730 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
@@ -9,18 +9,26 @@
#include <memory>
+#include "base/containers/flat_set.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/strings/string16.h"
#include "content/common/mac/attributed_string_coder.h"
#include "third_party/blink/public/web/web_popup_type.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/ime/text_input_type.h"
namespace gfx {
+struct CALayerParams;
class Point;
class Range;
class Rect;
} // namespace gfx
+namespace ui {
+enum class DomCode;
+} // namespace ui
+
namespace content {
class RenderWidgetHostNSViewClient;
@@ -46,6 +54,10 @@ class RenderWidgetHostNSViewBridge {
virtual void InitAsPopup(const gfx::Rect& content_rect,
blink::WebPopupType popup_type) = 0;
+ // Disable displaying any content (including the background color). This is
+ // to be called on views that are to be displayed via a parent ui::Compositor.
+ virtual void DisableDisplay() = 0;
+
// Make the NSView be the first responder of its NSWindow.
virtual void MakeFirstResponder() = 0;
@@ -53,6 +65,9 @@ class RenderWidgetHostNSViewBridge {
// window type).
virtual void SetBounds(const gfx::Rect& rect) = 0;
+ // Set the contents to display in the NSView.
+ virtual void SetCALayerParams(const gfx::CALayerParams& ca_layer_params) = 0;
+
// Set the background color of the hosted CALayer.
virtual void SetBackgroundColor(SkColor color) = 0;
@@ -62,6 +77,9 @@ class RenderWidgetHostNSViewBridge {
// Call the -[NSView setToolTipAtMousePoint] method.
virtual void SetTooltipText(const base::string16& display_text) = 0;
+ // Forward changes in ui::TextInputType.
+ virtual void SetTextInputType(ui::TextInputType text_input_type) = 0;
+
// Forward the TextInputManager::TextSelection from the renderer.
virtual void SetTextSelection(const base::string16& text,
size_t offset,
@@ -92,6 +110,13 @@ class RenderWidgetHostNSViewBridge {
const mac::AttributedStringCoder::EncodedString& encoded_string,
gfx::Point baseline_point) = 0;
+ // Start intercepting keyboard events.
+ virtual void LockKeyboard(
+ base::Optional<base::flat_set<ui::DomCode>> dom_codes) = 0;
+
+ // Stop intercepting keyboard events.
+ virtual void UnlockKeyboard() = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridge);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
index ce3cc68af90..54b1c71bb4c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
@@ -13,9 +13,11 @@
#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
#include "content/common/cursors/webcursor.h"
#import "skia/ext/skia_utils_mac.h"
+#include "ui/accelerated_widget_mac/display_ca_layer_tree.h"
#import "ui/base/cocoa/animation_utils.h"
#include "ui/display/display_observer.h"
#include "ui/display/screen.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/mac/coordinate_conversion.h"
namespace content {
@@ -36,11 +38,14 @@ class RenderWidgetHostViewNSViewBridgeLocal
void InitAsPopup(const gfx::Rect& content_rect,
blink::WebPopupType popup_type) override;
+ void DisableDisplay() override;
void MakeFirstResponder() override;
void SetBounds(const gfx::Rect& rect) override;
+ void SetCALayerParams(const gfx::CALayerParams& ca_layer_params) override;
void SetBackgroundColor(SkColor color) override;
void SetVisible(bool visible) override;
void SetTooltipText(const base::string16& display_text) override;
+ void SetTextInputType(ui::TextInputType text_input_type) override;
void SetTextSelection(const base::string16& text,
size_t offset,
const gfx::Range& range) override;
@@ -53,6 +58,8 @@ class RenderWidgetHostViewNSViewBridgeLocal
void ShowDictionaryOverlay(
const mac::AttributedStringCoder::EncodedString& encoded_string,
gfx::Point baseline_point) override;
+ void LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
+ void UnlockKeyboard() override;
private:
bool IsPopup() const {
@@ -68,12 +75,18 @@ class RenderWidgetHostViewNSViewBridgeLocal
// The NSView used for input and display.
base::scoped_nsobject<RenderWidgetHostViewCocoa> cocoa_view_;
+ // Once set, all calls to set the background color or CALayer content will
+ // be ignored.
+ bool display_disabled_ = false;
+
// The window used for popup widgets, and its helper.
std::unique_ptr<PopupWindowMac> popup_window_;
blink::WebPopupType popup_type_ = blink::kWebPopupTypeNone;
- // The background CoreAnimation layer which is hosted by |cocoa_view_|.
+ // The background CALayer which is hosted by |cocoa_view_|, and is used as
+ // the root of |display_ca_layer_tree_|.
base::scoped_nsobject<CALayer> background_layer_;
+ std::unique_ptr<ui::DisplayCALayerTree> display_ca_layer_tree_;
// Cached copy of the tooltip text, to avoid redundant calls.
base::string16 tooltip_text_;
@@ -88,6 +101,8 @@ RenderWidgetHostViewNSViewBridgeLocal::RenderWidgetHostViewNSViewBridgeLocal(
cocoa_view_.reset([[RenderWidgetHostViewCocoa alloc] initWithClient:client]);
background_layer_.reset([[CALayer alloc] init]);
+ display_ca_layer_tree_ =
+ std::make_unique<ui::DisplayCALayerTree>(background_layer_.get());
[cocoa_view_ setLayer:background_layer_];
[cocoa_view_ setWantsLayer:YES];
}
@@ -124,6 +139,14 @@ void RenderWidgetHostViewNSViewBridgeLocal::MakeFirstResponder() {
[[cocoa_view_ window] makeFirstResponder:cocoa_view_];
}
+void RenderWidgetHostViewNSViewBridgeLocal::DisableDisplay() {
+ if (display_disabled_)
+ return;
+ SetBackgroundColor(SK_ColorTRANSPARENT);
+ display_ca_layer_tree_.reset();
+ display_disabled_ = true;
+}
+
void RenderWidgetHostViewNSViewBridgeLocal::SetBounds(const gfx::Rect& rect) {
// |rect.size()| is view coordinates, |rect.origin| is screen coordinates,
// TODO(thakis): fix, http://crbug.com/73362
@@ -165,7 +188,16 @@ void RenderWidgetHostViewNSViewBridgeLocal::SetBounds(const gfx::Rect& rect) {
}
}
+void RenderWidgetHostViewNSViewBridgeLocal::SetCALayerParams(
+ const gfx::CALayerParams& ca_layer_params) {
+ if (display_disabled_)
+ return;
+ display_ca_layer_tree_->UpdateCALayerTree(ca_layer_params);
+}
+
void RenderWidgetHostViewNSViewBridgeLocal::SetBackgroundColor(SkColor color) {
+ if (display_disabled_)
+ return;
ScopedCAActionDisabler disabler;
base::ScopedCFTypeRef<CGColorRef> cg_color(
skia::CGColorCreateFromSkColor(color));
@@ -211,6 +243,11 @@ void RenderWidgetHostViewNSViewBridgeLocal::CancelComposition() {
[cocoa_view_ cancelComposition];
}
+void RenderWidgetHostViewNSViewBridgeLocal::SetTextInputType(
+ ui::TextInputType text_input_type) {
+ [cocoa_view_ setTextInputType:text_input_type];
+}
+
void RenderWidgetHostViewNSViewBridgeLocal::SetTextSelection(
const base::string16& text,
size_t offset,
@@ -275,6 +312,15 @@ void RenderWidgetHostViewNSViewBridgeLocal::ShowDictionaryOverlay(
atPoint:flipped_baseline_point];
}
+void RenderWidgetHostViewNSViewBridgeLocal::LockKeyboard(
+ base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+ [cocoa_view_ lockKeyboard:std::move(dom_codes)];
+}
+
+void RenderWidgetHostViewNSViewBridgeLocal::UnlockKeyboard() {
+ [cocoa_view_ unlockKeyboard];
+}
+
} // namespace
// static
diff --git a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
index 25c14510b94..bc2365191c6 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_ns_view_client.h
@@ -109,7 +109,8 @@ class RenderWidgetHostNSViewClient {
const blink::WebMouseWheelEvent& web_event) = 0;
// Handling pinch gesture events.
- virtual void OnNSViewGestureBegin(blink::WebGestureEvent begin_event) = 0;
+ virtual void OnNSViewGestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) = 0;
virtual void OnNSViewGestureUpdate(blink::WebGestureEvent update_event) = 0;
virtual void OnNSViewGestureEnd(blink::WebGestureEvent end_event) = 0;
virtual void OnNSViewSmartMagnify(
@@ -140,10 +141,6 @@ class RenderWidgetHostNSViewClient {
virtual void OnNSViewLookUpDictionaryOverlayFromRange(
const gfx::Range& range) = 0;
- // Synchronously query the text input type from the
- virtual void OnNSViewSyncGetTextInputType(
- ui::TextInputType* text_input_type) = 0;
-
// Synchronously query the character index for |root_point| and return it in
// |*index|. Sets it to UINT32_MAX if the request fails or is not completed.
virtual void OnNSViewSyncGetCharacterIndexAtPoint(
diff --git a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
index ec9145eab42..99e582adf7d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -12,15 +12,16 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "cc/trees/render_frame_metadata.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
@@ -29,7 +30,6 @@
#include "components/viz/test/mock_compositor_frame_sink_client.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/frame_token_message_queue.h"
-#include "content/browser/renderer_host/input/legacy_input_router_impl.h"
#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -38,8 +38,8 @@
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
#include "content/common/render_frame_metadata.mojom.h"
-#include "content/common/resize_params.h"
#include "content/common/view_messages.h"
+#include "content/common/visual_properties.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -131,7 +131,6 @@ class MockInputRouter : public InputRouter {
void SetForceEnableZoom(bool enabled) override {}
void BindHost(mojom::WidgetInputHandlerHostRequest request,
bool frame_handler) override {}
- void ProgressFling(base::TimeTicks time) override {}
void StopFling() override {}
bool FlingCancellationIsDeferred() override { return false; }
@@ -183,13 +182,12 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
public:
// Allow poking at a few private members.
- using RenderWidgetHostImpl::GetResizeParams;
- using RenderWidgetHostImpl::OnResizeOrRepaintACK;
+ using RenderWidgetHostImpl::GetVisualProperties;
using RenderWidgetHostImpl::RendererExited;
- using RenderWidgetHostImpl::SetInitialRenderSizeParams;
- using RenderWidgetHostImpl::old_resize_params_;
+ using RenderWidgetHostImpl::SetInitialVisualProperties;
+ using RenderWidgetHostImpl::old_visual_properties_;
using RenderWidgetHostImpl::is_hidden_;
- using RenderWidgetHostImpl::resize_ack_pending_;
+ using RenderWidgetHostImpl::visual_properties_ack_pending_;
using RenderWidgetHostImpl::input_router_;
using RenderWidgetHostImpl::frame_token_message_queue_;
@@ -210,31 +208,16 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
}
void DisableGestureDebounce() {
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- input_router_.reset(
- new InputRouterImpl(this, this, InputRouter::Config()));
- legacy_widget_input_handler_ = nullptr;
- } else {
- input_router_.reset(new LegacyInputRouterImpl(
- process_, this, this, routing_id_, InputRouter::Config()));
- legacy_widget_input_handler_ =
- std::make_unique<LegacyIPCWidgetInputHandler>(
- static_cast<LegacyInputRouterImpl*>(input_router_.get()));
- }
+ input_router_.reset(new InputRouterImpl(this, this, fling_scheduler_.get(),
+ InputRouter::Config()));
}
void ExpectForceEnableZoom(bool enable) {
EXPECT_EQ(enable, force_enable_zoom_);
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- InputRouterImpl* input_router =
- static_cast<InputRouterImpl*>(input_router_.get());
- EXPECT_EQ(enable, input_router->touch_action_filter_.force_enable_zoom_);
- } else {
- LegacyInputRouterImpl* input_router =
- static_cast<LegacyInputRouterImpl*>(input_router_.get());
- EXPECT_EQ(enable, input_router->touch_action_filter_.force_enable_zoom_);
- }
+ InputRouterImpl* input_router =
+ static_cast<InputRouterImpl*>(input_router_.get());
+ EXPECT_EQ(enable, input_router->touch_action_filter_.force_enable_zoom_);
}
WebInputEvent::Type acked_touch_event_type() const {
@@ -252,7 +235,6 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
void SetupForInputRouterTest() {
input_router_.reset(new MockInputRouter(this));
- legacy_widget_input_handler_ = nullptr;
}
MockInputRouter* mock_input_router() {
@@ -278,10 +260,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
}
mojom::WidgetInputHandler* GetWidgetInputHandler() override {
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- return &mock_widget_input_handler_;
- }
- return RenderWidgetHostImpl::GetWidgetInputHandler();
+ return &mock_widget_input_handler_;
}
MockWidgetInputHandler mock_widget_input_handler_;
@@ -306,13 +285,15 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
std::move(widget),
false),
new_content_rendering_timeout_fired_(false),
- widget_impl_(std::move(widget_impl)) {
+ widget_impl_(std::move(widget_impl)),
+ fling_scheduler_(std::make_unique<FlingScheduler>(this)) {
acked_touch_event_type_ = blink::WebInputEvent::kUndefined;
frame_token_message_queue_.reset(new TestFrameTokenMessageQueue(this));
}
std::unique_ptr<MockWidgetImpl> widget_impl_;
+ std::unique_ptr<FlingScheduler> fling_scheduler_;
DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost);
};
@@ -354,13 +335,18 @@ class TestView : public TestRenderWidgetHostView {
if (bounds_ == bounds)
return;
bounds_ = bounds;
- local_surface_id_ = local_surface_id_allocator_.GenerateId();
+ local_surface_id_allocator_.GenerateId();
}
void SetScreenInfo(const ScreenInfo& screen_info) {
+ if (screen_info_ == screen_info)
+ return;
screen_info_ = screen_info;
+ local_surface_id_allocator_.GenerateId();
}
+ void InvalidateLocalSurfaceId() { local_surface_id_allocator_.Invalidate(); }
+
void GetScreenInfo(ScreenInfo* screen_info) const override {
*screen_info = screen_info_;
}
@@ -391,11 +377,20 @@ class TestView : public TestRenderWidgetHostView {
void SetMockCompositorViewportPixelSize(
const gfx::Size& mock_compositor_viewport_pixel_size) {
+ if (use_fake_compositor_viewport_pixel_size_ &&
+ mock_compositor_viewport_pixel_size_ ==
+ mock_compositor_viewport_pixel_size) {
+ return;
+ }
use_fake_compositor_viewport_pixel_size_ = true;
mock_compositor_viewport_pixel_size_ = mock_compositor_viewport_pixel_size;
+ local_surface_id_allocator_.GenerateId();
}
void ClearMockCompositorViewportPixelSize() {
+ if (!use_fake_compositor_viewport_pixel_size_)
+ return;
use_fake_compositor_viewport_pixel_size_ = false;
+ local_surface_id_allocator_.GenerateId();
}
const viz::BeginFrameAck& last_did_not_produce_frame_ack() {
@@ -409,7 +404,7 @@ class TestView : public TestRenderWidgetHostView {
return bottom_controls_height_;
}
viz::LocalSurfaceId GetLocalSurfaceId() const override {
- return local_surface_id_;
+ return local_surface_id_allocator_.GetCurrentLocalSurfaceId();
}
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
@@ -451,7 +446,6 @@ class TestView : public TestRenderWidgetHostView {
float top_controls_height_;
float bottom_controls_height_;
viz::BeginFrameAck last_did_not_produce_frame_ack_;
- viz::LocalSurfaceId local_surface_id_;
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
ScreenInfo screen_info_;
@@ -629,28 +623,20 @@ enum WheelScrollingMode {
kAsyncWheelEvents,
};
-enum class UseMojoInputMessages { kEnabled, kDisabled };
-
// RenderWidgetHostTest --------------------------------------------------------
class RenderWidgetHostTest : public testing::Test {
public:
RenderWidgetHostTest(
- UseMojoInputMessages input_messages_mode = UseMojoInputMessages::kEnabled,
WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
: process_(nullptr),
handle_key_press_event_(false),
handle_mouse_event_(false),
- simulated_event_time_delta_seconds_(0),
+ last_simulated_event_time_(ui::EventTimeForNow()),
wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
kWheelScrollingModeNone) {
std::vector<base::StringPiece> features;
std::vector<base::StringPiece> disabled_features;
- if (input_messages_mode == UseMojoInputMessages::kEnabled) {
- features.push_back(features::kMojoInputMessages.name);
- } else {
- disabled_features.push_back(features::kMojoInputMessages.name);
- }
switch (wheel_scrolling_mode) {
case kWheelScrollingModeNone:
@@ -672,9 +658,6 @@ class RenderWidgetHostTest : public testing::Test {
feature_list_.InitFromCommandLine(base::JoinString(features, ","),
base::JoinString(disabled_features, ","));
-
- last_simulated_event_time_seconds_ =
- ui::EventTimeStampToSeconds(ui::EventTimeForNow());
}
~RenderWidgetHostTest() override {}
@@ -710,7 +693,7 @@ class RenderWidgetHostTest : public testing::Test {
view_.reset(new TestView(host_.get()));
ConfigureView(view_.get());
host_->SetView(view_.get());
- SetInitialRenderSizeParams();
+ SetInitialVisualProperties();
host_->Init();
host_->DisableGestureDebounce();
@@ -739,7 +722,9 @@ class RenderWidgetHostTest : public testing::Test {
std::move(render_frame_metadata_observer_client_info));
host_->RequestCompositorFrameSink(
- std::move(sink_request), std::move(renderer_compositor_frame_sink_ptr_),
+ std::move(sink_request),
+ std::move(renderer_compositor_frame_sink_ptr_));
+ host_->RegisterRenderFrameMetadataObserver(
std::move(render_frame_metadata_observer_client_request),
std::move(renderer_render_frame_metadata_observer_ptr));
}
@@ -766,10 +751,11 @@ class RenderWidgetHostTest : public testing::Test {
base::RunLoop().RunUntilIdle();
}
- void SetInitialRenderSizeParams() {
- ResizeParams render_size_params;
- host_->GetResizeParams(&render_size_params);
- host_->SetInitialRenderSizeParams(render_size_params);
+ void SetInitialVisualProperties() {
+ VisualProperties visual_properties;
+ bool needs_ack = false;
+ host_->GetVisualProperties(&visual_properties, &needs_ack);
+ host_->SetInitialVisualProperties(visual_properties, needs_ack);
}
virtual void ConfigureView(TestView* view) {
@@ -777,23 +763,9 @@ class RenderWidgetHostTest : public testing::Test {
int64_t GetLatencyComponentId() { return host_->GetLatencyComponentId(); }
- void SendInputEventACK(WebInputEvent::Type type,
- InputEventAckState ack_result) {
- DCHECK(!WebInputEvent::IsTouchEventType(type));
- InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD, type, ack_result);
- host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
- }
-
- void SendScrollBeginAckIfneeded(InputEventAckState ack_result) {
- if (wheel_scroll_latching_enabled_) {
- // GSB events are blocking, send the ack.
- SendInputEventACK(WebInputEvent::kGestureScrollBegin, ack_result);
- }
- }
-
- double GetNextSimulatedEventTimeSeconds() {
- last_simulated_event_time_seconds_ += simulated_event_time_delta_seconds_;
- return last_simulated_event_time_seconds_;
+ base::TimeTicks GetNextSimulatedEventTime() {
+ last_simulated_event_time_ += simulated_event_time_delta_;
+ return last_simulated_event_time_;
}
void SimulateKeyboardEvent(WebInputEvent::Type type) {
@@ -802,13 +774,12 @@ class RenderWidgetHostTest : public testing::Test {
void SimulateKeyboardEvent(WebInputEvent::Type type, int modifiers) {
NativeWebKeyboardEvent native_event(type, modifiers,
- GetNextSimulatedEventTimeSeconds());
+ GetNextSimulatedEventTime());
host_->ForwardKeyboardEvent(native_event);
}
void SimulateKeyboardEventWithCommands(WebInputEvent::Type type) {
- NativeWebKeyboardEvent native_event(type, 0,
- GetNextSimulatedEventTimeSeconds());
+ NativeWebKeyboardEvent native_event(type, 0, GetNextSimulatedEventTime());
EditCommands commands;
commands.emplace_back("name", "value");
host_->ForwardKeyboardEventWithCommands(native_event, ui::LatencyInfo(),
@@ -879,7 +850,7 @@ class RenderWidgetHostTest : public testing::Test {
SyntheticWebMouseEventBuilder::Build(type, x, y, modifiers);
if (pressed)
event.button = WebMouseEvent::Button::kLeft;
- event.SetTimeStampSeconds(GetNextSimulatedEventTimeSeconds());
+ event.SetTimeStamp(GetNextSimulatedEventTime());
host_->ForwardMouseEvent(event);
}
@@ -935,11 +906,8 @@ class RenderWidgetHostTest : public testing::Test {
}
void UnhandledWheelEvent();
- void UnhandledWheelEventMojoInputDisabled();
void HandleWheelEvent();
- void HandleWheelEventMojoInputDisabled();
void InputEventRWHLatencyComponent();
- void InputEventRWHLatencyComponentMojoInputDisabled();
std::unique_ptr<TestBrowserContext> browser_context_;
RenderWidgetHostProcess* process_; // Deleted automatically by the widget.
@@ -949,8 +917,8 @@ class RenderWidgetHostTest : public testing::Test {
std::unique_ptr<display::Screen> screen_;
bool handle_key_press_event_;
bool handle_mouse_event_;
- double last_simulated_event_time_seconds_;
- double simulated_event_time_delta_seconds_;
+ base::TimeTicks last_simulated_event_time_;
+ base::TimeDelta simulated_event_time_delta_;
IPC::TestSink* sink_;
std::unique_ptr<FakeRendererCompositorFrameSink>
renderer_compositor_frame_sink_;
@@ -968,42 +936,18 @@ class RenderWidgetHostTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest);
};
-class RenderWidgetHostMojoInputDisabledTest : public RenderWidgetHostTest {
- public:
- RenderWidgetHostMojoInputDisabledTest()
- : RenderWidgetHostTest(UseMojoInputMessages::kDisabled) {}
-};
-
class RenderWidgetHostWheelScrollLatchingDisabledTest
: public RenderWidgetHostTest {
public:
RenderWidgetHostWheelScrollLatchingDisabledTest()
- : RenderWidgetHostTest(UseMojoInputMessages::kEnabled,
- kWheelScrollingModeNone) {}
+ : RenderWidgetHostTest(kWheelScrollingModeNone) {}
};
class RenderWidgetHostAsyncWheelEventsEnabledTest
: public RenderWidgetHostTest {
public:
RenderWidgetHostAsyncWheelEventsEnabledTest()
- : RenderWidgetHostTest(UseMojoInputMessages::kEnabled,
- kAsyncWheelEvents) {}
-};
-
-class RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest
- : public RenderWidgetHostTest {
- public:
- RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest()
- : RenderWidgetHostTest(UseMojoInputMessages::kDisabled,
- kWheelScrollingModeNone) {}
-};
-
-class RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest
- : public RenderWidgetHostTest {
- public:
- RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest()
- : RenderWidgetHostTest(UseMojoInputMessages::kDisabled,
- kAsyncWheelEvents) {}
+ : RenderWidgetHostTest(kAsyncWheelEvents) {}
};
// RenderWidgetHostWithSourceTest ----------------------------------------------
@@ -1017,19 +961,20 @@ class RenderWidgetHostWithSourceTest
// -----------------------------------------------------------------------------
-TEST_F(RenderWidgetHostTest, Resize) {
+TEST_F(RenderWidgetHostTest, SynchronizeVisualProperties) {
// The initial bounds is the empty rect, so setting it to the same thing
// shouldn't send the resize message.
view_->SetBounds(gfx::Rect());
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
- // No resize ack if the physical backing gets set, but the view bounds are
- // zero.
+ // No visual properties ACK if the physical backing gets set, but the view
+ // bounds are zero.
view_->SetMockCompositorViewportPixelSize(gfx::Size(200, 200));
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
// Setting the view bounds to nonzero should send out the notification.
// but should not expect ack for empty physical backing size.
@@ -1037,104 +982,117 @@ TEST_F(RenderWidgetHostTest, Resize) {
process_->sink().ClearMessages();
view_->SetBounds(original_size);
view_->SetMockCompositorViewportPixelSize(gfx::Size());
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(original_size.size(), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
// Setting the bounds and physical backing size to nonzero should send out
// the notification and expect an ack.
process_->sink().ClearMessages();
view_->ClearMockCompositorViewportPixelSize();
- host_->WasResized();
- EXPECT_TRUE(host_->resize_ack_pending_);
- EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
- ViewHostMsg_ResizeOrRepaint_ACK_Params params;
- params.flags = ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK;
- params.view_size = original_size.size();
- host_->OnResizeOrRepaintACK(params);
- EXPECT_FALSE(host_->resize_ack_pending_);
-
- // Send out a update that's not a resize ack after setting resize ack pending
- // flag. This should not clean the resize ack pending flag.
+ host_->SynchronizeVisualProperties();
+ EXPECT_TRUE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(original_size.size(), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = original_size.size();
+ metadata.local_surface_id = base::nullopt;
+ host_->DidUpdateVisualProperties(metadata);
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+
process_->sink().ClearMessages();
gfx::Rect second_size(0, 0, 110, 110);
- EXPECT_FALSE(host_->resize_ack_pending_);
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
view_->SetBounds(second_size);
- host_->WasResized();
- EXPECT_TRUE(host_->resize_ack_pending_);
- params.flags = 0;
- params.view_size = gfx::Size(100, 100);
- host_->OnResizeOrRepaintACK(params);
- EXPECT_TRUE(host_->resize_ack_pending_);
- EXPECT_EQ(second_size.size(), host_->old_resize_params_->new_size);
+ EXPECT_TRUE(host_->SynchronizeVisualProperties());
+ EXPECT_TRUE(host_->visual_properties_ack_pending_);
// Sending out a new notification should NOT send out a new IPC message since
- // a resize ACK is pending.
+ // a visual properties ACK is pending.
gfx::Rect third_size(0, 0, 120, 120);
process_->sink().ClearMessages();
view_->SetBounds(third_size);
- host_->WasResized();
- EXPECT_TRUE(host_->resize_ack_pending_);
- EXPECT_EQ(second_size.size(), host_->old_resize_params_->new_size);
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
-
- // Send a update that's a resize ack, but for the original_size we sent. Since
- // this isn't the second_size, the message handler should immediately send
- // a new resize message for the new size to the renderer.
+ EXPECT_FALSE(host_->SynchronizeVisualProperties());
+ EXPECT_TRUE(host_->visual_properties_ack_pending_);
+ EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+
+ // Send a update that's a visual properties ACK, but for the original_size we
+ // sent. Since this isn't the second_size, the message handler should
+ // immediately send a new resize message for the new size to the renderer.
process_->sink().ClearMessages();
- params.flags = ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK;
- params.view_size = original_size.size();
- host_->OnResizeOrRepaintACK(params);
- EXPECT_TRUE(host_->resize_ack_pending_);
- EXPECT_EQ(third_size.size(), host_->old_resize_params_->new_size);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
-
- // Send the resize ack for the latest size.
+ metadata.viewport_size_in_pixels = original_size.size();
+ metadata.local_surface_id = base::nullopt;
+ host_->DidUpdateVisualProperties(metadata);
+ EXPECT_TRUE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(third_size.size(), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+
+ // Send the visual properties ACK for the latest size.
process_->sink().ClearMessages();
- params.flags = ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK;
- params.view_size = third_size.size();
- host_->OnResizeOrRepaintACK(params);
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(third_size.size(), host_->old_resize_params_->new_size);
- EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
+ metadata.viewport_size_in_pixels = third_size.size();
+ metadata.local_surface_id = base::nullopt;
+ host_->DidUpdateVisualProperties(metadata);
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(third_size.size(), host_->old_visual_properties_->new_size);
+ EXPECT_FALSE(process_->sink().GetFirstMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
// Now clearing the bounds should send out a notification but we shouldn't
- // expect a resize ack (since the renderer won't ack empty sizes). The message
- // should contain the new size (0x0) and not the previous one that we skipped
+ // expect a visual properties ACK (since the renderer won't ack empty sizes).
+ // The message should contain the new size (0x0) and not the previous one that
+ // we skipped.
process_->sink().ClearMessages();
view_->SetBounds(gfx::Rect());
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(gfx::Size(), host_->old_resize_params_->new_size);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(gfx::Size(), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
// Send a rect that has no area but has either width or height set.
process_->sink().ClearMessages();
view_->SetBounds(gfx::Rect(0, 0, 0, 30));
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(gfx::Size(0, 30), host_->old_resize_params_->new_size);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(gfx::Size(0, 30), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
// Set the same size again. It should not be sent again.
process_->sink().ClearMessages();
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(gfx::Size(0, 30), host_->old_resize_params_->new_size);
- EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(gfx::Size(0, 30), host_->old_visual_properties_->new_size);
+ EXPECT_FALSE(process_->sink().GetFirstMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
// A different size should be sent again, however.
view_->SetBounds(gfx::Rect(0, 0, 0, 31));
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(gfx::Size(0, 31), host_->old_resize_params_->new_size);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(gfx::Size(0, 31), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+
+ // An invalid LocalSurfaceId should result in no change to the
+ // |visual_properties_ack_pending_| bit.
+ process_->sink().ClearMessages();
+ view_->SetBounds(gfx::Rect(25, 25));
+ view_->InvalidateLocalSurfaceId();
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(gfx::Size(25, 25), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
}
-// Test that a resize event is sent if WasResized() is called after a
-// ScreenInfo change.
+// Test that a resize event is sent if SynchronizeVisualProperties() is called
+// after a ScreenInfo change.
TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
ScreenInfo screen_info;
screen_info.device_scale_factor = 1.f;
@@ -1144,37 +1102,42 @@ TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
screen_info.orientation_type = SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY;
view_->SetScreenInfo(screen_info);
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
process_->sink().ClearMessages();
screen_info.orientation_angle = 180;
screen_info.orientation_type = SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY;
view_->SetScreenInfo(screen_info);
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
process_->sink().ClearMessages();
screen_info.device_scale_factor = 2.f;
view_->SetScreenInfo(screen_info);
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
process_->sink().ClearMessages();
// No screen change.
view_->SetScreenInfo(screen_info);
- host_->WasResized();
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
}
// Test for crbug.com/25097. If a renderer crashes between a resize and the
-// corresponding update message, we must be sure to clear the resize ack logic.
+// corresponding update message, we must be sure to clear the visual properties
+// ACK logic.
TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
// Clear the first Resize message that carried screen info.
process_->sink().ClearMessages();
@@ -1182,18 +1145,19 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
// Setting the bounds to a "real" rect should send out the notification.
gfx::Rect original_size(0, 0, 100, 100);
view_->SetBounds(original_size);
- host_->WasResized();
- EXPECT_TRUE(host_->resize_ack_pending_);
- EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+ host_->SynchronizeVisualProperties();
+ EXPECT_TRUE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(original_size.size(), host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
// Simulate a renderer crash before the update message. Ensure all the
- // resize ack logic is cleared. Must clear the view first so it doesn't get
- // deleted.
+ // visual properties ACK logic is cleared. Must clear the view first so it
+ // doesn't get deleted.
host_->SetView(nullptr);
host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
- EXPECT_FALSE(host_->resize_ack_pending_);
- EXPECT_EQ(gfx::Size(), host_->old_resize_params_->new_size);
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
+ EXPECT_EQ(nullptr, host_->old_visual_properties_);
// Reset the view so we can exit the test cleanly.
host_->SetView(view_.get());
@@ -1214,11 +1178,11 @@ TEST_F(RenderWidgetHostTest, Background) {
#endif
host_->SetView(view.get());
- EXPECT_NE(static_cast<unsigned>(SK_ColorTRANSPARENT),
- view->background_color());
+ ASSERT_FALSE(view->GetBackgroundColor());
view->SetBackgroundColor(SK_ColorTRANSPARENT);
+ ASSERT_TRUE(view->GetBackgroundColor());
EXPECT_EQ(static_cast<unsigned>(SK_ColorTRANSPARENT),
- view->background_color());
+ *view->GetBackgroundColor());
const IPC::Message* set_background =
process_->sink().GetUniqueMessageMatching(
@@ -1244,9 +1208,10 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
// Send it an update as from the renderer.
process_->sink().ClearMessages();
- ViewHostMsg_ResizeOrRepaint_ACK_Params params;
- params.view_size = gfx::Size(100, 100);
- host_->OnResizeOrRepaintACK(params);
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(100, 100);
+ metadata.local_surface_id = base::nullopt;
+ host_->DidUpdateVisualProperties(metadata);
// Now unhide.
process_->sink().ClearMessages();
@@ -1262,21 +1227,6 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
EXPECT_TRUE(std::get<0>(needs_repaint));
}
-TEST_F(RenderWidgetHostMojoInputDisabledTest,
- IgnoreKeyEventsHandledByRenderer) {
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kRawKeyDown, INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_FALSE(delegate_->unhandled_keyboard_event_called());
-}
-
TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
// Simulate a keyboard event.
SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
@@ -1292,26 +1242,6 @@ TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
EXPECT_FALSE(delegate_->unhandled_keyboard_event_called());
}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, SendEditCommandsBeforeKeyEvent) {
- // Clear any messages unrelated to this test.
- process_->sink().ClearMessages();
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Simulate a keyboard event.
- SimulateKeyboardEventWithCommands(WebInputEvent::kRawKeyDown);
-
- // Make sure we sent commands and key event to the renderer.
- EXPECT_EQ(2U, process_->sink().message_count());
- EXPECT_EQ(static_cast<uint32_t>(InputMsg_SetEditCommandsForNextKeyEvent::ID),
- process_->sink().GetMessageAt(0)->type());
- EXPECT_EQ(static_cast<uint32_t>(InputMsg_HandleInputEvent::ID),
- process_->sink().GetMessageAt(1)->type());
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kRawKeyDown, INPUT_EVENT_ACK_STATE_CONSUMED);
-}
-
TEST_F(RenderWidgetHostTest, SendEditCommandsBeforeKeyEvent) {
// Simulate a keyboard event.
SimulateKeyboardEventWithCommands(WebInputEvent::kRawKeyDown);
@@ -1327,53 +1257,6 @@ TEST_F(RenderWidgetHostTest, SendEditCommandsBeforeKeyEvent) {
dispatched_events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, PreHandleRawKeyDownEvent) {
- // Simulate the situation that the browser handled the key down event during
- // pre-handle phrase.
- delegate_->set_prehandle_keyboard_event(true);
- process_->sink().ClearMessages();
-
- // Simulate a keyboard event.
- SimulateKeyboardEventWithCommands(WebInputEvent::kRawKeyDown);
-
- EXPECT_TRUE(delegate_->prehandle_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::kRawKeyDown,
- delegate_->prehandle_keyboard_event_type());
-
- // Make sure the commands and key event are not sent to the renderer.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // The browser won't pre-handle a Char event.
- delegate_->set_prehandle_keyboard_event(false);
-
- // Forward the Char event.
- SimulateKeyboardEvent(WebInputEvent::kChar);
-
- // Make sure the Char event is suppressed.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Forward the KeyUp event.
- SimulateKeyboardEvent(WebInputEvent::kKeyUp);
-
- // Make sure the KeyUp event is suppressed.
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Simulate a new RawKeyDown event.
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ(static_cast<uint32_t>(InputMsg_HandleInputEvent::ID),
- process_->sink().GetMessageAt(0)->type());
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kRawKeyDown,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- EXPECT_TRUE(delegate_->unhandled_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::kRawKeyDown,
- delegate_->unhandled_keyboard_event_type());
-}
-
TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
// Simulate the situation that the browser handled the key down event during
// pre-handle phrase.
@@ -1428,59 +1311,6 @@ TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
delegate_->unhandled_keyboard_event_type());
}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, RawKeyDownShortcutEvent) {
- // Simulate the situation that the browser marks the key down as a keyboard
- // shortcut, but doesn't consume it in the pre-handle phase.
- delegate_->set_prehandle_keyboard_event_is_shortcut(true);
- process_->sink().ClearMessages();
-
- // Simulate a keyboard event.
- SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
- EXPECT_TRUE(delegate_->prehandle_keyboard_event_called());
- EXPECT_EQ(WebInputEvent::kRawKeyDown,
- delegate_->prehandle_keyboard_event_type());
-
- // Make sure the RawKeyDown event is sent to the renderer.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ("RawKeyDown", GetInputMessageTypes(process_));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kRawKeyDown,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(WebInputEvent::kRawKeyDown,
- delegate_->unhandled_keyboard_event_type());
-
- // The browser won't pre-handle a Char event.
- delegate_->set_prehandle_keyboard_event_is_shortcut(false);
-
- // Forward the Char event.
- SimulateKeyboardEvent(WebInputEvent::kChar);
-
- // The Char event is not suppressed; the renderer will ignore it
- // if the preceding RawKeyDown shortcut goes unhandled.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ("Char", GetInputMessageTypes(process_));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kChar, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(WebInputEvent::kChar, delegate_->unhandled_keyboard_event_type());
-
- // Forward the KeyUp event.
- SimulateKeyboardEvent(WebInputEvent::kKeyUp);
-
- // Make sure only KeyUp was sent to the renderer.
- EXPECT_EQ(1U, process_->sink().message_count());
- EXPECT_EQ("KeyUp", GetInputMessageTypes(process_));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kKeyUp, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(WebInputEvent::kKeyUp, delegate_->unhandled_keyboard_event_type());
-}
-
TEST_F(RenderWidgetHostTest, RawKeyDownShortcutEvent) {
// Simulate the situation that the browser marks the key down as a keyboard
// shortcut, but doesn't consume it in the pre-handle phase.
@@ -1544,34 +1374,6 @@ TEST_F(RenderWidgetHostTest, RawKeyDownShortcutEvent) {
EXPECT_EQ(WebInputEvent::kKeyUp, delegate_->unhandled_keyboard_event_type());
}
-void RenderWidgetHostTest::UnhandledWheelEventMojoInputDisabled() {
- SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kMouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(delegate_->handle_wheel_event_called());
- EXPECT_EQ(1, view_->unhandled_wheel_event_count());
- EXPECT_EQ(-5, view_->unhandled_wheel_event().delta_x);
-}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, UnhandledWheelEvent) {
- UnhandledWheelEventMojoInputDisabled();
-}
-TEST_F(RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest,
- UnhandledWheelEvent) {
- UnhandledWheelEventMojoInputDisabled();
-}
-TEST_F(RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest,
- UnhandledWheelEvent) {
- UnhandledWheelEventMojoInputDisabled();
-}
-
void RenderWidgetHostTest::UnhandledWheelEvent() {
SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
WebMouseWheelEvent::kPhaseBegan);
@@ -1601,40 +1403,6 @@ TEST_F(RenderWidgetHostAsyncWheelEventsEnabledTest, UnhandledWheelEvent) {
UnhandledWheelEvent();
}
-void RenderWidgetHostTest::HandleWheelEventMojoInputDisabled() {
- // Indicate that we're going to handle this wheel event
- delegate_->set_handle_wheel_event(true);
-
- SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(
- process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kMouseWheel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // ensure the wheel event handler was invoked
- EXPECT_TRUE(delegate_->handle_wheel_event_called());
-
- // and that it suppressed the unhandled wheel event handler.
- EXPECT_EQ(0, view_->unhandled_wheel_event_count());
-}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, HandleWheelEvent) {
- HandleWheelEventMojoInputDisabled();
-}
-TEST_F(RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest,
- HandleWheelEvent) {
- HandleWheelEventMojoInputDisabled();
-}
-TEST_F(RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest,
- HandleWheelEvent) {
- HandleWheelEventMojoInputDisabled();
-}
-
void RenderWidgetHostTest::HandleWheelEvent() {
// Indicate that we're going to handle this wheel event
delegate_->set_handle_wheel_event(true);
@@ -1669,22 +1437,6 @@ TEST_F(RenderWidgetHostAsyncWheelEventsEnabledTest, HandleWheelEvent) {
HandleWheelEvent();
}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, UnhandledGestureEvent) {
- SimulateGestureEvent(WebInputEvent::kGestureTwoFingerTap,
- blink::kWebGestureDeviceTouchscreen);
-
- // Make sure we sent the input event to the renderer.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- InputMsg_HandleInputEvent::ID));
- process_->sink().ClearMessages();
-
- // Send the simulated response from the renderer back.
- SendInputEventACK(WebInputEvent::kGestureTwoFingerTap,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(WebInputEvent::kGestureTwoFingerTap, view_->gesture_event_type());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, view_->ack_result());
-}
-
TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
SimulateGestureEvent(WebInputEvent::kGestureTwoFingerTap,
blink::kWebGestureDeviceTouchscreen);
@@ -1716,7 +1468,7 @@ TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMilliseconds(10));
base::RunLoop().Run();
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
@@ -1735,7 +1487,7 @@ TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMilliseconds(40));
base::RunLoop().Run();
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
@@ -1753,7 +1505,7 @@ TEST_F(RenderWidgetHostTest, ShorterDelayHangMonitorTimeout) {
// Wait long enough for the second timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMilliseconds(25));
base::RunLoop().Run();
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
@@ -1771,7 +1523,7 @@ TEST_F(RenderWidgetHostTest, HangMonitorTimeoutDisabledForInputWhenHidden) {
// The timeout should not fire.
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(2));
base::RunLoop().Run();
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
@@ -1779,7 +1531,7 @@ TEST_F(RenderWidgetHostTest, HangMonitorTimeoutDisabledForInputWhenHidden) {
// The timeout should never reactivate while hidden.
SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10, 0, false);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(2));
base::RunLoop().Run();
EXPECT_FALSE(delegate_->unresponsive_timer_fired());
@@ -1788,7 +1540,7 @@ TEST_F(RenderWidgetHostTest, HangMonitorTimeoutDisabledForInputWhenHidden) {
// not yet been ack'ed.
host_->WasShown(ui::LatencyInfo());
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(2));
base::RunLoop().Run();
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
@@ -1805,11 +1557,18 @@ TEST_F(RenderWidgetHostTest, MultipleInputEvents) {
// Send two events but only one ack.
SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
- SendInputEventACK(WebInputEvent::kRawKeyDown, INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ MockWidgetInputHandler::MessageVector dispatched_events =
+ host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
+ ASSERT_EQ(2u, dispatched_events.size());
+ ASSERT_TRUE(dispatched_events[0]->ToEvent());
+
+ // Send the simulated response from the renderer back.
+ dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
// Wait long enough for first timeout and see if it fired.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(20));
base::RunLoop().Run();
EXPECT_TRUE(delegate_->unresponsive_timer_fired());
@@ -1845,9 +1604,10 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
.AddDefaultRenderPass()
.SetContentSourceId(5)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(20));
base::RunLoop().Run();
@@ -1861,9 +1621,10 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
.AddDefaultRenderPass()
.SetContentSourceId(9)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(20));
base::RunLoop().Run();
@@ -1876,10 +1637,11 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
.AddDefaultRenderPass()
.SetContentSourceId(7)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
host_->DidNavigate(7);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(20));
base::RunLoop().Run();
@@ -1889,7 +1651,7 @@ TEST_F(RenderWidgetHostTest, NewContentRenderingTimeoutWithoutSurfaceSync) {
// Don't send any frames after the timer starts. The timer should fire.
host_->DidNavigate(20);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
TimeDelta::FromMicroseconds(20));
base::RunLoop().Run();
EXPECT_TRUE(host_->new_content_rendering_timeout_fired());
@@ -1926,8 +1688,8 @@ TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
host_->SetMockRendererCompositorFrameSink(
mock_compositor_frame_sink_client.get());
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr,
- 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_FALSE(
static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
EXPECT_EQ(viz::BeginFrameAck(0, 1, false),
@@ -1942,8 +1704,8 @@ TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
.AddDefaultRenderPass()
.SetContentSourceId(100)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr,
- 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_TRUE(
static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
static_cast<TestView*>(host_->GetView())->reset_did_swap_compositor_frame();
@@ -1957,405 +1719,13 @@ TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
.AddDefaultRenderPass()
.SetContentSourceId(101)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr,
- 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_TRUE(
static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
}
}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, TouchEmulator) {
- simulated_event_time_delta_seconds_ = 0.1;
- // Immediately ack all touches instead of sending them to the renderer.
- host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
- host_->GetTouchEmulator()->Enable(
- TouchEmulator::Mode::kEmulatingTouchFromMouse,
- ui::GestureProviderConfigType::GENERIC_MOBILE);
- process_->sink().ClearMessages();
- view_->SetBounds(gfx::Rect(0, 0, 400, 200));
- view_->Show();
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10, 0, false);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Mouse press becomes touch start which in turn becomes tap.
- SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 10, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
- EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_));
-
- // Mouse drag generates touch move, cancels tap and starts scroll.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 30, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- SendScrollBeginAckIfneeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(
- "GestureTapCancel GestureScrollBegin TouchScrollStarted "
- "GestureScrollUpdate",
- GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Mouse drag with shift becomes pinch.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 40,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- EXPECT_EQ("GesturePinchBegin",
- GetInputMessageTypes(process_));
- EXPECT_EQ(0U, process_->sink().message_count());
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 50,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- EXPECT_EQ("GesturePinchUpdate",
- GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Mouse drag without shift becomes scroll again.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 60, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- EXPECT_EQ("GesturePinchEnd GestureScrollUpdate",
- GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 70, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- EXPECT_EQ("GestureScrollUpdate",
- GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- SimulateMouseEvent(WebInputEvent::kMouseUp, 10, 70, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchEnd, host_->acked_touch_event_type());
- EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_));
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Mouse move does nothing.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 80, 0, false);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Another mouse down continues scroll.
- SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 80, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
- EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_));
- EXPECT_EQ(0U, process_->sink().message_count());
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 100, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- SendScrollBeginAckIfneeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(
- "GestureTapCancel GestureScrollBegin TouchScrollStarted "
- "GestureScrollUpdate",
- GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Another pinch.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 110,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- EXPECT_EQ("GesturePinchBegin",
- GetInputMessageTypes(process_));
- EXPECT_EQ(0U, process_->sink().message_count());
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 120,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- EXPECT_EQ("GesturePinchUpdate",
- GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kGesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Turn off emulation during a pinch.
- host_->GetTouchEmulator()->Disable();
- EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
- EXPECT_EQ("GesturePinchEnd GestureScrollEnd",
- GetInputMessageTypes(process_));
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Mouse event should pass untouched.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ("MouseMove", GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kMouseMove, INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Turn on emulation.
- host_->GetTouchEmulator()->Enable(
- TouchEmulator::Mode::kEmulatingTouchFromMouse,
- ui::GestureProviderConfigType::GENERIC_MOBILE);
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Another touch.
- SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 10, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
- EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_));
- EXPECT_EQ(0U, process_->sink().message_count());
-
- // Scroll.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 30, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- SendScrollBeginAckIfneeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(
- "GestureTapCancel GestureScrollBegin TouchScrollStarted "
- "GestureScrollUpdate",
- GetInputMessageTypes(process_));
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Turn off emulation during a scroll.
- host_->GetTouchEmulator()->Disable();
- EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
-
- EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_));
- EXPECT_EQ(0U, process_->sink().message_count());
-}
-
-TEST_F(RenderWidgetHostTest, TouchEmulator) {
- simulated_event_time_delta_seconds_ = 0.1;
- // Immediately ack all touches instead of sending them to the renderer.
- host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
- host_->GetTouchEmulator()->Enable(
- TouchEmulator::Mode::kEmulatingTouchFromMouse,
- ui::GestureProviderConfigType::GENERIC_MOBILE);
- process_->sink().ClearMessages();
- view_->SetBounds(gfx::Rect(0, 0, 400, 200));
- view_->Show();
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10, 0, false);
- MockWidgetInputHandler::MessageVector dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- EXPECT_EQ(0u, dispatched_events.size());
-
- // Mouse press becomes touch start which in turn becomes tap.
- SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 10, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureTapDown,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
-
- // Mouse drag generates touch move, cancels tap and starts scroll.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 30, 0, true);
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(4u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- ASSERT_TRUE(dispatched_events[1]->ToEvent());
- ASSERT_TRUE(dispatched_events[2]->ToEvent());
- ASSERT_TRUE(dispatched_events[3]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureTapCancel,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
- dispatched_events[1]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kTouchScrollStarted,
- dispatched_events[2]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_events[3]->ToEvent()->Event()->web_event->GetType());
- dispatched_events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- EXPECT_EQ(
- 0u,
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages().size());
- dispatched_events[3]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- // Mouse drag with shift becomes pinch.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 40,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
-
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGesturePinchBegin,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 50,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
-
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
-
- dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Mouse drag without shift becomes scroll again.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 60, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
-
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(2u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- ASSERT_TRUE(dispatched_events[1]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_events[1]->ToEvent()->Event()->web_event->GetType());
- dispatched_events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 70, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- SimulateMouseEvent(WebInputEvent::kMouseUp, 10, 70, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchEnd, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
-
- // Mouse move does nothing.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 80, 0, false);
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- EXPECT_EQ(0u, dispatched_events.size());
-
- // Another mouse down continues scroll.
- SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 80, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureTapDown,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 100, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(4u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- ASSERT_TRUE(dispatched_events[1]->ToEvent());
- ASSERT_TRUE(dispatched_events[2]->ToEvent());
- ASSERT_TRUE(dispatched_events[3]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureTapCancel,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
- dispatched_events[1]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kTouchScrollStarted,
- dispatched_events[2]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_events[3]->ToEvent()->Event()->web_event->GetType());
- dispatched_events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(
- 0u,
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages().size());
- dispatched_events[3]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- // Another pinch.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 110,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- EXPECT_EQ(1u, dispatched_events.size());
- EXPECT_EQ(WebInputEvent::kGesturePinchBegin,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 120,
- WebInputEvent::kShiftKey, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- EXPECT_EQ(1u, dispatched_events.size());
- EXPECT_EQ(WebInputEvent::kGesturePinchUpdate,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Turn off emulation during a pinch.
- host_->GetTouchEmulator()->Disable();
- EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(2u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- ASSERT_TRUE(dispatched_events[1]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGesturePinchEnd,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
- dispatched_events[1]->ToEvent()->Event()->web_event->GetType());
-
- // Mouse event should pass untouched.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 10,
- WebInputEvent::kShiftKey, true);
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kMouseMove,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Turn on emulation.
- host_->GetTouchEmulator()->Enable(
- TouchEmulator::Mode::kEmulatingTouchFromMouse,
- ui::GestureProviderConfigType::GENERIC_MOBILE);
-
- // Another touch.
- SimulateMouseEvent(WebInputEvent::kMouseDown, 10, 10, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchStart, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureTapDown,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
-
- // Scroll.
- SimulateMouseEvent(WebInputEvent::kMouseMove, 10, 30, 0, true);
- EXPECT_EQ(WebInputEvent::kTouchMove, host_->acked_touch_event_type());
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(4u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- ASSERT_TRUE(dispatched_events[1]->ToEvent());
- ASSERT_TRUE(dispatched_events[2]->ToEvent());
- ASSERT_TRUE(dispatched_events[3]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureTapCancel,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollBegin,
- dispatched_events[1]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kTouchScrollStarted,
- dispatched_events[2]->ToEvent()->Event()->web_event->GetType());
- EXPECT_EQ(WebInputEvent::kGestureScrollUpdate,
- dispatched_events[3]->ToEvent()->Event()->web_event->GetType());
- dispatched_events[1]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(
- 0u,
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages().size());
- dispatched_events[3]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Turn off emulation during a scroll.
- host_->GetTouchEmulator()->Disable();
- EXPECT_EQ(WebInputEvent::kTouchCancel, host_->acked_touch_event_type());
-
- dispatched_events =
- host_->mock_widget_input_handler_.GetAndResetDispatchedMessages();
- ASSERT_EQ(1u, dispatched_events.size());
- ASSERT_TRUE(dispatched_events[0]->ToEvent());
- EXPECT_EQ(WebInputEvent::kGestureScrollEnd,
- dispatched_events[0]->ToEvent()->Event()->web_event->GetType());
-}
-
TEST_F(RenderWidgetHostTest, IgnoreInputEvent) {
host_->SetupForInputRouterTest();
@@ -2437,30 +1807,6 @@ TEST_F(RenderWidgetHostTest, MouseEventCallbackCanHandleEvent) {
EXPECT_TRUE(host_->mock_input_router()->sent_mouse_event_);
}
-TEST_F(RenderWidgetHostTest, InputRouterReceivesHandleInputEvent_ACK) {
- host_->SetupForInputRouterTest();
-
- SendInputEventACK(WebInputEvent::kRawKeyDown, INPUT_EVENT_ACK_STATE_CONSUMED);
-
- EXPECT_TRUE(host_->mock_input_router()->message_received_);
-}
-
-TEST_F(RenderWidgetHostTest, InputRouterReceivesMoveCaret_ACK) {
- host_->SetupForInputRouterTest();
-
- host_->OnMessageReceived(InputHostMsg_MoveCaret_ACK(0));
-
- EXPECT_TRUE(host_->mock_input_router()->message_received_);
-}
-
-TEST_F(RenderWidgetHostTest, InputRouterReceivesSelectRange_ACK) {
- host_->SetupForInputRouterTest();
-
- host_->OnMessageReceived(InputHostMsg_SelectRange_ACK(0));
-
- EXPECT_TRUE(host_->mock_input_router()->message_received_);
-}
-
TEST_F(RenderWidgetHostTest, InputRouterReceivesHasTouchEventHandlers) {
host_->SetupForInputRouterTest();
@@ -2469,130 +1815,6 @@ TEST_F(RenderWidgetHostTest, InputRouterReceivesHasTouchEventHandlers) {
EXPECT_TRUE(host_->mock_input_router()->message_received_);
}
-void CheckLatencyInfoComponentInMessage(RenderWidgetHostProcess* process,
- int64_t component_id,
- WebInputEvent::Type expected_type) {
- EXPECT_EQ(process->sink().message_count(), 1U);
-
- const IPC::Message* message = process->sink().GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(InputMsg_HandleInputEvent::ID),
- message->type());
- InputMsg_HandleInputEvent::Param params;
- EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
-
- const WebInputEvent* event = std::get<0>(params);
- ui::LatencyInfo latency_info = std::get<2>(params);
-
- EXPECT_TRUE(event->GetType() == expected_type);
- EXPECT_TRUE(latency_info.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, component_id, nullptr));
-
- process->sink().ClearMessages();
-}
-
-void CheckLatencyInfoComponentInGestureScrollUpdate(
- RenderWidgetHostProcess* process,
- int64_t component_id) {
- EXPECT_EQ(process->sink().message_count(), 2U);
- const IPC::Message* message = process->sink().GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(InputMsg_HandleInputEvent::ID),
- message->type());
- InputMsg_HandleInputEvent::Param params;
- EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
-
- const WebInputEvent* event = std::get<0>(params);
- ui::LatencyInfo latency_info = std::get<2>(params);
-
- EXPECT_TRUE(event->GetType() == WebInputEvent::kTouchScrollStarted);
-
- message = process->sink().GetMessageAt(1);
- EXPECT_EQ(static_cast<uint32_t>(InputMsg_HandleInputEvent::ID),
- message->type());
- EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
-
- event = std::get<0>(params);
- latency_info = std::get<2>(params);
-
- EXPECT_TRUE(event->GetType() == WebInputEvent::kGestureScrollUpdate);
- EXPECT_TRUE(latency_info.FindLatency(
- ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, component_id, nullptr));
-
- process->sink().ClearMessages();
-}
-
-// Tests that after input event passes through RWHI through ForwardXXXEvent()
-// or ForwardXXXEventWithLatencyInfo(), LatencyInfo component
-// ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT will always present in the
-// event's LatencyInfo.
-void RenderWidgetHostTest::InputEventRWHLatencyComponentMojoInputDisabled() {
- host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
- process_->sink().ClearMessages();
-
- // Tests RWHI::ForwardWheelEvent().
- SimulateWheelEventPossiblyIncludingPhase(-5, 0, 0, true,
- WebMouseWheelEvent::kPhaseBegan);
- CheckLatencyInfoComponentInMessage(process_, GetLatencyComponentId(),
- WebInputEvent::kMouseWheel);
- SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Tests RWHI::ForwardWheelEventWithLatencyInfo().
- SimulateWheelEventWithLatencyInfoAndPossiblyPhase(
- -5, 0, 0, true, ui::LatencyInfo(), WebMouseWheelEvent::kPhaseChanged);
- CheckLatencyInfoComponentInMessage(process_, GetLatencyComponentId(),
- WebInputEvent::kMouseWheel);
- SendInputEventACK(WebInputEvent::kMouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Tests RWHI::ForwardMouseEvent().
- SimulateMouseEvent(WebInputEvent::kMouseMove);
- CheckLatencyInfoComponentInMessage(process_, GetLatencyComponentId(),
- WebInputEvent::kMouseMove);
- SendInputEventACK(WebInputEvent::kMouseMove, INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Tests RWHI::ForwardMouseEventWithLatencyInfo().
- SimulateMouseEventWithLatencyInfo(WebInputEvent::kMouseMove,
- ui::LatencyInfo());
- CheckLatencyInfoComponentInMessage(process_, GetLatencyComponentId(),
- WebInputEvent::kMouseMove);
- SendInputEventACK(WebInputEvent::kMouseMove, INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Tests RWHI::ForwardGestureEvent().
- SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
- blink::kWebGestureDeviceTouchscreen);
- SendScrollBeginAckIfneeded(INPUT_EVENT_ACK_STATE_CONSUMED);
- CheckLatencyInfoComponentInMessage(process_, GetLatencyComponentId(),
- WebInputEvent::kGestureScrollBegin);
-
- // Tests RWHI::ForwardGestureEventWithLatencyInfo().
- SimulateGestureEventWithLatencyInfo(WebInputEvent::kGestureScrollUpdate,
- blink::kWebGestureDeviceTouchscreen,
- ui::LatencyInfo());
- CheckLatencyInfoComponentInGestureScrollUpdate(process_,
- GetLatencyComponentId());
- SendInputEventACK(WebInputEvent::kGestureScrollUpdate,
- INPUT_EVENT_ACK_STATE_CONSUMED);
-
- // Tests RWHI::ForwardTouchEventWithLatencyInfo().
- PressTouchPoint(0, 1);
- uint32_t touch_event_id = SendTouchEvent();
- InputEventAck ack(InputEventAckSource::COMPOSITOR_THREAD,
- WebInputEvent::kTouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
- touch_event_id);
- host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
- CheckLatencyInfoComponentInMessage(process_, GetLatencyComponentId(),
- WebInputEvent::kTouchStart);
-}
-TEST_F(RenderWidgetHostMojoInputDisabledTest, InputEventRWHLatencyComponent) {
- InputEventRWHLatencyComponentMojoInputDisabled();
-}
-TEST_F(RenderWidgetHostWheelScrollLatchingMojoInputDisabledTest,
- InputEventRWHLatencyComponent) {
- InputEventRWHLatencyComponentMojoInputDisabled();
-}
-TEST_F(RenderWidgetHostAsyncWheelEventsEnabledMojoInputDisabledTest,
- InputEventRWHLatencyComponent) {
- InputEventRWHLatencyComponentMojoInputDisabled();
-}
-
void CheckLatencyInfoComponentInMessage(
MockWidgetInputHandler::MessageVector& dispatched_events,
int64_t component_id,
@@ -2723,20 +1945,21 @@ TEST_F(RenderWidgetHostTest, RendererExitedResetsIsHidden) {
ASSERT_FALSE(host_->input_router()->HasPendingEvents());
}
-TEST_F(RenderWidgetHostTest, ResizeParams) {
+TEST_F(RenderWidgetHostTest, VisualProperties) {
gfx::Rect bounds(0, 0, 100, 100);
gfx::Size compositor_viewport_pixel_size(40, 50);
view_->SetBounds(bounds);
view_->SetMockCompositorViewportPixelSize(compositor_viewport_pixel_size);
- ResizeParams resize_params;
- host_->GetResizeParams(&resize_params);
- EXPECT_EQ(bounds.size(), resize_params.new_size);
+ VisualProperties visual_properties;
+ bool needs_ack = false;
+ host_->GetVisualProperties(&visual_properties, &needs_ack);
+ EXPECT_EQ(bounds.size(), visual_properties.new_size);
EXPECT_EQ(compositor_viewport_pixel_size,
- resize_params.compositor_viewport_pixel_size);
+ visual_properties.compositor_viewport_pixel_size);
}
-TEST_F(RenderWidgetHostTest, ResizeParamsDeviceScale) {
+TEST_F(RenderWidgetHostTest, VisualPropertiesDeviceScale) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII(switches::kEnableUseZoomForDSF, "true");
@@ -2745,19 +1968,20 @@ TEST_F(RenderWidgetHostTest, ResizeParamsDeviceScale) {
screen_info.device_scale_factor = device_scale;
view_->SetScreenInfo(screen_info);
- host_->WasResized();
+ host_->SynchronizeVisualProperties();
float top_controls_height = 10.0f;
float bottom_controls_height = 20.0f;
view_->set_top_controls_height(top_controls_height);
view_->set_bottom_controls_height(bottom_controls_height);
- ResizeParams resize_params;
- host_->GetResizeParams(&resize_params);
+ VisualProperties visual_properties;
+ bool needs_ack = false;
+ host_->GetVisualProperties(&visual_properties, &needs_ack);
EXPECT_EQ(top_controls_height * device_scale,
- resize_params.top_controls_height);
+ visual_properties.top_controls_height);
EXPECT_EQ(bottom_controls_height * device_scale,
- resize_params.bottom_controls_height);
+ visual_properties.bottom_controls_height);
}
// Make sure no dragging occurs after renderer exited. See crbug.com/704832.
@@ -2799,12 +2023,29 @@ class RenderWidgetHostInitialSizeTest : public RenderWidgetHostTest {
TEST_F(RenderWidgetHostInitialSizeTest, InitialSize) {
// Having an initial size set means that the size information had been sent
- // with the reqiest to new up the RenderView and so subsequent WasResized
- // calls should not result in new IPC (unless the size has actually changed).
- host_->WasResized();
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
- EXPECT_EQ(initial_size_, host_->old_resize_params_->new_size);
- EXPECT_TRUE(host_->resize_ack_pending_);
+ // with the reqiest to new up the RenderView and so subsequent
+ // SynchronizeVisualProperties calls should not result in new IPC (unless the
+ // size has actually changed).
+ EXPECT_FALSE(host_->SynchronizeVisualProperties());
+ EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+ EXPECT_EQ(initial_size_, host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(host_->visual_properties_ack_pending_);
+}
+
+TEST_F(RenderWidgetHostTest, HideUnthrottlesResize) {
+ gfx::Size original_size(100, 100);
+ view_->SetBounds(gfx::Rect(original_size));
+ process_->sink().ClearMessages();
+ EXPECT_TRUE(host_->SynchronizeVisualProperties());
+ EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID));
+ EXPECT_EQ(original_size, host_->old_visual_properties_->new_size);
+ EXPECT_TRUE(host_->visual_properties_ack_pending_);
+
+ // Hiding the widget should unthrottle resize.
+ host_->WasHidden();
+ EXPECT_FALSE(host_->visual_properties_ack_pending_);
}
// Tests that event dispatch after the delegate has been detached doesn't cause
@@ -2847,7 +2088,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_MessageThenFrame) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
}
@@ -2868,7 +2110,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_FrameThenMessage) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2907,7 +2150,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token1)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
@@ -2915,7 +2159,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(2u, host_->processed_frame_messages_count());
}
@@ -2939,7 +2184,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token1)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2947,7 +2193,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2991,7 +2238,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_DroppedFrame) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(2u, host_->processed_frame_messages_count());
}
@@ -3035,7 +2283,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token2)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -3054,7 +2303,8 @@ TEST_F(RenderWidgetHostTest, FrameToken_RendererCrash) {
.AddDefaultRenderPass()
.SetFrameToken(frame_token3)
.Build();
- host_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr, 0);
+ host_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt, 0);
EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
EXPECT_EQ(1u, host_->processed_frame_messages_count());
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.cc b/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
index 18be0d64dcf..c0cefeddd6b 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -24,6 +24,7 @@
#include "cc/layers/surface_layer.h"
#include "cc/trees/latency_info_swap_promise.h"
#include "cc/trees/layer_tree_host.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
@@ -156,17 +157,6 @@ void WakeUpGpu(GpuProcessHost* host) {
} // namespace
-void RenderWidgetHostViewAndroid::OnContextLost() {
- std::unique_ptr<RenderWidgetHostIterator> widgets(
- RenderWidgetHostImpl::GetAllRenderWidgetHosts());
- while (RenderWidgetHost* widget = widgets->GetNextHost()) {
- if (widget->GetView()) {
- static_cast<RenderWidgetHostViewAndroid*>(widget->GetView())
- ->OnLostResources();
- }
- }
-}
-
RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
RenderWidgetHostImpl* widget_host,
gfx::NativeView parent_native_view)
@@ -182,9 +172,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
selection_popup_controller_(nullptr),
text_suggestion_host_(nullptr),
gesture_listener_manager_(nullptr),
- background_color_(SK_ColorWHITE),
- cached_background_color_(SK_ColorWHITE),
- view_(this, ui::ViewAndroid::LayoutType::MATCH_PARENT),
+ view_(ui::ViewAndroid::LayoutType::MATCH_PARENT),
gesture_provider_(ui::GetGestureProviderConfig(
ui::GestureProviderConfigType::CURRENT_PLATFORM),
this),
@@ -205,6 +193,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
// Set the layer which will hold the content layer for this view. The content
// layer is managed by the DelegatedFrameHost.
view_.SetLayer(cc::Layer::Create());
+ view_.set_event_handler(this);
if (using_browser_compositor_) {
delegated_frame_host_ = std::make_unique<ui::DelegatedFrameHostAndroid>(
@@ -213,7 +202,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
// Let the page-level input event router know about our frame sink ID
// for surface-based hit testing.
- if (host()->delegate() && host()->delegate()->GetInputEventRouter()) {
+ if (ShouldRouteEvents()) {
host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(
GetFrameSinkId(), this);
}
@@ -232,6 +221,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
UpdateNativeViewTree(nullptr);
+ view_.set_event_handler(nullptr);
DCHECK(!ime_adapter_android_);
DCHECK(ack_callbacks_.empty());
DCHECK(!delegated_frame_host_);
@@ -249,9 +239,6 @@ void RenderWidgetHostViewAndroid::RemoveDestructionObserver(
bool RenderWidgetHostViewAndroid::OnMessageReceived(
const IPC::Message& message) {
- if (IPC_MESSAGE_ID_CLASS(message.type()) == SyncCompositorMsgStart) {
- return SyncCompositorOnMessageReceived(message);
- }
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectWordAroundCaretAck,
@@ -261,12 +248,6 @@ bool RenderWidgetHostViewAndroid::OnMessageReceived(
return handled;
}
-bool RenderWidgetHostViewAndroid::SyncCompositorOnMessageReceived(
- const IPC::Message& message) {
- DCHECK(!view_.parent() || sync_compositor_) << !!view_.parent();
- return sync_compositor_ && sync_compositor_->OnMessageReceived(message);
-}
-
void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
NOTIMPLEMENTED();
}
@@ -281,10 +262,18 @@ void RenderWidgetHostViewAndroid::InitAsFullscreen(
NOTIMPLEMENTED();
}
-void RenderWidgetHostViewAndroid::WasResized() {
- if (delegated_frame_host_)
- delegated_frame_host_->WasResized();
- host()->WasResized();
+bool RenderWidgetHostViewAndroid::SynchronizeVisualProperties() {
+ if (delegated_frame_host_) {
+ delegated_frame_host_->SynchronizeVisualProperties(
+ GetCompositorViewportPixelSize());
+
+ // TODO(ericrk): This can be removed once surface synchronization is
+ // enabled. https://crbug.com/835102
+ delegated_frame_host_->PixelSizeWillChange(
+ GetCompositorViewportPixelSize());
+ }
+
+ return host()->SynchronizeVisualProperties();
}
void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
@@ -532,15 +521,6 @@ void RenderWidgetHostViewAndroid::OnTextSelectionChanged(
base::UTF16ToUTF8(selection.selected_text()));
}
-void RenderWidgetHostViewAndroid::UpdateBackgroundColor(SkColor color) {
- if (cached_background_color_ == color)
- return;
-
- cached_background_color_ = color;
-
- view_.OnBackgroundColorChanged(color);
-}
-
void RenderWidgetHostViewAndroid::SetNeedsBeginFrames(bool needs_begin_frames) {
TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SetNeedsBeginFrames",
"needs_begin_frames", needs_begin_frames);
@@ -565,7 +545,7 @@ viz::SurfaceId RenderWidgetHostViewAndroid::GetCurrentSurfaceId() const {
: viz::SurfaceId();
}
-bool RenderWidgetHostViewAndroid::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewAndroid::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
@@ -599,7 +579,8 @@ bool RenderWidgetHostViewAndroid::TransformPointToLocalCoordSpace(
bool RenderWidgetHostViewAndroid::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) {
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
if (target_view == this || !delegated_frame_host_) {
*transformed_point = point;
return true;
@@ -612,8 +593,8 @@ bool RenderWidgetHostViewAndroid::TransformPointToCoordSpaceForView(
if (!surface_id.is_valid())
return false;
- return target_view->TransformPointToLocalCoordSpace(point, surface_id,
- transformed_point);
+ return target_view->TransformPointToLocalCoordSpace(
+ point, surface_id, transformed_point, source);
}
base::WeakPtr<RenderWidgetHostViewAndroid>
@@ -630,7 +611,9 @@ bool RenderWidgetHostViewAndroid::OnGestureEvent(
web_event = ui::CreateWebGestureEventFromGestureEventAndroid(
ui::GestureEventAndroid(event.type(), event.location(),
event.screen_location(), event.time(), delta, 0,
- 0, 0, 0, false, false));
+ 0, 0, 0, /*target_viewport*/ false,
+ /*synthetic_scroll*/ false,
+ /*prevent_boosting*/ false));
} else {
web_event = ui::CreateWebGestureEventFromGestureEventAndroid(event);
}
@@ -689,8 +672,8 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
return false;
ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
- if (host()->delegate()->GetInputEventRouter()) {
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+ if (ShouldRouteEvents()) {
host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &web_event,
latency_info);
} else {
@@ -734,11 +717,11 @@ void RenderWidgetHostViewAndroid::ResetGestureDetection() {
if (gesture_provider_.OnTouchEvent(*cancel_event).succeeded) {
bool causes_scrolling = false;
ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
blink::WebTouchEvent web_event = ui::CreateWebTouchEventFromMotionEvent(
*cancel_event, causes_scrolling /* may_cause_scrolling */,
false /* hovering */);
- if (host()->delegate()->GetInputEventRouter()) {
+ if (ShouldRouteEvents()) {
host()->delegate()->GetInputEventRouter()->RouteTouchEvent(
this, &web_event, latency_info);
} else {
@@ -792,17 +775,11 @@ void RenderWidgetHostViewAndroid::SetTooltipText(
// Tooltips don't makes sense on Android.
}
-void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color) {
- background_color_ = color;
+void RenderWidgetHostViewAndroid::UpdateBackgroundColor() {
+ DCHECK(RenderWidgetHostViewBase::GetBackgroundColor());
- DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
- SkColorGetA(color) == SK_AlphaTRANSPARENT);
- host()->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
- UpdateBackgroundColor(color);
-}
-
-SkColor RenderWidgetHostViewAndroid::background_color() const {
- return background_color_;
+ SkColor color = *RenderWidgetHostViewBase::GetBackgroundColor();
+ view_.OnBackgroundColorChanged(color);
}
void RenderWidgetHostViewAndroid::CopyFromSurface(
@@ -839,6 +816,15 @@ void RenderWidgetHostViewAndroid::CopyFromSurface(
std::move(callback), start_time));
}
+void RenderWidgetHostViewAndroid::EnsureSurfaceSynchronizedForLayoutTest() {
+ ++latest_capture_sequence_number_;
+ SynchronizeVisualProperties();
+}
+
+uint32_t RenderWidgetHostViewAndroid::GetCaptureSequenceNumber() const {
+ return latest_capture_sequence_number_;
+}
+
void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
if (!tap_disambiguator_)
@@ -857,6 +843,12 @@ RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
new SyntheticGestureTargetAndroid(host(), &view_));
}
+bool RenderWidgetHostViewAndroid::ShouldRouteEvents() const {
+ DCHECK(host());
+ return using_browser_compositor_ && host()->delegate() &&
+ host()->delegate()->GetInputEventRouter();
+}
+
void RenderWidgetHostViewAndroid::SendReclaimCompositorResources(
bool is_swap_ack) {
DCHECK(host());
@@ -905,6 +897,10 @@ void RenderWidgetHostViewAndroid::OnFrameTokenChanged(uint32_t frame_token) {
OnFrameTokenChangedForView(frame_token);
}
+void RenderWidgetHostViewAndroid::DidReceiveFirstFrameAfterNavigation() {
+ host_->DidReceiveFirstFrameAfterNavigation();
+}
+
void RenderWidgetHostViewAndroid::DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
if (!delegated_frame_host_) {
@@ -937,14 +933,14 @@ void RenderWidgetHostViewAndroid::EvictFrameIfNecessary() {
current_surface_size_.width() == view_.GetPhysicalBackingSize().width();
if (!is_width_same) {
EvictDelegatedFrame();
- UpdateBackgroundColor(SK_ColorBLACK);
+ SetContentBackgroundColor(SK_ColorBLACK);
}
}
void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) {
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) {
if (!delegated_frame_host_) {
DCHECK(!using_browser_compositor_);
return;
@@ -1026,6 +1022,10 @@ void RenderWidgetHostViewAndroid::ClearCompositorFrame() {
DestroyDelegatedContent();
}
+bool RenderWidgetHostViewAndroid::RequestRepaintForTesting() {
+ return SynchronizeVisualProperties();
+}
+
void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
viz::CompositorFrameMetadata frame_metadata) {
if (!view_.parent())
@@ -1084,20 +1084,23 @@ void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
void RenderWidgetHostViewAndroid::MoveRangeSelectionExtent(
const gfx::PointF& extent) {
- DCHECK(selection_popup_controller_);
+ if (!selection_popup_controller_)
+ return;
selection_popup_controller_->MoveRangeSelectionExtent(extent);
}
void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
const gfx::PointF& base,
const gfx::PointF& extent) {
- DCHECK(selection_popup_controller_);
+ if (!selection_popup_controller_)
+ return;
selection_popup_controller_->SelectBetweenCoordinates(base, extent);
}
void RenderWidgetHostViewAndroid::OnSelectionEvent(
ui::SelectionEventType event) {
- DCHECK(selection_popup_controller_);
+ if (!selection_popup_controller_)
+ return;
DCHECK(touch_selection_controller_);
// If a selection drag has started, it has taken over the active touch
// sequence. Immediately cancel gesture detection and any downstream touch
@@ -1111,7 +1114,8 @@ void RenderWidgetHostViewAndroid::OnSelectionEvent(
}
void RenderWidgetHostViewAndroid::OnDragUpdate(const gfx::PointF& position) {
- DCHECK(selection_popup_controller_);
+ if (!selection_popup_controller_)
+ return;
selection_popup_controller_->OnDragUpdate(position);
}
@@ -1136,7 +1140,8 @@ RenderWidgetHostViewAndroid::CreateDrawable() {
return std::unique_ptr<ui::TouchHandleDrawable>(
sync_compositor_->client()->CreateDrawable());
}
- DCHECK(selection_popup_controller_);
+ if (!selection_popup_controller_)
+ return nullptr;
return selection_popup_controller_->CreateTouchHandleDrawable();
}
@@ -1208,9 +1213,6 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
}
float to_pix = IsUseZoomForDSFEnabled() ? 1.f : dip_scale;
- float top_controls_pix = frame_metadata.top_controls_height * to_pix;
- // |top_content_offset| is in physical pixels if --use-zoom-for-dsf is
- // enabled. Otherwise, it is in DIPs.
// Note that the height of browser control is not affected by page scale
// factor. Thus, |top_content_offset| in CSS pixels is also in DIPs.
float top_content_offset = frame_metadata.top_controls_height *
@@ -1223,7 +1225,7 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
auto* wcax = GetWebContentsAccessibilityAndroid();
if (wcax)
- wcax->UpdateFrameInfo();
+ wcax->UpdateFrameInfo(frame_metadata.page_scale_factor);
if (!gesture_listener_manager_)
return;
@@ -1248,60 +1250,90 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
touch_selection_controller_->OnViewportChanged(viewport_rect);
}
- UpdateBackgroundColor(is_transparent ? SK_ColorTRANSPARENT
- : frame_metadata.root_background_color);
+ SetContentBackgroundColor(is_transparent
+ ? SK_ColorTRANSPARENT
+ : frame_metadata.root_background_color);
// ViewAndroid::content_offset() must be in CSS scale
float top_content_offset_dip = IsUseZoomForDSFEnabled()
? top_content_offset / dip_scale
: top_content_offset;
view_.UpdateFrameInfo({scrollable_viewport_size_dip, top_content_offset});
-
- bool top_changed = !FloatEquals(top_shown_pix, prev_top_shown_pix_);
- // TODO(carlosil, https://crbug.com/825765): Remove the IsInVR() check here,
- // which is a temporary hack. Interstitial pages are not committed navigations
- // and their metadata updates never leave the content layer, so Chrome and the
- // content layer end up mismatched and hit testing is offset. They rely on the
- // previous (erroneous) behavior of ignoring the initial control offset update
- // if offset is 0. The fix is still crucial for VR as VR needs the top
- // controls to be initially hidden correctly (so we don't want the offset of 0
- // to get ignored. Tracking bug for the interstitial work to fix this by
- // converting interstitials to committed navigations is
- // https://crbug.com/755632.
- float top_translate = top_shown_pix - top_controls_pix;
- if (top_changed || (!controls_initialized_ && IsInVR())) {
- view_.OnTopControlsChanged(top_translate, top_shown_pix);
- }
- prev_top_shown_pix_ = top_shown_pix;
- prev_top_controls_translate_ = top_translate;
-
- float bottom_controls_pix = frame_metadata.bottom_controls_height * to_pix;
- float bottom_shown_pix =
- bottom_controls_pix * frame_metadata.bottom_controls_shown_ratio;
- bool bottom_changed = !FloatEquals(bottom_shown_pix, prev_bottom_shown_pix_);
- float bottom_translate = bottom_controls_pix - bottom_shown_pix;
- if (bottom_changed || (!controls_initialized_ && IsInVR())) {
- view_.OnBottomControlsChanged(bottom_translate, bottom_shown_pix);
- }
- prev_bottom_shown_pix_ = bottom_shown_pix;
- prev_bottom_controls_translate_ = bottom_translate;
- controls_initialized_ = true;
+ bool controls_changed =
+ features::IsSurfaceSynchronizationEnabled()
+ ? false
+ : UpdateControls(view_.GetDipScale(),
+ frame_metadata.top_controls_height,
+ frame_metadata.top_controls_shown_ratio,
+ frame_metadata.bottom_controls_height,
+ frame_metadata.bottom_controls_shown_ratio);
page_scale_ = frame_metadata.page_scale_factor;
min_page_scale_ = frame_metadata.min_page_scale_factor;
max_page_scale_ = frame_metadata.max_page_scale_factor;
// All offsets and sizes except |top_shown_pix| are in CSS pixels.
+ // TODO(fsamuel): This needs to be synchronized with RenderFrameMetadata when
+ // surface synchronization is enabled.
gesture_listener_manager_->UpdateScrollInfo(
root_scroll_offset_dip, frame_metadata.page_scale_factor,
frame_metadata.min_page_scale_factor,
frame_metadata.max_page_scale_factor, root_layer_size_dip,
scrollable_viewport_size_dip, top_content_offset_dip, top_shown_pix,
- top_changed);
+ controls_changed);
EvictFrameIfNecessary();
}
+bool RenderWidgetHostViewAndroid::UpdateControls(
+ float dip_scale,
+ float top_controls_height,
+ float top_controls_shown_ratio,
+ float bottom_controls_height,
+ float bottom_controls_shown_ratio) {
+ float to_pix = IsUseZoomForDSFEnabled() ? 1.f : dip_scale;
+ float top_controls_pix = top_controls_height * to_pix;
+ // |top_content_offset| is in physical pixels if --use-zoom-for-dsf is
+ // enabled. Otherwise, it is in DIPs.
+ // Note that the height of browser control is not affected by page scale
+ // factor. Thus, |top_content_offset| in CSS pixels is also in DIPs.
+ float top_content_offset = top_controls_height * top_controls_shown_ratio;
+ float top_shown_pix = top_content_offset * to_pix;
+ float top_translate = top_shown_pix - top_controls_pix;
+ bool top_changed = !FloatEquals(top_shown_pix, prev_top_shown_pix_);
+ // TODO(mthiesse, https://crbug.com/853686): Remove the IsInVR check once
+ // there are no use cases for ignoring the initial update.
+ if (top_changed || (!controls_initialized_ && IsInVR()))
+ view_.OnTopControlsChanged(top_translate, top_shown_pix);
+ prev_top_shown_pix_ = top_shown_pix;
+ prev_top_controls_translate_ = top_translate;
+
+ float bottom_controls_pix = bottom_controls_height * to_pix;
+ float bottom_shown_pix = bottom_controls_pix * bottom_controls_shown_ratio;
+ bool bottom_changed = !FloatEquals(bottom_shown_pix, prev_bottom_shown_pix_);
+ float bottom_translate = bottom_controls_pix - bottom_shown_pix;
+ if (bottom_changed || (!controls_initialized_ && IsInVR()))
+ view_.OnBottomControlsChanged(bottom_translate, bottom_shown_pix);
+ prev_bottom_shown_pix_ = bottom_shown_pix;
+ prev_bottom_controls_translate_ = bottom_translate;
+ controls_initialized_ = true;
+ return top_changed || bottom_changed;
+}
+
+void RenderWidgetHostViewAndroid::OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata) {
+ if (delegated_frame_host_->GetLocalSurfaceIdAllocator()->UpdateFromChild(
+ metadata.local_surface_id.value_or(viz::LocalSurfaceId()))) {
+ // A synchronization event was initiated by the renderer so let's updated
+ // the top/bottom bar controls now.
+ UpdateControls(view_.GetDipScale(), metadata.top_controls_height,
+ metadata.top_controls_shown_ratio,
+ metadata.bottom_controls_height,
+ metadata.bottom_controls_shown_ratio);
+ }
+ host()->SynchronizeVisualProperties();
+}
+
void RenderWidgetHostViewAndroid::ShowInternal() {
bool show = is_showing_ && is_window_activity_started_ && is_window_visible_;
if (!show)
@@ -1461,7 +1493,7 @@ void RenderWidgetHostViewAndroid::SendBeginFrame(viz::BeginFrameArgs args) {
bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
bool needs_animate = false;
- if (overscroll_controller_ && !is_in_vr_) {
+ if (overscroll_controller_) {
needs_animate |=
overscroll_controller_->Animate(frame_time, view_.parent()->GetLayer());
}
@@ -1481,8 +1513,9 @@ void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
DestroyDelegatedContent();
}
-gfx::Vector2d RenderWidgetHostViewAndroid::GetOffsetFromRootSurface() {
- return gfx::Vector2d(
+void RenderWidgetHostViewAndroid::TransformPointToRootSurface(
+ gfx::PointF* point) {
+ *point += gfx::Vector2d(
0, DoBrowserControlsShrinkBlinkSize() ? GetTopControlsHeight() : 0);
}
@@ -1617,7 +1650,7 @@ void RenderWidgetHostViewAndroid::SendKeyEvent(
event.GetType() == blink::WebInputEvent::kChar) {
latency_info.set_source_event_type(ui::SourceEventType::KEY_PRESS);
}
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
target_host->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
}
@@ -1647,7 +1680,7 @@ void RenderWidgetHostViewAndroid::SendMouseEvent(
if (!host() || !host()->delegate())
return;
- if (host()->delegate()->GetInputEventRouter()) {
+ if (ShouldRouteEvents()) {
host()->delegate()->GetInputEventRouter()->RouteMouseEvent(
this, &mouse_event, ui::LatencyInfo());
} else {
@@ -1685,14 +1718,14 @@ void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
return;
ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
blink::WebMouseWheelEvent wheel_event(event);
- bool should_route_event = !!host()->delegate()->GetInputEventRouter();
+ bool should_route_events = ShouldRouteEvents();
if (wheel_scroll_latching_enabled()) {
mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
- wheel_event, should_route_event);
+ wheel_event, should_route_events);
}
- if (should_route_event) {
+ if (should_route_events) {
host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
this, &wheel_event, latency_info);
} else {
@@ -1719,9 +1752,7 @@ void RenderWidgetHostViewAndroid::SendGestureEvent(
switch (event.GetType()) {
case blink::WebInputEvent::kGestureLongPress:
touch_selection_controller_->HandleLongPressEvent(
- base::TimeTicks() +
- base::TimeDelta::FromSecondsD(event.TimeStampSeconds()),
- event.PositionInWidget());
+ event.TimeStamp(), event.PositionInWidget());
break;
case blink::WebInputEvent::kGestureTap:
@@ -1763,8 +1794,7 @@ void RenderWidgetHostViewAndroid::SendGestureEvent(
mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
}
}
- bool should_route_event = !!host()->delegate()->GetInputEventRouter();
- if (should_route_event) {
+ if (ShouldRouteEvents()) {
blink::WebGestureEvent gesture_event(event);
host()->delegate()->GetInputEventRouter()->RouteGestureEvent(
this, &gesture_event, latency_info);
@@ -1788,8 +1818,9 @@ void RenderWidgetHostViewAndroid::ResolveTapDisambiguation(
bool is_long_press) {
DCHECK(host());
host()->Send(new ViewMsg_ResolveTapDisambiguation(
- host()->GetRoutingID(), timestamp_seconds, tap_viewport_offset,
- is_long_press));
+ host()->GetRoutingID(),
+ base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp_seconds),
+ tap_viewport_offset, is_long_press));
}
void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
@@ -1819,8 +1850,9 @@ void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(
handles_hidden_by_selection_ui_ || handles_hidden_by_stylus_);
}
-SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
- return cached_background_color_;
+base::Optional<SkColor> RenderWidgetHostViewAndroid::GetCachedBackgroundColor()
+ const {
+ return RenderWidgetHostViewBase::GetBackgroundColor();
}
void RenderWidgetHostViewAndroid::SetIsInVR(bool is_in_vr) {
@@ -1834,7 +1866,7 @@ void RenderWidgetHostViewAndroid::SetIsInVR(bool is_in_vr) {
}
if (is_in_vr_ && controls_initialized_) {
- // TODO(carlosil, https://crbug.com/825765): See the TODO in
+ // TODO(mthiesse, https://crbug.com/825765): See the TODO in
// RenderWidgetHostViewAndroid::OnFrameMetadataUpdated. RWHVA isn't
// initialized with VR state so the initial frame metadata top controls
// height can be dropped when a new RWHVA is created.
@@ -1919,7 +1951,7 @@ void RenderWidgetHostViewAndroid::UpdateNativeViewTree(
StartObservingRootWindow();
if (resize)
- WasResized();
+ SynchronizeVisualProperties();
if (!touch_selection_controller_) {
ui::TouchSelectionControllerClient* client =
@@ -1933,6 +1965,11 @@ void RenderWidgetHostViewAndroid::UpdateNativeViewTree(
CreateOverscrollControllerIfPossible();
}
+MouseWheelPhaseHandler*
+RenderWidgetHostViewAndroid::GetMouseWheelPhaseHandler() {
+ return &mouse_wheel_phase_handler_;
+}
+
void RenderWidgetHostViewAndroid::RunAckCallbacks() {
while (!ack_callbacks_.empty()) {
ack_callbacks_.front().Run();
@@ -2000,7 +2037,7 @@ void RenderWidgetHostViewAndroid::OnSizeChanged() {
void RenderWidgetHostViewAndroid::OnPhysicalBackingSizeChanged() {
EvictFrameIfNecessary();
- WasResized();
+ SynchronizeVisualProperties();
}
void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
@@ -2073,12 +2110,12 @@ void RenderWidgetHostViewAndroid::OnBeginFrame(
bool webview_fling = sync_compositor_ && is_currently_scrolling_viewport_;
if (!webview_fling) {
- host_->ProgressFling(args.frame_time);
+ host_->ProgressFlingIfNeeded(args.frame_time);
} else if (sync_compositor_->on_compute_scroll_called()) {
// On Android webview progress the fling only when |OnComputeScroll| is
// called since in some cases Apps override |OnComputeScroll| to cancel
// fling animation.
- host_->ProgressFling(args.frame_time);
+ host_->ProgressFlingIfNeeded(args.frame_time);
}
// Update |last_begin_frame_args_| before handling
@@ -2184,8 +2221,7 @@ void RenderWidgetHostViewAndroid::OnStylusSelectTap(base::TimeTicks time,
// Treat the stylus tap as a long press, activating either a word selection or
// context menu depending on the targetted content.
blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
- blink::WebInputEvent::kGestureLongPress,
- (time - base::TimeTicks()).InSecondsF(), x, y);
+ blink::WebInputEvent::kGestureLongPress, time, x, y);
SendGestureEvent(long_press);
}
@@ -2266,7 +2302,10 @@ void RenderWidgetHostViewAndroid::TakeFallbackContentFrom(
->IsRenderWidgetHostViewChildFrame());
DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)
->IsRenderWidgetHostViewGuest());
- SetBackgroundColor(view->background_color());
+ base::Optional<SkColor> color = view->GetBackgroundColor();
+ if (color)
+ SetBackgroundColor(*color);
+
RenderWidgetHostViewAndroid* view_android =
static_cast<RenderWidgetHostViewAndroid*>(view);
if (!delegated_frame_host_ || !view_android->delegated_frame_host_)
@@ -2276,4 +2315,33 @@ void RenderWidgetHostViewAndroid::TakeFallbackContentFrom(
host()->GetContentRenderingTimeoutFrom(view_android->host());
}
+void RenderWidgetHostViewAndroid::OnSynchronizedDisplayPropertiesChanged() {
+ SynchronizeVisualProperties();
+}
+
+base::Optional<SkColor> RenderWidgetHostViewAndroid::GetBackgroundColor()
+ const {
+ return default_background_color_;
+}
+
+void RenderWidgetHostViewAndroid::DidNavigate() {
+ RenderWidgetHostViewBase::DidNavigate();
+
+ if (delegated_frame_host_)
+ delegated_frame_host_->DidNavigate();
+}
+
+viz::ScopedSurfaceIdAllocator
+RenderWidgetHostViewAndroid::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
+ if (!features::IsSurfaceSynchronizationEnabled())
+ return RenderWidgetHostViewBase::DidUpdateVisualProperties(metadata);
+
+ base::OnceCallback<void()> allocation_task = base::BindOnce(
+ &RenderWidgetHostViewAndroid::OnDidUpdateVisualPropertiesComplete,
+ weak_ptr_factory_.GetWeakPtr(), metadata);
+ return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
+ ;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.h b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
index 472e6316b7a..87b3d601b77 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
@@ -31,9 +31,9 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/android/delegated_frame_host_android.h"
#include "ui/android/view_android.h"
-#include "ui/android/view_client.h"
#include "ui/android/window_android_observer.h"
#include "ui/base/ui_base_types.h"
+#include "ui/events/android/event_handler_android.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -65,16 +65,16 @@ struct ContextMenuParams;
// -----------------------------------------------------------------------------
class CONTENT_EXPORT RenderWidgetHostViewAndroid
: public RenderWidgetHostViewBase,
- public ui::GestureProviderClient,
- public ui::ViewAndroidObserver,
- public ui::ViewClient,
- public ui::WindowAndroidObserver,
- public viz::FrameEvictorClient,
public StylusTextSelectorClient,
- public ui::TouchSelectionControllerClient,
public content::TextInputManager::Observer,
public ui::DelegatedFrameHostAndroid::Client,
- public viz::BeginFrameObserver {
+ public ui::EventHandlerAndroid,
+ public ui::GestureProviderClient,
+ public ui::TouchSelectionControllerClient,
+ public ui::ViewAndroidObserver,
+ public ui::WindowAndroidObserver,
+ public viz::BeginFrameObserver,
+ public viz::FrameEvictorClient {
public:
RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
gfx::NativeView parent_native_view);
@@ -120,6 +120,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const gfx::Rect& src_rect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) override;
+ void EnsureSurfaceSynchronizedForLayoutTest() override;
+ uint32_t GetCaptureSequenceNumber() const override;
bool DoBrowserControlsShrinkBlinkSize() const override;
float GetTopControlsHeight() const override;
float GetBottomControlsHeight() const override;
@@ -132,9 +134,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
int error_code) override;
void Destroy() override;
void SetTooltipText(const base::string16& tooltip_text) override;
- void SetBackgroundColor(SkColor color) override;
- SkColor background_color() const override;
- gfx::Vector2d GetOffsetFromRootSurface() override;
+ void TransformPointToRootSurface(gfx::PointF* point) override;
gfx::Rect GetBoundsInRootWindow() override;
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
@@ -154,9 +154,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) override;
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
+ bool RequestRepaintForTesting() override;
void SetIsInVR(bool is_in_vr) override;
bool IsInVR() const override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
@@ -170,22 +171,29 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SetNeedsBeginFrames(bool needs_begin_frames) override;
void SetWantsAnimateOnlyBeginFrames() override;
viz::FrameSinkId GetFrameSinkId() override;
- bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
- const viz::SurfaceId& original_surface,
- gfx::PointF* transformed_point) override;
+ bool TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point) override;
viz::FrameSinkId GetRootFrameSinkId() override;
viz::SurfaceId GetCurrentSurfaceId() const override;
bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) override;
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY) override;
TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager() override;
viz::LocalSurfaceId GetLocalSurfaceId() const override;
void OnRenderWidgetInit() override;
void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
+ void OnSynchronizedDisplayPropertiesChanged() override;
+ base::Optional<SkColor> GetBackgroundColor() const override;
+ void DidNavigate() override;
+ viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) override;
- // ui::ViewClient implementation.
+ // ui::EventHandlerAndroid implementation.
bool OnTouchEvent(const ui::MotionEventAndroid& m) override;
bool OnMouseEvent(const ui::MotionEventAndroid& m) override;
bool OnMouseWheelEvent(const ui::MotionEventAndroid& event) override;
@@ -241,6 +249,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
+ void DidReceiveFirstFrameAfterNavigation() override;
// viz::BeginFrameObserver implementation.
void OnBeginFrame(const viz::BeginFrameArgs& args) override;
@@ -250,7 +259,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// Non-virtual methods
void UpdateNativeViewTree(gfx::NativeView parent_native_view);
- SkColor GetCachedBackgroundColor() const;
+
+ // Returns the temporary background color of the underlaying document, for
+ // example, returns black during screen rotation.
+ base::Optional<SkColor> GetCachedBackgroundColor() const;
void SendKeyEvent(const NativeWebKeyboardEvent& event);
void SendMouseEvent(const ui::MotionEventAndroid&, int action_button);
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
@@ -284,7 +296,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void SetDoubleTapSupportEnabled(bool enabled);
void SetMultiTouchZoomSupportEnabled(bool enabled);
- void WasResized();
+ bool SynchronizeVisualProperties();
bool HasValidFrame() const;
@@ -306,8 +318,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void OnOverscrollRefreshHandlerAvailable();
- static void OnContextLost();
-
// TextInputManager::Observer overrides.
void OnUpdateTextInputStateCalled(TextInputManager* text_input_manager,
RenderWidgetHostViewBase* updated_view,
@@ -333,22 +343,35 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void GotFocus();
void LostFocus();
+ protected:
+ // RenderWidgetHostViewBase:
+ void UpdateBackgroundColor() override;
+
private:
+ MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
+
void RunAckCallbacks();
+ bool ShouldRouteEvents() const;
void SendReclaimCompositorResources(bool is_swap_ack);
void OnFrameMetadataUpdated(
const viz::CompositorFrameMetadata& frame_metadata,
bool is_transparent);
+ bool UpdateControls(float dip_scale,
+ float top_controls_height,
+ float top_controls_shown_ratio,
+ float bottom_controls_height,
+ float bottom_controls_shown_ratio);
+ void OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata);
+
void ShowInternal();
void HideInternal();
void AttachLayers();
void RemoveLayers();
- void UpdateBackgroundColor(SkColor color);
-
void EvictFrameIfNecessary();
// DevTools ScreenCast support for Android WebView.
@@ -424,12 +447,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
TextSuggestionHostAndroid* text_suggestion_host_;
GestureListenerManager* gesture_listener_manager_;
- // The background color of the widget.
- SkColor background_color_;
-
- // Body background color of the underlying document.
- SkColor cached_background_color_;
-
mutable ui::ViewAndroid view_;
// Manages the Compositor Frames received from the renderer.
@@ -493,6 +510,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
base::ObserverList<DestructionObserver> destruction_observers_;
MouseWheelPhaseHandler mouse_wheel_phase_handler_;
+ uint32_t latest_capture_sequence_number_ = 0u;
base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
index ebf2d257e64..861122e9908 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -14,7 +14,6 @@
#include "base/debug/stack_trace.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -91,6 +90,7 @@
#include "ui/events/event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gestures/gesture_recognizer.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -107,8 +107,8 @@
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
-#include "ui/base/ime/win/osk_display_manager.h"
-#include "ui/base/ime/win/osk_display_observer.h"
+#include "ui/base/ime/input_method_keyboard_controller.h"
+#include "ui/base/ime/input_method_keyboard_controller_observer.h"
#include "ui/base/win/hidden_window.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/gdi_util.h"
@@ -138,26 +138,37 @@ namespace content {
namespace {
+// Callback from embedding the renderer.
+void EmbedCallback(bool result) {
+ if (!result)
+ DVLOG(1) << "embed failed";
+}
+
+} // namespace
+
#if defined(OS_WIN)
-// This class implements the ui::OnScreenKeyboardObserver interface
+// This class implements the ui::InputMethodKeyboardControllerObserver interface
// which provides notifications about the on screen keyboard on Windows getting
// displayed or hidden in response to taps on editable fields.
// It provides functionality to request blink to scroll the input field if it
// is obscured by the on screen keyboard.
-class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver {
+class WinScreenKeyboardObserver
+ : public ui::InputMethodKeyboardControllerObserver {
public:
WinScreenKeyboardObserver(RenderWidgetHostViewAura* host_view)
: host_view_(host_view) {
host_view_->SetInsets(gfx::Insets());
+ if (auto* input_method = host_view_->GetInputMethod())
+ input_method->GetInputMethodKeyboardController()->AddObserver(this);
}
~WinScreenKeyboardObserver() override {
- if (auto* instance = ui::OnScreenKeyboardDisplayManager::GetInstance())
- instance->RemoveObserver(this);
+ if (auto* input_method = host_view_->GetInputMethod())
+ input_method->GetInputMethodKeyboardController()->RemoveObserver(this);
}
- // base::win::OnScreenKeyboardObserver overrides.
+ // InputMethodKeyboardControllerObserver overrides.
void OnKeyboardVisible(const gfx::Rect& keyboard_rect) override {
host_view_->SetInsets(gfx::Insets(
0, 0, keyboard_rect.IsEmpty() ? 0 : keyboard_rect.height(), 0));
@@ -175,14 +186,6 @@ class WinScreenKeyboardObserver : public ui::OnScreenKeyboardObserver {
};
#endif // defined(OS_WIN)
-// Callback from embedding the renderer.
-void EmbedCallback(bool result) {
- if (!result)
- DVLOG(1) << "embed failed";
-}
-
-} // namespace
-
// We need to watch for mouse events outside a Web Popup or its parent
// and dismiss the popup for certain events.
class RenderWidgetHostViewAura::EventFilterForPopupExit
@@ -349,7 +352,6 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(
popup_child_host_view_(nullptr),
is_loading_(false),
has_composition_text_(false),
- background_color_(SK_ColorWHITE),
needs_begin_frames_(false),
added_frame_observer_(false),
cursor_visibility_state_in_renderer_(UNKNOWN),
@@ -578,7 +580,7 @@ void RenderWidgetHostViewAura::SetWantsAnimateOnlyBeginFrames() {
}
void RenderWidgetHostViewAura::OnBeginFrame(base::TimeTicks frame_time) {
- host()->ProgressFling(frame_time);
+ host()->ProgressFlingIfNeeded(frame_time);
UpdateNeedsBeginFramesInternal();
}
@@ -637,6 +639,12 @@ bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
return delegated_frame_host_->CanCopyFromCompositingSurface();
}
+void RenderWidgetHostViewAura::EnsureSurfaceSynchronizedForLayoutTest() {
+ ++latest_capture_sequence_number_;
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseInfiniteDeadline(),
+ base::nullopt);
+}
+
bool RenderWidgetHostViewAura::IsShowing() {
return window_->IsVisible();
}
@@ -650,18 +658,19 @@ void RenderWidgetHostViewAura::WasUnOccluded() {
ui::LatencyInfo renderer_latency_info, browser_latency_info;
if (has_saved_frame) {
browser_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
- host()->GetLatencyComponentId(), 0);
+ host()->GetLatencyComponentId());
browser_latency_info.set_trace_id(++tab_show_sequence_);
} else {
renderer_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
- host()->GetLatencyComponentId(), 0);
+ host()->GetLatencyComponentId());
renderer_latency_info.set_trace_id(++tab_show_sequence_);
}
// If the primary surface was evicted, we should create a new primary.
- if (features::IsSurfaceSynchronizationEnabled() && delegated_frame_host_ &&
+ if (delegated_frame_host_ &&
delegated_frame_host_->IsPrimarySurfaceEvicted()) {
- WasResized(cc::DeadlinePolicy::UseDefaultDeadline());
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
}
TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency",
@@ -714,26 +723,10 @@ gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
return window_->GetBoundsInScreen();
}
-void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
- // The renderer will feed its color back to us with the first CompositorFrame.
- // We short-cut here to show a sensible color before that happens.
- UpdateBackgroundColorFromRenderer(color);
-
- DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
- SkColorGetA(color) == SK_AlphaTRANSPARENT);
- host()->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
-}
-
-SkColor RenderWidgetHostViewAura::background_color() const {
- return background_color_;
-}
-
-void RenderWidgetHostViewAura::UpdateBackgroundColorFromRenderer(
- SkColor color) {
- if (color == background_color())
- return;
- background_color_ = color;
+void RenderWidgetHostViewAura::UpdateBackgroundColor() {
+ DCHECK(GetBackgroundColor());
+ SkColor color = *GetBackgroundColor();
bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE;
window_->layer()->SetFillsBoundsOpaquely(opaque);
window_->layer()->SetColor(color);
@@ -759,24 +752,24 @@ gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
if (insets != insets_) {
insets_ = insets;
- host()->WasResized(!insets_.IsEmpty());
+ host()->SynchronizeVisualProperties(!insets_.IsEmpty());
}
}
-void RenderWidgetHostViewAura::FocusedNodeTouched(
- bool editable) {
+void RenderWidgetHostViewAura::FocusedNodeTouched(bool editable) {
#if defined(OS_WIN)
- ui::OnScreenKeyboardDisplayManager* osk_display_manager =
- ui::OnScreenKeyboardDisplayManager::GetInstance();
- DCHECK(osk_display_manager);
+ auto* input_method = GetInputMethod();
+ if (!input_method)
+ return;
+ auto* controller = input_method->GetInputMethodKeyboardController();
if (editable && host()->GetView() && host()->delegate()) {
keyboard_observer_.reset(new WinScreenKeyboardObserver(this));
- if (!osk_display_manager->DisplayVirtualKeyboard(keyboard_observer_.get()))
+ if (!controller->DisplayVirtualKeyboard())
keyboard_observer_.reset(nullptr);
virtual_keyboard_requested_ = keyboard_observer_.get();
} else {
virtual_keyboard_requested_ = false;
- osk_display_manager->DismissVirtualKeyboard();
+ controller->DismissVirtualKeyboard();
}
#endif
}
@@ -844,6 +837,10 @@ gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
: RenderWidgetHostViewBase::GetRequestedRendererSize();
}
+uint32_t RenderWidgetHostViewAura::GetCaptureSequenceNumber() const {
+ return latest_capture_sequence_number_;
+}
+
void RenderWidgetHostViewAura::CopyFromSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
@@ -883,17 +880,10 @@ void RenderWidgetHostViewAura::DidCreateNewRendererCompositorFrameSink(
void RenderWidgetHostViewAura::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) {
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) {
DCHECK(delegated_frame_host_);
TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
- // Override the background color to the current compositor background.
- // This allows us to, when navigating to a new page, transfer this color to
- // that page. This allows us to pass this background color to new views on
- // navigation.
- // TODO(yiyix): Remove this line when https://crbug.com/830540 is fixed.
- UpdateBackgroundColorFromRenderer(frame.metadata.root_background_color);
-
delegated_frame_host_->SubmitCompositorFrame(
local_surface_id, std::move(frame), std::move(hit_test_region_list));
}
@@ -909,12 +899,18 @@ void RenderWidgetHostViewAura::ClearCompositorFrame() {
delegated_frame_host_->ClearDelegatedFrame();
}
+bool RenderWidgetHostViewAura::RequestRepaintForTesting() {
+ return SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
+}
+
void RenderWidgetHostViewAura::DidStopFlinging() {
selection_controller_client_->OnScrollCompleted();
}
-gfx::Vector2d RenderWidgetHostViewAura::GetOffsetFromRootSurface() {
- return window_->GetBoundsInRootWindow().OffsetFromOrigin();
+void RenderWidgetHostViewAura::TransformPointToRootSurface(gfx::PointF* point) {
+ aura::Window::ConvertPointToTarget(window_, window_->GetRootWindow(), point);
+ window_->GetRootWindow()->transform().TransformPoint(point);
}
gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
@@ -1150,8 +1146,8 @@ void RenderWidgetHostViewAura::UnlockMouse() {
}
bool RenderWidgetHostViewAura::LockKeyboard(
- base::Optional<base::flat_set<int>> keys) {
- return event_handler_->LockKeyboard(std::move(keys));
+ base::Optional<base::flat_set<ui::DomCode>> codes) {
+ return event_handler_->LockKeyboard(std::move(codes));
}
void RenderWidgetHostViewAura::UnlockKeyboard() {
@@ -1162,6 +1158,14 @@ bool RenderWidgetHostViewAura::IsKeyboardLocked() {
return event_handler_->IsKeyboardLocked();
}
+base::flat_map<std::string, std::string>
+RenderWidgetHostViewAura::GetKeyboardLayoutMap() {
+ aura::WindowTreeHost* host = window_->GetHost();
+ if (host)
+ return host->GetKeyboardLayoutMap();
+ return {};
+}
+
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, ui::TextInputClient implementation:
void RenderWidgetHostViewAura::SetCompositionText(
@@ -1311,6 +1315,23 @@ bool RenderWidgetHostViewAura::HasCompositionText() const {
return has_composition_text_;
}
+ui::TextInputClient::FocusReason RenderWidgetHostViewAura::GetFocusReason()
+ const {
+ if (!HasFocus())
+ return ui::TextInputClient::FOCUS_REASON_NONE;
+
+ switch (last_pointer_type_before_focus_) {
+ case ui::EventPointerType::POINTER_TYPE_MOUSE:
+ return ui::TextInputClient::FOCUS_REASON_MOUSE;
+ case ui::EventPointerType::POINTER_TYPE_PEN:
+ return ui::TextInputClient::FOCUS_REASON_PEN;
+ case ui::EventPointerType::POINTER_TYPE_TOUCH:
+ return ui::TextInputClient::FOCUS_REASON_TOUCH;
+ default:
+ return ui::TextInputClient::FOCUS_REASON_OTHER;
+ }
+}
+
bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
if (!text_input_manager_ || !GetFocusedWidget())
return false;
@@ -1440,7 +1461,15 @@ void RenderWidgetHostViewAura::SetTextEditCommandForNextKeyEvent(
ui::TextEditCommand command) {}
const std::string& RenderWidgetHostViewAura::GetClientSourceInfo() const {
- return GetFocusedFrame()->GetLastCommittedURL().spec();
+ RenderFrameHostImpl* frame = GetFocusedFrame();
+ if (frame) {
+ return frame->GetLastCommittedURL().spec();
+ }
+ return base::EmptyString();
+}
+
+bool RenderWidgetHostViewAura::ShouldDoLearning() {
+ return GetTextInputManager() && GetTextInputManager()->should_do_learning();
}
////////////////////////////////////////////////////////////////////////////////
@@ -1580,6 +1609,7 @@ void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
// RenderWidgetHostViewAura, ui::EventHandler implementation:
void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
+ last_pointer_type_ = ui::EventPointerType::POINTER_TYPE_UNKNOWN;
event_handler_->OnKeyEvent(event);
}
@@ -1593,10 +1623,11 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
last_mouse_move_location_ = event->location();
}
#endif
+ last_pointer_type_ = ui::EventPointerType::POINTER_TYPE_MOUSE;
event_handler_->OnMouseEvent(event);
}
-bool RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewAura::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
@@ -1607,7 +1638,7 @@ bool RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
// TODO: this shouldn't be used with aura-mus, so that the null check so
// go away and become a DCHECK.
if (delegated_frame_host_ &&
- !delegated_frame_host_->TransformPointToLocalCoordSpace(
+ !delegated_frame_host_->TransformPointToLocalCoordSpaceLegacy(
point_in_pixels, original_surface, transformed_point))
return false;
*transformed_point =
@@ -1618,7 +1649,8 @@ bool RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
bool RenderWidgetHostViewAura::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) {
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
if (target_view == this || !delegated_frame_host_) {
*transformed_point = point;
return true;
@@ -1628,11 +1660,11 @@ bool RenderWidgetHostViewAura::TransformPointToCoordSpaceForView(
// but it is not necessary here because the final target view is responsible
// for converting before computing the final transform.
return delegated_frame_host_->TransformPointToCoordSpaceForView(
- point, target_view, transformed_point);
+ point, target_view, transformed_point, source);
}
viz::FrameSinkId RenderWidgetHostViewAura::GetRootFrameSinkId() {
- if (window_->GetHost()->compositor())
+ if (window_ && window_->GetHost() && window_->GetHost()->compositor())
return window_->GetHost()->compositor()->frame_sink_id();
return viz::FrameSinkId();
}
@@ -1645,16 +1677,25 @@ viz::SurfaceId RenderWidgetHostViewAura::GetCurrentSurfaceId() const {
void RenderWidgetHostViewAura::FocusedNodeChanged(
bool editable,
const gfx::Rect& node_bounds_in_screen) {
- if (GetInputMethod())
- GetInputMethod()->CancelComposition(this);
+ // The last gesture most likely caused the focus change. The focus reason will
+ // be incorrect if the focus was triggered without a user gesture.
+ // TODO(https://crbug.com/824604): Get the focus reason from the renderer
+ // process instead to get the true focus reason.
+ last_pointer_type_before_focus_ = last_pointer_type_;
+
+ auto* input_method = GetInputMethod();
+ if (input_method)
+ input_method->CancelComposition(this);
has_composition_text_ = false;
#if defined(OS_WIN)
- if (!editable && virtual_keyboard_requested_) {
+ if (!editable && virtual_keyboard_requested_ && window_) {
virtual_keyboard_requested_ = false;
- DCHECK(ui::OnScreenKeyboardDisplayManager::GetInstance());
- ui::OnScreenKeyboardDisplayManager::GetInstance()->DismissVirtualKeyboard();
+ if (input_method) {
+ input_method->GetInputMethodKeyboardController()
+ ->DismissVirtualKeyboard();
+ }
}
#endif
}
@@ -1662,7 +1703,7 @@ void RenderWidgetHostViewAura::FocusedNodeChanged(
void RenderWidgetHostViewAura::ScheduleEmbed(
ui::mojom::WindowTreeClientPtr client,
base::OnceCallback<void(const base::UnguessableToken&)> callback) {
- DCHECK(features::IsMusEnabled());
+ DCHECK(features::IsMashEnabled());
aura::Env::GetInstance()->ScheduleEmbed(std::move(client),
std::move(callback));
}
@@ -1672,10 +1713,12 @@ void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
}
void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
+ last_pointer_type_ = event->pointer_details().pointer_type;
event_handler_->OnTouchEvent(event);
}
void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
+ last_pointer_type_ = event->details().primary_pointer_type();
event_handler_->OnGestureEvent(event);
}
@@ -1797,7 +1840,7 @@ void RenderWidgetHostViewAura::OnRenderFrameMetadataChanged() {
RenderWidgetHostViewBase::OnRenderFrameMetadataChanged();
const cc::RenderFrameMetadata& metadata =
host()->render_frame_metadata_provider()->LastRenderFrameMetadata();
- UpdateBackgroundColorFromRenderer(metadata.root_background_color);
+ SetContentBackgroundColor(metadata.root_background_color);
if (metadata.selection.start != selection_start_ ||
metadata.selection.end != selection_end_) {
@@ -1875,13 +1918,14 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
window_->SetType(type);
window_->Init(ui::LAYER_SOLID_COLOR);
- window_->layer()->SetColor(background_color_);
+ window_->layer()->SetColor(GetBackgroundColor() ? *GetBackgroundColor()
+ : SK_ColorWHITE);
// This needs to happen only after |window_| has been initialized using
// Init(), because it needs to have the layer.
if (frame_sink_id_.is_valid())
window_->SetEmbedFrameSinkId(frame_sink_id_);
- if (!features::IsMusEnabled())
+ if (!features::IsMashEnabled())
return;
// Embed the renderer into the Window.
@@ -1903,8 +1947,7 @@ void RenderWidgetHostViewAura::CreateDelegatedFrameHostClient() {
const bool enable_viz =
base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
delegated_frame_host_ = std::make_unique<DelegatedFrameHost>(
- frame_sink_id_, delegated_frame_host_client_.get(),
- features::IsSurfaceSynchronizationEnabled(), enable_viz,
+ frame_sink_id_, delegated_frame_host_client_.get(), enable_viz,
false /* should_register_frame_sink_id */);
// Let the page-level input event router know about our surface ID
@@ -1981,10 +2024,14 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
}
}
-void RenderWidgetHostViewAura::WasResized(
- const cc::DeadlinePolicy& deadline_policy) {
- window_->AllocateLocalSurfaceId();
- SyncSurfaceProperties(deadline_policy);
+bool RenderWidgetHostViewAura::SynchronizeVisualProperties(
+ const cc::DeadlinePolicy& deadline_policy,
+ const base::Optional<viz::LocalSurfaceId>&
+ child_allocated_local_surface_id) {
+ DCHECK(window_);
+ window_->UpdateLocalSurfaceIdFromEmbeddedClient(
+ child_allocated_local_surface_id);
+ return SyncSurfaceProperties(deadline_policy);
}
ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
@@ -2122,23 +2169,20 @@ void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
#endif
}
-void RenderWidgetHostViewAura::SyncSurfaceProperties(
+bool RenderWidgetHostViewAura::SyncSurfaceProperties(
const cc::DeadlinePolicy& deadline_policy) {
if (IsLocalSurfaceIdAllocationSuppressed())
- return;
+ return false;
if (delegated_frame_host_) {
- delegated_frame_host_->WasResized(window_->GetLocalSurfaceId(),
- window_->bounds().size(),
- deadline_policy);
+ delegated_frame_host_->SynchronizeVisualProperties(
+ window_->GetLocalSurfaceId(), window_->bounds().size(),
+ deadline_policy);
}
// Note that |host_| will retrieve resize parameters from
- // |delegated_frame_host_|, so it must have WasResized called after.
- host()->WasResized();
- if (host()->auto_resize_enabled()) {
- host()->DidAllocateLocalSurfaceIdForAutoResize(
- host()->last_auto_resize_request_number());
- }
+ // |delegated_frame_host_|, so it must have SynchronizeVisualProperties called
+ // after.
+ return host()->SynchronizeVisualProperties();
}
#if defined(OS_WIN)
@@ -2230,6 +2274,11 @@ void RenderWidgetHostViewAura::DetachFromInputMethod() {
wm::RestoreWindowBoundsOnClientFocusLost(window_->GetToplevelWindow());
#endif // defined(OS_CHROMEOS)
}
+
+#if defined(OS_WIN)
+ // Reset the keyboard observer because it attaches to the input method.
+ keyboard_observer_.reset();
+#endif // defined(OS_WIN)
}
void RenderWidgetHostViewAura::ForwardKeyboardEventWithLatencyInfo(
@@ -2420,15 +2469,18 @@ void RenderWidgetHostViewAura::ScrollFocusedEditableNodeIntoRect(
}
void RenderWidgetHostViewAura::OnSynchronizedDisplayPropertiesChanged() {
- WasResized(cc::DeadlinePolicy::UseDefaultDeadline());
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+ base::nullopt);
}
-viz::ScopedSurfaceIdAllocator RenderWidgetHostViewAura::ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
+viz::ScopedSurfaceIdAllocator
+RenderWidgetHostViewAura::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
base::OnceCallback<void()> allocation_task = base::BindOnce(
- &RenderWidgetHostViewAura::WasResized, weak_ptr_factory_.GetWeakPtr(),
- cc::DeadlinePolicy::UseDefaultDeadline());
+ base::IgnoreResult(
+ &RenderWidgetHostViewAura::SynchronizeVisualProperties),
+ weak_ptr_factory_.GetWeakPtr(), cc::DeadlinePolicy::UseDefaultDeadline(),
+ metadata.local_surface_id);
return window_->GetSurfaceIdAllocator(std::move(allocation_task));
}
@@ -2443,7 +2495,8 @@ void RenderWidgetHostViewAura::DidNavigate() {
if (is_first_navigation_) {
SyncSurfaceProperties(cc::DeadlinePolicy::UseExistingDeadline());
} else {
- WasResized(cc::DeadlinePolicy::UseExistingDeadline());
+ SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
+ base::nullopt);
}
if (delegated_frame_host_)
delegated_frame_host_->DidNavigate();
@@ -2458,6 +2511,10 @@ RenderWidgetHostViewAura::AllocateFrameSinkIdForGuestViewHack() {
->AllocateFrameSinkId();
}
+MouseWheelPhaseHandler* RenderWidgetHostViewAura::GetMouseWheelPhaseHandler() {
+ return &event_handler_->mouse_wheel_phase_handler();
+}
+
void RenderWidgetHostViewAura::TakeFallbackContentFrom(
RenderWidgetHostView* view) {
DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)
@@ -2466,7 +2523,10 @@ void RenderWidgetHostViewAura::TakeFallbackContentFrom(
->IsRenderWidgetHostViewGuest());
RenderWidgetHostViewAura* view_aura =
static_cast<RenderWidgetHostViewAura*>(view);
- SetBackgroundColor(view_aura->background_color());
+ base::Optional<SkColor> color = view_aura->GetBackgroundColor();
+ if (color)
+ SetBackgroundColor(*color);
+
if (delegated_frame_host_ && view_aura->delegated_frame_host_) {
delegated_frame_host_->TakeFallbackContentFrom(
view_aura->delegated_frame_host_.get());
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
index bc92c58c5c0..d36135e491b 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -57,11 +57,9 @@ class Rect;
}
namespace ui {
+enum class DomCode;
class InputMethod;
class LocatedEvent;
-#if defined(OS_WIN)
-class OnScreenKeyboardObserver;
-#endif
}
namespace content {
@@ -73,6 +71,7 @@ class DirectManipulationBrowserTest;
class CursorManager;
class DelegatedFrameHost;
class DelegatedFrameHostClient;
+class MouseWheelPhaseHandler;
class RenderFrameHostImpl;
class RenderWidgetHostView;
class TouchSelectionControllerClientAura;
@@ -114,8 +113,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void WasUnOccluded() override;
void WasOccluded() override;
gfx::Rect GetViewBounds() const override;
- void SetBackgroundColor(SkColor color) override;
- SkColor background_color() const override;
bool IsMouseLocked() override;
gfx::Size GetVisibleViewportSize() const override;
void SetInsets(const gfx::Insets& insets) override;
@@ -140,12 +137,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void SetTooltipText(const base::string16& tooltip_text) override;
void DisplayTooltipText(const base::string16& tooltip_text) override;
gfx::Size GetRequestedRendererSize() const override;
+ uint32_t GetCaptureSequenceNumber() const override;
bool IsSurfaceAvailableForCopy() const override;
void CopyFromSurface(
const gfx::Rect& src_rect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) override;
- gfx::Vector2d GetOffsetFromRootSurface() override;
+ void EnsureSurfaceSynchronizedForLayoutTest() override;
+ void TransformPointToRootSurface(gfx::PointF* point) override;
gfx::Rect GetBoundsInRootWindow() override;
void WheelEventAck(const blink::WebMouseWheelEvent& event,
InputEventAckState ack_result) override;
@@ -167,29 +166,33 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void SetMainFrameAXTreeID(ui::AXTreeIDRegistry::AXTreeID id) override;
bool LockMouse() override;
void UnlockMouse() override;
- bool LockKeyboard(base::Optional<base::flat_set<int>> keys) override;
+ bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
void UnlockKeyboard() override;
bool IsKeyboardLocked() override;
+ base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
void DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
override;
void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) override;
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
+ bool RequestRepaintForTesting() override;
void DidStopFlinging() override;
void OnDidNavigateMainFrameToNewPage() override;
viz::FrameSinkId GetFrameSinkId() override;
viz::LocalSurfaceId GetLocalSurfaceId() const override;
- bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
- const viz::SurfaceId& original_surface,
- gfx::PointF* transformed_point) override;
+ bool TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point) override;
bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) override;
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY) override;
viz::FrameSinkId GetRootFrameSinkId() override;
viz::SurfaceId GetCurrentSurfaceId() const override;
@@ -199,9 +202,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
base::OnceCallback<void(const base::UnguessableToken&)>
callback) override;
void OnSynchronizedDisplayPropertiesChanged() override;
- viz::ScopedSurfaceIdAllocator ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) override;
+ viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) override;
bool IsLocalSurfaceIdAllocationSuppressed() const override;
@@ -223,6 +225,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const override;
bool HasCompositionText() const override;
+ ui::TextInputClient::FocusReason GetFocusReason() const override;
bool GetTextRange(gfx::Range* range) const override;
bool GetCompositionTextRange(gfx::Range* range) const override;
bool GetSelectionRange(gfx::Range* range) const override;
@@ -238,6 +241,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
const std::string& GetClientSourceInfo() const override;
+ bool ShouldDoLearning() override;
// Overridden from display::DisplayObserver:
void OnDisplayAdded(const display::Display& new_display) override;
@@ -348,6 +352,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
return delegated_frame_host_.get();
}
+ // RenderWidgetHostViewBase:
+ void UpdateBackgroundColor() override;
+
private:
friend class DelegatedFrameHostClientAura;
friend class InputMethodAuraTestBase;
@@ -374,6 +381,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
SkippedDelegatedFrames);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
ResizeAfterReceivingFrame);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ ChildGeneratedResizeRoutesLocalSurfaceId);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, MissingFramesDontLock);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
@@ -395,6 +404,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
VirtualKeyboardFocusEnsureCaretInRect);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
HitTestRegionListSubmitted);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraKeyboardTest,
+ KeyboardObserverDestroyed);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
DropFallbackWhenHidden);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
@@ -432,13 +443,17 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// collide with FrameSinkIds used by RenderWidgetHostImpls.
static viz::FrameSinkId AllocateFrameSinkIdForGuestViewHack();
+ MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
+
void CreateAuraWindow(aura::client::WindowType type);
void CreateDelegatedFrameHostClient();
void UpdateCursorIfOverSelf();
- void WasResized(const cc::DeadlinePolicy& deadline_policy);
+ bool SynchronizeVisualProperties(const cc::DeadlinePolicy& deadline_policy,
+ const base::Optional<viz::LocalSurfaceId>&
+ child_allocated_local_surface_id);
// Tracks whether SnapToPhysicalPixelBoundary() has been called.
bool has_snapped_to_boundary() { return has_snapped_to_boundary_; }
@@ -450,7 +465,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void InternalSetBounds(const gfx::Rect& rect);
// Handles propagation of surface properties when they are changed.
- void SyncSurfaceProperties(const cc::DeadlinePolicy& deadline_policy);
+ bool SyncSurfaceProperties(const cc::DeadlinePolicy& deadline_policy);
#if defined(OS_WIN)
// Creates and/or updates the legacy dummy window which corresponds to
@@ -523,12 +538,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Tells DelegatedFrameHost whether we need to receive BeginFrames.
void UpdateNeedsBeginFramesInternal();
- // Applies background color without notifying the RenderWidget about
- // opaqueness changes. This allows us to, when navigating to a new page,
- // transfer this color to that page. This allows us to pass this background
- // color to new views on navigation.
- void UpdateBackgroundColorFromRenderer(SkColor color);
-
// Called when the window title is changed.
void WindowTitleChanged();
@@ -576,9 +585,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Current tooltip text.
base::string16 tooltip_;
- // The background color of the web content.
- SkColor background_color_;
-
// Whether a request for begin frames has been issued.
bool needs_begin_frames_;
@@ -618,7 +624,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Set to true if we requested the on screen keyboard to be displayed.
bool virtual_keyboard_requested_;
- std::unique_ptr<ui::OnScreenKeyboardObserver> keyboard_observer_;
+ friend class WinScreenKeyboardObserver;
+ std::unique_ptr<WinScreenKeyboardObserver> keyboard_observer_;
gfx::Point last_mouse_move_location_;
#endif
@@ -655,6 +662,19 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
std::unique_ptr<CursorManager> cursor_manager_;
int tab_show_sequence_ = 0;
+ // Latest capture sequence number which is incremented when the caller
+ // requests surfaces be synchronized via
+ // EnsureSurfaceSynchronizedForLayoutTest().
+ uint32_t latest_capture_sequence_number_ = 0u;
+
+ // The pointer type of the most recent gesture/mouse/touch event.
+ ui::EventPointerType last_pointer_type_ =
+ ui::EventPointerType::POINTER_TYPE_UNKNOWN;
+ // The pointer type that caused the most recent focus. This value will be
+ // incorrect if the focus was not triggered by a user gesture.
+ ui::EventPointerType last_pointer_type_before_focus_ =
+ ui::EventPointerType::POINTER_TYPE_UNKNOWN;
+
bool is_first_navigation_ = true;
base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index ba3facd9161..b84c96372ca 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
@@ -30,6 +29,7 @@
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
+#include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
@@ -95,6 +95,9 @@
#include "ui/aura/window_observer.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/input_method_factory.h"
+#include "ui/base/ime/input_method_keyboard_controller.h"
+#include "ui/base/ime/mock_input_method.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/ui_base_types.h"
@@ -234,53 +237,14 @@ class FakeWindowEventDispatcher : public aura::WindowEventDispatcher {
size_t processed_touch_event_count_;
};
-class FakeDelegatedFrameHostClientAura
- : public DelegatedFrameHostClientAura,
- public ui::CompositorLockManagerClient {
+class FakeDelegatedFrameHostClientAura : public DelegatedFrameHostClientAura {
public:
explicit FakeDelegatedFrameHostClientAura(
RenderWidgetHostViewAura* render_widget_host_view)
- : DelegatedFrameHostClientAura(render_widget_host_view),
- lock_manager_(new base::NullTaskRunner(), this) {}
+ : DelegatedFrameHostClientAura(render_widget_host_view) {}
~FakeDelegatedFrameHostClientAura() override = default;
- void DisableResizeLock() { can_create_resize_lock_ = false; }
-
- bool resize_locked() const { return resize_locked_; }
- bool compositor_locked() const { return compositor_locked_; }
-
private:
- // DelegatedFrameHostClientAura implementation.
- bool DelegatedFrameCanCreateResizeLock() const override {
- return can_create_resize_lock_;
- }
-
- // CompositorResizeLockClient implemention. Overrides from
- // DelegatedFrameHostClientAura, to prevent the lock from timing out.
- std::unique_ptr<ui::CompositorLock> GetCompositorLock(
- ui::CompositorLockClient* client) override {
- resize_locked_ = compositor_locked_ = true;
- return lock_manager_.GetCompositorLock(nullptr, base::TimeDelta());
- }
- // CompositorResizeLockClient implemention. Overrides from
- // // DelegatedFrameHostClientAura.
- void CompositorResizeLockEnded() override {
- resize_locked_ = false;
- DelegatedFrameHostClientAura::CompositorResizeLockEnded();
- }
-
- // ui::CompositorLockManagerClient implementation.
- void OnCompositorLockStateChanged(bool locked) override {
- if (!locked) {
- compositor_locked_ = false;
- }
- }
-
- bool can_create_resize_lock_ = true;
- bool resize_locked_ = false;
- bool compositor_locked_ = false;
- ui::CompositorLockManager lock_manager_;
-
DISALLOW_COPY_AND_ASSIGN(FakeDelegatedFrameHostClientAura);
};
@@ -314,10 +278,6 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
renderer_compositor_frame_sink_ptr_.get());
}
- void DisableResizeLock() {
- delegated_frame_host_client_->DisableResizeLock();
- }
-
void UseFakeDispatcher() {
dispatcher_ = new FakeWindowEventDispatcher(window()->GetHost());
std::unique_ptr<aura::WindowEventDispatcher> dispatcher(dispatcher_);
@@ -341,10 +301,6 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
return GetDelegatedFrameHost()->HasFallbackSurface();
}
- bool released_front_lock_active() const {
- return GetDelegatedFrameHost()->ReleasedFrontLockActiveForTesting();
- }
-
void ReclaimResources(const std::vector<viz::ReturnedResource>& resources) {
GetDelegatedFrameHost()->ReclaimResources(resources);
}
@@ -360,12 +316,6 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
metadata);
}
- bool resize_locked() const {
- return delegated_frame_host_client_->resize_locked();
- }
- bool compositor_locked() const {
- return delegated_frame_host_client_->compositor_locked();
- }
bool is_guest_view_hack() { return is_guest_view_hack_; }
gfx::Size last_frame_size_;
@@ -489,16 +439,16 @@ class TestScopedKeyboardHook : public aura::ScopedKeyboardHook {
~TestScopedKeyboardHook() override;
// aura::ScopedKeyboardHook override.
- bool IsKeyLocked(int native_key_code) override;
+ bool IsKeyLocked(ui::DomCode dom_code) override;
// Set up the keys being locked for testing. One of these methods must be
// called before using an instance.
void LockAllKeys();
- void LockSpecificKey(int new_key_to_lock);
+ void LockSpecificKey(ui::DomCode dom_code);
private:
bool keyboard_lock_active_ = false;
- base::Optional<int> locked_key_;
+ base::Optional<ui::DomCode> locked_key_;
DISALLOW_COPY_AND_ASSIGN(TestScopedKeyboardHook);
};
@@ -507,9 +457,9 @@ TestScopedKeyboardHook::TestScopedKeyboardHook() = default;
TestScopedKeyboardHook::~TestScopedKeyboardHook() = default;
-bool TestScopedKeyboardHook::IsKeyLocked(int native_key_code) {
+bool TestScopedKeyboardHook::IsKeyLocked(ui::DomCode dom_code) {
DCHECK(keyboard_lock_active_) << "Did you forget to reserve keys to lock?";
- return !locked_key_ || (locked_key_.value() == native_key_code);
+ return !locked_key_ || (locked_key_.value() == dom_code);
}
void TestScopedKeyboardHook::LockAllKeys() {
@@ -517,9 +467,9 @@ void TestScopedKeyboardHook::LockAllKeys() {
locked_key_.reset();
}
-void TestScopedKeyboardHook::LockSpecificKey(int key_to_lock) {
+void TestScopedKeyboardHook::LockSpecificKey(ui::DomCode dom_code) {
keyboard_lock_active_ = true;
- locked_key_ = key_to_lock;
+ locked_key_ = dom_code;
}
enum WheelScrollingMode {
@@ -545,8 +495,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
view->delegated_frame_host_ = nullptr;
view->delegated_frame_host_ = std::make_unique<DelegatedFrameHost>(
view->frame_sink_id_, view->delegated_frame_host_client_.get(),
- features::IsSurfaceSynchronizationEnabled(), enable_viz,
- false /* should_register_frame_sink_id */);
+ enable_viz, false /* should_register_frame_sink_id */);
}
FakeRenderWidgetHostViewAura* CreateView(bool is_guest_view_hack) {
@@ -576,7 +525,6 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
}
void SetUpEnvironment() {
- mojo_feature_list_.InitAndEnableFeature(features::kMojoInputMessages);
ImageTransportFactory::SetFactory(
std::make_unique<TestImageTransportFactory>());
aura_test_helper_.reset(new aura::test::AuraTestHelper());
@@ -684,6 +632,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
void TimerBasedLatchingBreaksWithMouseMove();
void TimerBasedLatchingBreaksWithModifiersChange();
void TimerBasedLatchingBreaksWithDirectionChange();
+ void TimerBasedLatchingBreaksWithAutoscrollStart();
void TouchpadFlingStartResetsWheelPhaseState();
void GSBWithTouchSourceStopsWheelScrollSequence();
@@ -697,7 +646,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
}
MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() const {
- return &(view_->event_handler()->mouse_wheel_phase_handler());
+ return view_->GetMouseWheelPhaseHandler();
}
// Sets the |view| active in TextInputManager with the given |type|. |type|
@@ -1744,7 +1693,6 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
InputEventAck ack(
InputEventAckSource::COMPOSITOR_THREAD, blink::WebInputEvent::kTouchStart,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, press.unique_event_id());
- widget_host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
events = GetAndResetDispatchedMessages();
EXPECT_EQ(0U, events.size());
@@ -1784,8 +1732,7 @@ TEST_F(RenderWidgetHostViewAuraTest,
view_->Show();
auto test_hook = std::make_unique<TestScopedKeyboardHook>();
- test_hook->LockSpecificKey(
- ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::US_A));
+ test_hook->LockSpecificKey(ui::DomCode::US_A);
view_->event_handler()->scoped_keyboard_hook_ = std::move(test_hook);
// This locked key will skip the prehandler and be sent to the input handler.
@@ -1844,8 +1791,7 @@ TEST_F(RenderWidgetHostViewAuraTest,
view_->Show();
auto test_hook = std::make_unique<TestScopedKeyboardHook>();
- test_hook->LockSpecificKey(
- ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::ESCAPE));
+ test_hook->LockSpecificKey(ui::DomCode::ESCAPE);
view_->event_handler()->scoped_keyboard_hook_ = std::move(test_hook);
// Although this key was locked, it will still pass through the prehandler as
@@ -2101,8 +2047,7 @@ void RenderWidgetHostViewAuraTest::TimerBasedWheelEventPhaseInfo() {
events = GetAndResetDispatchedMessages();
wheel_event = static_cast<const WebMouseWheelEvent*>(
events[0]->ToEvent()->Event()->web_event.get());
- base::TimeTicks wheel_event_timestamp =
- ui::EventTimeStampFromSeconds(wheel_event->TimeStampSeconds());
+ base::TimeTicks wheel_event_timestamp = wheel_event->TimeStamp();
EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, wheel_event->phase);
if (wheel_scrolling_mode_ == kWheelScrollLatching) {
events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -2133,8 +2078,7 @@ void RenderWidgetHostViewAuraTest::TimerBasedWheelEventPhaseInfo() {
EXPECT_EQ(0U, wheel_end_event->delta_y);
EXPECT_EQ(0U, wheel_end_event->wheel_ticks_x);
EXPECT_EQ(0U, wheel_end_event->wheel_ticks_y);
- EXPECT_GT(ui::EventTimeStampFromSeconds(wheel_end_event->TimeStampSeconds()),
- wheel_event_timestamp);
+ EXPECT_GT(wheel_end_event->TimeStamp(), wheel_event_timestamp);
gesture_event = static_cast<const WebGestureEvent*>(
events[1]->ToEvent()->Event()->web_event.get());
@@ -2377,6 +2321,63 @@ TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
TimerBasedLatchingBreaksWithDirectionChange();
}
+void RenderWidgetHostViewAuraTest::
+ TimerBasedLatchingBreaksWithAutoscrollStart() {
+ // The test is valid only when wheel scroll latching is enabled.
+ if (wheel_scrolling_mode_ == kWheelScrollingModeNone)
+ return;
+
+ // Set the mouse_wheel_phase_handler_ timer timeout to a large value to make
+ // sure that the timer is still running when the Autoscroll starts.
+ view_->event_handler()->set_mouse_wheel_wheel_phase_handler_timeout(
+ TestTimeouts::action_max_timeout());
+
+ view_->InitAsChild(nullptr);
+ view_->Show();
+ sink_->ClearMessages();
+
+ ui::MouseWheelEvent event(gfx::Vector2d(0, 5), gfx::Point(2, 2),
+ gfx::Point(2, 2), ui::EventTimeForNow(), 0, 0);
+ view_->OnMouseEvent(&event);
+ base::RunLoop().RunUntilIdle();
+ MockWidgetInputHandler::MessageVector events =
+ GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel", GetMessageNames(events));
+ EXPECT_TRUE(events[0]->ToEvent());
+ const WebMouseWheelEvent* wheel_event =
+ static_cast<const WebMouseWheelEvent*>(
+ events[0]->ToEvent()->Event()->web_event.get());
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
+ events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_TRUE(view_->GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
+ events = GetAndResetDispatchedMessages();
+
+ // Autoscroll start breaks wheel scroll latching sequence by sending the
+ // pending wheel end event, the non-blocking wheel end event will be acked
+ // immediately and a GSE will be sent. The next wheel event will start a new
+ // scrolling sequence.
+ view_->OnAutoscrollStart();
+ EXPECT_FALSE(view_->GetMouseWheelPhaseHandler()->HasPendingWheelEndEvent());
+ ui::MouseWheelEvent event2(gfx::Vector2d(0, 5), gfx::Point(2, 2),
+ gfx::Point(2, 2), ui::EventTimeForNow(), 0, 0);
+ view_->OnMouseEvent(&event2);
+ base::RunLoop().RunUntilIdle();
+ events = GetAndResetDispatchedMessages();
+ EXPECT_EQ("MouseWheel GestureScrollEnd MouseWheel", GetMessageNames(events));
+ EXPECT_TRUE(events[0]->ToEvent());
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ events[0]->ToEvent()->Event()->web_event.get());
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->phase);
+ EXPECT_TRUE(events[2]->ToEvent());
+ wheel_event = static_cast<const WebMouseWheelEvent*>(
+ events[2]->ToEvent()->Event()->web_event.get());
+ EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
+}
+TEST_F(RenderWidgetHostViewAuraAsyncWheelEventsEnabledTest,
+ TimerBasedLatchingBreaksWithAutoscrollStart) {
+ TimerBasedLatchingBreaksWithAutoscrollStart();
+}
+
// Tests that a gesture fling start with touchpad source resets wheel phase
// state.
void RenderWidgetHostViewAuraTest::TouchpadFlingStartResetsWheelPhaseState() {
@@ -2802,20 +2803,21 @@ TEST_F(RenderWidgetHostViewAuraTest, CompositorViewportPixelSizeWithScale) {
view_->SetSize(gfx::Size(100, 100));
EXPECT_EQ("100x100", view_->GetCompositorViewportPixelSize().ToString());
EXPECT_EQ(1u, sink_->message_count());
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID),
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
sink_->GetMessageAt(0)->type());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ("100x100", std::get<0>(params).new_size.ToString()); // dip size
EXPECT_EQ("100x100",
std::get<0>(params)
.compositor_viewport_pixel_size.ToString()); // backing size
}
- widget_host_->ResetSizeAndRepaintPendingFlags();
+ widget_host_->ResetSentVisualProperties();
sink_->ClearMessages();
aura_test_helper_->test_screen()->SetDeviceScaleFactor(2.0f);
@@ -2823,24 +2825,25 @@ TEST_F(RenderWidgetHostViewAuraTest, CompositorViewportPixelSizeWithScale) {
// Extra ScreenInfoChanged message for |parent_view_|.
// Changing the device scale factor triggers the
// RenderWidgetHostViewAura::OnDisplayMetricsChanged() observer callback,
- // which sends a ViewMsg_Resize::ID message to the renderer.
+ // which sends a ViewMsg_SynchronizeVisualProperties::ID message to the
+ // renderer.
EXPECT_EQ(1u, sink_->message_count());
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID),
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
sink_->GetMessageAt(0)->type());
- widget_host_->ResetSizeAndRepaintPendingFlags();
+ widget_host_->ResetSentVisualProperties();
sink_->ClearMessages();
aura_test_helper_->test_screen()->SetDeviceScaleFactor(1.0f);
// Extra ScreenInfoChanged message for |parent_view_|.
EXPECT_EQ(1u, sink_->message_count());
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID),
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
sink_->GetMessageAt(0)->type());
EXPECT_EQ("100x100", view_->GetCompositorViewportPixelSize().ToString());
}
// This test verifies that in AutoResize mode a new
-// ViewMsg_Resize message is sent when ScreenInfo
+// ViewMsg_SynchronizeVisualProperties message is sent when ScreenInfo
// changes and that message contains the latest ScreenInfo.
TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithScale) {
view_->InitAsChild(nullptr);
@@ -2850,39 +2853,38 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithScale) {
viz::LocalSurfaceId local_surface_id1(view_->GetLocalSurfaceId());
EXPECT_TRUE(local_surface_id1.is_valid());
- view_->EnableAutoResize(gfx::Size(50, 50), gfx::Size(100, 100));
sink_->ClearMessages();
- ViewHostMsg_ResizeOrRepaint_ACK_Params params;
- params.view_size = gfx::Size(75, 75);
- params.sequence_number = 1;
- widget_host_->OnResizeOrRepaintACK(params);
-
- // RenderWidgetHostImpl has delayed auto-resize processing. Yield here to
- // let it complete.
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- run_loop.QuitClosure());
- run_loop.Run();
+ view_->EnableAutoResize(gfx::Size(50, 50), gfx::Size(100, 100));
viz::LocalSurfaceId local_surface_id2;
ASSERT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
- ResizeParams resize_params = std::get<0>(params);
- EXPECT_EQ(1u,
- resize_params.auto_resize_sequence_number); // sequence_number
- EXPECT_EQ("50x50", resize_params.min_size_for_auto_resize.ToString());
- EXPECT_EQ("100x100", resize_params.max_size_for_auto_resize.ToString());
- EXPECT_EQ(1, resize_params.screen_info.device_scale_factor);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ VisualProperties visual_properties = std::get<0>(params);
+ EXPECT_EQ("50x50", visual_properties.min_size_for_auto_resize.ToString());
+ EXPECT_EQ("100x100", visual_properties.max_size_for_auto_resize.ToString());
+ EXPECT_EQ(1, visual_properties.screen_info.device_scale_factor);
local_surface_id2 =
- resize_params.local_surface_id.value_or(viz::LocalSurfaceId());
- EXPECT_NE(local_surface_id1, local_surface_id2);
+ visual_properties.local_surface_id.value_or(viz::LocalSurfaceId());
+ EXPECT_EQ(local_surface_id1, local_surface_id2);
EXPECT_TRUE(local_surface_id2.is_valid());
}
+ viz::LocalSurfaceId local_surface_id(
+ local_surface_id1.parent_sequence_number(),
+ local_surface_id1.child_sequence_number() + 1,
+ local_surface_id1.embed_token());
+ {
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(75, 75);
+ metadata.local_surface_id = local_surface_id;
+ widget_host_->DidUpdateVisualProperties(metadata);
+ }
+
sink_->ClearMessages();
aura_test_helper_->test_screen()->SetDeviceScaleFactor(2.0f);
@@ -2890,25 +2892,23 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithScale) {
// TODO(samans): There should be only one message in the sink, but some
// testers are seeing two (crrev.com/c/839580). Investigate why.
const IPC::Message* msg =
- sink_->GetFirstMessageMatching(ViewMsg_Resize::ID);
+ sink_->GetFirstMessageMatching(ViewMsg_SynchronizeVisualProperties::ID);
ASSERT_TRUE(msg);
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
- ResizeParams resize_params = std::get<0>(params);
- EXPECT_EQ(1u,
- resize_params.auto_resize_sequence_number); // sequence_number
- EXPECT_EQ("50x50", resize_params.min_size_for_auto_resize.ToString());
- EXPECT_EQ("100x100", resize_params.max_size_for_auto_resize.ToString());
- EXPECT_EQ(2, resize_params.screen_info.device_scale_factor);
- EXPECT_NE(local_surface_id1,
- resize_params.local_surface_id.value_or(viz::LocalSurfaceId()));
- EXPECT_NE(local_surface_id2,
- resize_params.local_surface_id.value_or(viz::LocalSurfaceId()));
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ VisualProperties visual_properties = std::get<0>(params);
+ EXPECT_EQ("50x50", visual_properties.min_size_for_auto_resize.ToString());
+ EXPECT_EQ("100x100", visual_properties.max_size_for_auto_resize.ToString());
+ EXPECT_EQ(2, visual_properties.screen_info.device_scale_factor);
+ EXPECT_NE(local_surface_id1, visual_properties.local_surface_id.value_or(
+ viz::LocalSurfaceId()));
+ EXPECT_NE(local_surface_id2, visual_properties.local_surface_id.value_or(
+ viz::LocalSurfaceId()));
}
}
// This test verifies that in AutoResize mode a new
-// ViewMsg_Resize message is sent when size changes.
+// ViewMsg_SynchronizeVisualProperties message is sent when size changes.
TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithBrowserInitiatedResize) {
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
@@ -2917,36 +2917,36 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithBrowserInitiatedResize) {
viz::LocalSurfaceId local_surface_id1(view_->GetLocalSurfaceId());
EXPECT_TRUE(local_surface_id1.is_valid());
- view_->EnableAutoResize(gfx::Size(50, 50), gfx::Size(100, 100));
sink_->ClearMessages();
- ViewHostMsg_ResizeOrRepaint_ACK_Params params;
- params.view_size = gfx::Size(75, 75);
- params.sequence_number = 1;
- widget_host_->OnResizeOrRepaintACK(params);
-
- // RenderWidgetHostImpl has delayed auto-resize processing. Yield here to
- // let it complete.
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- run_loop.QuitClosure());
- run_loop.Run();
+ view_->EnableAutoResize(gfx::Size(50, 50), gfx::Size(100, 100));
viz::LocalSurfaceId local_surface_id2;
ASSERT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
- ResizeParams resize_params = std::get<0>(params);
- EXPECT_EQ(1u, resize_params.auto_resize_sequence_number);
- EXPECT_EQ("50x50", resize_params.min_size_for_auto_resize.ToString());
- EXPECT_EQ("100x100", resize_params.max_size_for_auto_resize.ToString());
- EXPECT_EQ(1, resize_params.screen_info.device_scale_factor);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ VisualProperties visual_properties = std::get<0>(params);
+ EXPECT_EQ("50x50", visual_properties.min_size_for_auto_resize.ToString());
+ EXPECT_EQ("100x100", visual_properties.max_size_for_auto_resize.ToString());
+ EXPECT_EQ(1, visual_properties.screen_info.device_scale_factor);
local_surface_id2 =
- resize_params.local_surface_id.value_or(viz::LocalSurfaceId());
+ visual_properties.local_surface_id.value_or(viz::LocalSurfaceId());
EXPECT_TRUE(local_surface_id2.is_valid());
- EXPECT_NE(local_surface_id1, local_surface_id2);
+ EXPECT_EQ(local_surface_id1, local_surface_id2);
+ }
+
+ viz::LocalSurfaceId local_surface_id(
+ local_surface_id1.parent_sequence_number(),
+ local_surface_id1.child_sequence_number() + 1,
+ local_surface_id1.embed_token());
+ {
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(75, 75);
+ metadata.local_surface_id = local_surface_id;
+ widget_host_->DidUpdateVisualProperties(metadata);
}
sink_->ClearMessages();
@@ -2956,24 +2956,90 @@ TEST_F(RenderWidgetHostViewAuraTest, AutoResizeWithBrowserInitiatedResize) {
ASSERT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
- ResizeParams resize_params = std::get<0>(params);
- EXPECT_EQ(1u, resize_params.auto_resize_sequence_number);
- EXPECT_EQ("50x50", resize_params.min_size_for_auto_resize.ToString());
- EXPECT_EQ("100x100", resize_params.max_size_for_auto_resize.ToString());
- EXPECT_EQ(1, resize_params.screen_info.device_scale_factor);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
+ VisualProperties visual_properties = std::get<0>(params);
+ EXPECT_EQ("50x50", visual_properties.min_size_for_auto_resize.ToString());
+ EXPECT_EQ("100x100", visual_properties.max_size_for_auto_resize.ToString());
+ EXPECT_EQ(1, visual_properties.screen_info.device_scale_factor);
local_surface_id3 =
- resize_params.local_surface_id.value_or(viz::LocalSurfaceId());
+ visual_properties.local_surface_id.value_or(viz::LocalSurfaceId());
EXPECT_TRUE(local_surface_id3.is_valid());
EXPECT_NE(local_surface_id1, local_surface_id3);
EXPECT_NE(local_surface_id2, local_surface_id3);
}
}
-// Checks that InputMsg_CursorVisibilityChange IPC messages are dispatched
-// to the renderer at the correct times.
+// This test verifies that in AutoResize mode a child-allocated
+// viz::LocalSurfaceId will be properly routed and stored in the parent.
+TEST_F(RenderWidgetHostViewAuraTest, ChildAllocationAcceptedInParent) {
+ view_->InitAsChild(nullptr);
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
+ sink_->ClearMessages();
+ viz::LocalSurfaceId local_surface_id1(view_->GetLocalSurfaceId());
+ EXPECT_TRUE(local_surface_id1.is_valid());
+
+ widget_host_->SetAutoResize(true, gfx::Size(50, 50), gfx::Size(100, 100));
+ viz::ChildLocalSurfaceIdAllocator child_allocator;
+ child_allocator.UpdateFromParent(local_surface_id1);
+ viz::LocalSurfaceId local_surface_id2 = child_allocator.GenerateId();
+
+ {
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(75, 75);
+ metadata.local_surface_id = local_surface_id2;
+ widget_host_->DidUpdateVisualProperties(metadata);
+ }
+
+ viz::LocalSurfaceId local_surface_id3(view_->GetLocalSurfaceId());
+ EXPECT_NE(local_surface_id1, local_surface_id3);
+ EXPECT_EQ(local_surface_id2, local_surface_id3);
+}
+
+// This test verifies that when the child and parent both allocate their own
+// viz::LocalSurfaceId the resulting conflict is resolved.
+TEST_F(RenderWidgetHostViewAuraTest, ConflictingAllocationsResolve) {
+ view_->InitAsChild(nullptr);
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
+ sink_->ClearMessages();
+ viz::LocalSurfaceId local_surface_id1(view_->GetLocalSurfaceId());
+ EXPECT_TRUE(local_surface_id1.is_valid());
+
+ widget_host_->SetAutoResize(true, gfx::Size(50, 50), gfx::Size(100, 100));
+ viz::ChildLocalSurfaceIdAllocator child_allocator;
+ child_allocator.UpdateFromParent(local_surface_id1);
+ viz::LocalSurfaceId local_surface_id2 = child_allocator.GenerateId();
+
+ {
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(75, 75);
+ metadata.local_surface_id = local_surface_id2;
+ widget_host_->DidUpdateVisualProperties(metadata);
+ }
+
+ // Cause a conflicting viz::LocalSurfaceId allocation
+ aura_test_helper_->test_screen()->SetDeviceScaleFactor(2.0f);
+ viz::LocalSurfaceId local_surface_id3(view_->GetLocalSurfaceId());
+ EXPECT_NE(local_surface_id1, local_surface_id3);
+
+ viz::LocalSurfaceId local_surface_id4(view_->GetLocalSurfaceId());
+ EXPECT_NE(local_surface_id1, local_surface_id4);
+ EXPECT_NE(local_surface_id2, local_surface_id4);
+ viz::LocalSurfaceId merged_local_surface_id(
+ local_surface_id2.parent_sequence_number() + 1,
+ local_surface_id2.child_sequence_number(),
+ local_surface_id2.embed_token());
+ EXPECT_EQ(local_surface_id4, merged_local_surface_id);
+}
+
+// Checks that WidgetInputHandler::CursorVisibilityChange IPC messages are
+// dispatched to the renderer at the correct times.
TEST_F(RenderWidgetHostViewAuraTest, CursorVisibilityChange) {
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
@@ -3072,31 +3138,31 @@ TEST_F(RenderWidgetHostViewAuraTest, UpdateCursorIfOverSelf) {
// Cursor is in the middle of the window.
cursor_client.reset_calls_to_set_cursor();
- aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(110, 110));
+ aura::Env::GetInstance()->SetLastMouseLocation(gfx::Point(110, 110));
view_->UpdateCursorIfOverSelf();
EXPECT_EQ(1, cursor_client.calls_to_set_cursor());
// Cursor is near the top of the window.
cursor_client.reset_calls_to_set_cursor();
- aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(80, 65));
+ aura::Env::GetInstance()->SetLastMouseLocation(gfx::Point(80, 65));
view_->UpdateCursorIfOverSelf();
EXPECT_EQ(1, cursor_client.calls_to_set_cursor());
// Cursor is near the bottom of the window.
cursor_client.reset_calls_to_set_cursor();
- aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(159, 159));
+ aura::Env::GetInstance()->SetLastMouseLocation(gfx::Point(159, 159));
view_->UpdateCursorIfOverSelf();
EXPECT_EQ(1, cursor_client.calls_to_set_cursor());
// Cursor is above the window.
cursor_client.reset_calls_to_set_cursor();
- aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(67, 59));
+ aura::Env::GetInstance()->SetLastMouseLocation(gfx::Point(67, 59));
view_->UpdateCursorIfOverSelf();
EXPECT_EQ(0, cursor_client.calls_to_set_cursor());
// Cursor is below the window.
cursor_client.reset_calls_to_set_cursor();
- aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(161, 161));
+ aura::Env::GetInstance()->SetLastMouseLocation(gfx::Point(161, 161));
view_->UpdateCursorIfOverSelf();
EXPECT_EQ(0, cursor_client.calls_to_set_cursor());
}
@@ -3181,7 +3247,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
resource.id = 1;
frame.resource_list.push_back(resource);
view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId, std::move(frame),
- nullptr);
+ base::nullopt);
EXPECT_EQ(0u, sink_->message_count());
// Signal that a new RendererCompositorFrameSink was created by the renderer.
@@ -3191,7 +3257,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TwoOutputSurfaces) {
// old RendererCompositorFrameSink and should not be returned.
view_->SubmitCompositorFrame(parent_local_surface_id_allocator_.GenerateId(),
MakeDelegatedFrame(1.f, view_size, view_rect),
- nullptr);
+ base::nullopt);
EXPECT_EQ(0u, sink_->message_count());
// Report that the surface is drawn to trigger an ACK.
@@ -3212,17 +3278,18 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
root_window->SetLayoutManager(new FullscreenLayoutManager(root_window));
view_->InitAsFullscreen(parent_view_);
view_->Show();
- widget_host_->ResetSizeAndRepaintPendingFlags();
+ widget_host_->ResetSentVisualProperties();
sink_->ClearMessages();
- // Call WasResized to flush the old screen info.
- view_->GetRenderWidgetHost()->WasResized();
+ // Call SynchronizeVisualProperties to flush the old screen info.
+ view_->GetRenderWidgetHost()->SynchronizeVisualProperties();
{
// 0 is CreatingNew message.
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(
"0,0 800x600",
std::get<0>(params).screen_info.available_rect.ToString());
@@ -3233,12 +3300,12 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
kArbitraryLocalSurfaceId,
MakeDelegatedFrame(1.f, std::get<0>(params).new_size,
gfx::Rect(std::get<0>(params).new_size)),
- nullptr);
+ base::nullopt);
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetHost()->compositor());
}
- widget_host_->ResetSizeAndRepaintPendingFlags();
+ widget_host_->ResetSentVisualProperties();
sink_->ClearMessages();
// Make sure the corrent screen size is set along in the resize
@@ -3247,9 +3314,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
EXPECT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(
"0,0 1600x1200",
std::get<0>(params).screen_info.available_rect.ToString());
@@ -3258,86 +3326,17 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
kArbitraryLocalSurfaceId,
MakeDelegatedFrame(1.f, std::get<0>(params).new_size,
gfx::Rect(std::get<0>(params).new_size)),
- nullptr);
+ base::nullopt);
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetHost()->compositor());
}
}
-// If the view size is larger than the compositor frame then extra layers
-// should be created to fill the gap.
-TEST_F(RenderWidgetHostViewAuraTest, DelegatedFrameGutter) {
- // TODO(fsamuel): Delete this test once surface synchronization is on for
- // all platforms.
- if (features::IsSurfaceSynchronizationEnabled())
- return;
-
- gfx::Size large_size(100, 100);
- gfx::Size small_size(40, 45);
- gfx::Size medium_size(40, 95);
- viz::LocalSurfaceId small_id =
- parent_local_surface_id_allocator_.GenerateId();
- viz::LocalSurfaceId medium_id =
- parent_local_surface_id_allocator_.GenerateId();
-
- // Prevent the DelegatedFrameHost from skipping frames.
- view_->DisableResizeLock();
-
- view_->InitAsChild(nullptr);
- aura::client::ParentWindowWithContext(
- view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
- gfx::Rect());
- view_->SetSize(large_size);
- view_->Show();
- viz::CompositorFrame frame =
- MakeDelegatedFrame(1.f, small_size, gfx::Rect(small_size));
- frame.metadata.root_background_color = SK_ColorRED;
-
- cc::RenderFrameMetadata metadata;
- metadata.root_background_color = SK_ColorRED;
- view_->SetRenderFrameMetadata(metadata);
- view_->OnRenderFrameMetadataChanged();
- view_->SubmitCompositorFrame(small_id, std::move(frame), nullptr);
-
- ui::Layer* parent_layer = view_->GetNativeView()->layer();
-
- ASSERT_EQ(2u, parent_layer->children().size());
- EXPECT_EQ(gfx::Rect(40, 0, 60, 100), parent_layer->children()[0]->bounds());
- EXPECT_EQ(SK_ColorRED, parent_layer->children()[0]->background_color());
- EXPECT_EQ(gfx::Rect(0, 45, 40, 55), parent_layer->children()[1]->bounds());
- EXPECT_EQ(SK_ColorRED, parent_layer->children()[1]->background_color());
-
- delegates_.back()->set_is_fullscreen(true);
- view_->SetSize(medium_size);
-
- // Right gutter is unnecessary.
- ASSERT_EQ(1u, parent_layer->children().size());
- EXPECT_EQ(gfx::Rect(0, 45, 40, 50), parent_layer->children()[0]->bounds());
-
- // RWH is fullscreen, so gutters should be black.
- EXPECT_EQ(SK_ColorBLACK, parent_layer->children()[0]->background_color());
-
- frame = MakeDelegatedFrame(1.f, medium_size, gfx::Rect(medium_size));
- view_->SubmitCompositorFrame(medium_id, std::move(frame), nullptr);
- EXPECT_EQ(0u, parent_layer->children().size());
-
- view_->SetSize(large_size);
- ASSERT_EQ(2u, parent_layer->children().size());
-
- // This should evict the frame and remove the gutter layers.
- view_->Hide();
- view_->SetSize(small_size);
- ASSERT_EQ(0u, parent_layer->children().size());
-}
-
TEST_F(RenderWidgetHostViewAuraTest, ZeroSizeStillGetsLocalSurfaceId) {
gfx::Size frame_size;
viz::LocalSurfaceId local_surface_id =
parent_local_surface_id_allocator_.GenerateId();
- // Prevent the DelegatedFrameHost from skipping frames.
- view_->DisableResizeLock();
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3350,9 +3349,10 @@ TEST_F(RenderWidgetHostViewAuraTest, ZeroSizeStillGetsLocalSurfaceId) {
EXPECT_EQ(2u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(1);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(frame_size.ToString(), std::get<0>(params).new_size.ToString());
ASSERT_TRUE(std::get<0>(params).local_surface_id.has_value());
EXPECT_TRUE(std::get<0>(params).local_surface_id->is_valid());
@@ -3368,9 +3368,6 @@ TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) {
viz::LocalSurfaceId local_surface_id =
parent_local_surface_id_allocator_.GenerateId();
- // Prevent the DelegatedFrameHost from skipping frames.
- view_->DisableResizeLock();
-
view_->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
@@ -3387,6 +3384,29 @@ TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) {
EXPECT_EQ(SK_ColorRED, parent_layer->background_color());
}
+// Tests background setting priority.
+TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorOrder) {
+ // If the default background color is not available, then use the theme
+ // background color.
+ view_->InitAsChild(nullptr);
+ view_->SetBackgroundColor(SK_ColorBLUE);
+ ASSERT_TRUE(view_->GetBackgroundColor());
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE), *view_->GetBackgroundColor());
+
+ // If the content background color is available, ignore the default background
+ // color setting.
+ cc::RenderFrameMetadata metadata;
+ metadata.root_background_color = SK_ColorWHITE;
+ view_->SetRenderFrameMetadata(metadata);
+ view_->OnRenderFrameMetadataChanged();
+ ASSERT_TRUE(view_->GetBackgroundColor());
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE), *view_->GetBackgroundColor());
+
+ view_->SetBackgroundColor(SK_ColorRED);
+ ASSERT_TRUE(view_->GetBackgroundColor());
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE), *view_->GetBackgroundColor());
+}
+
// Resizing is disabled due to flakiness. Commit might come before
// DrawWaiterForTest looks for compositor frame. crbug.com/759653
TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
@@ -3404,14 +3424,15 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
view_->Show();
view_->SetSize(size1);
view_->SubmitCompositorFrame(
- id1, MakeDelegatedFrame(1.f, size1, gfx::Rect(size1)), nullptr);
+ id1, MakeDelegatedFrame(1.f, size1, gfx::Rect(size1)), base::nullopt);
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetHost()->compositor());
- ViewHostMsg_ResizeOrRepaint_ACK_Params update_params;
- update_params.view_size = size1;
- update_params.flags = ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK;
- widget_host_->OnMessageReceived(ViewHostMsg_ResizeOrRepaint_ACK(
- widget_host_->GetRoutingID(), update_params));
+ {
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = size1;
+ metadata.local_surface_id = base::nullopt;
+ widget_host_->DidUpdateVisualProperties(metadata);
+ }
sink_->ClearMessages();
// Resize logic is idle (no pending resize, no pending commit).
EXPECT_EQ(size1.ToString(), view_->GetRequestedRendererSize().ToString());
@@ -3422,15 +3443,19 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
EXPECT_EQ(1u, sink_->message_count());
{
const IPC::Message* msg = sink_->GetMessageAt(0);
- EXPECT_EQ(static_cast<uint32_t>(ViewMsg_Resize::ID), msg->type());
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
+ EXPECT_EQ(static_cast<uint32_t>(ViewMsg_SynchronizeVisualProperties::ID),
+ msg->type());
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(size2.ToString(), std::get<0>(params).new_size.ToString());
}
// Send resize ack to observe new Resize messages.
- update_params.view_size = size2;
- widget_host_->OnMessageReceived(ViewHostMsg_ResizeOrRepaint_ACK(
- widget_host_->GetRoutingID(), update_params));
+ {
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = size2;
+ metadata.local_surface_id = base::nullopt;
+ widget_host_->DidUpdateVisualProperties(metadata);
+ }
sink_->ClearMessages();
// Resize renderer again, before receiving a frame. Should not produce a
@@ -3443,7 +3468,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
// message.
view_->renderer_compositor_frame_sink_->Reset();
view_->SubmitCompositorFrame(
- id3, MakeDelegatedFrame(1.f, size3, gfx::Rect(size3)), nullptr);
+ id3, MakeDelegatedFrame(1.f, size3, gfx::Rect(size3)), base::nullopt);
view_->renderer_compositor_frame_sink_->Flush();
// Expect the frame ack;
EXPECT_TRUE(view_->renderer_compositor_frame_sink_->did_receive_ack());
@@ -3453,7 +3478,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
// produce a Resize message after the commit.
view_->renderer_compositor_frame_sink_->Reset();
view_->SubmitCompositorFrame(
- id2, MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)), nullptr);
+ id2, MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)), base::nullopt);
view_->renderer_compositor_frame_sink_->Flush();
viz::SurfaceId surface_id = view_->surface_id();
if (!surface_id.is_valid()) {
@@ -3474,10 +3499,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
for (uint32_t i = 0; i < sink_->message_count(); ++i) {
const IPC::Message* msg = sink_->GetMessageAt(i);
switch (msg->type()) {
- case ViewMsg_Resize::ID: {
+ case ViewMsg_SynchronizeVisualProperties::ID: {
EXPECT_FALSE(has_resize);
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(msg, &params);
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(msg, &params);
EXPECT_EQ(size3.ToString(), std::get<0>(params).new_size.ToString());
has_resize = true;
break;
@@ -3488,263 +3513,15 @@ TEST_F(RenderWidgetHostViewAuraTest, DISABLED_Resize) {
}
}
EXPECT_TRUE(has_resize);
- update_params.view_size = size3;
- widget_host_->OnMessageReceived(ViewHostMsg_ResizeOrRepaint_ACK(
- widget_host_->GetRoutingID(), update_params));
+ {
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = size3;
+ metadata.local_surface_id = base::nullopt;
+ widget_host_->DidUpdateVisualProperties(metadata);
+ }
sink_->ClearMessages();
}
-// Skipped frames should not drop their damage.
-TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
- // TODO(fsamuel): Delete this test once surface synchronization is on for
- // all platforms.
- if (features::IsSurfaceSynchronizationEnabled())
- return;
-
- gfx::Rect view_rect(100, 100);
- gfx::Size frame_size = view_rect.size();
- viz::LocalSurfaceId local_surface_id =
- parent_local_surface_id_allocator_.GenerateId();
-
- view_->InitAsChild(nullptr);
- aura::client::ParentWindowWithContext(
- view_->GetNativeView(),
- parent_view_->GetNativeView()->GetRootWindow(),
- gfx::Rect());
- view_->SetSize(view_rect.size());
-
- // A full frame of damage.
- view_->SubmitCompositorFrame(local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
- EXPECT_EQ(kFrameIndexStart + 1u, FrameIndexForView(view_));
- EXPECT_EQ(view_rect, DamageRectForView(view_));
- view_->RunOnCompositingDidCommit();
-
- // A partial damage frame.
- gfx::Rect partial_view_rect(30, 30, 20, 20);
- view_->SubmitCompositorFrame(
- local_surface_id, MakeDelegatedFrame(1.f, frame_size, partial_view_rect),
- nullptr);
- EXPECT_EQ(kFrameIndexStart + 2u, FrameIndexForView(view_));
- EXPECT_EQ(partial_view_rect, DamageRectForView(view_));
- view_->RunOnCompositingDidCommit();
-
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // Lock the compositor. Now we should drop frames.
- view_rect = gfx::Rect(150, 150);
- view_->SetSize(view_rect.size());
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_TRUE(view_->compositor_locked());
-
- // This frame is dropped.
- gfx::Rect dropped_damage_rect_1(10, 20, 30, 40);
- view_->SubmitCompositorFrame(
- local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1), nullptr);
- EXPECT_EQ(kFrameIndexStart + 2u, FrameIndexForView(view_));
- view_->RunOnCompositingDidCommit();
-
- gfx::Rect dropped_damage_rect_2(40, 50, 10, 20);
- view_->SubmitCompositorFrame(
- local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2), nullptr);
- EXPECT_EQ(kFrameIndexStart + 2u, FrameIndexForView(view_));
- view_->RunOnCompositingDidCommit();
-
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_TRUE(view_->compositor_locked());
-
- // Unlock the compositor. This frame should damage everything.
- frame_size = view_rect.size();
- local_surface_id = parent_local_surface_id_allocator_.GenerateId();
-
- gfx::Rect new_damage_rect(5, 6, 10, 10);
- view_->SubmitCompositorFrame(
- local_surface_id, MakeDelegatedFrame(1.f, frame_size, new_damage_rect),
- nullptr);
- // The swap unlocks the compositor.
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
- EXPECT_EQ(kFrameIndexStart + 3u, FrameIndexForView(view_));
- EXPECT_EQ(view_rect, DamageRectForView(view_));
- // The UI commit unlocks for further resize.
- view_->RunOnCompositingDidCommit();
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // A partial damage frame, this should not be dropped.
- view_->SubmitCompositorFrame(
- local_surface_id, MakeDelegatedFrame(1.f, frame_size, partial_view_rect),
- nullptr);
- EXPECT_EQ(kFrameIndexStart + 4u, FrameIndexForView(view_));
- EXPECT_EQ(partial_view_rect, DamageRectForView(view_));
- view_->RunOnCompositingDidCommit();
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // Resize to something empty. This doesn't lock anything since it's not
- // visible anymore anyways.
- view_rect = gfx::Rect(100, 0);
- view_->SetSize(view_rect.size());
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // We're never expecting empty frames, resize to something non-empty.
- view_rect = gfx::Rect(100, 100);
- frame_size = view_rect.size();
- local_surface_id = parent_local_surface_id_allocator_.GenerateId();
- view_->SetSize(view_rect.size());
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_TRUE(view_->compositor_locked());
-
- // This frame should not be dropped.
- view_->SubmitCompositorFrame(local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
- EXPECT_EQ(kFrameIndexStart + 5u, FrameIndexForView(view_));
- EXPECT_EQ(view_rect, DamageRectForView(view_));
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
- view_->RunOnCompositingDidCommit();
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-}
-
-// If resize races with a renderer frame, we should lock for the right size.
-TEST_F(RenderWidgetHostViewAuraTest, ResizeAfterReceivingFrame) {
- // TODO(fsamuel): Delete this test once surface synchronization is on for
- // all platforms.
- if (features::IsSurfaceSynchronizationEnabled())
- return;
-
- gfx::Rect view_rect(100, 100);
- gfx::Size frame_size = view_rect.size();
- viz::LocalSurfaceId local_surface_id =
- parent_local_surface_id_allocator_.GenerateId();
-
- view_->InitAsChild(nullptr);
- aura::client::ParentWindowWithContext(
- view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
- gfx::Rect());
- view_->SetSize(view_rect.size());
-
- // A frame of initial size.
- view_->SubmitCompositorFrame(
- local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr);
- EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_));
- EXPECT_EQ(view_rect, DamageRectForView(view_));
- view_->RunOnCompositingDidCommit();
-
- // A frame of initial size arrives, but we don't commit in the UI yet.
- view_->SubmitCompositorFrame(
- local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr);
- EXPECT_EQ(kFrameIndexStart + 2, FrameIndexForView(view_));
-
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // Resize, and lock the compositor. Now we should drop frames of the old size.
- view_rect = gfx::Rect(150, 150);
- view_->SetSize(view_rect.size());
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_TRUE(view_->compositor_locked());
-
- view_->SubmitCompositorFrame(
- local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr);
- EXPECT_EQ(kFrameIndexStart + 2, FrameIndexForView(view_));
-
- // If the CompositorLock times out in the meantime, a commit would happen.
- // Verify that if a commit occurs, the lock remains and we reject frames
- // of the wrong size still.
- view_->RunOnCompositingDidCommit();
-
- EXPECT_TRUE(view_->resize_locked());
- // In this case we lied about it and the CompositorLock is still active.
- EXPECT_TRUE(view_->compositor_locked());
-
- view_->SubmitCompositorFrame(
- local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr);
- EXPECT_EQ(kFrameIndexStart + 2, FrameIndexForView(view_));
-
- // A frame arrives of the new size, which will be accepted.
- frame_size = view_rect.size();
- local_surface_id = parent_local_surface_id_allocator_.GenerateId();
- view_->SubmitCompositorFrame(
- local_surface_id,
- MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr);
- // Receiving the frame unlocks the compositor so it can commit.
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
- EXPECT_EQ(kFrameIndexStart + 3, FrameIndexForView(view_));
-
- // When the frame of the correct size is committed, the CompositorResizeLock
- // is released.
- view_->RunOnCompositingDidCommit();
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-}
-
-// When the DelegatedFrameHost does not have a frame from the renderer, it has
-// no reason to lock the compositor as there can't be guttering around a
-// renderer frame that doesn't exist.
-TEST_F(RenderWidgetHostViewAuraTest, MissingFramesDontLock) {
- // TODO(fsamuel): Delete this test once surface synchronization is on for
- // all platforms.
- if (features::IsSurfaceSynchronizationEnabled())
- return;
-
- gfx::Rect view_rect(100, 100);
- gfx::Size frame_size = view_rect.size();
-
- view_->InitAsChild(nullptr);
- aura::client::ParentWindowWithContext(
- view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
- gfx::Rect());
-
- // The view is resized before the first frame, which should not lock the
- // compositor as it's never received a frame to show yet.
- view_->SetSize(view_rect.size());
-
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // Submit a frame of initial size to make a frame present in
- // DelegatedFrameHost, at which point locking becomes feasible if resized.
- view_->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)), nullptr);
- view_->RunOnCompositingDidCommit();
-
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // The view is resized and has its frame evicted, before a new frame arrives.
- // The resize will lock the compositor, but when evicted, it should no longer
- // be locked.
- view_rect.SetRect(0, 0, 150, 150);
- view_->SetSize(view_rect.size());
- EXPECT_TRUE(view_->resize_locked());
- EXPECT_TRUE(view_->compositor_locked());
-
- view_->ClearCompositorFrame();
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-
- // And future resizes after eviction should not lock the compositor since
- // there is no frame present.
- view_rect.SetRect(0, 0, 120, 120);
- view_->SetSize(view_rect.size());
- EXPECT_FALSE(view_->resize_locked());
- EXPECT_FALSE(view_->compositor_locked());
-}
-
TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// TODO: fix for mash.
if (base::FeatureList::IsEnabled(features::kMash))
@@ -3763,7 +3540,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// Swap a frame.
view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId,
MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
+ base::nullopt);
EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_));
EXPECT_EQ(view_rect, DamageRectForView(view_));
view_->RunOnCompositingDidCommit();
@@ -3774,7 +3551,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// Submit a frame from the new RendererCompositorFrameSink.
view_->SubmitCompositorFrame(parent_local_surface_id_allocator_.GenerateId(),
MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
+ base::nullopt);
EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_));
EXPECT_EQ(view_rect, DamageRectForView(view_));
view_->RunOnCompositingDidCommit();
@@ -3785,7 +3562,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// Submit a frame from the new RendererCompositorFrameSink.
view_->SubmitCompositorFrame(parent_local_surface_id_allocator_.GenerateId(),
MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
+ base::nullopt);
EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_));
EXPECT_EQ(view_rect, DamageRectForView(view_));
view_->RunOnCompositingDidCommit();
@@ -3796,7 +3573,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
// Swap another frame, with a different surface id.
view_->SubmitCompositorFrame(parent_local_surface_id_allocator_.GenerateId(),
MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
+ base::nullopt);
EXPECT_EQ(kFrameIndexStart + 1, FrameIndexForView(view_));
EXPECT_EQ(view_rect, DamageRectForView(view_));
view_->RunOnCompositingDidCommit();
@@ -3827,7 +3604,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
view_->SubmitCompositorFrame(
kArbitraryLocalSurfaceId,
MakeDelegatedFrame(1.f, gfx::Size(400, 400), gfx::Rect(400, 400)),
- nullptr);
+ base::nullopt);
EXPECT_FALSE(view_->HasPrimarySurface());
EXPECT_FALSE(view_->HasFallbackSurface());
}
@@ -3844,8 +3621,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
gfx::Rect());
- // Prevent the DelegatedFrameHost from skipping frames.
- view_->DisableResizeLock();
ASSERT_TRUE(view_->delegated_frame_host_);
view_->SetSize(gfx::Size(300, 300));
@@ -3866,7 +3641,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) {
view_->SubmitCompositorFrame(
kArbitraryLocalSurfaceId,
MakeDelegatedFrame(1.f, gfx::Size(400, 400), gfx::Rect(400, 400)),
- nullptr);
+ base::nullopt);
EXPECT_EQ(gfx::Size(400, 400), view_->window_->layer()->size());
}
@@ -3883,9 +3658,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
gfx::Rect());
- // Prevent the DelegatedFrameHost from skipping frames.
- view_->DisableResizeLock();
-
view_->SetSize(gfx::Size(300, 300));
ASSERT_TRUE(view_->HasPrimarySurface());
EXPECT_EQ(gfx::Size(300, 300), view_->window_->layer()->size());
@@ -3921,7 +3693,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// Swap a frame.
view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId,
MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
+ base::nullopt);
view_->RunOnCompositingDidCommit();
// Signal that a new RendererCompositorFrameSink was created.
@@ -3930,7 +3702,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// Submit a frame from the new RendererCompositorFrameSink.
view_->SubmitCompositorFrame(parent_local_surface_id_allocator_.GenerateId(),
MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
+ base::nullopt);
view_->RunOnCompositingDidCommit();
}
@@ -3970,7 +3742,6 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// run a UI compositor so the DelegatedFrameHost doesn't get the chance
// to release its resize lock once it receives a frame of the expected
// size.
- views[i]->DisableResizeLock();
views[i]->InitAsChild(nullptr);
aura::client::ParentWindowWithContext(
views[i]->GetNativeView(),
@@ -3986,7 +3757,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
ASSERT_FALSE(views[i]->HasFallbackSurface());
views[i]->SubmitCompositorFrame(
views[i]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
ASSERT_TRUE(views[i]->HasPrimarySurface());
EXPECT_TRUE(views[i]->HasFallbackSurface());
views[i]->Hide();
@@ -4006,7 +3777,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// Swap a frame on it, it should evict the next LRU [1].
views[0]->SubmitCompositorFrame(
views[0]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
EXPECT_TRUE(views[0]->HasFallbackSurface());
EXPECT_FALSE(views[1]->HasFallbackSurface());
views[0]->Hide();
@@ -4016,7 +3787,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[1]->Show();
views[1]->SubmitCompositorFrame(
views[1]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
EXPECT_TRUE(views[0]->HasFallbackSurface());
EXPECT_TRUE(views[1]->HasFallbackSurface());
EXPECT_FALSE(views[2]->HasFallbackSurface());
@@ -4031,7 +3802,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// have a frame should not.
views[i]->SubmitCompositorFrame(
views[i]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
EXPECT_TRUE(views[i]->HasFallbackSurface());
}
EXPECT_FALSE(views[0]->HasFallbackSurface());
@@ -4039,7 +3810,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
// Swap a frame on [0], it should be evicted immediately.
views[0]->SubmitCompositorFrame(
views[0]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
EXPECT_FALSE(views[0]->HasFallbackSurface());
// Make [0] visible, and swap a frame on it. Nothing should be evicted
@@ -4047,7 +3818,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[0]->Show();
views[0]->SubmitCompositorFrame(
views[0]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
for (size_t i = 0; i < renderer_count; ++i)
EXPECT_TRUE(views[i]->HasFallbackSurface()) << i;
@@ -4070,161 +3841,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
views[1]->Show();
views[1]->SubmitCompositorFrame(
views[1]->GetLocalSurfaceId(),
- MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)), nullptr);
-
- for (size_t i = 0; i < renderer_count; ++i) {
- views[i]->Destroy();
- delete hosts[i];
- }
-}
-
-TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
- // TODO(fsamuel): Delete this test once surface synchronization is on for
- // all platforms.
- if (features::IsSurfaceSynchronizationEnabled())
- return;
-
- view_->InitAsChild(nullptr);
-
- size_t max_renderer_frames =
- FrameEvictionManager::GetInstance()->GetMaxNumberOfSavedFrames();
- ASSERT_LE(2u, max_renderer_frames);
- size_t renderer_count = max_renderer_frames + 1;
- gfx::Rect view_rect(100, 100);
- gfx::Size frame_size = view_rect.size();
-
- std::unique_ptr<RenderWidgetHostImpl* []> hosts(
- new RenderWidgetHostImpl*[renderer_count]);
- std::unique_ptr<FakeRenderWidgetHostViewAura* []> views(
- new FakeRenderWidgetHostViewAura*[renderer_count]);
-
- // Create a bunch of renderers.
- for (size_t i = 0; i < renderer_count; ++i) {
- int32_t routing_id = process_host_->GetNextRoutingID();
- delegates_.push_back(base::WrapUnique(new MockRenderWidgetHostDelegate));
- hosts[i] = MockRenderWidgetHostImpl::Create(delegates_.back().get(),
- process_host_, routing_id);
- delegates_.back()->set_widget_host(hosts[i]);
- hosts[i]->Init();
- views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
- // Prevent frames from being skipped due to resize, this test does not
- // run a UI compositor so the DelegatedFrameHost doesn't get the chance
- // to release its resize lock once it receives a frame of the expected
- // size.
- views[i]->DisableResizeLock();
- views[i]->InitAsChild(nullptr);
- aura::client::ParentWindowWithContext(
- views[i]->GetNativeView(),
- parent_view_->GetNativeView()->GetRootWindow(),
- gfx::Rect());
- views[i]->SetSize(view_rect.size());
- }
-
- // Make each renderer visible, and swap a frame on it, then make it invisible.
- for (size_t i = 0; i < renderer_count; ++i) {
- views[i]->Show();
- views[i]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
- EXPECT_TRUE(views[i]->HasFallbackSurface());
- views[i]->Hide();
- }
-
- // There should be max_renderer_frames with a frame in it, and one without it.
- // Since the logic is LRU eviction, the first one should be without.
- EXPECT_FALSE(views[0]->HasFallbackSurface());
- for (size_t i = 1; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->HasFallbackSurface());
-
- // LRU renderer is [0], make it visible, it shouldn't evict anything yet.
- views[0]->Show();
- EXPECT_FALSE(views[0]->HasFallbackSurface());
- EXPECT_TRUE(views[1]->HasFallbackSurface());
- // Since [0] doesn't have a frame, it should be waiting for the renderer to
- // give it one.
- EXPECT_TRUE(views[0]->released_front_lock_active());
-
- // Swap a frame on it, it should evict the next LRU [1].
- views[0]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId, MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
- EXPECT_TRUE(views[0]->HasFallbackSurface());
- EXPECT_FALSE(views[1]->HasFallbackSurface());
- // Now that [0] got a frame, it shouldn't be waiting any more.
- EXPECT_FALSE(views[0]->released_front_lock_active());
- views[0]->Hide();
-
- // LRU renderer is [1], still hidden. Swap a frame on it, it should evict
- // the next LRU [2].
- views[1]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId, MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
- EXPECT_TRUE(views[0]->HasFallbackSurface());
- EXPECT_TRUE(views[1]->HasFallbackSurface());
- EXPECT_FALSE(views[2]->HasFallbackSurface());
- for (size_t i = 3; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->HasFallbackSurface());
-
- // Make all renderers but [0] visible and swap a frame on them, keep [0]
- // hidden, it becomes the LRU.
- for (size_t i = 1; i < renderer_count; ++i) {
- views[i]->Show();
- // The renderers who don't have a frame should be waiting. The ones that
- // have a frame should not.
- // In practice, [1] has a frame, but anything after has its frame evicted.
- EXPECT_EQ(!views[i]->HasFallbackSurface(),
- views[i]->released_front_lock_active());
- views[i]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
- // Now everyone has a frame.
- EXPECT_FALSE(views[i]->released_front_lock_active());
- EXPECT_TRUE(views[i]->HasFallbackSurface());
- }
- EXPECT_FALSE(views[0]->HasFallbackSurface());
-
- // Swap a frame on [0], it should be evicted immediately.
- views[0]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId, MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
- EXPECT_FALSE(views[0]->HasFallbackSurface());
-
- // Make [0] visible, and swap a frame on it. Nothing should be evicted
- // although we're above the limit.
- views[0]->Show();
- // We don't have a frame, wait.
- EXPECT_TRUE(views[0]->released_front_lock_active());
- views[0]->SubmitCompositorFrame(
- kArbitraryLocalSurfaceId, MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
- EXPECT_FALSE(views[0]->released_front_lock_active());
- for (size_t i = 0; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->HasFallbackSurface());
-
- // Make [0] hidden, it should evict its frame.
- views[0]->Hide();
- EXPECT_FALSE(views[0]->HasFallbackSurface());
-
- // Make [0] visible, don't give it a frame, it should be waiting.
- views[0]->Show();
- EXPECT_TRUE(views[0]->released_front_lock_active());
- // Make [0] hidden, it should stop waiting.
- views[0]->Hide();
- EXPECT_FALSE(views[0]->released_front_lock_active());
-
- // Make [1] hidden, resize it. It should drop its frame.
- views[1]->Hide();
- EXPECT_TRUE(views[1]->HasFallbackSurface());
- gfx::Size size2(200, 200);
- viz::LocalSurfaceId id2 = parent_local_surface_id_allocator_.GenerateId();
- views[1]->SetSize(size2);
- EXPECT_FALSE(views[1]->HasFallbackSurface());
- // Show it, it should block until we give it a frame.
- views[1]->Show();
- EXPECT_TRUE(views[1]->released_front_lock_active());
- views[1]->SubmitCompositorFrame(
- id2, MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)), nullptr);
- EXPECT_FALSE(views[1]->released_front_lock_active());
+ MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)), base::nullopt);
for (size_t i = 0; i < renderer_count; ++i) {
views[i]->Destroy();
@@ -4275,7 +3892,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
views[i]->SubmitCompositorFrame(
i ? parent_local_surface_id_allocator_.GenerateId()
: kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
EXPECT_TRUE(views[i]->HasFallbackSurface());
}
@@ -4287,7 +3904,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
views[0]->Show();
views[0]->SubmitCompositorFrame(
kArbitraryLocalSurfaceId, MakeDelegatedFrame(1.f, frame_size, view_rect),
- nullptr);
+ base::nullopt);
EXPECT_TRUE(views[0]->HasFallbackSurface());
views[0]->GetDelegatedFrameHost()->LockResources();
views[0]->Hide();
@@ -4352,7 +3969,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
views[i]->Show();
views[i]->SubmitCompositorFrame(
kArbitraryLocalSurfaceId,
- MakeDelegatedFrame(1.f, frame_size, view_rect), nullptr);
+ MakeDelegatedFrame(1.f, frame_size, view_rect), base::nullopt);
EXPECT_TRUE(views[i]->HasFallbackSurface());
}
@@ -4439,7 +4056,8 @@ TEST_F(RenderWidgetHostViewAuraTest, ForwardsBeginFrameAcks) {
viz::BeginFrameAck ack(source_id, 5, true);
viz::CompositorFrame frame = MakeDelegatedFrame(1.f, frame_size, view_rect);
frame.metadata.begin_frame_ack = ack;
- view_->SubmitCompositorFrame(local_surface_id, std::move(frame), nullptr);
+ view_->SubmitCompositorFrame(local_surface_id, std::move(frame),
+ base::nullopt);
view_->RunOnCompositingDidCommit();
EXPECT_EQ(ack, observer.last_ack());
}
@@ -4469,18 +4087,18 @@ TEST_F(RenderWidgetHostViewAuraTest, VisibleViewportTest) {
// Defaults to full height of the view.
EXPECT_EQ(100, view_->GetVisibleViewportSize().height());
- widget_host_->ResetSizeAndRepaintPendingFlags();
+ widget_host_->ResetSentVisualProperties();
sink_->ClearMessages();
view_->SetInsets(gfx::Insets(0, 0, 40, 0));
EXPECT_EQ(60, view_->GetVisibleViewportSize().height());
- const IPC::Message *message = sink_->GetFirstMessageMatching(
- ViewMsg_Resize::ID);
+ const IPC::Message* message =
+ sink_->GetFirstMessageMatching(ViewMsg_SynchronizeVisualProperties::ID);
ASSERT_TRUE(message != nullptr);
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(message, &params);
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(message, &params);
EXPECT_EQ(60, std::get<0>(params).visible_viewport_size.height());
}
@@ -4956,7 +4574,7 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollEventsOverscrollWithFling() {
base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(17);
// Overscroll mode will get reset at the end of the fling progress.
while (overscroll_mode() != OVERSCROLL_NONE) {
- widget_host_->ProgressFling(progress_time);
+ widget_host_->ProgressFlingIfNeeded(progress_time);
progress_time += base::TimeDelta::FromMilliseconds(17);
}
EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
@@ -5142,7 +4760,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
// progress.
base::TimeTicks progress_time =
base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(17);
- widget_host_->ProgressFling(progress_time);
+ widget_host_->ProgressFlingIfNeeded(progress_time);
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
}
}
@@ -6419,7 +6037,7 @@ void RenderWidgetHostViewAuraOverscrollTest::ScrollDeltasResetOnEnd() {
base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(17);
// Overscroll delta will get reset at the end of the fling progress.
while (overscroll_delta_y() != 0.f) {
- widget_host_->ProgressFling(progress_time);
+ widget_host_->ProgressFlingIfNeeded(progress_time);
progress_time += base::TimeDelta::FromMilliseconds(17);
}
}
@@ -6527,8 +6145,8 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
viz::SurfaceId surface_id(view_->GetFrameSinkId(), kArbitraryLocalSurfaceId);
- auto hit_test_region_list = viz::mojom::HitTestRegionList::New();
- hit_test_region_list->flags = viz::mojom::kHitTestMine;
+ base::Optional<viz::HitTestRegionList> hit_test_region_list(base::in_place);
+ hit_test_region_list->flags = viz::HitTestRegionFlags::kHitTestMine;
hit_test_region_list->bounds.SetRect(0, 0, 100, 100);
view_->SubmitCompositorFrame(kArbitraryLocalSurfaceId,
MakeDelegatedFrame(1.f, frame_size, view_rect),
@@ -6541,10 +6159,11 @@ TEST_F(RenderWidgetHostViewAuraTest, HitTestRegionListSubmitted) {
view_->GetDelegatedFrameHost()
->GetCompositorFrameSinkSupportForTesting()
->frame_sink_manager();
- const viz::mojom::HitTestRegionList* active_hit_test_region_list =
+ const viz::HitTestRegionList* active_hit_test_region_list =
frame_sink_manager->hit_test_manager()->GetActiveHitTestRegionList(
&delegate, surface_id.frame_sink_id());
- EXPECT_EQ(active_hit_test_region_list->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(active_hit_test_region_list->flags,
+ viz::HitTestRegionFlags::kHitTestMine);
EXPECT_EQ(active_hit_test_region_list->bounds, view_rect);
}
@@ -7305,4 +6924,167 @@ TEST_F(InputMethodStateAuraTest, ImeFocusedNodeChanged) {
EXPECT_FALSE(has_composition_text());
}
+TEST_F(RenderWidgetHostViewAuraTest, FocusReasonNotFocused) {
+ EXPECT_EQ(ui::TextInputClient::FOCUS_REASON_NONE,
+ parent_view_->GetFocusReason());
+}
+
+TEST_F(RenderWidgetHostViewAuraTest, FocusReasonMouse) {
+ parent_view_->Focus();
+ ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT);
+
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ 0);
+ parent_view_->OnMouseEvent(&mouse_event);
+ parent_view_->FocusedNodeChanged(true, gfx::Rect());
+
+ EXPECT_EQ(ui::TextInputClient::FOCUS_REASON_MOUSE,
+ parent_view_->GetFocusReason());
+}
+
+TEST_F(RenderWidgetHostViewAuraTest, FocusReasonTouch) {
+ parent_view_->Focus();
+ ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT);
+
+ ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP_DOWN);
+ tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ tap_details.set_primary_pointer_type(
+ ui::EventPointerType::POINTER_TYPE_TOUCH);
+ ui::GestureEvent touch_event(0, 0, 0, base::TimeTicks(), tap_details);
+
+ parent_view_->OnGestureEvent(&touch_event);
+ parent_view_->FocusedNodeChanged(true, gfx::Rect());
+
+ EXPECT_EQ(ui::TextInputClient::FOCUS_REASON_TOUCH,
+ parent_view_->GetFocusReason());
+}
+
+TEST_F(RenderWidgetHostViewAuraTest, FocusReasonPen) {
+ parent_view_->Focus();
+ ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT);
+
+ ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP_DOWN);
+ tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ tap_details.set_primary_pointer_type(ui::EventPointerType::POINTER_TYPE_PEN);
+ ui::GestureEvent pen_event(0, 0, 0, base::TimeTicks(), tap_details);
+
+ parent_view_->OnGestureEvent(&pen_event);
+ parent_view_->FocusedNodeChanged(true, gfx::Rect());
+
+ EXPECT_EQ(ui::TextInputClient::FOCUS_REASON_PEN,
+ parent_view_->GetFocusReason());
+}
+
+TEST_F(RenderWidgetHostViewAuraTest, FocusReasonMultipleEventsOnSameNode) {
+ parent_view_->Focus();
+ ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT);
+
+ // Touch then pen.
+ {
+ ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP_DOWN);
+ tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ tap_details.set_primary_pointer_type(
+ ui::EventPointerType::POINTER_TYPE_TOUCH);
+ ui::GestureEvent touch_event(0, 0, 0, base::TimeTicks(), tap_details);
+
+ parent_view_->OnGestureEvent(&touch_event);
+ parent_view_->FocusedNodeChanged(true, gfx::Rect());
+ }
+
+ {
+ ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP_DOWN);
+ tap_details.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ tap_details.set_primary_pointer_type(
+ ui::EventPointerType::POINTER_TYPE_PEN);
+ ui::GestureEvent pen_event(0, 0, 0, base::TimeTicks(), tap_details);
+
+ parent_view_->OnGestureEvent(&pen_event);
+ }
+
+ EXPECT_EQ(ui::TextInputClient::FOCUS_REASON_TOUCH,
+ parent_view_->GetFocusReason());
+}
+
+#if defined(OS_WIN)
+class MockInputMethodKeyboardController final
+ : public ui::InputMethodKeyboardController {
+ public:
+ MockInputMethodKeyboardController() = default;
+ bool DisplayVirtualKeyboard() override { return true; }
+
+ void DismissVirtualKeyboard() override {}
+
+ void AddObserver(
+ ui::InputMethodKeyboardControllerObserver* observer) override {
+ observer_count_++;
+ }
+
+ void RemoveObserver(
+ ui::InputMethodKeyboardControllerObserver* observer) override {
+ observer_count_--;
+ }
+
+ bool IsKeyboardVisible() override { return false; }
+
+ size_t observer_count() const { return observer_count_; }
+
+ private:
+ size_t observer_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(MockInputMethodKeyboardController);
+};
+
+class RenderWidgetHostViewAuraKeyboardMockInputMethod
+ : public ui::MockInputMethod {
+ public:
+ RenderWidgetHostViewAuraKeyboardMockInputMethod()
+ : MockInputMethod(nullptr) {}
+ ui::InputMethodKeyboardController* GetInputMethodKeyboardController()
+ override {
+ return &keyboard_controller_;
+ }
+ size_t keyboard_controller_observer_count() const {
+ return keyboard_controller_.observer_count();
+ }
+
+ private:
+ MockInputMethodKeyboardController keyboard_controller_;
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraKeyboardMockInputMethod);
+};
+
+class RenderWidgetHostViewAuraKeyboardTest
+ : public RenderWidgetHostViewAuraTest {
+ public:
+ RenderWidgetHostViewAuraKeyboardTest() = default;
+ ~RenderWidgetHostViewAuraKeyboardTest() override{};
+ void SetUp() override {
+ input_method_ = new RenderWidgetHostViewAuraKeyboardMockInputMethod();
+ // transfers ownership.
+ ui::SetUpInputMethodForTesting(input_method_);
+ SetUpEnvironment();
+ }
+
+ size_t keyboard_controller_observer_count() const {
+ return input_method_->keyboard_controller_observer_count();
+ }
+
+ private:
+ // Not owned.
+ RenderWidgetHostViewAuraKeyboardMockInputMethod* input_method_ = nullptr;
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraKeyboardTest);
+};
+
+TEST_F(RenderWidgetHostViewAuraKeyboardTest, KeyboardObserverDestroyed) {
+ parent_view_->FocusedNodeTouched(true);
+ EXPECT_NE(parent_view_->keyboard_observer_.get(), nullptr);
+ EXPECT_EQ(keyboard_controller_observer_count(), 1u);
+ // Detach the RenderWidgetHostViewAura from the IME.
+ parent_view_->DetachFromInputMethod();
+ EXPECT_EQ(parent_view_->keyboard_observer_.get(), nullptr);
+ EXPECT_EQ(keyboard_controller_observer_count(), 0u);
+}
+
+#endif // defined(OS_WIN)
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
index 7655a0fe3f5..1c52a5fd396 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -8,18 +8,23 @@
#include "base/logging.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface_hittest.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/compositor/surface_utils.h"
+#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/renderer_host/display_util.h"
+#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/common/content_switches_internal.h"
#include "content/public/common/content_features.h"
@@ -27,6 +32,7 @@
#include "ui/base/ui_base_types.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -50,6 +56,7 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
features::kTouchpadAndWheelScrollLatching)),
web_contents_accessibility_(nullptr),
is_currently_scrolling_viewport_(false),
+ use_viz_hit_test_(features::IsVizHitTestingEnabled()),
renderer_frame_number_(0),
weak_factory_(this) {
host_->render_frame_metadata_provider()->AddObserver(this);
@@ -84,6 +91,14 @@ RenderWidgetHost* RenderWidgetHostViewBase::GetRenderWidgetHost() const {
return host();
}
+void RenderWidgetHostViewBase::SetContentBackgroundColor(SkColor color) {
+ if (content_background_color_ == color)
+ return;
+
+ content_background_color_ = color;
+ UpdateBackgroundColor();
+}
+
void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() {
// Note: RenderWidgetHostInputEventRouter is an observer, and uses the
// following notification to remove this view from its surface owners map.
@@ -93,6 +108,10 @@ void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() {
DCHECK(!observers_.might_have_observers());
}
+MouseWheelPhaseHandler* RenderWidgetHostViewBase::GetMouseWheelPhaseHandler() {
+ return nullptr;
+}
+
bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message& msg){
return false;
}
@@ -105,9 +124,8 @@ void RenderWidgetHostViewBase::OnRenderFrameMetadataChanged() {
void RenderWidgetHostViewBase::OnRenderFrameSubmission() {}
-void RenderWidgetHostViewBase::SetBackgroundColorToDefault() {
- SetBackgroundColor(SK_ColorWHITE);
-}
+void RenderWidgetHostViewBase::OnLocalSurfaceIdChanged(
+ const cc::RenderFrameMetadata& metadata) {}
gfx::Size RenderWidgetHostViewBase::GetCompositorViewportPixelSize() const {
return gfx::ScaleToCeiledSize(GetRequestedRendererSize(),
@@ -154,13 +172,19 @@ gfx::Size RenderWidgetHostViewBase::GetRequestedRendererSize() const {
return GetViewBounds().size();
}
+uint32_t RenderWidgetHostViewBase::GetCaptureSequenceNumber() const {
+ // TODO(vmpstr): Implement this for overrides other than aura and child frame.
+ NOTIMPLEMENTED_LOG_ONCE();
+ return 0u;
+}
+
ui::TextInputClient* RenderWidgetHostViewBase::GetTextInputClient() {
NOTREACHED();
return nullptr;
}
void RenderWidgetHostViewBase::SetIsInVR(bool is_in_vr) {
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
}
bool RenderWidgetHostViewBase::IsInVR() const {
@@ -179,15 +203,14 @@ void RenderWidgetHostViewBase::CopyFromSurface(
const gfx::Rect& src_rect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
std::move(callback).Run(SkBitmap());
}
-viz::mojom::FrameSinkVideoCapturerPtr
+std::unique_ptr<viz::ClientFrameSinkVideoCapturer>
RenderWidgetHostViewBase::CreateVideoCapturer() {
- viz::mojom::FrameSinkVideoCapturerPtr video_capturer;
- GetHostFrameSinkManager()->CreateVideoCapturer(
- mojo::MakeRequest(&video_capturer));
+ std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer =
+ GetHostFrameSinkManager()->CreateVideoCapturer();
video_capturer->ChangeTarget(GetFrameSinkId());
return video_capturer;
}
@@ -198,24 +221,51 @@ base::string16 RenderWidgetHostViewBase::GetSelectedText() {
return GetTextInputManager()->GetTextSelection(this)->selected_text();
}
+void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) {
+ DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
+ SkColorGetA(color) == SK_AlphaTRANSPARENT);
+ if (default_background_color_ == color)
+ return;
+
+ bool opaque = default_background_color_
+ ? SkColorGetA(*default_background_color_)
+ : SK_AlphaOPAQUE;
+ default_background_color_ = color;
+ UpdateBackgroundColor();
+ if (opaque != (SkColorGetA(color) == SK_AlphaOPAQUE))
+ host()->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
+}
+
+base::Optional<SkColor> RenderWidgetHostViewBase::GetBackgroundColor() const {
+ if (content_background_color_)
+ return content_background_color_;
+ return default_background_color_;
+}
+
bool RenderWidgetHostViewBase::IsMouseLocked() {
return mouse_locked_;
}
bool RenderWidgetHostViewBase::LockKeyboard(
- base::Optional<base::flat_set<int>> keys) {
- NOTIMPLEMENTED();
+ base::Optional<base::flat_set<ui::DomCode>> codes) {
+ NOTIMPLEMENTED_LOG_ONCE();
return false;
}
void RenderWidgetHostViewBase::UnlockKeyboard() {
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
}
bool RenderWidgetHostViewBase::IsKeyboardLocked() {
return keyboard_locked_;
}
+base::flat_map<std::string, std::string>
+RenderWidgetHostViewBase::GetKeyboardLayoutMap() {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return base::flat_map<std::string, std::string>();
+}
+
InputEventAckState RenderWidgetHostViewBase::FilterInputEvent(
const blink::WebInputEvent& input_event) {
// By default, input events are simply forwarded to the renderer.
@@ -273,6 +323,10 @@ gfx::NativeViewAccessible
return nullptr;
}
+bool RenderWidgetHostViewBase::RequestRepaintForTesting() {
+ return false;
+}
+
void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
if (host() && host()->delegate())
host()->delegate()->SendScreenRects();
@@ -310,7 +364,7 @@ void RenderWidgetHostViewBase::DidUnregisterFromTextInputManager(
void RenderWidgetHostViewBase::EnableAutoResize(const gfx::Size& min_size,
const gfx::Size& max_size) {
host()->SetAutoResize(true, min_size, max_size);
- host()->WasResized();
+ host()->SynchronizeVisualProperties();
}
void RenderWidgetHostViewBase::DisableAutoResize(const gfx::Size& new_size) {
@@ -321,23 +375,21 @@ void RenderWidgetHostViewBase::DisableAutoResize(const gfx::Size& new_size) {
if (host()->delegate())
host()->delegate()->ResetAutoResizeSize();
host()->SetAutoResize(false, gfx::Size(), gfx::Size());
- host()->WasResized();
+ host()->SynchronizeVisualProperties();
}
bool RenderWidgetHostViewBase::IsScrollOffsetAtTop() const {
return is_scroll_offset_at_top_;
}
-viz::ScopedSurfaceIdAllocator RenderWidgetHostViewBase::ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
- // TODO(cblume): This doesn't currently suppress allocation.
- // It maintains existing behavior while using the suppression style.
- // This will be addressed in a follow-up patch.
- // See https://crbug.com/805073
+viz::ScopedSurfaceIdAllocator
+RenderWidgetHostViewBase::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
+ // This doesn't suppress allocation. Derived classes that need suppression
+ // should override this function.
base::OnceCallback<void()> allocation_task =
- base::BindOnce(&RenderWidgetHostViewBase::OnResizeDueToAutoResizeComplete,
- weak_factory_.GetWeakPtr(), sequence_number);
+ base::BindOnce(&RenderWidgetHostViewBase::SynchronizeVisualProperties,
+ weak_factory_.GetWeakPtr());
return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
}
@@ -381,7 +433,15 @@ void RenderWidgetHostViewBase::DidReceiveRendererFrame() {
void RenderWidgetHostViewBase::ShowDisambiguationPopup(
const gfx::Rect& rect_pixels,
const SkBitmap& zoomed_bitmap) {
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void RenderWidgetHostViewBase::OnAutoscrollStart() {
+ if (!GetMouseWheelPhaseHandler())
+ return;
+
+ // End the current scrolling seqeunce when autoscrolling starts.
+ GetMouseWheelPhaseHandler()->DispatchPendingWheelEndEvent();
}
gfx::Size RenderWidgetHostViewBase::GetVisibleViewportSize() const {
@@ -389,7 +449,7 @@ gfx::Size RenderWidgetHostViewBase::GetVisibleViewportSize() const {
}
void RenderWidgetHostViewBase::SetInsets(const gfx::Insets& insets) {
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
}
void RenderWidgetHostViewBase::DisplayCursor(const WebCursor& cursor) {
@@ -400,6 +460,10 @@ CursorManager* RenderWidgetHostViewBase::GetCursorManager() {
return nullptr;
}
+void RenderWidgetHostViewBase::TransformPointToRootSurface(gfx::PointF* point) {
+ return;
+}
+
void RenderWidgetHostViewBase::OnDidNavigateMainFrameToNewPage() {
}
@@ -490,6 +554,19 @@ gfx::PointF RenderWidgetHostViewBase::TransformRootPointToViewCoordSpace(
bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
+ if (use_viz_hit_test_) {
+ return TransformPointToLocalCoordSpaceViz(point, original_surface,
+ transformed_point, source);
+ }
+ return TransformPointToLocalCoordSpaceLegacy(point, original_surface,
+ transformed_point);
+}
+
+bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
*transformed_point = point;
return true;
@@ -498,7 +575,8 @@ bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
bool RenderWidgetHostViewBase::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) {
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
NOTREACHED();
return true;
}
@@ -598,6 +676,11 @@ void RenderWidgetHostViewBase::OnChildFrameDestroyed(int routing_id) {
}
#endif
+void RenderWidgetHostViewBase::SynchronizeVisualProperties() {
+ if (host())
+ host()->SynchronizeVisualProperties();
+}
+
#if defined(USE_AURA)
void RenderWidgetHostViewBase::OnDidScheduleEmbed(
int routing_id,
@@ -636,21 +719,96 @@ RenderWidgetHostViewBase::GetWindowTreeClientFromRenderer() {
#endif
-void RenderWidgetHostViewBase::OnResizeDueToAutoResizeComplete(
- uint64_t sequence_number) {
- if (host())
- host()->DidAllocateLocalSurfaceIdForAutoResize(sequence_number);
-}
-
#if defined(OS_MACOSX)
bool RenderWidgetHostViewBase::ShouldContinueToPauseForFrame() {
return false;
}
+
+void RenderWidgetHostViewBase::SetParentUiLayer(ui::Layer* parent_ui_layer) {}
#endif
void RenderWidgetHostViewBase::DidNavigate() {
if (host())
- host()->WasResized();
+ host()->SynchronizeVisualProperties();
+}
+
+bool RenderWidgetHostViewBase::TransformPointToTargetCoordSpace(
+ RenderWidgetHostViewBase* original_view,
+ RenderWidgetHostViewBase* target_view,
+ const gfx::PointF& point,
+ gfx::PointF* transformed_point,
+ viz::EventSource source) const {
+ DCHECK(use_viz_hit_test_);
+ viz::FrameSinkId root_frame_sink_id = original_view->GetRootFrameSinkId();
+ if (!root_frame_sink_id.is_valid())
+ return false;
+ const auto& display_hit_test_query_map =
+ GetHostFrameSinkManager()->display_hit_test_query();
+ const auto iter = display_hit_test_query_map.find(root_frame_sink_id);
+ if (iter == display_hit_test_query_map.end())
+ return false;
+ viz::HitTestQuery* query = iter->second.get();
+
+ std::vector<viz::FrameSinkId> target_ancestors;
+ target_ancestors.push_back(target_view->GetFrameSinkId());
+ RenderWidgetHostViewBase* cur_view = target_view;
+ while (cur_view->IsRenderWidgetHostViewChildFrame()) {
+ if (cur_view->IsRenderWidgetHostViewGuest()) {
+ cur_view = static_cast<RenderWidgetHostViewGuest*>(cur_view)
+ ->GetOwnerRenderWidgetHostView();
+ } else {
+ cur_view = static_cast<RenderWidgetHostViewChildFrame*>(cur_view)
+ ->GetParentView();
+ }
+ if (!cur_view)
+ return false;
+ target_ancestors.push_back(cur_view->GetFrameSinkId());
+ }
+ target_ancestors.push_back(root_frame_sink_id);
+
+ float device_scale_factor = original_view->GetDeviceScaleFactor();
+ DCHECK_GT(device_scale_factor, 0.0f);
+ gfx::Point3F point_in_pixels(
+ gfx::ConvertPointToPixel(device_scale_factor, point));
+ // TODO(riajiang): Optimize so that |point_in_pixels| doesn't need to be in
+ // the coordinate space of the root surface in HitTestQuery.
+ gfx::Transform transform_root_to_original;
+ query->GetTransformToTarget(original_view->GetFrameSinkId(),
+ &transform_root_to_original);
+ if (!transform_root_to_original.TransformPointReverse(&point_in_pixels))
+ return false;
+ if (!query->TransformLocationForTarget(source, target_ancestors,
+ point_in_pixels.AsPointF(),
+ transformed_point)) {
+ return false;
+ }
+ *transformed_point =
+ gfx::ConvertPointToDIP(device_scale_factor, *transformed_point);
+ return true;
+}
+
+bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpaceViz(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
+ DCHECK(use_viz_hit_test_);
+ viz::FrameSinkId original_frame_sink_id = original_surface.frame_sink_id();
+ viz::FrameSinkId target_frame_sink_id = GetFrameSinkId();
+ if (!original_frame_sink_id.is_valid() || !target_frame_sink_id.is_valid())
+ return false;
+ if (original_frame_sink_id == target_frame_sink_id)
+ return true;
+ if (!host() || !host()->delegate())
+ return false;
+ auto* router = host()->delegate()->GetInputEventRouter();
+ if (!router)
+ return false;
+ *transformed_point = point;
+ return TransformPointToTargetCoordSpace(
+ router->FindViewFromFrameSinkId(original_frame_sink_id),
+ router->FindViewFromFrameSinkId(target_frame_sink_id), point,
+ transformed_point, source);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.h b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
index 8e391207a8a..048fd7d3a8b 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
@@ -20,6 +20,7 @@
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/surfaces/scoped_surface_id_allocator.h"
#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/host/hit_test/hit_test_query.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
#include "content/public/browser/render_frame_metadata_provider.h"
@@ -29,7 +30,7 @@
#include "ipc/ipc_listener.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_type.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h"
#include "third_party/blink/public/web/web_popup_type.h"
#include "third_party/blink/public/web/web_text_direction.h"
#include "third_party/skia/include/core/SkImageInfo.h"
@@ -65,7 +66,9 @@ class WebMouseWheelEvent;
}
namespace ui {
+enum class DomCode;
class LatencyInfo;
+class Layer;
struct DidOverscrollParams;
}
@@ -78,6 +81,7 @@ namespace content {
class BrowserAccessibilityDelegate;
class BrowserAccessibilityManager;
class CursorManager;
+class MouseWheelPhaseHandler;
class RenderWidgetHostImpl;
class RenderWidgetHostViewBaseObserver;
class SyntheticGestureTarget;
@@ -107,16 +111,18 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// RenderWidgetHostView implementation.
RenderWidgetHost* GetRenderWidgetHost() const final;
- void SetBackgroundColorToDefault() final;
ui::TextInputClient* GetTextInputClient() override;
void WasUnOccluded() override {}
void WasOccluded() override {}
void SetIsInVR(bool is_in_vr) override;
base::string16 GetSelectedText() override;
bool IsMouseLocked() override;
- bool LockKeyboard(base::Optional<base::flat_set<int>> keys) override;
+ bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
+ void SetBackgroundColor(SkColor color) override;
+ base::Optional<SkColor> GetBackgroundColor() const override;
void UnlockKeyboard() override;
bool IsKeyboardLocked() override;
+ base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
gfx::Size GetVisibleViewportSize() const override;
void SetInsets(const gfx::Insets& insets) override;
bool IsSurfaceAvailableForCopy() const override;
@@ -124,7 +130,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
const gfx::Rect& src_rect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) override;
- viz::mojom::FrameSinkVideoCapturerPtr CreateVideoCapturer() override;
+ std::unique_ptr<viz::ClientFrameSinkVideoCapturer> CreateVideoCapturer()
+ override;
void FocusedNodeTouched(bool editable) override;
void GetScreenInfo(ScreenInfo* screen_info) const override;
void EnableAutoResize(const gfx::Size& min_size,
@@ -148,6 +155,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// RenderFrameMetadataProvider::Observer
void OnRenderFrameMetadataChanged() override;
void OnRenderFrameSubmission() override;
+ void OnLocalSurfaceIdChanged(
+ const cc::RenderFrameMetadata& metadata) override;
void SetPopupType(blink::WebPopupType popup_type);
@@ -174,11 +183,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// to nullptr.
void DidUnregisterFromTextInputManager(TextInputManager* text_input_manager);
- // Informs the view that the renderer has resized to |new_size| because auto-
- // resize is enabled.
- virtual viz::ScopedSurfaceIdAllocator ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number);
+ // Informs the view that the renderer's visual properties have been updated
+ // and a new viz::LocalSurfaceId has been allocated.
+ virtual viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata);
virtual bool IsLocalSurfaceIdAllocationSuppressed() const;
@@ -196,6 +204,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// when the view requires additional throttling.
virtual gfx::Size GetRequestedRendererSize() const;
+ // Returns the current capture sequence number.
+ virtual uint32_t GetCaptureSequenceNumber() const;
+
// The size of the view's backing surface in non-DPI-adjusted pixels.
virtual gfx::Size GetCompositorViewportPixelSize() const;
@@ -272,7 +283,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) = 0;
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) = 0;
virtual void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {}
@@ -281,6 +292,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// with what is visible on screen.
virtual void ClearCompositorFrame() = 0;
+ // Requests a new CompositorFrame from the renderer. This is done by
+ // allocating a new viz::LocalSurfaceId which forces a commit and draw.
+ virtual bool RequestRepaintForTesting();
+
// Because the associated remote WebKit instance can asynchronously
// prevent-default on a dispatched touch event, the touch events are queued in
// the GestureRecognizer until invocation of ProcessAckedTouchEvent releases
@@ -316,6 +331,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
gfx::PointF* transformed_point,
bool* out_query_renderer);
+ virtual void InjectTouchEvent(const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency) {}
+
virtual void PreProcessMouseEvent(const blink::WebMouseEvent& event) {}
virtual void PreProcessTouchEvent(const blink::WebTouchEvent& event) {}
@@ -339,7 +357,14 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// spaces of surfaces where one does not contain the other. To transform
// between sibling surfaces, the point must be transformed to the root's
// coordinate space as an intermediate step.
- virtual bool TransformPointToLocalCoordSpace(
+ bool TransformPointToLocalCoordSpace(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY);
+
+ // This is deprecated, and will be removed once Viz hit-test is the default.
+ virtual bool TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point);
@@ -349,7 +374,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
virtual bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point);
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY);
// TODO(kenrb, wjmaclean): This is a temporary subclass identifier for
// RenderWidgetHostViewGuests that is needed for special treatment during
@@ -457,9 +483,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// Displays the requested tooltip on the screen.
virtual void DisplayTooltipText(const base::string16& tooltip_text) {}
- // Returns the offset of the view from the origin of the browser compositor's
+ // Transforms |point| to be in the coordinate space of browser compositor's
// surface. This is in DIP.
- virtual gfx::Vector2d GetOffsetFromRootSurface() = 0;
+ virtual void TransformPointToRootSurface(gfx::PointF* point);
// Gets the bounds of the top-level window, in screen coordinates.
virtual gfx::Rect GetBoundsInRootWindow() = 0;
@@ -478,6 +504,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// changes.
virtual void SetShowingContextMenu(bool showing) {}
+ virtual void OnAutoscrollStart();
+
// Returns the associated RenderWidgetHostImpl.
RenderWidgetHostImpl* host() const { return host_; }
@@ -532,6 +560,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// Use only for resize on macOS. Returns true if there is not currently a
// frame of the view's size being displayed.
virtual bool ShouldContinueToPauseForFrame();
+
+ // Specify a ui::Layer into which the renderer's content should be
+ // composited. If nullptr is specified, then this layer will create a
+ // separate ui::Compositor as needed (e.g, for tab capture).
+ virtual void SetParentUiLayer(ui::Layer* parent_ui_layer);
#endif
virtual void DidNavigate();
@@ -542,8 +575,19 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
protected:
explicit RenderWidgetHostViewBase(RenderWidgetHost* host);
+ // SetContentBackgroundColor is called when the render wants to update the
+ // view's background color.
+ void SetContentBackgroundColor(SkColor color);
void NotifyObserversAboutShutdown();
+ virtual MouseWheelPhaseHandler* GetMouseWheelPhaseHandler();
+
+ // Applies background color without notifying the RenderWidget about
+ // opaqueness changes. This allows us to, when navigating to a new page,
+ // transfer this color to that page. This allows us to pass this background
+ // color to new views on navigation.
+ virtual void UpdateBackgroundColor() = 0;
+
#if defined(USE_AURA)
virtual void ScheduleEmbed(
ui::mojom::WindowTreeClientPtr client,
@@ -592,13 +636,24 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// destroyed before the RWHV is destroyed.
TextInputManager* text_input_manager_;
+ // The background color used in the current renderer.
+ base::Optional<SkColor> content_background_color_;
+
+ // The default background color used before getting the
+ // |content_background_color|.
+ base::Optional<SkColor> default_background_color_;
+
const bool wheel_scroll_latching_enabled_;
WebContentsAccessibility* web_contents_accessibility_;
bool is_currently_scrolling_viewport_;
+ bool use_viz_hit_test_ = false;
+
private:
+ void SynchronizeVisualProperties();
+
#if defined(USE_AURA)
void OnDidScheduleEmbed(int routing_id,
int embed_id,
@@ -611,7 +666,22 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
// LocalSurfaceId.
virtual void OnSynchronizedDisplayPropertiesChanged() {}
- void OnResizeDueToAutoResizeComplete(uint64_t sequence_number);
+ // Transforms |point| from |original_view| coord space to |target_view| coord
+ // space. Result is stored in |transformed_point|. Returns true if the
+ // transform is successful, false otherwise.
+ bool TransformPointToTargetCoordSpace(RenderWidgetHostViewBase* original_view,
+ RenderWidgetHostViewBase* target_view,
+ const gfx::PointF& point,
+ gfx::PointF* transformed_point,
+ viz::EventSource source) const;
+
+ // Used to transform |point| when Viz hit-test is enabled.
+ // TransformPointToLocalCoordSpaceLegacy is used in non-Viz hit-testing.
+ bool TransformPointToLocalCoordSpaceViz(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point,
+ viz::EventSource source);
gfx::Rect current_display_area_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc
index 47d80a3e04d..28147d2085c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc
@@ -6,7 +6,7 @@
#include "content/browser/renderer_host/display_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_type.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h"
#include "ui/display/display.h"
namespace content {
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 2e37ed47d72..801847175d3 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -7,7 +7,7 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
@@ -63,7 +63,7 @@ class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
frames_captured_(0) {}
void SetUpOnMainThread() override {
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
+ ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir_));
}
// Attempts to set up the source surface. Returns false if unsupported on the
@@ -157,8 +157,7 @@ class CommitBeforeSwapAckSentHelper
::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
service_manager::mojom::InterfaceProviderRequest*
interface_provider_request) override {
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
+ base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
frame_observer_->WaitForAnyFrameSubmission();
}
@@ -453,13 +452,13 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
"<style>"
"body { padding: 0; margin: 0; }"
".left { position: absolute;"
- " background: #0ff;"
+ " background: %%230ff;"
" width: %dpx;"
" height: %dpx;"
"}"
".right { position: absolute;"
" left: %dpx;"
- " background: #ff0;"
+ " background: %%23ff0;"
" width: %dpx;"
" height: %dpx;"
"}"
@@ -748,7 +747,7 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestHiDPI,
"<style>"
"body { padding: 0; margin: 0; }"
".box { position: absolute;"
- " background: #0ff;"
+ " background: %%230ff;"
" width: 100%%;"
" height: %dpx;"
"}"
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index c02239a7bc5..2891bddd1be 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -73,7 +73,6 @@ RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
frame_connector_(nullptr),
enable_viz_(
base::FeatureList::IsEnabled(features::kVizDisplayCompositor)),
- background_color_(SK_ColorWHITE),
scroll_bubbling_state_(NO_ACTIVE_GESTURE_SCROLL),
weak_factory_(this) {
if (base::FeatureList::IsEnabled(features::kMash)) {
@@ -171,7 +170,7 @@ void RenderWidgetHostViewChildFrame::SetFrameConnectorDelegate(
}
#if defined(USE_AURA)
- if (features::IsMusEnabled()) {
+ if (features::IsMashEnabled()) {
frame_connector_->EmbedRendererWindowTreeClientInParent(
GetWindowTreeClientFromRenderer());
}
@@ -241,6 +240,17 @@ bool RenderWidgetHostViewChildFrame::IsSurfaceAvailableForCopy() const {
return has_frame_;
}
+void RenderWidgetHostViewChildFrame::EnsureSurfaceSynchronizedForLayoutTest() {
+ // The capture sequence number which would normally be updated here is
+ // actually retrieved from the frame connector.
+}
+
+uint32_t RenderWidgetHostViewChildFrame::GetCaptureSequenceNumber() const {
+ if (!frame_connector_)
+ return 0u;
+ return frame_connector_->capture_sequence_number();
+}
+
void RenderWidgetHostViewChildFrame::Show() {
if (!host()->is_hidden())
return;
@@ -330,7 +340,7 @@ void RenderWidgetHostViewChildFrame::SetInsets(const gfx::Insets& insets) {
// Insets are used only for <webview> and are used to let the UI know it's
// being obscured (for e.g. by the virtual keyboard).
insets_ = insets;
- host()->WasResized(!insets_.IsEmpty());
+ host()->SynchronizeVisualProperties(!insets_.IsEmpty());
}
gfx::NativeView RenderWidgetHostViewChildFrame::GetNativeView() const {
@@ -349,18 +359,15 @@ RenderWidgetHostViewChildFrame::GetNativeViewAccessible() {
return nullptr;
}
-void RenderWidgetHostViewChildFrame::SetBackgroundColor(SkColor color) {
- background_color_ = color;
+void RenderWidgetHostViewChildFrame::UpdateBackgroundColor() {
+ DCHECK(GetBackgroundColor());
+ SkColor color = *GetBackgroundColor();
DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
SkColorGetA(color) == SK_AlphaTRANSPARENT);
host()->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
}
-SkColor RenderWidgetHostViewChildFrame::background_color() const {
- return background_color_;
-}
-
gfx::Size RenderWidgetHostViewChildFrame::GetCompositorViewportPixelSize()
const {
if (frame_connector_)
@@ -485,6 +492,14 @@ void RenderWidgetHostViewChildFrame::SetIsInert() {
}
}
+void RenderWidgetHostViewChildFrame::UpdateInheritedEffectiveTouchAction() {
+ if (host_ && frame_connector_) {
+ host_->Send(new ViewMsg_SetInheritedEffectiveTouchAction(
+ host_->GetRoutingID(),
+ frame_connector_->InheritedEffectiveTouchAction()));
+ }
+}
+
void RenderWidgetHostViewChildFrame::UpdateRenderThrottlingStatus() {
if (host() && frame_connector_) {
host()->Send(new ViewMsg_UpdateRenderThrottlingStatus(
@@ -625,7 +640,7 @@ void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedderImpl(
void RenderWidgetHostViewChildFrame::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) {
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) {
DCHECK(!enable_viz_);
TRACE_EVENT0("content",
"RenderWidgetHostViewChildFrame::OnSwapCompositorFrame");
@@ -660,11 +675,12 @@ void RenderWidgetHostViewChildFrame::ProcessFrameSwappedCallbacks() {
std::move(callback).Run();
}
-gfx::Vector2d RenderWidgetHostViewChildFrame::GetOffsetFromRootSurface() {
+void RenderWidgetHostViewChildFrame::TransformPointToRootSurface(
+ gfx::PointF* point) {
// This function is called by RenderWidgetHostInputEventRouter only for
// root-views.
NOTREACHED();
- return gfx::Vector2d();
+ return;
}
gfx::Rect RenderWidgetHostViewChildFrame::GetBoundsInRootWindow() {
@@ -731,6 +747,18 @@ void RenderWidgetHostViewChildFrame::PreProcessTouchEvent(
}
}
+viz::FrameSinkId RenderWidgetHostViewChildFrame::GetRootFrameSinkId() {
+ if (frame_connector_) {
+ RenderWidgetHostViewBase* root_view =
+ frame_connector_->GetRootRenderWidgetHostView();
+
+ // The root_view can be null in tests when using a TestWebContents.
+ if (root_view)
+ return root_view->GetRootFrameSinkId();
+ }
+ return viz::FrameSinkId();
+}
+
viz::SurfaceId RenderWidgetHostViewChildFrame::GetCurrentSurfaceId() const {
return viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_);
}
@@ -741,14 +769,17 @@ bool RenderWidgetHostViewChildFrame::HasSize() const {
gfx::PointF RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpaceF(
const gfx::PointF& point) {
- if (!frame_connector_ || !last_received_local_surface_id_.is_valid())
+ // LocalSurfaceId is not needed in Viz hit-test.
+ if (!frame_connector_ ||
+ (!use_viz_hit_test_ && !last_received_local_surface_id_.is_valid())) {
return point;
+ }
return frame_connector_->TransformPointToRootCoordSpace(
point, viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_));
}
-bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpace(
+bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
@@ -756,7 +787,7 @@ bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpace(
if (!frame_connector_ || !last_received_local_surface_id_.is_valid())
return false;
- return frame_connector_->TransformPointToLocalCoordSpace(
+ return frame_connector_->TransformPointToLocalCoordSpaceLegacy(
point, original_surface,
viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
transformed_point);
@@ -765,9 +796,13 @@ bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpace(
bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) {
- if (!frame_connector_ || !last_received_local_surface_id_.is_valid())
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
+ // LocalSurfaceId is not needed in Viz hit-test.
+ if (!frame_connector_ ||
+ (!use_viz_hit_test_ && !last_received_local_surface_id_.is_valid())) {
return false;
+ }
if (target_view == this) {
*transformed_point = point;
@@ -777,7 +812,7 @@ bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
return frame_connector_->TransformPointToCoordSpaceForView(
point, target_view,
viz::SurfaceId(frame_sink_id_, last_received_local_surface_id_),
- transformed_point);
+ transformed_point, source);
}
gfx::PointF RenderWidgetHostViewChildFrame::TransformRootPointToViewCoordSpace(
@@ -815,6 +850,7 @@ void RenderWidgetHostViewChildFrame::WillSendScreenRects() {
UpdateViewportIntersection(frame_connector_->viewport_intersection_rect(),
frame_connector_->compositor_visible_rect());
SetIsInert();
+ UpdateInheritedEffectiveTouchAction();
UpdateRenderThrottlingStatus();
}
}
@@ -894,7 +930,7 @@ void RenderWidgetHostViewChildFrame::ReclaimResources(
void RenderWidgetHostViewChildFrame::OnBeginFrame(
const viz::BeginFrameArgs& args) {
- host_->ProgressFling(args.frame_time);
+ host_->ProgressFlingIfNeeded(args.frame_time);
if (renderer_compositor_frame_sink_)
renderer_compositor_frame_sink_->OnBeginFrame(args);
}
@@ -951,6 +987,19 @@ void RenderWidgetHostViewChildFrame::TakeFallbackContentFrom(
InputEventAckState RenderWidgetHostViewChildFrame::FilterInputEvent(
const blink::WebInputEvent& input_event) {
+ // A child renderer should not receive touchscreen pinch events. Ideally, we
+ // would DCHECK this, but since touchscreen pinch events may be targeted to
+ // a child in order to have the child's TouchActionFilter filter them, we
+ // may encounter https://crbug.com/771330 which would let the pinch events
+ // through.
+ if (blink::WebInputEvent::IsPinchGestureEventType(input_event.GetType())) {
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(input_event);
+ if (gesture_event.SourceDevice() == blink::kWebGestureDeviceTouchscreen) {
+ return INPUT_EVENT_ACK_STATE_CONSUMED;
+ }
+ }
+
if (input_event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
const blink::WebGestureEvent& gesture_event =
static_cast<const blink::WebGestureEvent&>(input_event);
@@ -1046,16 +1095,12 @@ void RenderWidgetHostViewChildFrame::DisableAutoResize(
}
viz::ScopedSurfaceIdAllocator
-RenderWidgetHostViewChildFrame::ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
- // TODO(cblume): This doesn't currently suppress allocation.
- // It maintains existing behavior while using the suppression style.
- // This will be addressed in a follow-up patch.
- // See https://crbug.com/805073
+RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
base::OnceCallback<void()> allocation_task = base::BindOnce(
- &RenderWidgetHostViewChildFrame::OnResizeDueToAutoResizeComplete,
- weak_factory_.GetWeakPtr(), new_size, sequence_number);
+ base::IgnoreResult(
+ &RenderWidgetHostViewChildFrame::OnDidUpdateVisualPropertiesComplete),
+ weak_factory_.GetWeakPtr(), metadata);
return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
}
@@ -1138,19 +1183,15 @@ bool RenderWidgetHostViewChildFrame::CanBecomeVisible() {
->CanBecomeVisible();
}
-void RenderWidgetHostViewChildFrame::OnResizeDueToAutoResizeComplete(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
+void RenderWidgetHostViewChildFrame::OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata) {
if (frame_connector_)
- frame_connector_->ResizeDueToAutoResize(new_size, sequence_number);
+ frame_connector_->DidUpdateVisualProperties(metadata);
+ host()->SynchronizeVisualProperties();
}
void RenderWidgetHostViewChildFrame::DidNavigate() {
- host()->WasResized();
- if (host()->auto_resize_enabled()) {
- host()->DidAllocateLocalSurfaceIdForAutoResize(
- host()->last_auto_resize_request_number());
- }
+ host()->SynchronizeVisualProperties();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h
index a004195a306..07982e165bf 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -15,6 +15,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "build/build_config.h"
+#include "cc/input/touch_action.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/surfaces/surface_info.h"
@@ -96,6 +97,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
const gfx::Rect& src_rect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) override;
+ void EnsureSurfaceSynchronizedForLayoutTest() override;
+ uint32_t GetCaptureSequenceNumber() const override;
void Show() override;
void Hide() override;
bool IsShowing() override;
@@ -104,8 +107,6 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void SetInsets(const gfx::Insets& insets) override;
gfx::NativeView GetNativeView() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
- void SetBackgroundColor(SkColor color) override;
- SkColor background_color() const override;
gfx::Size GetCompositorViewportPixelSize() const override;
bool IsMouseLocked() override;
void SetNeedsBeginFrames(bool needs_begin_frames) override;
@@ -130,12 +131,12 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) override;
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
// Since the URL of content rendered by this class is not displayed in
// the URL bar, this method does not need an implementation.
void ClearCompositorFrame() override {}
- gfx::Vector2d GetOffsetFromRootSurface() override;
+ void TransformPointToRootSurface(gfx::PointF* point) override;
gfx::Rect GetBoundsInRootWindow() override;
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
@@ -145,17 +146,20 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
viz::FrameSinkId GetFrameSinkId() override;
viz::LocalSurfaceId GetLocalSurfaceId() const override;
void PreProcessTouchEvent(const blink::WebTouchEvent& event) override;
+ viz::FrameSinkId GetRootFrameSinkId() override;
viz::SurfaceId GetCurrentSurfaceId() const override;
bool HasSize() const override;
gfx::PointF TransformPointToRootCoordSpaceF(
const gfx::PointF& point) override;
- bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
- const viz::SurfaceId& original_surface,
- gfx::PointF* transformed_point) override;
+ bool TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point) override;
bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) override;
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY) override;
void DidNavigate() override;
gfx::PointF TransformRootPointToViewCoordSpace(
const gfx::PointF& point) override;
@@ -185,9 +189,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void EnableAutoResize(const gfx::Size& min_size,
const gfx::Size& max_size) override;
void DisableAutoResize(const gfx::Size& new_size) override;
- viz::ScopedSurfaceIdAllocator ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) override;
+ viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) override;
// viz::mojom::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck(
@@ -216,7 +219,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// Returns the view into which this view is directly embedded. This can
// return nullptr when this view's associated child frame is not connected
// to the frame tree.
- RenderWidgetHostViewBase* GetParentView();
+ virtual RenderWidgetHostViewBase* GetParentView();
void RegisterFrameSinkId();
void UnregisterFrameSinkId();
@@ -224,7 +227,9 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void UpdateViewportIntersection(const gfx::Rect& viewport_intersection,
const gfx::Rect& compositor_visible_rect);
+ // TODO(sunxd): Rename SetIsInert to UpdateIsInert.
void SetIsInert();
+ void UpdateInheritedEffectiveTouchAction();
void UpdateRenderThrottlingStatus();
@@ -256,6 +261,9 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void ProcessFrameSwappedCallbacks();
+ // RenderWidgetHostViewBase:
+ void UpdateBackgroundColor() override;
+
// The ID for FrameSink associated with this view.
viz::FrameSinkId frame_sink_id_;
@@ -295,8 +303,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// using CSS.
bool CanBecomeVisible();
- void OnResizeDueToAutoResizeComplete(const gfx::Size& new_size,
- uint64_t sequence_number);
+ void OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata);
std::vector<base::OnceClosure> frame_swapped_callbacks_;
@@ -308,9 +316,6 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ =
nullptr;
- // The background color of the widget.
- SkColor background_color_;
-
gfx::Insets insets_;
std::unique_ptr<TouchSelectionControllerClientChildFrame>
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
index a568705e47a..e6ee8ec9bc1 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -134,20 +134,13 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest,
root->child_at(0)->current_frame_host()->GetRenderWidgetHost()->GetView();
// Fake an auto-resize update from the parent renderer.
- int routing_id =
- root->current_frame_host()->GetRenderWidgetHost()->GetRoutingID();
- ViewHostMsg_ResizeOrRepaint_ACK_Params params;
- params.view_size = gfx::Size(75, 75);
- params.flags = 0;
- root->current_frame_host()->GetRenderWidgetHost()->OnMessageReceived(
- ViewHostMsg_ResizeOrRepaint_ACK(routing_id, params));
-
- // RenderWidgetHostImpl has delayed auto-resize processing. Yield here to
- // let it complete.
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- run_loop.QuitClosure());
- run_loop.Run();
+ viz::LocalSurfaceId local_surface_id(10, 10,
+ base::UnguessableToken::Create());
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(75, 75);
+ metadata.local_surface_id = local_surface_id;
+ root->current_frame_host()->GetRenderWidgetHost()->DidUpdateVisualProperties(
+ metadata);
// The child frame's RenderWidgetHostView should now use the auto-resize value
// for its visible viewport.
@@ -168,8 +161,8 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) {
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
- scoped_refptr<UpdateResizeParamsMessageFilter> message_filter(
- new UpdateResizeParamsMessageFilter());
+ scoped_refptr<SynchronizeVisualPropertiesMessageFilter> message_filter(
+ new SynchronizeVisualPropertiesMessageFilter());
root->current_frame_host()->GetProcess()->AddFilter(message_filter.get());
// Load cross-site page into iframe.
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 7a55f9227b7..c190e59907d 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -15,6 +15,7 @@
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -27,7 +28,7 @@
#include "content/browser/renderer_host/frame_connector_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_features.h"
@@ -199,9 +200,12 @@ TEST_F(RenderWidgetHostViewChildFrameTest, VisibilityTest) {
// Verify that SubmitCompositorFrame behavior is correct when a delegated
// frame is received from a renderer process.
TEST_F(RenderWidgetHostViewChildFrameTest, SwapCompositorFrame) {
- // TODO: fix for mash.
- if (base::FeatureList::IsEnabled(features::kMash))
+ // TODO(jonross): Delete this test once Viz launches as it will be obsolete.
+ // https://crbug.com/844469
+ if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+ base::FeatureList::IsEnabled(features::kMash)) {
return;
+ }
gfx::Size view_size(100, 100);
gfx::Rect view_rect(view_size);
@@ -213,7 +217,7 @@ TEST_F(RenderWidgetHostViewChildFrameTest, SwapCompositorFrame) {
view_->SubmitCompositorFrame(
local_surface_id,
- CreateDelegatedFrame(scale_factor, view_size, view_rect), nullptr);
+ CreateDelegatedFrame(scale_factor, view_size, view_rect), base::nullopt);
viz::SurfaceId id = GetSurfaceId();
if (id.is_valid()) {
@@ -351,23 +355,25 @@ TEST_F(RenderWidgetHostViewChildFrameTest, WasResizedOncePerChange) {
process->sink().ClearMessages();
- FrameResizeParams resize_params;
- resize_params.screen_space_rect = screen_space_rect;
- resize_params.local_frame_size = compositor_viewport_pixel_size;
- resize_params.auto_resize_sequence_number = 1u;
- test_frame_connector_->UpdateResizeParams(surface_id, resize_params);
+ FrameVisualProperties visual_properties;
+ visual_properties.screen_space_rect = screen_space_rect;
+ visual_properties.local_frame_size = compositor_viewport_pixel_size;
+ visual_properties.capture_sequence_number = 123u;
+ test_frame_connector_->SynchronizeVisualProperties(surface_id,
+ visual_properties);
ASSERT_EQ(1u, process->sink().message_count());
- const IPC::Message* resize_msg =
- process->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID);
+ const IPC::Message* resize_msg = process->sink().GetUniqueMessageMatching(
+ ViewMsg_SynchronizeVisualProperties::ID);
ASSERT_NE(nullptr, resize_msg);
- ViewMsg_Resize::Param params;
- ViewMsg_Resize::Read(resize_msg, &params);
+ ViewMsg_SynchronizeVisualProperties::Param params;
+ ViewMsg_SynchronizeVisualProperties::Read(resize_msg, &params);
EXPECT_EQ(compositor_viewport_pixel_size,
std::get<0>(params).compositor_viewport_pixel_size);
EXPECT_EQ(screen_space_rect.size(), std::get<0>(params).new_size);
EXPECT_EQ(local_surface_id, std::get<0>(params).local_surface_id);
+ EXPECT_EQ(123u, std::get<0>(params).capture_sequence_number);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
index acdb2fd0ae6..0fd6933ba64 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.h
@@ -10,12 +10,15 @@
#include <set>
#include <vector>
+#include "base/containers/flat_set.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/optional.h"
#include "content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h"
#include "content/common/edit_command.h"
#import "ui/base/cocoa/command_dispatcher.h"
#import "ui/base/cocoa/tool_tip_base_view.h"
#include "ui/base/ime/ime_text_span.h"
+#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/range/range.h"
namespace blink {
@@ -29,6 +32,7 @@ class RenderWidgetHostViewMacEditCommandHelper;
}
namespace ui {
+enum class DomCode;
struct DidOverscrollParams;
}
@@ -111,6 +115,8 @@ struct DidOverscrollParams;
// the whole content yet.
NSRange markedRange_;
+ ui::TextInputType textInputType_;
+
// The text selection, cached from the RenderWidgetHostView. This is only ever
// updated from the renderer.
base::string16 textSelectionText_;
@@ -169,6 +175,7 @@ struct DidOverscrollParams;
}
@property(nonatomic, assign) NSRange markedRange;
+@property(nonatomic, assign) ui::TextInputType textInputType;
// Common code path for handling begin gesture events. This helper method is
// called via different codepaths based on OS version and SDK:
@@ -176,7 +183,8 @@ struct DidOverscrollParams;
// |magnifyWithEvent:| when the given event's phase is NSEventPhaseBegin.
// - On 10.10 and earlier, or when linking with an earlier SDK, it is called
// by |beginGestureWithEvent:| when a gesture begins.
-- (void)handleBeginGestureWithEvent:(NSEvent*)event;
+- (void)handleBeginGestureWithEvent:(NSEvent*)event
+ isSyntheticallyInjected:(BOOL)isSyntheticallyInjected;
// Common code path for handling end gesture events. This helper method is
// called via different codepaths based on OS version and SDK:
@@ -213,6 +221,11 @@ struct DidOverscrollParams;
- (base::string16)selectedText;
// Set the current TextInputManager::CompositionRangeInfo from the renderer.
- (void)setCompositionRange:(gfx::Range)range;
+
+// KeyboardLock methods.
+- (void)lockKeyboard:(base::Optional<base::flat_set<ui::DomCode>>)keysToLock;
+- (void)unlockKeyboard;
+
// Methods previously marked as private.
- (id)initWithClient:(content::RenderWidgetHostNSViewClient*)client;
- (void)setResponderDelegate:
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
index 8ee84cdafbd..d86576cc36a 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -8,8 +8,8 @@
#include <utility>
#include "base/debug/crash_logging.h"
-#include "base/mac/bind_objc_block.h"
#include "base/mac/mac_util.h"
+#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#import "content/browser/accessibility/browser_accessibility_mac.h"
@@ -25,6 +25,8 @@
#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/mac/coordinate_conversion.h"
using content::BrowserAccessibility;
@@ -80,7 +82,8 @@ class NoopClient : public RenderWidgetHostNSViewClient {
const blink::WebMouseEvent& web_event) override {}
void OnNSViewForwardWheelEvent(
const blink::WebMouseWheelEvent& web_event) override {}
- void OnNSViewGestureBegin(blink::WebGestureEvent begin_event) override {}
+ void OnNSViewGestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) override {}
void OnNSViewGestureUpdate(blink::WebGestureEvent update_event) override {}
void OnNSViewGestureEnd(blink::WebGestureEvent end_event) override {}
void OnNSViewSmartMagnify(
@@ -99,8 +102,6 @@ class NoopClient : public RenderWidgetHostNSViewClient {
const gfx::PointF& root_point) override {}
void OnNSViewLookUpDictionaryOverlayFromRange(
const gfx::Range& range) override {}
- void OnNSViewSyncGetTextInputType(
- ui::TextInputType* text_input_type) override {}
void OnNSViewSyncGetCharacterIndexAtPoint(const gfx::PointF& root_point,
uint32_t* index) override {}
void OnNSViewSyncGetFirstRectForRange(const gfx::Range& requested_range,
@@ -132,7 +133,7 @@ BOOL EventIsReservedBySystem(NSEvent* event) {
}
// TODO(suzhe): Upstream this function.
-blink::WebColor WebColorFromNSColor(NSColor* color) {
+SkColor SkColorFromNSColor(NSColor* color) {
CGFloat r, g, b, a;
[color getRed:&r green:&g blue:&b alpha:&a];
@@ -157,10 +158,10 @@ void ExtractUnderlines(NSAttributedString* string,
longestEffectiveRange:&range
inRange:NSMakeRange(i, length - i)];
if (NSNumber* style = [attrs objectForKey:NSUnderlineStyleAttributeName]) {
- blink::WebColor color = SK_ColorBLACK;
+ SkColor color = SK_ColorBLACK;
if (NSColor* colorAttr =
[attrs objectForKey:NSUnderlineColorAttributeName]) {
- color = WebColorFromNSColor(
+ color = SkColorFromNSColor(
[colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
}
ui::ImeTextSpan::Thickness thickness =
@@ -188,7 +189,10 @@ void ExtractUnderlines(NSAttributedString* string,
// RenderWidgetHostViewCocoa ---------------------------------------------------
// Private methods:
-@interface RenderWidgetHostViewCocoa ()
+@interface RenderWidgetHostViewCocoa () {
+ bool keyboardLockActive_;
+ base::Optional<base::flat_set<ui::DomCode>> lockedKeys_;
+}
- (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event
consumed:(BOOL)consumed;
- (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv;
@@ -199,10 +203,12 @@ void ExtractUnderlines(NSAttributedString* string,
- (void)sendViewBoundsInWindowToClient;
- (void)sendWindowFrameInScreenToClient;
- (bool)clientIsDisconnected;
+- (bool)isKeyLocked:(int)keyCode;
@end
@implementation RenderWidgetHostViewCocoa
@synthesize markedRange = markedRange_;
+@synthesize textInputType = textInputType_;
- (id)initWithClient:(RenderWidgetHostNSViewClient*)client {
self = [super initWithFrame:NSZeroRect];
@@ -215,6 +221,8 @@ void ExtractUnderlines(NSAttributedString* string,
client_ = client;
canBeKeyView_ = YES;
isStylusEnteringProximity_ = false;
+ keyboardLockActive_ = false;
+ textInputType_ = ui::TEXT_INPUT_TYPE_NONE;
}
return self;
}
@@ -477,6 +485,11 @@ void ExtractUnderlines(NSAttributedString* string,
}
}
+ // Because |updateCursor:| changes the current cursor, we have to reset it to
+ // the default cursor on mouse exit.
+ if (type == NSMouseExited)
+ [[NSCursor arrowCursor] set];
+
if ([self shouldIgnoreMouseEvent:theEvent]) {
// If this is the first such event, send a mouse exit to the host view.
if (!mouseEventWasIgnored_) {
@@ -541,6 +554,25 @@ void ExtractUnderlines(NSAttributedString* string,
}
}
+- (void)lockKeyboard:(base::Optional<base::flat_set<ui::DomCode>>)keysToLock {
+ // TODO(joedow): Integrate System-level keyboard hook into this method.
+ lockedKeys_ = std::move(keysToLock);
+ keyboardLockActive_ = true;
+}
+
+- (void)unlockKeyboard {
+ keyboardLockActive_ = false;
+ lockedKeys_.reset();
+}
+
+- (bool)isKeyLocked:(int)keyCode {
+ // Note: We do not want to treat the ESC key as locked as that key is used
+ // to exit fullscreen and we don't want to prevent them from exiting.
+ ui::DomCode domCode = ui::KeycodeConverter::NativeKeycodeToDomCode(keyCode);
+ return keyboardLockActive_ && domCode != ui::DomCode::ESCAPE &&
+ (!lockedKeys_ || base::ContainsKey(lockedKeys_.value(), domCode));
+}
+
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent {
// |performKeyEquivalent:| is sent to all views of a window, not only down the
// responder chain (cf. "Handling Key Equivalents" in
@@ -641,7 +673,12 @@ void ExtractUnderlines(NSAttributedString* string,
latency_info.set_source_event_type(ui::SourceEventType::KEY_PRESS);
}
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
+
+ // If KeyboardLock has been requested for this keyCode, then mark the event
+ // so it skips the pre-handler and is delivered straight to the website.
+ if ([self isKeyLocked:keyCode])
+ event.skip_in_browser = true;
// Do not forward key up events unless preceded by a matching key down,
// otherwise we might get an event from releasing the return key in the
@@ -658,9 +695,7 @@ void ExtractUnderlines(NSAttributedString* string,
// function call.
client_->OnNSViewBeginKeyboardEvent();
- ui::TextInputType textInputType = ui::TEXT_INPUT_TYPE_NONE;
- client_->OnNSViewSyncGetTextInputType(&textInputType);
- bool shouldAutohideCursor = textInputType != ui::TEXT_INPUT_TYPE_NONE &&
+ bool shouldAutohideCursor = textInputType_ != ui::TEXT_INPUT_TYPE_NONE &&
eventType == NSKeyDown &&
!(modifierFlags & NSCommandKeyMask);
@@ -859,12 +894,13 @@ void ExtractUnderlines(NSAttributedString* string,
}
}
-- (void)handleBeginGestureWithEvent:(NSEvent*)event {
+- (void)handleBeginGestureWithEvent:(NSEvent*)event
+ isSyntheticallyInjected:(BOOL)isSyntheticallyInjected {
[responderDelegate_ beginGestureWithEvent:event];
WebGestureEvent gestureBeginEvent(WebGestureEventBuilder::Build(event, self));
- client_->OnNSViewGestureBegin(gestureBeginEvent);
+ client_->OnNSViewGestureBegin(gestureBeginEvent, isSyntheticallyInjected);
}
- (void)handleEndGestureWithEvent:(NSEvent*)event {
@@ -895,7 +931,7 @@ void ExtractUnderlines(NSAttributedString* string,
#endif
if (shouldHandle) {
- [self handleBeginGestureWithEvent:event];
+ [self handleBeginGestureWithEvent:event isSyntheticallyInjected:NO];
}
}
@@ -979,7 +1015,7 @@ void ExtractUnderlines(NSAttributedString* string,
// "end" phases.
if (base::mac::IsAtLeastOS10_11()) {
if (event.phase == NSEventPhaseBegan) {
- [self handleBeginGestureWithEvent:event];
+ [self handleBeginGestureWithEvent:event isSyntheticallyInjected:NO];
}
if (event.phase == NSEventPhaseEnded ||
@@ -1028,7 +1064,7 @@ void ExtractUnderlines(NSAttributedString* string,
// "end" phases.
if (base::mac::IsAtLeastOS10_11()) {
if (event.phase == NSEventPhaseBegan) {
- [self handleBeginGestureWithEvent:event];
+ [self handleBeginGestureWithEvent:event isSyntheticallyInjected:NO];
return;
}
@@ -1560,9 +1596,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
// nil when the caret is in non-editable content or password box to avoid
// making input methods do their work.
- (NSTextInputContext*)inputContext {
- ui::TextInputType textInputType = ui::TEXT_INPUT_TYPE_NONE;
- client_->OnNSViewSyncGetTextInputType(&textInputType);
- switch (textInputType) {
+ switch (textInputType_) {
case ui::TEXT_INPUT_TYPE_NONE:
case ui::TEXT_INPUT_TYPE_PASSWORD:
return nil;
@@ -1717,7 +1751,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
// open mouse-downs.
if (hasOpenMouseDown_) {
WebMouseEvent event(WebInputEvent::kMouseUp, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ ui::EventTimeForNow());
event.button = WebMouseEvent::Button::kLeft;
client_->OnNSViewForwardMouseEvent(event);
hasOpenMouseDown_ = NO;
@@ -1795,14 +1829,11 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
- (id)validRequestorForSendType:(NSString*)sendType
returnType:(NSString*)returnType {
- ui::TextInputType textInputType = ui::TEXT_INPUT_TYPE_NONE;
- client_->OnNSViewSyncGetTextInputType(&textInputType);
-
id requestor = nil;
BOOL sendTypeIsString = [sendType isEqual:NSStringPboardType];
BOOL returnTypeIsString = [returnType isEqual:NSStringPboardType];
BOOL hasText = !textSelectionRange_.is_empty();
- BOOL takesText = textInputType != ui::TEXT_INPUT_TYPE_NONE;
+ BOOL takesText = textInputType_ != ui::TEXT_INPUT_TYPE_NONE;
if (sendTypeIsString && hasText && !returnType) {
requestor = self;
@@ -1817,6 +1848,23 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
return requestor;
}
+- (BOOL)shouldChangeCurrentCursor {
+ // |updateCursor:| might be called outside the view bounds. Check the mouse
+ // location before setting the cursor. Also, do not set cursor if it's not a
+ // key window.
+ NSPoint location = ui::ConvertPointFromScreenToWindow(
+ [self window], [NSEvent mouseLocation]);
+ location = [self convertPoint:location fromView:nil];
+ if (![self mouse:location inRect:[self bounds]] ||
+ ![[self window] isKeyWindow])
+ return NO;
+
+ if (cursorHidden_ || showingContextMenu_)
+ return NO;
+
+ return YES;
+}
+
- (void)updateCursor:(NSCursor*)cursor {
if (currentCursor_ == cursor)
return;
@@ -1826,8 +1874,8 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
// NSWindow's invalidateCursorRectsForView: resets cursor rects but does not
// update the cursor instantly. The cursor is updated when the mouse moves.
- // Update the cursor by setting the current cursor if not hidden.
- if (!cursorHidden_ && !showingContextMenu_)
+ // Update the cursor instantly by setting the current cursor.
+ if ([self shouldChangeCurrentCursor])
[currentCursor_ set];
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc
index 69c041eed92..af9912a5f02 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.cc
@@ -27,7 +27,7 @@
#include "ui/base/ime/text_input_client.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/web_input_event.h"
-#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/touch_selection/touch_selection_controller.h"
#if defined(OS_WIN)
@@ -234,14 +234,14 @@ void RenderWidgetHostViewEventHandler::UnlockMouse() {
}
bool RenderWidgetHostViewEventHandler::LockKeyboard(
- base::Optional<base::flat_set<int>> keys) {
+ base::Optional<base::flat_set<ui::DomCode>> codes) {
aura::Window* root_window = window_->GetRootWindow();
if (!root_window)
return false;
// Remove existing hook, if registered.
UnlockKeyboard();
- scoped_keyboard_hook_ = root_window->CaptureSystemKeyEvents(std::move(keys));
+ scoped_keyboard_hook_ = root_window->CaptureSystemKeyEvents(std::move(codes));
return IsKeyboardLocked();
}
@@ -442,9 +442,10 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) {
gesture_event.SetPositionInWidget(event->location_f());
blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent(
*event, base::Bind(&GetScreenLocationFromEvent));
- if (host_view_->wheel_scroll_latching_enabled())
+ if (host_view_->wheel_scroll_latching_enabled()) {
mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
mouse_wheel_event, should_route_event);
+ }
if (should_route_event) {
host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
host_view_, &gesture_event,
@@ -568,7 +569,6 @@ void RenderWidgetHostViewEventHandler::OnGestureEvent(ui::GestureEvent* event) {
if (gesture.GetType() != blink::WebInputEvent::kUndefined) {
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
- RecordAction(base::UserMetricsAction("TouchscreenScroll"));
// If there is a current scroll going on and a new scroll that isn't
// wheel based send a synthetic wheel event with kPhaseEnded to cancel
// the current scroll.
@@ -953,11 +953,10 @@ bool RenderWidgetHostViewEventHandler::IsKeyLocked(const ui::KeyEvent& event) {
// Note: We never consider 'ESC' to be locked as we don't want to prevent it
// from being handled by the browser. Doing so would have adverse effects
// such as the user being unable to exit fullscreen mode.
- if (!IsKeyboardLocked() || event.key_code() == ui::VKEY_ESCAPE)
+ if (!IsKeyboardLocked() || event.code() == ui::DomCode::ESCAPE)
return false;
- int key_code = ui::KeycodeConverter::DomCodeToNativeKeycode(event.code());
- return scoped_keyboard_hook_->IsKeyLocked(key_code);
+ return scoped_keyboard_hook_->IsKeyLocked(event.code());
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
index 410e6e2f209..2e4f30a6017 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_event_handler.h
@@ -30,6 +30,7 @@ class WebTouchEvent;
} // namespace blink
namespace ui {
+enum class DomCode;
class TextInputClient;
class TouchSelectionController;
}
@@ -144,7 +145,7 @@ class CONTENT_EXPORT RenderWidgetHostViewEventHandler
void UnlockMouse();
// Start/Stop processing of future system keyboard events.
- bool LockKeyboard(base::Optional<base::flat_set<int>> keys);
+ bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes);
void UnlockKeyboard();
bool IsKeyboardLocked() const;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.h b/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
index d4b8dadb129..7a4fdcecf33 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -25,6 +25,7 @@
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/display_link_mac.h"
#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/events/gesture_detection/filtered_gesture_provider.h"
namespace content {
class CursorManager;
@@ -36,6 +37,7 @@ class WebCursor;
}
namespace ui {
+enum class DomCode;
class ScopedPasswordInputEnabler;
}
@@ -66,6 +68,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
public RenderWidgetHostNSViewClient,
public BrowserCompositorMacClient,
public TextInputManager::Observer,
+ public ui::GestureProviderClient,
public ui::AcceleratedWidgetMacNSView,
public IPC::Sender {
public:
@@ -104,8 +107,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void SetActive(bool active) override;
void ShowDefinitionForSelection() override;
void SpeakSelection() override;
- void SetBackgroundColor(SkColor color) override;
- SkColor background_color() const override;
void SetNeedsBeginFrames(bool needs_begin_frames) override;
void GetScreenInfo(ScreenInfo* screen_info) const override;
void SetWantsAnimateOnlyBeginFrames() override;
@@ -119,6 +120,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void UpdateCursor(const WebCursor& cursor) override;
void DisplayCursor(const WebCursor& cursor) override;
CursorManager* GetCursorManager() override;
+ void OnDidNavigateMainFrameToNewPage() override;
void SetIsLoading(bool is_loading) override;
void RenderProcessGone(base::TerminationStatus status,
int error_code) override;
@@ -126,11 +128,13 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void SetTooltipText(const base::string16& tooltip_text) override;
void DisplayTooltipText(const base::string16& tooltip_text) override;
gfx::Size GetRequestedRendererSize() const override;
+ uint32_t GetCaptureSequenceNumber() const override;
bool IsSurfaceAvailableForCopy() const override;
void CopyFromSurface(
const gfx::Rect& src_rect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) override;
+ void EnsureSurfaceSynchronizedForLayoutTest() override;
void FocusedNodeChanged(bool is_editable_node,
const gfx::Rect& node_bounds_in_screen) override;
void DidCreateNewRendererCompositorFrameSink(
@@ -139,26 +143,33 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) override;
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) override;
void OnDidNotProduceFrame(const viz::BeginFrameAck& ack) override;
void ClearCompositorFrame() override;
+ bool RequestRepaintForTesting() override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds) override;
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
+ base::Optional<SkColor> GetBackgroundColor() const override;
bool ShouldContinueToPauseForFrame() override;
- gfx::Vector2d GetOffsetFromRootSurface() override;
+ void SetParentUiLayer(ui::Layer* parent_ui_layer) override;
+ void TransformPointToRootSurface(gfx::PointF* point) override;
gfx::Rect GetBoundsInRootWindow() override;
- viz::ScopedSurfaceIdAllocator ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) override;
+ viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) override;
void DidNavigate() override;
bool LockMouse() override;
void UnlockMouse() override;
+ bool LockKeyboard(base::Optional<base::flat_set<ui::DomCode>> codes) override;
+ void UnlockKeyboard() override;
+ bool IsKeyboardLocked() override;
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
+ void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) override;
void DidOverscroll(const ui::DidOverscrollParams& params) override;
@@ -177,13 +188,20 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// consumer, such as PDF or maps, wants to intercept them and implement a
// custom behavior.
void SendGesturePinchEvent(blink::WebGestureEvent* event);
- bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
- const viz::SurfaceId& original_surface,
- gfx::PointF* transformed_point) override;
+
+ // Inject synthetic touch events.
+ void InjectTouchEvent(const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency_info) override;
+
+ bool TransformPointToLocalCoordSpaceLegacy(
+ const gfx::PointF& point,
+ const viz::SurfaceId& original_surface,
+ gfx::PointF* transformed_point) override;
bool TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) override;
+ gfx::PointF* transformed_point,
+ viz::EventSource source = viz::EventSource::ANY) override;
viz::FrameSinkId GetRootFrameSinkId() override;
viz::SurfaceId GetCurrentSurfaceId() const override;
@@ -202,15 +220,15 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void OnTextSelectionChanged(TextInputManager* text_input_manager,
RenderWidgetHostViewBase* updated_view) override;
+ // ui::GestureProviderClient implementation.
+ void OnGestureEvent(const ui::GestureEventData& gesture) override;
+
// RenderFrameMetadataProvider::Observer
void OnRenderFrameMetadataChanged() override;
// IPC::Sender implementation.
bool Send(IPC::Message* message) override;
- // Forwards the mouse event to the renderer.
- void ForwardMouseEvent(const blink::WebMouseEvent& event);
-
void SetTextInputActive(bool active);
// Returns true and stores first rectangle for character range if the
@@ -254,7 +272,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Delegated frame management and compositor interface.
std::unique_ptr<BrowserCompositorMac> browser_compositor_;
- BrowserCompositorMac* BrowserCompositorForTesting() const {
+ BrowserCompositorMac* BrowserCompositor() const {
return browser_compositor_.get();
}
@@ -304,7 +322,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
const blink::WebMouseEvent& web_event) override;
void OnNSViewForwardWheelEvent(
const blink::WebMouseWheelEvent& web_event) override;
- void OnNSViewGestureBegin(blink::WebGestureEvent begin_event) override;
+ void OnNSViewGestureBegin(blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) override;
void OnNSViewGestureUpdate(blink::WebGestureEvent update_event) override;
void OnNSViewGestureEnd(blink::WebGestureEvent end_event) override;
void OnNSViewSmartMagnify(
@@ -323,8 +342,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
const gfx::PointF& root_point) override;
void OnNSViewLookUpDictionaryOverlayFromRange(
const gfx::Range& range) override;
- void OnNSViewSyncGetTextInputType(
- ui::TextInputType* text_input_type) override;
void OnNSViewSyncGetCharacterIndexAtPoint(const gfx::PointF& root_point,
uint32_t* index) override;
void OnNSViewSyncGetFirstRectForRange(const gfx::Range& requested_range,
@@ -350,13 +367,11 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void OnFrameTokenChanged(uint32_t frame_token) override;
void DidReceiveFirstFrameAfterNavigation() override;
void DestroyCompositorForShutdown() override;
- void WasResized() override;
+ bool SynchronizeVisualProperties() override;
// AcceleratedWidgetMacNSView implementation.
NSView* AcceleratedWidgetGetNSView() const override;
- void AcceleratedWidgetGetVSyncParameters(
- base::TimeTicks* timebase, base::TimeDelta* interval) const override;
- void AcceleratedWidgetSwapCompleted() override;
+ void AcceleratedWidgetCALayerParamsUpdated() override;
void SetShowingContextMenu(bool showing) override;
@@ -417,6 +432,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// collide with FrameSinkIds used by RenderWidgetHostImpls.
static viz::FrameSinkId AllocateFrameSinkIdForGuestViewHack();
+ MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
+
// Shuts down the render_widget_host_. This is a separate function so we can
// invoke it from the message loop.
void ShutdownHost();
@@ -431,8 +448,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
blink::WebMouseWheelEvent wheel_event,
bool should_route_event);
- void OnResizeDueToAutoResizeComplete(const gfx::Size& new_size,
- uint64_t sequence_number);
+ void OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata);
void OnGotStringForDictionaryOverlay(
int32_t targetWidgetProcessId,
@@ -440,6 +457,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
const mac::AttributedStringCoder::EncodedString& encodedString,
gfx::Point baselinePoint);
+ // RenderWidgetHostViewBase:
+ void UpdateBackgroundColor() override;
+
// Gets a textual view of the page's contents, and passes it to the callback
// provided.
using SpeechCallback = base::OnceCallback<void(const base::string16&)>;
@@ -451,6 +471,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// State tracked by Show/Hide/IsShowing.
bool is_visible_ = false;
+ // Set to true if |this| has ever been displayed via a parent ui::Layer (in
+ // which case its NSView will only ever be used for input, not display).
+ bool display_only_using_parent_ui_layer_ = false;
+
// The bounds of the view in its NSWindow's coordinate system (with origin
// in the upper-left).
gfx::Rect view_bounds_in_window_dip_;
@@ -497,7 +521,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// The background color of the last frame that was swapped. This is not
// applied until the swap completes (see comments in
- // AcceleratedWidgetSwapCompleted).
+ // AcceleratedWidgetCALayerParamsUpdated).
SkColor last_frame_root_background_color_ = SK_ColorTRANSPARENT;
int tab_show_sequence_ = 0;
@@ -507,6 +531,10 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Used to track active password input sessions.
std::unique_ptr<ui::ScopedPasswordInputEnabler> password_input_enabler_;
+ // Provides gesture synthesis given a stream of touch events and touch event
+ // acks. This is for generating gesture events from injected touch events.
+ ui::FilteredGestureProvider gesture_provider_;
+
// Used to ensure that a consistent RenderWidgetHost is targeted throughout
// the duration of a keyboard event.
bool in_keyboard_event_ = false;
@@ -533,6 +561,14 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool pinch_has_reached_zoom_threshold_ = false;
float pinch_unused_amount_ = 1.f;
+ // Tracks whether keyboard lock is active.
+ bool is_keyboard_locked_ = false;
+
+ // Latest capture sequence number which is incremented when the caller
+ // requests surfaces be synchronized via
+ // EnsureSurfaceSynchronizedForLayoutTest().
+ uint32_t latest_capture_sequence_number_ = 0u;
+
// Factory used to safely scope delayed calls to ShutdownHost().
base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
index 6a161f0f36c..8b012bcb8f7 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -17,8 +17,10 @@
#include "base/macros.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/viz/common/switches.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
#include "content/browser/renderer_host/cursor_manager.h"
+#include "content/browser/renderer_host/input/motion_event_web.h"
#import "content/browser/renderer_host/input/synthetic_gesture_target_mac.h"
#include "content/browser/renderer_host/input/web_input_event_builders_mac.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -28,6 +30,7 @@
#import "content/browser/renderer_host/render_widget_host_ns_view_bridge.h"
#import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
#import "content/browser/renderer_host/text_input_client_mac.h"
+#import "content/browser/renderer_host/ui_events_helper.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
@@ -43,15 +46,18 @@
#include "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/base/cocoa/secure_password_input.h"
#include "ui/base/cocoa/text_services_context_menu.h"
+#include "ui/base/ui_base_features.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
+#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/mac/coordinate_conversion.h"
-#include "ui/gl/gl_switches.h"
using blink::WebInputEvent;
using blink::WebMouseEvent;
using blink::WebGestureEvent;
+using blink::WebTouchEvent;
namespace content {
@@ -72,7 +78,7 @@ void RenderWidgetHostViewMac::BrowserCompositorMacOnBeginFrame(
base::TimeTicks frame_time) {
// ProgressFling must get called for middle click autoscroll fling on Mac.
if (host())
- host()->ProgressFling(frame_time);
+ host()->ProgressFlingIfNeeded(frame_time);
UpdateNeedsBeginFramesInternal();
}
@@ -92,8 +98,8 @@ void RenderWidgetHostViewMac::DestroyCompositorForShutdown() {
Destroy();
}
-void RenderWidgetHostViewMac::WasResized() {
- host()->WasResized();
+bool RenderWidgetHostViewMac::SynchronizeVisualProperties() {
+ return host()->SynchronizeVisualProperties();
}
////////////////////////////////////////////////////////////////////////////////
@@ -103,22 +109,19 @@ NSView* RenderWidgetHostViewMac::AcceleratedWidgetGetNSView() const {
return cocoa_view();
}
-void RenderWidgetHostViewMac::AcceleratedWidgetGetVSyncParameters(
- base::TimeTicks* timebase, base::TimeDelta* interval) const {
- if (display_link_ &&
- display_link_->GetVSyncParameters(timebase, interval))
- return;
- *timebase = base::TimeTicks();
- *interval = base::TimeDelta();
-}
-
-void RenderWidgetHostViewMac::AcceleratedWidgetSwapCompleted() {
+void RenderWidgetHostViewMac::AcceleratedWidgetCALayerParamsUpdated() {
// Set the background color for the root layer from the frame that just
// swapped. See RenderWidgetHostViewAura for more details. Note that this is
// done only after the swap has completed, so that the background is not set
// before the frame is up.
SetBackgroundLayerColor(last_frame_root_background_color_);
+ // Update the contents that the NSView is displaying.
+ const gfx::CALayerParams* ca_layer_params =
+ browser_compositor_->GetLastCALayerParams();
+ if (ca_layer_params)
+ ns_view_bridge_->SetCALayerParams(*ca_layer_params);
+
if (display_link_)
display_link_->NotifyCurrentTime(base::TimeTicks::Now());
}
@@ -134,6 +137,9 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
is_loading_(false),
allow_pause_for_resize_or_repaint_(true),
is_guest_view_hack_(is_guest_view_hack),
+ gesture_provider_(ui::GetGestureProviderConfig(
+ ui::GestureProviderConfigType::CURRENT_PLATFORM),
+ this),
weak_factory_(this) {
// The NSView is on the other side of |ns_view_bridge_|.
ns_view_bridge_ = RenderWidgetHostNSViewBridge::Create(this);
@@ -192,6 +198,21 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
}
+void RenderWidgetHostViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
+ if (!display_only_using_parent_ui_layer_) {
+ // The first time that we display using a parent ui::Layer, permanently
+ // switch from drawing using Cocoa to only drawing using ui::Views. Erase
+ // the existing content being drawn by Cocoa (which may have been set due
+ // to races, e.g, in https://crbug.com/845807). Note that this transition
+ // must be done lazily because not all code has been updated to use
+ // ui::Views (e.g, content_shell).
+ display_only_using_parent_ui_layer_ = true;
+ ns_view_bridge_->DisableDisplay();
+ }
+ if (browser_compositor_)
+ browser_compositor_->SetParentUiLayer(parent_ui_layer);
+}
+
RenderWidgetHostViewCocoa* RenderWidgetHostViewMac::cocoa_view() const {
return ns_view_bridge_->GetRenderWidgetHostViewCocoa();
}
@@ -293,10 +314,10 @@ RenderWidgetHostImpl* RenderWidgetHostViewMac::GetWidgetForIme() {
}
void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() {
- static bool is_vsync_disabled =
+ static bool is_frame_rate_limit_disabled =
base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGpuVsync);
- if (!is_vsync_disabled) {
+ switches::kDisableFrameRateLimit);
+ if (!is_frame_rate_limit_disabled) {
display_link_ = ui::DisplayLinkMac::GetForDisplay(display_.id());
if (!display_link_.get()) {
// Note that on some headless systems, the display link will fail to be
@@ -336,7 +357,7 @@ void RenderWidgetHostViewMac::Show() {
ui::LatencyInfo renderer_latency_info;
renderer_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
- host()->GetLatencyComponentId(), 0);
+ host()->GetLatencyComponentId());
renderer_latency_info.set_trace_id(++tab_show_sequence_);
host()->WasShown(renderer_latency_info);
TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency",
@@ -344,7 +365,7 @@ void RenderWidgetHostViewMac::Show() {
// If there is not a frame being currently drawn, kick one, so that the below
// pause will have a frame to wait on.
- host()->ScheduleComposite();
+ host()->RequestRepaintForTesting();
PauseForPendingResizeOrRepaintsAndDraw();
}
@@ -417,6 +438,10 @@ CursorManager* RenderWidgetHostViewMac::GetCursorManager() {
return cursor_manager_.get();
}
+void RenderWidgetHostViewMac::OnDidNavigateMainFrameToNewPage() {
+ gesture_provider_.ResetDetection();
+}
+
void RenderWidgetHostViewMac::SetIsLoading(bool is_loading) {
is_loading_ = is_loading;
// If we ever decide to show the waiting cursor while the page is loading
@@ -430,6 +455,8 @@ void RenderWidgetHostViewMac::OnUpdateTextInputStateCalled(
if (!did_update_state)
return;
+ ns_view_bridge_->SetTextInputType(GetTextInputType());
+
// |updated_view| is the last view to change its TextInputState which can be
// used to start/stop monitoring composition info when it has a focused
// editable text input field.
@@ -457,14 +484,6 @@ void RenderWidgetHostViewMac::OnUpdateTextInputStateCalled(
// Let AppKit cache the new input context to make IMEs happy.
// See http://crbug.com/73039.
[NSApp updateWindows];
-
-#ifndef __LP64__
- bool can_compose_inline =
- !!GetTextInputManager()->GetActiveWidget()
- ? GetTextInputManager()->GetTextInputState()->can_compose_inline
- : true;
- UseInputWindow(TSMGetActiveDocument(), !can_compose_inline);
-#endif
}
}
@@ -531,6 +550,22 @@ void RenderWidgetHostViewMac::OnTextSelectionChanged(
selection->range());
}
+void RenderWidgetHostViewMac::OnGestureEvent(
+ const ui::GestureEventData& gesture) {
+ blink::WebGestureEvent web_gesture =
+ ui::CreateWebGestureEventFromGestureEventData(gesture);
+
+ ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
+
+ if (ShouldRouteEvent(web_gesture)) {
+ blink::WebGestureEvent gesture_event(web_gesture);
+ host()->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ this, &gesture_event, latency_info);
+ } else {
+ host()->ForwardGestureEventWithLatencyInfo(web_gesture, latency_info);
+ }
+}
+
void RenderWidgetHostViewMac::OnRenderFrameMetadataChanged() {
last_frame_root_background_color_ = host()
->render_frame_metadata_provider()
@@ -585,17 +620,15 @@ void RenderWidgetHostViewMac::DisplayTooltipText(
ns_view_bridge_->SetTooltipText(tooltip_text);
}
-viz::ScopedSurfaceIdAllocator RenderWidgetHostViewMac::ResizeDueToAutoResize(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
- // TODO(cblume): This doesn't currently suppress allocation.
- // It maintains existing behavior while using the suppression style.
- // This will be addressed in a follow-up patch.
- // See https://crbug.com/805073
- base::OnceCallback<void()> allocation_task =
- base::BindOnce(&RenderWidgetHostViewMac::OnResizeDueToAutoResizeComplete,
- weak_factory_.GetWeakPtr(), new_size, sequence_number);
- return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
+viz::ScopedSurfaceIdAllocator
+RenderWidgetHostViewMac::DidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
+ base::OnceCallback<void()> allocation_task = base::BindOnce(
+ base::IgnoreResult(
+ &RenderWidgetHostViewMac::OnDidUpdateVisualPropertiesComplete),
+ weak_factory_.GetWeakPtr(), metadata);
+ return browser_compositor_->GetScopedRendererSurfaceIdAllocator(
+ std::move(allocation_task));
}
void RenderWidgetHostViewMac::DidNavigate() {
@@ -684,6 +717,10 @@ void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) {
ns_view_bridge_->SetShowingContextMenu(showing);
}
+uint32_t RenderWidgetHostViewMac::GetCaptureSequenceNumber() const {
+ return latest_capture_sequence_number_;
+}
+
void RenderWidgetHostViewMac::CopyFromSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
@@ -692,6 +729,11 @@ void RenderWidgetHostViewMac::CopyFromSurface(
src_subrect, dst_size, std::move(callback));
}
+void RenderWidgetHostViewMac::EnsureSurfaceSynchronizedForLayoutTest() {
+ ++latest_capture_sequence_number_;
+ SynchronizeVisualProperties();
+}
+
void RenderWidgetHostViewMac::SetNeedsBeginFrames(bool needs_begin_frames) {
needs_begin_frames_ = needs_begin_frames;
UpdateNeedsBeginFramesInternal();
@@ -701,11 +743,11 @@ void RenderWidgetHostViewMac::UpdateNeedsBeginFramesInternal() {
browser_compositor_->SetNeedsBeginFrames(needs_begin_frames_);
}
-void RenderWidgetHostViewMac::OnResizeDueToAutoResizeComplete(
- const gfx::Size& new_size,
- uint64_t sequence_number) {
- browser_compositor_->UpdateForAutoResize(new_size);
- host()->DidAllocateLocalSurfaceIdForAutoResize(sequence_number);
+void RenderWidgetHostViewMac::OnDidUpdateVisualPropertiesComplete(
+ const cc::RenderFrameMetadata& metadata) {
+ browser_compositor_->SynchronizeVisualProperties(
+ metadata.viewport_size_in_pixels,
+ metadata.local_surface_id.value_or(viz::LocalSurfaceId()));
}
void RenderWidgetHostViewMac::SetWantsAnimateOnlyBeginFrames() {
@@ -721,7 +763,16 @@ void RenderWidgetHostViewMac::TakeFallbackContentFrom(
RenderWidgetHostViewMac* view_mac =
static_cast<RenderWidgetHostViewMac*>(view);
ScopedCAActionDisabler disabler;
- SetBackgroundColor(view_mac->background_color());
+ base::Optional<SkColor> color = view_mac->GetBackgroundColor();
+ if (color)
+ SetBackgroundColor(*color);
+
+ // Make the NSView for |this| display the same content as is being displayed
+ // in the NSView for |view_mac|.
+ const gfx::CALayerParams* ca_layer_params =
+ view_mac->browser_compositor_->GetLastCALayerParams();
+ if (ca_layer_params)
+ ns_view_bridge_->SetCALayerParams(*ca_layer_params);
browser_compositor_->TakeFallbackContentFrom(
view_mac->browser_compositor_.get());
}
@@ -890,6 +941,10 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
}
bool RenderWidgetHostViewMac::ShouldContinueToPauseForFrame() {
+ // Only pause for frames when drawing through a separate ui::Compositor.
+ if (display_only_using_parent_ui_layer_)
+ return false;
+
return browser_compositor_->ShouldContinueToPauseForFrame();
}
@@ -917,7 +972,7 @@ void RenderWidgetHostViewMac::DidCreateNewRendererCompositorFrameSink(
void RenderWidgetHostViewMac::SubmitCompositorFrame(
const viz::LocalSurfaceId& local_surface_id,
viz::CompositorFrame frame,
- viz::mojom::HitTestRegionListPtr hit_test_region_list) {
+ base::Optional<viz::HitTestRegionList> hit_test_region_list) {
TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame");
page_at_minimum_scale_ =
@@ -938,8 +993,13 @@ void RenderWidgetHostViewMac::ClearCompositorFrame() {
browser_compositor_->ClearCompositorFrame();
}
-gfx::Vector2d RenderWidgetHostViewMac::GetOffsetFromRootSurface() {
- return gfx::Vector2d();
+bool RenderWidgetHostViewMac::RequestRepaintForTesting() {
+ return browser_compositor_->RequestRepaintForTesting();
+}
+
+void RenderWidgetHostViewMac::TransformPointToRootSurface(gfx::PointF* point) {
+ if (display_only_using_parent_ui_layer_)
+ *point += view_bounds_in_window_dip_.OffsetFromOrigin();
}
gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() {
@@ -971,6 +1031,25 @@ void RenderWidgetHostViewMac::UnlockMouse() {
host()->LostMouseLock();
}
+bool RenderWidgetHostViewMac::LockKeyboard(
+ base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
+ is_keyboard_locked_ = true;
+ ns_view_bridge_->LockKeyboard(std::move(dom_codes));
+ return true;
+}
+
+void RenderWidgetHostViewMac::UnlockKeyboard() {
+ if (!is_keyboard_locked_)
+ return;
+
+ is_keyboard_locked_ = false;
+ ns_view_bridge_->UnlockKeyboard();
+}
+
+bool RenderWidgetHostViewMac::IsKeyboardLocked() {
+ return is_keyboard_locked_;
+}
+
void RenderWidgetHostViewMac::GestureEventAck(const WebGestureEvent& event,
InputEventAckState ack_result) {
bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
@@ -986,6 +1065,23 @@ void RenderWidgetHostViewMac::GestureEventAck(const WebGestureEvent& event,
mouse_wheel_phase_handler_.GestureEventAck(event, ack_result);
}
+void RenderWidgetHostViewMac::ProcessAckedTouchEvent(
+ const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) {
+ const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
+ gesture_provider_.OnTouchEventAck(
+ touch.event.unique_touch_event_id, event_consumed,
+ InputEventAckStateIsSetNonBlocking(ack_result));
+ if (touch.event.touch_start_or_first_touch_move && event_consumed &&
+ host()->delegate() && host()->delegate()->GetInputEventRouter()) {
+ host()
+ ->delegate()
+ ->GetInputEventRouter()
+ ->OnHandledTouchStartOrFirstTouchMove(
+ touch.event.unique_touch_event_id);
+ }
+}
+
void RenderWidgetHostViewMac::DidOverscroll(
const ui::DidOverscrollParams& params) {
[cocoa_view() processedOverscroll:params];
@@ -1009,12 +1105,16 @@ viz::FrameSinkId RenderWidgetHostViewMac::GetFrameSinkId() {
bool RenderWidgetHostViewMac::ShouldRouteEvent(
const WebInputEvent& event) const {
+ // Event routing requires a valid frame sink (that is, that we be connected to
+ // a ui::Compositor), which is not guaranteed to be the case.
+ // https://crbug.com/844095
+ if (!browser_compositor_->GetRootFrameSinkId().is_valid())
+ return false;
// See also RenderWidgetHostViewAura::ShouldRouteEvent.
// TODO(wjmaclean): Update this function if RenderWidgetHostViewMac implements
// OnTouchEvent(), to match what we are doing in RenderWidgetHostViewAura.
- DCHECK(WebInputEvent::IsMouseEventType(event.GetType()) ||
- event.GetType() == WebInputEvent::kMouseWheel ||
- WebInputEvent::IsPinchGestureEventType(event.GetType()));
+ // The only touch events and touch gesture events expected here are
+ // injected synthetic events.
return host()->delegate() && host()->delegate()->GetInputEventRouter();
}
@@ -1030,7 +1130,24 @@ void RenderWidgetHostViewMac::SendGesturePinchEvent(WebGestureEvent* event) {
host()->ForwardGestureEvent(*event);
}
-bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
+void RenderWidgetHostViewMac::InjectTouchEvent(
+ const WebTouchEvent& event,
+ const ui::LatencyInfo& latency_info) {
+ ui::FilteredGestureProvider::TouchHandlingResult result =
+ gesture_provider_.OnTouchEvent(MotionEventWeb(event));
+ if (!result.succeeded)
+ return;
+
+ if (ShouldRouteEvent(event)) {
+ WebTouchEvent touch_event(event);
+ host()->delegate()->GetInputEventRouter()->RouteTouchEvent(
+ this, &touch_event, latency_info);
+ } else {
+ host()->ForwardTouchEventWithLatencyInfo(event, latency_info);
+ }
+}
+
+bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpaceLegacy(
const gfx::PointF& point,
const viz::SurfaceId& original_surface,
gfx::PointF* transformed_point) {
@@ -1039,8 +1156,8 @@ bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
float scale_factor = display_.device_scale_factor();
gfx::PointF point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
if (!browser_compositor_->GetDelegatedFrameHost()
- ->TransformPointToLocalCoordSpace(point_in_pixels, original_surface,
- transformed_point))
+ ->TransformPointToLocalCoordSpaceLegacy(
+ point_in_pixels, original_surface, transformed_point))
return false;
*transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
return true;
@@ -1049,15 +1166,16 @@ bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
bool RenderWidgetHostViewMac::TransformPointToCoordSpaceForView(
const gfx::PointF& point,
RenderWidgetHostViewBase* target_view,
- gfx::PointF* transformed_point) {
+ gfx::PointF* transformed_point,
+ viz::EventSource source) {
if (target_view == this) {
*transformed_point = point;
return true;
}
return browser_compositor_->GetDelegatedFrameHost()
- ->TransformPointToCoordSpaceForView(point, target_view,
- transformed_point);
+ ->TransformPointToCoordSpaceForView(point, target_view, transformed_point,
+ source);
}
viz::FrameSinkId RenderWidgetHostViewMac::GetRootFrameSinkId() {
@@ -1102,32 +1220,25 @@ void RenderWidgetHostViewMac::ShowDefinitionForSelection() {
ns_view_bridge_->ShowDictionaryOverlayForSelection();
}
-void RenderWidgetHostViewMac::SetBackgroundColor(SkColor color) {
+void RenderWidgetHostViewMac::UpdateBackgroundColor() {
// This is called by the embedding code prior to the first frame appearing,
// to set a reasonable color to show before the web content generates its
// first frame. This will be overridden by the web contents.
+ DCHECK(RenderWidgetHostViewBase::GetBackgroundColor());
+ SkColor color = *RenderWidgetHostViewBase::GetBackgroundColor();
SetBackgroundLayerColor(color);
browser_compositor_->SetBackgroundColor(color);
-
- DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
- SkColorGetA(color) == SK_AlphaTRANSPARENT);
- bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE;
- if (background_is_opaque_ != opaque) {
- background_is_opaque_ = opaque;
- if (host())
- host()->SetBackgroundOpaque(opaque);
- }
}
-SkColor RenderWidgetHostViewMac::background_color() const {
+base::Optional<SkColor> RenderWidgetHostViewMac::GetBackgroundColor() const {
// This is used to specify a color to temporarily show while waiting for web
// content. This should never return transparent, since that will cause bugs
// where views are initialized as having a transparent background
// inappropriately.
// https://crbug.com/735407
- if (background_layer_color_ == SK_ColorTRANSPARENT)
- return SK_ColorWHITE;
- return background_layer_color_;
+ base::Optional<SkColor> color =
+ RenderWidgetHostViewBase::GetBackgroundColor();
+ return (color && *color == SK_ColorTRANSPARENT) ? SK_ColorWHITE : color;
}
void RenderWidgetHostViewMac::SetBackgroundLayerColor(SkColor color) {
@@ -1194,6 +1305,10 @@ RenderWidgetHostViewMac::AllocateFrameSinkIdForGuestViewHack() {
->AllocateFrameSinkId();
}
+MouseWheelPhaseHandler* RenderWidgetHostViewMac::GetMouseWheelPhaseHandler() {
+ return &mouse_wheel_phase_handler_;
+}
+
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostNSViewClient implementation:
@@ -1262,7 +1377,14 @@ void RenderWidgetHostViewMac::OnNSViewBoundsInWindowChanged(
void RenderWidgetHostViewMac::OnNSViewWindowFrameInScreenChanged(
const gfx::Rect& window_frame_in_screen_dip) {
+ if (window_frame_in_screen_dip_ == window_frame_in_screen_dip)
+ return;
+
window_frame_in_screen_dip_ = window_frame_in_screen_dip;
+ if (host()->delegate())
+ host()->delegate()->SendScreenRects();
+ else
+ host()->SendScreenRects();
}
void RenderWidgetHostViewMac::OnNSViewDisplayChanged(
@@ -1313,7 +1435,7 @@ void RenderWidgetHostViewMac::OnNSViewRouteOrProcessMouseEvent(
const blink::WebMouseEvent& const_web_event) {
blink::WebMouseEvent web_event = const_web_event;
ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
if (ShouldRouteEvent(web_event)) {
host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &web_event,
latency_info);
@@ -1326,7 +1448,7 @@ void RenderWidgetHostViewMac::OnNSViewRouteOrProcessWheelEvent(
const blink::WebMouseWheelEvent& const_web_event) {
blink::WebMouseWheelEvent web_event = const_web_event;
ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
if (wheel_scroll_latching_enabled()) {
mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
web_event, ShouldRouteEvent(web_event));
@@ -1362,19 +1484,21 @@ void RenderWidgetHostViewMac::OnNSViewForwardWheelEvent(
false);
} else {
ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
- latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
+ latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0);
host()->ForwardWheelEventWithLatencyInfo(web_event, latency_info);
}
}
void RenderWidgetHostViewMac::OnNSViewGestureBegin(
- blink::WebGestureEvent begin_event) {
+ blink::WebGestureEvent begin_event,
+ bool is_synthetically_injected) {
gesture_begin_event_.reset(new WebGestureEvent(begin_event));
// If the page is at the minimum zoom level, require a threshold be reached
- // before the pinch has an effect.
+ // before the pinch has an effect. Synthetic pinches are not subject to this
+ // threshold.
if (page_at_minimum_scale_) {
- pinch_has_reached_zoom_threshold_ = false;
+ pinch_has_reached_zoom_threshold_ = is_synthetically_injected;
pinch_unused_amount_ = 1;
}
}
@@ -1504,11 +1628,6 @@ void RenderWidgetHostViewMac::OnNSViewLookUpDictionaryOverlayAtPoint(
target_widget_routing_id));
}
-void RenderWidgetHostViewMac::OnNSViewSyncGetTextInputType(
- ui::TextInputType* text_input_type) {
- *text_input_type = GetTextInputType();
-}
-
void RenderWidgetHostViewMac::OnNSViewSyncGetCharacterIndexAtPoint(
const gfx::PointF& root_point,
uint32_t* index) {
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index 84029bb39e9..fbca43e1919 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -21,6 +21,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -359,7 +360,6 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
ui::SetEventTickClockForTesting(&mock_clock_);
SetFeatureList();
- mojo_feature_list_.InitAndEnableFeature(features::kMojoInputMessages);
vsync_feature_list_.InitAndEnableFeature(
features::kVsyncAlignedInputEvents);
}
@@ -451,7 +451,6 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
// This class isn't derived from PlatformTest.
base::mac::ScopedNSAutoreleasePool pool_;
- base::test::ScopedFeatureList mojo_feature_list_;
base::test::ScopedFeatureList vsync_feature_list_;
base::test::ScopedFeatureList feature_list_;
@@ -1078,22 +1077,22 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
const IPC::Message* set_background = nullptr;
std::tuple<bool> sent_background;
- // If no color has been specified then default color of white should be
- // returned.
- EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE),
- rwhv_mac_->background_color());
+ // If no color has been specified then background_color is not set yet.
+ ASSERT_FALSE(rwhv_mac_->GetBackgroundColor());
// Set the color to red. The background is initially assumed to be opaque, so
// no opacity message change should be sent.
rwhv_mac_->SetBackgroundColor(SK_ColorRED);
- EXPECT_EQ(static_cast<unsigned>(SK_ColorRED), rwhv_mac_->background_color());
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorRED),
+ *rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_FALSE(set_background);
// Set the color to blue. This should not send an opacity message.
rwhv_mac_->SetBackgroundColor(SK_ColorBLUE);
- EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE), rwhv_mac_->background_color());
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE),
+ *rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_FALSE(set_background);
@@ -1104,7 +1103,7 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
process_host_->sink().ClearMessages();
rwhv_mac_->SetBackgroundColor(SK_ColorTRANSPARENT);
EXPECT_EQ(static_cast<unsigned>(SK_ColorWHITE),
- rwhv_mac_->background_color());
+ *rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
@@ -1114,7 +1113,8 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
// Set the color to red. This should send an opacity message.
process_host_->sink().ClearMessages();
rwhv_mac_->SetBackgroundColor(SK_ColorBLUE);
- EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE), rwhv_mac_->background_color());
+ EXPECT_EQ(static_cast<unsigned>(SK_ColorBLUE),
+ *rwhv_mac_->GetBackgroundColor());
set_background = process_host_->sink().GetUniqueMessageMatching(
ViewMsg_SetBackgroundOpaque::ID);
ASSERT_TRUE(set_background);
@@ -1935,13 +1935,72 @@ TEST_F(InputMethodMacTest, MonitorCompositionRangeForActiveWidget) {
}
TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) {
- BrowserCompositorMac* browser_compositor =
- rwhv_mac_->BrowserCompositorForTesting();
- EXPECT_NE(browser_compositor->CompositorForTesting(), nullptr);
- EXPECT_TRUE(browser_compositor->CompositorForTesting()->IsLocked());
+ BrowserCompositorMac* browser_compositor = rwhv_mac_->BrowserCompositor();
+ ui::Compositor* ui_compositor = browser_compositor->GetCompositorForTesting();
+ EXPECT_NE(ui_compositor, nullptr);
+ EXPECT_TRUE(ui_compositor->IsLocked());
rwhv_mac_->ClearCompositorFrame();
- EXPECT_NE(browser_compositor->CompositorForTesting(), nullptr);
- EXPECT_FALSE(browser_compositor->CompositorForTesting()->IsLocked());
+ EXPECT_EQ(browser_compositor->GetCompositorForTesting(), 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) {
+ viz::LocalSurfaceId local_surface_id1(rwhv_mac_->GetLocalSurfaceId());
+ EXPECT_TRUE(local_surface_id1.is_valid());
+
+ host_->SetAutoResize(true, gfx::Size(50, 50), gfx::Size(100, 100));
+
+ viz::ChildLocalSurfaceIdAllocator child_allocator;
+ child_allocator.UpdateFromParent(local_surface_id1);
+ viz::LocalSurfaceId local_surface_id2 = child_allocator.GenerateId();
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(75, 75);
+ metadata.local_surface_id = local_surface_id2;
+ host_->DidUpdateVisualProperties(metadata);
+
+ viz::LocalSurfaceId local_surface_id3(rwhv_mac_->GetLocalSurfaceId());
+ EXPECT_NE(local_surface_id1, local_surface_id3);
+ EXPECT_EQ(local_surface_id2, local_surface_id3);
+}
+
+// This test verifies that when the child and parent both allocate their own
+// viz::LocalSurfaceId the resulting conflict is resolved.
+TEST_F(RenderWidgetHostViewMacTest, ConflictingAllocationsResolve) {
+ viz::LocalSurfaceId local_surface_id1(rwhv_mac_->GetLocalSurfaceId());
+ EXPECT_TRUE(local_surface_id1.is_valid());
+
+ host_->SetAutoResize(true, gfx::Size(50, 50), gfx::Size(100, 100));
+ viz::ChildLocalSurfaceIdAllocator child_allocator;
+ child_allocator.UpdateFromParent(local_surface_id1);
+ viz::LocalSurfaceId local_surface_id2 = child_allocator.GenerateId();
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(75, 75);
+ metadata.local_surface_id = local_surface_id2;
+ host_->DidUpdateVisualProperties(metadata);
+
+ // Cause a conflicting viz::LocalSurfaceId allocation
+ BrowserCompositorMac* browser_compositor = rwhv_mac_->BrowserCompositor();
+ EXPECT_TRUE(browser_compositor->ForceNewSurfaceForTesting());
+ viz::LocalSurfaceId local_surface_id3(rwhv_mac_->GetLocalSurfaceId());
+ EXPECT_NE(local_surface_id1, local_surface_id3);
+
+ // RenderWidgetHostImpl has delayed auto-resize processing. Yield here to
+ // let it complete.
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+
+ viz::LocalSurfaceId local_surface_id4(rwhv_mac_->GetLocalSurfaceId());
+ EXPECT_NE(local_surface_id1, local_surface_id4);
+ EXPECT_NE(local_surface_id2, local_surface_id4);
+ viz::LocalSurfaceId merged_local_surface_id(
+ local_surface_id2.parent_sequence_number() + 1,
+ local_surface_id2.child_sequence_number(),
+ local_surface_id2.embed_token());
+ EXPECT_EQ(local_surface_id4, merged_local_surface_id);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_targeter.cc b/chromium/content/browser/renderer_host/render_widget_targeter.cc
index 9e0e5b96b8e..f25502b308e 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.cc
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.cc
@@ -5,9 +5,11 @@
#include "content/browser/renderer_host/render_widget_targeter.h"
#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "content/browser/renderer_host/input/one_shot_timeout_monitor.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/public/browser/site_isolation_policy.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/events/blink/blink_event_util.h"
@@ -88,10 +90,12 @@ RenderWidgetTargetResult::RenderWidgetTargetResult(
RenderWidgetTargetResult::RenderWidgetTargetResult(
RenderWidgetHostViewBase* in_view,
bool in_should_query_view,
- base::Optional<gfx::PointF> in_location)
+ base::Optional<gfx::PointF> in_location,
+ bool in_latched_target)
: view(in_view),
should_query_view(in_should_query_view),
- target_location(in_location) {}
+ target_location(in_location),
+ latched_target(in_latched_target) {}
RenderWidgetTargetResult::~RenderWidgetTargetResult() = default;
@@ -146,6 +150,7 @@ void RenderWidgetTargeter::FindTargetAndDispatch(
RenderWidgetHostViewBase* target = result.view;
auto* event_ptr = &event;
+ async_depth_ = 0;
// TODO(kenrb, wjmaclean): Asynchronous hit tests don't work properly with
// GuestViews, so rely on the synchronous result.
// See https://crbug.com/802378.
@@ -159,7 +164,8 @@ void RenderWidgetTargeter::FindTargetAndDispatch(
QueryClient(root_view, root_view, *event_ptr, latency,
ComputeEventLocation(event), nullptr, gfx::PointF());
} else {
- FoundTarget(root_view, target, *event_ptr, latency, result.target_location);
+ FoundTarget(root_view, target, *event_ptr, latency, result.target_location,
+ result.latched_target);
}
}
@@ -177,26 +183,33 @@ void RenderWidgetTargeter::QueryClient(
const gfx::PointF& last_target_location) {
DCHECK(!request_in_flight_);
- request_in_flight_ = true;
auto* target_client = target->host()->input_target_client();
+ // |target_client| may not be set yet for this |target| on Mac, need to
+ // understand why this happens. https://crbug.com/859492
+ if (!target_client) {
+ FoundTarget(root_view, target, event, latency, target_location, false);
+ return;
+ }
+
+ request_in_flight_ = true;
+ async_depth_++;
TracingUmaTracker tracker("Event.AsyncTargeting.ResponseTime",
"input,latency");
- async_hit_test_timeout_.reset(new OneShotTimeoutMonitor(
- base::BindOnce(
- &RenderWidgetTargeter::AsyncHitTestTimedOut,
- weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
- target->GetWeakPtr(), target_location,
- last_request_target ? last_request_target->GetWeakPtr() : nullptr,
- last_target_location, ui::WebInputEventTraits::Clone(event),
- latency),
- async_hit_test_timeout_delay_));
- target_client->FrameSinkIdAt(
- gfx::ToCeiledPoint(target_location),
- base::BindOnce(
- &RenderWidgetTargeter::FoundFrameSinkId,
- weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
- target->GetWeakPtr(), ui::WebInputEventTraits::Clone(event),
- latency, ++last_request_id_, target_location, std::move(tracker)));
+ async_hit_test_timeout_.reset(new OneShotTimeoutMonitor(
+ base::BindOnce(
+ &RenderWidgetTargeter::AsyncHitTestTimedOut,
+ weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
+ target->GetWeakPtr(), target_location,
+ last_request_target ? last_request_target->GetWeakPtr() : nullptr,
+ last_target_location, ui::WebInputEventTraits::Clone(event), latency),
+ async_hit_test_timeout_delay_));
+ target_client->FrameSinkIdAt(
+ gfx::ToCeiledPoint(target_location),
+ base::BindOnce(&RenderWidgetTargeter::FoundFrameSinkId,
+ weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
+ target->GetWeakPtr(),
+ ui::WebInputEventTraits::Clone(event), latency,
+ ++last_request_id_, target_location, std::move(tracker)));
}
void RenderWidgetTargeter::FlushEventQueue() {
@@ -242,7 +255,7 @@ void RenderWidgetTargeter::FoundFrameSinkId(
// asking the clients until a client claims an event for itself.
if (view == target.get() ||
unresponsive_views_.find(view) != unresponsive_views_.end()) {
- FoundTarget(root_view.get(), view, *event, latency, target_location);
+ FoundTarget(root_view.get(), view, *event, latency, target_location, false);
} else {
gfx::PointF location = target_location;
target->TransformPointToCoordSpaceForView(location, view, &location);
@@ -256,7 +269,13 @@ void RenderWidgetTargeter::FoundTarget(
RenderWidgetHostViewBase* target,
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency,
- const base::Optional<gfx::PointF>& target_location) {
+ const base::Optional<gfx::PointF>& target_location,
+ bool latched_target) {
+ if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites() &&
+ !latched_target) {
+ UMA_HISTOGRAM_COUNTS_100("Event.AsyncTargeting.AsyncClientDepth",
+ async_depth_);
+ }
// RenderWidgetHostViewMac can be deleted asynchronously, in which case the
// View will be valid but there will no longer be a RenderWidgetHostImpl.
if (!root_view || !root_view->GetRenderWidgetHost())
@@ -290,10 +309,10 @@ void RenderWidgetTargeter::AsyncHitTestTimedOut(
// renderer fails to process it.
FoundTarget(current_request_root_view.get(),
current_request_root_view.get(), *event, latency,
- current_target_location);
+ current_target_location, false);
} else {
FoundTarget(current_request_root_view.get(), last_request_target.get(),
- *event, latency, last_target_location);
+ *event, latency, last_target_location, false);
}
}
diff --git a/chromium/content/browser/renderer_host/render_widget_targeter.h b/chromium/content/browser/renderer_host/render_widget_targeter.h
index 899c37f20bc..e9b3e2addf4 100644
--- a/chromium/content/browser/renderer_host/render_widget_targeter.h
+++ b/chromium/content/browser/renderer_host/render_widget_targeter.h
@@ -38,12 +38,16 @@ struct CONTENT_EXPORT RenderWidgetTargetResult {
RenderWidgetTargetResult(const RenderWidgetTargetResult&);
RenderWidgetTargetResult(RenderWidgetHostViewBase* view,
bool should_query_view,
- base::Optional<gfx::PointF> location);
+ base::Optional<gfx::PointF> location,
+ bool latched_target);
~RenderWidgetTargetResult();
RenderWidgetHostViewBase* view = nullptr;
bool should_query_view = false;
base::Optional<gfx::PointF> target_location = base::nullopt;
+ // When |latched_target| is false, we explicitly hit-tested events instead of
+ // using a known target.
+ bool latched_target = false;
};
class TracingUmaTracker;
@@ -121,12 +125,15 @@ class RenderWidgetTargeter {
const viz::FrameSinkId& frame_sink_id);
// |event| is in the coordinate space of |root_view|. |target_location|, if
- // set, is the location in |target|'s coordinate space.
+ // set, is the location in |target|'s coordinate space. If |latched_target| is
+ // false, we explicitly did hit-testing for this event, instead of using a
+ // known target.
void FoundTarget(RenderWidgetHostViewBase* root_view,
RenderWidgetHostViewBase* target,
const blink::WebInputEvent& event,
const ui::LatencyInfo& latency,
- const base::Optional<gfx::PointF>& target_location);
+ const base::Optional<gfx::PointF>& target_location,
+ bool latched_target);
// Callback when the hit testing timer fires, to resume event processing
// without further waiting for a response to the last targeting request.
@@ -161,6 +168,10 @@ class RenderWidgetTargeter {
std::unordered_set<RenderWidgetHostViewBase*> unresponsive_views_;
+ // This value keeps track of the number of clients we have asked in order to
+ // do async hit-testing.
+ uint32_t async_depth_ = 0;
+
// This value limits how long to wait for a response from the renderer
// process before giving up and resuming event processing.
base::TimeDelta async_hit_test_timeout_delay_ =
diff --git a/chromium/content/browser/renderer_host/text_input_manager.cc b/chromium/content/browser/renderer_host/text_input_manager.cc
index 8ab29925959..24f32e7228a 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.cc
+++ b/chromium/content/browser/renderer_host/text_input_manager.cc
@@ -35,7 +35,8 @@ bool ShouldUpdateTextInputState(const content::TextInputState& old_state,
} // namespace
-TextInputManager::TextInputManager() : active_view_(nullptr) {}
+TextInputManager::TextInputManager(bool should_do_learning)
+ : active_view_(nullptr), should_do_learning_(should_do_learning) {}
TextInputManager::~TextInputManager() {
// If there is an active view, we should unregister it first so that the
diff --git a/chromium/content/browser/renderer_host/text_input_manager.h b/chromium/content/browser/renderer_host/text_input_manager.h
index b4cbcaec304..8e4ecfe5be2 100644
--- a/chromium/content/browser/renderer_host/text_input_manager.h
+++ b/chromium/content/browser/renderer_host/text_input_manager.h
@@ -131,7 +131,7 @@ class CONTENT_EXPORT TextInputManager {
base::string16 text_;
};
- TextInputManager();
+ explicit TextInputManager(bool should_do_learning);
~TextInputManager();
// Returns the currently active widget, i.e., the RWH which is associated with
@@ -226,6 +226,8 @@ class CONTENT_EXPORT TextInputManager {
RenderWidgetHostViewBase* view);
const gfx::Range* GetCompositionRangeForTesting() const;
+ bool should_do_learning() const { return should_do_learning_; }
+
private:
// This class is used to create maps which hold specific IME state for a
// view.
@@ -249,6 +251,10 @@ class CONTENT_EXPORT TextInputManager {
ViewMap<CompositionRangeInfo> composition_range_info_map_;
ViewMap<TextSelection> text_selection_map_;
+ // Whether the text input should be used to improve typing suggestions for the
+ // user.
+ bool should_do_learning_;
+
base::ObserverList<Observer> observer_list_;
DISALLOW_COPY_AND_ASSIGN(TextInputManager);
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index a958b79e8c8..8b3330f22c9 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -64,8 +64,7 @@ bool MakeUITouchEventsFromWebTouchEvents(
}
int flags = ui::WebEventModifiersToEventFlags(touch.GetModifiers());
- base::TimeTicks timestamp =
- ui::EventTimeStampFromSeconds(touch.TimeStampSeconds());
+ base::TimeTicks timestamp = touch.TimeStamp();
for (unsigned i = 0; i < touch.touches_length; ++i) {
const blink::WebTouchPoint& point = touch.touches[i];
if (WebTouchPointStateToEventType(point.state) != type)
diff --git a/chromium/content/browser/renderer_interface_binders.cc b/chromium/content/browser/renderer_interface_binders.cc
index 24bd8c4e1e2..e306536aa57 100644
--- a/chromium/content/browser/renderer_interface_binders.cc
+++ b/chromium/content/browser/renderer_interface_binders.cc
@@ -7,9 +7,8 @@
#include <utility>
#include "base/bind.h"
-#include "base/feature_list.h"
#include "content/browser/background_fetch/background_fetch_service_impl.h"
-#include "content/browser/dedicated_worker/dedicated_worker_host.h"
+#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/locks/lock_manager.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/payments/payment_manager.h"
@@ -26,7 +25,6 @@
#include "content/public/common/content_switches.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/vibration_manager.mojom.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/restricted_cookie_manager.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -34,6 +32,7 @@
#include "services/shape_detection/public/mojom/constants.mojom.h"
#include "services/shape_detection/public/mojom/facedetection_provider.mojom.h"
#include "services/shape_detection/public/mojom/textdetection.mojom.h"
+#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/platform/modules/notifications/notification_service.mojom.h"
#include "url/origin.h"
@@ -132,8 +131,17 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
parameterized_binder_registry_.AddInterface(
base::Bind(&ForwardServiceRequest<device::mojom::VibrationManager>,
device::mojom::kServiceName));
+
+ // Used for shared workers and service workers to create a websocket.
+ // In other cases, RenderFrameHostImpl for documents or DedicatedWorkerHost
+ // for dedicated workers handles interface requests in order to associate
+ // websockets with a frame. Shared workers and service workers don't have to
+ // do it because they don't have a frame.
+ // TODO(nhiroki): Consider moving this into SharedWorkerHost and
+ // ServiceWorkerProviderHost.
parameterized_binder_registry_.AddInterface(
base::BindRepeating(CreateWebSocket));
+
parameterized_binder_registry_.AddInterface(
base::Bind([](payments::mojom::PaymentManagerRequest request,
RenderProcessHost* host, const url::Origin& origin) {
@@ -162,8 +170,6 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
->CreateService(std::move(request), origin);
}));
parameterized_binder_registry_.AddInterface(
- base::Bind(&CreateDedicatedWorkerHostFactory));
- parameterized_binder_registry_.AddInterface(
base::Bind([](blink::mojom::NotificationServiceRequest request,
RenderProcessHost* host, const url::Origin& origin) {
static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
@@ -176,6 +182,13 @@ void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
base::BindRepeating(GetRestrictedCookieManagerForWorker));
parameterized_binder_registry_.AddInterface(
base::BindRepeating(&QuotaDispatcherHost::CreateForWorker));
+ parameterized_binder_registry_.AddInterface(base::BindRepeating(
+ [](blink::mojom::CookieStoreRequest request, RenderProcessHost* host,
+ const url::Origin& origin) {
+ static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
+ ->GetCookieStoreContext()
+ ->CreateService(std::move(request), origin);
+ }));
}
RendererInterfaceBinders& GetRendererInterfaceBinders() {
@@ -187,16 +200,8 @@ void RendererInterfaceBinders::CreateWebSocket(
network::mojom::WebSocketRequest request,
RenderProcessHost* host,
const url::Origin& origin) {
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- StoragePartition* storage_partition = host->GetStoragePartition();
- network::mojom::NetworkContext* network_context =
- storage_partition->GetNetworkContext();
- network_context->CreateWebSocket(std::move(request), host->GetID(),
- MSG_ROUTING_NONE, origin);
- } else {
- WebSocketManager::CreateWebSocketWithOrigin(
- host->GetID(), origin, std::move(request), MSG_ROUTING_NONE);
- }
+ WebSocketManager::CreateWebSocket(host->GetID(), MSG_ROUTING_NONE, origin,
+ std::move(request));
}
} // namespace
diff --git a/chromium/content/browser/resources/BUILD.gn b/chromium/content/browser/resources/BUILD.gn
new file mode 100644
index 00000000000..126fcfc4584
--- /dev/null
+++ b/chromium/content/browser/resources/BUILD.gn
@@ -0,0 +1,13 @@
+# 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("//ui/webui/webui_features.gni")
+
+if (closure_compile) {
+ group("closure_compile") {
+ deps = [
+ "histograms:closure_compile",
+ ]
+ }
+}
diff --git a/chromium/content/browser/resources/appcache/OWNERS b/chromium/content/browser/resources/appcache/OWNERS
index 3dbb5c2ac74..7afe42b77c6 100644
--- a/chromium/content/browser/resources/appcache/OWNERS
+++ b/chromium/content/browser/resources/appcache/OWNERS
@@ -1,8 +1,5 @@
jsbell@chromium.org
pwnall@chromium.org
-# OOO until this comment is removed.
-michaeln@chromium.org
-
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>AppCache
diff --git a/chromium/content/browser/resources/gpu/browser_bridge.js b/chromium/content/browser/resources/gpu/browser_bridge.js
index c2ad051d09b..24e4b078f59 100644
--- a/chromium/content/browser/resources/gpu/browser_bridge.js
+++ b/chromium/content/browser/resources/gpu/browser_bridge.js
@@ -143,8 +143,8 @@ cr.define('gpu', function() {
* Returns the value of the "Sandboxed" row.
*/
isSandboxedForTesting : function() {
- for (i = 0; i < this.gpuInfo_.basic_info.length; ++i) {
- var info = this.gpuInfo_.basic_info[i];
+ for (i = 0; i < this.gpuInfo_.basicInfo.length; ++i) {
+ var info = this.gpuInfo_.basicInfo[i];
if (info.description == "Sandboxed")
return info.value;
}
diff --git a/chromium/content/browser/resources/gpu/info_view.html b/chromium/content/browser/resources/gpu/info_view.html
index 288f402dc58..1d44f6ccc7d 100644
--- a/chromium/content/browser/resources/gpu/info_view.html
+++ b/chromium/content/browser/resources/gpu/info_view.html
@@ -61,6 +61,29 @@ found in the LICENSE file.
<div id="diagnostics-table">None</div>
</div>
+ <div class='basic-info-for-hardware-gpu-div'>
+ <h3>Driver Information for Hardware GPU</h3>
+ <div id="basic-info-for-hardware-gpu"></div>
+ </div>
+
+ <div class='feature-status-for-hardware-gpu-div'>
+ <h3>Graphics Feature Status for Hardware GPU</h3>
+ <ul class="feature-status-for-hardware-gpu-list">
+ </ul>
+ </div>
+
+ <div class='workarounds-for-hardware-gpu-div'>
+ <h3>Driver Bug Workarounds for Hardware GPU</h3>
+ <ul class="workarounds-for-hardware-gpu-list">
+ </ul>
+ </div>
+
+ <div class='problems-for-hardware-gpu-div'>
+ <h3>Problems Detected for Hardware GPU</h3>
+ <ul class="problems-for-hardware-gpu-list">
+ </ul>
+ </div>
+
<div id="log-messages" jsdisplay="values.length">
<h3>Log Messages</h3>
<ul>
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index eca2b71095f..41a64405b78 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -99,6 +99,125 @@ cr.define('gpu', function() {
this.setText_('client-info', '... loading...');
}
+
+ // GPU info, basic
+ var diagnosticsDiv = this.querySelector('.diagnostics');
+ var diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading');
+ var featureStatusList = this.querySelector('.feature-status-list');
+ var problemsDiv = this.querySelector('.problems-div');
+ var problemsList = this.querySelector('.problems-list');
+ var workaroundsDiv = this.querySelector('.workarounds-div');
+ var workaroundsList = this.querySelector('.workarounds-list');
+
+ var basicInfoForHardwareGpuDiv =
+ this.querySelector('.basic-info-for-hardware-gpu-div');
+ var featureStatusForHardwareGpuDiv =
+ this.querySelector('.feature-status-for-hardware-gpu-div');
+ var featureStatusForHardwareGpuList =
+ this.querySelector('.feature-status-for-hardware-gpu-list');
+ var problemsForHardwareGpuDiv =
+ this.querySelector('.problems-for-hardware-gpu-div');
+ var problemsForHardwareGpuList =
+ this.querySelector('.problems-for-hardware-gpu-list');
+ var workaroundsForHardwareGpuDiv =
+ this.querySelector('.workarounds-for-hardware-gpu-div');
+ var workaroundsForHardwareGpuList =
+ this.querySelector('.workarounds-for-hardware-gpu-list');
+
+ var gpuInfo = browserBridge.gpuInfo;
+ var i;
+ if (gpuInfo) {
+ // Not using jstemplate here for blacklist status because we construct
+ // href from data, which jstemplate can't seem to do.
+ if (gpuInfo.featureStatus) {
+ this.appendFeatureInfo_(gpuInfo.featureStatus, featureStatusList,
+ problemsDiv, problemsList,
+ workaroundsDiv, workaroundsList);
+ } else {
+ featureStatusList.textContent = '';
+ problemsList.hidden = true;
+ workaroundsList.hidden = true;
+ }
+
+ if (gpuInfo.featureStatusForHardwareGpu) {
+ basicInfoForHardwareGpuDiv.hidden = false;
+ featureStatusForHardwareGpuDiv.hidden = false;
+ problemsForHardwareGpuDiv.hidden = false;
+ workaroundsForHardwareGpuDiv.hidden = false;
+ this.appendFeatureInfo_(gpuInfo.featureStatusForHardwareGpu,
+ featureStatusForHardwareGpuList,
+ problemsForHardwareGpuDiv,
+ problemsForHardwareGpuList,
+ workaroundsForHardwareGpuDiv,
+ workaroundsForHardwareGpuList);
+ if (gpuInfo.basicInfoForHardwareGpu) {
+ this.setTable_('basic-info-for-hardware-gpu',
+ gpuInfo.basicInfoForHardwareGpu);
+ } else {
+ this.setTable_('basic-info-for-hardware-gpu', []);
+ }
+ } else {
+ basicInfoForHardwareGpuDiv.hidden = true;
+ featureStatusForHardwareGpuDiv.hidden = true;
+ problemsForHardwareGpuDiv.hidden = true;
+ workaroundsForHardwareGpuDiv.hidden = true;
+ }
+
+ if (gpuInfo.basicInfo)
+ this.setTable_('basic-info', gpuInfo.basicInfo);
+ else
+ this.setTable_('basic-info', []);
+
+ if (gpuInfo.compositorInfo)
+ this.setTable_('compositor-info', gpuInfo.compositorInfo);
+ else
+ this.setTable_('compositor-info', []);
+
+ if (gpuInfo.gpuMemoryBufferInfo)
+ this.setTable_('gpu-memory-buffer-info', gpuInfo.gpuMemoryBufferInfo);
+ else
+ this.setTable_('gpu-memory-buffer-info', []);
+
+ if (gpuInfo.displayInfo)
+ this.setTable_('display-info', gpuInfo.displayInfo);
+ else
+ this.setTable_('display-info', []);
+
+ if (gpuInfo.videoAcceleratorsInfo) {
+ this.setTable_(
+ 'video-acceleration-info', gpuInfo.videoAcceleratorsInfo);
+ } else {
+ this.setTable_('video-acceleration-info', []);
+ }
+
+ if (gpuInfo.diagnostics) {
+ diagnosticsDiv.hidden = false;
+ diagnosticsLoadingDiv.hidden = true;
+ $('diagnostics-table').hidden = false;
+ this.setTable_('diagnostics-table', gpuInfo.diagnostics);
+ } else if (gpuInfo.diagnostics === null) {
+ // gpu_internals.cc sets diagnostics to null when it is being loaded
+ diagnosticsDiv.hidden = false;
+ diagnosticsLoadingDiv.hidden = false;
+ $('diagnostics-table').hidden = true;
+ } else {
+ diagnosticsDiv.hidden = true;
+ }
+ } else {
+ this.setText_('basic-info', '... loading ...');
+ diagnosticsDiv.hidden = true;
+ featureStatusList.textContent = '';
+ problemsDiv.hidden = true;
+ }
+
+ // Log messages
+ jstProcess(new JsEvalContext({values: browserBridge.logMessages}),
+ $('log-messages'));
+ },
+
+ appendFeatureInfo_: function(featureInfo, featureStatusList,
+ problemsDiv, problemsList,
+ workaroundsDiv, workaroundsList) {
// Feature map
var featureLabelMap = {
'2d_canvas': 'Canvas',
@@ -113,11 +232,13 @@ cr.define('gpu', function() {
'rasterization': 'Rasterization',
'multiple_raster_threads': 'Multiple Raster Threads',
'native_gpu_memory_buffers': 'Native GpuMemoryBuffers',
+ 'protected_video_decode': 'Hardware Protected Video Decode',
'surface_synchronization': 'Surface Synchronization',
'vpx_decode': 'VPx Video Decode',
'webgl2': 'WebGL2',
- 'checker_imaging': 'CheckerImaging',
'viz_display_compositor': 'Viz Service Display Compositor',
+ 'skia_renderer': 'Skia Renderer',
+ 'skia_deferred_display_list': 'Skia Deferred Display List',
};
var statusMap = {
@@ -167,130 +288,58 @@ cr.define('gpu', function() {
},
};
- // GPU info, basic
- var diagnosticsDiv = this.querySelector('.diagnostics');
- var diagnosticsLoadingDiv = this.querySelector('.diagnostics-loading');
- var featureStatusList = this.querySelector('.feature-status-list');
- var problemsDiv = this.querySelector('.problems-div');
- var problemsList = this.querySelector('.problems-list');
- var workaroundsDiv = this.querySelector('.workarounds-div');
- var workaroundsList = this.querySelector('.workarounds-list');
- var gpuInfo = browserBridge.gpuInfo;
- var i;
- if (gpuInfo) {
- // Not using jstemplate here for blacklist status because we construct
- // href from data, which jstemplate can't seem to do.
- if (gpuInfo.featureStatus) {
- // feature status list
- featureStatusList.textContent = '';
- for (var featureName in gpuInfo.featureStatus.featureStatus) {
- var featureStatus =
- gpuInfo.featureStatus.featureStatus[featureName];
- var featureEl = document.createElement('li');
-
- var nameEl = document.createElement('span');
- if (!featureLabelMap[featureName])
- console.log('Missing featureLabel for', featureName);
- nameEl.textContent = featureLabelMap[featureName] + ': ';
- featureEl.appendChild(nameEl);
-
- var statusEl = document.createElement('span');
- var statusInfo = statusMap[featureStatus];
- if (!statusInfo) {
- console.log('Missing status for ', featureStatus);
- statusEl.textContent = 'Unknown';
- statusEl.className = 'feature-red';
- } else {
- statusEl.textContent = statusInfo['label'];
- statusEl.className = statusInfo['class'];
- }
- featureEl.appendChild(statusEl);
-
- featureStatusList.appendChild(featureEl);
- }
-
- // problems list
- if (gpuInfo.featureStatus.problems.length) {
- problemsDiv.hidden = false;
- problemsList.textContent = '';
- for (i = 0; i < gpuInfo.featureStatus.problems.length; i++) {
- var problem = gpuInfo.featureStatus.problems[i];
- var problemEl = this.createProblemEl_(problem);
- problemsList.appendChild(problemEl);
- }
- } else {
- problemsDiv.hidden = true;
- }
-
- // driver bug workarounds list
- if (gpuInfo.featureStatus.workarounds.length) {
- workaroundsDiv.hidden = false;
- workaroundsList.textContent = '';
- for (i = 0; i < gpuInfo.featureStatus.workarounds.length; i++) {
- var workaroundEl = document.createElement('li');
- workaroundEl.textContent = gpuInfo.featureStatus.workarounds[i];
- workaroundsList.appendChild(workaroundEl);
- }
- } else {
- workaroundsDiv.hidden = true;
- }
-
+ // feature status list
+ featureStatusList.textContent = '';
+ for (var featureName in featureInfo.featureStatus) {
+ var featureStatus = featureInfo.featureStatus[featureName];
+ var featureEl = document.createElement('li');
+
+ var nameEl = document.createElement('span');
+ if (!featureLabelMap[featureName])
+ console.log('Missing featureLabel for', featureName);
+ nameEl.textContent = featureLabelMap[featureName] + ': ';
+ featureEl.appendChild(nameEl);
+
+ var statusEl = document.createElement('span');
+ var statusInfo = statusMap[featureStatus];
+ if (!statusInfo) {
+ console.log('Missing status for ', featureStatus);
+ statusEl.textContent = 'Unknown';
+ statusEl.className = 'feature-red';
} else {
- featureStatusList.textContent = '';
- problemsList.hidden = true;
- workaroundsList.hidden = true;
+ statusEl.textContent = statusInfo['label'];
+ statusEl.className = statusInfo['class'];
}
+ featureEl.appendChild(statusEl);
- if (gpuInfo.basic_info)
- this.setTable_('basic-info', gpuInfo.basic_info);
- else
- this.setTable_('basic-info', []);
-
- if (gpuInfo.compositorInfo)
- this.setTable_('compositor-info', gpuInfo.compositorInfo);
- else
- this.setTable_('compositor-info', []);
-
- if (gpuInfo.gpuMemoryBufferInfo)
- this.setTable_('gpu-memory-buffer-info', gpuInfo.gpuMemoryBufferInfo);
- else
- this.setTable_('gpu-memory-buffer-info', []);
-
- if (gpuInfo.displayInfo)
- this.setTable_('display-info', gpuInfo.displayInfo);
- else
- this.setTable_('display-info', []);
+ featureStatusList.appendChild(featureEl);
+ }
- if (gpuInfo.videoAcceleratorsInfo) {
- this.setTable_(
- 'video-acceleration-info', gpuInfo.videoAcceleratorsInfo);
- } else {
- this.setTable_('video-acceleration-info', []);
- }
-
- if (gpuInfo.diagnostics) {
- diagnosticsDiv.hidden = false;
- diagnosticsLoadingDiv.hidden = true;
- $('diagnostics-table').hidden = false;
- this.setTable_('diagnostics-table', gpuInfo.diagnostics);
- } else if (gpuInfo.diagnostics === null) {
- // gpu_internals.cc sets diagnostics to null when it is being loaded
- diagnosticsDiv.hidden = false;
- diagnosticsLoadingDiv.hidden = false;
- $('diagnostics-table').hidden = true;
- } else {
- diagnosticsDiv.hidden = true;
+ // problems list
+ if (featureInfo.problems.length) {
+ problemsDiv.hidden = false;
+ problemsList.textContent = '';
+ for (i = 0; i < featureInfo.problems.length; i++) {
+ var problem = featureInfo.problems[i];
+ var problemEl = this.createProblemEl_(problem);
+ problemsList.appendChild(problemEl);
}
} else {
- this.setText_('basic-info', '... loading ...');
- diagnosticsDiv.hidden = true;
- featureStatusList.textContent = '';
problemsDiv.hidden = true;
}
- // Log messages
- jstProcess(new JsEvalContext({values: browserBridge.logMessages}),
- $('log-messages'));
+ // driver bug workarounds list
+ if (featureInfo.workarounds.length) {
+ workaroundsDiv.hidden = false;
+ workaroundsList.textContent = '';
+ for (i = 0; i < featureInfo.workarounds.length; i++) {
+ var workaroundEl = document.createElement('li');
+ workaroundEl.textContent = featureInfo.workarounds[i];
+ workaroundsList.appendChild(workaroundEl);
+ }
+ } else {
+ workaroundsDiv.hidden = true;
+ }
},
createProblemEl_: function(problem) {
diff --git a/chromium/content/browser/resources/histograms/BUILD.gn b/chromium/content/browser/resources/histograms/BUILD.gn
new file mode 100644
index 00000000000..9b67dcd52b2
--- /dev/null
+++ b/chromium/content/browser/resources/histograms/BUILD.gn
@@ -0,0 +1,18 @@
+# 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("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":histograms_internals",
+ ]
+}
+
+js_library("histograms_internals") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:util",
+ ]
+}
diff --git a/chromium/content/browser/resources/histograms/OWNERS b/chromium/content/browser/resources/histograms/OWNERS
new file mode 100644
index 00000000000..a6565c5a54c
--- /dev/null
+++ b/chromium/content/browser/resources/histograms/OWNERS
@@ -0,0 +1 @@
+asvitkine@chromium.org \ No newline at end of file
diff --git a/chromium/content/browser/resources/histograms/histograms_internals.html b/chromium/content/browser/resources/histograms/histograms_internals.html
new file mode 100644
index 00000000000..5fd6ebfb75b
--- /dev/null
+++ b/chromium/content/browser/resources/histograms/histograms_internals.html
@@ -0,0 +1,18 @@
+<!-- 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.-->
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+ <meta charset="utf-8">
+ <script src="chrome://resources/js/cr.js"></script>
+ <script src="chrome://resources/js/promise_resolver.js"></script>
+ <script src="chrome://resources/js/util.js"></script>
+ <script src="histograms_internals.js"></script>
+ <title>📊 About Histograms</title>
+</head>
+<p>Stats accumulated from browser startup to previous page load; reload to get stats as of this page load.
+</p>
+<button id="refresh">Refresh</button>
+<div id="histograms"></div>
+</html>
diff --git a/chromium/content/browser/resources/histograms/histograms_internals.js b/chromium/content/browser/resources/histograms/histograms_internals.js
new file mode 100644
index 00000000000..428fc36261f
--- /dev/null
+++ b/chromium/content/browser/resources/histograms/histograms_internals.js
@@ -0,0 +1,37 @@
+// 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.
+
+/**
+ * Initiates the request for histograms.
+ */
+function requestHistograms() {
+ let query = '';
+ if (document.location.pathname)
+ query = document.location.pathname.substring(1);
+ cr.sendWithPromise('requestHistograms', query).then(addHistograms);
+}
+
+/**
+ * Callback from backend with the list of histograms. Builds the UI.
+ * @param {!Array<string>} histograms A list of trusted HTML strings
+ * representing histograms.
+ */
+function addHistograms(histograms) {
+ let htmlOutput = '';
+ for (let histogram of histograms)
+ htmlOutput += histogram;
+
+ // NOTE: This is generally unsafe due to XSS attacks. Make sure |htmlOutput|
+ // cannot be modified by an external party.
+ $('histograms').innerHTML = htmlOutput;
+}
+
+/**
+ * Load the initial list of histograms.
+ */
+document.addEventListener('DOMContentLoaded', function() {
+ $('refresh').onclick = requestHistograms;
+
+ requestHistograms();
+});
diff --git a/chromium/content/browser/resources/media/client_renderer.js b/chromium/content/browser/resources/media/client_renderer.js
index acc8ef28a4d..0b5413e8ae7 100644
--- a/chromium/content/browser/resources/media/client_renderer.js
+++ b/chromium/content/browser/resources/media/client_renderer.js
@@ -67,7 +67,7 @@ var ClientRenderer = (function() {
while (element.hasChildNodes()) {
element.removeChild(element.lastChild);
}
- };
+ }
function createSelectableButton(id, groupName, buttonLabel, select_cb,
isDestructed) {
@@ -94,7 +94,7 @@ var ClientRenderer = (function() {
});
return fragment;
- };
+ }
function selectSelectableButton(id) {
var element = document.getElementById(id);
@@ -208,7 +208,7 @@ var ClientRenderer = (function() {
table.appendChild(thead);
var tbody = document.createElement('tbody');
for (var i=0; i < formats.length; ++i) {
- var tr = document.createElement('tr')
+ var tr = document.createElement('tr');
for (var key in formats[i]) {
var td = document.createElement('td');
td.appendChild(document.createTextNode(formats[i][key]));
@@ -245,7 +245,7 @@ var ClientRenderer = (function() {
cellElement = document.createTextNode(
((typeof value) == 'undefined') ? 'n/a' : value);
}
- tableCell.appendChild(cellElement)
+ tableCell.appendChild(cellElement);
tableRow.appendChild(tableCell);
}
videoTableBodyElement.appendChild(tableRow);
@@ -263,7 +263,7 @@ var ClientRenderer = (function() {
baseName = 'Stream';
break;
default:
- baseName = 'UnknownType'
+ baseName = 'UnknownType';
console.error('Unrecognized component type: ' + componentType);
break;
}
@@ -377,7 +377,7 @@ var ClientRenderer = (function() {
label.appendChild(frame_node);
}
- var desc = []
+ var desc = [];
if (p.width && p.height)
desc.push(p.width + 'x' + p.height);
if (p.video_codec_name)
@@ -468,7 +468,7 @@ var ClientRenderer = (function() {
},
saveLog_: function() {
- var strippedPlayers = []
+ var strippedPlayers = [];
for (var id in this.players) {
var p = this.players[id];
strippedPlayers.push({properties: p.properties, events: p.allEvents});
diff --git a/chromium/content/browser/resources/media/main.js b/chromium/content/browser/resources/media/main.js
index e6c9d8ccf14..add25a1fc38 100644
--- a/chromium/content/browser/resources/media/main.js
+++ b/chromium/content/browser/resources/media/main.js
@@ -24,8 +24,8 @@ var media = (function() {
};
media.onReceiveVideoCaptureCapabilities = function(videoCaptureCapabilities) {
- manager.updateVideoCaptureCapabilities(videoCaptureCapabilities)
- }
+ manager.updateVideoCaptureCapabilities(videoCaptureCapabilities);
+ };
media.updateAudioComponent = function(component) {
var uniqueComponentId = component.owner_id + ':' + component.component_id;
diff --git a/chromium/content/browser/resources/media/peer_connection_update_table.js b/chromium/content/browser/resources/media/peer_connection_update_table.js
index 4dcc476e90b..09998a6bf7d 100644
--- a/chromium/content/browser/resources/media/peer_connection_update_table.js
+++ b/chromium/content/browser/resources/media/peer_connection_update_table.js
@@ -128,7 +128,7 @@ var PeerConnectionUpdateTable = (function() {
'update-log-legacy-api-usage');
valueContainer.parentElement.title = update.type + ' is no longer ' +
'part of the WebRTC API and may be removed in future versions. ' +
- 'Use the addTrack/removeTrack APIs instead.'
+ 'Use the addTrack/removeTrack APIs instead.';
}
var value = update.value;
diff --git a/chromium/content/browser/resources/media/ssrc_info_manager.js b/chromium/content/browser/resources/media/ssrc_info_manager.js
index 6db5687c76a..2b47c8afe73 100644
--- a/chromium/content/browser/resources/media/ssrc_info_manager.js
+++ b/chromium/content/browser/resources/media/ssrc_info_manager.js
@@ -34,7 +34,7 @@ function GetSsrcFromReport(report) {
}
}
return report.id;
-};
+}
/**
* SsrcInfoManager stores the ssrc stream info extracted from SDP.
diff --git a/chromium/content/browser/resources/media/stats_table.js b/chromium/content/browser/resources/media/stats_table.js
index 53e71a209fa..8ad8f54d631 100644
--- a/chromium/content/browser/resources/media/stats_table.js
+++ b/chromium/content/browser/resources/media/stats_table.js
@@ -133,6 +133,7 @@ var StatsTable = (function(ssrcInfoManager) {
updateStatsTableRow_: function(statsTable, rowName, value) {
var trId = statsTable.id + '-' + rowName;
var trElement = $(trId);
+ var activeConnectionClass = 'stats-table-active-connection';
if (!trElement) {
trElement = document.createElement('tr');
trElement.id = trId;
@@ -142,8 +143,13 @@ var StatsTable = (function(ssrcInfoManager) {
trElement.cells[1].textContent = value;
// Highlights the table for the active connection.
- if (rowName == 'googActiveConnection' && value == true)
- statsTable.parentElement.classList.add('stats-table-active-connection');
+ if (rowName == 'googActiveConnection') {
+ if (value === true) {
+ statsTable.parentElement.classList.add(activeConnectionClass);
+ } else {
+ statsTable.parentElement.classList.remove(activeConnectionClass);
+ }
+ }
}
};
diff --git a/chromium/content/browser/resources/media/timeline_graph_view.js b/chromium/content/browser/resources/media/timeline_graph_view.js
index d2b12329da2..157ad392ebc 100644
--- a/chromium/content/browser/resources/media/timeline_graph_view.js
+++ b/chromium/content/browser/resources/media/timeline_graph_view.js
@@ -149,9 +149,13 @@ var TimelineGraphView = (function() {
},
/**
- * Draws the graph on |canvas_|.
+ * Draws the graph on |canvas_| when visible.
*/
repaint: function() {
+ if (this.canvas_.offsetParent === null) {
+ return; // do not repaint graphs that are not visible.
+ }
+
this.repaintTimerRunning_ = false;
var width = this.canvas_.width;
diff --git a/chromium/content/browser/resources/media/webrtc_internals.js b/chromium/content/browser/resources/media/webrtc_internals.js
index 4f5fc0d971a..f41067a12de 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.js
+++ b/chromium/content/browser/resources/media/webrtc_internals.js
@@ -26,7 +26,7 @@ var PeerConnectionRecord = (function() {
updateLog: [],
url: '',
};
- };
+ }
PeerConnectionRecord.prototype = {
/** @override */
diff --git a/chromium/content/browser/resources/process/process_internals.html b/chromium/content/browser/resources/process/process_internals.html
new file mode 100644
index 00000000000..9e5acb2d80a
--- /dev/null
+++ b/chromium/content/browser/resources/process/process_internals.html
@@ -0,0 +1,16 @@
+<!-- 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.-->
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+ <script src="chrome://resources/js/mojo_bindings.js"></script>
+ <script src="process_internals.mojom.js"></script>
+ <script src='process_internals.js'></script>
+ <title>Process Model Internals</title>
+</head>
+<div id="site-isolation-mode">Site Isolation mode: <span id='isolation-mode'>unknown</span></div>
+<div id="isolated-origins-container">Isolated origins: <span id='isolated-origins'></span></div>
+</html>
diff --git a/chromium/content/browser/resources/process/process_internals.js b/chromium/content/browser/resources/process/process_internals.js
new file mode 100644
index 00000000000..a745e29b6ec
--- /dev/null
+++ b/chromium/content/browser/resources/process/process_internals.js
@@ -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.
+
+console.log('process internals initializing');
+
+(function() {
+'use strict';
+
+/**
+ * Reference to the backend.
+ * @type {mojom.ProcessInternalsHandlerPtr}
+ */
+var uiHandler = null;
+
+document.addEventListener('DOMContentLoaded', function() {
+ // Setup Mojo interface to the backend.
+ uiHandler = new mojom.ProcessInternalsHandlerPtr;
+ Mojo.bindInterface(
+ mojom.ProcessInternalsHandler.name,
+ mojo.makeRequest(uiHandler).handle);
+
+ // Get the Site Isolation mode and populate it.
+ uiHandler.getIsolationMode().then((response) => {
+ document.getElementById('isolation-mode').innerText = response.mode;
+ });
+ uiHandler.getIsolatedOrigins().then((response) => {
+ document.getElementById('isolated-origins').innerText =
+ response.isolatedOrigins.join(', ');
+ });
+});
+
+})();
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.js b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
index 087c5a65cf7..810676ab9d1 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.js
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
@@ -220,7 +220,7 @@ cr.define('serviceworker', function() {
update();
}
- function onRegistrationStored(scope) {
+ function onRegistrationCompleted(scope) {
update();
}
@@ -258,7 +258,7 @@ cr.define('serviceworker', function() {
onErrorReported: onErrorReported,
onConsoleMessageReported: onConsoleMessageReported,
onVersionStateChanged: onVersionStateChanged,
- onRegistrationStored: onRegistrationStored,
+ onRegistrationCompleted: onRegistrationCompleted,
onRegistrationDeleted: onRegistrationDeleted,
};
});
diff --git a/chromium/content/browser/sandbox_parameters_mac.mm b/chromium/content/browser/sandbox_parameters_mac.mm
index a87788c2820..e9415b0de5f 100644
--- a/chromium/content/browser/sandbox_parameters_mac.mm
+++ b/chromium/content/browser/sandbox_parameters_mac.mm
@@ -22,6 +22,7 @@
#include "content/public/common/pepper_plugin_info.h"
#include "sandbox/mac/seatbelt_exec.h"
#include "services/service_manager/sandbox/mac/sandbox_mac.h"
+#include "services/service_manager/sandbox/switches.h"
namespace content {
@@ -48,7 +49,7 @@ void SetupCommonSandboxParameters(sandbox::SeatbeltExecClient* client) {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
bool enable_logging =
- command_line->HasSwitch(switches::kEnableSandboxLogging);
+ command_line->HasSwitch(service_manager::switches::kEnableSandboxLogging);
CHECK(client->SetBooleanParameter(
service_manager::SandboxMac::kSandboxEnableLogging, enable_logging));
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h
index bf9d91c31b5..120700af9fc 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "content/public/browser/screen_orientation_delegate.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
namespace content {
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider.cc b/chromium/content/browser/screen_orientation/screen_orientation_provider.cc
index 5d96c58eddc..8f1a0a31f05 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_provider.cc
@@ -13,7 +13,6 @@
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/screen_orientation_delegate.h"
#include "content/public/browser/web_contents.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_lock_orientation_error.h"
namespace content {
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider.h b/chromium/content/browser/screen_orientation/screen_orientation_provider.h
index 6ff35095bc1..9d16e0fef42 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider.h
+++ b/chromium/content/browser/screen_orientation/screen_orientation_provider.h
@@ -14,7 +14,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "services/device/public/mojom/screen_orientation.mojom.h"
#include "services/device/public/mojom/screen_orientation_lock_types.mojom.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
namespace content {
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider_unittest.cc b/chromium/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
index 97e3b3ecf6a..64c4cacf214 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
@@ -11,7 +11,7 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
namespace content {
@@ -59,8 +59,10 @@ class FakeWebContentsDelegate : public WebContentsDelegate {
FakeWebContentsDelegate() = default;
~FakeWebContentsDelegate() override = default;
- void EnterFullscreenModeForTab(WebContents* web_contents,
- const GURL& origin) override {
+ void EnterFullscreenModeForTab(
+ WebContents* web_contents,
+ const GURL& origin,
+ const blink::WebFullscreenOptions& options) override {
fullscreened_contents_ = web_contents;
}
@@ -179,8 +181,8 @@ TEST_F(ScreenOrientationProviderTest, DelegateRequireFullScreenLockOnce) {
EXPECT_EQ(0, delegate.lock_count());
// Simulates entering full screen.
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_ToggleFullscreen(main_test_rfh()->GetRoutingID(), true));
+ main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
+ main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
ASSERT_TRUE(contents()->IsFullscreenForCurrentTab());
base::Optional<ScreenOrientationLockResult> result_2;
@@ -282,8 +284,8 @@ TEST_F(ScreenOrientationProviderTest, UnlockWhenExitingFullScreen) {
std::string());
// Simulates entering full screen.
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_ToggleFullscreen(main_test_rfh()->GetRoutingID(), true));
+ main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
+ main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
ASSERT_TRUE(contents()->IsFullscreenForCurrentTab());
base::Optional<ScreenOrientationLockResult> result;
@@ -298,7 +300,7 @@ TEST_F(ScreenOrientationProviderTest, UnlockWhenExitingFullScreen) {
// Simulates exiting full screen.
main_test_rfh()->OnMessageReceived(
- FrameHostMsg_ToggleFullscreen(main_test_rfh()->GetRoutingID(), false));
+ FrameHostMsg_ExitFullscreen(main_test_rfh()->GetRoutingID()));
ASSERT_FALSE(contents()->IsFullscreenForCurrentTab());
// The pending lock request is cancelled.
EXPECT_EQ(ScreenOrientationLockResult::
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index 637fae1bf91..9c298b18244 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -104,7 +104,7 @@ RenderFrameHostImpl* PrepareToDuplicateHosts(Shell* shell,
wc->GetFrameTree()->root()->current_frame_host(), extension_url, false,
nullptr, std::string(), Referrer(), WindowOpenDisposition::CURRENT_TAB,
false, true, blink::WebTriggeringEventInfo::kFromTrustedEvent,
- base::nullopt);
+ nullptr /* blob_url_loader_factory */);
// Since the navigation above requires a cross-process swap, there will be a
// speculative/pending RenderFrameHost. Ensure it exists and is in a different
@@ -211,7 +211,8 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) {
NavigateToURL(shell, GURL("http://foo.com/simple_page.html"));
- RenderFrameHost* rfh = shell->web_contents()->GetMainFrame();
+ RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
+ shell->web_contents()->GetMainFrame());
if (block_loaders) {
// Test the case where loaders are placed into blocked_loaders_map_.
diff --git a/chromium/content/browser/service_manager/common_browser_interfaces.cc b/chromium/content/browser/service_manager/common_browser_interfaces.cc
index 55e52930552..af1a24e735b 100644
--- a/chromium/content/browser/service_manager/common_browser_interfaces.cc
+++ b/chromium/content/browser/service_manager/common_browser_interfaces.cc
@@ -44,7 +44,7 @@ class ConnectionFilterImpl : public ConnectionFilter {
#elif defined(OS_MACOSX)
registry_.AddInterface(base::BindRepeating(&FontLoaderDispatcher::Create));
#endif
- if (!features::IsMusEnabled()) {
+ if (!features::IsMashEnabled()) {
// For mus, the mojom::discardable_memory::DiscardableSharedMemoryManager
// is exposed from ui::Service. So we don't need bind the interface here.
auto* browser_main_loop = BrowserMainLoop::GetInstance();
diff --git a/chromium/content/browser/service_manager/service_manager_context.cc b/chromium/content/browser/service_manager/service_manager_context.cc
index cc276364172..6df4527d9a4 100644
--- a/chromium/content/browser/service_manager/service_manager_context.cc
+++ b/chromium/content/browser/service_manager/service_manager_context.cc
@@ -91,14 +91,6 @@
#include "ui/aura/env.h"
#endif
-#if BUILDFLAG(ENABLE_MUS)
-#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
-#include "content/public/browser/discardable_shared_memory_manager.h"
-#include "services/ui/common/image_cursors_set.h"
-#include "services/ui/public/interfaces/constants.mojom.h"
-#include "services/ui/service.h"
-#endif
-
namespace content {
namespace {
@@ -263,6 +255,25 @@ class NullServiceProcessLauncherFactory
DISALLOW_COPY_AND_ASSIGN(NullServiceProcessLauncherFactory);
};
+// This class is intended for tests that want to load service binaries (rather
+// than via the utility process). Production code uses
+// NullServiceProcessLauncherFactory.
+class ServiceBinaryLauncherFactory
+ : public service_manager::ServiceProcessLauncherFactory {
+ public:
+ ServiceBinaryLauncherFactory() = default;
+ ~ServiceBinaryLauncherFactory() override = default;
+
+ private:
+ std::unique_ptr<service_manager::ServiceProcessLauncher> Create(
+ const base::FilePath& service_path) override {
+ return std::make_unique<service_manager::ServiceProcessLauncher>(
+ nullptr, service_path);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceBinaryLauncherFactory);
+};
+
// Helper to invoke GetGeolocationRequestContext on the currently-set
// ContentBrowserClient.
void GetGeolocationRequestContextFromContentClient(
@@ -282,44 +293,6 @@ bool ShouldEnableVizService() {
#endif
}
-#if BUILDFLAG(ENABLE_MUS)
-std::unique_ptr<service_manager::Service> CreateEmbeddedUIService(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr,
- discardable_memory::DiscardableSharedMemoryManager* memory_manager) {
- ui::Service::InitParams params;
- params.running_standalone = false;
- params.resource_runner = task_runner;
- params.image_cursors_set_weak_ptr = image_cursors_set_weak_ptr;
- params.memory_manager = memory_manager;
- params.should_host_viz = base::FeatureList::IsEnabled(features::kMash);
- return std::make_unique<ui::Service>(params);
-}
-
-void RegisterUIServiceInProcessIfNecessary(
- ServiceManagerConnection* connection) {
- // Some tests don't create BrowserMainLoop.
- if (!BrowserMainLoop::GetInstance())
- return;
- // Do not embed the UI service when running in mash.
- if (base::FeatureList::IsEnabled(features::kMash))
- return;
- // Do not embed the UI service if not running with mus.
- if (!features::IsMusEnabled())
- return;
-
- service_manager::EmbeddedServiceInfo info;
- info.factory = base::Bind(
- &CreateEmbeddedUIService, base::ThreadTaskRunnerHandle::Get(),
- BrowserMainLoop::GetInstance()->image_cursors_set()->GetWeakPtr(),
- GetDiscardableSharedMemoryManager());
- info.use_own_thread = true;
- info.message_loop_type = base::MessageLoop::TYPE_UI;
- info.thread_priority = base::ThreadPriority::DISPLAY;
- connection->AddEmbeddedService(ui::mojom::kServiceName, info);
-}
-#endif
-
std::unique_ptr<service_manager::Service> CreateNetworkService() {
// The test interface doesn't need to be implemented in the in-process case.
auto registry = std::make_unique<service_manager::BinderRegistry>();
@@ -364,8 +337,18 @@ class ServiceManagerContext::InProcessServiceManagerContext
std::unique_ptr<BuiltinManifestProvider> manifest_provider,
service_manager::mojom::ServicePtrInfo packaged_services_service_info) {
manifest_provider_ = std::move(manifest_provider);
+ std::unique_ptr<service_manager::ServiceProcessLauncherFactory>
+ service_process_launcher_factory;
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableServiceBinaryLauncher)) {
+ service_process_launcher_factory =
+ std::make_unique<ServiceBinaryLauncherFactory>();
+ } else {
+ service_process_launcher_factory =
+ std::make_unique<NullServiceProcessLauncherFactory>();
+ }
service_manager_ = std::make_unique<service_manager::ServiceManager>(
- std::make_unique<NullServiceProcessLauncherFactory>(), nullptr,
+ std::move(service_process_launcher_factory), nullptr,
manifest_provider_.get());
service_manager::mojom::ServicePtr packaged_services_service;
@@ -541,29 +524,14 @@ ServiceManagerContext::ServiceManagerContext() {
metrics::mojom::kMetricsServiceName, info);
}
- if (BrowserMainLoop* bml = BrowserMainLoop::GetInstance()) {
- service_manager::EmbeddedServiceInfo info;
- info.factory = base::BindRepeating(
- [](BrowserMainLoop* bml) -> std::unique_ptr<service_manager::Service> {
- return audio::CreateEmbeddedService(bml->audio_manager());
- },
- bml);
- info.task_runner = bml->audio_service_runner();
- packaged_services_connection_->AddEmbeddedService(
- audio::mojom::kServiceName, info);
- }
-
ContentBrowserClient::StaticServiceMap services;
- GetContentClient()->browser()->RegisterInProcessServices(&services);
+ GetContentClient()->browser()->RegisterInProcessServices(
+ &services, packaged_services_connection_.get());
for (const auto& entry : services) {
packaged_services_connection_->AddEmbeddedService(entry.first,
entry.second);
}
-#if BUILDFLAG(ENABLE_MUS)
- RegisterUIServiceInProcessIfNecessary(packaged_services_connection_.get());
-#endif
-
// This is safe to assign directly from any thread, because
// ServiceManagerContext must be constructed before anyone can call
// GetConnectorForIOThread().
@@ -600,6 +568,26 @@ ServiceManagerContext::ServiceManagerContext() {
GetNetworkService();
}
+ if (BrowserMainLoop* bml = BrowserMainLoop::GetInstance()) {
+ if (bml->AudioServiceOutOfProcess()) {
+ DCHECK(base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams));
+ out_of_process_services[audio::mojom::kServiceName] =
+ base::ASCIIToUTF16("Audio Service");
+ } else {
+ service_manager::EmbeddedServiceInfo info;
+ info.factory = base::BindRepeating(
+ [](BrowserMainLoop* bml)
+ -> std::unique_ptr<service_manager::Service> {
+ return audio::CreateEmbeddedService(bml->audio_manager());
+ },
+ bml);
+ info.task_runner = bml->audio_service_runner();
+ DCHECK(info.task_runner);
+ packaged_services_connection_->AddEmbeddedService(
+ audio::mojom::kServiceName, info);
+ }
+ }
+
if (features::IsVideoCaptureServiceEnabledForOutOfProcess()) {
out_of_process_services[video_capture::mojom::kServiceName] =
base::ASCIIToUTF16("Video Capture Service");
diff --git a/chromium/content/browser/service_worker/OWNERS b/chromium/content/browser/service_worker/OWNERS
index c19a2565fc3..a0d918100a0 100644
--- a/chromium/content/browser/service_worker/OWNERS
+++ b/chromium/content/browser/service_worker/OWNERS
@@ -15,7 +15,6 @@ falken@chromium.org
horo@chromium.org
kinuko@chromium.org
mek@chromium.org
-michaeln@chromium.org
nhiroki@chromium.org
shimazu@chromium.org
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index 19d8459d972..eef43481a14 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind_helpers.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
@@ -16,10 +17,13 @@
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_content_settings_proxy_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/url_loader_factory_getter.h"
#include "content/common/content_switches_internal.h"
#include "content/common/renderer.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/common/url_loader_factory_bundle.mojom.h"
+#include "content/common/url_schemes.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
@@ -27,6 +31,8 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_message.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "url/gurl.h"
@@ -76,30 +82,34 @@ using SetupProcessCallback = base::OnceCallback<void(
ServiceWorkerStatusCode,
mojom::EmbeddedWorkerStartParamsPtr,
std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>,
- std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy)>;
+ std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy>,
+ std::unique_ptr<URLLoaderFactoryBundleInfo>,
+ blink::mojom::CacheStoragePtrInfo)>;
// Allocates a renderer process for starting a worker and does setup like
// registering with DevTools. Called on the UI thread. Calls |callback| on the
// IO thread. |context| and |weak_context| are only for passing to DevTools and
// must not be dereferenced here on the UI thread.
-void SetupOnUIThread(
- base::WeakPtr<ServiceWorkerProcessManager> process_manager,
- bool can_use_existing_process,
- mojom::EmbeddedWorkerStartParamsPtr params,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request,
- ServiceWorkerContextCore* context,
- base::WeakPtr<ServiceWorkerContextCore> weak_context,
- SetupProcessCallback callback) {
+void SetupOnUIThread(base::WeakPtr<ServiceWorkerProcessManager> process_manager,
+ bool can_use_existing_process,
+ mojom::EmbeddedWorkerStartParamsPtr params,
+ mojom::EmbeddedWorkerInstanceClientRequest request,
+ ServiceWorkerContextCore* context,
+ base::WeakPtr<ServiceWorkerContextCore> weak_context,
+ SetupProcessCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto process_info =
std::make_unique<ServiceWorkerProcessManager::AllocatedProcessInfo>();
std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy;
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle;
+
if (!process_manager) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_ABORT,
std::move(params), std::move(process_info),
- std::move(devtools_proxy)));
+ std::move(devtools_proxy), std::move(factory_bundle),
+ nullptr /* cache_storage */));
return;
}
@@ -111,7 +121,8 @@ void SetupOnUIThread(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), status, std::move(params),
- std::move(process_info), std::move(devtools_proxy)));
+ std::move(process_info), std::move(devtools_proxy),
+ std::move(factory_bundle), nullptr /* cache_storage */));
return;
}
const int process_id = process_info->process_id;
@@ -120,6 +131,19 @@ void SetupOnUIThread(
// crash reports agree. Consider also checking for rph->HasConnection().
CHECK(rph);
+ // Create cache storage now as an optimization, so the service worker can use
+ // the Cache Storage API immediately on startup. Don't do this when
+ // byte-to-byte check will be performed on the worker (|pause_after_download|)
+ // as most of those workers will have byte-to-byte equality and abort instead
+ // of running.
+ blink::mojom::CacheStoragePtr cache_storage;
+ if (base::FeatureList::IsEnabled(
+ blink::features::kEagerCacheStorageSetupForServiceWorkers) &&
+ !params->pause_after_download) {
+ rph->BindCacheStorage(mojo::MakeRequest(&cache_storage),
+ url::Origin::Create(params->script_url));
+ }
+
// Bind |request|, which is attached to |EmbeddedWorkerInstance::client_|, to
// the process. If the process dies, |client_|'s connection error callback
// will be called on the IO thread.
@@ -128,6 +152,37 @@ void SetupOnUIThread(
std::move(request));
}
+ // S13nServiceWorker:
+ // Create the loader factories for non-http(s) URLs, for example
+ // chrome-extension:// URLs. For performance, only do this step when the main
+ // script URL is non-http(s). We assume an http(s) service worker cannot
+ // importScripts a non-http(s) URL.
+ if (ServiceWorkerUtils::IsServicificationEnabled() &&
+ !params->script_url.SchemeIsHTTPOrHTTPS()) {
+ ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
+ GetContentClient()
+ ->browser()
+ ->RegisterNonNetworkSubresourceURLLoaderFactories(
+ rph->GetID(), MSG_ROUTING_NONE, &factories);
+
+ factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
+ for (auto& pair : factories) {
+ const std::string& scheme = pair.first;
+ std::unique_ptr<network::mojom::URLLoaderFactory> factory =
+ std::move(pair.second);
+
+ // To be safe, ignore schemes that aren't allowed to register service
+ // workers. We assume that importScripts should fail on such schemes.
+ if (!base::ContainsValue(GetServiceWorkerSchemes(), scheme))
+ continue;
+ network::mojom::URLLoaderFactoryPtr factory_ptr;
+ mojo::MakeStrongBinding(std::move(factory),
+ mojo::MakeRequest(&factory_ptr));
+ factory_bundle->factories_info().emplace(scheme,
+ factory_ptr.PassInterface());
+ }
+ }
+
// Register to DevTools and update params accordingly.
// TODO(dgozman): we can now remove this routing id and use something else
// as id when talking to ServiceWorkerDevToolsManager.
@@ -151,11 +206,12 @@ void SetupOnUIThread(
GetContentClient()->browser()->IsDataSaverEnabled(
process_manager->browser_context());
- // Continue on the IO thread.
+ // Continue to OnSetupCompleted on the IO thread.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(std::move(callback), status, std::move(params),
- std::move(process_info), std::move(devtools_proxy)));
+ std::move(process_info), std::move(devtools_proxy),
+ std::move(factory_bundle), cache_storage.PassInterface()));
}
bool HasSentStartWorker(EmbeddedWorkerInstance::StartingPhase phase) {
@@ -238,10 +294,11 @@ class EmbeddedWorkerInstance::DevToolsProxy {
// UI thread. Lives on the IO thread.
class EmbeddedWorkerInstance::WorkerProcessHandle {
public:
- WorkerProcessHandle(const base::WeakPtr<ServiceWorkerContextCore>& context,
- int embedded_worker_id,
- int process_id)
- : context_(context),
+ WorkerProcessHandle(
+ const base::WeakPtr<ServiceWorkerProcessManager>& process_manager,
+ int embedded_worker_id,
+ int process_id)
+ : process_manager_(process_manager),
embedded_worker_id_(embedded_worker_id),
process_id_(process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -250,19 +307,17 @@ class EmbeddedWorkerInstance::WorkerProcessHandle {
~WorkerProcessHandle() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!context_)
- return;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&ServiceWorkerProcessManager::ReleaseWorkerProcess,
- context_->process_manager()->AsWeakPtr(),
- embedded_worker_id_));
+ process_manager_, embedded_worker_id_));
}
int process_id() const { return process_id_; }
private:
- base::WeakPtr<ServiceWorkerContextCore> context_;
+ // Can be dereferenced on the UI thread only.
+ base::WeakPtr<ServiceWorkerProcessManager> process_manager_;
const int embedded_worker_id_;
const int process_id_;
@@ -282,7 +337,7 @@ class EmbeddedWorkerInstance::StartTask {
StartTask(EmbeddedWorkerInstance* instance,
const GURL& script_url,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request)
+ mojom::EmbeddedWorkerInstanceClientRequest request)
: instance_(instance),
request_(std::move(request)),
state_(ProcessAllocationState::NOT_ALLOCATED),
@@ -355,17 +410,19 @@ class EmbeddedWorkerInstance::StartTask {
DCHECK_EQ(params->embedded_worker_id, instance_->embedded_worker_id_);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "ALLOCATING_PROCESS",
this);
+ base::WeakPtr<ServiceWorkerContextCore> context = instance_->context_;
+ base::WeakPtr<ServiceWorkerProcessManager> process_manager =
+ context->process_manager()->AsWeakPtr();
+
// Hop to the UI thread for process allocation and setup. We will continue
// on the IO thread in StartTask::OnSetupCompleted().
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(&SetupOnUIThread,
- instance_->context_->process_manager()->AsWeakPtr(),
- can_use_existing_process, std::move(params),
- std::move(request_), instance_->context_.get(),
- instance_->context_,
- base::BindOnce(&StartTask::OnSetupCompleted,
- weak_factory_.GetWeakPtr())));
+ base::BindOnce(
+ &SetupOnUIThread, process_manager, can_use_existing_process,
+ std::move(params), std::move(request_), context.get(), context,
+ base::BindOnce(&StartTask::OnSetupCompleted,
+ weak_factory_.GetWeakPtr(), process_manager)));
}
static void RunStartCallback(StartTask* task,
@@ -384,12 +441,28 @@ class EmbeddedWorkerInstance::StartTask {
private:
void OnSetupCompleted(
+ base::WeakPtr<ServiceWorkerProcessManager> process_manager,
ServiceWorkerStatusCode status,
mojom::EmbeddedWorkerStartParamsPtr params,
std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>
process_info,
- std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy) {
+ std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle,
+ blink::mojom::CacheStoragePtrInfo cache_storage) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ std::unique_ptr<WorkerProcessHandle> process_handle;
+ if (status == SERVICE_WORKER_OK) {
+ // If we allocated a process, WorkerProcessHandle has to be created before
+ // returning to ensure the process is eventually released.
+ process_handle = std::make_unique<WorkerProcessHandle>(
+ process_manager, instance_->embedded_worker_id(),
+ process_info->process_id);
+
+ if (!instance_->context_)
+ status = SERVICE_WORKER_ERROR_ABORT;
+ }
+
if (status != SERVICE_WORKER_OK) {
TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "ALLOCATING_PROCESS",
this, "Error",
@@ -416,23 +489,38 @@ class EmbeddedWorkerInstance::StartTask {
// Notify the instance that a process is allocated.
state_ = ProcessAllocationState::ALLOCATED;
- instance_->OnProcessAllocated(
- std::make_unique<WorkerProcessHandle>(instance_->context_,
- instance_->embedded_worker_id(),
- process_info->process_id),
- start_situation);
+ instance_->OnProcessAllocated(std::move(process_handle), start_situation);
// Notify the instance that it is registered to the DevTools manager.
instance_->OnRegisteredToDevToolsManager(std::move(devtools_proxy),
params->wait_for_debugger);
- status = instance_->SendStartWorker(std::move(params));
- if (status != SERVICE_WORKER_OK) {
- StatusCallback callback = std::move(start_callback_);
- start_callback_.Reset();
- instance_->OnStartFailed(std::move(callback), status);
- // |this| may be destroyed.
+ // S13nServiceWorker: Build the URLLoaderFactory for loading new scripts.
+ scoped_refptr<network::SharedURLLoaderFactory> factory_for_new_scripts;
+ if (ServiceWorkerUtils::IsServicificationEnabled()) {
+ if (factory_bundle) {
+ network::mojom::URLLoaderFactoryPtr network_factory_ptr;
+ // The factory from CloneNetworkFactory() doesn't support reconnection
+ // to the network service after a crash, but it's probably OK since it's
+ // used for a single service worker startup until installation finishes
+ // (with the exception of https://crbug.com/719052).
+ instance_->context_->loader_factory_getter()->CloneNetworkFactory(
+ mojo::MakeRequest(&network_factory_ptr));
+ scoped_refptr<URLLoaderFactoryBundle> factory =
+ base::MakeRefCounted<URLLoaderFactoryBundle>(
+ std::move(factory_bundle));
+ factory->SetDefaultFactory(std::move(network_factory_ptr));
+ factory_for_new_scripts = std::move(factory);
+ } else {
+ factory_for_new_scripts =
+ instance_->context_->loader_factory_getter()->GetNetworkFactory();
+ }
}
+
+ instance_->SendStartWorker(std::move(params),
+ std::move(factory_for_new_scripts),
+ std::move(cache_storage));
+
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker",
"INITIALIZING_ON_RENDERER", this);
// |this|'s work is done here, but |instance_| still uses its state until
@@ -443,7 +531,7 @@ class EmbeddedWorkerInstance::StartTask {
EmbeddedWorkerInstance* instance_;
// Ownership is transferred by a PostTask() call after process allocation.
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request_;
+ mojom::EmbeddedWorkerInstanceClientRequest request_;
StatusCallback start_callback_;
ProcessAllocationState state_;
@@ -463,6 +551,8 @@ EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
DCHECK(status_ == EmbeddedWorkerStatus::STOPPING ||
status_ == EmbeddedWorkerStatus::STOPPED)
<< static_cast<int>(status_);
+ for (auto& observer : listener_list_)
+ observer.OnDestroyed();
devtools_proxy_.reset();
if (registry_->GetWorker(embedded_worker_id_))
registry_->RemoveWorker(process_id(), embedded_worker_id_);
@@ -498,7 +588,7 @@ void EmbeddedWorkerInstance::Start(mojom::EmbeddedWorkerStartParamsPtr params,
params->wait_for_debugger = false;
params->v8_cache_options = GetV8CacheOptions();
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request =
+ mojom::EmbeddedWorkerInstanceClientRequest request =
mojo::MakeRequest(&client_);
client_.set_connection_error_handler(
base::BindOnce(&EmbeddedWorkerInstance::Detach, base::Unretained(this)));
@@ -603,25 +693,13 @@ void EmbeddedWorkerInstance::OnRegisteredToDevToolsManager(
observer.OnRegisteredToDevToolsManager();
}
-ServiceWorkerStatusCode EmbeddedWorkerInstance::SendStartWorker(
- mojom::EmbeddedWorkerStartParamsPtr params) {
- if (!context_)
- return SERVICE_WORKER_ERROR_ABORT;
- if (!context_->GetDispatcherHost(process_id())) {
- // Check if there's a dispatcher host, which is a good sign the process is
- // still alive. It's possible that previously the process crashed, and the
- // Mojo connection error via |client_| detected it and this instance was
- // detached, but on restart ServiceWorkerProcessManager assigned us the
- // process again before RenderProcessHostImpl itself or
- // ServiceWorkerProcessManager knew it crashed, and by the time we get here
- // RenderProcessHostImpl::EnableSendQueue may have been called in
- // anticipation of the RPHI being reused for another renderer process, so
- // Mojo doesn't consider it an error. See https://crbug.com/732729.
- return SERVICE_WORKER_ERROR_IPC_FAILED;
- }
+void EmbeddedWorkerInstance::SendStartWorker(
+ mojom::EmbeddedWorkerStartParamsPtr params,
+ scoped_refptr<network::SharedURLLoaderFactory> factory,
+ blink::mojom::CacheStoragePtrInfo cache_storage) {
+ DCHECK(context_);
DCHECK(params->dispatcher_request.is_pending());
DCHECK(params->controller_request.is_pending());
- DCHECK(params->service_worker_host.is_valid());
DCHECK(!instance_host_binding_.is_bound());
instance_host_binding_.Bind(mojo::MakeRequest(&params->instance_host));
@@ -632,15 +710,12 @@ ServiceWorkerStatusCode EmbeddedWorkerInstance::SendStartWorker(
const bool is_script_streaming = !params->installed_scripts_info.is_null();
inflight_start_task_->set_start_worker_sent_time(base::TimeTicks::Now());
- params->provider_info = std::move(provider_info_getter_).Run(process_id());
+ params->provider_info =
+ std::move(provider_info_getter_).Run(process_id(), std::move(factory));
+ params->provider_info->cache_storage = std::move(cache_storage);
client_->StartWorker(std::move(params));
registry_->BindWorkerToProcess(process_id(), embedded_worker_id());
- OnStartWorkerMessageSent(is_script_streaming);
- return SERVICE_WORKER_OK;
-}
-void EmbeddedWorkerInstance::OnStartWorkerMessageSent(
- bool is_script_streaming) {
if (!step_time_.is_null()) {
base::TimeDelta duration = UpdateStepTime();
if (inflight_start_task_->is_installed()) {
@@ -874,11 +949,11 @@ int EmbeddedWorkerInstance::worker_devtools_agent_route_id() const {
return MSG_ROUTING_NONE;
}
-void EmbeddedWorkerInstance::AddListener(Listener* listener) {
+void EmbeddedWorkerInstance::AddObserver(Listener* listener) {
listener_list_.AddObserver(listener);
}
-void EmbeddedWorkerInstance::RemoveListener(Listener* listener) {
+void EmbeddedWorkerInstance::RemoveObserver(Listener* listener) {
listener_list_.RemoveObserver(listener);
}
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 5b6566ecb6d..2546eb0d4ae 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -31,6 +31,7 @@
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
#include "url/gurl.h"
namespace content {
@@ -73,7 +74,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
using ProviderInfoGetter =
base::OnceCallback<mojom::ServiceWorkerProviderInfoForStartWorkerPtr(
- int /* process_id */)>;
+ int /* process_id */,
+ scoped_refptr<network::SharedURLLoaderFactory>)>;
class Listener {
public:
@@ -113,6 +115,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
const base::string16& message,
int line_number,
const GURL& source_url) {}
+ // The instance is being deleted, so it's not safe to call any methods that
+ // may result in a virtual method call.
+ virtual void OnDestroyed() {}
};
~EmbeddedWorkerInstance() override;
@@ -160,8 +165,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
int thread_id() const { return thread_id_; }
int worker_devtools_agent_route_id() const;
- void AddListener(Listener* listener);
- void RemoveListener(Listener* listener);
+ void AddObserver(Listener* listener);
+ void RemoveObserver(Listener* listener);
void SetDevToolsAttached(bool attached);
bool devtools_attached() const { return devtools_attached_; }
@@ -236,12 +241,18 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
std::unique_ptr<DevToolsProxy> devtools_proxy,
bool wait_for_debugger);
- // Sends StartWorker message via Mojo.
- ServiceWorkerStatusCode SendStartWorker(
- mojom::EmbeddedWorkerStartParamsPtr params);
-
- // Called back from StartTask after a start worker message is sent.
- void OnStartWorkerMessageSent(bool is_script_streaming);
+ // Sends the StartWorker message to the renderer.
+ //
+ // |cache_storage| is an optional optimization so the service worker can
+ // use the Cache Storage API immediately upon startup.
+ //
+ // S13nServiceWorker:
+ // |factory| is used for loading non-installed scripts. It can internally be a
+ // bundle of factories instead of just the direct network factory to support
+ // non-NetworkService schemes like chrome-extension:// URLs.
+ void SendStartWorker(mojom::EmbeddedWorkerStartParamsPtr params,
+ scoped_refptr<network::SharedURLLoaderFactory> factory,
+ blink::mojom::CacheStoragePtrInfo cache_storage);
// Implements mojom::EmbeddedWorkerInstanceHost.
// These functions all run on the IO thread.
@@ -297,8 +308,10 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
std::unique_ptr<EmbeddedWorkerInstance::WorkerProcessHandle> process_handle_;
int thread_id_;
- // |client_| is used to send messages to the renderer process.
- mojom::EmbeddedWorkerInstanceClientAssociatedPtr client_;
+ // |client_| is used to send messages to the renderer process. The browser
+ // process should not disconnect the pipe because associated interfaces may be
+ // using it. The renderer process will disconnect the pipe when appropriate.
+ mojom::EmbeddedWorkerInstanceClientPtr client_;
// Binding for EmbeddedWorkerInstanceHost, runs on IO thread.
mojo::AssociatedBinding<EmbeddedWorkerInstanceHost> instance_host_binding_;
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
index b77c0716f69..9389f539804 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/test/scoped_feature_list.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -28,6 +29,7 @@
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -56,12 +58,6 @@ class ProviderHostEndpoints : public mojom::ServiceWorkerContainerHost {
// Just keep the endpoints.
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
mojom::ServiceWorkerProviderInfoForStartWorker::New();
- provider_info->registration =
- blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
- provider_info->registration->options =
- blink::mojom::ServiceWorkerRegistrationOptions::New();
- registration_object_host_request_ =
- mojo::MakeRequest(&(provider_info->registration->host_ptr_info));
binding_.Bind(mojo::MakeRequest(&provider_info->host_ptr_info));
provider_info->client_request = mojo::MakeRequest(&client_);
mojo::MakeRequest(&provider_info->interface_provider);
@@ -99,8 +95,6 @@ class ProviderHostEndpoints : public mojom::ServiceWorkerContainerHost {
mojom::ServiceWorkerContainerAssociatedPtr client_;
mojo::AssociatedBinding<mojom::ServiceWorkerContainerHost> binding_;
- blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedRequest
- registration_object_host_request_;
DISALLOW_COPY_AND_ASSIGN(ProviderHostEndpoints);
};
@@ -198,12 +192,12 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
params->dispatcher_request = CreateEventDispatcher();
params->controller_request = CreateController();
params->installed_scripts_info = GetInstalledScriptsInfoPtr();
- params->service_worker_host = GetServiceWorkerHostPtrInfo();
return params;
}
mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfo(
- int /* process_id */) {
+ int /* process_id */,
+ scoped_refptr<network::SharedURLLoaderFactory>) {
provider_host_endpoints_.emplace_back(
std::make_unique<ProviderHostEndpoints>());
return provider_host_endpoints_.back()->CreateProviderInfoPtr();
@@ -229,12 +223,6 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
worker->status_ = status;
}
- ServiceWorkerStatusCode SimulateSendStartWorker(
- EmbeddedWorkerInstance* worker,
- mojom::EmbeddedWorkerStartParamsPtr params) {
- return worker->SendStartWorker(std::move(params));
- }
-
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
GetInstalledScriptsInfoPtr() {
installed_scripts_managers_.emplace_back();
@@ -246,13 +234,6 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
return info;
}
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo
- GetServiceWorkerHostPtrInfo() {
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo ptr_info;
- service_worker_host_requests_.push_back(mojo::MakeRequest(&ptr_info));
- return ptr_info;
- }
-
ServiceWorkerContextCore* context() { return helper_->context(); }
EmbeddedWorkerRegistry* embedded_worker_registry() {
@@ -275,8 +256,6 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
installed_scripts_managers_;
std::vector<blink::mojom::ServiceWorkerInstalledScriptsManagerHostRequest>
installed_scripts_manager_host_requests_;
- std::vector<blink::mojom::ServiceWorkerHostAssociatedRequest>
- service_worker_host_requests_;
std::vector<std::unique_ptr<ProviderHostEndpoints>> provider_host_endpoints_;
TestBrowserThreadBundle thread_bundle_;
@@ -302,7 +281,6 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -316,9 +294,8 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
pause_after_download, std::move(dispatcher_request),
- std::move(controller_request), std::move(service_worker_host),
- std::move(instance_host), std::move(provider_info),
- std::move(installed_scripts_info));
+ std::move(controller_request), std::move(instance_host),
+ std::move(provider_info), std::move(installed_scripts_info));
}
void OnStopWorker(int embedded_worker_id) override {
@@ -352,7 +329,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Start should succeed.
ServiceWorkerStatusCode status;
@@ -559,7 +536,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Run the start worker sequence and detach during process allocation.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -593,7 +570,7 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Run the start worker sequence until a start worker message is sent.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -633,7 +610,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Stop the start worker sequence before a process is allocated.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -708,7 +685,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Run the start worker sequence until pause after download.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -741,7 +718,7 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Run the start worker sequence until a start worker message is sent.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -805,7 +782,7 @@ TEST_F(EmbeddedWorkerInstanceTest, Detach) {
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- worker->AddListener(this);
+ worker->AddObserver(this);
// Start the worker.
base::RunLoop run_loop;
@@ -840,7 +817,7 @@ TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Attempt to start the worker.
mojom::EmbeddedWorkerStartParamsPtr params =
@@ -885,7 +862,7 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveRemoteInterface) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Attempt to start the worker.
mojom::EmbeddedWorkerStartParamsPtr params =
@@ -937,7 +914,7 @@ TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- worker->AddListener(this);
+ worker->AddObserver(this);
// Attempt to start the worker and immediate AddMessageToConsole should not
// cause a crash.
@@ -972,21 +949,162 @@ TEST_F(EmbeddedWorkerInstanceTest, AddMessageToConsole) {
EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
}
-// Test that SendStartWorker checks if dispatcher host exists.
-TEST_F(EmbeddedWorkerInstanceTest, NoDispatcherHost) {
+// Records whether a CacheStoragePtr was sent as part of StartWorker.
+class RecordCacheStorageHelper : public EmbeddedWorkerTestHelper {
+ public:
+ RecordCacheStorageHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ ~RecordCacheStorageHelper() override {}
+
+ void OnStartWorker(
+ int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download,
+ mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
+ mojom::ControllerServiceWorkerRequest controller_request,
+ mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
+ blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
+ override {
+ had_cache_storage_ = !!provider_info->cache_storage;
+ EmbeddedWorkerTestHelper::OnStartWorker(
+ embedded_worker_id, service_worker_version_id, scope, script_url,
+ pause_after_download, std::move(dispatcher_request),
+ std::move(controller_request), std::move(instance_host),
+ std::move(provider_info), std::move(installed_scripts_info));
+ }
+
+ bool had_cache_storage() const { return had_cache_storage_; }
+
+ private:
+ bool had_cache_storage_ = false;
+};
+
+// Test that the worker is given a CacheStoragePtr during startup, when
+// |pause_after_download| is false.
+TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimization) {
+ const GURL scope("http://example.com/");
+ const GURL url("http://example.com/worker.js");
+ auto helper = std::make_unique<RecordCacheStorageHelper>();
+ auto* helper_rawptr = helper.get();
+ helper_ = std::move(helper);
+
+ RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
+ const int64_t version_id = pair.second->version_id();
+ std::unique_ptr<EmbeddedWorkerInstance> worker =
+ embedded_worker_registry()->CreateWorker(pair.second.get());
+
+ // First, test a worker without pause after download.
+ {
+ // Start the worker.
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::RunLoop run_loop;
+ mojom::EmbeddedWorkerStartParamsPtr params =
+ CreateStartParams(version_id, scope, url);
+ worker->Start(
+ std::move(params), CreateProviderInfoGetter(),
+ base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ run_loop.Run();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ // Cache storage should have been sent.
+ EXPECT_TRUE(helper_rawptr->had_cache_storage());
+
+ // Stop the worker.
+ worker->Stop();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ // Second, test a worker with pause after download.
+ {
+ // Start the worker until paused.
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ mojom::EmbeddedWorkerStartParamsPtr params =
+ CreateStartParams(version_id, scope, url);
+ params->pause_after_download = true;
+ worker->Start(
+ std::move(params), CreateProviderInfoGetter(),
+ base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
+ base::RunLoop().RunUntilIdle();
+
+ // Finish starting.
+ worker->ResumeAfterDownload();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ // Cache storage should not have been sent.
+ EXPECT_FALSE(helper_rawptr->had_cache_storage());
+
+ // Stop the worker.
+ worker->Stop();
+ base::RunLoop().RunUntilIdle();
+ }
+}
+
+// Test that the worker is not given a CacheStoragePtr during startup when
+// the feature is disabled.
+TEST_F(EmbeddedWorkerInstanceTest, CacheStorageOptimizationIsDisabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(
+ blink::features::kEagerCacheStorageSetupForServiceWorkers);
+
const GURL scope("http://example.com/");
const GURL url("http://example.com/worker.js");
+ auto helper = std::make_unique<RecordCacheStorageHelper>();
+ auto* helper_rawptr = helper.get();
+ helper_ = std::move(helper);
RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
+ const int64_t version_id = pair.second->version_id();
std::unique_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker(pair.second.get());
- SetWorkerStatus(worker.get(), EmbeddedWorkerStatus::STARTING);
- auto params = mojom::EmbeddedWorkerStartParams::New();
- ServiceWorkerStatusCode result =
- SimulateSendStartWorker(worker.get(), std::move(params));
- EXPECT_EQ(SERVICE_WORKER_ERROR_IPC_FAILED, result);
- // Set to STOPPED because EWInstance's destructor DCHECKs status.
- SetWorkerStatus(worker.get(), EmbeddedWorkerStatus::STOPPED);
+
+ // First, test a worker without pause after download.
+ {
+ // Start the worker.
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::RunLoop run_loop;
+ mojom::EmbeddedWorkerStartParamsPtr params =
+ CreateStartParams(version_id, scope, url);
+ worker->Start(
+ std::move(params), CreateProviderInfoGetter(),
+ base::BindOnce(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ run_loop.Run();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ // Cache storage should not have been sent.
+ EXPECT_FALSE(helper_rawptr->had_cache_storage());
+
+ // Stop the worker.
+ worker->Stop();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ // Second, test a worker with pause after download.
+ {
+ // Start the worker until paused.
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ mojom::EmbeddedWorkerStartParamsPtr params =
+ CreateStartParams(version_id, scope, url);
+ params->pause_after_download = true;
+ worker->Start(
+ std::move(params), CreateProviderInfoGetter(),
+ base::BindOnce(&SaveStatusAndCall, &status, base::DoNothing::Once<>()));
+ base::RunLoop().RunUntilIdle();
+
+ // Finish starting.
+ worker->ResumeAfterDownload();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ // Cache storage should not have been sent.
+ EXPECT_FALSE(helper_rawptr->had_cache_storage());
+
+ // Stop the worker.
+ worker->Stop();
+ base::RunLoop().RunUntilIdle();
+ }
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
index 963ff792cd5..4db8a45e0d1 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -12,7 +12,6 @@
#include "base/atomic_sequence_num.h"
#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -45,11 +44,8 @@ namespace {
class MockServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
public:
- MockServiceWorkerDispatcherHost(int process_id,
- ResourceContext* resource_context,
- IPC::Sender* sender)
- : ServiceWorkerDispatcherHost(process_id, resource_context),
- sender_(sender) {}
+ MockServiceWorkerDispatcherHost(int process_id, IPC::Sender* sender)
+ : ServiceWorkerDispatcherHost(process_id), sender_(sender) {}
bool Send(IPC::Message* message) override { return sender_->Send(message); }
@@ -137,7 +133,7 @@ void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
// static
void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::Bind(
const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request) {
+ mojom::EmbeddedWorkerInstanceClientRequest request) {
std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>* clients =
helper->mock_instance_clients();
size_t next_client_index = helper->mock_instance_clients_next_index_;
@@ -159,20 +155,31 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
: public mojom::ServiceWorkerEventDispatcher {
public:
static void Create(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- int thread_id,
+ int embedded_worker_id,
mojom::ServiceWorkerEventDispatcherRequest request) {
- mojo::MakeStrongBinding(
- std::make_unique<MockServiceWorkerEventDispatcher>(helper, thread_id),
- std::move(request));
+ mojo::MakeStrongBinding(std::make_unique<MockServiceWorkerEventDispatcher>(
+ helper, embedded_worker_id),
+ std::move(request));
}
MockServiceWorkerEventDispatcher(
const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- int thread_id)
- : helper_(helper), thread_id_(thread_id) {}
+ int embedded_worker_id)
+ : helper_(helper), embedded_worker_id_(embedded_worker_id) {}
~MockServiceWorkerEventDispatcher() override {}
+ void InitializeGlobalScope(
+ blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info)
+ override {
+ if (!helper_)
+ return;
+ helper_->OnInitializeGlobalScope(embedded_worker_id_,
+ std::move(service_worker_host),
+ std::move(registration_info));
+ }
+
void DispatchInstallEvent(
DispatchInstallEventCallback callback) override {
if (!helper_)
@@ -188,10 +195,13 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
void DispatchBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchAbortEventCallback callback) override {
if (!helper_)
return;
- helper_->OnBackgroundFetchAbortEventStub(developer_id, std::move(callback));
+ helper_->OnBackgroundFetchAbortEventStub(developer_id, unique_id, fetches,
+ std::move(callback));
}
void DispatchBackgroundFetchClickEvent(
@@ -206,11 +216,12 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
void DispatchBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchFailEventCallback callback) override {
if (!helper_)
return;
- helper_->OnBackgroundFetchFailEventStub(developer_id, fetches,
+ helper_->OnBackgroundFetchFailEventStub(developer_id, unique_id, fetches,
std::move(callback));
}
@@ -225,6 +236,15 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
std::move(callback));
}
+ void DispatchCookieChangeEvent(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ DispatchCookieChangeEventCallback callback) override {
+ if (!helper_)
+ return;
+ helper_->OnCookieChangeEventStub(cookie, cause, std::move(callback));
+ }
+
void DispatchFetchEvent(
mojom::DispatchFetchEventParamsPtr params,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
@@ -232,7 +252,7 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
if (!helper_)
return;
helper_->OnFetchEventStub(
- thread_id_, params->request, std::move(params->preload_handle),
+ embedded_worker_id_, params->request, std::move(params->preload_handle),
std::move(response_callback), std::move(callback));
}
@@ -322,7 +342,7 @@ class EmbeddedWorkerTestHelper::MockServiceWorkerEventDispatcher
private:
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
- const int thread_id_;
+ const int embedded_worker_id_;
};
class EmbeddedWorkerTestHelper::MockRendererInterface : public mojom::Renderer {
@@ -342,8 +362,7 @@ class EmbeddedWorkerTestHelper::MockRendererInterface : public mojom::Renderer {
void CreateView(mojom::CreateViewParamsPtr) override { NOTREACHED(); }
void CreateFrame(mojom::CreateFrameParamsPtr) override { NOTREACHED(); }
void SetUpEmbeddedWorkerChannelForServiceWorker(
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest client_request)
- override {
+ mojom::EmbeddedWorkerInstanceClientRequest client_request) override {
MockEmbeddedWorkerInstanceClient::Bind(helper_, std::move(client_request));
}
void CreateFrameProxy(
@@ -367,6 +386,7 @@ class EmbeddedWorkerTestHelper::MockRendererInterface : public mojom::Renderer {
NOTREACHED();
}
void SetWebKitSharedTimersSuspended(bool suspend) override { NOTREACHED(); }
+ void SetUserAgent(const std::string& user_agent) override { NOTREACHED(); }
void UpdateScrollbarTheme(
mojom::UpdateScrollbarThemeParamsPtr params) override {
NOTREACHED();
@@ -468,8 +488,8 @@ void EmbeddedWorkerTestHelper::RegisterDispatcherHost(
void EmbeddedWorkerTestHelper::EnsureDispatcherHostForProcess(int process_id) {
if (context()->GetDispatcherHost(process_id))
return;
- auto dispatcher_host = base::MakeRefCounted<MockServiceWorkerDispatcherHost>(
- process_id, browser_context_->GetResourceContext(), this);
+ auto dispatcher_host =
+ base::MakeRefCounted<MockServiceWorkerDispatcherHost>(process_id, this);
dispatcher_host->Init(wrapper_.get());
RegisterDispatcherHost(process_id, std::move(dispatcher_host));
}
@@ -508,13 +528,12 @@ void EmbeddedWorkerTestHelper::OnStartWorker(
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker);
- MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), worker->thread_id(),
+ MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), embedded_worker_id,
std::move(dispatcher_request));
embedded_worker_id_service_worker_version_id_map_[embedded_worker_id] =
service_worker_version_id;
@@ -562,6 +581,8 @@ void EmbeddedWorkerTestHelper::OnActivateEvent(
void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback) {
std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
@@ -579,6 +600,7 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEvent(
void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback) {
@@ -596,6 +618,15 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchedEvent(
base::Time::Now());
}
+void EmbeddedWorkerTestHelper::OnCookieChangeEvent(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
+ callback) {
+ std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
+ base::Time::Now());
+}
+
void EmbeddedWorkerTestHelper::OnExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
@@ -778,6 +809,32 @@ void EmbeddedWorkerTestHelper::SimulateWorkerStopped(int embedded_worker_id) {
}
}
+void EmbeddedWorkerTestHelper::OnInitializeGlobalScope(
+ int embedded_worker_id,
+ blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info) {
+ embedded_worker_id_host_map_[embedded_worker_id].Bind(
+ std::move(service_worker_host));
+ // To enable the caller end points to make calls safely with no need to pass
+ // these associated interface requests through a message pipe endpoint.
+ mojo::AssociateWithDisconnectedPipe(registration_info->request.PassHandle());
+ if (registration_info->installing) {
+ mojo::AssociateWithDisconnectedPipe(
+ registration_info->installing->request.PassHandle());
+ }
+ if (registration_info->waiting) {
+ mojo::AssociateWithDisconnectedPipe(
+ registration_info->waiting->request.PassHandle());
+ }
+ if (registration_info->active) {
+ mojo::AssociateWithDisconnectedPipe(
+ registration_info->active->request.PassHandle());
+ }
+ // Keep all Mojo connections alive.
+ embedded_worker_id_registration_info_map_[embedded_worker_id] =
+ std::move(registration_info);
+}
+
void EmbeddedWorkerTestHelper::OnStartWorkerStub(
mojom::EmbeddedWorkerStartParamsPtr params) {
EmbeddedWorkerInstance* worker =
@@ -792,7 +849,6 @@ void EmbeddedWorkerTestHelper::OnStartWorkerStub(
params->scope, params->script_url, params->pause_after_download,
std::move(params->dispatcher_request),
std::move(params->controller_request),
- std::move(params->service_worker_host),
std::move(params->instance_host), std::move(params->provider_info),
std::move(params->installed_scripts_info)));
}
@@ -823,12 +879,15 @@ void EmbeddedWorkerTestHelper::OnActivateEventStub(
void EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEventStub(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchAbortEvent,
- AsWeakPtr(), developer_id, std::move(callback)));
+ AsWeakPtr(), developer_id, unique_id, fetches,
+ std::move(callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEventStub(
@@ -844,13 +903,15 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchClickEventStub(
void EmbeddedWorkerTestHelper::OnBackgroundFetchFailEventStub(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnBackgroundFetchFailEvent,
- AsWeakPtr(), developer_id, fetches, std::move(callback)));
+ AsWeakPtr(), developer_id, unique_id, fetches,
+ std::move(callback)));
}
void EmbeddedWorkerTestHelper::OnBackgroundFetchedEventStub(
@@ -866,6 +927,17 @@ void EmbeddedWorkerTestHelper::OnBackgroundFetchedEventStub(
std::move(callback)));
}
+void EmbeddedWorkerTestHelper::OnCookieChangeEventStub(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
+ callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&EmbeddedWorkerTestHelper::OnCookieChangeEvent,
+ AsWeakPtr(), cookie, cause, std::move(callback)));
+}
+
void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
mojom::ExtendableMessageEventPtr event,
mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
@@ -885,7 +957,7 @@ void EmbeddedWorkerTestHelper::OnInstallEventStub(
}
void EmbeddedWorkerTestHelper::OnFetchEventStub(
- int thread_id,
+ int embedded_worker_id,
const network::ResourceRequest& request,
mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
@@ -894,9 +966,8 @@ void EmbeddedWorkerTestHelper::OnFetchEventStub(
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&EmbeddedWorkerTestHelper::OnFetchEvent, AsWeakPtr(),
- thread_id_embedded_worker_id_map_[thread_id], request,
- std::move(preload_handle), std::move(response_callback),
- std::move(finish_callback)));
+ embedded_worker_id, request, std::move(preload_handle),
+ std::move(response_callback), std::move(finish_callback)));
}
void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
diff --git a/chromium/content/browser/service_worker/embedded_worker_test_helper.h b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
index c0cd7275d30..609a99102b0 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -24,8 +24,10 @@
#include "content/common/service_worker/service_worker_status_code.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_test_sink.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/cookies/cookie_change_dispatcher.h"
#include "net/http/http_response_info.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "url/gurl.h"
@@ -71,9 +73,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
base::WeakPtr<EmbeddedWorkerTestHelper> helper);
~MockEmbeddedWorkerInstanceClient() override;
- static void Bind(
- const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request);
+ static void Bind(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+ mojom::EmbeddedWorkerInstanceClientRequest request);
protected:
// mojom::EmbeddedWorkerInstanceClient implementation.
@@ -86,7 +87,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
blink::mojom::DevToolsAgentAssociatedRequest request) override {}
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
- mojo::AssociatedBinding<mojom::EmbeddedWorkerInstanceClient> binding_;
+ mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_;
base::Optional<int> embedded_worker_id_;
@@ -153,10 +154,6 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
return render_process_host_.get();
}
- std::map<int, int64_t> embedded_worker_id_service_worker_version_id_map() {
- return embedded_worker_id_service_worker_version_id_map_;
- }
-
// Only used for tests that force creating a new render process.
int new_render_process_id() const { return new_mock_render_process_id_; }
@@ -176,8 +173,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
protected:
// StartWorker IPC handler routed through MockEmbeddedWorkerInstanceClient.
- // This simulates each legacy IPC sent from the renderer and binds |request|
- // to MockServiceWorkerEventDispatcher by default.
+ // This simulates behaviors in the renderer process. Binds
+ // |dispatcher_request| to MockServiceWorkerEventDispatcher by default.
virtual void OnStartWorker(
int embedded_worker_id,
int64_t service_worker_version_id,
@@ -186,7 +183,6 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
@@ -203,6 +199,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
callback);
virtual void OnBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback);
virtual void OnBackgroundFetchClickEvent(
@@ -212,6 +210,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
DispatchBackgroundFetchClickEventCallback callback);
virtual void OnBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback);
@@ -221,6 +220,11 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchedEventCallback callback);
+ virtual void OnCookieChangeEvent(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
+ callback);
virtual void OnExtendableMessageEvent(
mojom::ExtendableMessageEventPtr event,
mojom::ServiceWorkerEventDispatcher::
@@ -277,6 +281,11 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
EmbeddedWorkerRegistry* registry();
+ blink::mojom::ServiceWorkerHost* GetServiceWorkerHost(
+ int embedded_worker_id) {
+ return embedded_worker_id_host_map_[embedded_worker_id].get();
+ }
+
private:
class MockServiceWorkerEventDispatcher;
class MockRendererInterface;
@@ -284,6 +293,10 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
void DidSimulateWorkerScriptCached(int embedded_worker_id,
bool pause_after_download);
+ void OnInitializeGlobalScope(
+ int embedded_worker_id,
+ blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info);
void OnStartWorkerStub(mojom::EmbeddedWorkerStartParamsPtr params);
void OnResumeAfterDownloadStub(int embedded_worker_id);
void OnStopWorkerStub(int embedded_worker_id);
@@ -292,6 +305,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
callback);
void OnBackgroundFetchAbortEventStub(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchAbortEventCallback callback);
void OnBackgroundFetchClickEventStub(
@@ -301,6 +316,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
DispatchBackgroundFetchClickEventCallback callback);
void OnBackgroundFetchFailEventStub(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchFailEventCallback callback);
@@ -310,6 +326,11 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
const std::vector<BackgroundFetchSettledFetch>& fetches,
mojom::ServiceWorkerEventDispatcher::
DispatchBackgroundFetchedEventCallback callback);
+ void OnCookieChangeEventStub(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ mojom::ServiceWorkerEventDispatcher::DispatchCookieChangeEventCallback
+ callback);
void OnExtendableMessageEventStub(
mojom::ExtendableMessageEventPtr event,
mojom::ServiceWorkerEventDispatcher::
@@ -318,7 +339,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
mojom::ServiceWorkerEventDispatcher::DispatchInstallEventCallback
callback);
void OnFetchEventStub(
- int thread_id,
+ int embedded_worker_id,
const network::ResourceRequest& request,
mojom::FetchEventPreloadHandlePtr preload_handle,
mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
@@ -375,8 +396,6 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
dispatcher_hosts_;
std::map<int, int64_t> embedded_worker_id_service_worker_version_id_map_;
- std::map<int /* thread_id */, int /* embedded_worker_id */>
- thread_id_embedded_worker_id_map_;
std::map<
int /* embedded_worker_id */,
@@ -387,6 +406,14 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
std::map<int /* embedded_worker_id */,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr>
embedded_worker_id_installed_scripts_info_map_;
+ std::map<
+ int /* embedded_worker_id */,
+ blink::mojom::ServiceWorkerHostAssociatedPtr /* service_worker_host */>
+ embedded_worker_id_host_map_;
+ std::map<int /* embedded_worker_id */,
+ blink::mojom::
+ ServiceWorkerRegistrationObjectInfoPtr /* registration_info */>
+ embedded_worker_id_registration_info_map_;
std::vector<Event> events_;
scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index baf6eb5e6ab..c12bec86b88 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -227,7 +227,8 @@ class WorkerActivatedObserver
std::unique_ptr<net::test_server::HttpResponse>
VerifyServiceWorkerHeaderInRequest(
const net::test_server::HttpRequest& request) {
- EXPECT_EQ(request.relative_url, "/service_worker/generated_sw.js");
+ if (request.relative_url != "/service_worker/generated_sw.js")
+ return nullptr;
auto it = request.headers.find("Service-Worker");
EXPECT_TRUE(it != request.headers.end());
EXPECT_EQ("script", it->second);
@@ -240,6 +241,8 @@ VerifyServiceWorkerHeaderInRequest(
std::unique_ptr<net::test_server::HttpResponse> VerifySaveDataHeaderInRequest(
const net::test_server::HttpRequest& request) {
+ if (request.relative_url != "/service_worker/generated_sw.js")
+ return nullptr;
auto it = request.headers.find("Save-Data");
EXPECT_NE(request.headers.end(), it);
EXPECT_EQ("on", it->second);
@@ -252,6 +255,8 @@ std::unique_ptr<net::test_server::HttpResponse> VerifySaveDataHeaderInRequest(
std::unique_ptr<net::test_server::HttpResponse>
VerifySaveDataHeaderNotInRequest(const net::test_server::HttpRequest& request) {
+ if (request.relative_url != "/service_worker/generated_sw.js")
+ return nullptr;
auto it = request.headers.find("Save-Data");
EXPECT_EQ(request.headers.end(), it);
return std::make_unique<net::test_server::BasicHttpResponse>();
@@ -1160,7 +1165,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
"/service_worker/worker_install_rejected.js"));
ConsoleListener console_listener;
- RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddListener,
+ RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver,
base::Unretained(version_->embedded_worker()),
&console_listener));
@@ -1179,7 +1184,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
console_listener.WaitForConsoleMessages(1);
ASSERT_NE(base::string16::npos,
console_listener.messages()[0].find(expected));
- RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveListener,
+ RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver,
base::Unretained(version_->embedded_worker()),
&console_listener));
}
@@ -1208,7 +1213,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
base::RunLoop start_run_loop;
base::RunLoop load_run_loop;
WaitForLoaded wait_for_load(load_run_loop.QuitClosure());
- RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddListener,
+ RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver,
base::Unretained(version_->embedded_worker()),
&wait_for_load));
BrowserThread::PostTask(
@@ -1216,7 +1221,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
base::BindOnce(&self::StartOnIOThread, base::Unretained(this),
start_run_loop.QuitClosure(), &status));
load_run_loop.Run();
- RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveListener,
+ RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver,
base::Unretained(version_->embedded_worker()),
&wait_for_load));
@@ -1337,7 +1342,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
SERVICE_WORKER_OK);
ConsoleListener console_listener;
- RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddListener,
+ RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver,
base::Unretained(version_->embedded_worker()),
&console_listener));
@@ -1350,7 +1355,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ASSERT_NE(base::string16::npos,
console_listener.messages()[0].find(expected1));
ASSERT_EQ(0u, console_listener.messages()[1].find(expected2));
- RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveListener,
+ RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver,
base::Unretained(version_->embedded_worker()),
&console_listener));
@@ -2347,8 +2352,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
EXPECT_TRUE(entry->GetSSL().initialized);
EXPECT_FALSE(!!(entry->GetSSL().content_status &
SSLStatus::DISPLAYED_INSECURE_CONTENT));
- EXPECT_TRUE(
- https_server.GetCertificate()->Equals(entry->GetSSL().certificate.get()));
+ EXPECT_TRUE(https_server.GetCertificate()->EqualsExcludingChain(
+ entry->GetSSL().certificate.get()));
EXPECT_FALSE(net::IsCertStatusError(entry->GetSSL().cert_status));
shell()->Close();
@@ -2796,7 +2801,7 @@ class CacheStorageSideDataSizeChecker
void OpenCacheOnIOThread(int* result, const base::Closure& continuation) {
cache_storage_context_->cache_manager()->OpenCache(
- url::Origin::Create(origin_), cache_name_,
+ url::Origin::Create(origin_), CacheStorageOwner::kCacheAPI, cache_name_,
base::BindOnce(&self::OnCacheStorageOpenCallback, this, result,
continuation));
}
@@ -2810,7 +2815,7 @@ class CacheStorageSideDataSizeChecker
new ServiceWorkerFetchRequest());
scoped_request->url = url_;
CacheStorageCache* cache = cache_handle.value();
- cache->Match(std::move(scoped_request), CacheStorageCacheQueryParams(),
+ cache->Match(std::move(scoped_request), nullptr,
base::BindOnce(&self::OnCacheStorageCacheMatchCallback, this,
result, continuation, std::move(cache_handle)));
}
diff --git a/chromium/content/browser/service_worker/service_worker_client_info.cc b/chromium/content/browser/service_worker/service_worker_client_info.cc
new file mode 100644
index 00000000000..cff6cf107f3
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_client_info.cc
@@ -0,0 +1,34 @@
+// 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/service_worker/service_worker_client_info.h"
+
+#include "content/public/common/child_process_host.h"
+#include "ipc/ipc_message.h"
+
+namespace content {
+
+ServiceWorkerClientInfo::ServiceWorkerClientInfo()
+ : ServiceWorkerClientInfo(
+ ChildProcessHost::kInvalidUniqueID,
+ MSG_ROUTING_NONE,
+ base::RepeatingCallback<WebContents*(void)>(),
+ blink::mojom::ServiceWorkerProviderType::kUnknown) {}
+
+ServiceWorkerClientInfo::ServiceWorkerClientInfo(
+ int process_id,
+ int route_id,
+ const base::RepeatingCallback<WebContents*(void)>& web_contents_getter,
+ blink::mojom::ServiceWorkerProviderType type)
+ : process_id(process_id),
+ route_id(route_id),
+ web_contents_getter(web_contents_getter),
+ type(type) {}
+
+ServiceWorkerClientInfo::ServiceWorkerClientInfo(
+ const ServiceWorkerClientInfo& other) = default;
+
+ServiceWorkerClientInfo::~ServiceWorkerClientInfo() {}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_client_info.h b/chromium/content/browser/service_worker/service_worker_client_info.h
new file mode 100644
index 00000000000..245c198622f
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_client_info.h
@@ -0,0 +1,43 @@
+// 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_SERVICE_WORKER_SERVICE_WORKER_CLIENT_INFO_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CLIENT_INFO_H_
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
+
+namespace content {
+
+// Holds information about a single service worker client:
+// https://w3c.github.io/ServiceWorker/#client
+struct CONTENT_EXPORT ServiceWorkerClientInfo {
+ ServiceWorkerClientInfo();
+ ServiceWorkerClientInfo(
+ int process_id,
+ int route_id,
+ const base::RepeatingCallback<WebContents*(void)>& web_contents_getter,
+ blink::mojom::ServiceWorkerProviderType type);
+ ServiceWorkerClientInfo(const ServiceWorkerClientInfo& other);
+ ~ServiceWorkerClientInfo();
+
+ // The renderer process this client lives in.
+ int process_id;
+ // If this client is a document |route_id| is its frame id; otherwise it is
+ // MSG_ROUTING_NONE.
+ int route_id;
+ // Non-null if this client is a document and its corresponding
+ // ServiceWorkerProviderHost was pre-created for a navigation. Returns
+ // information indicating the tab where the navigation is occurring or
+ // occurred in.
+ base::RepeatingCallback<WebContents*(void)> web_contents_getter;
+ // The client type.
+ blink::mojom::ServiceWorkerProviderType type;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CLIENT_INFO_H_
diff --git a/chromium/content/browser/service_worker/service_worker_client_utils.cc b/chromium/content/browser/service_worker/service_worker_client_utils.cc
index b27c2d353f7..947d1166e58 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -380,7 +380,8 @@ void GetNonWindowClients(
AddNonWindowClient(controllee.second, std::move(options), clients.get());
} else if (controller->context()) {
GURL origin = controller->script_url().GetOrigin();
- for (auto it = controller->context()->GetClientProviderHostIterator(origin);
+ for (auto it = controller->context()->GetClientProviderHostIterator(
+ origin, false /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
AddNonWindowClient(it->GetProviderHost(), std::move(options),
clients.get());
@@ -418,7 +419,8 @@ void GetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
AddWindowClient(controllee.second, &clients_info);
} else if (controller->context()) {
GURL origin = controller->script_url().GetOrigin();
- for (auto it = controller->context()->GetClientProviderHostIterator(origin);
+ for (auto it = controller->context()->GetClientProviderHostIterator(
+ origin, false /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
AddWindowClient(it->GetProviderHost(), &clients_info);
}
@@ -560,7 +562,8 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
}
for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
- context->GetClientProviderHostIterator(origin);
+ context->GetClientProviderHostIterator(
+ origin, false /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
ServiceWorkerProviderHost* provider_host = it->GetProviderHost();
if (provider_host->process_id() != render_process_id ||
diff --git a/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc b/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
index 2934d52f2c7..e4b82677f15 100644
--- a/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
+++ b/chromium/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
@@ -27,6 +27,11 @@ void ServiceWorkerContentSettingsProxyImpl::AllowIndexedDB(
const base::string16& name,
AllowIndexedDBCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // May be shutting down.
+ if (!context_ || !context_->wrapper()->resource_context()) {
+ std::move(callback).Run(false);
+ return;
+ }
if (origin_.unique()) {
std::move(callback).Run(false);
return;
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.cc b/chromium/content/browser/service_worker/service_worker_context_core.cc
index d5b665ca761..46f20d354a1 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -87,19 +87,19 @@ void SuccessReportingCallback(
}
bool IsSameOriginClientProviderHost(const GURL& origin,
+ bool allow_reserved_client,
ServiceWorkerProviderHost* host) {
return host->IsProviderForClient() &&
host->document_url().GetOrigin() == origin &&
- // Don't expose "reserved" clients (clients that are not yet execution
- // ready) to the Clients API.
- host->is_execution_ready();
+ (allow_reserved_client || host->is_execution_ready());
}
bool IsSameOriginWindowProviderHost(const GURL& origin,
ServiceWorkerProviderHost* host) {
return host->provider_type() ==
blink::mojom::ServiceWorkerProviderType::kForWindow &&
- host->document_url().GetOrigin() == origin;
+ host->document_url().GetOrigin() == origin &&
+ host->is_execution_ready();
}
// Returns true if any of the frames specified by |frames| is a top-level frame.
@@ -269,7 +269,7 @@ bool ServiceWorkerContextCore::ProviderHostIterator::
}
ServiceWorkerContextCore::ServiceWorkerContextCore(
- const base::FilePath& path,
+ const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy,
@@ -282,17 +282,17 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
provider_by_uuid_(std::make_unique<ProviderByClientUUIDMap>()),
loader_factory_getter_(url_loader_factory_getter),
force_update_on_page_load_(false),
- next_handle_id_(0),
was_service_worker_registered_(false),
observer_list_(observer_list),
weak_factory_(this) {
- // These get a WeakPtr from weak_factory_, so must be set after weak_factory_
- // is initialized.
+ DCHECK(observer_list_);
+ // These get a WeakPtr from |weak_factory_|, so must be set after
+ // |weak_factory_| is initialized.
storage_ = ServiceWorkerStorage::Create(
- path, AsWeakPtr(), std::move(database_task_runner), quota_manager_proxy,
- special_storage_policy);
+ user_data_directory, AsWeakPtr(), std::move(database_task_runner),
+ quota_manager_proxy, special_storage_policy);
embedded_worker_registry_ = EmbeddedWorkerRegistry::Create(AsWeakPtr());
- job_coordinator_.reset(new ServiceWorkerJobCoordinator(AsWeakPtr()));
+ job_coordinator_ = std::make_unique<ServiceWorkerJobCoordinator>(AsWeakPtr());
}
ServiceWorkerContextCore::ServiceWorkerContextCore(
@@ -303,27 +303,25 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
providers_(old_context->providers_.release()),
provider_by_uuid_(old_context->provider_by_uuid_.release()),
loader_factory_getter_(old_context->loader_factory_getter()),
- next_handle_id_(old_context->next_handle_id_),
was_service_worker_registered_(
old_context->was_service_worker_registered_),
observer_list_(old_context->observer_list_),
weak_factory_(this) {
- // These get a WeakPtr from weak_factory_, so must be set after weak_factory_
- // is initialized.
+ DCHECK(observer_list_);
+
+ // These get a WeakPtr from |weak_factory_|, so must be set after
+ // |weak_factory_| is initialized.
storage_ = ServiceWorkerStorage::Create(AsWeakPtr(), old_context->storage());
embedded_worker_registry_ = EmbeddedWorkerRegistry::Create(
AsWeakPtr(),
old_context->embedded_worker_registry());
- job_coordinator_.reset(new ServiceWorkerJobCoordinator(AsWeakPtr()));
+ job_coordinator_ = std::make_unique<ServiceWorkerJobCoordinator>(AsWeakPtr());
}
ServiceWorkerContextCore::~ServiceWorkerContextCore() {
DCHECK(storage_);
- for (VersionMap::iterator it = live_versions_.begin();
- it != live_versions_.end();
- ++it) {
- it->second->RemoveListener(this);
- }
+ for (const auto& it : live_versions_)
+ it.second->RemoveListener(this);
weak_factory_.InvalidateWeakPtrs();
}
@@ -366,6 +364,18 @@ void ServiceWorkerContextCore::AddProviderHost(
map->AddWithID(std::move(host), provider_id);
}
+std::unique_ptr<ServiceWorkerProviderHost>
+ServiceWorkerContextCore::ReleaseProviderHost(int process_id, int provider_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ProviderMap* map = GetProviderMapForProcess(process_id);
+ if (!map || !map->Lookup(provider_id))
+ return nullptr;
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ map->Replace(provider_id, nullptr);
+ map->Remove(provider_id);
+ return host;
+}
+
ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
int process_id,
int provider_id) {
@@ -392,10 +402,13 @@ void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
}
std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator>
-ServiceWorkerContextCore::GetClientProviderHostIterator(const GURL& origin) {
+ServiceWorkerContextCore::GetClientProviderHostIterator(
+ const GURL& origin,
+ bool include_reserved_clients) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return base::WrapUnique(new ProviderHostIterator(
- providers_.get(), base::Bind(IsSameOriginClientProviderHost, origin)));
+ providers_.get(), base::BindRepeating(IsSameOriginClientProviderHost,
+ origin, include_reserved_clients)));
}
void ServiceWorkerContextCore::HasMainFrameProviderHost(
@@ -403,7 +416,8 @@ void ServiceWorkerContextCore::HasMainFrameProviderHost(
BoolCallback callback) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ProviderHostIterator provider_host_iterator(
- providers_.get(), base::Bind(IsSameOriginWindowProviderHost, origin));
+ providers_.get(),
+ base::BindRepeating(IsSameOriginWindowProviderHost, origin));
if (provider_host_iterator.IsAtEnd()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -494,9 +508,9 @@ void ServiceWorkerContextCore::DeleteForOrigin(const GURL& origin,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
storage()->GetRegistrationsForOrigin(
origin,
- AdaptCallbackForRepeating(base::BindOnce(
+ base::BindOnce(
&ServiceWorkerContextCore::DidGetRegistrationsForDeleteForOrigin,
- AsWeakPtr(), std::move(callback))));
+ AsWeakPtr(), std::move(callback)));
}
void ServiceWorkerContextCore::DidGetRegistrationsForDeleteForOrigin(
@@ -524,8 +538,7 @@ void ServiceWorkerContextCore::DidGetRegistrationsForDeleteForOrigin(
}
UnregisterServiceWorker(
registration->pattern(),
- AdaptCallbackForRepeating(base::BindOnce(&SuccessCollectorCallback,
- barrier, overall_success)));
+ base::BindOnce(&SuccessCollectorCallback, barrier, overall_success));
}
}
@@ -550,14 +563,11 @@ void ServiceWorkerContextCore::RegistrationComplete(
DCHECK(registration);
std::move(callback).Run(status, status_message, registration->id());
- // TODO(falken): At this point the registration promise is resolved, but we
- // haven't persisted anything to storage yet. So we should either call
- // OnRegistrationStored somewhere else or change its name.
- if (observer_list_.get()) {
- observer_list_->Notify(
- FROM_HERE, &ServiceWorkerContextCoreObserver::OnRegistrationStored,
- registration->id(), pattern);
- }
+ // At this point the registration promise is resolved, but we haven't
+ // persisted anything to storage yet.
+ observer_list_->Notify(
+ FROM_HERE, &ServiceWorkerContextCoreObserver::OnRegistrationCompleted,
+ registration->id(), pattern);
}
void ServiceWorkerContextCore::UpdateComplete(
@@ -582,7 +592,7 @@ void ServiceWorkerContextCore::UnregistrationComplete(
int64_t registration_id,
ServiceWorkerStatusCode status) {
std::move(callback).Run(status);
- if (status == SERVICE_WORKER_OK && observer_list_.get()) {
+ if (status == SERVICE_WORKER_OK) {
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnRegistrationDeleted,
registration_id, pattern);
@@ -599,11 +609,9 @@ void ServiceWorkerContextCore::AddLiveRegistration(
ServiceWorkerRegistration* registration) {
DCHECK(!GetLiveRegistration(registration->id()));
live_registrations_[registration->id()] = registration;
- if (observer_list_.get()) {
- observer_list_->Notify(
- FROM_HERE, &ServiceWorkerContextCoreObserver::OnNewLiveRegistration,
- registration->id(), registration->pattern());
- }
+ observer_list_->Notify(
+ FROM_HERE, &ServiceWorkerContextCoreObserver::OnNewLiveRegistration,
+ registration->id(), registration->pattern());
}
void ServiceWorkerContextCore::RemoveLiveRegistration(int64_t id) {
@@ -615,45 +623,16 @@ ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(int64_t id) {
return (it != live_versions_.end()) ? it->second : nullptr;
}
-// PlzNavigate
-void ServiceWorkerContextCore::AddNavigationHandleCore(
- int service_worker_provider_id,
- ServiceWorkerNavigationHandleCore* handle) {
- auto result = navigation_handle_cores_map_.insert(
- std::pair<int, ServiceWorkerNavigationHandleCore*>(
- service_worker_provider_id, handle));
- DCHECK(result.second)
- << "Inserting a duplicate ServiceWorkerNavigationHandleCore";
-}
-
-// PlzNavigate
-void ServiceWorkerContextCore::RemoveNavigationHandleCore(
- int service_worker_provider_id) {
- navigation_handle_cores_map_.erase(service_worker_provider_id);
-}
-
-// PlzNavigate
-ServiceWorkerNavigationHandleCore*
-ServiceWorkerContextCore::GetNavigationHandleCore(
- int service_worker_provider_id) {
- auto result = navigation_handle_cores_map_.find(service_worker_provider_id);
- if (result == navigation_handle_cores_map_.end())
- return nullptr;
- return result->second;
-}
-
void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
// TODO(horo): If we will see crashes here, we have to find the root cause of
// the version ID conflict. Otherwise change CHECK to DCHECK.
CHECK(!GetLiveVersion(version->version_id()));
live_versions_[version->version_id()] = version;
version->AddListener(this);
- if (observer_list_.get()) {
- ServiceWorkerVersionInfo version_info = version->GetInfo();
- observer_list_->Notify(FROM_HERE,
- &ServiceWorkerContextCoreObserver::OnNewLiveVersion,
- version_info);
- }
+ ServiceWorkerVersionInfo version_info = version->GetInfo();
+ observer_list_->Notify(FROM_HERE,
+ &ServiceWorkerContextCoreObserver::OnNewLiveVersion,
+ version_info);
}
void ServiceWorkerContextCore::RemoveLiveVersion(int64_t id) {
@@ -694,10 +673,6 @@ void ServiceWorkerContextCore::UnprotectVersion(int64_t version_id) {
protected_versions_.erase(version_id);
}
-int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
- return next_handle_id_++;
-}
-
void ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const {
storage_->Disable();
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -776,17 +751,21 @@ int ServiceWorkerContextCore::GetVersionFailureCount(int64_t version_id) {
return it->second.count;
}
+void ServiceWorkerContextCore::NotifyRegistrationStored(int64_t registration_id,
+ const GURL& pattern) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ observer_list_->Notify(
+ FROM_HERE, &ServiceWorkerContextCoreObserver::OnRegistrationStored,
+ registration_id, pattern);
+}
+
void ServiceWorkerContextCore::OnStorageWiped() {
- if (!observer_list_)
- return;
observer_list_->Notify(FROM_HERE,
&ServiceWorkerContextCoreObserver::OnStorageWiped);
}
void ServiceWorkerContextCore::OnRunningStateChanged(
ServiceWorkerVersion* version) {
- if (!observer_list_)
- return;
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnRunningStateChanged,
version->version_id(), version->running_status());
@@ -794,8 +773,6 @@ void ServiceWorkerContextCore::OnRunningStateChanged(
void ServiceWorkerContextCore::OnVersionStateChanged(
ServiceWorkerVersion* version) {
- if (!observer_list_)
- return;
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnVersionStateChanged,
version->version_id(), version->status());
@@ -803,7 +780,7 @@ void ServiceWorkerContextCore::OnVersionStateChanged(
void ServiceWorkerContextCore::OnDevToolsRoutingIdChanged(
ServiceWorkerVersion* version) {
- if (!observer_list_ || !version->embedded_worker())
+ if (!version->embedded_worker())
return;
observer_list_->Notify(
FROM_HERE,
@@ -814,8 +791,6 @@ void ServiceWorkerContextCore::OnDevToolsRoutingIdChanged(
void ServiceWorkerContextCore::OnMainScriptHttpResponseInfoSet(
ServiceWorkerVersion* version) {
- if (!observer_list_)
- return;
const net::HttpResponseInfo* info = version->GetMainScriptHttpResponseInfo();
DCHECK(info);
base::Time lastModified;
@@ -833,8 +808,6 @@ void ServiceWorkerContextCore::OnErrorReported(
int line_number,
int column_number,
const GURL& source_url) {
- if (!observer_list_)
- return;
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnErrorReported,
version->version_id(), version->embedded_worker()->process_id(),
@@ -850,8 +823,6 @@ void ServiceWorkerContextCore::OnReportConsoleMessage(
const base::string16& message,
int line_number,
const GURL& source_url) {
- if (!observer_list_)
- return;
observer_list_->Notify(
FROM_HERE, &ServiceWorkerContextCoreObserver::OnReportConsoleMessage,
version->version_id(), version->embedded_worker()->process_id(),
@@ -862,24 +833,19 @@ void ServiceWorkerContextCore::OnReportConsoleMessage(
void ServiceWorkerContextCore::OnControlleeAdded(
ServiceWorkerVersion* version,
- ServiceWorkerProviderHost* provider_host) {
- if (!observer_list_)
- return;
- observer_list_->Notify(
- FROM_HERE, &ServiceWorkerContextCoreObserver::OnControlleeAdded,
- version->version_id(), provider_host->client_uuid(),
- provider_host->process_id(), provider_host->route_id(),
- provider_host->web_contents_getter(), provider_host->provider_type());
+ const std::string& client_uuid,
+ const ServiceWorkerClientInfo& client_info) {
+ observer_list_->Notify(FROM_HERE,
+ &ServiceWorkerContextCoreObserver::OnControlleeAdded,
+ version->version_id(), client_uuid, client_info);
}
void ServiceWorkerContextCore::OnControlleeRemoved(
ServiceWorkerVersion* version,
- ServiceWorkerProviderHost* provider_host) {
- if (!observer_list_)
- return;
+ const std::string& client_uuid) {
observer_list_->Notify(FROM_HERE,
&ServiceWorkerContextCoreObserver::OnControlleeRemoved,
- version->version_id(), provider_host->client_uuid());
+ version->version_id(), client_uuid);
}
ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.h b/chromium/content/browser/service_worker/service_worker_context_core.h
index 18389af21fb..5168ea6801c 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -45,7 +45,6 @@ class ServiceWorkerContextCoreObserver;
class ServiceWorkerContextWrapper;
class ServiceWorkerDispatcherHost;
class ServiceWorkerJobCoordinator;
-class ServiceWorkerNavigationHandleCore;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
class ServiceWorkerStorage;
@@ -147,9 +146,10 @@ class CONTENT_EXPORT ServiceWorkerContextCore
int line_number,
const GURL& source_url) override;
void OnControlleeAdded(ServiceWorkerVersion* version,
- ServiceWorkerProviderHost* provider_host) override;
+ const std::string& client_uuid,
+ const ServiceWorkerClientInfo& client_info) override;
void OnControlleeRemoved(ServiceWorkerVersion* version,
- ServiceWorkerProviderHost* provider_host) override;
+ const std::string& client_uuid) override;
ServiceWorkerContextWrapper* wrapper() const { return wrapper_; }
ServiceWorkerStorage* storage() { return storage_.get(); }
@@ -172,19 +172,24 @@ class CONTENT_EXPORT ServiceWorkerContextCore
void AddProviderHost(
std::unique_ptr<ServiceWorkerProviderHost> provider_host);
ServiceWorkerProviderHost* GetProviderHost(int process_id, int provider_id);
+ std::unique_ptr<ServiceWorkerProviderHost> ReleaseProviderHost(
+ int process_id,
+ int provider_id);
void RemoveProviderHost(int process_id, int provider_id);
void RemoveAllProviderHostsForProcess(int process_id);
// Returns a ProviderHost iterator for all service worker clients for the
- // |origin|. This only returns clients that are execution ready (i.e., for
- // windows, the navigation has been committed and for workers, the final
- // response after redirects has been delivered).
+ // |origin|. If |include_reserved_clients| is false, this only returns clients
+ // that are execution ready (i.e., for windows, the navigation has been
+ // committed and for workers, the final response after redirects has been
+ // delivered).
std::unique_ptr<ProviderHostIterator> GetClientProviderHostIterator(
- const GURL& origin);
+ const GURL& origin,
+ bool include_reserved_clients);
// Runs the callback with true if there is a ProviderHost for |origin| of type
// blink::mojom::ServiceWorkerProviderType::kForWindow which is a main
- // (top-level) frame.
+ // (top-level) frame. Reserved clients are ignored.
void HasMainFrameProviderHost(const GURL& origin,
BoolCallback callback) const;
@@ -245,15 +250,6 @@ class CONTENT_EXPORT ServiceWorkerContextCore
return live_versions_;
}
- // PlzNavigate
- // Methods to manage the map keeping track of all
- // ServiceWorkerNavigationHandleCores registered for ongoing navigations.
- void AddNavigationHandleCore(int service_worker_provider_id,
- ServiceWorkerNavigationHandleCore* handle);
- void RemoveNavigationHandleCore(int service_worker_provider_id);
- ServiceWorkerNavigationHandleCore* GetNavigationHandleCore(
- int service_worker_provider_id);
-
std::vector<ServiceWorkerRegistrationInfo> GetAllLiveRegistrationInfo();
std::vector<ServiceWorkerVersionInfo> GetAllLiveVersionInfo();
@@ -262,9 +258,6 @@ class CONTENT_EXPORT ServiceWorkerContextCore
void ProtectVersion(const scoped_refptr<ServiceWorkerVersion>& version);
void UnprotectVersion(int64_t version_id);
- // Returns new context-local unique ID.
- int GetNewServiceWorkerHandleId();
-
void ScheduleDeleteAndStartOver() const;
// Deletes all files on disk and restarts the system. This leaves the system
@@ -287,6 +280,9 @@ class CONTENT_EXPORT ServiceWorkerContextCore
// version. The count resets to zero when the worker successfully starts.
int GetVersionFailureCount(int64_t version_id);
+ // Called by ServiceWorkerStorage when StoreRegistration() succeeds.
+ void NotifyRegistrationStored(int64_t registration_id, const GURL& pattern);
+
URLLoaderFactoryGetter* loader_factory_getter() {
return loader_factory_getter_.get();
}
@@ -357,22 +353,18 @@ class CONTENT_EXPORT ServiceWorkerContextCore
std::map<int64_t /* version_id */, FailureInfo> failure_counts_;
- // PlzNavigate
- // Map of ServiceWorkerNavigationHandleCores used for navigation requests.
- std::map<int, ServiceWorkerNavigationHandleCore*>
- navigation_handle_cores_map_;
-
// IsServicificationEnabled
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
bool force_update_on_page_load_;
- int next_handle_id_;
// Set in RegisterServiceWorker(), cleared in ClearAllServiceWorkersForTest().
// This is used to avoid unnecessary disk read operation in tests. This value
// is false if Chrome was relaunched after service workers were registered.
bool was_service_worker_registered_;
- scoped_refptr<base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>>
- observer_list_;
+ using ServiceWorkerContextObserverList =
+ base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>;
+ const scoped_refptr<ServiceWorkerContextObserverList> observer_list_;
+
base::WeakPtrFactory<ServiceWorkerContextCore> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextCore);
diff --git a/chromium/content/browser/service_worker/service_worker_context_core_observer.h b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
index 1453739b55a..99966ec319b 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core_observer.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core_observer.h
@@ -79,16 +79,23 @@ class ServiceWorkerContextCoreObserver {
int process_id,
int thread_id,
const ConsoleMessage& message) {}
- // |web_contents_getter| is only set in PlzNavigate.
- virtual void OnControlleeAdded(
- int64_t version_id,
- const std::string& uuid,
- int process_id,
- int route_id,
- const base::Callback<WebContents*(void)>& web_contents_getter,
- blink::mojom::ServiceWorkerProviderType type) {}
+ virtual void OnControlleeAdded(int64_t version_id,
+ const std::string& uuid,
+ const ServiceWorkerClientInfo& info) {}
virtual void OnControlleeRemoved(int64_t version_id,
const std::string& uuid) {}
+ // Called when the ServiceWorkerContainer.register() promise is resolved.
+ //
+ // This is called before the service worker registration is persisted to
+ // storage. The implementation cannot assume that the ServiceWorkerContextCore
+ // will find the registration at this point.
+ virtual void OnRegistrationCompleted(int64_t registration_id,
+ const GURL& pattern) {}
+ // Called after a service worker registration is persisted to storage.
+ //
+ // This happens after OnRegistrationCompleted(). The implementation can assume
+ // that ServiceWorkerContextCore will find the registration, and can safely
+ // add user data to the registration.
virtual void OnRegistrationStored(int64_t registration_id,
const GURL& pattern) {}
virtual void OnRegistrationDeleted(int64_t registration_id,
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
index eaf2f2b0759..4722982af26 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
@@ -12,6 +12,7 @@
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_switches.h"
#include "net/base/load_flags.h"
#include "net/log/net_log.h"
@@ -23,31 +24,6 @@
namespace content {
-namespace {
-
-bool ShouldBypassCacheDueToUpdateViaCache(
- bool is_main_script,
- blink::mojom::ServiceWorkerUpdateViaCache cache_mode) {
- // TODO(https://crbug.com/675540): Remove the command line check and always
- // respect cache_mode when shipping updateViaCache flag to stable.
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExperimentalWebPlatformFeatures)) {
- return false;
- }
- switch (cache_mode) {
- case blink::mojom::ServiceWorkerUpdateViaCache::kImports:
- return is_main_script;
- case blink::mojom::ServiceWorkerUpdateViaCache::kNone:
- return true;
- case blink::mojom::ServiceWorkerUpdateViaCache::kAll:
- return false;
- }
- NOTREACHED() << static_cast<int>(cache_mode);
- return false;
-}
-
-} // namespace
-
ServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
@@ -220,8 +196,8 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
base::TimeDelta time_since_last_check =
base::Time::Now() - registration->last_update_check();
- if (ShouldBypassCacheDueToUpdateViaCache(is_main_script,
- registration->update_via_cache()) ||
+ if (ServiceWorkerUtils::ShouldBypassCacheDueToUpdateViaCache(
+ is_main_script, registration->update_via_cache()) ||
time_since_last_check > kServiceWorkerScriptMaxCacheAge ||
version_->force_bypass_cache_for_scripts()) {
extra_load_flags = net::LOAD_BYPASS_CACHE;
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
index c7e1e2194f7..9c653a1e5e2 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -137,11 +137,6 @@ class ServiceWorkerContextRequestHandlerTest : public testing::Test {
void TestBypassCache(const GURL& url,
ResourceType resource_type,
bool expect_bypass) {
- // TODO(https://crbug.com/675540): Remove the following command line switch
- // when updateViaCache is shipped to stable.
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableExperimentalWebPlatformFeatures);
-
std::unique_ptr<net::URLRequest> request(CreateRequest(url));
std::unique_ptr<ServiceWorkerContextRequestHandler> handler(
CreateHandler(resource_type));
@@ -190,37 +185,9 @@ TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateBefore24Hours) {
TestBypassCacheForImportedScript(false);
}
-// TODO(https://crbug.com/675540): Remove the
-// UpdateBefore24HoursWithoutUpdateViaCache test when the update_via_cache flag
-// is shipped to stable as this is to test the legacy behavior.
-TEST_F(ServiceWorkerContextRequestHandlerTest,
- UpdateBefore24HoursWithoutUpdateViaCache) {
- registration_->set_last_update_check(base::Time::Now());
- version_->SetStatus(ServiceWorkerVersion::NEW);
-
- // Conduct a resource fetch for the main script.
- base::HistogramTester histograms;
- std::unique_ptr<net::URLRequest> request(CreateRequest(script_url_));
- std::unique_ptr<ServiceWorkerContextRequestHandler> handler(
- CreateHandler(RESOURCE_TYPE_SERVICE_WORKER));
- std::unique_ptr<net::URLRequestJob> job(
- handler->MaybeCreateJob(request.get(), nullptr, nullptr));
- ASSERT_TRUE(job.get());
- ServiceWorkerWriteToCacheJob* sw_job =
- static_cast<ServiceWorkerWriteToCacheJob*>(job.get());
- histograms.ExpectUniqueSample(
- "ServiceWorker.ContextRequestHandlerStatus.NewWorker.MainScript",
- static_cast<int>(
- ServiceWorkerContextRequestHandler::CreateJobStatus::WRITE_JOB),
- 1);
-
- // Verify the net request is not initialized to bypass the browser cache.
- EXPECT_FALSE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
-}
-
TEST_F(ServiceWorkerContextRequestHandlerTest,
UpdateBefore24HoursWithUpdateViaCacheAll) {
- registration_->set_update_via_cache(
+ registration_->SetUpdateViaCache(
blink::mojom::ServiceWorkerUpdateViaCache::kAll);
// Give the registration a very recent last update time and pretend
// we're installing a new version.
@@ -233,7 +200,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest,
TEST_F(ServiceWorkerContextRequestHandlerTest,
UpdateBefore24HoursWithUpdateViaCacheNone) {
- registration_->set_update_via_cache(
+ registration_->SetUpdateViaCache(
blink::mojom::ServiceWorkerUpdateViaCache::kNone);
// Give the registration a very recent last update time and pretend
// we're installing a new version.
@@ -257,7 +224,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateAfter24Hours) {
TEST_F(ServiceWorkerContextRequestHandlerTest,
UpdateAfter24HoursWithUpdateViaCacheAll) {
- registration_->set_update_via_cache(
+ registration_->SetUpdateViaCache(
blink::mojom::ServiceWorkerUpdateViaCache::kAll);
// Give the registration a old update time and pretend
// we're installing a new version.
@@ -271,7 +238,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest,
TEST_F(ServiceWorkerContextRequestHandlerTest,
UpdateAfter24HoursWithUpdateViaCacheNone) {
- registration_->set_update_via_cache(
+ registration_->SetUpdateViaCache(
blink::mojom::ServiceWorkerUpdateViaCache::kNone);
// Give the registration a old update time and pretend
// we're installing a new version.
@@ -284,7 +251,7 @@ TEST_F(ServiceWorkerContextRequestHandlerTest,
}
TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateForceBypassCache) {
- registration_->set_update_via_cache(
+ registration_->SetUpdateViaCache(
blink::mojom::ServiceWorkerUpdateViaCache::kAll);
// Give the registration a very recent last update time and pretend
// we're installing a new version.
diff --git a/chromium/content/browser/service_worker/service_worker_context_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
index 06decdcd47b..df64683c72e 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -8,7 +8,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -112,6 +111,7 @@ class RejectActivateTestHelper : public EmbeddedWorkerTestHelper {
};
enum NotificationType {
+ REGISTRATION_COMPLETED,
REGISTRATION_STORED,
REGISTRATION_DELETED,
STORAGE_RECOVERED,
@@ -139,6 +139,14 @@ class ServiceWorkerContextTest : public ServiceWorkerContextCoreObserver,
void TearDown() override { helper_.reset(); }
// ServiceWorkerContextCoreObserver overrides.
+ void OnRegistrationCompleted(int64_t registration_id,
+ const GURL& pattern) override {
+ NotificationLog log;
+ log.type = REGISTRATION_COMPLETED;
+ log.pattern = pattern;
+ log.registration_id = registration_id;
+ notifications_.push_back(log);
+ }
void OnRegistrationStored(int64_t registration_id,
const GURL& pattern) override {
NotificationLog log;
@@ -200,8 +208,8 @@ class RecordableEmbeddedWorkerInstanceClient
// Make sure basic registration is working.
TEST_F(ServiceWorkerContextTest, Register) {
- GURL pattern("http://www.example.com/");
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern;
@@ -218,8 +226,8 @@ TEST_F(ServiceWorkerContextTest, Register) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- ASSERT_EQ(2UL, helper_->dispatched_events()->size());
- ASSERT_EQ(1UL, client->events().size());
+ ASSERT_EQ(2u, helper_->dispatched_events()->size());
+ ASSERT_EQ(1u, client->events().size());
EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
client->events()[0]);
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Install,
@@ -229,10 +237,13 @@ TEST_F(ServiceWorkerContextTest, Register) {
EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
- ASSERT_EQ(1u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ ASSERT_EQ(2u, notifications_.size());
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(pattern, notifications_[0].pattern);
EXPECT_EQ(registration_id, notifications_[0].registration_id);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
+ EXPECT_EQ(pattern, notifications_[1].pattern);
+ EXPECT_EQ(registration_id, notifications_[1].registration_id);
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
@@ -245,8 +256,8 @@ TEST_F(ServiceWorkerContextTest, Register) {
// registration callback should indicate success, but there should be no waiting
// or active worker in the registration.
TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
- GURL pattern("http://www.example.com/");
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern;
@@ -267,8 +278,8 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- ASSERT_EQ(1UL, helper_->dispatched_events()->size());
- ASSERT_EQ(2UL, client->events().size());
+ ASSERT_EQ(1u, helper_->dispatched_events()->size());
+ ASSERT_EQ(2u, client->events().size());
EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
client->events()[0]);
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Install,
@@ -279,7 +290,7 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
ASSERT_EQ(1u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(pattern, notifications_[0].pattern);
EXPECT_EQ(registration_id, notifications_[0].registration_id);
@@ -293,8 +304,8 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
// Test registration when the service worker rejects the activate event. The
// worker should be activated anyway.
TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
- GURL pattern("http://www.example.com/");
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern;
@@ -315,8 +326,8 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- ASSERT_EQ(2UL, helper_->dispatched_events()->size());
- ASSERT_EQ(1UL, client->events().size());
+ ASSERT_EQ(2u, helper_->dispatched_events()->size());
+ ASSERT_EQ(1u, client->events().size());
EXPECT_EQ(RecordableEmbeddedWorkerInstanceClient::Message::StartWorker,
client->events()[0]);
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Install,
@@ -326,10 +337,13 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
EXPECT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
- ASSERT_EQ(1u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ ASSERT_EQ(2u, notifications_.size());
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(pattern, notifications_[0].pattern);
EXPECT_EQ(registration_id, notifications_[0].registration_id);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
+ EXPECT_EQ(pattern, notifications_[1].pattern);
+ EXPECT_EQ(registration_id, notifications_[1].registration_id);
context()->storage()->FindRegistrationForId(
registration_id, pattern.GetOrigin(),
@@ -340,14 +354,14 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
// Make sure registrations are cleaned up when they are unregistered.
TEST_F(ServiceWorkerContextTest, Unregister) {
- GURL pattern("http://www.example.com/");
+ GURL pattern("https://www.example.com/");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern;
bool called = false;
int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/service_worker.js"), options,
+ GURL("https://www.example.com/service_worker.js"), options,
MakeRegisteredCallback(&called, &registration_id));
ASSERT_FALSE(called);
@@ -369,21 +383,24 @@ TEST_F(ServiceWorkerContextTest, Unregister) {
false /* expect_waiting */, false /* expect_active */));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(2u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ ASSERT_EQ(3u, notifications_.size());
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(pattern, notifications_[0].pattern);
EXPECT_EQ(registration_id, notifications_[0].registration_id);
- EXPECT_EQ(REGISTRATION_DELETED, notifications_[1].type);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
EXPECT_EQ(pattern, notifications_[1].pattern);
EXPECT_EQ(registration_id, notifications_[1].registration_id);
+ EXPECT_EQ(REGISTRATION_DELETED, notifications_[2].type);
+ EXPECT_EQ(pattern, notifications_[2].pattern);
+ EXPECT_EQ(registration_id, notifications_[2].registration_id);
}
// Make sure registrations are cleaned up when they are unregistered in bulk.
TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
- GURL origin1_p1("http://www.example.com/test");
- GURL origin1_p2("http://www.example.com/hello");
- GURL origin2_p1("http://www.example.com:8080/again");
- GURL origin3_p1("http://www.other.com/");
+ GURL origin1_p1("https://www.example.com/test");
+ GURL origin1_p2("https://www.example.com/hello");
+ GURL origin2_p1("https://www.example.com:8080/again");
+ GURL origin3_p1("https://www.other.com/");
int64_t registration_id1 = blink::mojom::kInvalidServiceWorkerRegistrationId;
int64_t registration_id2 = blink::mojom::kInvalidServiceWorkerRegistrationId;
int64_t registration_id3 = blink::mojom::kInvalidServiceWorkerRegistrationId;
@@ -394,7 +411,7 @@ TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = origin1_p1;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/service_worker.js"), options,
+ GURL("https://www.example.com/service_worker.js"), options,
MakeRegisteredCallback(&called, &registration_id1));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -406,7 +423,7 @@ TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = origin1_p2;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/service_worker2.js"), options,
+ GURL("https://www.example.com/service_worker2.js"), options,
MakeRegisteredCallback(&called, &registration_id2));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -418,7 +435,7 @@ TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = origin2_p1;
context()->RegisterServiceWorker(
- GURL("http://www.example.com:8080/service_worker3.js"), options,
+ GURL("https://www.example.com:8080/service_worker3.js"), options,
MakeRegisteredCallback(&called, &registration_id3));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -430,7 +447,7 @@ TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = origin3_p1;
context()->RegisterServiceWorker(
- GURL("http://www.other.com/service_worker4.js"), options,
+ GURL("https://www.other.com/service_worker4.js"), options,
MakeRegisteredCallback(&called, &registration_id4));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -474,30 +491,42 @@ TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(6u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ ASSERT_EQ(10u, notifications_.size());
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(registration_id1, notifications_[0].registration_id);
EXPECT_EQ(origin1_p1, notifications_[0].pattern);
EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
- EXPECT_EQ(origin1_p2, notifications_[1].pattern);
- EXPECT_EQ(registration_id2, notifications_[1].registration_id);
- EXPECT_EQ(REGISTRATION_STORED, notifications_[2].type);
- EXPECT_EQ(origin2_p1, notifications_[2].pattern);
- EXPECT_EQ(registration_id3, notifications_[2].registration_id);
+ EXPECT_EQ(registration_id1, notifications_[1].registration_id);
+ EXPECT_EQ(origin1_p1, notifications_[1].pattern);
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[2].type);
+ EXPECT_EQ(origin1_p2, notifications_[2].pattern);
+ EXPECT_EQ(registration_id2, notifications_[2].registration_id);
EXPECT_EQ(REGISTRATION_STORED, notifications_[3].type);
- EXPECT_EQ(origin3_p1, notifications_[3].pattern);
- EXPECT_EQ(registration_id4, notifications_[3].registration_id);
- EXPECT_EQ(REGISTRATION_DELETED, notifications_[4].type);
- EXPECT_EQ(origin1_p1, notifications_[4].pattern);
- EXPECT_EQ(registration_id1, notifications_[4].registration_id);
- EXPECT_EQ(REGISTRATION_DELETED, notifications_[5].type);
- EXPECT_EQ(origin1_p2, notifications_[5].pattern);
- EXPECT_EQ(registration_id2, notifications_[5].registration_id);
+ EXPECT_EQ(origin1_p2, notifications_[3].pattern);
+ EXPECT_EQ(registration_id2, notifications_[3].registration_id);
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[4].type);
+ EXPECT_EQ(origin2_p1, notifications_[4].pattern);
+ EXPECT_EQ(registration_id3, notifications_[4].registration_id);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[5].type);
+ EXPECT_EQ(origin2_p1, notifications_[5].pattern);
+ EXPECT_EQ(registration_id3, notifications_[5].registration_id);
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[6].type);
+ EXPECT_EQ(origin3_p1, notifications_[6].pattern);
+ EXPECT_EQ(registration_id4, notifications_[6].registration_id);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[7].type);
+ EXPECT_EQ(origin3_p1, notifications_[7].pattern);
+ EXPECT_EQ(registration_id4, notifications_[7].registration_id);
+ EXPECT_EQ(REGISTRATION_DELETED, notifications_[8].type);
+ EXPECT_EQ(origin1_p1, notifications_[8].pattern);
+ EXPECT_EQ(registration_id1, notifications_[8].registration_id);
+ EXPECT_EQ(REGISTRATION_DELETED, notifications_[9].type);
+ EXPECT_EQ(origin1_p2, notifications_[9].pattern);
+ EXPECT_EQ(registration_id2, notifications_[9].registration_id);
}
// Make sure registering a new script shares an existing registration.
TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
- GURL pattern("http://www.example.com/");
+ GURL pattern("https://www.example.com/");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern;
@@ -505,7 +534,7 @@ TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
int64_t old_registration_id =
blink::mojom::kInvalidServiceWorkerRegistrationId;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/service_worker.js"), options,
+ GURL("https://www.example.com/service_worker.js"), options,
MakeRegisteredCallback(&called, &old_registration_id));
ASSERT_FALSE(called);
@@ -518,7 +547,7 @@ TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
int64_t new_registration_id =
blink::mojom::kInvalidServiceWorkerRegistrationId;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/service_worker_new.js"), options,
+ GURL("https://www.example.com/service_worker_new.js"), options,
MakeRegisteredCallback(&called, &new_registration_id));
ASSERT_FALSE(called);
@@ -529,20 +558,26 @@ TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
new_registration_id);
EXPECT_EQ(old_registration_id, new_registration_id);
- ASSERT_EQ(2u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ ASSERT_EQ(4u, notifications_.size());
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(pattern, notifications_[0].pattern);
EXPECT_EQ(old_registration_id, notifications_[0].registration_id);
EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
EXPECT_EQ(pattern, notifications_[1].pattern);
- EXPECT_EQ(new_registration_id, notifications_[1].registration_id);
+ EXPECT_EQ(old_registration_id, notifications_[1].registration_id);
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[2].type);
+ EXPECT_EQ(pattern, notifications_[2].pattern);
+ EXPECT_EQ(new_registration_id, notifications_[2].registration_id);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[3].type);
+ EXPECT_EQ(pattern, notifications_[3].pattern);
+ EXPECT_EQ(new_registration_id, notifications_[3].registration_id);
}
// Make sure that when registering a duplicate pattern+script_url
// combination, that the same registration is used.
TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
- GURL pattern("http://www.example.com/");
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern;
@@ -571,20 +606,23 @@ TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
ASSERT_TRUE(called);
EXPECT_EQ(old_registration_id, new_registration_id);
- ASSERT_EQ(2u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ ASSERT_EQ(3u, notifications_.size());
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(pattern, notifications_[0].pattern);
EXPECT_EQ(old_registration_id, notifications_[0].registration_id);
EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
EXPECT_EQ(pattern, notifications_[1].pattern);
EXPECT_EQ(old_registration_id, notifications_[1].registration_id);
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[2].type);
+ EXPECT_EQ(pattern, notifications_[2].pattern);
+ EXPECT_EQ(old_registration_id, notifications_[2].registration_id);
}
TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
const int kRenderProcessId1 = 1;
const int kRenderProcessId2 = 2;
- const GURL kOrigin1 = GURL("http://www.example.com/");
- const GURL kOrigin2 = GURL("https://www.example.com/");
+ const GURL kOrigin1 = GURL("https://www.example.com/");
+ const GURL kOrigin2 = GURL("https://another-origin.example.net/");
int provider_id = 1;
std::vector<ServiceWorkerRemoteProviderEndpoint> remote_endpoints;
@@ -617,14 +655,15 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
// CreateProviderHostForServiceWorkerContext, the provider_id is not a fixed
// number.
blink::mojom::ServiceWorkerRegistrationOptions registration_opt;
- registration_opt.scope = GURL("http://www.example.com/test/");
+ registration_opt.scope = GURL("https://another-origin.example.net/test/");
scoped_refptr<ServiceWorkerRegistration> registration =
base::MakeRefCounted<ServiceWorkerRegistration>(
registration_opt, 1L /* registration_id */,
helper_->context()->AsWeakPtr());
scoped_refptr<ServiceWorkerVersion> version =
base::MakeRefCounted<ServiceWorkerVersion>(
- registration.get(), GURL("http://www.example.com/test/script_url"),
+ registration.get(),
+ GURL("https://another-origin.example.net/test/script_url"),
1L /* version_id */, helper_->context()->AsWeakPtr());
// CreateProviderHostForServiceWorkerContext calls
// ServiceWorkerProviderHost::CompleteStartWorkerPreparation, which requires a
@@ -649,7 +688,8 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
// Iterate over the client provider hosts that belong to kOrigin1.
std::set<ServiceWorkerProviderHost*> results;
- for (auto it = context()->GetClientProviderHostIterator(kOrigin1);
+ for (auto it = context()->GetClientProviderHostIterator(
+ kOrigin1, true /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
results.insert(it->GetProviderHost());
}
@@ -660,7 +700,8 @@ TEST_F(ServiceWorkerContextTest, ProviderHostIterator) {
// Iterate over the provider hosts that belong to kOrigin2.
// (This should not include host4 as it's not for controllee.)
results.clear();
- for (auto it = context()->GetClientProviderHostIterator(kOrigin2);
+ for (auto it = context()->GetClientProviderHostIterator(
+ kOrigin2, true /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
results.insert(it->GetProviderHost());
}
@@ -685,8 +726,8 @@ class ServiceWorkerContextRecoveryTest
};
TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
- GURL pattern("http://www.example.com/");
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL pattern("https://www.example.com/");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern;
@@ -713,10 +754,6 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
false /* expect_waiting */, true /* expect_active */));
content::RunAllTasksUntilIdle();
- // Next handle id should be 1 (the next call should return 2) because
- // registered worker should have taken ID 0.
- EXPECT_EQ(1, context()->GetNewServiceWorkerHandleId());
-
context()->ScheduleDeleteAndStartOver();
// The storage is disabled while the recovery process is running, so the
@@ -749,18 +786,20 @@ TEST_P(ServiceWorkerContextRecoveryTest, DeleteAndStartOver) {
false /* expect_waiting */, true /* expect_active */));
content::RunAllTasksUntilIdle();
- // The new context should take over next handle id. ID 2 should have been
- // taken by the running registration, so the following method calls return 3.
- EXPECT_EQ(3, context()->GetNewServiceWorkerHandleId());
-
- ASSERT_EQ(3u, notifications_.size());
- EXPECT_EQ(REGISTRATION_STORED, notifications_[0].type);
+ ASSERT_EQ(5u, notifications_.size());
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[0].type);
EXPECT_EQ(pattern, notifications_[0].pattern);
EXPECT_EQ(registration_id, notifications_[0].registration_id);
- EXPECT_EQ(STORAGE_RECOVERED, notifications_[1].type);
- EXPECT_EQ(REGISTRATION_STORED, notifications_[2].type);
- EXPECT_EQ(pattern, notifications_[2].pattern);
- EXPECT_EQ(registration_id, notifications_[2].registration_id);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[1].type);
+ EXPECT_EQ(pattern, notifications_[1].pattern);
+ EXPECT_EQ(registration_id, notifications_[1].registration_id);
+ EXPECT_EQ(STORAGE_RECOVERED, notifications_[2].type);
+ EXPECT_EQ(REGISTRATION_COMPLETED, notifications_[3].type);
+ EXPECT_EQ(pattern, notifications_[3].pattern);
+ EXPECT_EQ(registration_id, notifications_[3].registration_id);
+ EXPECT_EQ(REGISTRATION_STORED, notifications_[4].type);
+ EXPECT_EQ(pattern, notifications_[4].pattern);
+ EXPECT_EQ(registration_id, notifications_[4].registration_id);
}
INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRecoveryTest,
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.cc b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
index 983547fe8ed..e4d1f2758c4 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
@@ -337,17 +337,13 @@ void ServiceWorkerContextWatcher::OnReportConsoleMessage(
void ServiceWorkerContextWatcher::OnControlleeAdded(
int64_t version_id,
const std::string& uuid,
- int process_id,
- int route_id,
- const base::Callback<WebContents*(void)>& web_contents_getter,
- blink::mojom::ServiceWorkerProviderType type) {
+ const ServiceWorkerClientInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto it = version_info_map_.find(version_id);
if (it == version_info_map_.end())
return;
ServiceWorkerVersionInfo* version = it->second.get();
- version->clients[uuid] = ServiceWorkerVersionInfo::ClientInfo(
- process_id, route_id, web_contents_getter, type);
+ version->clients[uuid] = info;
SendVersionInfo(*version);
}
@@ -362,8 +358,9 @@ void ServiceWorkerContextWatcher::OnControlleeRemoved(int64_t version_id,
SendVersionInfo(*version);
}
-void ServiceWorkerContextWatcher::OnRegistrationStored(int64_t registration_id,
- const GURL& pattern) {
+void ServiceWorkerContextWatcher::OnRegistrationCompleted(
+ int64_t registration_id,
+ const GURL& pattern) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
SendRegistrationInfo(registration_id, pattern,
ServiceWorkerRegistrationInfo::IS_NOT_DELETED);
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.h b/chromium/content/browser/service_worker/service_worker_context_watcher.h
index aa432522b51..68f86f49e37 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.h
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.h
@@ -103,17 +103,13 @@ class CONTENT_EXPORT ServiceWorkerContextWatcher
int process_id,
int thread_id,
const ConsoleMessage& message) override;
- void OnControlleeAdded(
- int64_t version_id,
- const std::string& uuid,
- int process_id,
- int route_id,
- const base::Callback<WebContents*(void)>& web_contents_getter,
- blink::mojom::ServiceWorkerProviderType type) override;
+ void OnControlleeAdded(int64_t version_id,
+ const std::string& uuid,
+ const ServiceWorkerClientInfo& info) override;
void OnControlleeRemoved(int64_t version_id,
const std::string& uuid) override;
- void OnRegistrationStored(int64_t registration_id,
- const GURL& pattern) override;
+ void OnRegistrationCompleted(int64_t registration_id,
+ const GURL& pattern) override;
void OnRegistrationDeleted(int64_t registration_id,
const GURL& pattern) override;
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
index 241193f74fd..b91bad88fcd 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -165,12 +165,9 @@ bool ServiceWorkerContext::ScopeMatches(const GURL& scope, const GURL& url) {
ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
BrowserContext* browser_context)
: core_observer_list_(
- new base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>()),
+ base::MakeRefCounted<ServiceWorkerContextObserverList>()),
process_manager_(
- std::make_unique<ServiceWorkerProcessManager>(browser_context)),
- is_incognito_(false),
- storage_partition_(nullptr),
- resource_context_(nullptr) {
+ std::make_unique<ServiceWorkerProcessManager>(browser_context)) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Add this object as an observer of the wrapped |context_core_|. This lets us
@@ -245,10 +242,11 @@ ResourceContext* ServiceWorkerContextWrapper::resource_context() {
return resource_context_;
}
-void ServiceWorkerContextWrapper::OnRegistrationStored(int64_t registration_id,
- const GURL& pattern) {
+void ServiceWorkerContextWrapper::OnRegistrationCompleted(
+ int64_t registration_id,
+ const GURL& pattern) {
for (auto& observer : observer_list_)
- observer.OnRegistrationStored(pattern);
+ observer.OnRegistrationCompleted(pattern);
}
void ServiceWorkerContextWrapper::AddObserver(
@@ -527,7 +525,8 @@ ServiceWorkerContextWrapper::GetProviderHostIds(const GURL& origin) const {
new std::vector<std::pair<int, int>>());
for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
- context_core_->GetClientProviderHostIterator(origin);
+ context_core_->GetClientProviderHostIterator(
+ origin, false /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
ServiceWorkerProviderHost* provider_host = it->GetProviderHost();
provider_host_ids->push_back(
@@ -858,10 +857,10 @@ void ServiceWorkerContextWrapper::InitInternal(
quota_manager_proxy->RegisterClient(new ServiceWorkerQuotaClient(this));
}
- context_core_.reset(new ServiceWorkerContextCore(
+ context_core_ = std::make_unique<ServiceWorkerContextCore>(
user_data_directory, std::move(database_task_runner), quota_manager_proxy,
special_storage_policy, loader_factory_getter, core_observer_list_.get(),
- this));
+ this);
}
void ServiceWorkerContextWrapper::ShutdownOnIO() {
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.h b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
index 96ec90d9a1c..e06300d2141 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -98,8 +98,8 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
}
// ServiceWorkerContextCoreObserver implementation:
- void OnRegistrationStored(int64_t registration_id,
- const GURL& pattern) override;
+ void OnRegistrationCompleted(int64_t registration_id,
+ const GURL& pattern) override;
// ServiceWorkerContext implementation:
void AddObserver(ServiceWorkerContextObserver* observer) override;
@@ -343,9 +343,9 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// Observers of |context_core_| which live within content's implementation
// boundary. Shared with |context_core_|.
- const scoped_refptr<
- base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>>
- core_observer_list_;
+ using ServiceWorkerContextObserverList =
+ base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>;
+ const scoped_refptr<ServiceWorkerContextObserverList> core_observer_list_;
// Observers which live outside content's implementation boundary. Observer
// methods will always be dispatched on the UI thread.
@@ -356,13 +356,13 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
std::unique_ptr<ServiceWorkerContextCore> context_core_;
// Initialized in Init(); true if the user data directory is empty.
- bool is_incognito_;
+ bool is_incognito_ = false;
// Raw pointer to the StoragePartitionImpl owning |this|.
- StoragePartitionImpl* storage_partition_;
+ StoragePartitionImpl* storage_partition_ = nullptr;
// The ResourceContext associated with this context.
- ResourceContext* resource_context_;
+ ResourceContext* resource_context_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextWrapper);
};
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
index ea569859aef..d2dcaa67d40 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -268,8 +268,13 @@ ServiceWorkerControlleeRequestHandler::MaybeCreateSubresourceLoaderParams() {
controller_info->endpoint =
provider_host_->GetControllerServiceWorkerPtr().PassInterface();
controller_info->client_id = provider_host_->client_uuid();
- controller_info->object_info = provider_host_->GetOrCreateServiceWorkerHandle(
- provider_host_->controller());
+ base::WeakPtr<ServiceWorkerHandle> handle =
+ provider_host_->GetOrCreateServiceWorkerHandle(
+ provider_host_->controller());
+ if (handle) {
+ params.controller_service_worker_handle = handle;
+ controller_info->object_info = handle->CreateIncompleteObjectInfo();
+ }
params.controller_service_worker_info = std::move(controller_info);
return base::Optional<SubresourceLoaderParams>(std::move(params));
}
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index 746351acfb8..c34711b2eb7 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -1257,7 +1257,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
leveldb_env::Options options;
options.create_if_missing = create_if_missing;
if (IsDatabaseInMemory()) {
- env_.reset(leveldb_chrome::NewMemEnv(leveldb::Env::Default()));
+ env_ = leveldb_chrome::NewMemEnv("service-worker");
options.env = env_.get();
} else {
options.env = g_service_worker_env.Pointer();
@@ -1466,15 +1466,10 @@ void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
for (uint32_t feature : registration.used_features)
data.add_used_features(feature);
- // TODO(https://crbug.com/675540): Remove the the command line check and
- // always set to data when shipping the updateViaCache flag to stable.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExperimentalWebPlatformFeatures)) {
- data.set_update_via_cache(
- static_cast<
- ServiceWorkerRegistrationData_ServiceWorkerUpdateViaCacheType>(
- registration.update_via_cache));
- }
+ data.set_update_via_cache(
+ static_cast<
+ ServiceWorkerRegistrationData_ServiceWorkerUpdateViaCacheType>(
+ registration.update_via_cache));
std::string value;
bool success = data.SerializeToString(&value);
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
index 5401fdb46d8..0f7a0bbd637 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -50,16 +50,12 @@ const uint32_t kServiceWorkerFilteredMessageClasses[] = {
} // namespace
-ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
- int render_process_id,
- ResourceContext* resource_context)
+ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(int render_process_id)
: BrowserMessageFilter(kServiceWorkerFilteredMessageClasses,
arraysize(kServiceWorkerFilteredMessageClasses)),
BrowserAssociatedInterface<mojom::ServiceWorkerDispatcherHost>(this,
this),
render_process_id_(render_process_id),
- resource_context_(resource_context),
- channel_ready_(false),
weak_ptr_factory_(this) {}
ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
@@ -90,18 +86,6 @@ void ServiceWorkerDispatcherHost::Init(
phase_ = Phase::kAddedToContext;
}
-void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Channel* channel) {
- TRACE_EVENT0("ServiceWorker",
- "ServiceWorkerDispatcherHost::OnFilterAdded");
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- channel_ready_ = true;
- std::vector<std::unique_ptr<IPC::Message>> messages;
- messages.swap(pending_messages_);
- for (auto& message : messages) {
- BrowserMessageFilter::Send(message.release());
- }
-}
-
void ServiceWorkerDispatcherHost::OnFilterRemoved() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Don't wait until the destructor to teardown since a new dispatcher host
@@ -112,7 +96,6 @@ void ServiceWorkerDispatcherHost::OnFilterRemoved() {
}
phase_ = Phase::kRemovedFromContext;
context_wrapper_ = nullptr;
- channel_ready_ = false;
}
void ServiceWorkerDispatcherHost::OnDestruct() const {
@@ -126,17 +109,6 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
return false;
}
-bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
- if (channel_ready_) {
- BrowserMessageFilter::Send(message);
- // Don't bother passing through Send()'s result: it's not reliable.
- return true;
- }
-
- pending_messages_.push_back(base::WrapUnique(message));
- return true;
-}
-
base::WeakPtr<ServiceWorkerDispatcherHost>
ServiceWorkerDispatcherHost::AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
@@ -164,13 +136,10 @@ void ServiceWorkerDispatcherHost::OnProviderCreated(
return;
}
- // Retrieve the provider host previously created for navigation requests.
- std::unique_ptr<ServiceWorkerProviderHost> provider_host;
- ServiceWorkerNavigationHandleCore* navigation_handle_core =
- GetContext()->GetNavigationHandleCore(info.provider_id);
- if (navigation_handle_core != nullptr)
- provider_host = navigation_handle_core->RetrievePreCreatedHost();
-
+ // Retrieve the provider host pre-created for the navigation.
+ std::unique_ptr<ServiceWorkerProviderHost> provider_host =
+ GetContext()->ReleaseProviderHost(ChildProcessHost::kInvalidUniqueID,
+ info.provider_id);
// If no host is found, create one.
// TODO(crbug.com/789111#c14): This is probably not right, see bug.
if (!provider_host) {
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
index 89a2aae8739..0a096b2d367 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -25,7 +25,6 @@
namespace content {
-class ResourceContext;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
@@ -58,33 +57,23 @@ FORWARD_DECLARE_TEST(BackgroundSyncManagerTest,
// InterfacePtrs on the same render process are bound to the same
// content::ServiceWorkerDispatcherHost. This can be overridden only for
// testing.
+//
+// TODO(leonhsl): This class no longer needs to be a BrowserMessageFilter
+// because we are already in a pure Mojo world.
class CONTENT_EXPORT ServiceWorkerDispatcherHost
: public BrowserMessageFilter,
public BrowserAssociatedInterface<mojom::ServiceWorkerDispatcherHost>,
public mojom::ServiceWorkerDispatcherHost {
public:
- ServiceWorkerDispatcherHost(
- int render_process_id,
- ResourceContext* resource_context);
+ explicit ServiceWorkerDispatcherHost(int render_process_id);
void Init(ServiceWorkerContextWrapper* context_wrapper);
// BrowserMessageFilter implementation
- void OnFilterAdded(IPC::Channel* channel) override;
void OnFilterRemoved() override;
void OnDestruct() const override;
bool OnMessageReceived(const IPC::Message& message) override;
- // IPC::Sender implementation
-
- // Send() queues the message until the underlying sender is ready. This
- // class assumes that Send() can only fail after that when the renderer
- // process has terminated, at which point the whole instance will eventually
- // be destroyed.
- bool Send(IPC::Message* message) override;
-
- ResourceContext* resource_context() { return resource_context_; }
-
base::WeakPtr<ServiceWorkerDispatcherHost> AsWeakPtr();
protected:
@@ -117,15 +106,11 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost
ServiceWorkerContextCore* GetContext();
const int render_process_id_;
- ResourceContext* resource_context_;
// Only accessed on the IO thread.
Phase phase_ = Phase::kInitial;
// Only accessed on the IO thread.
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
- bool channel_ready_; // True after BrowserMessageFilter::sender_ != NULL.
- std::vector<std::unique_ptr<IPC::Message>> pending_messages_;
-
base::WeakPtrFactory<ServiceWorkerDispatcherHost> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherHost);
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index b4394c09853..1505284dc5f 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -25,7 +25,6 @@
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
-#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
@@ -87,9 +86,8 @@ std::unique_ptr<ServiceWorkerNavigationHandleCore> CreateNavigationHandleCore(
class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
public:
TestingServiceWorkerDispatcherHost(int process_id,
- ResourceContext* resource_context,
EmbeddedWorkerTestHelper* helper)
- : ServiceWorkerDispatcherHost(process_id, resource_context),
+ : ServiceWorkerDispatcherHost(process_id),
bad_messages_received_count_(0),
helper_(helper) {}
@@ -130,8 +128,8 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
helper_.reset(helper.release());
// Replace the default dispatcher host.
int process_id = helper_->mock_render_process_id();
- dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
- process_id, &resource_context_, helper_.get());
+ dispatcher_host_ =
+ new TestingServiceWorkerDispatcherHost(process_id, helper_.get());
helper_->RegisterDispatcherHost(process_id, nullptr);
dispatcher_host_->Init(context_wrapper());
}
@@ -179,7 +177,6 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
}
TestBrowserThreadBundle browser_thread_bundle_;
- content::MockResourceContext resource_context_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
scoped_refptr<ServiceWorkerRegistration> registration_;
@@ -198,7 +195,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
navigation_handle_core =
CreateNavigationHandleCore(helper_->context_wrapper());
ASSERT_TRUE(navigation_handle_core);
- std::unique_ptr<ServiceWorkerProviderHost> host1 =
+ base::WeakPtr<ServiceWorkerProviderHost> host1 =
ServiceWorkerProviderHost::PreCreateNavigationHost(
context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::RepeatingCallback<WebContents*(void)>());
@@ -210,7 +207,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
host1->provider_id(), 1 /* route_id */, host1->provider_type(),
host1->is_parent_frame_secure());
RemoteProviderInfo remote_info_1 = SetupProviderHostInfoPtrs(&host_info_1);
- navigation_handle_core->DidPreCreateProviderHost(std::move(host1));
+ navigation_handle_core->DidPreCreateProviderHost(host1->provider_id());
dispatcher_host_->OnProviderCreated(std::move(host_info_1));
EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId1));
@@ -229,8 +226,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
navigation_handle_core =
CreateNavigationHandleCore(helper_->context_wrapper());
ASSERT_TRUE(navigation_handle_core);
- // ProviderHost should be created before OnProviderCreated.
- std::unique_ptr<ServiceWorkerProviderHost> host2 =
+ base::WeakPtr<ServiceWorkerProviderHost> host2 =
ServiceWorkerProviderHost::PreCreateNavigationHost(
context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::RepeatingCallback<WebContents*(void)>());
@@ -239,7 +235,7 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
host2->provider_id(), 2 /* route_id */, host2->provider_type(),
host2->is_parent_frame_secure());
RemoteProviderInfo remote_info_2 = SetupProviderHostInfoPtrs(&host_info_2);
- navigation_handle_core->DidPreCreateProviderHost(std::move(host2));
+ navigation_handle_core->DidPreCreateProviderHost(host2->provider_id());
// Deletion of the dispatcher_host should cause providers for that
// process to get deleted as well.
@@ -251,8 +247,8 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
}
TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
- GURL pattern = GURL("http://www.example.com/");
- GURL script_url = GURL("http://www.example.com/service_worker.js");
+ GURL pattern = GURL("https://www.example.com/");
+ GURL script_url = GURL("https://www.example.com/service_worker.js");
int process_id = helper_->mock_render_process_id();
SendProviderCreated(blink::mojom::ServiceWorkerProviderType::kForWindow,
@@ -286,9 +282,9 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
// We should be able to hook up a new dispatcher host although the old object
// is not yet destroyed. This is what the browser does when reusing a crashed
// render process.
- scoped_refptr<TestingServiceWorkerDispatcherHost> new_dispatcher_host(
- new TestingServiceWorkerDispatcherHost(process_id, &resource_context_,
- helper_.get()));
+ auto new_dispatcher_host =
+ base::MakeRefCounted<TestingServiceWorkerDispatcherHost>(process_id,
+ helper_.get());
new_dispatcher_host->Init(context_wrapper());
// To show the new dispatcher can operate, simulate provider creation. Since
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index da9ecafedbf..740ca70679f 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -53,7 +53,13 @@ class DelegatingURLLoader final : public network::mojom::URLLoader {
: binding_(this), loader_(std::move(loader)) {}
~DelegatingURLLoader() override {}
- void FollowRedirect() override { loader_->FollowRedirect(); }
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ loader_->FollowRedirect(base::nullopt);
+ }
void ProceedWithResponse() override { NOTREACHED(); }
void SetPriority(net::RequestPriority priority,
@@ -103,13 +109,13 @@ void NotifyNavigationPreloadRequestSentOnUI(
void NotifyNavigationPreloadResponseReceivedOnUI(
const GURL& url,
- const network::ResourceResponseHead& head,
+ scoped_refptr<network::ResourceResponse> response,
const std::pair<int, int>& worker_id,
const std::string& request_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ServiceWorkerDevToolsManager::GetInstance()
->NavigationPreloadResponseReceived(worker_id.first, worker_id.second,
- request_id, url, head);
+ request_id, url, response->head);
}
void NotifyNavigationPreloadCompletedOnUI(
@@ -134,9 +140,12 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
: binding_(this),
client_(std::move(client)),
on_response_(std::move(on_response)),
- url_(request.url) {
+ url_(request.url),
+ devtools_enabled_(request.report_raw_headers) {
+ if (!devtools_enabled_)
+ return;
AddDevToolsCallback(
- base::Bind(&NotifyNavigationPreloadRequestSentOnUI, request));
+ base::BindOnce(&NotifyNavigationPreloadRequestSentOnUI, request));
}
~DelegatingURLLoaderClient() override {
if (!completed_) {
@@ -144,8 +153,10 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
network::URLLoaderCompletionStatus status;
status.error_code = net::ERR_ABORTED;
client_->OnComplete(status);
+ if (!devtools_enabled_)
+ return;
AddDevToolsCallback(
- base::Bind(&NotifyNavigationPreloadCompletedOnUI, status));
+ base::BindOnce(&NotifyNavigationPreloadCompletedOnUI, status));
}
}
@@ -176,8 +187,14 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
client_->OnReceiveResponse(head, std::move(downloaded_file));
DCHECK(on_response_);
std::move(on_response_).Run();
+ if (!devtools_enabled_)
+ return;
+ // Make a deep copy of ResourceResponseHead before passing it cross-thread.
+ auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
+ resource_response->head = head;
AddDevToolsCallback(
- base::Bind(&NotifyNavigationPreloadResponseReceivedOnUI, url_, head));
+ base::BindOnce(&NotifyNavigationPreloadResponseReceivedOnUI, url_,
+ resource_response->DeepCopy()));
}
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override {
@@ -186,11 +203,18 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
// OnReceiveRedirect IPC and don't send OnComplete IPC. The service worker
// will clean up the preload request when OnReceiveRedirect() is called.
client_->OnReceiveRedirect(redirect_info, head);
+
+ if (!devtools_enabled_)
+ return;
+ // Make a deep copy of ResourceResponseHead before passing it cross-thread.
+ auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
+ resource_response->head = head;
AddDevToolsCallback(
- base::Bind(&NotifyNavigationPreloadResponseReceivedOnUI, url_, head));
+ base::BindOnce(&NotifyNavigationPreloadResponseReceivedOnUI, url_,
+ resource_response->DeepCopy()));
network::URLLoaderCompletionStatus status;
AddDevToolsCallback(
- base::Bind(&NotifyNavigationPreloadCompletedOnUI, status));
+ base::BindOnce(&NotifyNavigationPreloadCompletedOnUI, status));
}
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override {
@@ -201,8 +225,10 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
return;
completed_ = true;
client_->OnComplete(status);
+ if (!devtools_enabled_)
+ return;
AddDevToolsCallback(
- base::Bind(&NotifyNavigationPreloadCompletedOnUI, status));
+ base::BindOnce(&NotifyNavigationPreloadCompletedOnUI, status));
}
void Bind(network::mojom::URLLoaderClientPtr* ptr_info) {
@@ -211,7 +237,7 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
private:
void MaybeRunDevToolsCallbacks() {
- if (!worker_id_)
+ if (!worker_id_ || !devtools_enabled_)
return;
while (!devtools_callbacks.empty()) {
BrowserThread::PostTask(
@@ -222,7 +248,7 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
}
}
void AddDevToolsCallback(
- base::Callback<void(const WorkerId&, const std::string&)> callback) {
+ base::OnceCallback<void(const WorkerId&, const std::string&)> callback) {
devtools_callbacks.push(std::move(callback));
MaybeRunDevToolsCallbacks();
}
@@ -232,10 +258,11 @@ class DelegatingURLLoaderClient final : public network::mojom::URLLoaderClient {
base::OnceClosure on_response_;
bool completed_ = false;
const GURL url_;
+ const bool devtools_enabled_;
base::Optional<std::pair<int, int>> worker_id_;
std::string devtools_request_id_;
- base::queue<base::Callback<void(const WorkerId&, const std::string&)>>
+ base::queue<base::OnceCallback<void(const WorkerId&, const std::string&)>>
devtools_callbacks;
DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoaderClient);
};
diff --git a/chromium/content/browser/service_worker/service_worker_handle.cc b/chromium/content/browser/service_worker/service_worker_handle.cc
index 1b87b9edab0..777cea9149d 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.cc
+++ b/chromium/content/browser/service_worker/service_worker_handle.cc
@@ -11,6 +11,7 @@
#include "content/browser/service_worker/service_worker_type_converters.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/common/browser_side_navigation_policy.h"
namespace content {
@@ -87,6 +88,9 @@ bool SetSourceClientInfo(
return true;
}
+// The output |event| must be sent over Mojo immediately after this function
+// returns. See ServiceWorkerHandle::CreateCompleteObjectInfoToSend() for
+// details.
bool SetSourceServiceWorkerInfo(scoped_refptr<ServiceWorkerVersion> worker,
base::WeakPtr<ServiceWorkerProviderHost>
source_service_worker_provider_host,
@@ -98,9 +102,16 @@ bool SetSourceServiceWorkerInfo(scoped_refptr<ServiceWorkerVersion> worker,
DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
source_service_worker_provider_host->provider_type());
- blink::mojom::ServiceWorkerObjectInfoPtr source_worker_info =
+ blink::mojom::ServiceWorkerObjectInfoPtr source_worker_info;
+ base::WeakPtr<ServiceWorkerHandle> service_worker_handle =
worker->provider_host()->GetOrCreateServiceWorkerHandle(
source_service_worker_provider_host->running_hosted_version());
+ if (service_worker_handle) {
+ // CreateCompleteObjectInfoToSend() is safe because |source_worker_info|
+ // will be sent immediately by the caller of this function.
+ source_worker_info =
+ service_worker_handle->CreateCompleteObjectInfoToSend();
+ }
(*event)->source_info_for_service_worker = std::move(source_worker_info);
// Hide the service worker url if the service worker has a unique origin.
@@ -159,7 +170,6 @@ ServiceWorkerHandle::ServiceWorkerHandle(
provider_host_(provider_host),
provider_origin_(url::Origin::Create(provider_host->document_url())),
provider_id_(provider_host->provider_id()),
- handle_id_(context->GetNewServiceWorkerHandleId()),
version_(std::move(version)),
weak_ptr_factory_(this) {
DCHECK(context_ && provider_host_ && version_);
@@ -170,20 +180,37 @@ ServiceWorkerHandle::ServiceWorkerHandle(
}
ServiceWorkerHandle::~ServiceWorkerHandle() {
+ // TODO(crbug.com/838410): These CHECKs are temporary debugging for the linked
+ // bug.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ CHECK(!in_dtor_);
+ in_dtor_ = true;
+
version_->RemoveListener(this);
}
void ServiceWorkerHandle::OnVersionStateChanged(ServiceWorkerVersion* version) {
DCHECK(version);
- provider_host_->SendServiceWorkerStateChangedMessage(
- handle_id_,
- mojo::ConvertTo<blink::mojom::ServiceWorkerState>(version->status()));
+ blink::mojom::ServiceWorkerState state =
+ mojo::ConvertTo<blink::mojom::ServiceWorkerState>(version->status());
+ remote_objects_.ForAllPtrs(
+ [state](blink::mojom::ServiceWorkerObject* remote_object) {
+ remote_object->StateChanged(state);
+ });
}
blink::mojom::ServiceWorkerObjectInfoPtr
-ServiceWorkerHandle::CreateObjectInfo() {
+ServiceWorkerHandle::CreateCompleteObjectInfoToSend() {
+ auto info = CreateIncompleteObjectInfo();
+ blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object;
+ info->request = mojo::MakeRequest(&remote_object);
+ remote_objects_.AddPtr(std::move(remote_object));
+ return info;
+}
+
+blink::mojom::ServiceWorkerObjectInfoPtr
+ServiceWorkerHandle::CreateIncompleteObjectInfo() {
auto info = blink::mojom::ServiceWorkerObjectInfo::New();
- info->handle_id = handle_id_;
info->url = version_->script_url();
info->state =
mojo::ConvertTo<blink::mojom::ServiceWorkerState>(version_->status());
@@ -192,6 +219,23 @@ ServiceWorkerHandle::CreateObjectInfo() {
return info;
}
+void ServiceWorkerHandle::AddRemoteObjectPtrAndUpdateState(
+ blink::mojom::ServiceWorkerObjectAssociatedPtrInfo remote_object_ptr_info,
+ blink::mojom::ServiceWorkerState sent_state) {
+ DCHECK(remote_object_ptr_info.is_valid());
+ blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object;
+ remote_object.Bind(std::move(remote_object_ptr_info));
+ auto state =
+ mojo::ConvertTo<blink::mojom::ServiceWorkerState>(version_->status());
+ if (sent_state != state)
+ remote_object->StateChanged(state);
+ remote_objects_.AddPtr(std::move(remote_object));
+}
+
+base::WeakPtr<ServiceWorkerHandle> ServiceWorkerHandle::AsWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
void ServiceWorkerHandle::PostMessageToServiceWorker(
::blink::TransferableMessage message) {
// When this method is called the encoded_message inside message could just
@@ -248,10 +292,6 @@ void ServiceWorkerHandle::DispatchExtendableMessageEvent(
NOTREACHED() << provider_host_->provider_type();
}
-base::WeakPtr<ServiceWorkerHandle> ServiceWorkerHandle::AsWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
-}
-
void ServiceWorkerHandle::OnConnectionError() {
// If there are still bindings, |this| is still being used.
if (!bindings_.empty())
diff --git a/chromium/content/browser/service_worker/service_worker_handle.h b/chromium/content/browser/service_worker/service_worker_handle.h
index b6a2d421279..948f68283ac 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_handle.h
@@ -14,6 +14,7 @@
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "url/origin.h"
@@ -46,13 +47,40 @@ class CONTENT_EXPORT ServiceWorkerHandle
// ServiceWorkerVersion::Listener overrides.
void OnVersionStateChanged(ServiceWorkerVersion* version) override;
- // Establishes a new mojo connection into |bindings_|.
- blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo();
+ // Returns an info for the ServiceWorker object of this handle. The info
+ // contains a Mojo ptr to |this| which ensures |this| stays alive while the
+ // info is alive. Furthermore, it contains a Mojo request for the
+ // ServiceWorkerObject interface in the renderer. |this| will make calls to
+ // the ServiceWorkerObject to update its state.
+ //
+ // WARNING: The returned info must be sent immediately over Mojo, because
+ // |this| will start making calls on an associated interface ptr to
+ // ServiceWorkerObject, which crashes unless the request inside the info has
+ // been sent. If the info cannot be sent immediately, use
+ // CreateIncompleteObjectInfo() instead.
+ blink::mojom::ServiceWorkerObjectInfoPtr CreateCompleteObjectInfoToSend();
+
+ // Similar to CreateCompleteObjectInfoToSend(), except the returned info has
+ // an empty Mojo request for ServiceWorkerObject. To make the info usable, the
+ // caller should add a request to the info, send the info over Mojo, and
+ // then call AddRemoteObjectPtrAndUpdateState().
+ //
+ // This function is useful when an info is needed before it can be sent over
+ // Mojo.
+ blink::mojom::ServiceWorkerObjectInfoPtr CreateIncompleteObjectInfo();
+
+ // Starts to use the |remote_object_ptr_info| as a valid Mojo pipe endpoint,
+ // and triggers statechanged event if |sent_state| is old and needs to be
+ // updated.
+ void AddRemoteObjectPtrAndUpdateState(
+ blink::mojom::ServiceWorkerObjectAssociatedPtrInfo remote_object_ptr_info,
+ blink::mojom::ServiceWorkerState sent_state);
int provider_id() const { return provider_id_; }
- int handle_id() const { return handle_id_; }
ServiceWorkerVersion* version() { return version_.get(); }
+ base::WeakPtr<ServiceWorkerHandle> AsWeakPtr();
+
private:
friend class service_worker_handle_unittest::ServiceWorkerHandleTest;
@@ -68,8 +96,6 @@ class CONTENT_EXPORT ServiceWorkerHandle
::blink::TransferableMessage message,
base::OnceCallback<void(ServiceWorkerStatusCode)> callback);
- base::WeakPtr<ServiceWorkerHandle> AsWeakPtr();
-
void OnConnectionError();
base::WeakPtr<ServiceWorkerContextCore> context_;
@@ -82,9 +108,20 @@ class CONTENT_EXPORT ServiceWorkerHandle
// object.
const url::Origin provider_origin_;
const int provider_id_;
- const int handle_id_;
scoped_refptr<ServiceWorkerVersion> version_;
mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
+ // Typically |remote_objects_| contains only one Mojo connection,
+ // corresponding to the content::WebServiceWorkerImpl in the renderer which
+ // corresponds to the ServiceWorker JavaScript object. However, multiple Mojo
+ // connections may exist while propagating multiple service worker object
+ // infos to the renderer process, but only the first one that arrived there
+ // will be used to create the new content::WebServiceWorkerImpl instance and
+ // be bound to it.
+ mojo::AssociatedInterfacePtrSet<blink::mojom::ServiceWorkerObject>
+ remote_objects_;
+
+ // TODO(crbug.com/838410): Temporary debugging for the linked bug.
+ bool in_dtor_ = false;
base::WeakPtrFactory<ServiceWorkerHandle> weak_ptr_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
index 1c31c0c11ff..6122d08b40c 100644
--- a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -16,17 +16,13 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_test_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_state.mojom.h"
@@ -34,17 +30,6 @@
namespace content {
namespace service_worker_handle_unittest {
-void VerifyStateChangedMessage(int expected_handle_id,
- blink::mojom::ServiceWorkerState expected_state,
- const IPC::Message* message) {
- ASSERT_TRUE(message != nullptr);
- ServiceWorkerMsg_ServiceWorkerStateChanged::Param param;
- ASSERT_TRUE(ServiceWorkerMsg_ServiceWorkerStateChanged::Read(
- message, &param));
- EXPECT_EQ(expected_handle_id, std::get<1>(param));
- EXPECT_EQ(expected_state, std::get<2>(param));
-}
-
static void SaveStatusCallback(bool* called,
ServiceWorkerStatusCode* out,
ServiceWorkerStatusCode status) {
@@ -94,7 +79,6 @@ class FailToStartWorkerTestHelper : public ExtendableMessageEventTestHelper {
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -106,24 +90,26 @@ class FailToStartWorkerTestHelper : public ExtendableMessageEventTestHelper {
}
};
-class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
+class MockServiceWorkerObject : public blink::mojom::ServiceWorkerObject {
public:
- TestingServiceWorkerDispatcherHost(int process_id,
- ResourceContext* resource_context,
- EmbeddedWorkerTestHelper* helper)
- : ServiceWorkerDispatcherHost(process_id, resource_context),
- bad_message_received_count_(0),
- helper_(helper) {}
-
- bool Send(IPC::Message* message) override { return helper_->Send(message); }
+ explicit MockServiceWorkerObject(
+ blink::mojom::ServiceWorkerObjectInfoPtr info)
+ : info_(std::move(info)),
+ state_(info_->state),
+ binding_(this, std::move(info_->request)) {}
+ ~MockServiceWorkerObject() override = default;
- void ShutdownForBadMessage() override { ++bad_message_received_count_; }
+ blink::mojom::ServiceWorkerState state() const { return state_; }
- int bad_message_received_count_;
+ private:
+ // Implements blink::mojom::ServiceWorkerObject.
+ void StateChanged(blink::mojom::ServiceWorkerState state) override {
+ state_ = state;
+ }
- protected:
- EmbeddedWorkerTestHelper* helper_;
- ~TestingServiceWorkerDispatcherHost() override {}
+ blink::mojom::ServiceWorkerObjectInfoPtr info_;
+ blink::mojom::ServiceWorkerState state_;
+ mojo::AssociatedBinding<blink::mojom::ServiceWorkerObject> binding_;
};
class ServiceWorkerHandleTest : public testing::Test {
@@ -134,8 +120,8 @@ class ServiceWorkerHandleTest : public testing::Test {
void Initialize(std::unique_ptr<EmbeddedWorkerTestHelper> helper) {
helper_ = std::move(helper);
- dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
- helper_->mock_render_process_id(), &resource_context_, helper_.get());
+ dispatcher_host_ = base::MakeRefCounted<ServiceWorkerDispatcherHost>(
+ helper_->mock_render_process_id());
helper_->RegisterDispatcherHost(helper_->mock_render_process_id(),
dispatcher_host_);
dispatcher_host_->Init(helper_->context_wrapper());
@@ -201,16 +187,38 @@ class ServiceWorkerHandleTest : public testing::Test {
return nullptr;
}
- IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
+ GetRegistrationFromRemote(mojom::ServiceWorkerContainerHost* container_host,
+ const GURL& scope) {
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info;
+ base::RunLoop run_loop;
+ container_host->GetRegistration(
+ scope, base::BindOnce(
+ [](base::OnceClosure quit_closure,
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr*
+ out_registration_info,
+ blink::mojom::ServiceWorkerErrorType error,
+ const base::Optional<std::string>& error_msg,
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
+ registration) {
+ ASSERT_EQ(blink::mojom::ServiceWorkerErrorType::kNone,
+ error);
+ *out_registration_info = std::move(registration);
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &registration_info));
+ run_loop.Run();
+ EXPECT_TRUE(registration_info);
+ return registration_info;
+ }
TestBrowserThreadBundle browser_thread_bundle_;
- MockResourceContext resource_context_;
base::SimpleTestTickClock tick_clock_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
- scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
+ scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host_;
private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerHandleTest);
@@ -223,6 +231,7 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
const GURL script_url("https://www.example.com/service_worker.js");
Initialize(std::make_unique<EmbeddedWorkerTestHelper>(base::FilePath()));
SetUpRegistration(pattern, script_url);
+ registration_->SetInstallingVersion(version_);
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
@@ -230,32 +239,21 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
helper_->mock_render_process_id(), kProviderId,
helper_->context()->AsWeakPtr(), kRenderFrameId,
dispatcher_host_.get(), &remote_endpoint);
- blink::mojom::ServiceWorkerObjectInfoPtr info =
- provider_host->GetOrCreateServiceWorkerHandle(version_.get());
- ServiceWorkerHandle* handle =
- GetServiceWorkerHandle(provider_host.get(), version_->version_id());
-
- // Start the worker, and then...
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
- CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ provider_host->SetDocumentUrl(pattern);
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info =
+ GetRegistrationFromRemote(remote_endpoint.host_ptr()->get(), pattern);
+ // |version_| is the installing version of |registration_| now.
+ EXPECT_TRUE(registration_info->installing);
+ EXPECT_EQ(version_->version_id(), registration_info->installing->version_id);
+ auto mock_object = std::make_unique<MockServiceWorkerObject>(
+ std::move(registration_info->installing));
// ...update state to installed.
+ EXPECT_EQ(blink::mojom::ServiceWorkerState::kInstalling,
+ mock_object->state());
version_->SetStatus(ServiceWorkerVersion::INSTALLED);
-
- ASSERT_EQ(0L, dispatcher_host_->bad_message_received_count_);
-
- const IPC::Message* message = nullptr;
- // StartWorker shouldn't be recorded here.
- ASSERT_EQ(1UL, ipc_sink()->message_count());
- message = ipc_sink()->GetMessageAt(0);
-
- // StateChanged (state == Installed).
- VerifyStateChangedMessage(handle->handle_id(),
- blink::mojom::ServiceWorkerState::kInstalled,
- message);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::mojom::ServiceWorkerState::kInstalled, mock_object->state());
}
TEST_F(ServiceWorkerHandleTest,
@@ -290,7 +288,8 @@ TEST_F(ServiceWorkerHandleTest,
// object in the service worker execution context for |version_|.
ServiceWorkerProviderHost* provider_host = version_->provider_host();
blink::mojom::ServiceWorkerObjectInfoPtr info =
- provider_host->GetOrCreateServiceWorkerHandle(version_.get());
+ provider_host->GetOrCreateServiceWorkerHandle(version_.get())
+ ->CreateCompleteObjectInfoToSend();
ServiceWorkerHandle* sender_worker_handle =
GetServiceWorkerHandle(provider_host, version_->version_id());
EXPECT_EQ(1u, GetBindingsCount(sender_worker_handle));
@@ -318,8 +317,6 @@ TEST_F(ServiceWorkerHandleTest,
EXPECT_EQ(1u, events.size());
EXPECT_FALSE(events[0]->source_info_for_client);
EXPECT_TRUE(events[0]->source_info_for_service_worker);
- EXPECT_EQ(sender_worker_handle->handle_id(),
- events[0]->source_info_for_service_worker->handle_id);
EXPECT_EQ(version_->version_id(),
events[0]->source_info_for_service_worker->version_id);
@@ -353,7 +350,8 @@ TEST_F(ServiceWorkerHandleTest, DispatchExtendableMessageEvent_FromClient) {
provider_host->SetDocumentUrl(pattern);
// Prepare a ServiceWorkerHandle for the above |provider_host|.
blink::mojom::ServiceWorkerObjectInfoPtr info =
- provider_host->GetOrCreateServiceWorkerHandle(version_.get());
+ provider_host->GetOrCreateServiceWorkerHandle(version_.get())
+ ->CreateCompleteObjectInfoToSend();
ServiceWorkerHandle* handle =
GetServiceWorkerHandle(provider_host.get(), version_->version_id());
@@ -408,7 +406,8 @@ TEST_F(ServiceWorkerHandleTest, DispatchExtendableMessageEvent_Fail) {
provider_host->SetDocumentUrl(pattern);
// Prepare a ServiceWorkerHandle for the above |provider_host|.
blink::mojom::ServiceWorkerObjectInfoPtr info =
- provider_host->GetOrCreateServiceWorkerHandle(version_.get());
+ provider_host->GetOrCreateServiceWorkerHandle(version_.get())
+ ->CreateCompleteObjectInfoToSend();
ServiceWorkerHandle* handle =
GetServiceWorkerHandle(provider_host.get(), version_->version_id());
diff --git a/chromium/content/browser/service_worker/service_worker_info.cc b/chromium/content/browser/service_worker/service_worker_info.cc
index c6412175033..0b2b348664b 100644
--- a/chromium/content/browser/service_worker/service_worker_info.cc
+++ b/chromium/content/browser/service_worker/service_worker_info.cc
@@ -14,28 +14,6 @@
namespace content {
-ServiceWorkerVersionInfo::ClientInfo::ClientInfo()
- : ClientInfo(ChildProcessHost::kInvalidUniqueID,
- MSG_ROUTING_NONE,
- base::Callback<WebContents*(void)>(),
- blink::mojom::ServiceWorkerProviderType::kUnknown) {}
-
-ServiceWorkerVersionInfo::ClientInfo::ClientInfo(
- int process_id,
- int route_id,
- const base::Callback<WebContents*(void)>& web_contents_getter,
- blink::mojom::ServiceWorkerProviderType type)
- : process_id(process_id),
- route_id(route_id),
- web_contents_getter(web_contents_getter),
- type(type) {}
-
-ServiceWorkerVersionInfo::ClientInfo::ClientInfo(
- const ServiceWorkerVersionInfo::ClientInfo& other) = default;
-
-ServiceWorkerVersionInfo::ClientInfo::~ClientInfo() {
-}
-
ServiceWorkerVersionInfo::ServiceWorkerVersionInfo()
: running_status(EmbeddedWorkerStatus::STOPPED),
status(ServiceWorkerVersion::NEW),
diff --git a/chromium/content/browser/service_worker/service_worker_info.h b/chromium/content/browser/service_worker/service_worker_info.h
index 945008dadcd..1da804ee2cf 100644
--- a/chromium/content/browser/service_worker/service_worker_info.h
+++ b/chromium/content/browser/service_worker/service_worker_info.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <map>
#include <vector>
#include "base/callback.h"
@@ -20,25 +21,10 @@
namespace content {
enum class EmbeddedWorkerStatus;
+struct ServiceWorkerClientInfo;
struct CONTENT_EXPORT ServiceWorkerVersionInfo {
public:
- struct CONTENT_EXPORT ClientInfo {
- public:
- ClientInfo();
- ClientInfo(int process_id,
- int route_id,
- const base::Callback<WebContents*(void)>& web_contents_getter,
- blink::mojom::ServiceWorkerProviderType type);
- ClientInfo(const ClientInfo& other);
- ~ClientInfo();
- int process_id;
- int route_id;
- // |web_contents_getter| is only set for PlzNavigate.
- base::Callback<WebContents*(void)> web_contents_getter;
- blink::mojom::ServiceWorkerProviderType type;
- };
-
ServiceWorkerVersionInfo();
ServiceWorkerVersionInfo(
EmbeddedWorkerStatus running_status,
@@ -65,7 +51,7 @@ struct CONTENT_EXPORT ServiceWorkerVersionInfo {
int devtools_agent_route_id;
base::Time script_response_time;
base::Time script_last_modified;
- std::map<std::string, ClientInfo> clients;
+ std::map<std::string, ServiceWorkerClientInfo> clients;
};
struct CONTENT_EXPORT ServiceWorkerRegistrationInfo {
diff --git a/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc b/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc
index 8283e936fdc..09bba617925 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_script_loader.cc
@@ -40,7 +40,7 @@ ServiceWorkerInstalledScriptLoader::~ServiceWorkerInstalledScriptLoader() =
void ServiceWorkerInstalledScriptLoader::OnStarted(
std::string encoding,
- std::unordered_map<std::string, std::string> headers,
+ base::flat_map<std::string, std::string> headers,
mojo::ScopedDataPipeConsumerHandle body_handle,
uint64_t body_size,
mojo::ScopedDataPipeConsumerHandle metadata_handle,
@@ -110,7 +110,8 @@ void ServiceWorkerInstalledScriptLoader::OnFinished(FinishedReason reason) {
client_->OnComplete(network::URLLoaderCompletionStatus(net_error));
}
-void ServiceWorkerInstalledScriptLoader::FollowRedirect() {
+void ServiceWorkerInstalledScriptLoader::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
// This class never returns a redirect response to its client, so should never
// be asked to follow one.
NOTREACHED();
diff --git a/chromium/content/browser/service_worker/service_worker_installed_script_loader.h b/chromium/content/browser/service_worker/service_worker_installed_script_loader.h
index ad4844c1d64..89a412e2270 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_script_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_installed_script_loader.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT ServiceWorkerInstalledScriptLoader
// ServiceWorkerInstalledScriptReader::Client overrides:
void OnStarted(std::string encoding,
- std::unordered_map<std::string, std::string> headers,
+ base::flat_map<std::string, std::string> headers,
mojo::ScopedDataPipeConsumerHandle body_handle,
uint64_t body_size,
mojo::ScopedDataPipeConsumerHandle meta_data_handle,
@@ -48,7 +48,8 @@ class CONTENT_EXPORT ServiceWorkerInstalledScriptLoader
ServiceWorkerInstalledScriptReader::FinishedReason reason) override;
// network::mojom::URLLoader overrides:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
diff --git a/chromium/content/browser/service_worker/service_worker_installed_script_reader.cc b/chromium/content/browser/service_worker/service_worker_installed_script_reader.cc
index a70872a74d8..8c42abbd0ae 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_script_reader.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_script_reader.cc
@@ -154,7 +154,7 @@ void ServiceWorkerInstalledScriptReader::OnReadInfoComplete(
headers->GetCharset(&charset);
// Create a map of response headers.
- std::unordered_map<std::string, std::string> header_strings;
+ base::flat_map<std::string, std::string> header_strings;
size_t iter = 0;
std::string key;
std::string value;
diff --git a/chromium/content/browser/service_worker/service_worker_installed_script_reader.h b/chromium/content/browser/service_worker/service_worker_installed_script_reader.h
index 334dc38620d..4c5a2a13a7e 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_script_reader.h
+++ b/chromium/content/browser/service_worker/service_worker_installed_script_reader.h
@@ -7,8 +7,8 @@
#include <memory>
#include <string>
-#include <unordered_map>
+#include "base/containers/flat_map.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/system/data_pipe.h"
@@ -38,7 +38,7 @@ class ServiceWorkerInstalledScriptReader {
class Client {
public:
virtual void OnStarted(std::string encoding,
- std::unordered_map<std::string, std::string> headers,
+ base::flat_map<std::string, std::string> headers,
mojo::ScopedDataPipeConsumerHandle body_handle,
uint64_t body_size,
mojo::ScopedDataPipeConsumerHandle meta_data_handle,
diff --git a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
index a7f29950858..c7dd5fee1e2 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -81,7 +81,7 @@ void ServiceWorkerInstalledScriptsSender::StartSendingScript(
void ServiceWorkerInstalledScriptsSender::OnStarted(
std::string encoding,
- std::unordered_map<std::string, std::string> headers,
+ base::flat_map<std::string, std::string> headers,
mojo::ScopedDataPipeConsumerHandle body_handle,
uint64_t body_size,
mojo::ScopedDataPipeConsumerHandle meta_data_handle,
diff --git a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h
index 81531ca5c3a..7817a40aaf4 100644
--- a/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h
+++ b/chromium/content/browser/service_worker/service_worker_installed_scripts_sender.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPTS_SENDER_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPTS_SENDER_H_
+#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "content/browser/service_worker/service_worker_installed_script_reader.h"
#include "content/common/content_export.h"
@@ -75,7 +76,7 @@ class CONTENT_EXPORT ServiceWorkerInstalledScriptsSender
// Implements ServiceWorkerInstalledScriptReader::Client.
void OnStarted(std::string encoding,
- std::unordered_map<std::string, std::string> headers,
+ base::flat_map<std::string, std::string> headers,
mojo::ScopedDataPipeConsumerHandle body_handle,
uint64_t body_size,
mojo::ScopedDataPipeConsumerHandle meta_data_handle,
diff --git a/chromium/content/browser/service_worker/service_worker_internals_ui.cc b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
index 6770fe5ac9d..5fba22499c9 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -82,7 +82,7 @@ base::ProcessId GetRealProcessId(int process_host_id) {
if (!rph)
return base::kNullProcessId;
- base::ProcessHandle handle = rph->GetHandle();
+ base::ProcessHandle handle = rph->GetProcess().Handle();
if (handle == base::kNullProcessHandle)
return base::kNullProcessId;
// TODO(nhiroki): On Windows, |rph->GetHandle()| does not duplicate ownership
@@ -306,11 +306,11 @@ class ServiceWorkerInternalsUI::PartitionObserver
web_ui_->CallJavascriptFunctionUnsafe(
"serviceworker.onConsoleMessageReported", ConvertToRawPtrVector(args));
}
- void OnRegistrationStored(int64_t registration_id,
- const GURL& pattern) override {
+ void OnRegistrationCompleted(int64_t registration_id,
+ const GURL& pattern) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- web_ui_->CallJavascriptFunctionUnsafe("serviceworker.onRegistrationStored",
- Value(pattern.spec()));
+ web_ui_->CallJavascriptFunctionUnsafe(
+ "serviceworker.onRegistrationCompleted", Value(pattern.spec()));
}
void OnRegistrationDeleted(int64_t registration_id,
const GURL& pattern) override {
diff --git a/chromium/content/browser/service_worker/service_worker_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
index 78c577fe053..f39721041ba 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -140,7 +140,7 @@ class ServiceWorkerJobTest : public testing::Test {
scoped_refptr<ServiceWorkerRegistration> FindRegistrationForPattern(
const GURL& pattern,
ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
- std::unique_ptr<ServiceWorkerProviderHost> CreateControllee();
+ ServiceWorkerProviderHost* CreateControllee();
TestBrowserThreadBundle browser_thread_bundle_;
std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
@@ -189,29 +189,32 @@ ServiceWorkerJobTest::FindRegistrationForPattern(
return registration;
}
-std::unique_ptr<ServiceWorkerProviderHost>
-ServiceWorkerJobTest::CreateControllee() {
+ServiceWorkerProviderHost* ServiceWorkerJobTest::CreateControllee() {
+ static int s_next_provider_id = 1;
remote_endpoints_.emplace_back();
std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
- 33 /* dummy render process id */, 1 /* dummy provider_id */,
+ 33 /* dummy render process id */, s_next_provider_id++,
true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr(),
&remote_endpoints_.back());
- return host;
+ auto* host_ptr = host.get();
+ helper_->context()->AddProviderHost(std::move(host));
+ return host_ptr;
}
TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> original_registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ RunRegisterJob(GURL("https://www.example.com/service_worker.js"),
+ options);
bool called;
scoped_refptr<ServiceWorkerRegistration> registration1;
storage()->FindRegistrationForDocument(
- GURL("http://www.example.com/"),
+ GURL("https://www.example.com/"),
SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
scoped_refptr<ServiceWorkerRegistration> registration2;
storage()->FindRegistrationForDocument(
- GURL("http://www.example.com/"),
+ GURL("https://www.example.com/"),
SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
@@ -223,22 +226,23 @@ TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
bool called;
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> original_registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ RunRegisterJob(GURL("https://www.example.com/service_worker.js"),
+ options);
ASSERT_NE(static_cast<ServiceWorkerRegistration*>(nullptr),
original_registration.get());
scoped_refptr<ServiceWorkerRegistration> registration1;
storage()->FindRegistrationForDocument(
- GURL("http://www.example.com/one"),
+ GURL("https://www.example.com/one"),
SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration1));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
scoped_refptr<ServiceWorkerRegistration> registration2;
storage()->FindRegistrationForDocument(
- GURL("http://www.example.com/two"),
+ GURL("https://www.example.com/two"),
SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
@@ -249,18 +253,18 @@ TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
bool called1;
blink::mojom::ServiceWorkerRegistrationOptions options1;
- options1.scope = GURL("http://www.example.com/one/");
+ options1.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> original_registration1;
job_coordinator()->Register(
- GURL("http://www.example.com/service_worker.js"), options1,
+ GURL("https://www.example.com/service_worker.js"), options1,
SaveRegistration(SERVICE_WORKER_OK, &called1, &original_registration1));
bool called2;
blink::mojom::ServiceWorkerRegistrationOptions options2;
- options2.scope = GURL("http://www.example.com/two/");
+ options2.scope = GURL("https://www.example.com/two/");
scoped_refptr<ServiceWorkerRegistration> original_registration2;
job_coordinator()->Register(
- GURL("http://www.example.com/service_worker.js"), options2,
+ GURL("https://www.example.com/service_worker.js"), options2,
SaveRegistration(SERVICE_WORKER_OK, &called2, &original_registration2));
EXPECT_FALSE(called1);
@@ -271,11 +275,11 @@ TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
scoped_refptr<ServiceWorkerRegistration> registration1;
storage()->FindRegistrationForDocument(
- GURL("http://www.example.com/one/"),
+ GURL("https://www.example.com/one/"),
SaveFoundRegistration(SERVICE_WORKER_OK, &called1, &registration1));
scoped_refptr<ServiceWorkerRegistration> registration2;
storage()->FindRegistrationForDocument(
- GURL("http://www.example.com/two/"),
+ GURL("https://www.example.com/two/"),
SaveFoundRegistration(SERVICE_WORKER_OK, &called2, &registration2));
base::RunLoop().RunUntilIdle();
@@ -287,9 +291,9 @@ TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
// Make sure basic registration is working.
TEST_F(ServiceWorkerJobTest, Register) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
- scoped_refptr<ServiceWorkerRegistration> registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ options.scope = GURL("https://www.example.com/");
+ scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
+ GURL("https://www.example.com/service_worker.js"), options);
EXPECT_TRUE(registration);
EXPECT_EQ(EmbeddedWorkerTestHelper::Event::Install,
@@ -301,9 +305,9 @@ TEST_F(ServiceWorkerJobTest, Register) {
// Make sure registrations are cleaned up when they are unregistered.
TEST_F(ServiceWorkerJobTest, Unregister) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
- scoped_refptr<ServiceWorkerRegistration> registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ options.scope = GURL("https://www.example.com/");
+ scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
+ GURL("https://www.example.com/service_worker.js"), options);
scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
ServiceWorkerProviderHost* provider_host =
@@ -334,7 +338,7 @@ TEST_F(ServiceWorkerJobTest, Unregister) {
}
TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
- GURL pattern("http://www.example.com/");
+ GURL pattern("https://www.example.com/");
RunUnregisterJob(pattern, SERVICE_WORKER_ERROR_NOT_FOUND);
}
@@ -343,10 +347,10 @@ TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
// existing registration.
TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
- scoped_refptr<ServiceWorkerRegistration> old_registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ scoped_refptr<ServiceWorkerRegistration> old_registration = RunRegisterJob(
+ GURL("https://www.example.com/service_worker.js"), options);
scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern =
FindRegistrationForPattern(options.scope);
@@ -355,7 +359,7 @@ TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
old_registration_by_pattern = nullptr;
scoped_refptr<ServiceWorkerRegistration> new_registration = RunRegisterJob(
- GURL("http://www.example.com/service_worker_new.js"), options);
+ GURL("https://www.example.com/service_worker_new.js"), options);
ASSERT_EQ(old_registration, new_registration);
@@ -368,9 +372,9 @@ TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
// Make sure that when registering a duplicate pattern+script_url
// combination, that the same registration is used.
TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> old_registration =
RunRegisterJob(script_url, options);
@@ -471,7 +475,6 @@ class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -487,9 +490,9 @@ TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
helper_.reset(new FailToStartWorkerTestHelper);
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options,
+ RunRegisterJob(GURL("https://www.example.com/service_worker.js"), options,
SERVICE_WORKER_ERROR_START_WORKER_FAILED);
ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(nullptr), registration);
@@ -498,9 +501,9 @@ TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
// Register and then unregister the pattern, in parallel. Job coordinator should
// process jobs until the last job.
TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
bool registration_called = false;
scoped_refptr<ServiceWorkerRegistration> registration;
@@ -529,9 +532,9 @@ TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
// registration should win, and the old registration should have been
// shutdown.
TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
- GURL pattern("http://www.example.com/");
+ GURL pattern("https://www.example.com/");
- GURL script_url1("http://www.example.com/service_worker1.js");
+ GURL script_url1("https://www.example.com/service_worker1.js");
bool registration1_called = false;
scoped_refptr<ServiceWorkerRegistration> registration1;
job_coordinator()->Register(
@@ -541,7 +544,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
SaveRegistration(SERVICE_WORKER_OK, &registration1_called,
&registration1));
- GURL script_url2("http://www.example.com/service_worker2.js");
+ GURL script_url2("https://www.example.com/service_worker2.js");
bool registration2_called = false;
scoped_refptr<ServiceWorkerRegistration> registration2;
job_coordinator()->Register(
@@ -568,9 +571,9 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
// object.
TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
- GURL script_url("http://www.example.com/service_worker1.js");
+ GURL script_url("https://www.example.com/service_worker1.js");
bool registration1_called = false;
scoped_refptr<ServiceWorkerRegistration> registration1;
job_coordinator()->Register(
@@ -601,9 +604,9 @@ TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
// Call simulataneous unregister calls.
TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
- GURL pattern("http://www.example.com/");
+ GURL pattern("https://www.example.com/");
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL script_url("https://www.example.com/service_worker.js");
bool unregistration1_called = false;
job_coordinator()->Unregister(
pattern,
@@ -632,13 +635,13 @@ TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
}
TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
- GURL script_url1("http://www1.example.com/service_worker.js");
- GURL script_url2("http://www2.example.com/service_worker.js");
+ GURL script_url1("https://www1.example.com/service_worker.js");
+ GURL script_url2("https://www2.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options1;
- options1.scope = GURL("http://www1.example.com/");
+ options1.scope = GURL("https://www1.example.com/");
blink::mojom::ServiceWorkerRegistrationOptions options2;
- options2.scope = GURL("http://www2.example.com/");
+ options2.scope = GURL("https://www2.example.com/");
bool registration_called1 = false;
scoped_refptr<ServiceWorkerRegistration> registration1;
@@ -680,8 +683,8 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
}
TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
- GURL pattern1("http://www1.example.com/");
- GURL pattern2("http://www2.example.com/");
+ GURL pattern1("https://www1.example.com/");
+ GURL pattern2("https://www2.example.com/");
bool unregistration_called1 = false;
scoped_refptr<ServiceWorkerRegistration> registration1;
@@ -706,9 +709,9 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
}
TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
bool registration_called = false;
scoped_refptr<ServiceWorkerRegistration> registration;
@@ -739,9 +742,9 @@ TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
// Tests that the waiting worker enters the 'redundant' state upon
// unregistration.
TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
- GURL script_url("http://www.example.com/service_worker.js");
+ GURL script_url("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script_url, options);
ASSERT_TRUE(registration.get());
@@ -763,7 +766,7 @@ TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
- RunUnregisterJob(GURL("http://www.example.com/"));
+ RunUnregisterJob(GURL("https://www.example.com/"));
// The version should be stopped since there is no controllee after
// unregistration.
@@ -775,16 +778,16 @@ TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
// unregistration.
TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
- scoped_refptr<ServiceWorkerRegistration> registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ options.scope = GURL("https://www.example.com/");
+ scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
+ GURL("https://www.example.com/service_worker.js"), options);
ASSERT_TRUE(registration.get());
scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
- RunUnregisterJob(GURL("http://www.example.com/"));
+ RunUnregisterJob(GURL("https://www.example.com/"));
// The version should be stopped since there is no controllee after
// unregistration.
@@ -797,25 +800,25 @@ TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
TEST_F(ServiceWorkerJobTest,
UnregisterActiveSetsRedundant_WaitForNoControllee) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
- scoped_refptr<ServiceWorkerRegistration> registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ options.scope = GURL("https://www.example.com/");
+ scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
+ GURL("https://www.example.com/service_worker.js"), options);
ASSERT_TRUE(registration.get());
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
- registration->active_version()->AddControllee(host.get());
+ ServiceWorkerProviderHost* host = CreateControllee();
+ registration->active_version()->AddControllee(host);
scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
- RunUnregisterJob(GURL("http://www.example.com/"));
+ RunUnregisterJob(GURL("https://www.example.com/"));
// The version should be running since there is still a controllee.
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
- registration->active_version()->RemoveControllee(host.get());
+ registration->active_version()->RemoveControllee(host->client_uuid());
base::RunLoop().RunUntilIdle();
// The version should be stopped since there is no controllee.
@@ -825,8 +828,8 @@ TEST_F(ServiceWorkerJobTest,
namespace { // Helpers for the update job tests.
-const GURL kNoChangeOrigin("http://nochange/");
-const GURL kNewVersionOrigin("http://newversion/");
+const GURL kNoChangeOrigin("https://nochange/");
+const GURL kNewVersionOrigin("https://newversion/");
const std::string kScope("scope/");
const std::string kScript("script.js");
@@ -935,7 +938,6 @@ class UpdateJobTestHelper
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -997,8 +999,8 @@ class UpdateJobTestHelper
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id, version_id, scope, script, pause_after_download,
std::move(dispatcher_request), std::move(controller_request),
- std::move(service_worker_host), std::move(instance_host),
- std::move(provider_info), std::move(installed_scripts_info));
+ std::move(instance_host), std::move(provider_info),
+ std::move(installed_scripts_info));
}
void OnStopWorker(int embedded_worker_id) override {
@@ -1073,7 +1075,6 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -1092,8 +1093,8 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
UpdateJobTestHelper::OnStartWorker(
embedded_worker_id, version_id, scope, script, pause_after_download,
std::move(dispatcher_request), std::move(controller_request),
- std::move(service_worker_host), std::move(instance_host),
- std::move(provider_info), std::move(installed_scripts_info));
+ std::move(instance_host), std::move(provider_info),
+ std::move(installed_scripts_info));
}
void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
@@ -1287,15 +1288,15 @@ TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
TEST_F(ServiceWorkerJobTest, Update_ScriptUrlChanged) {
// Create a registration with an active version.
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
- scoped_refptr<ServiceWorkerRegistration> registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ options.scope = GURL("https://www.example.com/one/");
+ scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
+ GURL("https://www.example.com/service_worker.js"), options);
// Queue an Update. When this runs, it will use the waiting version's script.
job_coordinator()->Update(registration.get(), false);
// Add a waiting version with a new script.
- GURL new_script("http://www.example.com/new_worker.js");
+ GURL new_script("https://www.example.com/new_worker.js");
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
registration.get(), new_script, 2L /* dummy version id */,
helper_->context()->AsWeakPtr());
@@ -1344,16 +1345,16 @@ TEST_F(ServiceWorkerJobTest, Update_EvictedIncumbent) {
TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
bool called;
- scoped_refptr<ServiceWorkerRegistration> registration =
- RunRegisterJob(GURL("http://www.example.com/service_worker.js"), options);
+ scoped_refptr<ServiceWorkerRegistration> registration = RunRegisterJob(
+ GURL("https://www.example.com/service_worker.js"), options);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
ServiceWorkerVersion* active_version = registration->active_version();
- active_version->AddControllee(host.get());
- job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
+ active_version->AddControllee(host);
+ job_coordinator()->Unregister(GURL("https://www.example.com/one/"),
SaveUnregistration(SERVICE_WORKER_OK, &called));
// Update should abort after it starts and sees uninstalling.
@@ -1371,10 +1372,10 @@ TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
}
TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
- GURL script1("http://www.example.com/service_worker.js");
- GURL script2("http://www.example.com/service_worker.js?new");
+ GURL script1("https://www.example.com/service_worker.js");
+ GURL script2("https://www.example.com/service_worker.js?new");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script1, options);
@@ -1383,10 +1384,10 @@ TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
registration->SetTaskRunnerForTest(runner);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> old_version =
registration->active_version();
- old_version->AddControllee(host.get());
+ old_version->AddControllee(host);
RunUnregisterJob(options.scope);
// Register another script.
@@ -1404,7 +1405,7 @@ TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
- old_version->RemoveControllee(host.get());
+ old_version->RemoveControllee(host->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(registration->is_uninstalling());
@@ -1423,19 +1424,19 @@ TEST_F(ServiceWorkerJobTest, RegisterWhileUninstalling) {
}
TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
- GURL script1("http://www.example.com/service_worker.js");
- GURL script2("http://www.example.com/service_worker.js?new");
+ GURL script1("https://www.example.com/service_worker.js");
+ GURL script2("https://www.example.com/service_worker.js?new");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script1, options);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> old_version =
registration->active_version();
- old_version->AddControllee(host.get());
+ old_version->AddControllee(host);
RunUnregisterJob(options.scope);
EXPECT_EQ(registration, RunRegisterJob(script2, options));
@@ -1459,7 +1460,7 @@ TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, new_version->running_status());
EXPECT_EQ(ServiceWorkerVersion::INSTALLED, new_version->status());
- old_version->RemoveControllee(host.get());
+ old_version->RemoveControllee(host->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(registration->is_uninstalling());
@@ -1472,10 +1473,10 @@ TEST_F(ServiceWorkerJobTest, RegisterAndUnregisterWhileUninstalling) {
}
TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
- GURL script1("http://www.example.com/service_worker.js");
- GURL script2("http://www.example.com/service_worker.js?new");
+ GURL script1("https://www.example.com/service_worker.js");
+ GURL script2("https://www.example.com/service_worker.js?new");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script1, options);
@@ -1484,10 +1485,10 @@ TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
registration->SetTaskRunnerForTest(runner);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> old_version =
registration->active_version();
- old_version->AddControllee(host.get());
+ old_version->AddControllee(host);
RunUnregisterJob(options.scope);
EXPECT_EQ(registration, RunRegisterJob(script2, options));
@@ -1505,7 +1506,7 @@ TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
EXPECT_FALSE(registration->is_uninstalling());
EXPECT_EQ(new_version, registration->waiting_version());
- old_version->RemoveControllee(host.get());
+ old_version->RemoveControllee(host->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(registration->is_uninstalling());
@@ -1524,11 +1525,11 @@ TEST_F(ServiceWorkerJobTest, RegisterSameScriptMultipleTimesWhileUninstalling) {
}
TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
- GURL script1("http://www.example.com/service_worker.js?first");
- GURL script2("http://www.example.com/service_worker.js?second");
- GURL script3("http://www.example.com/service_worker.js?third");
+ GURL script1("https://www.example.com/service_worker.js?first");
+ GURL script2("https://www.example.com/service_worker.js?second");
+ GURL script3("https://www.example.com/service_worker.js?third");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script1, options);
@@ -1537,10 +1538,10 @@ TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
registration->SetTaskRunnerForTest(runner);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> first_version =
registration->active_version();
- first_version->AddControllee(host.get());
+ first_version->AddControllee(host);
RunUnregisterJob(options.scope);
EXPECT_EQ(registration, RunRegisterJob(script2, options));
@@ -1562,7 +1563,7 @@ TEST_F(ServiceWorkerJobTest, RegisterMultipleTimesWhileUninstalling) {
EXPECT_FALSE(registration->is_uninstalling());
EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, second_version->status());
- first_version->RemoveControllee(host.get());
+ first_version->RemoveControllee(host->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(registration->is_uninstalling());
@@ -1629,25 +1630,25 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
- GURL script1("http://www.example.com/service_worker.js");
- GURL script2("http://www.example.com/service_worker.js?new");
+ GURL script1("https://www.example.com/service_worker.js");
+ GURL script2("https://www.example.com/service_worker.js?new");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script1, options);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> old_version =
registration->active_version();
- old_version->AddControllee(host.get());
+ old_version->AddControllee(host);
RunUnregisterJob(options.scope);
// Register another script. While installing, old_version loses controllee.
helper->set_install_callback(
- base::Bind(&ServiceWorkerVersion::RemoveControllee,
- old_version, host.get()));
+ base::BindRepeating(&ServiceWorkerVersion::RemoveControllee, old_version,
+ host->client_uuid()));
EXPECT_EQ(registration, RunRegisterJob(script2, options));
EXPECT_FALSE(registration->is_uninstalling());
@@ -1670,26 +1671,26 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringRejectedInstall) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
- GURL script1("http://www.example.com/service_worker.js");
- GURL script2("http://www.example.com/service_worker.js?new");
+ GURL script1("https://www.example.com/service_worker.js");
+ GURL script2("https://www.example.com/service_worker.js?new");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script1, options);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> old_version =
registration->active_version();
- old_version->AddControllee(host.get());
+ old_version->AddControllee(host);
RunUnregisterJob(options.scope);
// Register another script that fails to install. While installing,
// old_version loses controllee.
helper->set_install_callback(
- base::Bind(&ServiceWorkerVersion::RemoveControllee,
- old_version, host.get()));
+ base::BindRepeating(&ServiceWorkerVersion::RemoveControllee, old_version,
+ host->client_uuid()));
helper->set_install_event_result(
blink::mojom::ServiceWorkerEventStatus::REJECTED);
EXPECT_EQ(registration, RunRegisterJob(script2, options));
@@ -1708,26 +1709,26 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
- GURL script1("http://www.example.com/service_worker.js");
- GURL script2("http://www.example.com/service_worker.js?new");
+ GURL script1("https://www.example.com/service_worker.js");
+ GURL script2("https://www.example.com/service_worker.js?new");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/one/");
+ options.scope = GURL("https://www.example.com/one/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script1, options);
// Add a controllee and queue an unregister to force the uninstalling state.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> old_version =
registration->active_version();
- old_version->AddControllee(host.get());
+ old_version->AddControllee(host);
RunUnregisterJob(options.scope);
// Register another script that fails to activate. While installing,
// old_version loses controllee.
helper->set_install_callback(
- base::Bind(&ServiceWorkerVersion::RemoveControllee,
- old_version, host.get()));
+ base::BindRepeating(&ServiceWorkerVersion::RemoveControllee, old_version,
+ host->client_uuid()));
helper->set_activate_event_result(
blink::mojom::ServiceWorkerEventStatus::REJECTED);
EXPECT_EQ(registration, RunRegisterJob(script2, options));
@@ -1746,9 +1747,9 @@ TEST_F(ServiceWorkerJobTest, HasFetchHandler) {
EventCallbackHelper* helper = new EventCallbackHelper;
helper_.reset(helper);
- GURL script("http://www.example.com/service_worker.js");
+ GURL script("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> registration;
helper->set_has_fetch_handler(true);
@@ -1823,9 +1824,9 @@ TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
helper_.reset(update_helper);
- GURL script("http://www.example.com/service_worker.js");
+ GURL script("https://www.example.com/service_worker.js");
blink::mojom::ServiceWorkerRegistrationOptions options;
- options.scope = GURL("http://www.example.com/");
+ options.scope = GURL("https://www.example.com/");
scoped_refptr<ServiceWorkerRegistration> registration =
RunRegisterJob(script, options);
@@ -1834,10 +1835,10 @@ TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
registration->SetTaskRunnerForTest(runner);
// Add a controllee.
- std::unique_ptr<ServiceWorkerProviderHost> host = CreateControllee();
+ ServiceWorkerProviderHost* host = CreateControllee();
scoped_refptr<ServiceWorkerVersion> first_version =
registration->active_version();
- first_version->AddControllee(host.get());
+ first_version->AddControllee(host);
// Update. The new version should be waiting.
registration->AddListener(update_helper);
@@ -1857,7 +1858,7 @@ TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
// Remove the controllee. The new version should be activating, and delayed
// until the runner runs again.
- first_version->RemoveControllee(host.get());
+ first_version->RemoveControllee(host->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(new_version.get(), registration->active_version());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
@@ -1874,6 +1875,44 @@ TEST_F(ServiceWorkerJobTest, ActivateCancelsOnShutdown) {
EXPECT_EQ(new_version.get(), registration->active_version());
EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, new_version->status());
registration->RemoveListener(update_helper);
+ // Dispatch Mojo messages for those Mojo interfaces bound on |runner| to avoid
+ // possible memory leak.
+ runner->RunUntilIdle();
+}
+
+// Test that clients are alerted of new registrations if they are
+// in-scope, so that Clients.claim() or ServiceWorkerContainer.ready work
+// correctly.
+TEST_F(ServiceWorkerJobTest, AddRegistrationToMatchingProviderHosts) {
+ GURL scope("https://www.example.com/scope/");
+ GURL in_scope("https://www.example.com/scope/page");
+ GURL out_scope("https://www.example.com/page");
+
+ // Make an in-scope client.
+ ServiceWorkerProviderHost* client = CreateControllee();
+ client->SetDocumentUrl(in_scope);
+
+ // Make an in-scope reserved client.
+ base::WeakPtr<ServiceWorkerProviderHost> reserved_client =
+ ServiceWorkerProviderHost::PreCreateNavigationHost(
+ helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
+ {} /* web_contents_getter */);
+ reserved_client->SetDocumentUrl(in_scope);
+
+ // Make an out-scope client.
+ ServiceWorkerProviderHost* out_scope_client = CreateControllee();
+ out_scope_client->SetDocumentUrl(out_scope);
+
+ // Make a new registration.
+ GURL script("https://www.example.com/service_worker.js");
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = scope;
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ RunRegisterJob(script, options);
+
+ EXPECT_EQ(registration.get(), client->MatchRegistration());
+ EXPECT_EQ(registration.get(), reserved_client->MatchRegistration());
+ EXPECT_NE(registration.get(), out_scope_client->MatchRegistration());
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index 463d9e7d2dd..f5fc5073da2 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -94,6 +94,8 @@ std::string EventTypeToSuffix(ServiceWorkerMetrics::EventType event_type) {
return "_CAN_MAKE_PAYMENT";
case ServiceWorkerMetrics::EventType::ABORT_PAYMENT:
return "_ABORT_PAYMENT";
+ case ServiceWorkerMetrics::EventType::COOKIE_CHANGE:
+ return "_COOKIE_CHANGE";
case ServiceWorkerMetrics::EventType::NUM_TYPES:
NOTREACHED() << static_cast<int>(event_type);
}
@@ -339,8 +341,10 @@ const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
return "Navigation Hint";
case EventType::CAN_MAKE_PAYMENT:
return "Can Make Payment";
- case ServiceWorkerMetrics::EventType::ABORT_PAYMENT:
+ case EventType::ABORT_PAYMENT:
return "Abort Payment";
+ case EventType::COOKIE_CHANGE:
+ return "Cookie Change";
case EventType::NUM_TYPES:
break;
}
@@ -717,6 +721,9 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
case EventType::ABORT_PAYMENT:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.AbortPaymentEvent.Time", time);
break;
+ case EventType::COOKIE_CHANGE:
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.CookieChangeEvent.Time", time);
+ break;
case EventType::NAVIGATION_HINT:
// The navigation hint should not be sent as an event.
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index e0a5ce15932..5c3c51296be 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -128,6 +128,7 @@ class ServiceWorkerMetrics {
NAVIGATION_HINT = 27,
CAN_MAKE_PAYMENT = 28,
ABORT_PAYMENT = 29,
+ COOKIE_CHANGE = 30,
// Add new events to record here.
NUM_TYPES
};
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle.h b/chromium/content/browser/service_worker/service_worker_navigation_handle.h
index e1f32a87465..fffae169e15 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_navigation_handle.h
@@ -27,9 +27,9 @@ class ServiceWorkerNavigationHandleCore;
// 2) When the navigation request is sent to the IO thread, we include a
// pointer to the ServiceWorkerNavigationHandleCore.
//
-// 3) If we pre-create a ServiceWorkerProviderHost for this navigation, its
-// ownership is passed to the ServiceWorkerNavigationHandleCore. The
-// ServiceWorkerNavigationHandleCore id is updated.
+// 3) If we pre-create a ServiceWorkerProviderHost for this navigation, it
+// is added to ServiceWorkerContextCore and the id is passed to
+// ServiceWorkerNavigationHandleCore.
//
// 4) The ServiceWorkerNavigationHandleCore informs the
// ServiceWorkerNavigationHandle on the UI thread that the service worker
@@ -40,10 +40,11 @@ class ServiceWorkerNavigationHandleCore;
// ServiceWorkerNavigationHandle.
//
// 6) If the commit leads to the creation of a ServiceWorkerNetworkProvider
-// in the renderer, a ServiceWorkerHostMsg_ProviderCreated will be received
-// in the browser. The ServiceWorkerDispatcherHost will retrieve the
-// ServiceWorkerProviderHost from the ServiceWorkerNavigationHandleCore and
-// put it in the ServiceWorkerContextCore map of ServiceWorkerProviderHosts.
+// in the renderer, an OnProviderCreated IPC will be received in the browser.
+// The ServiceWorkerDispatcherHost will take the ServiceWorkerProviderHost
+// from ServiceWorkerContextCore and complete its initialization, including
+// setting the process id. It is then re-added to ServiceWorkerContextCore
+// since it now has a correct process id.
//
// 7) When the navigation finishes, the ServiceWorkerNavigationHandle is
// destroyed. The destructor of the ServiceWorkerNavigationHandle posts a
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
index a840a8aa76b..686fa1312a9 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.cc
@@ -12,7 +12,9 @@
#include "content/browser/service_worker/service_worker_navigation_handle.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/child_process_host.h"
namespace content {
@@ -27,39 +29,28 @@ ServiceWorkerNavigationHandleCore::ServiceWorkerNavigationHandleCore(
ServiceWorkerNavigationHandleCore::~ServiceWorkerNavigationHandleCore() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (precreated_host_.get() && context_wrapper_->context()) {
- context_wrapper_->context()->RemoveNavigationHandleCore(
- precreated_host_->provider_id());
+ if (provider_id_ == kInvalidServiceWorkerProviderId)
+ return;
+ // Remove the provider host if it was never completed (navigation failed).
+ ServiceWorkerContextCore* context = context_wrapper_->context();
+ if (!context || !context->GetProviderHost(ChildProcessHost::kInvalidUniqueID,
+ provider_id_)) {
+ return;
}
+ context->RemoveProviderHost(ChildProcessHost::kInvalidUniqueID, provider_id_);
}
void ServiceWorkerNavigationHandleCore::DidPreCreateProviderHost(
- std::unique_ptr<ServiceWorkerProviderHost> precreated_host) {
+ int provider_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(precreated_host.get());
- DCHECK(context_wrapper_->context());
+ DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id));
- precreated_host_ = std::move(precreated_host);
- context_wrapper_->context()->AddNavigationHandleCore(
- precreated_host_->provider_id(), this);
+ provider_id_ = provider_id;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&ServiceWorkerNavigationHandle::DidCreateServiceWorkerProviderHost,
- ui_handle_, precreated_host_->provider_id()));
-}
-
-std::unique_ptr<ServiceWorkerProviderHost>
-ServiceWorkerNavigationHandleCore::RetrievePreCreatedHost() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(precreated_host_);
- // Remove the ServiceWorkerNavigationHandleCore from the list of
- // ServiceWorkerNavigationHandleCores since it will no longer hold a
- // ServiceWorkerProviderHost.
- DCHECK(context_wrapper_->context());
- context_wrapper_->context()->RemoveNavigationHandleCore(
- precreated_host_->provider_id());
- return std::move(precreated_host_);
+ ui_handle_, provider_id_));
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.h b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.h
index 8e98b058739..ce581432ea9 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_handle_core.h
+++ b/chromium/content/browser/service_worker/service_worker_navigation_handle_core.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "content/common/service_worker/service_worker_types.h"
namespace content {
@@ -33,21 +34,15 @@ class CONTENT_EXPORT ServiceWorkerNavigationHandleCore {
~ServiceWorkerNavigationHandleCore();
// Called when a ServiceWorkerProviderHost was pre-created for the navigation
- // tracked by this ServiceWorkerNavigationHandleCore. Takes ownership of
- // |precreated_host|.
- void DidPreCreateProviderHost(
- std::unique_ptr<ServiceWorkerProviderHost> precreated_host);
-
- // Called when the renderer created a ServiceWorkerNetworkProvider matching
- // |precreated_host_|. This releases ownership of |precreated_host_|.
- std::unique_ptr<ServiceWorkerProviderHost> RetrievePreCreatedHost();
+ // tracked by this ServiceWorkerNavigationHandleCore.
+ void DidPreCreateProviderHost(int provider_id);
ServiceWorkerContextWrapper* context_wrapper() const {
return context_wrapper_.get();
}
private:
- std::unique_ptr<ServiceWorkerProviderHost> precreated_host_;
+ int provider_id_ = kInvalidServiceWorkerProviderId;
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
base::WeakPtr<ServiceWorkerNavigationHandle> ui_handle_;
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader.cc b/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
index 241e860824a..a5e6d0f8e73 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -359,7 +359,8 @@ void ServiceWorkerNavigationLoader::StartErrorResponse(
// URLLoader implementation----------------------------------------
-void ServiceWorkerNavigationLoader::FollowRedirect() {
+void ServiceWorkerNavigationLoader::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
NOTIMPLEMENTED();
}
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader.h b/chromium/content/browser/service_worker/service_worker_navigation_loader.h
index 4f12d5b6d15..3aef0461d18 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.h
@@ -57,8 +57,7 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
// determines how the request should be served (e.g. should fallback
// to network or should be sent to the SW). If it decides to fallback
// to the network this will call |loader_callback| with a null
- // RequestHandler, which will be then handled by
- // NavigationURLLoaderNetworkService.
+ // RequestHandler, which will be then handled by NavigationURLLoaderImpl.
// 2. If it is decided that the request should be sent to the SW,
// this job dispatches a FetchEvent in StartRequest.
// 3. In DidDispatchFetchEvent() this job determines the request's
@@ -69,12 +68,12 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
// StartResponse().
// 5. Then StartResponse() will be called with a
// network::mojom::URLLoaderClientPtr that is connected to
- // NavigationURLLoaderNetworkService (for resource loading for navigation).
+ // NavigationURLLoaderImpl (for resource loading for navigation).
// This forwards the blob/stream data pipe to the NavigationURLLoader if
// the response body was sent as a blob/stream.
//
// Loads for shared workers work similarly, except SharedWorkerScriptLoader
- // is used instead of NavigationURLLoaderNetworkService.
+ // is used instead of NavigationURLLoaderImpl.
ServiceWorkerNavigationLoader(
NavigationLoaderInterceptor::LoaderCallback loader_callback,
Delegate* delegate,
@@ -140,7 +139,8 @@ class CONTENT_EXPORT ServiceWorkerNavigationLoader
void ReturnNetworkError();
// network::mojom::URLLoader:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index e37883b9028..362281ad037 100644
--- a/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -191,11 +191,12 @@ class MockNetworkURLLoaderFactory final
client->OnComplete(status);
}
- void Clone(network::mojom::URLLoaderFactoryRequest factory) override {
- NOTREACHED();
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+ bindings_.AddBinding(this, std::move(request));
}
private:
+ mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
DISALLOW_COPY_AND_ASSIGN(MockNetworkURLLoaderFactory);
};
diff --git a/chromium/content/browser/service_worker/service_worker_new_script_loader.cc b/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
index 578d4ad6511..99d175d307f 100644
--- a/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -16,6 +16,7 @@
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "net/base/load_flags.h"
#include "net/cert/cert_status_flags.h"
#include "services/network/public/cpp/resource_response.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
@@ -31,20 +32,23 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
int32_t routing_id,
int32_t request_id,
uint32_t options,
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& original_request,
network::mojom::URLLoaderClientPtr client,
scoped_refptr<ServiceWorkerVersion> version,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
- : request_url_(resource_request.url),
- resource_type_(static_cast<ResourceType>(resource_request.resource_type)),
+ : request_url_(original_request.url),
+ resource_type_(static_cast<ResourceType>(original_request.resource_type)),
version_(version),
network_client_binding_(this),
network_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL,
base::SequencedTaskRunnerHandle::Get()),
+ loader_factory_(std::move(loader_factory)),
client_(std::move(client)),
weak_factory_(this) {
+ network::ResourceRequest resource_request(original_request);
+
// ServiceWorkerNewScriptLoader is used for fetching the service worker main
// script (RESOURCE_TYPE_SERVICE_WORKER) during worker startup or
// importScripts() (RESOURCE_TYPE_SCRIPT).
@@ -64,10 +68,13 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
// |incumbent_cache_resource_id| is valid if the incumbent service worker
// exists and it's required to do the byte-for-byte check.
int64_t incumbent_cache_resource_id = kInvalidServiceWorkerResourceId;
- if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
- scoped_refptr<ServiceWorkerRegistration> registration =
- version_->context()->GetLiveRegistration(version_->registration_id());
- DCHECK(registration);
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ version_->context()->GetLiveRegistration(version_->registration_id());
+ // ServiceWorkerVersion keeps the registration alive while the service
+ // worker is starting up, and it must be starting up here.
+ DCHECK(registration);
+ const bool is_main_script = resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
+ if (is_main_script) {
ServiceWorkerVersion* stored_version = registration->waiting_version()
? registration->waiting_version()
: registration->active_version();
@@ -80,6 +87,10 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
}
}
+ if (ServiceWorkerUtils::ShouldBypassCacheDueToUpdateViaCache(
+ is_main_script, registration->update_via_cache()))
+ resource_request.load_flags |= net::LOAD_BYPASS_CACHE;
+
// Create response readers only when we have to do the byte-for-byte check.
std::unique_ptr<ServiceWorkerResponseReader> compare_reader;
std::unique_ptr<ServiceWorkerResponseReader> copy_reader;
@@ -96,20 +107,21 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
cache_resource_id);
AdvanceState(State::kStarted);
- // Disable MIME sniffing sniffing. The spec requires the header list to have
- // a JavaScript MIME type. Therefore, no sniffing is needed.
+ // Disable MIME sniffing. The spec requires the header list to have a
+ // JavaScript MIME type. Therefore, no sniffing is needed.
options &= ~network::mojom::kURLLoadOptionSniffMimeType;
network::mojom::URLLoaderClientPtr network_client;
network_client_binding_.Bind(mojo::MakeRequest(&network_client));
- loader_factory_getter->GetNetworkFactory()->CreateLoaderAndStart(
+ loader_factory_->CreateLoaderAndStart(
mojo::MakeRequest(&network_loader_), routing_id, request_id, options,
resource_request, std::move(network_client), traffic_annotation);
}
ServiceWorkerNewScriptLoader::~ServiceWorkerNewScriptLoader() = default;
-void ServiceWorkerNewScriptLoader::FollowRedirect() {
+void ServiceWorkerNewScriptLoader::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
// Resource requests for service worker scripts should not follow redirects.
// See comments in OnReceiveRedirect().
NOTREACHED();
diff --git a/chromium/content/browser/service_worker/service_worker_new_script_loader.h b/chromium/content/browser/service_worker/service_worker_new_script_loader.h
index 621ce8ef458..c26100f4ca9 100644
--- a/chromium/content/browser/service_worker/service_worker_new_script_loader.h
+++ b/chromium/content/browser/service_worker/service_worker_new_script_loader.h
@@ -19,7 +19,6 @@ namespace content {
class ServiceWorkerCacheWriter;
class ServiceWorkerVersion;
-class URLLoaderFactoryGetter;
struct HttpResponseInfoIOBuffer;
// S13nServiceWorker:
@@ -44,23 +43,32 @@ struct HttpResponseInfoIOBuffer;
// this class also performs the "byte-for-byte" comparison for updating the
// worker. If the script is identical, the load succeeds but no script is
// written, and ServiceWorkerVersion is told to terminate startup.
+//
+// NOTE: To perform the network request, this class uses |loader_factory_| which
+// may internally use a non-NetworkService factory if URL has a non-http(s)
+// scheme, e.g., a chrome-extension:// URL. Regardless, that is still called a
+// "network" request in comments and naming. "network" is meant to distinguish
+// from the load this URLLoader does for its client:
+// "network" <------> SWNewScriptLoader <------> client
class CONTENT_EXPORT ServiceWorkerNewScriptLoader
: public network::mojom::URLLoader,
public network::mojom::URLLoaderClient {
public:
+ // |loader_factory| is used to load the script, see class comments.
ServiceWorkerNewScriptLoader(
int32_t routing_id,
int32_t request_id,
uint32_t options,
- const network::ResourceRequest& resource_request,
+ const network::ResourceRequest& original_request,
network::mojom::URLLoaderClientPtr client,
scoped_refptr<ServiceWorkerVersion> version,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
~ServiceWorkerNewScriptLoader() override;
// network::mojom::URLLoader:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
@@ -132,12 +140,14 @@ class CONTENT_EXPORT ServiceWorkerNewScriptLoader
std::unique_ptr<ServiceWorkerCacheWriter> cache_writer_;
- // Used for fetching the script from network.
+ // Used for fetching the script from network, which might not actually
+ // use the direct network factory, see class comments.
network::mojom::URLLoaderPtr network_loader_;
mojo::Binding<network::mojom::URLLoaderClient> network_client_binding_;
mojo::ScopedDataPipeConsumerHandle network_consumer_;
mojo::SimpleWatcher network_watcher_;
bool network_load_completed_ = false;
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
// Used for responding with the fetched script to this loader's client.
network::mojom::URLLoaderClientPtr client_;
diff --git a/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc b/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
index c034c9c80d5..100e0c71be4 100644
--- a/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
@@ -227,7 +227,7 @@ class ServiceWorkerNewScriptLoaderTest : public testing::Test {
client_ = std::make_unique<network::TestURLLoaderClient>();
loader_ = std::make_unique<ServiceWorkerNewScriptLoader>(
routing_id, request_id, options, request, client_->CreateInterfacePtr(),
- version_, helper_->url_loader_factory_getter(),
+ version_, helper_->url_loader_factory_getter()->GetNetworkFactory(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
}
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
index 0139091213d..ab6899ad6ae 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -4,6 +4,8 @@
#include "content/browser/service_worker/service_worker_process_manager.h"
+#include <string>
+
#include "base/macros.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -68,14 +70,14 @@ class ServiceWorkerProcessManagerTest : public testing::Test {
script_url_ = GURL("http://www.example.com/sw.js");
render_process_host_factory_.reset(
new SiteInstanceRenderProcessHostFactory());
- RenderProcessHostImpl::set_render_process_host_factory(
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(
render_process_host_factory_.get());
}
void TearDown() override {
process_manager_->Shutdown();
process_manager_.reset();
- RenderProcessHostImpl::set_render_process_host_factory(nullptr);
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(nullptr);
render_process_host_factory_.reset();
}
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.cc b/chromium/content/browser/service_worker/service_worker_provider_host.cc
index bdbd4e18287..4208300ee9b 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -19,6 +19,7 @@
#include "content/browser/service_worker/service_worker_consts.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_registration_object_host.h"
@@ -27,7 +28,6 @@
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
@@ -35,7 +35,6 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
@@ -146,36 +145,15 @@ ServiceWorkerMetrics::EventType PurposeToEventType(
return ServiceWorkerMetrics::EventType::UNKNOWN;
}
-// TODO(crbug/831255): Temporary debugging for the linked bug.
-std::string URLStringForBadMessage(const GURL& url) {
- return url.possibly_invalid_spec().substr(0, 64);
-}
-
-// TODO(crbug/831255): Temporary debugging for the linked bug.
-std::string ProviderTypeStringForBadMessage(
- blink::mojom::ServiceWorkerProviderType type) {
- switch (type) {
- case blink::mojom::ServiceWorkerProviderType::kUnknown:
- return "unknown";
- case blink::mojom::ServiceWorkerProviderType::kForSharedWorker:
- return "shared";
- case blink::mojom::ServiceWorkerProviderType::kForServiceWorker:
- return "service";
- case blink::mojom::ServiceWorkerProviderType::kForWindow:
- return "window";
- }
- NOTREACHED();
- return std::string();
-}
-
} // anonymous namespace
// static
-std::unique_ptr<ServiceWorkerProviderHost>
+base::WeakPtr<ServiceWorkerProviderHost>
ServiceWorkerProviderHost::PreCreateNavigationHost(
base::WeakPtr<ServiceWorkerContextCore> context,
bool are_ancestors_secure,
const WebContentsGetter& web_contents_getter) {
+ DCHECK(context);
auto host = base::WrapUnique(new ServiceWorkerProviderHost(
ChildProcessHost::kInvalidUniqueID,
ServiceWorkerProviderHostInfo(
@@ -184,7 +162,10 @@ ServiceWorkerProviderHost::PreCreateNavigationHost(
are_ancestors_secure),
context, nullptr /* dispatcher_host */));
host->web_contents_getter_ = web_contents_getter;
- return host;
+
+ auto weak_ptr = host->AsWeakPtr();
+ context->AddProviderHost(std::move(host));
+ return weak_ptr;
}
// static
@@ -282,17 +263,30 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost(
}
ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // TODO(crbug.com/838410): The CHECKs are temporary debugging for the linked
+ // bug.
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ CHECK(!in_dtor_);
+ in_dtor_ = true;
+
if (context_)
context_->UnregisterProviderHostByClientID(client_uuid_);
+ if (controller_)
+ controller_->RemoveControllee(client_uuid_);
- // Clear docurl so the deferred activation of a waiting worker
- // won't associate the new version with a provider being destroyed.
- document_url_ = GURL();
- if (controller_.get())
- controller_->RemoveControllee(this);
-
+ // Remove |this| as an observer of ServiceWorkerRegistrations.
+ // TODO(falken): Use ScopedObserver instead of this explicit call.
RemoveAllMatchingRegistrations();
+
+ // Explicitly destroy the ServiceWorkerObjectHosts and
+ // ServiceWorkerRegistrationObjectHosts owned by |this|. Otherwise, this
+ // destructor can trigger their Mojo connection error handlers, which would
+ // call back into halfway destroyed |this|. This is because they are
+ // associated with the ServiceWorkerEventDispatcher interface, which can
+ // be destroyed while in this destructor (|running_hosted_version_|'s
+ // |event_dispatcher_|). See https://crbug.com/854993.
+ handles_.clear();
+ registration_object_hosts_.clear();
}
int ServiceWorkerProviderHost::frame_id() const {
@@ -407,7 +401,7 @@ void ServiceWorkerProviderHost::SetControllerVersionAttribute(
version->AddControllee(this);
if (previous_version.get())
- previous_version->RemoveControllee(this);
+ previous_version->RemoveControllee(client_uuid_);
// SetController message should be sent only for clients.
DCHECK(IsProviderForClient());
@@ -462,7 +456,6 @@ void ServiceWorkerProviderHost::AssociateRegistration(
void ServiceWorkerProviderHost::DisassociateRegistration() {
DCHECK(IsProviderForClient());
- queued_events_.clear();
if (!associated_registration_.get())
return;
associated_registration_ = nullptr;
@@ -517,9 +510,10 @@ void ServiceWorkerProviderHost::RemoveServiceWorkerHandle(int64_t version_id) {
}
bool ServiceWorkerProviderHost::AllowServiceWorker(const GURL& scope) {
+ DCHECK(IsContextAlive());
return GetContentClient()->browser()->AllowServiceWorker(
scope, IsProviderForClient() ? topmost_frame_url() : document_url(),
- dispatcher_host_->resource_context(),
+ context_->wrapper()->resource_context(),
base::Bind(&WebContentsImpl::FromRenderFrameHostID, render_process_id_,
frame_id()));
}
@@ -572,7 +566,7 @@ ServiceWorkerProviderHost::CreateRequestHandler(
return std::unique_ptr<ServiceWorkerRequestHandler>();
}
-blink::mojom::ServiceWorkerObjectInfoPtr
+base::WeakPtr<ServiceWorkerHandle>
ServiceWorkerProviderHost::GetOrCreateServiceWorkerHandle(
ServiceWorkerVersion* version) {
if (!context_ || !version)
@@ -581,11 +575,11 @@ ServiceWorkerProviderHost::GetOrCreateServiceWorkerHandle(
const int64_t version_id = version->version_id();
auto existing_handle = handles_.find(version_id);
if (existing_handle != handles_.end())
- return existing_handle->second->CreateObjectInfo();
+ return existing_handle->second->AsWeakPtr();
handles_[version_id] =
std::make_unique<ServiceWorkerHandle>(context_, this, version);
- return handles_[version_id]->CreateObjectInfo();
+ return handles_[version_id]->AsWeakPtr();
}
bool ServiceWorkerProviderHost::CanAssociateRegistration(
@@ -606,8 +600,12 @@ void ServiceWorkerProviderHost::PostMessageToClient(
if (!dispatcher_host_)
return;
- container_->PostMessageToClient(GetOrCreateServiceWorkerHandle(version),
- std::move(message));
+ blink::mojom::ServiceWorkerObjectInfoPtr info;
+ base::WeakPtr<ServiceWorkerHandle> handle =
+ GetOrCreateServiceWorkerHandle(version);
+ if (handle)
+ info = handle->CreateCompleteObjectInfoToSend();
+ container_->PostMessageToClient(std::move(info), std::move(message));
}
void ServiceWorkerProviderHost::CountFeature(blink::mojom::WebFeature feature) {
@@ -661,19 +659,17 @@ void ServiceWorkerProviderHost::CompleteNavigationInitialized(
if (!controller_)
return;
- // In S13nServiceWorker/NavigationMojoResponse case the controller is already
- // sent in navigation commit, but we still need this for
- // S13nServiceWorker/NavigationMojoResponse case for setting the use counter
- // correctly.
- // TODO(kinuko): Stop doing this in S13nServiceWorker/NavigationMojoResponse
- // case.
+ // The controller is already sent in navigation commit, but we still need this
+ // for setting the use counter correctly.
+ // TODO(kinuko): Stop doing this.
SendSetControllerServiceWorker(false /* notify_controllerchange */);
}
mojom::ServiceWorkerProviderInfoForStartWorkerPtr
ServiceWorkerProviderHost::CompleteStartWorkerPreparation(
int process_id,
- scoped_refptr<ServiceWorkerVersion> hosted_version) {
+ scoped_refptr<ServiceWorkerVersion> hosted_version,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
DCHECK(context_);
DCHECK_EQ(kInvalidEmbeddedWorkerThreadId, render_thread_id_);
DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
@@ -690,20 +686,11 @@ ServiceWorkerProviderHost::CompleteStartWorkerPreparation(
DCHECK(dispatcher_host);
render_process_id_ = process_id;
dispatcher_host_ = dispatcher_host->AsWeakPtr();
- SetDocumentUrl(running_hosted_version()->script_url());
-
- // Retrieve the registration associated with |version|. The registration
- // must be alive because the version keeps it during starting worker.
- ServiceWorkerRegistration* registration = context_->GetLiveRegistration(
- running_hosted_version()->registration_id());
- DCHECK(registration);
// Initialize provider_info.
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
mojom::ServiceWorkerProviderInfoForStartWorker::New();
provider_info->provider_id = provider_id();
- provider_info->registration = CreateServiceWorkerRegistrationObjectInfo(
- scoped_refptr<ServiceWorkerRegistration>(registration));
provider_info->client_request = mojo::MakeRequest(&container_);
network::mojom::URLLoaderFactoryAssociatedPtrInfo
@@ -711,7 +698,7 @@ ServiceWorkerProviderHost::CompleteStartWorkerPreparation(
if (ServiceWorkerUtils::IsServicificationEnabled()) {
mojo::MakeStrongAssociatedBinding(
std::make_unique<ServiceWorkerScriptLoaderFactory>(
- context_, AsWeakPtr(), context_->loader_factory_getter()),
+ context_, AsWeakPtr(), std::move(loader_factory)),
mojo::MakeRequest(&script_loader_factory_ptr_info));
provider_info->script_loader_factory_ptr_info =
std::move(script_loader_factory_ptr_info);
@@ -734,33 +721,6 @@ void ServiceWorkerProviderHost::CompleteSharedWorkerPreparation() {
is_execution_ready_ = true;
}
-void ServiceWorkerProviderHost::SendServiceWorkerStateChangedMessage(
- int worker_handle_id,
- blink::mojom::ServiceWorkerState state) {
- if (!dispatcher_host_)
- return;
-
- if (!IsReadyToSendMessages()) {
- queued_events_.push_back(base::Bind(
- &ServiceWorkerProviderHost::SendServiceWorkerStateChangedMessage,
- AsWeakPtr(), worker_handle_id, state));
- return;
- }
-
- Send(new ServiceWorkerMsg_ServiceWorkerStateChanged(render_thread_id_,
- worker_handle_id, state));
-}
-
-void ServiceWorkerProviderHost::SetReadyToSendMessagesToWorker(
- int render_thread_id) {
- DCHECK(!IsReadyToSendMessages());
- render_thread_id_ = render_thread_id;
-
- for (const auto& event : queued_events_)
- event.Run();
- queued_events_.clear();
-}
-
void ServiceWorkerProviderHost::SyncMatchingRegistrations() {
DCHECK(context_);
RemoveAllMatchingRegistrations();
@@ -802,20 +762,10 @@ void ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded() {
scoped_refptr<ServiceWorkerRegistration>(registration)));
}
-bool ServiceWorkerProviderHost::IsReadyToSendMessages() const {
- return render_thread_id_ != kInvalidEmbeddedWorkerThreadId;
-}
-
bool ServiceWorkerProviderHost::IsContextAlive() {
return context_ != nullptr;
}
-void ServiceWorkerProviderHost::Send(IPC::Message* message) const {
- DCHECK(dispatcher_host_);
- DCHECK(IsReadyToSendMessages());
- dispatcher_host_->Send(message);
-}
-
void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
bool notify_controllerchange) {
if (!dispatcher_host_)
@@ -834,8 +784,10 @@ void ServiceWorkerProviderHost::SendSetControllerServiceWorker(
DCHECK_EQ(associated_registration_->active_version(), controller_.get());
// Set the info for the JavaScript ServiceWorkerContainer#controller object.
- controller_info->object_info =
+ base::WeakPtr<ServiceWorkerHandle> handle =
GetOrCreateServiceWorkerHandle(controller_.get());
+ if (handle)
+ controller_info->object_info = handle->CreateCompleteObjectInfoToSend();
// Populate used features for UseCounter purposes.
std::vector<blink::mojom::WebFeature> used_features;
@@ -1123,41 +1075,17 @@ bool ServiceWorkerProviderHost::IsValidRegisterMessage(
*out_error = ServiceWorkerConsts::kBadMessageFromNonWindow;
return false;
}
- // TODO(crbug/831255): Temporary detailed messages for the linked bug.
- // These message are compact since there are only 256 characters available.
- const std::string provider_str =
- ProviderTypeStringForBadMessage(provider_type());
- std::stringstream stream;
- if (!document_url_.is_valid()) {
- stream << "SWPH_REGISTER_INVALID_DOCUMENT:" << provider_str
- << "d=" << URLStringForBadMessage(document_url_);
- *out_error = stream.str();
- return false;
- }
- if (!options.scope.is_valid()) {
- stream << "SWPH_REGISTER_INVALID_SCOPE:" << provider_str
- << "p=" << URLStringForBadMessage(options.scope);
- *out_error = stream.str();
- return false;
- }
- if (!script_url.is_valid()) {
- stream << "SWPH_REGISTER_INVALID_SCRIPT: " << provider_str
- << "s=" << URLStringForBadMessage(script_url);
- *out_error = stream.str();
+ if (!options.scope.is_valid() || !script_url.is_valid()) {
+ *out_error = ServiceWorkerConsts::kBadMessageInvalidURL;
return false;
}
-
if (ServiceWorkerUtils::ContainsDisallowedCharacter(options.scope, script_url,
out_error)) {
return false;
}
- std::vector<GURL> urls = {document_url_, options.scope, script_url};
+ std::vector<GURL> urls = {document_url(), options.scope, script_url};
if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
- stream << "SWPH_REGISTER:" << provider_str
- << ",d=" << URLStringForBadMessage(document_url_)
- << ",p=" << URLStringForBadMessage(options.scope)
- << ",s=" << URLStringForBadMessage(script_url);
- *out_error = stream.str();
+ *out_error = ServiceWorkerConsts::kBadMessageImproperOrigins;
return false;
}
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.h b/chromium/content/browser/service_worker/service_worker_provider_host.h
index a82b1ffd2b5..9b69c149e3a 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -133,11 +133,16 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Used to pre-create a ServiceWorkerProviderHost for a navigation. The
// ServiceWorkerNetworkProvider will later be created in the renderer, should
- // the navigation succeed. |is_parent_frame_is_secure| should be true for main
+ // the navigation succeed. |are_ancestors_secure| should be true for main
// frames. Otherwise it is true iff all ancestor frames of this frame have a
// secure origin. |web_contents_getter| indicates the tab where the navigation
// is occurring.
- static std::unique_ptr<ServiceWorkerProviderHost> PreCreateNavigationHost(
+ //
+ // The returned host is owned by |context|. Upon successful navigation, the
+ // caller should remove it from |context| and re-add it after calling
+ // CompleteNavigationInitialized() to update it with the correct process id.
+ // If navigation fails, the caller should remove it from |context|.
+ static base::WeakPtr<ServiceWorkerProviderHost> PreCreateNavigationHost(
base::WeakPtr<ServiceWorkerContextCore> context,
bool are_ancestors_secure,
const WebContentsGetter& web_contents_getter);
@@ -332,13 +337,26 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
scoped_refptr<network::ResourceRequestBody> body,
bool skip_service_worker);
- // Used to get a ServiceWorkerObjectInfo to send to the renderer.
- // The object info holds a Mojo connection to the ServiceWorkerHandle for the
- // |version| to ensure the handle stays alive while the object info is alive.
- // A new handle is created if one does not already exist.
+ // Returns an object info representing |registration|. The object info holds a
+ // Mojo connection to the ServiceWorkerRegistrationObjectHost for the
+ // |registration| to ensure the host stays alive while the object info is
+ // alive. A new ServiceWorkerRegistrationObjectHost instance is created if one
+ // can not be found in |registration_object_hosts_|.
+ //
+ // NOTE: The registration object info should be sent over Mojo in the same
+ // task with calling this method. Otherwise, some Mojo calls to
+ // blink::mojom::ServiceWorkerRegistrationObject or
+ // blink::mojom::ServiceWorkerObject may happen before establishing the
+ // connections, and they'll end up with crashes.
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
+ CreateServiceWorkerRegistrationObjectInfo(
+ scoped_refptr<ServiceWorkerRegistration> registration);
+
+ // Returns a ServiceWorkerHandle instance for |version| for this provider
+ // host. A new instance is created if one does not already exist.
// TODO(leonhsl): Make |version| be a scoped_refptr because we'll take its
// ownership.
- blink::mojom::ServiceWorkerObjectInfoPtr GetOrCreateServiceWorkerHandle(
+ base::WeakPtr<ServiceWorkerHandle> GetOrCreateServiceWorkerHandle(
ServiceWorkerVersion* version);
// Returns true if |registration| can be associated with this provider.
@@ -364,36 +382,35 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// |registration| claims the document to be controlled.
void ClaimedByRegistration(ServiceWorkerRegistration* registration);
- // Completes initialization of provider hosts used for navigation requests.
+ // For service worker clients. Completes initialization of
+ // provider hosts used for navigation requests.
void CompleteNavigationInitialized(
int process_id,
ServiceWorkerProviderHostInfo info,
base::WeakPtr<ServiceWorkerDispatcherHost> dispatcher_host);
- // Completes initialization of this provider host (which is for hosting a
- // service worker). It is called once a renderer process has been found to
- // host the worker. Returns the info needed for creating a
- // ServiceWorkerNetworkProvider on the renderer which will be connected to
- // this instance. This instance will keep the reference to |hosted_version|,
- // so please be careful not to create a reference cycle.
+ // For service worker execution contexts. Completes initialization of this
+ // provider host. It is called once a renderer process has been found to host
+ // the worker. Returns the info needed for creating a provider on the renderer
+ // which will be connected to this provider host. This instance will take the
+ // reference to |hosted_version|, so be careful not to create a reference
+ // cycle.
+ //
+ // S13nServiceWorker:
+ // |loader_factory| is the factory to use for "network" requests for the
+ // service worker main script and import scripts. It is possibly not the
+ // simple direct network factory, since service worker scripts can have
+ // non-NetworkService schemes, e.g., chrome-extension:// URLs.
mojom::ServiceWorkerProviderInfoForStartWorkerPtr
CompleteStartWorkerPreparation(
int process_id,
- scoped_refptr<ServiceWorkerVersion> hosted_version);
+ scoped_refptr<ServiceWorkerVersion> hosted_version,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
// Called when the shared worker main script resource has finished loading.
// After this is called, is_execution_ready() returns true.
void CompleteSharedWorkerPreparation();
- // Sends event messages to the renderer. Events for the worker are queued up
- // until the worker thread id is known via SetReadyToSendMessagesToWorker().
- void SendServiceWorkerStateChangedMessage(
- int worker_handle_id,
- blink::mojom::ServiceWorkerState state);
-
- // Sets the worker thread id and flushes queued events.
- void SetReadyToSendMessagesToWorker(int render_thread_id);
-
void AddMatchingRegistration(ServiceWorkerRegistration* registration);
void RemoveMatchingRegistration(ServiceWorkerRegistration* registration);
@@ -482,9 +499,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void ReturnRegistrationForReadyIfNeeded();
- bool IsReadyToSendMessages() const;
- void Send(IPC::Message* message) const;
-
// Sends information about the controller to the providers of the service
// worker clients in the renderer. If |notify_controllerchange| is true,
// instructs the renderer to dispatch a 'controllerchange' event.
@@ -545,15 +559,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void GetInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
- // Returns an object info representing |registration|. The object info holds a
- // Mojo connection to the ServiceWorkerRegistrationObjectHost for the
- // |registration| to ensure the host stays alive while the object info is
- // alive. A new ServiceWorkerRegistrationObjectHost instance is created if one
- // can not be found in |registration_object_hosts_|.
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
- CreateServiceWorkerRegistrationObjectInfo(
- scoped_refptr<ServiceWorkerRegistration> registration);
-
// Perform common checks that need to run before ContainerHost methods that
// come from a child process are handled.
// |scope| is checked if it is allowed to run a service worker.
@@ -663,8 +668,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
mojo::BindingSet<mojom::ServiceWorkerContainerHost>
bindings_for_worker_threads_;
- std::vector<base::Closure> queued_events_;
-
// For service worker execution contexts.
mojo::Binding<service_manager::mojom::InterfaceProvider>
interface_provider_binding_;
@@ -674,6 +677,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// redirects.
bool is_execution_ready_ = false;
+ // TODO(crbug.com/838410): Temporary debugging for the linked bug.
+ bool in_dtor_ = false;
+
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHost);
};
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
index 21722145594..d5a07710e2f 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -161,6 +161,24 @@ class ServiceWorkerProviderHostTest : public testing::Test {
return host_raw;
}
+ void FinishNavigation(ServiceWorkerProviderHost* host,
+ ServiceWorkerProviderHostInfo info) {
+ // In production code, the loader/request handler does this.
+ host->SetDocumentUrl(GURL("https://www.example.com/page"));
+ host->SetTopmostFrameUrl(GURL("https://www.example.com/page"));
+
+ // In production code, the OnProviderCreated IPC is received which
+ // does this.
+ std::unique_ptr<ServiceWorkerProviderHost> owned_host =
+ helper_->context()->ReleaseProviderHost(host->process_id(),
+ host->provider_id());
+ host->CompleteNavigationInitialized(
+ helper_->mock_render_process_id(), std::move(info),
+ helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
+ ->AsWeakPtr());
+ helper_->context()->AddProviderHost(std::move(owned_host));
+ }
+
blink::mojom::ServiceWorkerErrorType Register(
mojom::ServiceWorkerContainerHost* container_host,
GURL pattern,
@@ -228,7 +246,8 @@ class ServiceWorkerProviderHostTest : public testing::Test {
bool CanFindClientProviderHost(ServiceWorkerProviderHost* host) {
for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
context_->GetClientProviderHostIterator(
- host->document_url().GetOrigin());
+ host->document_url().GetOrigin(),
+ false /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
if (host == it->GetProviderHost())
return true;
@@ -255,7 +274,7 @@ class ServiceWorkerProviderHostTest : public testing::Test {
const GURL& document_url,
const GURL& topmost_frame_url,
ServiceWorkerRemoteProviderEndpoint* remote_endpoint) {
- std::unique_ptr<ServiceWorkerProviderHost> host =
+ base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true,
base::Callback<WebContents*(void)>());
@@ -264,16 +283,19 @@ class ServiceWorkerProviderHostTest : public testing::Test {
blink::mojom::ServiceWorkerProviderType::kForWindow,
true /* is_parent_frame_secure */);
remote_endpoint->BindWithProviderHostInfo(&info);
+
+ std::unique_ptr<ServiceWorkerProviderHost> owned_host =
+ helper_->context()->ReleaseProviderHost(host->process_id(),
+ host->provider_id());
host->CompleteNavigationInitialized(
helper_->mock_render_process_id(), std::move(info),
helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
->AsWeakPtr());
-
host->SetDocumentUrl(document_url);
host->SetTopmostFrameUrl(topmost_frame_url);
- ServiceWorkerProviderHost* host_raw = host.get();
- context_->AddProviderHost(std::move(host));
- return host_raw;
+ helper_->context()->AddProviderHost(std::move(owned_host));
+
+ return host.get();
}
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostTest);
@@ -407,7 +429,7 @@ class MockServiceWorkerContainer : public mojom::ServiceWorkerContainer {
TEST_F(ServiceWorkerProviderHostTest, Controller) {
// Create a host.
- std::unique_ptr<ServiceWorkerProviderHost> host =
+ base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::Callback<WebContents*(void)>());
@@ -427,12 +449,7 @@ TEST_F(ServiceWorkerProviderHostTest, Controller) {
registration1_->SetActiveVersion(version);
// Finish the navigation.
- host->SetDocumentUrl(GURL("https://www.example.com/page"));
- host->CompleteNavigationInitialized(
- helper_->mock_render_process_id(), std::move(info),
- helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
- ->AsWeakPtr());
-
+ FinishNavigation(host.get(), std::move(info));
host->AssociateRegistration(registration1_.get(),
false /* notify_controllerchange */);
base::RunLoop().RunUntilIdle();
@@ -446,7 +463,7 @@ TEST_F(ServiceWorkerProviderHostTest, Controller) {
TEST_F(ServiceWorkerProviderHostTest, ActiveIsNotController) {
// Create a host.
- std::unique_ptr<ServiceWorkerProviderHost> host =
+ base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
base::Callback<WebContents*(void)>());
@@ -467,12 +484,7 @@ TEST_F(ServiceWorkerProviderHostTest, ActiveIsNotController) {
// Finish the navigation.
- host->SetDocumentUrl(GURL("https://www.example.com/page"));
- host->CompleteNavigationInitialized(
- helper_->mock_render_process_id(), std::move(info),
- helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
- ->AsWeakPtr());
-
+ FinishNavigation(host.get(), std::move(info));
host->AssociateRegistration(registration1_.get(),
false /* notify_controllerchange */);
// Promote the worker to active while navigation is still happening.
@@ -809,9 +821,9 @@ TEST_F(ServiceWorkerProviderHostTest,
EXPECT_EQ(1u, bad_messages_.size());
}
-// Test that a "reserved" (i.e., not execution ready) shared worker client is
-// not included when iterating over client provider hosts. If it were, it'd be
-// undesirably exposed via the Clients API.
+// Test that a "reserved" (i.e., not execution ready) client is not included
+// when iterating over client provider hosts. If it were, it'd be undesirably
+// exposed via the Clients API.
TEST_F(ServiceWorkerProviderHostTest,
ReservedClientsAreNotExposedToClientsAPI) {
{
@@ -828,7 +840,7 @@ TEST_F(ServiceWorkerProviderHostTest,
}
{
- std::unique_ptr<ServiceWorkerProviderHost> host =
+ base::WeakPtr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
helper_->context()->AsWeakPtr(), true,
base::RepeatingCallback<WebContents*(void)>());
@@ -841,13 +853,8 @@ TEST_F(ServiceWorkerProviderHostTest,
host->SetDocumentUrl(GURL("https://www.example.com/page"));
EXPECT_FALSE(CanFindClientProviderHost(host.get()));
- host->CompleteNavigationInitialized(
- helper_->mock_render_process_id(), std::move(info),
- helper_->GetDispatcherHostForProcess(helper_->mock_render_process_id())
- ->AsWeakPtr());
- auto* host_rawptr = host.get();
- context_->AddProviderHost(std::move(host));
- EXPECT_TRUE(CanFindClientProviderHost(host_rawptr));
+ FinishNavigation(host.get(), std::move(info));
+ EXPECT_TRUE(CanFindClientProviderHost(host.get()));
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.cc b/chromium/content/browser/service_worker/service_worker_register_job.cc
index d1d5416741b..69d7b3154e2 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -47,6 +47,7 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
force_bypass_cache_(false),
skip_script_comparison_(false),
promise_resolved_status_(SERVICE_WORKER_OK),
+ observer_(this),
weak_factory_(this) {}
ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
@@ -65,6 +66,7 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
force_bypass_cache_(force_bypass_cache),
skip_script_comparison_(skip_script_comparison),
promise_resolved_status_(SERVICE_WORKER_OK),
+ observer_(this),
weak_factory_(this) {
internal_.registration = registration;
}
@@ -241,7 +243,7 @@ void ServiceWorkerRegisterJob::ContinueWithRegistration(
// "Invoke Set Registration algorithm with job’s scope url and
// job’s update via cache mode."
- existing_registration->set_update_via_cache(update_via_cache_);
+ existing_registration->SetUpdateViaCache(update_via_cache_);
set_registration(existing_registration);
// "Return the result of running the [[Update]] algorithm, or its equivalent,
// passing registration as the argument."
@@ -356,7 +358,7 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
new_version()->set_force_bypass_cache_for_scripts(force_bypass_cache_);
if (registration()->has_installed_version() && !skip_script_comparison_) {
new_version()->set_pause_after_download(true);
- new_version()->embedded_worker()->AddListener(this);
+ observer_.Add(new_version()->embedded_worker());
} else {
new_version()->set_pause_after_download(false);
}
@@ -533,7 +535,7 @@ void ServiceWorkerRegisterJob::CompleteInternal(
if (new_version()) {
new_version()->set_pause_after_download(false);
- new_version()->embedded_worker()->RemoveListener(this);
+ observer_.RemoveAll();
}
if (status != SERVICE_WORKER_OK) {
@@ -588,7 +590,8 @@ void ServiceWorkerRegisterJob::AddRegistrationToMatchingProviderHosts(
DCHECK(registration);
for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
context_->GetClientProviderHostIterator(
- registration->pattern().GetOrigin());
+ registration->pattern().GetOrigin(),
+ true /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
ServiceWorkerProviderHost* host = it->GetProviderHost();
if (!ServiceWorkerUtils::ScopeMatches(registration->pattern(),
@@ -620,6 +623,16 @@ void ServiceWorkerRegisterJob::OnScriptLoaded() {
new_version()->embedded_worker()->ResumeAfterDownload();
}
+void ServiceWorkerRegisterJob::OnDestroyed() {
+ // The version's EmbeddedWorkerInstance is getting destructed, so
+ // remove the observer to avoid a use-after-free. We expect to continue when
+ // the StartWorker() callback is called with failure.
+ // TODO(crbug.com/855852): Remove the EmbeddedWorkerInstance::Listener
+ // interface and have this class listen to ServiceWorkerVersion directly.
+ if (observer_.IsObserving(new_version()->embedded_worker()))
+ observer_.Remove(new_version()->embedded_worker());
+}
+
void ServiceWorkerRegisterJob::BumpLastUpdateCheckTimeIfNeeded() {
// Bump the last update check time only when the register/update job fetched
// the version having bypassed the network cache. We assume that the
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.h b/chromium/content/browser/service_worker/service_worker_register_job.h
index cd726a0661b..29cd3f2e423 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/service_worker_register_job_base.h"
@@ -139,6 +140,7 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
// EmbeddedWorkerInstance::Listener implementation:
void OnScriptLoaded() override;
+ void OnDestroyed() override;
void BumpLastUpdateCheckTimeIfNeeded();
@@ -160,6 +162,8 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
ServiceWorkerStatusCode promise_resolved_status_;
std::string promise_resolved_status_message_;
scoped_refptr<ServiceWorkerRegistration> promise_resolved_registration_;
+ ScopedObserver<EmbeddedWorkerInstance, EmbeddedWorkerInstance::Listener>
+ observer_;
base::WeakPtrFactory<ServiceWorkerRegisterJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegisterJob);
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index 3791d4e7af3..98c613109de 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -194,6 +194,15 @@ void ServiceWorkerRegistration::UnsetVersionInternal(
}
}
+void ServiceWorkerRegistration::SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache) {
+ if (update_via_cache_ == update_via_cache)
+ return;
+ update_via_cache_ = update_via_cache;
+ for (auto& observer : listeners_)
+ observer.OnUpdateViaCacheChanged(this);
+}
+
void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
DCHECK(waiting_version());
should_activate_when_ready_ = true;
@@ -219,7 +228,8 @@ void ServiceWorkerRegistration::ClaimClients() {
DCHECK(active_version());
for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
- context_->GetClientProviderHostIterator(pattern_.GetOrigin());
+ context_->GetClientProviderHostIterator(
+ pattern_.GetOrigin(), false /* include_reserved_clients */);
!it->IsAtEnd(); it->Advance()) {
ServiceWorkerProviderHost* host = it->GetProviderHost();
if (host->controller() == active_version())
@@ -271,6 +281,9 @@ void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
return;
DCHECK_EQ(active_version(), version);
if (is_uninstalling_) {
+ // TODO(falken): This can destroy the caller during this observer function
+ // call, which is impolite and dangerous. Try to make this async, or make
+ // OnNoControllees not an observer function.
Clear();
return;
}
@@ -543,6 +556,14 @@ void ServiceWorkerRegistration::Clear() {
is_uninstalling_ = false;
is_uninstalled_ = true;
should_activate_when_ready_ = false;
+
+ // Some callbacks, at least OnRegistrationFinishedUninstalling and
+ // NotifyDoneUninstallingRegistration, may drop their references to
+ // |this|, so protect it first.
+ // TODO(falken): Clean this up, can we call the observers from a task
+ // or make the observers more polite?
+ auto protect = base::WrapRefCounted(this);
+
if (context_)
context_->storage()->NotifyDoneUninstallingRegistration(this);
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index 164a9ac1960..032fa94be09 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -47,6 +47,8 @@ class CONTENT_EXPORT ServiceWorkerRegistration
ServiceWorkerRegistration* registration,
ChangedVersionAttributesMask changed_mask,
const ServiceWorkerRegistrationInfo& info) {}
+ virtual void OnUpdateViaCacheChanged(
+ ServiceWorkerRegistration* registation) {}
virtual void OnRegistrationFailed(
ServiceWorkerRegistration* registration) {}
virtual void OnRegistrationFinishedUninstalling(
@@ -68,10 +70,6 @@ class CONTENT_EXPORT ServiceWorkerRegistration
blink::mojom::ServiceWorkerUpdateViaCache update_via_cache() const {
return update_via_cache_;
}
- void set_update_via_cache(
- blink::mojom::ServiceWorkerUpdateViaCache update_via_cache) {
- update_via_cache_ = update_via_cache;
- }
bool is_deleted() const { return is_deleted_; }
void set_is_deleted(bool deleted) { is_deleted_ = deleted; }
@@ -137,6 +135,11 @@ class CONTENT_EXPORT ServiceWorkerRegistration
// listeners via OnVersionAttributesChanged.
void UnsetVersion(ServiceWorkerVersion* version);
+ // Sets the updateViaCache attribute, and notifies listeners via
+ // OnUpdateViaCacheChanged.
+ void SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache);
+
// Triggers the [[Activate]] algorithm when the currently active version is
// ready to become redundant (see IsReadyToActivate()). The algorithm is
// triggered immediately if it's already ready.
diff --git a/chromium/content/browser/service_worker/service_worker_registration_object_host.cc b/chromium/content/browser/service_worker/service_worker_registration_object_host.cc
index 11837fba49e..38ea97ec4ac 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_object_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_object_host.cc
@@ -14,6 +14,22 @@
namespace content {
+namespace {
+
+// Returns an object info to send over Mojo. The info must be sent immediately.
+// See ServiceWorkerHandle::CreateCompleteObjectInfoToSend() for details.
+blink::mojom::ServiceWorkerObjectInfoPtr CreateCompleteObjectInfoToSend(
+ ServiceWorkerProviderHost* provider_host,
+ ServiceWorkerVersion* version) {
+ base::WeakPtr<ServiceWorkerHandle> service_worker_handle =
+ provider_host->GetOrCreateServiceWorkerHandle(version);
+ if (!service_worker_handle)
+ return nullptr;
+ return service_worker_handle->CreateCompleteObjectInfoToSend();
+}
+
+} // anonymous namespace
+
ServiceWorkerRegistrationObjectHost::ServiceWorkerRegistrationObjectHost(
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerProviderHost* provider_host,
@@ -42,15 +58,14 @@ ServiceWorkerRegistrationObjectHost::CreateObjectInfo() {
registration_->pattern(), registration_->update_via_cache());
info->registration_id = registration_->id();
bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
- if (!remote_registration_)
- info->request = mojo::MakeRequest(&remote_registration_);
-
- info->installing = provider_host_->GetOrCreateServiceWorkerHandle(
- registration_->installing_version());
- info->waiting = provider_host_->GetOrCreateServiceWorkerHandle(
- registration_->waiting_version());
- info->active = provider_host_->GetOrCreateServiceWorkerHandle(
- registration_->active_version());
+ info->request = mojo::MakeRequest(&remote_registration_);
+
+ info->installing = CreateCompleteObjectInfoToSend(
+ provider_host_, registration_->installing_version());
+ info->waiting = CreateCompleteObjectInfoToSend(
+ provider_host_, registration_->waiting_version());
+ info->active = CreateCompleteObjectInfoToSend(
+ provider_host_, registration_->active_version());
return info;
}
@@ -64,6 +79,11 @@ void ServiceWorkerRegistrationObjectHost::OnVersionAttributesChanged(
registration->active_version());
}
+void ServiceWorkerRegistrationObjectHost::OnUpdateViaCacheChanged(
+ ServiceWorkerRegistration* registration) {
+ remote_registration_->SetUpdateViaCache(registration->update_via_cache());
+}
+
void ServiceWorkerRegistrationObjectHost::OnRegistrationFailed(
ServiceWorkerRegistration* registration) {
DCHECK_EQ(registration->id(), registration_->id());
@@ -276,12 +296,12 @@ void ServiceWorkerRegistrationObjectHost::SetVersionAttributes(
blink::mojom::ServiceWorkerObjectInfoPtr active;
if (changed_mask.installing_changed()) {
installing =
- provider_host_->GetOrCreateServiceWorkerHandle(installing_version);
+ CreateCompleteObjectInfoToSend(provider_host_, installing_version);
}
if (changed_mask.waiting_changed())
- waiting = provider_host_->GetOrCreateServiceWorkerHandle(waiting_version);
+ waiting = CreateCompleteObjectInfoToSend(provider_host_, waiting_version);
if (changed_mask.active_changed())
- active = provider_host_->GetOrCreateServiceWorkerHandle(active_version);
+ active = CreateCompleteObjectInfoToSend(provider_host_, active_version);
DCHECK(remote_registration_);
remote_registration_->SetVersionAttributes(
changed_mask.changed(), std::move(installing), std::move(waiting),
diff --git a/chromium/content/browser/service_worker/service_worker_registration_object_host.h b/chromium/content/browser/service_worker/service_worker_registration_object_host.h
index 9b978c6761c..6af91e91ccd 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_object_host.h
+++ b/chromium/content/browser/service_worker/service_worker_registration_object_host.h
@@ -51,6 +51,8 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
ServiceWorkerRegistration* registration,
ChangedVersionAttributesMask changed_mask,
const ServiceWorkerRegistrationInfo& info) override;
+ void OnUpdateViaCacheChanged(
+ ServiceWorkerRegistration* registration) override;
void OnRegistrationFailed(ServiceWorkerRegistration* registration) override;
void OnUpdateFound(ServiceWorkerRegistration* registration) override;
@@ -110,6 +112,8 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
// |this|.
ServiceWorkerProviderHost* provider_host_;
base::WeakPtr<ServiceWorkerContextCore> context_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+
mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerRegistrationObjectHost>
bindings_;
// Mojo connection to the content::WebServiceWorkerRegistrationImpl in the
@@ -118,8 +122,6 @@ class CONTENT_EXPORT ServiceWorkerRegistrationObjectHost
blink::mojom::ServiceWorkerRegistrationObjectAssociatedPtr
remote_registration_;
- scoped_refptr<ServiceWorkerRegistration> registration_;
-
base::WeakPtrFactory<ServiceWorkerRegistrationObjectHost> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationObjectHost);
diff --git a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
index c3c86f49727..2a7e84d67f4 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -23,7 +23,6 @@
#include "content/browser/service_worker/service_worker_registration_object_host.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
#include "mojo/edk/embedder/embedder.h"
@@ -78,6 +77,9 @@ class MockServiceWorkerRegistrationObject
int set_version_attributes_called_count() const {
return set_version_attributes_called_count_;
};
+ int set_update_via_cache_called_count() const {
+ return set_update_via_cache_called_count_;
+ }
int changed_mask() const { return changed_mask_; }
const blink::mojom::ServiceWorkerObjectInfoPtr& installing() const {
return installing_;
@@ -88,6 +90,9 @@ class MockServiceWorkerRegistrationObject
const blink::mojom::ServiceWorkerObjectInfoPtr& active() const {
return active_;
}
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache() const {
+ return update_via_cache_;
+ }
private:
// Implements blink::mojom::ServiceWorkerRegistrationObject.
@@ -102,14 +107,22 @@ class MockServiceWorkerRegistrationObject
waiting_ = std::move(waiting);
active_ = std::move(active);
}
+ void SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache) override {
+ set_update_via_cache_called_count_++;
+ update_via_cache_ = update_via_cache;
+ }
void UpdateFound() override { update_found_called_count_++; }
int update_found_called_count_ = 0;
int set_version_attributes_called_count_ = 0;
+ int set_update_via_cache_called_count_ = 0;
int changed_mask_ = 0;
blink::mojom::ServiceWorkerObjectInfoPtr installing_;
blink::mojom::ServiceWorkerObjectInfoPtr waiting_;
blink::mojom::ServiceWorkerObjectInfoPtr active_;
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_ =
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports;
mojo::AssociatedBinding<blink::mojom::ServiceWorkerRegistrationObject>
binding_;
@@ -258,8 +271,7 @@ TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
options, kRegistrationId, context()->AsWeakPtr());
auto dispatcher_host = base::MakeRefCounted<ServiceWorkerDispatcherHost>(
- helper_->mock_render_process_id(),
- helper_->browser_context()->GetResourceContext());
+ helper_->mock_render_process_id());
// Prepare a ServiceWorkerProviderHost.
ServiceWorkerRemoteProviderEndpoint remote_endpoint;
std::unique_ptr<ServiceWorkerProviderHost> provider_host =
@@ -448,7 +460,7 @@ TEST_F(ServiceWorkerActivationTest, NoInflightRequest) {
// Remove the controllee. Since there is an in-flight request,
// activation should not yet happen.
- version_1->RemoveControllee(controllee());
+ version_1->RemoveControllee(controllee()->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_1.get(), reg->active_version());
@@ -473,7 +485,7 @@ TEST_F(ServiceWorkerActivationTest, NoControllee) {
EXPECT_EQ(version_1.get(), reg->active_version());
// Remove the controllee. Activation should happen.
- version_1->RemoveControllee(controllee());
+ version_1->RemoveControllee(controllee()->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_2.get(), reg->active_version());
}
@@ -603,7 +615,7 @@ TEST_F(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
// Remove the controllee. Since there is still an in-flight request,
// activation should not happen. But the lame duck timer should start.
EXPECT_FALSE(IsLameDuckTimerRunning());
- version_1->RemoveControllee(controllee());
+ version_1->RemoveControllee(controllee()->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(version_1.get(), reg->active_version());
EXPECT_TRUE(IsLameDuckTimerRunning());
@@ -618,7 +630,7 @@ TEST_F(ServiceWorkerActivationTest, LameDuckTime_NoControllee) {
EXPECT_TRUE(IsLameDuckTimerRunning());
// Remove the controllee.
- version_1->RemoveControllee(controllee());
+ version_1->RemoveControllee(controllee()->client_uuid());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsLameDuckTimerRunning());
@@ -884,10 +896,11 @@ TEST_F(ServiceWorkerRegistrationObjectHostTest, Unregister_Success) {
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
GetRegistrationFromRemote(remote_endpoint.host_ptr()->get(), kScope);
registration_host_ptr.Bind(std::move(info->host_ptr_info));
- // Ignore the messages to the registration object, otherwise the callbacks
- // issued from |registration_host_ptr| may wait for receiving the messages to
- // |info->request|.
+ // Ignore the messages to the registration object and corresponding service
+ // worker objects, otherwise the callbacks issued from |registration_host_ptr|
+ // may wait for receiving the messages to them.
info->request = nullptr;
+ info->waiting->request = nullptr;
EXPECT_EQ(SERVICE_WORKER_OK,
FindRegistrationInStorage(registration_id, kScope));
@@ -1043,6 +1056,58 @@ TEST_F(ServiceWorkerRegistrationObjectHostTest, SetVersionAttributes) {
}
}
+TEST_F(ServiceWorkerRegistrationObjectHostTest, SetUpdateViaCache) {
+ const GURL kScope("https://www.example.com/");
+ const GURL kScriptUrl("https://www.example.com/sw.js");
+ int64_t registration_id = SetUpRegistration(kScope, kScriptUrl);
+ const int64_t kProviderId = 99; // Dummy value
+ ServiceWorkerRemoteProviderEndpoint remote_endpoint =
+ PrepareProviderHost(kProviderId, kScope);
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
+ GetRegistrationFromRemote(remote_endpoint.host_ptr()->get(), kScope);
+ EXPECT_EQ(registration_id, info->registration_id);
+ EXPECT_TRUE(info->request.is_pending());
+ auto mock_registration_object =
+ std::make_unique<MockServiceWorkerRegistrationObject>(
+ std::move(info->request));
+
+ ServiceWorkerRegistration* registration =
+ context()->GetLiveRegistration(registration_id);
+ ASSERT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
+ registration->update_via_cache());
+ ASSERT_EQ(0, mock_registration_object->set_update_via_cache_called_count());
+ ASSERT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
+ mock_registration_object->update_via_cache());
+
+ registration->SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, mock_registration_object->set_update_via_cache_called_count());
+ EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
+ mock_registration_object->update_via_cache());
+
+ registration->SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache::kAll);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, mock_registration_object->set_update_via_cache_called_count());
+ EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kAll,
+ mock_registration_object->update_via_cache());
+
+ registration->SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache::kNone);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2, mock_registration_object->set_update_via_cache_called_count());
+ EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kNone,
+ mock_registration_object->update_via_cache());
+
+ registration->SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache::kImports);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(3, mock_registration_object->set_update_via_cache_called_count());
+ EXPECT_EQ(blink::mojom::ServiceWorkerUpdateViaCache::kImports,
+ mock_registration_object->update_via_cache());
+}
+
TEST_F(ServiceWorkerRegistrationObjectHostTest, UpdateFound) {
const GURL kScope("https://www.example.com/");
const GURL kScriptUrl("https://www.example.com/sw.js");
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.cc b/chromium/content/browser/service_worker/service_worker_request_handler.cc
index 2ca37e938e9..379a90df55e 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -71,7 +71,6 @@ bool SchemeMaySupportRedirectingToHTTPS(const GURL& url) {
// static
int ServiceWorkerRequestHandler::user_data_key_;
-// PlzNavigate:
// static
void ServiceWorkerRequestHandler::InitializeForNavigation(
net::URLRequest* request,
@@ -108,16 +107,17 @@ void ServiceWorkerRequestHandler::InitializeForNavigation(
return;
}
- if (!navigation_handle_core->context_wrapper() ||
- !navigation_handle_core->context_wrapper()->context()) {
+ if (!navigation_handle_core->context_wrapper())
+ return;
+ ServiceWorkerContextCore* context =
+ navigation_handle_core->context_wrapper()->context();
+ if (!context)
return;
- }
// Initialize the SWProviderHost.
- std::unique_ptr<ServiceWorkerProviderHost> provider_host =
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
- navigation_handle_core->context_wrapper()->context()->AsWeakPtr(),
- is_parent_frame_secure, web_contents_getter);
+ context->AsWeakPtr(), is_parent_frame_secure, web_contents_getter);
std::unique_ptr<ServiceWorkerRequestHandler> handler(
provider_host->CreateRequestHandler(
@@ -130,12 +130,8 @@ void ServiceWorkerRequestHandler::InitializeForNavigation(
if (handler)
request->SetUserData(&user_data_key_, std::move(handler));
- // Transfer ownership to the ServiceWorkerNavigationHandleCore.
- // In the case of a successful navigation, the SWProviderHost will be
- // transferred to its "final" destination in the OnProviderCreated handler. If
- // the navigation fails, it will be destroyed along with the
- // ServiceWorkerNavigationHandleCore.
- navigation_handle_core->DidPreCreateProviderHost(std::move(provider_host));
+ navigation_handle_core->DidPreCreateProviderHost(
+ provider_host->provider_id());
}
// S13nServiceWorker:
@@ -163,13 +159,15 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
return nullptr;
}
- if (!navigation_handle_core->context_wrapper() ||
- !navigation_handle_core->context_wrapper()->context()) {
+ if (!navigation_handle_core->context_wrapper())
+ return nullptr;
+ ServiceWorkerContextCore* context =
+ navigation_handle_core->context_wrapper()->context();
+ if (!context)
return nullptr;
- }
// Initialize the SWProviderHost.
- std::unique_ptr<ServiceWorkerProviderHost> provider_host =
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host =
ServiceWorkerProviderHost::PreCreateNavigationHost(
navigation_handle_core->context_wrapper()->context()->AsWeakPtr(),
is_parent_frame_secure, web_contents_getter);
@@ -183,12 +181,8 @@ ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
request_context_type, frame_type, blob_storage_context->AsWeakPtr(),
body, skip_service_worker));
- // Transfer ownership to the ServiceWorkerNavigationHandleCore.
- // In the case of a successful navigation, the SWProviderHost will be
- // transferred to its "final" destination in the OnProviderCreated handler. If
- // the navigation fails, it will be destroyed along with the
- // ServiceWorkerNavigationHandleCore.
- navigation_handle_core->DidPreCreateProviderHost(std::move(provider_host));
+ navigation_handle_core->DidPreCreateProviderHost(
+ provider_host->provider_id());
return base::WrapUnique<NavigationLoaderInterceptor>(handler.release());
}
@@ -238,6 +232,14 @@ void ServiceWorkerRequestHandler::InitializeHandler(
RequestContextType request_context_type,
network::mojom::RequestContextFrameType frame_type,
scoped_refptr<network::ResourceRequestBody> body) {
+ // S13nServiceWorker enabled, NetworkService disabled:
+ // for subresource requests, subresource loader should be used, but when that
+ // request handler falls back to network, InitializeHandler() is called.
+ // Since we already determined to fall back to network, don't create another
+ // handler.
+ if (ServiceWorkerUtils::IsServicificationEnabled())
+ return;
+
// Create the handler even for insecure HTTP since it's used in the
// case of redirect to HTTPS.
if (!request->url().SchemeIsHTTPOrHTTPS() &&
@@ -304,28 +306,6 @@ void ServiceWorkerRequestHandler::MaybeCreateLoader(
std::move(callback).Run({});
}
-void ServiceWorkerRequestHandler::PrepareForCrossSiteTransfer(
- int old_process_id) {
- CHECK(!IsBrowserSideNavigationEnabled());
-}
-
-void ServiceWorkerRequestHandler::CompleteCrossSiteTransfer(
- int new_process_id, int new_provider_id) {
- CHECK(!IsBrowserSideNavigationEnabled());
-}
-
-void ServiceWorkerRequestHandler::MaybeCompleteCrossSiteTransferInOldProcess(
- int old_process_id) {
- CHECK(!IsBrowserSideNavigationEnabled());
-}
-
-bool ServiceWorkerRequestHandler::SanityCheckIsSameContext(
- ServiceWorkerContextWrapper* wrapper) {
- if (!wrapper)
- return !context_;
- return context_.get() == wrapper->context();
-}
-
ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
}
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.h b/chromium/content/browser/service_worker/service_worker_request_handler.h
index da73b702058..1dc6fb71f4e 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -143,18 +143,6 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
ResourceContext* resource_context,
LoaderCallback callback) override;
- // These are obsolete, needed for non-PlzNavigate.
- // TODO(falken): Remove these completely.
- void PrepareForCrossSiteTransfer(int old_process_id);
- void CompleteCrossSiteTransfer(int new_process_id,
- int new_provider_id);
- void MaybeCompleteCrossSiteTransferInOldProcess(
- int old_process_id);
-
- // Useful for detecting storage partition mismatches in the context of cross
- // site transfer navigations.
- bool SanityCheckIsSameContext(ServiceWorkerContextWrapper* wrapper);
-
protected:
ServiceWorkerRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
diff --git a/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc b/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc
index a61fc1f14fe..344db0e12f9 100644
--- a/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory.cc
@@ -10,21 +10,22 @@
#include "content/browser/service_worker/service_worker_new_script_loader.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
ServiceWorkerScriptLoaderFactory::ServiceWorkerScriptLoaderFactory(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter)
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
: context_(context),
provider_host_(provider_host),
- loader_factory_getter_(loader_factory_getter) {
+ loader_factory_(std::move(loader_factory)) {
DCHECK(provider_host_->IsProviderForServiceWorker());
+ DCHECK(loader_factory_);
}
ServiceWorkerScriptLoaderFactory::~ServiceWorkerScriptLoaderFactory() = default;
@@ -38,13 +39,12 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
- DCHECK(loader_factory_getter_);
if (!ShouldHandleScriptRequest(resource_request)) {
- // If the request should not be handled, just fallback to the network.
- // This needs a relaying as we use different associated message pipes.
+ // If the request should not be handled, just do a passthrough load. This
+ // needs a relaying as we use different associated message pipes.
// TODO(kinuko): Record the reason like what we do with netlog in
// ServiceWorkerContextRequestHandler.
- loader_factory_getter_->GetNetworkFactory()->CreateLoaderAndStart(
+ loader_factory_->CreateLoaderAndStart(
std::move(request), routing_id, request_id, options, resource_request,
std::move(client), traffic_annotation);
return;
@@ -70,11 +70,11 @@ void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
return;
}
- // The common case: load the script from network and install it.
+ // The common case: load the script and install it.
mojo::MakeStrongBinding(
std::make_unique<ServiceWorkerNewScriptLoader>(
routing_id, request_id, options, resource_request, std::move(client),
- provider_host_->running_hosted_version(), loader_factory_getter_,
+ provider_host_->running_hosted_version(), loader_factory_,
traffic_annotation),
std::move(request));
}
diff --git a/chromium/content/browser/service_worker/service_worker_script_loader_factory.h b/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
index 8463f047bbe..995bb61f499 100644
--- a/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
+++ b/chromium/content/browser/service_worker/service_worker_script_loader_factory.h
@@ -8,30 +8,38 @@
#include "base/macros.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
+
namespace content {
class ServiceWorkerContextCore;
class ServiceWorkerProviderHost;
-class URLLoaderFactoryGetter;
// S13nServiceWorker:
-// Created per one running service worker for loading its scripts (only during
-// installation, eventually). This is kept alive while
-// ServiceWorkerNetworkProvider in the renderer process is alive.
+// Created per one running service worker for loading its scripts. This is kept
+// alive while ServiceWorkerNetworkProvider in the renderer process is alive.
//
// This factory handles requests for the scripts of a new (installing)
// service worker. For installed workers, service worker script streaming
-// (ServiceWorkerInstalledScriptsSender) is used instead.
+// (ServiceWorkerInstalledScriptsSender) is typically used instead. However,
+// this factory can still be used when an installed worker imports a
+// non-installed script (https://crbug.com/719052).
//
// This factory creates either a ServiceWorkerNewScriptLoader or a
// ServiceWorkerInstalledScriptLoader to load a script.
class ServiceWorkerScriptLoaderFactory
: public network::mojom::URLLoaderFactory {
public:
+ // |loader_factory| is used to load scripts. Typically
+ // a new script will be loaded from the NetworkService. However,
+ // |loader_factory| may internally contain non-NetworkService
+ // factories used for non-http(s) URLs, e.g., a chrome-extension:// URL.
ServiceWorkerScriptLoaderFactory(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter);
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
~ServiceWorkerScriptLoaderFactory() override;
// network::mojom::URLLoaderFactory:
@@ -51,7 +59,7 @@ class ServiceWorkerScriptLoaderFactory
base::WeakPtr<ServiceWorkerContextCore> context_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerScriptLoaderFactory);
};
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index 08f439d6e4c..81676aaacaf 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -11,7 +11,6 @@
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "base/task_scheduler/post_task.h"
@@ -121,24 +120,25 @@ ServiceWorkerStorage::~ServiceWorkerStorage() {
// static
std::unique_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
- const base::FilePath& path,
+ const base::FilePath& user_data_directory,
const base::WeakPtr<ServiceWorkerContextCore>& context,
scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
storage::SpecialStoragePolicy* special_storage_policy) {
- return base::WrapUnique(
- new ServiceWorkerStorage(path, context, std::move(database_task_runner),
- quota_manager_proxy, special_storage_policy));
+ return base::WrapUnique(new ServiceWorkerStorage(
+ user_data_directory, context, std::move(database_task_runner),
+ quota_manager_proxy, special_storage_policy));
}
// static
std::unique_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
const base::WeakPtr<ServiceWorkerContextCore>& context,
ServiceWorkerStorage* old_storage) {
- return base::WrapUnique(new ServiceWorkerStorage(
- old_storage->path_, context, old_storage->database_task_runner_,
- old_storage->quota_manager_proxy_.get(),
- old_storage->special_storage_policy_.get()));
+ return base::WrapUnique(
+ new ServiceWorkerStorage(old_storage->user_data_directory_, context,
+ old_storage->database_task_runner_,
+ old_storage->quota_manager_proxy_.get(),
+ old_storage->special_storage_policy_.get()));
}
void ServiceWorkerStorage::FindRegistrationForDocument(
@@ -1052,7 +1052,7 @@ void ServiceWorkerStorage::PurgeResources(const ResourceList& resources) {
}
ServiceWorkerStorage::ServiceWorkerStorage(
- const base::FilePath& path,
+ const base::FilePath& user_data_directory,
base::WeakPtr<ServiceWorkerContextCore> context,
scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
@@ -1062,7 +1062,7 @@ ServiceWorkerStorage::ServiceWorkerStorage(
next_resource_id_(kInvalidServiceWorkerResourceId),
state_(UNINITIALIZED),
expecting_done_with_disk_on_disable_(false),
- path_(path),
+ user_data_directory_(user_data_directory),
context_(context),
database_task_runner_(std::move(database_task_runner)),
quota_manager_proxy_(quota_manager_proxy),
@@ -1075,16 +1075,18 @@ ServiceWorkerStorage::ServiceWorkerStorage(
}
base::FilePath ServiceWorkerStorage::GetDatabasePath() {
- if (path_.empty())
+ if (user_data_directory_.empty())
return base::FilePath();
- return path_.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
+ return user_data_directory_
+ .Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
.Append(kDatabaseName);
}
base::FilePath ServiceWorkerStorage::GetDiskCachePath() {
- if (path_.empty())
+ if (user_data_directory_.empty())
return base::FilePath();
- return path_.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
+ return user_data_directory_
+ .Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
.Append(kDiskCacheName);
}
@@ -1389,6 +1391,8 @@ void ServiceWorkerStorage::DidStoreRegistration(
deleted_version.resources_total_size_bytes);
}
+ context_->NotifyRegistrationStored(new_version.registration_id,
+ new_version.scope);
std::move(callback).Run(SERVICE_WORKER_OK);
if (!context_->GetLiveVersion(deleted_version.version_id))
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
index 3daafe9cb55..88a1c291efb 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -97,7 +97,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
~ServiceWorkerStorage() override;
static std::unique_ptr<ServiceWorkerStorage> Create(
- const base::FilePath& path,
+ const base::FilePath& user_data_directory,
const base::WeakPtr<ServiceWorkerContextCore>& context,
scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
@@ -356,7 +356,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
ServiceWorkerDatabase::Status status)>;
ServiceWorkerStorage(
- const base::FilePath& path,
+ const base::FilePath& user_data_directory,
base::WeakPtr<ServiceWorkerContextCore> context,
scoped_refptr<base::SequencedTaskRunner> database_task_runner,
storage::QuotaManagerProxy* quota_manager_proxy,
@@ -583,7 +583,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
// ... so it's easier to keep track of the case when it will happen.
bool expecting_done_with_disk_on_disable_;
- base::FilePath path_;
+ base::FilePath user_data_directory_;
// The context should be valid while the storage is alive.
base::WeakPtr<ServiceWorkerContextCore> context_;
diff --git a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
index 8ab6e03831c..1c69543d47c 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -26,7 +26,7 @@
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/origin_trial_policy.h"
+#include "content/public/common/origin_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "ipc/ipc_message.h"
@@ -39,6 +39,7 @@
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
@@ -1449,7 +1450,7 @@ TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
// Removing the controllee should cause the resources to be deleted.
- registration_->active_version()->RemoveControllee(host.get());
+ registration_->active_version()->RemoveControllee(host.get()->client_uuid());
registration_->active_version()->Doom();
base::RunLoop().RunUntilIdle();
verify_ids.clear();
@@ -1666,7 +1667,7 @@ TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
// Removing the controllee should cause the old version's resources to be
// deleted.
- registration_->active_version()->RemoveControllee(host.get());
+ registration_->active_version()->RemoveControllee(host.get()->client_uuid());
registration_->active_version()->Doom();
base::RunLoop().RunUntilIdle();
verify_ids.clear();
@@ -1798,10 +1799,12 @@ class ServiceWorkerStorageOriginTrialsDiskTest
: public ServiceWorkerStorageTest {
public:
ServiceWorkerStorageOriginTrialsDiskTest() {
- SetContentClient(&test_content_client_);
+ blink::TrialTokenValidator::SetOriginTrialPolicyGetter(base::BindRepeating(
+ [](blink::OriginTrialPolicy* policy) { return policy; },
+ base::Unretained(&origin_trial_policy_)));
}
~ServiceWorkerStorageOriginTrialsDiskTest() override {
- SetContentClient(nullptr);
+ blink::TrialTokenValidator::ResetOriginTrialPolicyGetter();
}
void SetUp() override {
ASSERT_TRUE(InitUserDataDirectory());
@@ -1809,24 +1812,18 @@ class ServiceWorkerStorageOriginTrialsDiskTest
}
private:
- class TestOriginTrialPolicy : public OriginTrialPolicy {
+ class TestOriginTrialPolicy : public blink::OriginTrialPolicy {
public:
+ bool IsOriginTrialsSupported() const override { return true; }
base::StringPiece GetPublicKey() const override {
return base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
arraysize(kTestPublicKey));
}
- };
- class TestContentClient : public ContentClient {
- public:
- // ContentRendererClient methods
- OriginTrialPolicy* GetOriginTrialPolicy() override {
- return &origin_trial_policy_;
+ bool IsOriginSecure(const GURL& url) const override {
+ return content::IsOriginSecure(url);
}
-
- private:
- TestOriginTrialPolicy origin_trial_policy_;
};
- TestContentClient test_content_client_;
+ TestOriginTrialPolicy origin_trial_policy_;
};
TEST_F(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
diff --git a/chromium/content/browser/service_worker/service_worker_test_utils.cc b/chromium/content/browser/service_worker/service_worker_test_utils.cc
index 67e56a81a2b..d01073ccaeb 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.cc
@@ -101,11 +101,6 @@ void ServiceWorkerRemoteProviderEndpoint::BindWithProviderInfo(
mojom::ServiceWorkerProviderInfoForStartWorkerPtr info) {
client_request_ = std::move(info->client_request);
host_ptr_.Bind(std::move(info->host_ptr_info));
- registration_object_info_ = std::move(info->registration);
- // To enable the caller end point to make calls safely with no need to pass
- // |registration_object_info_->request| through a message pipe endpoint.
- mojo::AssociateWithDisconnectedPipe(
- registration_object_info_->request.PassHandle());
}
std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
@@ -136,8 +131,10 @@ CreateProviderHostForServiceWorkerContext(
is_parent_frame_secure);
std::unique_ptr<ServiceWorkerProviderHost> host =
ServiceWorkerProviderHost::PreCreateForController(std::move(context));
+ host->SetDocumentUrl(hosted_version->script_url());
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info =
- host->CompleteStartWorkerPreparation(process_id, hosted_version);
+ host->CompleteStartWorkerPreparation(
+ process_id, hosted_version, nullptr /* non_network_loader_factory */);
output_endpoint->BindWithProviderInfo(std::move(provider_info));
return host;
}
diff --git a/chromium/content/browser/service_worker/service_worker_test_utils.h b/chromium/content/browser/service_worker/service_worker_test_utils.h
index 363387afbde..859b06d488f 100644
--- a/chromium/content/browser/service_worker/service_worker_test_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_test_utils.h
@@ -29,7 +29,6 @@ namespace content {
class ServiceWorkerContextCore;
class ServiceWorkerDispatcherHost;
class ServiceWorkerProviderHost;
-class ServiceWorkerRegistration;
class ServiceWorkerStorage;
class ServiceWorkerVersion;
struct ServiceWorkerProviderHostInfo;
@@ -87,9 +86,6 @@ class ServiceWorkerRemoteProviderEndpoint {
// This is the other end of ServiceWorkerContainerAssociatedPtr owned by
// content::ServiceWorkerProviderHost.
mojom::ServiceWorkerContainerAssociatedRequest client_request_;
- // This is to keep alive the corresponding content::ServiceWorkerRegistration.
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
- registration_object_info_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRemoteProviderEndpoint);
};
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index 20b8ee246d9..094bfb5e5f4 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -468,9 +468,8 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
EmbeddedWorkerTestHelper::OnStartWorker(
embedded_worker_id_, service_worker_version_id_, scope_, script_url_,
pause_after_download_, std::move(start_worker_request_),
- std::move(controller_request_), std::move(service_worker_host_),
- std::move(start_worker_instance_host_), std::move(provider_info_),
- std::move(installed_scripts_info_));
+ std::move(controller_request_), std::move(start_worker_instance_host_),
+ std::move(provider_info_), std::move(installed_scripts_info_));
}
void Respond() {
@@ -500,7 +499,6 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -512,7 +510,6 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
pause_after_download_ = pause_after_download;
start_worker_request_ = std::move(dispatcher_request);
controller_request_ = std::move(controller_request);
- service_worker_host_ = std::move(service_worker_host);
start_worker_instance_host_ = std::move(instance_host);
provider_info_ = std::move(provider_info);
installed_scripts_info_ = std::move(installed_scripts_info);
@@ -538,7 +535,6 @@ class DelayHelper : public EmbeddedWorkerTestHelper {
bool pause_after_download_;
mojom::ServiceWorkerEventDispatcherRequest start_worker_request_;
mojom::ControllerServiceWorkerRequest controller_request_;
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host_;
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo
start_worker_instance_host_;
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info_;
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 025c6403566..bfe78b055f3 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -31,7 +31,6 @@
#include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_type_converters.h"
-#include "content/common/origin_trials/trial_policy_impl.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
@@ -166,17 +165,20 @@ void OnEventDispatcherConnectionError(
}
}
+// In S13nServiceWorker, |loader_factory| is the factory to use loading new
+// scripts from network (or other sources, e.g., for chrome-extension:// URLs).
mojom::ServiceWorkerProviderInfoForStartWorkerPtr
CompleteProviderHostPreparation(
ServiceWorkerVersion* version,
std::unique_ptr<ServiceWorkerProviderHost> provider_host,
base::WeakPtr<ServiceWorkerContextCore> context,
- int process_id) {
+ int process_id,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
// Caller should ensure |context| is alive when completing StartWorker
// preparation.
DCHECK(context);
- auto info =
- provider_host->CompleteStartWorkerPreparation(process_id, version);
+ auto info = provider_host->CompleteStartWorkerPreparation(
+ process_id, version, std::move(loader_factory));
context->AddProviderHost(std::move(provider_host));
return info;
}
@@ -329,14 +331,14 @@ ServiceWorkerVersion::ServiceWorkerVersion(
tick_clock_(base::DefaultTickClock::GetInstance()),
clock_(base::DefaultClock::GetInstance()),
ping_controller_(new PingController(this)),
- validator_(TrialPolicyImpl::CreateValidatorForPolicy()),
+ validator_(std::make_unique<blink::TrialTokenValidator>()),
weak_factory_(this) {
DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId, version_id);
DCHECK(context_);
DCHECK(registration);
DCHECK(script_url_.is_valid());
embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(this);
- embedded_worker_->AddListener(this);
+ embedded_worker_->AddObserver(this);
context_->AddLiveVersion(this);
}
@@ -359,7 +361,7 @@ ServiceWorkerVersion::~ServiceWorkerVersion() {
running_status() == EmbeddedWorkerStatus::RUNNING) {
embedded_worker_->Stop();
}
- embedded_worker_->RemoveListener(this);
+ embedded_worker_->RemoveObserver(this);
}
void ServiceWorkerVersion::SetNavigationPreloadState(
@@ -453,9 +455,9 @@ ServiceWorkerVersionInfo ServiceWorkerVersion::GetInfo() {
const ServiceWorkerProviderHost* host = controllee.second;
info.clients.insert(std::make_pair(
host->client_uuid(),
- ServiceWorkerVersionInfo::ClientInfo(
- host->process_id(), host->route_id(), host->web_contents_getter(),
- host->provider_type())));
+ ServiceWorkerClientInfo(host->process_id(), host->route_id(),
+ host->web_contents_getter(),
+ host->provider_type())));
}
if (!main_script_http_info_)
return info;
@@ -504,15 +506,7 @@ void ServiceWorkerVersion::StartWorker(ServiceWorkerMetrics::EventType purpose,
base::BindOnce(std::move(callback), SERVICE_WORKER_ERROR_REDUNDANT));
return;
}
-
- // Check that the worker is allowed to start on the given scope. Since this
- // worker might not be used for a specific tab, pass a null callback as
- // WebContents getter.
- // resource_context() can return null in unit tests.
- if (context_->wrapper()->resource_context() &&
- !GetContentClient()->browser()->AllowServiceWorker(
- scope_, scope_, context_->wrapper()->resource_context(),
- base::Callback<WebContents*(void)>())) {
+ if (!IsStartWorkerAllowed()) {
RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
is_browser_startup_complete,
SERVICE_WORKER_ERROR_DISALLOWED);
@@ -729,6 +723,7 @@ void ServiceWorkerVersion::RunAfterStartWorker(
void ServiceWorkerVersion::AddControllee(
ServiceWorkerProviderHost* provider_host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
const std::string& uuid = provider_host->client_uuid();
CHECK(!provider_host->client_uuid().empty());
DCHECK(!base::ContainsKey(controllee_map_, uuid));
@@ -736,22 +731,28 @@ void ServiceWorkerVersion::AddControllee(
// Keep the worker alive a bit longer right after a new controllee is added.
RestartTick(&idle_time_);
ClearTick(&no_controllees_time_);
- for (auto& observer : listeners_)
- observer.OnControlleeAdded(this, provider_host);
+
+ // Notify observers asynchronously for consistency with RemoveControllee.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ServiceWorkerVersion::NotifyControlleeAdded,
+ weak_factory_.GetWeakPtr(), uuid,
+ ServiceWorkerClientInfo(
+ provider_host->process_id(), provider_host->route_id(),
+ provider_host->web_contents_getter(),
+ provider_host->provider_type())));
}
-void ServiceWorkerVersion::RemoveControllee(
- ServiceWorkerProviderHost* provider_host) {
- const std::string& uuid = provider_host->client_uuid();
- DCHECK(base::ContainsKey(controllee_map_, uuid));
- controllee_map_.erase(uuid);
- for (auto& observer : listeners_)
- observer.OnControlleeRemoved(this, provider_host);
- if (!HasControllee()) {
- RestartTick(&no_controllees_time_);
- for (auto& observer : listeners_)
- observer.OnNoControllees(this);
- }
+void ServiceWorkerVersion::RemoveControllee(const std::string& client_uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(base::ContainsKey(controllee_map_, client_uuid));
+ controllee_map_.erase(client_uuid);
+ // Notify observers asynchronously since this gets called during
+ // ServiceWorkerProviderHost's destructor, and we don't want observers to do
+ // work during that.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&ServiceWorkerVersion::NotifyControlleeRemoved,
+ weak_factory_.GetWeakPtr(), client_uuid));
}
void ServiceWorkerVersion::OnStreamResponseStarted() {
@@ -935,9 +936,6 @@ ServiceWorkerVersion::InflightRequest::~InflightRequest() {}
void ServiceWorkerVersion::OnThreadStarted() {
DCHECK_EQ(EmbeddedWorkerStatus::STARTING, running_status());
- DCHECK(provider_host_);
- provider_host_->SetReadyToSendMessagesToWorker(
- embedded_worker()->thread_id());
// Activate ping/pong now that JavaScript execution will start.
ping_controller_->Activate();
}
@@ -1517,9 +1515,19 @@ void ServiceWorkerVersion::StartWorkerInternal() {
// TODO(horo): These CHECKs are for debugging crbug.com/759938.
CHECK(event_dispatcher_.is_bound());
CHECK(params->dispatcher_request.is_pending());
-
+ event_dispatcher_.set_connection_error_handler(base::BindOnce(
+ &OnEventDispatcherConnectionError, embedded_worker_->AsWeakPtr()));
+ blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host;
binding_.Close();
- binding_.Bind(mojo::MakeRequest(&params->service_worker_host));
+ binding_.Bind(mojo::MakeRequest(&service_worker_host));
+ ServiceWorkerRegistration* registration =
+ context_->GetLiveRegistration(registration_id_);
+ DCHECK(registration);
+ provider_host->SetDocumentUrl(script_url());
+ event_dispatcher_->InitializeGlobalScope(
+ std::move(service_worker_host),
+ provider_host->CreateServiceWorkerRegistrationObjectInfo(
+ scoped_refptr<ServiceWorkerRegistration>(registration)));
// S13nServiceWorker:
if (!controller_request_.is_pending()) {
@@ -1536,8 +1544,6 @@ void ServiceWorkerVersion::StartWorkerInternal() {
std::move(provider_host), context()),
base::BindOnce(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated,
weak_factory_.GetWeakPtr()));
- event_dispatcher_.set_connection_error_handler(base::BindOnce(
- &OnEventDispatcherConnectionError, embedded_worker_->AsWeakPtr()));
}
void ServiceWorkerVersion::StartTimeoutTimer() {
@@ -1610,10 +1616,10 @@ void ServiceWorkerVersion::OnTimeoutTimer() {
// EmbeddedWorkerInstance could destroy our ServiceWorkerProviderHost
// which could in turn destroy |this|.
scoped_refptr<ServiceWorkerVersion> protect_this(this);
- embedded_worker_->RemoveListener(this);
+ embedded_worker_->RemoveObserver(this);
embedded_worker_->Detach();
embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(this);
- embedded_worker_->AddListener(this);
+ embedded_worker_->AddObserver(this);
// Call OnStoppedInternal to fail callbacks and possibly restart.
OnStoppedInternal(EmbeddedWorkerStatus::STOPPING);
@@ -1994,4 +2000,50 @@ void ServiceWorkerVersion::OnNoWorkInBrowser() {
idle_timer_fired_in_renderer_ = false;
}
+bool ServiceWorkerVersion::IsStartWorkerAllowed() const {
+ // Check that the worker is allowed on this origin. It's possible a
+ // worker was previously allowed and installed, but later the embedder's
+ // policy or binary changed to disallow this origin.
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
+ {script_url_})) {
+ return false;
+ }
+
+ // Check that the worker is allowed on the given scope. It's possible a worker
+ // was previously allowed and installed, but later content settings changed to
+ // disallow this scope. Since this worker might not be used for a specific
+ // tab, pass a null callback as WebContents getter.
+ // resource_context() can return null in unit tests.
+ if ((context_->wrapper()->resource_context() &&
+ !GetContentClient()->browser()->AllowServiceWorker(
+ scope_, scope_, context_->wrapper()->resource_context(),
+ base::Callback<WebContents*(void)>()))) {
+ return false;
+ }
+
+ return true;
+}
+
+void ServiceWorkerVersion::NotifyControlleeAdded(
+ const std::string& uuid,
+ const ServiceWorkerClientInfo& info) {
+ for (auto& observer : listeners_)
+ observer.OnControlleeAdded(this, uuid, info);
+}
+
+void ServiceWorkerVersion::NotifyControlleeRemoved(const std::string& uuid) {
+ // The observers can destroy |this|, so protect it first.
+ // TODO(falken): Make OnNoControllees an explicit call to our registration
+ // instead of an observer callback, if it has dangerous side-effects like
+ // destroying the caller.
+ auto protect = base::WrapRefCounted(this);
+ for (auto& observer : listeners_)
+ observer.OnControlleeRemoved(this, uuid);
+ if (!HasControllee()) {
+ RestartTick(&no_controllees_time_);
+ for (auto& observer : listeners_)
+ observer.OnNoControllees(this);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index c0aba6af7c5..ce8fec41aaa 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -29,6 +29,7 @@
#include "base/timer/timer.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_status.h"
+#include "content/browser/service_worker/service_worker_client_info.h"
#include "content/browser/service_worker/service_worker_client_utils.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
#include "content/browser/service_worker/service_worker_metrics.h"
@@ -159,11 +160,15 @@ class CONTENT_EXPORT ServiceWorkerVersion
const base::string16& message,
int line_number,
const GURL& source_url) {}
+ // OnControlleeAdded/Removed are called asynchronously. It is possible the
+ // provider host identified by |client_uuid| was already destroyed when they
+ // are called.
virtual void OnControlleeAdded(ServiceWorkerVersion* version,
- ServiceWorkerProviderHost* provider_host) {}
- virtual void OnControlleeRemoved(ServiceWorkerVersion* version,
- ServiceWorkerProviderHost* provider_host) {
+ const std::string& client_uuid,
+ const ServiceWorkerClientInfo& client_info) {
}
+ virtual void OnControlleeRemoved(ServiceWorkerVersion* version,
+ const std::string& client_uuid) {}
virtual void OnNoControllees(ServiceWorkerVersion* version) {}
virtual void OnNoWork(ServiceWorkerVersion* version) {}
virtual void OnCachedMetadataUpdated(ServiceWorkerVersion* version,
@@ -323,6 +328,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
// This must be called when the worker is running.
mojom::ServiceWorkerEventDispatcher* event_dispatcher() {
+ DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
+ running_status() == EmbeddedWorkerStatus::RUNNING);
// Temporarily CHECK for debugging https://crbug.com/817981.
CHECK(event_dispatcher_.is_bound());
CHECK(event_dispatcher_.get());
@@ -344,9 +351,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
return controller_ptr_.get();
}
- // Adds and removes |provider_host| as a controllee of this ServiceWorker.
+ // Adds and removes the specified host as a controllee of this service worker.
void AddControllee(ServiceWorkerProviderHost* provider_host);
- void RemoveControllee(ServiceWorkerProviderHost* provider_host);
+ void RemoveControllee(const std::string& client_uuid);
// Returns if it has controllee.
bool HasControllee() const { return !controllee_map_.empty(); }
@@ -722,6 +729,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
// has been fired or the worker has been stopped.
void OnNoWorkInBrowser();
+ bool IsStartWorkerAllowed() const;
+
+ void NotifyControlleeAdded(const std::string& uuid,
+ const ServiceWorkerClientInfo& info);
+ void NotifyControlleeRemoved(const std::string& uuid);
+
const int64_t version_id_;
const int64_t registration_id_;
const GURL script_url_;
diff --git a/chromium/content/browser/service_worker/service_worker_version_unittest.cc b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
index 8023d7da5fa..dd8493e736a 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -45,45 +45,13 @@ class MessageReceiver : public EmbeddedWorkerTestHelper {
void SimulateSetCachedMetadata(int embedded_worker_id,
const GURL& url,
const std::vector<uint8_t>& data) {
- ASSERT_TRUE(service_worker_host_map_[embedded_worker_id]);
- service_worker_host_map_[embedded_worker_id]->SetCachedMetadata(url, data);
+ GetServiceWorkerHost(embedded_worker_id)->SetCachedMetadata(url, data);
}
void SimulateClearCachedMetadata(int embedded_worker_id, const GURL& url) {
- ASSERT_TRUE(service_worker_host_map_[embedded_worker_id]);
- service_worker_host_map_[embedded_worker_id]->ClearCachedMetadata(url);
+ GetServiceWorkerHost(embedded_worker_id)->ClearCachedMetadata(url);
}
- protected:
- void OnStartWorker(
- int embedded_worker_id,
- int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- bool pause_after_download,
- mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
- mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
- mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
- mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
- blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
- override {
- service_worker_host_map_[embedded_worker_id].Bind(
- std::move(service_worker_host));
- EmbeddedWorkerTestHelper::OnStartWorker(
- embedded_worker_id, service_worker_version_id, scope, script_url,
- pause_after_download, std::move(dispatcher_request),
- std::move(controller_request), nullptr /* service_worker_host */,
- std::move(instance_host), std::move(provider_info),
- std::move(installed_scripts_info));
- }
-
- private:
- std::map<
- int /* embedded_worker_id */,
- blink::mojom::ServiceWorkerHostAssociatedPtr /* service_worker_host */>
- service_worker_host_map_;
-
DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
};
@@ -177,7 +145,8 @@ class ServiceWorkerVersionTest : public testing::Test {
blink::mojom::ServiceWorkerRegistrationOptions options;
options.scope = pattern_;
registration_ = new ServiceWorkerRegistration(
- options, 1L, helper_->context()->AsWeakPtr());
+ options, helper_->context()->storage()->NewRegistrationId(),
+ helper_->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
registration_.get(),
GURL("https://www.example.com/test/service_worker.js"),
@@ -266,7 +235,6 @@ class MessageReceiverDisallowStart : public MessageReceiver {
bool pause_after_download,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info)
@@ -287,16 +255,13 @@ class MessageReceiverDisallowStart : public MessageReceiver {
mock_instance_clients()->size());
// Remove the connection by peer
mock_instance_clients()->at(current_mock_instance_index_).reset();
- std::move(dispatcher_request);
- std::move(controller_request);
break;
case StartMode::SUCCEED:
MessageReceiver::OnStartWorker(
embedded_worker_id, service_worker_version_id, scope, script_url,
pause_after_download, std::move(dispatcher_request),
- std::move(controller_request), std::move(service_worker_host),
- std::move(instance_host), std::move(provider_info),
- std::move(installed_scripts_info));
+ std::move(controller_request), std::move(instance_host),
+ std::move(provider_info), std::move(installed_scripts_info));
break;
}
current_mock_instance_index_++;
@@ -1266,6 +1231,26 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
base::Time::Now()));
}
+// Test starting a service worker from a disallowed origin.
+TEST_F(ServiceWorkerVersionTest, BadOrigin) {
+ const GURL scope("bad-origin://www.example.com/test/");
+ blink::mojom::ServiceWorkerRegistrationOptions options;
+ options.scope = scope;
+ auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
+ options, helper_->context()->storage()->NewRegistrationId(),
+ helper_->context()->AsWeakPtr());
+ auto version = base::MakeRefCounted<ServiceWorkerVersion>(
+ registration_.get(),
+ GURL("bad-origin://www.example.com/test/service_worker.js"),
+ helper_->context()->storage()->NewVersionId(),
+ helper_->context()->AsWeakPtr());
+ ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
+ version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_ERROR_DISALLOWED, status);
+}
+
TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
ServiceWorkerContextCore* context = helper_->context();
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
index 53b45366cfe..1a3a3f2ad9a 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -62,11 +62,6 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
private:
friend class ServiceWorkerContextRequestHandlerTest;
- // TODO(https://crbug.com/675540): Remove the following
- // FRIEND_TEST_ALL_PREFIXES directive when the update_via_cache flag is
- // shipped to stable.
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
- UpdateBefore24HoursWithoutUpdateViaCache);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
ServiceWorkerDataRequestAnnotation);
diff --git a/chromium/content/browser/shape_detection/shape_detection_browsertest.cc b/chromium/content/browser/shape_detection/shape_detection_browsertest.cc
index 8eb87b5f7e3..8b02c0faff0 100644
--- a/chromium/content/browser/shape_detection/shape_detection_browsertest.cc
+++ b/chromium/content/browser/shape_detection/shape_detection_browsertest.cc
@@ -49,9 +49,9 @@ class ShapeDetectionBrowserTest
public ::testing::WithParamInterface<struct TestParameters> {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
- // Flags to enable ShapeDetection and DOMRect API.
+ // Flag to enable ShapeDetection API.
CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kEnableBlinkFeatures, "ShapeDetection, GeometryInterfaces");
+ switches::kEnableBlinkFeatures, "ShapeDetection");
}
protected:
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.cc b/chromium/content/browser/shared_worker/mock_shared_worker.cc
new file mode 100644
index 00000000000..32ce0577fdc
--- /dev/null
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.cc
@@ -0,0 +1,197 @@
+// 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/shared_worker/mock_shared_worker.h"
+
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+template <typename T>
+bool CheckEquality(const T& expected, const T& actual) {
+ EXPECT_EQ(expected, actual);
+ return expected == actual;
+}
+
+} // namespace
+
+MockSharedWorker::MockSharedWorker(mojom::SharedWorkerRequest request)
+ : binding_(this, std::move(request)) {}
+
+MockSharedWorker::~MockSharedWorker() = default;
+
+bool MockSharedWorker::CheckReceivedConnect(int* connection_request_id,
+ blink::MessagePortChannel* port) {
+ if (connect_received_.empty())
+ return false;
+ if (connection_request_id)
+ *connection_request_id = connect_received_.front().first;
+ if (port)
+ *port = connect_received_.front().second;
+ connect_received_.pop();
+ return true;
+}
+
+bool MockSharedWorker::CheckNotReceivedConnect() {
+ return connect_received_.empty();
+}
+
+bool MockSharedWorker::CheckReceivedTerminate() {
+ if (!terminate_received_)
+ return false;
+ terminate_received_ = false;
+ return true;
+}
+
+void MockSharedWorker::Connect(int connection_request_id,
+ mojo::ScopedMessagePipeHandle port) {
+ connect_received_.emplace(connection_request_id,
+ blink::MessagePortChannel(std::move(port)));
+}
+
+void MockSharedWorker::Terminate() {
+ // Allow duplicate events.
+ terminate_received_ = true;
+}
+
+void MockSharedWorker::BindDevToolsAgent(
+ blink::mojom::DevToolsAgentAssociatedRequest request) {
+ NOTREACHED();
+}
+
+MockSharedWorkerFactory::MockSharedWorkerFactory(
+ mojom::SharedWorkerFactoryRequest request)
+ : binding_(this, std::move(request)) {}
+
+MockSharedWorkerFactory::~MockSharedWorkerFactory() = default;
+
+bool MockSharedWorkerFactory::CheckReceivedCreateSharedWorker(
+ const GURL& expected_url,
+ const std::string& expected_name,
+ blink::WebContentSecurityPolicyType expected_content_security_policy_type,
+ mojom::SharedWorkerHostPtr* host,
+ mojom::SharedWorkerRequest* request) {
+ std::unique_ptr<CreateParams> create_params = std::move(create_params_);
+ if (!create_params)
+ return false;
+ if (!CheckEquality(expected_url, create_params->info->url))
+ return false;
+ if (!CheckEquality(expected_name, create_params->info->name))
+ return false;
+ if (!CheckEquality(expected_content_security_policy_type,
+ create_params->info->content_security_policy_type))
+ return false;
+ if (!create_params->interface_provider)
+ return false;
+ *host = std::move(create_params->host);
+ *request = std::move(create_params->request);
+ return true;
+}
+
+void MockSharedWorkerFactory::CreateSharedWorker(
+ mojom::SharedWorkerInfoPtr info,
+ bool pause_on_start,
+ const base::UnguessableToken& devtools_worker_token,
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings,
+ mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
+ service_worker_provider_info,
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ script_loader_factory_ptr_info,
+ mojom::SharedWorkerHostPtr host,
+ mojom::SharedWorkerRequest request,
+ service_manager::mojom::InterfaceProviderPtr interface_provider) {
+ DCHECK(!create_params_);
+ create_params_ = std::make_unique<CreateParams>();
+ create_params_->info = std::move(info);
+ create_params_->pause_on_start = pause_on_start;
+ create_params_->content_settings = std::move(content_settings);
+ create_params_->host = std::move(host);
+ create_params_->request = std::move(request);
+ create_params_->interface_provider = std::move(interface_provider);
+}
+
+MockSharedWorkerFactory::CreateParams::CreateParams() = default;
+
+MockSharedWorkerFactory::CreateParams::~CreateParams() = default;
+
+MockSharedWorkerClient::MockSharedWorkerClient() : binding_(this) {}
+
+MockSharedWorkerClient::~MockSharedWorkerClient() = default;
+
+void MockSharedWorkerClient::Bind(mojom::SharedWorkerClientRequest request) {
+ binding_.Bind(std::move(request));
+}
+
+void MockSharedWorkerClient::Close() {
+ binding_.Close();
+}
+
+bool MockSharedWorkerClient::CheckReceivedOnCreated() {
+ if (!on_created_received_)
+ return false;
+ on_created_received_ = false;
+ return true;
+}
+
+bool MockSharedWorkerClient::CheckReceivedOnConnected(
+ std::set<blink::mojom::WebFeature> expected_used_features) {
+ if (!on_connected_received_)
+ return false;
+ on_connected_received_ = false;
+ if (!CheckEquality(expected_used_features, on_connected_features_))
+ return false;
+ return true;
+}
+
+bool MockSharedWorkerClient::CheckReceivedOnFeatureUsed(
+ blink::mojom::WebFeature expected_feature) {
+ if (!on_feature_used_received_)
+ return false;
+ on_feature_used_received_ = false;
+ if (!CheckEquality(expected_feature, on_feature_used_feature_))
+ return false;
+ return true;
+}
+
+bool MockSharedWorkerClient::CheckNotReceivedOnFeatureUsed() {
+ return !on_feature_used_received_;
+}
+
+bool MockSharedWorkerClient::CheckReceivedOnScriptLoadFailed() {
+ if (!on_script_load_failed_)
+ return false;
+ on_script_load_failed_ = false;
+ return true;
+}
+
+void MockSharedWorkerClient::OnCreated(
+ blink::mojom::SharedWorkerCreationContextType creation_context_type) {
+ DCHECK(!on_created_received_);
+ on_created_received_ = true;
+}
+
+void MockSharedWorkerClient::OnConnected(
+ const std::vector<blink::mojom::WebFeature>& features_used) {
+ DCHECK(!on_connected_received_);
+ on_connected_received_ = true;
+ for (auto feature : features_used)
+ on_connected_features_.insert(feature);
+}
+
+void MockSharedWorkerClient::OnScriptLoadFailed() {
+ DCHECK(!on_script_load_failed_);
+ on_script_load_failed_ = true;
+}
+
+void MockSharedWorkerClient::OnFeatureUsed(blink::mojom::WebFeature feature) {
+ DCHECK(!on_feature_used_received_);
+ on_feature_used_received_ = true;
+ on_feature_used_feature_ = feature;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/shared_worker/mock_shared_worker.h b/chromium/content/browser/shared_worker/mock_shared_worker.h
new file mode 100644
index 00000000000..791fdb17060
--- /dev/null
+++ b/chromium/content/browser/shared_worker/mock_shared_worker.h
@@ -0,0 +1,132 @@
+// 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_SHARED_WORKER_MOCK_SHARED_WORKER_H_
+#define CONTENT_BROWSER_SHARED_WORKER_MOCK_SHARED_WORKER_H_
+
+#include <memory>
+#include <queue>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "content/browser/shared_worker/shared_worker_host.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
+#include "content/common/shared_worker/shared_worker_factory.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/common/message_port/message_port_channel.h"
+
+class GURL;
+
+namespace content {
+
+class MockSharedWorker : public mojom::SharedWorker {
+ public:
+ explicit MockSharedWorker(mojom::SharedWorkerRequest request);
+ ~MockSharedWorker() override;
+
+ bool CheckReceivedConnect(int* connection_request_id,
+ blink::MessagePortChannel* port);
+ bool CheckNotReceivedConnect();
+ bool CheckReceivedTerminate();
+
+ private:
+ // mojom::SharedWorker methods:
+ void Connect(int connection_request_id,
+ mojo::ScopedMessagePipeHandle port) override;
+ void Terminate() override;
+ void BindDevToolsAgent(
+ blink::mojom::DevToolsAgentAssociatedRequest request) override;
+
+ mojo::Binding<mojom::SharedWorker> binding_;
+ std::queue<std::pair<int, blink::MessagePortChannel>> connect_received_;
+ bool terminate_received_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSharedWorker);
+};
+
+class MockSharedWorkerFactory : public mojom::SharedWorkerFactory {
+ public:
+ explicit MockSharedWorkerFactory(mojom::SharedWorkerFactoryRequest request);
+ ~MockSharedWorkerFactory() override;
+
+ bool CheckReceivedCreateSharedWorker(
+ const GURL& expected_url,
+ const std::string& expected_name,
+ blink::WebContentSecurityPolicyType expected_content_security_policy_type,
+ mojom::SharedWorkerHostPtr* host,
+ mojom::SharedWorkerRequest* request);
+
+ private:
+ // mojom::SharedWorkerFactory methods:
+ void CreateSharedWorker(
+ mojom::SharedWorkerInfoPtr info,
+ bool pause_on_start,
+ const base::UnguessableToken& devtools_worker_token,
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings,
+ mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
+ service_worker_provider_info,
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ script_loader_factory_ptr_info,
+ mojom::SharedWorkerHostPtr host,
+ mojom::SharedWorkerRequest request,
+ service_manager::mojom::InterfaceProviderPtr interface_provider) override;
+
+ struct CreateParams {
+ CreateParams();
+ ~CreateParams();
+ mojom::SharedWorkerInfoPtr info;
+ bool pause_on_start;
+ blink::mojom::WorkerContentSettingsProxyPtr content_settings;
+ mojom::SharedWorkerHostPtr host;
+ mojom::SharedWorkerRequest request;
+ service_manager::mojom::InterfaceProviderPtr interface_provider;
+ };
+
+ mojo::Binding<mojom::SharedWorkerFactory> binding_;
+ std::unique_ptr<CreateParams> create_params_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSharedWorkerFactory);
+};
+
+class MockSharedWorkerClient : public mojom::SharedWorkerClient {
+ public:
+ MockSharedWorkerClient();
+ ~MockSharedWorkerClient() override;
+
+ void Bind(mojom::SharedWorkerClientRequest request);
+ void Close();
+ bool CheckReceivedOnCreated();
+ bool CheckReceivedOnConnected(
+ std::set<blink::mojom::WebFeature> expected_used_features);
+ bool CheckReceivedOnFeatureUsed(blink::mojom::WebFeature expected_feature);
+ bool CheckNotReceivedOnFeatureUsed();
+ bool CheckReceivedOnScriptLoadFailed();
+
+ private:
+ // mojom::SharedWorkerClient methods:
+ void OnCreated(blink::mojom::SharedWorkerCreationContextType
+ creation_context_type) override;
+ void OnConnected(
+ const std::vector<blink::mojom::WebFeature>& features_used) override;
+ void OnScriptLoadFailed() override;
+ void OnFeatureUsed(blink::mojom::WebFeature feature) override;
+
+ mojo::Binding<mojom::SharedWorkerClient> binding_;
+ bool on_created_received_ = false;
+ bool on_connected_received_ = false;
+ std::set<blink::mojom::WebFeature> on_connected_features_;
+ bool on_feature_used_received_ = false;
+ blink::mojom::WebFeature on_feature_used_feature_ =
+ blink::mojom::WebFeature();
+ bool on_script_load_failed_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSharedWorkerClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SHARED_WORKER_MOCK_SHARED_WORKER_H_
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index 623c6617174..107d46564b9 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -54,6 +54,31 @@ bool AllowIndexedDBOnIOThread(const GURL& url,
} // namespace
+// RAII helper class for talking to SharedWorkerDevToolsManager.
+class SharedWorkerHost::ScopedDevToolsHandle {
+ public:
+ ScopedDevToolsHandle(SharedWorkerHost* owner,
+ bool* out_pause_on_start,
+ base::UnguessableToken* out_devtools_worker_token)
+ : owner_(owner) {
+ SharedWorkerDevToolsManager::GetInstance()->WorkerCreated(
+ owner, out_pause_on_start, out_devtools_worker_token);
+ }
+
+ ~ScopedDevToolsHandle() {
+ SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(owner_);
+ }
+
+ void WorkerReadyForInspection() {
+ SharedWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(
+ owner_);
+ }
+
+ private:
+ SharedWorkerHost* owner_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedDevToolsHandle);
+};
+
SharedWorkerHost::SharedWorkerHost(
SharedWorkerServiceImpl* service,
std::unique_ptr<SharedWorkerInstance> instance,
@@ -67,13 +92,29 @@ SharedWorkerHost::SharedWorkerHost(
interface_provider_binding_(this),
weak_factory_(this) {
DCHECK(instance_);
+ // Set up the worker interface request. This is needed first in either
+ // AddClient() or Start(). AddClient() can sometimes be called before Start()
+ // when two clients call new SharedWorker() at around the same time.
+ worker_request_ = mojo::MakeRequest(&worker_);
}
SharedWorkerHost::~SharedWorkerHost() {
UMA_HISTOGRAM_LONG_TIMES("SharedWorker.TimeToDeleted",
base::TimeTicks::Now() - creation_time_);
- if (!closed_ && !termination_message_sent_)
- SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(this);
+ switch (phase_) {
+ case Phase::kInitial:
+ // Tell clients that this worker failed to start. This is only needed in
+ // kInitial. Once in kStarted, the worker in the renderer would alert this
+ // host if script loading failed.
+ for (const ClientInfo& info : clients_)
+ info.client->OnScriptLoadFailed();
+ break;
+ case Phase::kStarted:
+ case Phase::kClosed:
+ case Phase::kTerminationSent:
+ case Phase::kTerminationSentAndClosed:
+ break;
+ }
}
void SharedWorkerHost::Start(
@@ -82,6 +123,7 @@ void SharedWorkerHost::Start(
service_worker_provider_info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ AdvanceTo(Phase::kStarted);
mojom::SharedWorkerInfoPtr info(mojom::SharedWorkerInfo::New(
instance_->url(), instance_->name(), instance_->content_security_policy(),
@@ -91,7 +133,7 @@ void SharedWorkerHost::Start(
// Register with DevTools.
bool pause_on_start;
base::UnguessableToken devtools_worker_token;
- SharedWorkerDevToolsManager::GetInstance()->WorkerCreated(
+ devtools_handle_ = std::make_unique<ScopedDevToolsHandle>(
this, &pause_on_start, &devtools_worker_token);
// Set up content settings interface.
@@ -115,7 +157,7 @@ void SharedWorkerHost::Start(
std::move(info), pause_on_start, devtools_worker_token,
std::move(content_settings), std::move(service_worker_provider_info),
std::move(script_loader_factory), std::move(host),
- mojo::MakeRequest(&worker_), std::move(interface_provider));
+ std::move(worker_request_), std::move(interface_provider));
// Monitor the lifetime of the worker.
worker_.set_connection_error_handler(base::BindOnce(
@@ -148,16 +190,57 @@ void SharedWorkerHost::AllowIndexedDB(const GURL& url,
}
void SharedWorkerHost::TerminateWorker() {
- // This can be called twice in tests while cleaning up all the workers.
- if (termination_message_sent_)
- return;
- termination_message_sent_ = true;
- if (!closed_)
- SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(this);
+ switch (phase_) {
+ case Phase::kInitial:
+ // The host is being asked to terminate the worker before it started.
+ // Tell clients that this worker failed to start.
+ for (const ClientInfo& info : clients_)
+ info.client->OnScriptLoadFailed();
+ // Tell the caller it terminated, so the caller doesn't wait forever.
+ AdvanceTo(Phase::kTerminationSentAndClosed);
+ OnWorkerConnectionLost();
+ // |this| is destroyed here.
+ return;
+ case Phase::kStarted:
+ AdvanceTo(Phase::kTerminationSent);
+ break;
+ case Phase::kClosed:
+ AdvanceTo(Phase::kTerminationSentAndClosed);
+ break;
+ case Phase::kTerminationSent:
+ case Phase::kTerminationSentAndClosed:
+ // Termination was already sent. TerminateWorker can be called twice in
+ // tests while cleaning up all the workers.
+ return;
+ }
+
+ devtools_handle_.reset();
worker_->Terminate();
// Now, we wait to observe OnWorkerConnectionLost.
}
+void SharedWorkerHost::AdvanceTo(Phase phase) {
+ switch (phase_) {
+ case Phase::kInitial:
+ DCHECK(phase == Phase::kStarted ||
+ phase == Phase::kTerminationSentAndClosed);
+ break;
+ case Phase::kStarted:
+ DCHECK(phase == Phase::kClosed || phase == Phase::kTerminationSent);
+ break;
+ case Phase::kClosed:
+ DCHECK(phase == Phase::kTerminationSentAndClosed);
+ break;
+ case Phase::kTerminationSent:
+ DCHECK(phase == Phase::kTerminationSentAndClosed);
+ break;
+ case Phase::kTerminationSentAndClosed:
+ NOTREACHED();
+ break;
+ }
+ phase_ = phase;
+}
+
SharedWorkerHost::ClientInfo::ClientInfo(mojom::SharedWorkerClientPtr client,
int connection_request_id,
int process_id,
@@ -182,17 +265,33 @@ void SharedWorkerHost::OnConnected(int connection_request_id) {
}
void SharedWorkerHost::OnContextClosed() {
- // Set the closed flag - this will stop any further messages from
- // being sent to the worker (messages can still be sent from the worker,
- // for exception reporting, etc).
- closed_ = true;
- if (!termination_message_sent_)
- SharedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(this);
+ devtools_handle_.reset();
+
+ // Mark as closed - this will stop any further messages from being sent to the
+ // worker (messages can still be sent from the worker, for exception
+ // reporting, etc).
+ switch (phase_) {
+ case Phase::kInitial:
+ // Not possible: there is no Mojo connection on which OnContextClosed can
+ // be called.
+ NOTREACHED();
+ break;
+ case Phase::kStarted:
+ AdvanceTo(Phase::kClosed);
+ break;
+ case Phase::kTerminationSent:
+ AdvanceTo(Phase::kTerminationSentAndClosed);
+ break;
+ case Phase::kClosed:
+ case Phase::kTerminationSentAndClosed:
+ // Already closed, just ignore.
+ break;
+ }
}
void SharedWorkerHost::OnReadyForInspection() {
- if (!closed_ && !termination_message_sent_)
- SharedWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(this);
+ if (devtools_handle_)
+ devtools_handle_->WorkerReadyForInspection();
}
void SharedWorkerHost::OnScriptLoaded() {
@@ -225,7 +324,21 @@ SharedWorkerHost::GetRenderFrameIDsForWorker() {
}
bool SharedWorkerHost::IsAvailable() const {
- return !termination_message_sent_ && !closed_;
+ switch (phase_) {
+ case Phase::kInitial:
+ case Phase::kStarted:
+ return true;
+ case Phase::kClosed:
+ case Phase::kTerminationSent:
+ case Phase::kTerminationSentAndClosed:
+ return false;
+ }
+ NOTREACHED();
+ return false;
+}
+
+base::WeakPtr<SharedWorkerHost> SharedWorkerHost::AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
}
void SharedWorkerHost::AddClient(mojom::SharedWorkerClientPtr client,
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.h b/chromium/content/browser/shared_worker/shared_worker_host.h
index dd95fc35655..e6f1f73f997 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.h
+++ b/chromium/content/browser/shared_worker/shared_worker_host.h
@@ -41,8 +41,9 @@ class SharedWorkerServiceImpl;
// the browser <-> worker communication channel. This is owned by
// SharedWorkerServiceImpl and destructed when a worker context or worker's
// message filter is closed.
-class SharedWorkerHost : public mojom::SharedWorkerHost,
- public service_manager::mojom::InterfaceProvider {
+class CONTENT_EXPORT SharedWorkerHost
+ : public mojom::SharedWorkerHost,
+ public service_manager::mojom::InterfaceProvider {
public:
SharedWorkerHost(SharedWorkerServiceImpl* service,
std::unique_ptr<SharedWorkerInstance> instance,
@@ -87,7 +88,21 @@ class SharedWorkerHost : public mojom::SharedWorkerHost,
int process_id() const { return process_id_; }
bool IsAvailable() const;
+ base::WeakPtr<SharedWorkerHost> AsWeakPtr();
+
private:
+ friend class SharedWorkerHostTest;
+
+ enum class Phase {
+ kInitial,
+ kStarted,
+ kClosed,
+ kTerminationSent,
+ kTerminationSentAndClosed
+ };
+
+ class ScopedDevToolsHandle;
+
struct ClientInfo {
ClientInfo(mojom::SharedWorkerClientPtr client,
int connection_request_id,
@@ -122,19 +137,22 @@ class SharedWorkerHost : public mojom::SharedWorkerHost,
void GetInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
+ void AdvanceTo(Phase phase);
+
mojo::Binding<mojom::SharedWorkerHost> binding_;
+
// |service_| owns |this|.
SharedWorkerServiceImpl* service_;
std::unique_ptr<SharedWorkerInstance> instance_;
ClientList clients_;
+ mojom::SharedWorkerRequest worker_request_;
mojom::SharedWorkerPtr worker_;
const int process_id_;
int next_connection_request_id_;
- bool termination_message_sent_ = false;
- bool closed_ = false;
const base::TimeTicks creation_time_;
+ std::unique_ptr<ScopedDevToolsHandle> devtools_handle_;
// This is the set of features that this worker has used.
std::set<blink::mojom::WebFeature> used_features_;
@@ -150,6 +168,8 @@ class SharedWorkerHost : public mojom::SharedWorkerHost,
mojo::Binding<service_manager::mojom::InterfaceProvider>
interface_provider_binding_;
+ Phase phase_ = Phase::kInitial;
+
base::WeakPtrFactory<SharedWorkerHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerHost);
diff --git a/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
new file mode 100644
index 00000000000..a00d44ffb4b
--- /dev/null
+++ b/chromium/content/browser/shared_worker/shared_worker_host_unittest.cc
@@ -0,0 +1,263 @@
+// 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/shared_worker/shared_worker_host.h"
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "content/browser/shared_worker/mock_shared_worker.h"
+#include "content/browser/shared_worker/shared_worker_connector_impl.h"
+#include "content/browser/shared_worker/shared_worker_instance.h"
+#include "content/browser/shared_worker/shared_worker_service_impl.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "url/origin.h"
+
+using blink::MessagePortChannel;
+
+namespace content {
+
+class SharedWorkerHostTest : public testing::Test {
+ public:
+ SharedWorkerHostTest() : service_(nullptr) {}
+
+ base::WeakPtr<SharedWorkerHost> CreateHost() {
+ GURL url("http://www.example.com/w.js");
+ std::string name("name");
+ url::Origin origin = url::Origin::Create(url);
+ std::string content_security_policy;
+ blink::WebContentSecurityPolicyType content_security_policy_type = blink::
+ WebContentSecurityPolicyType::kWebContentSecurityPolicyTypeReport;
+ blink::mojom::IPAddressSpace creation_address_space =
+ blink::mojom::IPAddressSpace::kPublic;
+ blink::mojom::SharedWorkerCreationContextType creation_context_type =
+ blink::mojom::SharedWorkerCreationContextType::kSecure;
+
+ auto instance = std::make_unique<SharedWorkerInstance>(
+ url, name, origin, content_security_policy,
+ content_security_policy_type, creation_address_space,
+ creation_context_type);
+ auto host = std::make_unique<SharedWorkerHost>(
+ &service_, std::move(instance), 11 /* dummy process_id */);
+ auto weak_host = host->AsWeakPtr();
+ service_.worker_hosts_.insert(std::move(host));
+ return weak_host;
+ }
+
+ void StartWorker(SharedWorkerHost* host,
+ mojom::SharedWorkerFactoryPtr factory) {
+ host->Start(std::move(factory), nullptr /* service_worker_provider_info */,
+ {} /* script_loader_factory_info */);
+ }
+
+ MessagePortChannel AddClient(SharedWorkerHost* host,
+ mojom::SharedWorkerClientPtr client) {
+ mojo::MessagePipe message_pipe;
+ MessagePortChannel local_port(std::move(message_pipe.handle0));
+ MessagePortChannel remote_port(std::move(message_pipe.handle1));
+ host->AddClient(std::move(client), host->process_id(),
+ 22 /* dummy frame_id */, std::move(remote_port));
+ return local_port;
+ }
+
+ protected:
+ TestBrowserThreadBundle test_browser_thread_bundle_;
+ SharedWorkerServiceImpl service_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedWorkerHostTest);
+};
+
+TEST_F(SharedWorkerHostTest, Normal) {
+ base::WeakPtr<SharedWorkerHost> host = CreateHost();
+
+ // Start the worker.
+ mojom::SharedWorkerFactoryPtr factory;
+ MockSharedWorkerFactory factory_impl(mojo::MakeRequest(&factory));
+ StartWorker(host.get(), std::move(factory));
+
+ // Add the initiating client.
+ MockSharedWorkerClient client;
+ mojom::SharedWorkerClientPtr client_ptr;
+ client.Bind(mojo::MakeRequest(&client_ptr));
+ MessagePortChannel local_port = AddClient(host.get(), std::move(client_ptr));
+ base::RunLoop().RunUntilIdle();
+
+ // The factory should have gotten the CreateSharedWorker message.
+ mojom::SharedWorkerHostPtr worker_host;
+ mojom::SharedWorkerRequest worker_request;
+ EXPECT_TRUE(factory_impl.CheckReceivedCreateSharedWorker(
+ host->instance()->url(), host->instance()->name(),
+ host->instance()->content_security_policy_type(), &worker_host,
+ &worker_request));
+ {
+ MockSharedWorker worker(std::move(worker_request));
+ base::RunLoop().RunUntilIdle();
+
+ // The worker and client should have gotten initial messages.
+ int connection_request_id;
+ MessagePortChannel port;
+ EXPECT_TRUE(worker.CheckReceivedConnect(&connection_request_id, &port));
+ EXPECT_TRUE(client.CheckReceivedOnCreated());
+ // Simulate events the shared worker would send.
+ worker_host->OnReadyForInspection();
+ worker_host->OnScriptLoaded();
+ worker_host->OnConnected(connection_request_id);
+ base::RunLoop().RunUntilIdle();
+
+ // The client should be connected.
+ EXPECT_TRUE(
+ client.CheckReceivedOnConnected({} /* expected_used_features */));
+
+ // Close the client. The host should detect that there are no clients left
+ // and ask the worker to terminate.
+ client.Close();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(worker.CheckReceivedTerminate());
+
+ // Simulate the worker terminating by breaking the Mojo connection when
+ // |worker| goes out of scope.
+ }
+ base::RunLoop().RunUntilIdle();
+
+ // The host should have self-destructed.
+ EXPECT_FALSE(host);
+}
+
+TEST_F(SharedWorkerHostTest, DestructBeforeStarting) {
+ base::WeakPtr<SharedWorkerHost> host = CreateHost();
+
+ // Add a client.
+ MockSharedWorkerClient client;
+ mojom::SharedWorkerClientPtr client_ptr;
+ client.Bind(mojo::MakeRequest(&client_ptr));
+ MessagePortChannel local_port = AddClient(host.get(), std::move(client_ptr));
+ base::RunLoop().RunUntilIdle();
+
+ // Destroy the host before starting.
+ service_.DestroyHost(host.get());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(host);
+
+ // The client should be told startup failed.
+ EXPECT_TRUE(client.CheckReceivedOnScriptLoadFailed());
+}
+
+TEST_F(SharedWorkerHostTest, TerminateBeforeStarting) {
+ base::WeakPtr<SharedWorkerHost> host = CreateHost();
+
+ // Add a client.
+ MockSharedWorkerClient client;
+ mojom::SharedWorkerClientPtr client_ptr;
+ client.Bind(mojo::MakeRequest(&client_ptr));
+ MessagePortChannel local_port = AddClient(host.get(), std::move(client_ptr));
+ base::RunLoop().RunUntilIdle();
+
+ // Request to terminate the worker before starting.
+ host->TerminateWorker();
+ base::RunLoop().RunUntilIdle();
+
+ // The client should be told startup failed.
+ EXPECT_TRUE(client.CheckReceivedOnScriptLoadFailed());
+
+ // The host should be destroyed.
+ EXPECT_FALSE(host);
+}
+
+TEST_F(SharedWorkerHostTest, TerminateAfterStarting) {
+ base::WeakPtr<SharedWorkerHost> host = CreateHost();
+
+ // Create the factory.
+ mojom::SharedWorkerFactoryPtr factory;
+ MockSharedWorkerFactory factory_impl(mojo::MakeRequest(&factory));
+
+ // Start the worker.
+ host->Start(std::move(factory), nullptr /* service_worker_provider_info */,
+ {} /* script_loader_factory_info */);
+
+ // Add a client.
+ MockSharedWorkerClient client;
+ mojom::SharedWorkerClientPtr client_ptr;
+ client.Bind(mojo::MakeRequest(&client_ptr));
+ MessagePortChannel local_port = AddClient(host.get(), std::move(client_ptr));
+ base::RunLoop().RunUntilIdle();
+
+ {
+ mojom::SharedWorkerHostPtr worker_host;
+ mojom::SharedWorkerRequest worker_request;
+ EXPECT_TRUE(factory_impl.CheckReceivedCreateSharedWorker(
+ host->instance()->url(), host->instance()->name(),
+ host->instance()->content_security_policy_type(), &worker_host,
+ &worker_request));
+ MockSharedWorker worker(std::move(worker_request));
+
+ // Terminate after starting.
+ host->TerminateWorker();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(worker.CheckReceivedTerminate());
+ // We simulate the worker terminating by breaking the Mojo connection when
+ // it goes out of scope.
+ }
+
+ // Simulate the worker in the renderer terminating.
+ base::RunLoop().RunUntilIdle();
+
+ // The client should not have been told startup failed.
+ EXPECT_FALSE(client.CheckReceivedOnScriptLoadFailed());
+ // The host should be destroyed.
+ EXPECT_FALSE(host);
+}
+
+TEST_F(SharedWorkerHostTest, OnContextClosed) {
+ base::WeakPtr<SharedWorkerHost> host = CreateHost();
+
+ // Start the worker.
+ mojom::SharedWorkerFactoryPtr factory;
+ MockSharedWorkerFactory factory_impl(mojo::MakeRequest(&factory));
+ StartWorker(host.get(), std::move(factory));
+
+ // Add a client.
+ MockSharedWorkerClient client;
+ mojom::SharedWorkerClientPtr client_ptr;
+ client.Bind(mojo::MakeRequest(&client_ptr));
+ MessagePortChannel local_port = AddClient(host.get(), std::move(client_ptr));
+ base::RunLoop().RunUntilIdle();
+
+ {
+ mojom::SharedWorkerHostPtr worker_host;
+ mojom::SharedWorkerRequest worker_request;
+ EXPECT_TRUE(factory_impl.CheckReceivedCreateSharedWorker(
+ host->instance()->url(), host->instance()->name(),
+ host->instance()->content_security_policy_type(), &worker_host,
+ &worker_request));
+ MockSharedWorker worker(std::move(worker_request));
+
+ // Simulate the worker calling OnContextClosed().
+ worker_host->OnContextClosed();
+ base::RunLoop().RunUntilIdle();
+
+ // Close the client. The host should detect that there are no clients left
+ // and terminate the worker.
+ client.Close();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(worker.CheckReceivedTerminate());
+
+ // Simulate the worker terminating by breaking the Mojo connection when
+ // |worker| goes out of scope.
+ }
+ base::RunLoop().RunUntilIdle();
+
+ // The host should have self-destructed.
+ EXPECT_FALSE(host);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader.cc b/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
index ff39e068b26..2a540fac395 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.cc
@@ -6,10 +6,10 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
-#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/resource_context.h"
#include "net/url_request/redirect_util.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
@@ -21,7 +21,7 @@ SharedWorkerScriptLoader::SharedWorkerScriptLoader(
network::mojom::URLLoaderClientPtr client,
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host,
ResourceContext* resource_context,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
: routing_id_(routing_id),
request_id_(request_id),
@@ -30,7 +30,7 @@ SharedWorkerScriptLoader::SharedWorkerScriptLoader(
client_(std::move(client)),
service_worker_provider_host_(service_worker_provider_host),
resource_context_(resource_context),
- loader_factory_getter_(std::move(loader_factory_getter)),
+ default_loader_factory_(std::move(default_loader_factory)),
traffic_annotation_(traffic_annotation),
url_loader_client_binding_(this),
weak_factory_(this) {
@@ -84,7 +84,7 @@ void SharedWorkerScriptLoader::MaybeStartLoader(
void SharedWorkerScriptLoader::LoadFromNetwork() {
network::mojom::URLLoaderClientPtr client;
url_loader_client_binding_.Bind(mojo::MakeRequest(&client));
- url_loader_factory_ = loader_factory_getter_->GetNetworkFactory();
+ url_loader_factory_ = default_loader_factory_;
url_loader_factory_->CreateLoaderAndStart(
mojo::MakeRequest(&url_loader_), routing_id_, request_id_, options_,
resource_request_, std::move(client), traffic_annotation_);
@@ -95,7 +95,11 @@ void SharedWorkerScriptLoader::LoadFromNetwork() {
// When this class gets a FollowRedirect IPC from the renderer, it restarts with
// the new URL.
-void SharedWorkerScriptLoader::FollowRedirect() {
+void SharedWorkerScriptLoader::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
+ "headers was not supported "
+ "yet. crbug.com/845683";
DCHECK(redirect_info_);
// |should_clear_upload| is unused because there is no body anyway.
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader.h b/chromium/content/browser/shared_worker/shared_worker_script_loader.h
index 7e61d8c6c69..3868aedd721 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader.h
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader.h
@@ -12,26 +12,34 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
+
namespace content {
class NavigationLoaderInterceptor;
class ResourceContext;
class ServiceWorkerProviderHost;
-class URLLoaderFactoryGetter;
// The URLLoader for loading a shared worker script. Only used for the main
// script request.
//
-// This acts much like NavigationURLLoaderNetworkService. It allows a
+// This acts much like NavigationURLLoaderImpl. It allows a
// NavigationLoaderInterceptor to intercept the request with its own loader, and
-// goes to the network loader otherwise. Once a loader is started, this class
-// acts as the URLLoaderClient for it, forwarding messages to the outer client.
-// On redirects, it starts over with the new request URL, possibly starting a
-// new loader and becoming the client of that.
+// goes to |default_loader_factory| otherwise. Once a loader is started, this
+// class acts as the URLLoaderClient for it, forwarding messages to the outer
+// client. On redirects, it starts over with the new request URL, possibly
+// starting a new loader and becoming the client of that.
//
// Lives on the IO thread.
class SharedWorkerScriptLoader : public network::mojom::URLLoader,
public network::mojom::URLLoaderClient {
public:
+ // |default_loader_factory| is used to load the script if the load is not
+ // intercepted by a feature like service worker. Typically it will load the
+ // script from the NetworkService. However, it may internally contain
+ // non-NetworkService factories used for non-http(s) URLs, e.g., a
+ // chrome-extension:// URL.
SharedWorkerScriptLoader(
int32_t routing_id,
int32_t request_id,
@@ -40,12 +48,13 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
network::mojom::URLLoaderClientPtr client,
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host,
ResourceContext* resource_context,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
~SharedWorkerScriptLoader() override;
// network::mojom::URLLoader:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
@@ -76,8 +85,7 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
SingleRequestURLLoaderFactory::RequestHandler single_request_handler);
void LoadFromNetwork();
- // TODO(falken): Add other interceptors like in
- // NavigationURLLoaderNetworkService.
+ // TODO(falken): Add other interceptors like in NavigationURLLoaderImpl.
std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor_;
const int32_t routing_id_;
@@ -87,7 +95,7 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
network::mojom::URLLoaderClientPtr client_;
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_;
ResourceContext* resource_context_;
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory_;
net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
base::Optional<net::RedirectInfo> redirect_info_;
@@ -95,6 +103,9 @@ class SharedWorkerScriptLoader : public network::mojom::URLLoader,
network::mojom::URLLoaderPtr url_loader_;
mojo::Binding<network::mojom::URLLoaderClient> url_loader_client_binding_;
+ // The factory used to request the script. This is the same as
+ // |default_loader_factory_| if a service worker or other interceptor didn't
+ // elect to handle the request.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
base::WeakPtrFactory<SharedWorkerScriptLoader> weak_factory_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
index f819351042c..08260e2484f 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.cc
@@ -10,10 +10,10 @@
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/shared_worker/shared_worker_script_loader.h"
-#include "content/browser/url_loader_factory_getter.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
namespace content {
@@ -22,10 +22,10 @@ SharedWorkerScriptLoaderFactory::SharedWorkerScriptLoaderFactory(
ServiceWorkerContextWrapper* context,
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host,
ResourceContext* resource_context,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter)
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
: service_worker_provider_host_(service_worker_provider_host),
resource_context_(resource_context),
- loader_factory_getter_(loader_factory_getter) {
+ loader_factory_(std::move(loader_factory)) {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
DCHECK_EQ(service_worker_provider_host_->provider_type(),
blink::mojom::ServiceWorkerProviderType::kForSharedWorker);
@@ -54,8 +54,8 @@ void SharedWorkerScriptLoaderFactory::CreateLoaderAndStart(
mojo::MakeStrongBinding(
std::make_unique<SharedWorkerScriptLoader>(
routing_id, request_id, options, resource_request, std::move(client),
- service_worker_provider_host_, resource_context_,
- loader_factory_getter_, traffic_annotation),
+ service_worker_provider_host_, resource_context_, loader_factory_,
+ traffic_annotation),
std::move(request));
}
diff --git a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h
index 7e0e4c5ceae..2e42cfaafa6 100644
--- a/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h
+++ b/chromium/content/browser/shared_worker/shared_worker_script_loader_factory.h
@@ -8,11 +8,14 @@
#include "base/macros.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
+
namespace content {
class ServiceWorkerContextWrapper;
class ServiceWorkerProviderHost;
-class URLLoaderFactoryGetter;
class ResourceContext;
// S13nServiceWorker:
@@ -28,11 +31,15 @@ class ResourceContext;
class SharedWorkerScriptLoaderFactory
: public network::mojom::URLLoaderFactory {
public:
+ // |loader_factory| is used to load the script if the load is not intercepted
+ // by a feature like service worker. Typically it will load the script from
+ // the NetworkService. However, it may internally contain non-NetworkService
+ // factories used for non-http(s) URLs, e.g., a chrome-extension:// URL.
SharedWorkerScriptLoaderFactory(
ServiceWorkerContextWrapper* context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
ResourceContext* resource_context,
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter);
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
~SharedWorkerScriptLoaderFactory() override;
// network::mojom::URLLoaderFactory:
@@ -49,7 +56,7 @@ class SharedWorkerScriptLoaderFactory
private:
base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_;
ResourceContext* resource_context_ = nullptr;
- scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
DISALLOW_COPY_AND_ASSIGN(SharedWorkerScriptLoaderFactory);
};
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
index 5589e34dec3..8140ae678d3 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -27,6 +27,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/common/bind_interface_helpers.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "url/origin.h"
@@ -40,24 +41,48 @@ bool IsShuttingDown(RenderProcessHost* host) {
void CreateScriptLoaderOnIO(
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
+ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_info,
scoped_refptr<ServiceWorkerContextWrapper> context,
int process_id,
base::OnceCallback<void(mojom::ServiceWorkerProviderInfoForSharedWorkerPtr,
network::mojom::URLLoaderFactoryAssociatedPtrInfo)>
callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
// Set up for service worker.
auto provider_info = mojom::ServiceWorkerProviderInfoForSharedWorker::New();
base::WeakPtr<ServiceWorkerProviderHost> host =
context->PreCreateHostForSharedWorker(process_id, &provider_info);
+ // Create the factory bundle for loading the script.
+ scoped_refptr<URLLoaderFactoryBundle> factory_bundle =
+ base::MakeRefCounted<URLLoaderFactoryBundle>(
+ std::move(factory_bundle_info));
+
+ // Add the network factory to the bundle. The factory from
+ // CloneNetworkFactory() doesn't support reconnection to the network service
+ // after a crash, but it's OK since it's used for a single shared worker
+ // startup.
+ network::mojom::URLLoaderFactoryPtr network_factory_ptr;
+ loader_factory_getter->CloneNetworkFactory(
+ mojo::MakeRequest(&network_factory_ptr));
+ factory_bundle->SetDefaultFactory(std::move(network_factory_ptr));
+
// Create the SharedWorkerScriptLoaderFactory.
network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory;
mojo::MakeStrongAssociatedBinding(
std::make_unique<SharedWorkerScriptLoaderFactory>(
context.get(), host->AsWeakPtr(), context->resource_context(),
- std::move(loader_factory_getter)),
+ std::move(factory_bundle)),
mojo::MakeRequest(&script_loader_factory));
+ // TODO(falken): Also send the factory bundle to the renderer like
+ // CommitNavigation does, to be used for subresource requests from the shared
+ // worker (SharedWorkerScriptLoaderFactory is only used for the main resource
+ // request). However, the restartable network factory should be used in this
+ // case.
+
+ // We continue in StartWorker.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(callback), std::move(provider_info),
@@ -77,6 +102,7 @@ bool SharedWorkerServiceImpl::TerminateWorker(
const GURL& url,
const std::string& name,
const url::Origin& constructor_origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (auto& host : worker_hosts_) {
if (host->IsAvailable() &&
host->instance()->Matches(url, name, constructor_origin)) {
@@ -160,29 +186,12 @@ void SharedWorkerServiceImpl::ConnectToWorker(
DestroyHost(host);
}
- // Bounce to the IO thread to setup service worker support in case the request
- // for the worker script will need to be intercepted by service workers.
- // TODO(falken): Move service worker to the UI thread.
- if (ServiceWorkerUtils::IsServicificationEnabled()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CreateScriptLoaderOnIO,
- service_worker_context_->storage_partition()
- ->url_loader_factory_getter(),
- service_worker_context_, process_id,
- base::BindOnce(&SharedWorkerServiceImpl::CreateWorker,
- weak_factory_.GetWeakPtr(),
- std::move(instance), std::move(client),
- process_id, frame_id, message_port)));
- return;
- }
-
CreateWorker(std::move(instance), std::move(client), process_id, frame_id,
- message_port, nullptr /* service_worker_provider_info */,
- {} /* script_loader_factory */);
+ message_port);
}
void SharedWorkerServiceImpl::DestroyHost(SharedWorkerHost* host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* process_host =
RenderProcessHost::FromID(host->process_id());
worker_hosts_.erase(worker_hosts_.find(host));
@@ -201,6 +210,69 @@ void SharedWorkerServiceImpl::CreateWorker(
mojom::SharedWorkerClientPtr client,
int process_id,
int frame_id,
+ const blink::MessagePortChannel& message_port) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Create the host. We need to do this even before starting the worker,
+ // because we are about to bounce to the IO thread. If another ConnectToWorker
+ // request arrives in the meantime, it finds and reuses the host instead of
+ // creating a new host and therefore new SharedWorker thread.
+ auto host =
+ std::make_unique<SharedWorkerHost>(this, std::move(instance), process_id);
+ auto weak_host = host->AsWeakPtr();
+ worker_hosts_.insert(std::move(host));
+
+ // Bounce to the IO thread to setup service worker support in case the request
+ // for the worker script will need to be intercepted by service workers.
+ if (ServiceWorkerUtils::IsServicificationEnabled()) {
+ // Set up the factory bundle for non-NetworkService URLs, e.g.,
+ // chrome-extension:// URLs.
+ ContentBrowserClient::NonNetworkURLLoaderFactoryMap factories;
+ GetContentClient()
+ ->browser()
+ ->RegisterNonNetworkSubresourceURLLoaderFactories(
+ process_id, MSG_ROUTING_NONE, &factories);
+
+ // TODO(falken): Add FileURLLoaderFactory if the requesting frame is a file
+ // resource.
+
+ auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
+ for (auto& pair : factories) {
+ const std::string& scheme = pair.first;
+ std::unique_ptr<network::mojom::URLLoaderFactory> factory =
+ std::move(pair.second);
+
+ network::mojom::URLLoaderFactoryPtr factory_ptr;
+ mojo::MakeStrongBinding(std::move(factory),
+ mojo::MakeRequest(&factory_ptr));
+ factory_bundle->factories_info().emplace(scheme,
+ factory_ptr.PassInterface());
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &CreateScriptLoaderOnIO,
+ service_worker_context_->storage_partition()
+ ->url_loader_factory_getter(),
+ std::move(factory_bundle), service_worker_context_, process_id,
+ base::BindOnce(&SharedWorkerServiceImpl::StartWorker,
+ weak_factory_.GetWeakPtr(), std::move(instance),
+ weak_host, std::move(client), process_id, frame_id,
+ message_port)));
+ return;
+ }
+
+ StartWorker(std::move(instance), weak_host, std::move(client), process_id,
+ frame_id, message_port, nullptr, {});
+}
+
+void SharedWorkerServiceImpl::StartWorker(
+ std::unique_ptr<SharedWorkerInstance> instance,
+ base::WeakPtr<SharedWorkerHost> host,
+ mojom::SharedWorkerClientPtr client,
+ int process_id,
+ int frame_id,
const blink::MessagePortChannel& message_port,
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
service_worker_provider_info,
@@ -208,17 +280,23 @@ void SharedWorkerServiceImpl::CreateWorker(
script_loader_factory_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // The host may already be gone if something forcibly terminated the worker
+ // before it could start (e.g., in tests or a UI action). Just fail.
+ if (!host)
+ return;
+
RenderProcessHost* process_host = RenderProcessHost::FromID(process_id);
- // If the requesting process is shutting down, then just drop this request on
- // the floor. The client is not going to be around much longer anyways.
- if (IsShuttingDown(process_host))
+ // If the target process is shutting down, then just drop this request and
+ // tell the host to destruct. This also means clients that were still waiting
+ // for the shared worker to start will fail.
+ if (!process_host || IsShuttingDown(process_host)) {
+ host->TerminateWorker();
return;
+ }
// Keep the renderer process alive that will be hosting the shared worker.
process_host->IncrementKeepAliveRefCount(
RenderProcessHost::KeepAliveClientType::kSharedWorker);
- auto host =
- std::make_unique<SharedWorkerHost>(this, std::move(instance), process_id);
// Get the factory used to instantiate the new shared worker instance in
// the target process.
@@ -228,8 +306,6 @@ void SharedWorkerServiceImpl::CreateWorker(
host->Start(std::move(factory), std::move(service_worker_provider_info),
std::move(script_loader_factory_info));
host->AddClient(std::move(client), process_id, frame_id, message_port);
-
- worker_hosts_.insert(std::move(host));
}
SharedWorkerHost* SharedWorkerServiceImpl::FindAvailableSharedWorkerHost(
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.h b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
index c4075f85b8b..b41bcc2d352 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
@@ -56,16 +56,23 @@ class CONTENT_EXPORT SharedWorkerServiceImpl : public SharedWorkerService {
private:
friend class SharedWorkerServiceImplTest;
+ friend class SharedWorkerHostTest;
void CreateWorker(std::unique_ptr<SharedWorkerInstance> instance,
mojom::SharedWorkerClientPtr client,
int process_id,
int frame_id,
- const blink::MessagePortChannel& message_port,
- mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
- service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_info);
+ const blink::MessagePortChannel& message_port);
+ void StartWorker(std::unique_ptr<SharedWorkerInstance> instance,
+ base::WeakPtr<SharedWorkerHost> host,
+ mojom::SharedWorkerClientPtr client,
+ int process_id,
+ int frame_id,
+ const blink::MessagePortChannel& message_port,
+ mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
+ service_worker_provider_info,
+ network::mojom::URLLoaderFactoryAssociatedPtrInfo
+ script_loader_factory_info);
// Returns nullptr if there is no such host.
SharedWorkerHost* FindSharedWorkerHost(int process_id, int route_id);
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index d3ac80d6a79..2afa11622eb 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -4,23 +4,16 @@
#include "content/browser/shared_worker/shared_worker_service_impl.h"
-#include <stddef.h>
-
-#include <map>
#include <memory>
+#include <queue>
#include <set>
#include <string>
-#include <tuple>
-#include "base/atomic_sequence_num.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
+#include "content/browser/shared_worker/mock_shared_worker.h"
#include "content/browser/shared_worker/shared_worker_connector_impl.h"
#include "content/browser/site_instance_impl.h"
-#include "content/public/browser/storage_partition.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
@@ -80,7 +73,7 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness {
RenderViewHostImplTestHarness::SetUp();
render_process_host_factory_ =
std::make_unique<MockRenderProcessHostFactory>();
- RenderProcessHostImpl::set_render_process_host_factory(
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(
render_process_host_factory_.get());
}
@@ -104,202 +97,14 @@ std::queue<mojom::SharedWorkerFactoryRequest>
namespace {
-template <typename T>
-static bool CheckEquality(const T& expected, const T& actual) {
- EXPECT_EQ(expected, actual);
- return expected == actual;
-}
-
-class MockSharedWorker : public mojom::SharedWorker {
- public:
- explicit MockSharedWorker(mojom::SharedWorkerRequest request)
- : binding_(this, std::move(request)) {}
-
- bool CheckReceivedConnect(int* connection_request_id,
- MessagePortChannel* port) {
- if (connect_received_.empty())
- return false;
- if (connection_request_id)
- *connection_request_id = connect_received_.front().first;
- if (port)
- *port = connect_received_.front().second;
- connect_received_.pop();
- return true;
- }
-
- bool CheckNotReceivedConnect() { return connect_received_.empty(); }
-
- bool CheckReceivedTerminate() {
- if (!terminate_received_)
- return false;
- terminate_received_ = false;
- return true;
- }
-
- private:
- // mojom::SharedWorker methods:
- void Connect(int connection_request_id,
- mojo::ScopedMessagePipeHandle port) override {
- connect_received_.emplace(connection_request_id,
- MessagePortChannel(std::move(port)));
- }
- void Terminate() override {
- // Allow duplicate events.
- terminate_received_ = true;
- }
- void BindDevToolsAgent(
- blink::mojom::DevToolsAgentAssociatedRequest request) override {
- NOTREACHED();
- }
-
- mojo::Binding<mojom::SharedWorker> binding_;
- std::queue<std::pair<int, MessagePortChannel>> connect_received_;
- bool terminate_received_ = false;
-};
-
-class MockSharedWorkerFactory : public mojom::SharedWorkerFactory {
- public:
- explicit MockSharedWorkerFactory(mojom::SharedWorkerFactoryRequest request)
- : binding_(this, std::move(request)) {}
-
- bool CheckReceivedCreateSharedWorker(
- const std::string& expected_url,
- const std::string& expected_name,
- blink::WebContentSecurityPolicyType expected_content_security_policy_type,
- mojom::SharedWorkerHostPtr* host,
- mojom::SharedWorkerRequest* request) {
- std::unique_ptr<CreateParams> create_params = std::move(create_params_);
- if (!create_params)
- return false;
- if (!CheckEquality(GURL(expected_url), create_params->info->url))
- return false;
- if (!CheckEquality(expected_name, create_params->info->name))
- return false;
- if (!CheckEquality(expected_content_security_policy_type,
- create_params->info->content_security_policy_type))
- return false;
- if (!create_params->interface_provider)
- return false;
- *host = std::move(create_params->host);
- *request = std::move(create_params->request);
- return true;
- }
-
- private:
- // mojom::SharedWorkerFactory methods:
- void CreateSharedWorker(
- mojom::SharedWorkerInfoPtr info,
- bool pause_on_start,
- const base::UnguessableToken& devtools_worker_token,
- blink::mojom::WorkerContentSettingsProxyPtr content_settings,
- mojom::ServiceWorkerProviderInfoForSharedWorkerPtr
- service_worker_provider_info,
- network::mojom::URLLoaderFactoryAssociatedPtrInfo
- script_loader_factory_ptr_info,
- mojom::SharedWorkerHostPtr host,
- mojom::SharedWorkerRequest request,
- service_manager::mojom::InterfaceProviderPtr interface_provider)
- override {
- CHECK(!create_params_);
- create_params_ = std::make_unique<CreateParams>();
- create_params_->info = std::move(info);
- create_params_->pause_on_start = pause_on_start;
- create_params_->content_settings = std::move(content_settings);
- create_params_->host = std::move(host);
- create_params_->request = std::move(request);
- create_params_->interface_provider = std::move(interface_provider);
- }
-
- struct CreateParams {
- mojom::SharedWorkerInfoPtr info;
- bool pause_on_start;
- blink::mojom::WorkerContentSettingsProxyPtr content_settings;
- mojom::SharedWorkerHostPtr host;
- mojom::SharedWorkerRequest request;
- service_manager::mojom::InterfaceProviderPtr interface_provider;
- };
-
- mojo::Binding<mojom::SharedWorkerFactory> binding_;
- std::unique_ptr<CreateParams> create_params_;
-};
-
-class MockSharedWorkerClient : public mojom::SharedWorkerClient {
- public:
- MockSharedWorkerClient() : binding_(this) {}
-
- void Bind(mojom::SharedWorkerClientRequest request) {
- binding_.Bind(std::move(request));
- }
-
- void Close() { binding_.Close(); }
-
- bool CheckReceivedOnCreated() {
- if (!on_created_received_)
- return false;
- on_created_received_ = false;
- return true;
- }
-
- bool CheckReceivedOnConnected(
- std::set<blink::mojom::WebFeature> expected_used_features) {
- if (!on_connected_received_)
- return false;
- on_connected_received_ = false;
- if (!CheckEquality(expected_used_features, on_connected_features_))
- return false;
- return true;
- }
-
- bool CheckReceivedOnFeatureUsed(blink::mojom::WebFeature expected_feature) {
- if (!on_feature_used_received_)
- return false;
- on_feature_used_received_ = false;
- if (!CheckEquality(expected_feature, on_feature_used_feature_))
- return false;
- return true;
- }
-
- bool CheckNotReceivedOnFeatureUsed() { return !on_feature_used_received_; }
-
- private:
- // mojom::SharedWorkerClient methods:
- void OnCreated(blink::mojom::SharedWorkerCreationContextType
- creation_context_type) override {
- CHECK(!on_created_received_);
- on_created_received_ = true;
- }
- void OnConnected(
- const std::vector<blink::mojom::WebFeature>& features_used) override {
- CHECK(!on_connected_received_);
- on_connected_received_ = true;
- for (auto feature : features_used)
- on_connected_features_.insert(feature);
- }
- void OnScriptLoadFailed() override { NOTREACHED(); }
- void OnFeatureUsed(blink::mojom::WebFeature feature) override {
- CHECK(!on_feature_used_received_);
- on_feature_used_received_ = true;
- on_feature_used_feature_ = feature;
- }
-
- mojo::Binding<mojom::SharedWorkerClient> binding_;
- bool on_created_received_ = false;
- bool on_connected_received_ = false;
- std::set<blink::mojom::WebFeature> on_connected_features_;
- bool on_feature_used_received_ = false;
- blink::mojom::WebFeature on_feature_used_feature_ =
- blink::mojom::WebFeature();
-};
-
void ConnectToSharedWorker(mojom::SharedWorkerConnectorPtr connector,
- const std::string& url,
+ const GURL& url,
const std::string& name,
MockSharedWorkerClient* client,
MessagePortChannel* local_port) {
- mojom::SharedWorkerInfoPtr info(
- mojom::SharedWorkerInfo::New(GURL(url), name, std::string(),
- blink::kWebContentSecurityPolicyTypeReport,
- blink::mojom::IPAddressSpace::kPublic));
+ mojom::SharedWorkerInfoPtr info(mojom::SharedWorkerInfo::New(
+ url, name, std::string(), blink::kWebContentSecurityPolicyTypeReport,
+ blink::mojom::IPAddressSpace::kPublic));
mojo::MessagePipe message_pipe;
*local_port = MessagePortChannel(std::move(message_pipe.handle0));
@@ -325,39 +130,38 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
MockSharedWorkerClient client;
MessagePortChannel local_port;
+ const GURL kUrl("http://example.com/w.js");
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host, render_frame_host->GetRoutingID()),
- "http://example.com/w.js", "name", &client,
- &local_port);
+ kUrl, "name", &client, &local_port);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerFactoryRequest factory_request;
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
MockSharedWorkerFactory factory(std::move(factory_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host;
mojom::SharedWorkerRequest worker_request;
EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker(
- "http://example.com/w.js", "name",
- blink::kWebContentSecurityPolicyTypeReport, &worker_host,
+ kUrl, "name", blink::kWebContentSecurityPolicyTypeReport, &worker_host,
&worker_request));
MockSharedWorker worker(std::move(worker_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
int connection_request_id;
MessagePortChannel port;
EXPECT_TRUE(worker.CheckReceivedConnect(&connection_request_id, &port));
- client.CheckReceivedOnCreated();
+ EXPECT_TRUE(client.CheckReceivedOnCreated());
// Simulate events the shared worker would send.
worker_host->OnReadyForInspection();
worker_host->OnScriptLoaded();
worker_host->OnConnected(connection_request_id);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(
client.CheckReceivedOnConnected(std::set<blink::mojom::WebFeature>()));
@@ -374,18 +178,18 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
// Send feature from shared worker to host.
auto feature1 = static_cast<blink::mojom::WebFeature>(124);
worker_host->OnFeatureUsed(feature1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client.CheckReceivedOnFeatureUsed(feature1));
// A message should be sent only one time per feature.
worker_host->OnFeatureUsed(feature1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client.CheckNotReceivedOnFeatureUsed());
// Send another feature.
auto feature2 = static_cast<blink::mojom::WebFeature>(901);
worker_host->OnFeatureUsed(feature2);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client.CheckReceivedOnFeatureUsed(feature2));
}
@@ -401,39 +205,38 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
MockSharedWorkerClient client0;
MessagePortChannel local_port0;
+ const GURL kUrl("http://example.com/w.js");
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- "http://example.com/w.js", "name", &client0,
- &local_port0);
+ kUrl, "name", &client0, &local_port0);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerFactoryRequest factory_request;
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
MockSharedWorkerFactory factory(std::move(factory_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host;
mojom::SharedWorkerRequest worker_request;
EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker(
- "http://example.com/w.js", "name",
- blink::kWebContentSecurityPolicyTypeReport, &worker_host,
+ kUrl, "name", blink::kWebContentSecurityPolicyTypeReport, &worker_host,
&worker_request));
MockSharedWorker worker(std::move(worker_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
int connection_request_id0;
MessagePortChannel port0;
EXPECT_TRUE(worker.CheckReceivedConnect(&connection_request_id0, &port0));
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
// Simulate events the shared worker would send.
worker_host->OnReadyForInspection();
worker_host->OnScriptLoaded();
worker_host->OnConnected(connection_request_id0);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(
client0.CheckReceivedOnConnected(std::set<blink::mojom::WebFeature>()));
@@ -449,11 +252,11 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
auto feature1 = static_cast<blink::mojom::WebFeature>(124);
worker_host->OnFeatureUsed(feature1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client0.CheckReceivedOnFeatureUsed(feature1));
auto feature2 = static_cast<blink::mojom::WebFeature>(901);
worker_host->OnFeatureUsed(feature2);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client0.CheckReceivedOnFeatureUsed(feature2));
// Only a single worker instance in process 0.
@@ -472,10 +275,9 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- "http://example.com/w.js", "name", &client1,
- &local_port1);
+ kUrl, "name", &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Should not have tried to create a new shared worker.
EXPECT_TRUE(CheckNotReceivedFactoryRequest());
@@ -484,7 +286,7 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
MessagePortChannel port1;
EXPECT_TRUE(worker.CheckReceivedConnect(&connection_request_id1, &port1));
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Only a single worker instance in process 0.
EXPECT_EQ(1u, renderer_host0->GetKeepAliveRefCount());
@@ -492,7 +294,7 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
worker_host->OnConnected(connection_request_id1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client1.CheckReceivedOnConnected({feature1, feature2}));
@@ -506,19 +308,19 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
EXPECT_EQ(expected_message1, received_message1);
worker_host->OnFeatureUsed(feature1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client0.CheckNotReceivedOnFeatureUsed());
EXPECT_TRUE(client1.CheckNotReceivedOnFeatureUsed());
auto feature3 = static_cast<blink::mojom::WebFeature>(1019);
worker_host->OnFeatureUsed(feature3);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client0.CheckReceivedOnFeatureUsed(feature3));
EXPECT_TRUE(client1.CheckReceivedOnFeatureUsed(feature3));
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase) {
- const char kURL[] = "http://example.com/w.js";
+ const GURL kUrl("http://example.com/w.js");
const char kName[] = "name";
// The first renderer host.
@@ -545,24 +347,24 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL, kName, &client0, &local_port0);
- RunAllPendingInMessageLoop();
+ kUrl, kName, &client0, &local_port0);
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerFactoryRequest factory_request;
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
MockSharedWorkerFactory factory(std::move(factory_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host;
mojom::SharedWorkerRequest worker_request;
EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker(
- kURL, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host,
+ kUrl, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host,
&worker_request));
MockSharedWorker worker(std::move(worker_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker.CheckReceivedConnect(nullptr, nullptr));
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
// Second client, same worker.
@@ -570,26 +372,26 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase) {
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL, kName, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ kUrl, kName, &client1, &local_port1);
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(CheckNotReceivedFactoryRequest());
EXPECT_TRUE(worker.CheckReceivedConnect(nullptr, nullptr));
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Cleanup
client0.Close();
client1.Close();
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker.CheckReceivedTerminate());
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
- const char kURL0[] = "http://example.com/w0.js";
- const char kURL1[] = "http://example.com/w1.js";
+ const GURL kUrl0("http://example.com/w0.js");
+ const GURL kUrl1("http://example.com/w1.js");
const char kName[] = "name";
// The first renderer host.
@@ -616,24 +418,24 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL0, kName, &client0, &local_port0);
- RunAllPendingInMessageLoop();
+ kUrl0, kName, &client0, &local_port0);
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerFactoryRequest factory_request0;
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
MockSharedWorkerFactory factory0(std::move(factory_request0));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host0;
mojom::SharedWorkerRequest worker_request0;
EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker(
- kURL0, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
+ kUrl0, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
&worker_request0));
MockSharedWorker worker0(std::move(worker_request0));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckReceivedConnect(nullptr, nullptr));
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
// Second client, creates worker.
@@ -641,37 +443,37 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_URLMismatch) {
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL1, kName, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ kUrl1, kName, &client1, &local_port1);
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerFactoryRequest factory_request1;
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
MockSharedWorkerFactory factory1(std::move(factory_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host1;
mojom::SharedWorkerRequest worker_request1;
EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker(
- kURL1, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
+ kUrl1, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
&worker_request1));
MockSharedWorker worker1(std::move(worker_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Cleanup
client0.Close();
client1.Close();
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckReceivedTerminate());
EXPECT_TRUE(worker1.CheckReceivedTerminate());
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
- const char kURL[] = "http://example.com/w.js";
+ const GURL kUrl("http://example.com/w.js");
const char kName0[] = "name0";
const char kName1[] = "name1";
@@ -699,24 +501,24 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL, kName0, &client0, &local_port0);
- RunAllPendingInMessageLoop();
+ kUrl, kName0, &client0, &local_port0);
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerFactoryRequest factory_request0;
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
MockSharedWorkerFactory factory0(std::move(factory_request0));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host0;
mojom::SharedWorkerRequest worker_request0;
EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker(
- kURL, kName0, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
+ kUrl, kName0, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
&worker_request0));
MockSharedWorker worker0(std::move(worker_request0));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckReceivedConnect(nullptr, nullptr));
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
// Second client, creates worker.
@@ -724,37 +526,37 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_NormalCase_NameMismatch) {
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL, kName1, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ kUrl, kName1, &client1, &local_port1);
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerFactoryRequest factory_request1;
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
MockSharedWorkerFactory factory1(std::move(factory_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host1;
mojom::SharedWorkerRequest worker_request1;
EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker(
- kURL, kName1, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
+ kUrl, kName1, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
&worker_request1));
MockSharedWorker worker1(std::move(worker_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Cleanup
client0.Close();
client1.Close();
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckReceivedTerminate());
EXPECT_TRUE(worker1.CheckReceivedTerminate());
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
- const char kURL[] = "http://example.com/w.js";
+ const GURL kUrl("http://example.com/w.js");
const char kName[] = "name";
// The first renderer host.
@@ -781,15 +583,15 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL, kName, &client0, &local_port0);
+ kUrl, kName, &client0, &local_port0);
MockSharedWorkerClient client1;
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL, kName, &client1, &local_port1);
+ kUrl, kName, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Check that the worker was created.
@@ -797,37 +599,37 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase) {
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
MockSharedWorkerFactory factory(std::move(factory_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host;
mojom::SharedWorkerRequest worker_request;
EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker(
- kURL, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host,
+ kUrl, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host,
&worker_request));
MockSharedWorker worker(std::move(worker_request));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Check that the worker received two connections.
EXPECT_TRUE(worker.CheckReceivedConnect(nullptr, nullptr));
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
EXPECT_TRUE(worker.CheckReceivedConnect(nullptr, nullptr));
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Cleanup
client0.Close();
client1.Close();
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker.CheckReceivedTerminate());
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
- const char kURL0[] = "http://example.com/w0.js";
- const char kURL1[] = "http://example.com/w1.js";
+ const GURL kUrl0("http://example.com/w0.js");
+ const GURL kUrl1("http://example.com/w1.js");
const char kName[] = "name";
// The first renderer host.
@@ -854,15 +656,15 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL0, kName, &client0, &local_port0);
+ kUrl0, kName, &client0, &local_port0);
MockSharedWorkerClient client1;
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL1, kName, &client1, &local_port1);
+ kUrl1, kName, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Check that both workers were created.
@@ -874,46 +676,46 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_URLMismatch) {
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
MockSharedWorkerFactory factory1(std::move(factory_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host0;
mojom::SharedWorkerRequest worker_request0;
EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker(
- kURL0, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
+ kUrl0, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
&worker_request0));
MockSharedWorker worker0(std::move(worker_request0));
mojom::SharedWorkerHostPtr worker_host1;
mojom::SharedWorkerRequest worker_request1;
EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker(
- kURL1, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
+ kUrl1, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
&worker_request1));
MockSharedWorker worker1(std::move(worker_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Check that the workers each received a connection.
EXPECT_TRUE(worker0.CheckReceivedConnect(nullptr, nullptr));
EXPECT_TRUE(worker0.CheckNotReceivedConnect());
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
EXPECT_TRUE(worker1.CheckNotReceivedConnect());
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Cleanup
client0.Close();
client1.Close();
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckReceivedTerminate());
EXPECT_TRUE(worker1.CheckReceivedTerminate());
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
- const char kURL[] = "http://example.com/w.js";
+ const GURL kUrl("http://example.com/w.js");
const char kName0[] = "name0";
const char kName1[] = "name1";
@@ -941,15 +743,15 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL, kName0, &client0, &local_port0);
+ kUrl, kName0, &client0, &local_port0);
MockSharedWorkerClient client1;
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL, kName1, &client1, &local_port1);
+ kUrl, kName1, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Check that both workers were created.
@@ -961,46 +763,46 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerTest_PendingCase_NameMismatch) {
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
MockSharedWorkerFactory factory1(std::move(factory_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host0;
mojom::SharedWorkerRequest worker_request0;
EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker(
- kURL, kName0, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
+ kUrl, kName0, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
&worker_request0));
MockSharedWorker worker0(std::move(worker_request0));
mojom::SharedWorkerHostPtr worker_host1;
mojom::SharedWorkerRequest worker_request1;
EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker(
- kURL, kName1, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
+ kUrl, kName1, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
&worker_request1));
MockSharedWorker worker1(std::move(worker_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Check that the workers each received a connection.
EXPECT_TRUE(worker0.CheckReceivedConnect(nullptr, nullptr));
EXPECT_TRUE(worker0.CheckNotReceivedConnect());
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
EXPECT_TRUE(worker1.CheckNotReceivedConnect());
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Cleanup
client0.Close();
client1.Close();
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckReceivedTerminate());
EXPECT_TRUE(worker1.CheckReceivedTerminate());
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
- const char kURL[] = "http://example.com/w.js";
+ const GURL kUrl("http://example.com/w.js");
const char kName[] = "name";
// Create three renderer hosts.
@@ -1033,9 +835,9 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL, kName, &client0, &local_port0);
+ kUrl, kName, &client0, &local_port0);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// Starts a worker.
@@ -1043,19 +845,19 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request0));
MockSharedWorkerFactory factory0(std::move(factory_request0));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host0;
mojom::SharedWorkerRequest worker_request0;
EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker(
- kURL, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
+ kUrl, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host0,
&worker_request0));
MockSharedWorker worker0(std::move(worker_request0));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckReceivedConnect(nullptr, nullptr));
- client0.CheckReceivedOnCreated();
+ EXPECT_TRUE(client0.CheckReceivedOnCreated());
// Kill this process, which should make worker0 unavailable.
web_contents0.reset();
@@ -1067,9 +869,9 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL, kName, &client1, &local_port1);
+ kUrl, kName, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// The previous worker is unavailable, so a new worker is created.
@@ -1077,38 +879,38 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest) {
EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request1));
MockSharedWorkerFactory factory1(std::move(factory_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host1;
mojom::SharedWorkerRequest worker_request1;
EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker(
- kURL, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
+ kUrl, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
&worker_request1));
MockSharedWorker worker1(std::move(worker_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker0.CheckNotReceivedConnect());
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Start another client to confirm that it can connect to the same worker.
MockSharedWorkerClient client2;
MessagePortChannel local_port2;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host2, render_frame_host2->GetRoutingID()),
- kURL, kName, &client2, &local_port2);
+ kUrl, kName, &client2, &local_port2);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(CheckNotReceivedFactoryRequest());
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
- client2.CheckReceivedOnCreated();
+ EXPECT_TRUE(client2.CheckReceivedOnCreated());
}
TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
- const char kURL[] = "http://example.com/w.js";
+ const GURL kUrl("http://example.com/w.js");
const char kName[] = "name";
// Create three renderer hosts.
@@ -1141,7 +943,7 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
MessagePortChannel local_port0;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host0, render_frame_host0->GetRoutingID()),
- kURL, kName, &client0, &local_port0);
+ kUrl, kName, &client0, &local_port0);
// Kill this process, which should make worker0 unavailable.
renderer_host0->FastShutdownIfPossible(0, true);
@@ -1151,9 +953,9 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
MessagePortChannel local_port1;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host1, render_frame_host1->GetRoutingID()),
- kURL, kName, &client1, &local_port1);
+ kUrl, kName, &client1, &local_port1);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
// The previous worker is unavailable, so a new worker is created.
@@ -1163,33 +965,104 @@ TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest2) {
EXPECT_TRUE(CheckNotReceivedFactoryRequest());
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
mojom::SharedWorkerHostPtr worker_host1;
mojom::SharedWorkerRequest worker_request1;
EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker(
- kURL, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
+ kUrl, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host1,
&worker_request1));
MockSharedWorker worker1(std::move(worker_request1));
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
- client1.CheckReceivedOnCreated();
+ EXPECT_TRUE(client1.CheckReceivedOnCreated());
// Start another client to confirm that it can connect to the same worker.
MockSharedWorkerClient client2;
MessagePortChannel local_port2;
ConnectToSharedWorker(MakeSharedWorkerConnector(
renderer_host2, render_frame_host2->GetRoutingID()),
- kURL, kName, &client2, &local_port2);
+ kUrl, kName, &client2, &local_port2);
- RunAllPendingInMessageLoop();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(CheckNotReceivedFactoryRequest());
EXPECT_TRUE(worker1.CheckReceivedConnect(nullptr, nullptr));
- client2.CheckReceivedOnCreated();
+ EXPECT_TRUE(client2.CheckReceivedOnCreated());
+}
+
+TEST_F(SharedWorkerServiceImplTest, CreateWorkerRaceTest3) {
+ const GURL kURL("http://example.com/w.js");
+ const char kName[] = "name";
+
+ // The first renderer host.
+ std::unique_ptr<TestWebContents> web_contents0 =
+ CreateWebContents(GURL("http://example.com/"));
+ TestRenderFrameHost* render_frame_host0 = web_contents0->GetMainFrame();
+ MockRenderProcessHost* renderer_host0 = render_frame_host0->GetProcess();
+ renderer_host0->OverrideBinderForTesting(
+ mojom::SharedWorkerFactory::Name_,
+ base::BindRepeating(
+ &SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+
+ // The second renderer host.
+ std::unique_ptr<TestWebContents> web_contents1 =
+ CreateWebContents(GURL("http://example.com/"));
+ TestRenderFrameHost* render_frame_host1 = web_contents1->GetMainFrame();
+ MockRenderProcessHost* renderer_host1 = render_frame_host1->GetProcess();
+ renderer_host1->OverrideBinderForTesting(
+ mojom::SharedWorkerFactory::Name_,
+ base::BindRepeating(
+ &SharedWorkerServiceImplTest::BindSharedWorkerFactory));
+
+ // Both clients try to connect/create a worker.
+
+ MockSharedWorkerClient client0;
+ MessagePortChannel local_port0;
+ ConnectToSharedWorker(MakeSharedWorkerConnector(
+ renderer_host0, render_frame_host0->GetRoutingID()),
+ kURL, kName, &client0, &local_port0);
+
+ MockSharedWorkerClient client1;
+ MessagePortChannel local_port1;
+ ConnectToSharedWorker(MakeSharedWorkerConnector(
+ renderer_host1, render_frame_host1->GetRoutingID()),
+ kURL, kName, &client1, &local_port1);
+ base::RunLoop().RunUntilIdle();
+
+ // Expect a factory request.
+ mojom::SharedWorkerFactoryRequest factory_request;
+ EXPECT_TRUE(CheckReceivedFactoryRequest(&factory_request));
+ MockSharedWorkerFactory factory(std::move(factory_request));
+ base::RunLoop().RunUntilIdle();
+
+ // Expect a create shared worker.
+ mojom::SharedWorkerHostPtr worker_host;
+ mojom::SharedWorkerRequest worker_request;
+ EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker(
+ kURL, kName, blink::kWebContentSecurityPolicyTypeReport, &worker_host,
+ &worker_request));
+ MockSharedWorker worker(std::move(worker_request));
+ base::RunLoop().RunUntilIdle();
+
+ // Expect one connect for the first client.
+ EXPECT_TRUE(worker.CheckReceivedConnect(nullptr, nullptr));
+ client0.CheckReceivedOnCreated();
+
+ // Expect one connect for the second client.
+ EXPECT_TRUE(worker.CheckReceivedConnect(nullptr, nullptr));
+ client1.CheckReceivedOnCreated();
+
+ // Cleanup
+
+ client0.Close();
+ client1.Close();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(worker.CheckReceivedTerminate());
}
} // namespace content
diff --git a/chromium/content/browser/shared_worker/worker_browsertest.cc b/chromium/content/browser/shared_worker/worker_browsertest.cc
index 6c9a3d21a54..179376232af 100644
--- a/chromium/content/browser/shared_worker/worker_browsertest.cc
+++ b/chromium/content/browser/shared_worker/worker_browsertest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -55,6 +54,7 @@ class WorkerTest : public ContentBrowserTest {
ShellContentBrowserClient::Get()->set_select_client_certificate_callback(
base::Bind(&WorkerTest::OnSelectClientCertificate,
base::Unretained(this)));
+ ASSERT_TRUE(embedded_test_server()->Start());
}
void TearDownOnMainThread() override {
@@ -65,9 +65,8 @@ class WorkerTest : public ContentBrowserTest {
int select_certificate_count() const { return select_certificate_count_; }
GURL GetTestURL(const std::string& test_case, const std::string& query) {
- base::FilePath test_file_path = GetTestFilePath(
- "workers", test_case.c_str());
- return GetFileUrlWithQuery(test_file_path, query);
+ std::string url_string = "/workers/" + test_case + "?" + query;
+ return embedded_test_server()->GetURL(url_string);
}
void RunTest(Shell* window, const GURL& url) {
@@ -129,11 +128,6 @@ IN_PROC_BROWSER_TEST_F(WorkerTest, IncognitoSharedWorkers) {
if (!SupportsSharedWorker())
return;
- // Launch the server to host a shared worker on http environment because a
- // local file (file://) is treated like it has an opaque origin and the
- // shared worker on the origin cannot be shared.
- ASSERT_TRUE(embedded_test_server()->Start());
-
// Load a non-incognito tab and have it create a shared worker
RunTest(embedded_test_server()->GetURL("/workers/incognito_worker.html"));
@@ -145,28 +139,11 @@ IN_PROC_BROWSER_TEST_F(WorkerTest, IncognitoSharedWorkers) {
// Make sure that auth dialog is displayed from worker context.
// http://crbug.com/33344
IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerHttpAuth) {
- ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/workers/worker_auth.html");
NavigateAndWaitForAuth(url);
}
-// Make sure that HTTP auth dialog is displayed from shared worker context.
-// http://crbug.com/33344
-//
-// TODO(davidben): HTTP auth dialogs are no longer displayed on shared workers,
-// but this test only tests that the delegate is called. Move handling the
-// WebContentsless case from chrome/ to content/ and adjust the test
-// accordingly.
-IN_PROC_BROWSER_TEST_F(WorkerTest, SharedWorkerHttpAuth) {
- if (!SupportsSharedWorker())
- return;
-
- ASSERT_TRUE(embedded_test_server()->Start());
- GURL url = embedded_test_server()->GetURL("/workers/shared_worker_auth.html");
- NavigateAndWaitForAuth(url);
-}
-
// Tests that TLS client auth prompts for normal workers's importScripts.
IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerTlsClientAuthImportScripts) {
// Launch HTTPS server.
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index d1ec2e7afab..b34db8034e1 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -36,6 +36,7 @@ SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
active_frame_count_(0),
browsing_instance_(browsing_instance),
process_(nullptr),
+ can_associate_with_spare_process_(true),
has_site_(false),
process_reuse_policy_(ProcessReusePolicy::DEFAULT),
is_for_service_worker_(false) {
@@ -154,6 +155,14 @@ RenderProcessHost* SiteInstanceImpl::GetProcess() {
return process_;
}
+bool SiteInstanceImpl::CanAssociateWithSpareProcess() {
+ return can_associate_with_spare_process_;
+}
+
+void SiteInstanceImpl::PreventAssociationWithSpareProcess() {
+ can_associate_with_spare_process_ = false;
+}
+
void SiteInstanceImpl::SetSite(const GURL& url) {
TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite",
"site id", id_, "url", url.possibly_invalid_spec());
@@ -468,6 +477,12 @@ bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
return true;
+ // Error pages in main frames do require isolation, however since this is
+ // missing the context whether this is for a main frame or not, that part
+ // is enforced in RenderFrameHostManager.
+ if (url.SchemeIs(kChromeErrorScheme))
+ return true;
+
// Always require a dedicated process for isolated origins.
GURL site_url = GetSiteForURL(browser_context, url);
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
@@ -536,9 +551,9 @@ void SiteInstanceImpl::RenderProcessWillExit(RenderProcessHost* host) {
observer.RenderProcessGone(this);
}
-void SiteInstanceImpl::RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {
+void SiteInstanceImpl::RenderProcessExited(
+ RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) {
for (auto& observer : observers_)
observer.RenderProcessGone(this);
}
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index 7548752f7d8..4e96a2383e2 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -165,6 +165,22 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
+ // Whether GetProcess() method (when it needs to find a new process to
+ // associate with the current SiteInstanceImpl) can return a spare process.
+ bool CanAssociateWithSpareProcess();
+
+ // Has no effect if the SiteInstanceImpl already has a |process_|.
+ // Otherwise, prevents GetProcess() from associating this SiteInstanceImpl
+ // with the spare RenderProcessHost - instead GetProcess will either need to
+ // create a new, not-yet-initialized/spawned RenderProcessHost or will need to
+ // reuse one of existing RenderProcessHosts.
+ //
+ // See also:
+ // - https://crbug.com/840409.
+ // - WebContents::CreateParams::desired_renderer_state
+ // - SiteInstanceImpl::CanAssociateWithSpareProcess().
+ void PreventAssociationWithSpareProcess();
+
// Get the effective URL for the given actual URL. This allows the
// ContentBrowserClient to override the SiteInstance's site for certain URLs.
// For example, Chrome uses this to replace hosted app URLs with extension
@@ -209,8 +225,7 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
void RenderProcessWillExit(RenderProcessHost* host) override;
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override;
+ const ChildProcessTerminationInfo& info) override;
// Used to restrict a process' origin access rights.
void LockToOriginIfNeeded();
@@ -241,6 +256,12 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
// scenario the RenderProcessHost remains the same.
RenderProcessHost* process_;
+ // Describes the desired behavior when GetProcess() method needs to find a new
+ // process to associate with the current SiteInstanceImpl. If |false|, then
+ // prevents the spare RenderProcessHost from being taken and stored in
+ // |process_|.
+ bool can_associate_with_spare_process_;
+
// The web site that this SiteInstance is rendering pages for.
GURL site_;
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index 95595ca8c75..effcb936cb2 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -107,7 +107,8 @@ class SiteInstanceTest : public testing::Test {
url::AddStandardScheme(kPrivilegedScheme, url::SCHEME_WITH_HOST);
url::AddStandardScheme(kChromeUIScheme, url::SCHEME_WITH_HOST);
- RenderProcessHostImpl::set_render_process_host_factory(&rph_factory_);
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(
+ &rph_factory_);
}
void TearDown() override {
@@ -115,7 +116,7 @@ class SiteInstanceTest : public testing::Test {
EXPECT_TRUE(RenderProcessHost::AllHostsIterator().IsAtEnd());
SetBrowserClientForTesting(old_browser_client_);
- RenderProcessHostImpl::set_render_process_host_factory(nullptr);
+ RenderProcessHostImpl::set_render_process_host_factory_for_testing(nullptr);
// http://crbug.com/143565 found SiteInstanceTest leaking an
// AppCacheDatabase. This happens because some part of the test indirectly
@@ -165,7 +166,7 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
NavigationEntryImpl* e1 = new NavigationEntryImpl(
instance, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
- false);
+ false, nullptr /* blob_url_loader_factory */);
// Redundantly setting e1's SiteInstance shouldn't affect the ref count.
e1->set_site_instance(instance);
@@ -175,7 +176,7 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// Add a second reference
NavigationEntryImpl* e2 = new NavigationEntryImpl(
instance, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
- false);
+ false, nullptr /* blob_url_loader_factory */);
instance = nullptr;
EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
@@ -194,10 +195,10 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// Ensure that instances are deleted when their RenderViewHosts are gone.
std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
{
- std::unique_ptr<WebContentsImpl> web_contents(static_cast<WebContentsImpl*>(
+ std::unique_ptr<WebContents> web_contents(
WebContents::Create(WebContents::CreateParams(
browser_context.get(),
- SiteInstance::Create(browser_context.get())))));
+ SiteInstance::Create(browser_context.get()))));
EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
}
@@ -219,8 +220,9 @@ TEST_F(SiteInstanceTest, CloneNavigationEntry) {
std::unique_ptr<NavigationEntryImpl> e1 =
base::WrapUnique(new NavigationEntryImpl(
- SiteInstanceImpl::Create(nullptr), url, Referrer(),
- base::string16(), ui::PAGE_TRANSITION_LINK, false));
+ SiteInstanceImpl::Create(nullptr), url, Referrer(), base::string16(),
+ ui::PAGE_TRANSITION_LINK, false,
+ nullptr /* blob_url_loader_factory */));
// Clone the entry.
std::unique_ptr<NavigationEntryImpl> e2 = e1->Clone();
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 35f13184f84..569aa71cfe3 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -22,9 +22,9 @@
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "base/scoped_observer.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/pattern.h"
@@ -33,6 +33,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
+#include "base/test/histogram_tester.h"
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -69,6 +70,7 @@
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
@@ -108,6 +110,10 @@
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/latency/latency_info.h"
@@ -415,44 +421,46 @@ class SwapoutACKMessageFilter : public BrowserMessageFilter {
DISALLOW_COPY_AND_ASSIGN(SwapoutACKMessageFilter);
};
-class RenderWidgetHostVisibilityObserver : public NotificationObserver {
+class RenderWidgetHostVisibilityObserver : public RenderWidgetHostObserver {
public:
explicit RenderWidgetHostVisibilityObserver(RenderWidgetHostImpl* rwhi,
bool expected_visibility_state)
: expected_visibility_state_(expected_visibility_state),
+ observer_(this),
was_observed_(false),
did_fail_(false),
- source_(rwhi) {
- registrar_.Add(this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
- source_);
+ render_widget_(rwhi) {
+ observer_.Add(render_widget_);
message_loop_runner_ = new MessageLoopRunner;
}
bool WaitUntilSatisfied() {
if (!was_observed_)
message_loop_runner_->Run();
- registrar_.Remove(this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
- source_);
+ if (observer_.IsObserving(render_widget_))
+ observer_.Remove(render_widget_);
return !did_fail_;
}
private:
- void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) override {
+ void RenderWidgetHostVisibilityChanged(RenderWidgetHost* widget_host,
+ bool became_visible) override {
was_observed_ = true;
- did_fail_ = expected_visibility_state_ !=
- (*static_cast<const Details<bool>&>(details).ptr());
+ did_fail_ = expected_visibility_state_ != became_visible;
if (message_loop_runner_->loop_running())
message_loop_runner_->Quit();
}
+ void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override {
+ observer_.Remove(widget_host);
+ }
+
bool expected_visibility_state_;
scoped_refptr<MessageLoopRunner> message_loop_runner_;
- NotificationRegistrar registrar_;
+ ScopedObserver<RenderWidgetHost, RenderWidgetHostObserver> observer_;
bool was_observed_;
bool did_fail_;
- Source<RenderWidgetHost> source_;
+ RenderWidgetHost* render_widget_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostVisibilityObserver);
};
@@ -527,9 +535,8 @@ void CheckFrameDepth(unsigned int expected_depth, FrameTreeNode* node) {
RenderProcessHost::Priority priority =
node->current_frame_host()->GetRenderWidgetHost()->GetPriority();
EXPECT_EQ(expected_depth, priority.frame_depth);
- EXPECT_EQ(
- expected_depth,
- node->current_frame_host()->GetProcess()->GetFrameDepthForTesting());
+ EXPECT_EQ(expected_depth,
+ node->current_frame_host()->GetProcess()->GetFrameDepth());
}
} // namespace
@@ -1133,8 +1140,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ViewBoundsInNestedFrameTest) {
// relative offset of its direct parent within the root frame.
gfx::Rect bounds = rwhv_nested->GetViewBounds();
- scoped_refptr<UpdateResizeParamsMessageFilter> filter =
- new UpdateResizeParamsMessageFilter();
+ scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter =
+ new SynchronizeVisualPropertiesMessageFilter();
root->current_frame_host()->GetProcess()->AddFilter(filter.get());
// Scroll the parent frame downward to verify that the child rect gets updated
@@ -1254,11 +1261,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
FrameTreeNode* parent_iframe_node = root->child_at(0);
// This test uses the position of the nested iframe within the parent iframe
- // to infer the scroll position of the parent. UpdateResizeParamsMessageFilter
- // catches updates to the position in order to avoid busy waiting.
- // It gets created early to catch the initial rects from the navigation.
- scoped_refptr<UpdateResizeParamsMessageFilter> filter =
- new UpdateResizeParamsMessageFilter();
+ // to infer the scroll position of the parent.
+ // SynchronizeVisualPropertiesMessageFilter catches updates to the position in
+ // order to avoid busy waiting. It gets created early to catch the initial
+ // rects from the navigation.
+ scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter =
+ new SynchronizeVisualPropertiesMessageFilter();
parent_iframe_node->current_frame_host()->GetProcess()->AddFilter(
filter.get());
@@ -1472,8 +1480,74 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
DCHECK_EQ(filter->last_rect().y(), 0);
}
+// Tests that scrolling with the keyboard will bubble unused scroll to the
+// OOPIF's parent.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ KeyboardScrollBubblingFromOOPIF) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_iframe_in_scrollable_div.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* iframe_node = root->child_at(0);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root));
+
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ iframe_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ double initial_y = 0.0;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractDouble(
+ root,
+ "var wrapperDiv = document.getElementById('wrapper-div');"
+ "var initial_y = wrapperDiv.scrollTop;"
+ "var waitForScrollDownPromise = new Promise(function(resolve) {"
+ " wrapperDiv.addEventListener('scroll', () => {"
+ " if (wrapperDiv.scrollTop > initial_y)"
+ " resolve(wrapperDiv.scrollTop);"
+ " });"
+ "});"
+ "window.domAutomationController.send(initial_y);",
+ &initial_y));
+ EXPECT_DOUBLE_EQ(0.0, initial_y);
+
+ NativeWebKeyboardEvent key_event(
+ blink::WebKeyboardEvent::kRawKeyDown, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ key_event.windows_key_code = ui::VKEY_DOWN;
+ key_event.native_key_code =
+ ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::ARROW_DOWN);
+ key_event.dom_code = static_cast<int>(ui::DomCode::ARROW_DOWN);
+ key_event.dom_key = ui::DomKey::ARROW_DOWN;
+
+ rwhv_child->GetRenderWidgetHost()->ForwardKeyboardEvent(key_event);
+
+ key_event.SetType(blink::WebKeyboardEvent::kKeyUp);
+ rwhv_child->GetRenderWidgetHost()->ForwardKeyboardEvent(key_event);
+
+ double scrolled_y = 0.0;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractDouble(
+ root,
+ "waitForScrollDownPromise.then((scrolled_y) => {"
+ " window.domAutomationController.send(scrolled_y);"
+ "});",
+ &scrolled_y));
+ EXPECT_GT(scrolled_y, 0.0);
+}
+
// Test that fling on an out-of-process iframe progresses properly.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, GestureFlingStart) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ TouchscreenGestureFlingStart) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1518,6 +1592,53 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, GestureFlingStart) {
gesture_scroll_update_ack_observer.Wait();
}
+// Test that fling on an out-of-process iframe progresses properly.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TouchpadGestureFlingStart) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_iframe_node = root->child_at(0);
+
+ RenderWidgetHost* child_rwh =
+ child_iframe_node->current_frame_host()->GetRenderWidgetHost();
+
+ // Send a wheel event with phaseBegan to start scrolling sequence.
+ InputEventAckWaiter gesture_scroll_begin_ack_observer(
+ child_rwh, blink::WebInputEvent::kGestureScrollBegin);
+ blink::WebMouseWheelEvent scroll_event(
+ blink::WebInputEvent::kMouseWheel, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ scroll_event.delta_x = 0.0f;
+ scroll_event.delta_y = 5.0f;
+ scroll_event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ scroll_event.has_precise_scrolling_deltas = true;
+ child_rwh->ForwardWheelEvent(scroll_event);
+ gesture_scroll_begin_ack_observer.Wait();
+
+ // Send a GFS and wait for the ack of the first GSU generated from progressing
+ // the fling on the browser.
+ InputEventAckWaiter gesture_scroll_update_ack_observer(
+ child_rwh, blink::WebInputEvent::kGestureScrollUpdate);
+ gesture_scroll_update_ack_observer.Reset();
+ blink::WebGestureEvent gesture_fling_start(
+ blink::WebGestureEvent::kGestureFlingStart,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ gesture_fling_start.SetSourceDevice(blink::kWebGestureDeviceTouchpad);
+ gesture_fling_start.data.fling_start.velocity_x = 0.f;
+ gesture_fling_start.data.fling_start.velocity_y = 50.f;
+ child_rwh->ForwardGestureEvent(gesture_fling_start);
+ // The test will pass when the GSU ack arrives, since it shows that the fling
+ // controller has properly generated a GSU event from progressing the fling.
+ gesture_scroll_update_ack_observer.Wait();
+}
+
class ScrollObserver : public RenderWidgetHost::InputEventObserver {
public:
ScrollObserver(double delta_x, double delta_y) { Reset(delta_x, delta_y); }
@@ -1656,10 +1777,18 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
}
+#if defined(OS_CHROMEOS)
+// Flaky: https://crbug.com/836200.
+#define MAYBE_ScrollBubblingFromOOPIFWithBodyOverflowHidden \
+ DISABLED_ScrollBubblingFromOOPIFWithBodyOverflowHidden
+#else
+#define MAYBE_ScrollBubblingFromOOPIFWithBodyOverflowHidden \
+ ScrollBubblingFromOOPIFWithBodyOverflowHidden
+#endif
// Tests that scrolling bubbles from an oopif if its source body has
// "overflow:hidden" style.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- ScrollBubblingFromOOPIFWithBodyOverflowHidden) {
+ MAYBE_ScrollBubblingFromOOPIFWithBodyOverflowHidden) {
GURL url_domain_a(embedded_test_server()->GetURL(
"a.com", "/scrollable_page_with_iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), url_domain_a));
@@ -2673,20 +2802,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ProcessTransferAfterError) {
// Disable host resolution in the test server and try to navigate the subframe
// cross-site, which will lead to a committed net error.
GURL url_b = embedded_test_server()->GetURL("b.com", "/title3.html");
- bool network_service =
- base::FeatureList::IsEnabled(network::features::kNetworkService);
std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor;
- if (network_service) {
- url_loader_interceptor = std::make_unique<URLLoaderInterceptor>(
- base::BindRepeating([](URLLoaderInterceptor::RequestParams* params) {
- network::URLLoaderCompletionStatus status;
- status.error_code = net::ERR_NOT_IMPLEMENTED;
- params->client->OnComplete(status);
- return true;
- }));
- } else {
- host_resolver()->ClearRules();
- }
+ url_loader_interceptor = std::make_unique<URLLoaderInterceptor>(
+ base::BindRepeating([](URLLoaderInterceptor::RequestParams* params) {
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::ERR_NOT_IMPLEMENTED;
+ params->client->OnComplete(status);
+ return true;
+ }));
TestNavigationObserver observer(shell()->web_contents());
NavigateIframeToURL(shell()->web_contents(), "child-0", url_b);
@@ -2711,11 +2834,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ProcessTransferAfterError) {
EXPECT_EQ("null", child->current_origin().Serialize());
// Try again after re-enabling host resolution.
- if (network_service) {
- url_loader_interceptor.reset();
- } else {
- host_resolver()->AddRule("*", "127.0.0.1");
- }
+ url_loader_interceptor.reset();
NavigateIframeToURL(shell()->web_contents(), "child-0", url_b);
EXPECT_TRUE(observer.last_navigation_succeeded());
@@ -7746,7 +7865,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FileChooserInSubframe) {
// Use FileChooserDelegate to avoid showing the actual dialog and to respond
// back to the renderer process with predefined file.
base::FilePath file;
- EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
+ EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &file));
file = file.AppendASCII("bar");
std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(file));
shell()->web_contents()->SetDelegate(delegate.get());
@@ -8929,6 +9048,64 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(0UL, final_effective_policy[0].origins.size());
}
+// Test that creating a new remote frame at the same origin as its parent
+// results in the correct feature policy in the RemoteSecurityContext.
+// https://crbug.com/852102
+IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyJavaScriptBrowserTest,
+ FeaturePolicyConstructionInExistingProxy) {
+ WebContentsImpl* contents = web_contents();
+ FrameTreeNode* root = contents->GetFrameTree()->root();
+
+ // Navigate to a page (1) with a cross-origin iframe (2). After load, the
+ // frame tree should look like:
+ //
+ // a.com(1)
+ // /
+ // b.com(2)
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)")));
+
+ // Programmatically create a new same-origin frame (3) under the root, with a
+ // cross-origin child (4). Since two SiteInstances already exist at this
+ // point, a proxy for frame 3 will be created in the renderer for frames 2 and
+ // 4. The frame tree should look like:
+ //
+ // a.com(1)
+ // / \
+ // b.com(2) a.com(3)
+ // \
+ // b.com(4)
+ std::string create_subframe_script =
+ "var f = document.createElement('iframe'); f.src='" +
+ embedded_test_server()
+ ->GetURL("a.com",
+ "/cross_site_iframe_factory.html?a(b{allow-autoplay})")
+ .spec() +
+ "'; document.body.appendChild(f);";
+ EXPECT_TRUE(ExecuteScript(root, create_subframe_script));
+ EXPECT_TRUE(WaitForLoadStop(contents));
+
+ // Verify the shape of the frame tree
+ EXPECT_EQ(2UL, root->child_count());
+ EXPECT_EQ(1UL, root->child_at(1)->child_count());
+
+ // Ask frame 4 to report the enabled state of the autoplay feature. Frame 3's
+ // policy should allow autoplay if created correctly, as it is same-origin
+ // with the root, where the feature is enabled by default, and therefore
+ // should be able to delegate it to frame 4.
+ // This indirectly tests the replicated policy in frame 3: Because frame 4 is
+ // cross-origin to frame 3, it will use the proxy's replicated policy as the
+ // parent policy; otherwise we would just ask frame 3 to report its own state.
+ bool success = false;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractBool(root->child_at(1)->child_at(0),
+ "window.domAutomationController.send("
+ "document.policy.allowsFeature('autoplay'));",
+ &success));
+ EXPECT_TRUE(success);
+}
+
// Test harness that allows for "barrier" style delaying of requests matching
// certain paths. Call SetDelayedRequestsForPath to delay requests, then
// SetUpEmbeddedTestServer to register handlers and start the server.
@@ -9945,7 +10122,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
#if defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TestChildProcessImportance) {
- web_contents()->SetImportance(ChildProcessImportance::MODERATE);
+ web_contents()->SetMainFrameImportance(ChildProcessImportance::MODERATE);
// Construct root page with one child in different domain.
GURL main_url(embedded_test_server()->GetURL(
@@ -9955,25 +10132,26 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TestChildProcessImportance) {
ASSERT_EQ(1u, root->child_count());
FrameTreeNode* child = root->child_at(0);
- // Importance should survive initial navigation.
+ // Importance should survive initial navigation. Note importance only affect
+ // main frame, so sub frame process should remain NORMAL throughout.
EXPECT_EQ(ChildProcessImportance::MODERATE,
root->current_frame_host()->GetProcess()->GetEffectiveImportance());
EXPECT_EQ(
- ChildProcessImportance::MODERATE,
+ ChildProcessImportance::NORMAL,
child->current_frame_host()->GetProcess()->GetEffectiveImportance());
// Check setting importance.
- web_contents()->SetImportance(ChildProcessImportance::NORMAL);
+ web_contents()->SetMainFrameImportance(ChildProcessImportance::NORMAL);
EXPECT_EQ(ChildProcessImportance::NORMAL,
root->current_frame_host()->GetProcess()->GetEffectiveImportance());
EXPECT_EQ(
ChildProcessImportance::NORMAL,
child->current_frame_host()->GetProcess()->GetEffectiveImportance());
- web_contents()->SetImportance(ChildProcessImportance::IMPORTANT);
+ web_contents()->SetMainFrameImportance(ChildProcessImportance::IMPORTANT);
EXPECT_EQ(ChildProcessImportance::IMPORTANT,
root->current_frame_host()->GetProcess()->GetEffectiveImportance());
EXPECT_EQ(
- ChildProcessImportance::IMPORTANT,
+ ChildProcessImportance::NORMAL,
child->current_frame_host()->GetProcess()->GetEffectiveImportance());
// Check importance is maintained if child navigates to new domain.
@@ -9987,8 +10165,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TestChildProcessImportance) {
int new_child_process_id = child->current_frame_host()->GetProcess()->GetID();
EXPECT_NE(old_child_process_id, new_child_process_id);
EXPECT_EQ(
- ChildProcessImportance::IMPORTANT,
+ ChildProcessImportance::NORMAL,
child->current_frame_host()->GetProcess()->GetEffectiveImportance());
+ EXPECT_EQ(ChildProcessImportance::IMPORTANT,
+ root->current_frame_host()->GetProcess()->GetEffectiveImportance());
// Check importance is maintained if root navigates to new domain.
int old_root_process_id = root->current_frame_host()->GetProcess()->GetID();
@@ -10018,7 +10198,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, TestChildProcessImportance) {
EXPECT_EQ(ChildProcessImportance::IMPORTANT,
interstitial_process->GetEffectiveImportance());
- web_contents()->SetImportance(ChildProcessImportance::MODERATE);
+ web_contents()->SetMainFrameImportance(ChildProcessImportance::MODERATE);
EXPECT_EQ(ChildProcessImportance::MODERATE,
interstitial_process->GetEffectiveImportance());
}
@@ -10893,9 +11073,7 @@ class CommitMessageOrderReverser : public DidCommitProvisionalLoadInterceptor {
if (params->url == deferred_url_) {
std::move(deferred_url_triggered_action_).Run(render_frame_host);
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
- base::RunLoop nested_run_loop;
+ base::RunLoop nested_run_loop(base::RunLoop::Type::kNestableTasksAllowed);
nested_loop_quit_ = nested_run_loop.QuitClosure();
nested_run_loop.Run();
outer_run_loop.Quit();
@@ -11300,9 +11478,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FrameDepthTest) {
child0->current_frame_host()->GetRenderWidgetHost()->GetPriority();
// Same site instance as root.
EXPECT_EQ(0u, priority.frame_depth);
- EXPECT_EQ(
- 0u,
- child0->current_frame_host()->GetProcess()->GetFrameDepthForTesting());
+ EXPECT_EQ(0u, child0->current_frame_host()->GetProcess()->GetFrameDepth());
}
FrameTreeNode* child1 = root->child_at(1);
@@ -11323,9 +11499,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FrameDepthTest) {
grand_child->current_frame_host()->GetRenderWidgetHost()->GetPriority();
EXPECT_EQ(2u, priority.frame_depth);
// Same process as root
- EXPECT_EQ(0u, grand_child->current_frame_host()
- ->GetProcess()
- ->GetFrameDepthForTesting());
+ EXPECT_EQ(0u,
+ grand_child->current_frame_host()->GetProcess()->GetFrameDepth());
}
}
@@ -11349,13 +11524,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityFrameDepthTest) {
popup_root->current_frame_host()->GetProcess();
EXPECT_EQ(subframe_process, popup_process);
EXPECT_EQ(2, popup_process->VisibleClientCount());
- EXPECT_EQ(0u, popup_process->GetFrameDepthForTesting());
+ EXPECT_EQ(0u, popup_process->GetFrameDepth());
// Hide popup. Process should have one visible client and depth should be 1,
// since depth 0 popup is hidden.
new_shell->web_contents()->WasHidden();
EXPECT_EQ(1, popup_process->VisibleClientCount());
- EXPECT_EQ(1u, popup_process->GetFrameDepthForTesting());
+ EXPECT_EQ(1u, popup_process->GetFrameDepth());
// Navigate main page to same origin as popup in same BrowsingInstance,
// s main page should run in the same process as the popup. The depth on the
@@ -11369,19 +11544,19 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityFrameDepthTest) {
root->current_frame_host()->GetProcess();
EXPECT_EQ(new_root_process, popup_process);
EXPECT_EQ(1, popup_process->VisibleClientCount());
- EXPECT_EQ(0u, popup_process->GetFrameDepthForTesting());
+ EXPECT_EQ(0u, popup_process->GetFrameDepth());
// Go back on main page. Should go back to same state as before navigation.
TestNavigationObserver back_load_observer(shell()->web_contents());
shell()->web_contents()->GetController().GoBack();
back_load_observer.Wait();
EXPECT_EQ(1, popup_process->VisibleClientCount());
- EXPECT_EQ(1u, popup_process->GetFrameDepthForTesting());
+ EXPECT_EQ(1u, popup_process->GetFrameDepth());
// Unhide popup. Should go back to same state as before hide.
new_shell->web_contents()->WasShown();
EXPECT_EQ(2, popup_process->VisibleClientCount());
- EXPECT_EQ(0u, popup_process->GetFrameDepthForTesting());
+ EXPECT_EQ(0u, popup_process->GetFrameDepth());
}
// Ensure that after a main frame with an OOPIF is navigated cross-site, the
@@ -11495,6 +11670,38 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_TRUE(success);
}
+// Tests that the last committed URL is preserved on an RFH even after the RFH
+// goes into the pending deletion state.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ LastCommittedURLRetainedAfterSwapOut) {
+ // Navigate to a.com.
+ GURL start_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+ RenderFrameHostImpl* rfh = web_contents()->GetMainFrame();
+ EXPECT_EQ(start_url, rfh->GetLastCommittedURL());
+
+ // Disable the swapout ACK and the swapout timer.
+ scoped_refptr<SwapoutACKMessageFilter> filter = new SwapoutACKMessageFilter();
+ rfh->GetProcess()->AddFilter(filter.get());
+ rfh->DisableSwapOutTimerForTesting();
+
+ // Open a popup on a.com to keep the process alive.
+ OpenPopup(shell(), embedded_test_server()->GetURL("a.com", "/title2.html"),
+ "foo");
+
+ // Navigate cross-process to b.com.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("b.com", "/title3.html")));
+
+ // The old RFH should be pending deletion.
+ EXPECT_FALSE(rfh->is_active());
+ EXPECT_FALSE(rfh->IsCurrent());
+ EXPECT_NE(rfh, web_contents()->GetMainFrame());
+
+ // Check that it still has a valid last committed URL.
+ EXPECT_EQ(start_url, rfh->GetLastCommittedURL());
+}
+
// Class to monitor incoming FrameHostMsg_UpdateViewportIntersection messages.
class UpdateViewportIntersectionMessageFilter
: public content::BrowserMessageFilter {
@@ -11549,9 +11756,10 @@ class UpdateViewportIntersectionMessageFilter
// Tests that when a large OOPIF has been scaled, the compositor raster area
// sent from the embedder is correct.
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
// Temporarily disabled on Android because this doesn't account for browser
// control height or page scale factor.
+// Flaky on Mac. https://crbug.com/840314
#define MAYBE_ScaledIframeRasterSize DISABLED_ScaledframeRasterSize
#else
#define MAYBE_ScaledIframeRasterSize ScaledIframeRasterSize
@@ -11823,4 +12031,664 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_TRUE(success);
}
+class SitePerProcessBrowserTouchActionTest : public SitePerProcessBrowserTest {
+ public:
+ SitePerProcessBrowserTouchActionTest() = default;
+
+ // Returns the effective touch action for |rwhv_child| by dispatching a
+ // touch to it through |rwhv_root|. |rwhv_root| is the root frame containing
+ // |rwhv_child|. |rwhv_child| is the child (or indirect descendent) of
+ // |rwhv_root| to get the touch action of. |event_position| should be within
+ // |rwhv_child| in |rwhv_root|'s coordinate space.
+ cc::TouchAction GetEffectiveTouchActionForChild(
+ RenderWidgetHostInputEventRouter* router,
+ RenderWidgetHostViewBase* rwhv_root,
+ RenderWidgetHostViewBase* rwhv_child,
+ const gfx::Point& event_position) {
+ InputEventAckWaiter ack_observer(
+ rwhv_child->GetRenderWidgetHost(),
+ base::BindRepeating([](content::InputEventAckSource source,
+ content::InputEventAckState state,
+ const blink::WebInputEvent& event) {
+ return event.GetType() == blink::WebGestureEvent::kTouchStart ||
+ event.GetType() == blink::WebGestureEvent::kTouchMove ||
+ event.GetType() == blink::WebGestureEvent::kTouchEnd;
+ }));
+
+ // Send a touch start event to child to get the TAF filled with child
+ // frame's touch action.
+ ack_observer.Reset();
+ SyntheticWebTouchEvent touch_event;
+ int index = touch_event.PressPoint(event_position.x(), event_position.y());
+ router->RouteTouchEvent(rwhv_root, &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ ack_observer.Wait();
+ cc::TouchAction touch_action =
+ static_cast<RenderWidgetHostImpl*>(rwhv_child->GetRenderWidgetHost())
+ ->input_router()
+ ->AllowedTouchAction();
+
+ // Send a touch move and touch end to complete the sequence, this also
+ // avoids triggering DCHECKs when sending followup events.
+ ack_observer.Reset();
+ touch_event.MovePoint(index, 1, 1);
+ router->RouteTouchEvent(rwhv_root, &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ ack_observer.Wait();
+
+ ack_observer.Reset();
+ touch_event.ReleasePoint(index);
+ router->RouteTouchEvent(rwhv_root, &touch_event,
+ ui::LatencyInfo(ui::SourceEventType::TOUCH));
+ ack_observer.Wait();
+ return touch_action;
+ }
+
+ // Waits until the parent frame has had enough time to propagate the effective
+ // touch action to the child frame and the child frame has had enough time to
+ // process it.
+ void WaitForTouchActionUpdated(MainThreadFrameObserver* observer,
+ content::RenderFrameHost* child_frame) {
+ // Ensures that main frame has calculated the new effective touch action for
+ // child frames.
+ observer->Wait();
+ // Ensures that if a child frame is in progress we will wait until the next
+ // one.
+ WaitForChildFrameSurfaceReady(child_frame);
+ // This child frame should receive the effective touch action from parent
+ // (if the previous one didn't) and propagates it.
+ WaitForChildFrameSurfaceReady(child_frame);
+ observer->Wait();
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
+ EffectiveTouchActionPropagatesAcrossFrames) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* child = root->child_at(0);
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child->current_frame_host()->GetRenderWidgetHost()->GetView());
+ std::unique_ptr<MainThreadFrameObserver> observer(new MainThreadFrameObserver(
+ root->current_frame_host()->GetRenderWidgetHost()));
+ observer->Wait();
+
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ NavigateFrameToURL(child, b_url);
+
+ // Force the renderer to generate a new frame.
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.body.style.touchAction = 'none'"));
+ // Waits for the next frame.
+ WaitForChildFrameSurfaceReady(child->current_frame_host());
+
+ RenderWidgetHostViewChildFrame* child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ child->current_frame_host()->GetRenderWidgetHost()->GetView());
+ gfx::Point point_inside_child = ToFlooredPoint(
+ child_view->TransformPointToRootCoordSpaceF(gfx::PointF(+5.f, +5.f)));
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(web_contents())->GetInputEventRouter();
+
+ WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ // Gestures are filtered by the intersection of touch-action values of the
+ // touched element and all its ancestors up to the one that implements the
+ // gesture. Since iframe allows scrolling, touch action pan restrictions will
+ // not affect iframe's descendants, so we expect kTouchActionPan instead of
+ // kTouchActionAuto in iframe's child.
+ EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
+ point_inside_child));
+
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.body.style.touchAction = 'auto'"));
+ WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ EXPECT_EQ(cc::TouchAction::kTouchActionAuto,
+ GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
+ point_inside_child));
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
+ EffectiveTouchActionPropagatesAcrossNestedFrames) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* parent = root->child_at(0);
+ GURL b_url(embedded_test_server()->GetURL(
+ "b.com", "/frame_tree/page_with_iframe_in_div.html"));
+ NavigateFrameToURL(parent, b_url);
+
+ ASSERT_EQ(1U, parent->child_count());
+ EXPECT_EQ(
+ " Site A ------------ proxies for B C\n"
+ " +--Site B ------- proxies for A C\n"
+ " +--Site C -- proxies for A B\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/\n"
+ " C = http://bar.com/",
+ DepictFrameTree(root));
+
+ FrameTreeNode* child = root->child_at(0)->child_at(0);
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child->current_frame_host()->GetRenderWidgetHost()->GetView());
+ std::unique_ptr<MainThreadFrameObserver> observer(new MainThreadFrameObserver(
+ root->current_frame_host()->GetRenderWidgetHost()));
+ observer->Wait();
+
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.body.style.touchAction = 'none'"));
+
+ // Wait for child frame ready in order to get the correct point inside child.
+ WaitForChildFrameSurfaceReady(child->current_frame_host());
+ RenderWidgetHostViewChildFrame* child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ child->current_frame_host()->GetRenderWidgetHost()->GetView());
+ gfx::Point point_inside_child = ToFlooredPoint(
+ child_view->TransformPointToRootCoordSpaceF(gfx::PointF(+5.f, +5.f)));
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(web_contents())->GetInputEventRouter();
+
+ // Child should inherit effective touch action none from root.
+ WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
+ point_inside_child));
+
+ // Child should inherit effective touch action none from parent.
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.body.style.touchAction = 'auto'"));
+ EXPECT_TRUE(ExecuteScript(
+ parent,
+ "document.getElementById('parent-div').style.touchAction = 'none';"));
+ WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
+ point_inside_child));
+
+ // Child should inherit effective touch action auto from root and parent.
+ EXPECT_TRUE(ExecuteScript(
+ parent,
+ "document.getElementById('parent-div').style.touchAction = 'auto'"));
+ WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ EXPECT_EQ(cc::TouchAction::kTouchActionAuto,
+ GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
+ point_inside_child));
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTouchActionTest,
+ EffectiveTouchActionPropagatesWhenChildFrameNavigates) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* child = root->child_at(0);
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ NavigateFrameToURL(child, b_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root));
+
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child->current_frame_host()->GetRenderWidgetHost()->GetView());
+ std::unique_ptr<MainThreadFrameObserver> observer(new MainThreadFrameObserver(
+ root->current_frame_host()->GetRenderWidgetHost()));
+ observer->Wait();
+
+ EXPECT_TRUE(
+ ExecuteScript(shell(), "document.body.style.touchAction = 'none'"));
+
+ // Wait for child frame ready in order to get the correct point inside child.
+ WaitForChildFrameSurfaceReady(child->current_frame_host());
+ RenderWidgetHostViewChildFrame* child_view =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ child->current_frame_host()->GetRenderWidgetHost()->GetView());
+ gfx::Point point_inside_child = gfx::ToFlooredPoint(
+ child_view->TransformPointToRootCoordSpaceF(gfx::PointF(+5.f, +5.f)));
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(web_contents())->GetInputEventRouter();
+ // Child should inherit effective touch action none from root.
+ WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
+ point_inside_child));
+
+ // After navigation, child should still inherit effective touch action none
+ // from parent.
+ GURL new_url(embedded_test_server()->GetURL("c.com", "/title2.html"));
+ NavigateFrameToURL(child, new_url);
+ WaitForChildFrameSurfaceReady(child->current_frame_host());
+ rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ WaitForTouchActionUpdated(observer.get(), child->current_frame_host());
+ EXPECT_EQ(cc::TouchAction::kTouchActionPan,
+ GetEffectiveTouchActionForChild(router, rwhv_root, rwhv_child,
+ point_inside_child));
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ChildFrameCrashMetrics_KilledWhileVisible) {
+ // Set-up a frame tree that helps verify what the metrics tracks:
+ // 1) frames (12 frames are affected if B process gets killed) or
+ // 2) crashes (simply 1 crash if B process gets killed)?
+ // 3) widgets (10 b widgets and 1 c widget are affected if B is killed,
+ // but a sad frame will appear only in 9 widgets - this excludes
+ // widgets for the b,c(b) part of the frame tree) or
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(b,c(b)),b,b,b,b,b,b,b,b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Kill the child frame.
+ base::HistogramTester histograms;
+ RenderProcessHost* child_process =
+ root->child_at(0)->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ child_process->Shutdown(0);
+ crash_observer.Wait();
+
+ // Verify that the expected metrics got logged.
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.Visibility",
+ CrossProcessFrameConnector::CrashVisibility::kCrashedWhileVisible, 9);
+
+ // Hide and show the web contents and verify that no more metrics got logged.
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.Visibility",
+ CrossProcessFrameConnector::CrashVisibility::kCrashedWhileVisible, 9);
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ChildFrameCrashMetrics_KilledMainFrame) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(b(b,c)))"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Kill the main frame.
+ base::HistogramTester histograms;
+ RenderProcessHost* child_process = root->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ child_process->Shutdown(0);
+ crash_observer.Wait();
+
+ // Verify that no child frame metrics got logged.
+ histograms.ExpectTotalCount("Stability.ChildFrameCrash.Visibility", 0);
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ChildFrameCrashMetrics_KilledWhileHiddenThenShown) {
+ // Set-up a frame tree that helps verify what the metrics tracks:
+ // 1) frames (12 frames are affected if B process gets killed) or
+ // 2) widgets (10 b widgets and 1 c widget are affected if B is killed) or
+ // 3) crashes (1 crash if B process gets killed)?
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(b,c),b,b,b,b,b,b,b,b,b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Hide the web contents (UpdateWebContentsVisibility is called twice to avoid
+ // hitting the |!did_first_set_visible_| case).
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+
+ // Kill the subframe.
+ base::HistogramTester histograms;
+ RenderProcessHost* child_process =
+ root->child_at(0)->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ child_process->Shutdown(0);
+ crash_observer.Wait();
+
+ // Verify that no child frame metrics got logged (yet - while WebContents are
+ // hidden).
+ histograms.ExpectTotalCount("Stability.ChildFrameCrash.Visibility", 0);
+
+ // Show the web contents.
+ // and verify that the expected metrics got logged.
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.Visibility",
+ CrossProcessFrameConnector::CrashVisibility::kShownAfterCrashing, 10);
+
+ // Hide and show the web contents again and verify that no more metrics got
+ // logged.
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.Visibility",
+ CrossProcessFrameConnector::CrashVisibility::kShownAfterCrashing, 10);
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ChildFrameCrashMetrics_NeverShown) {
+ // Set-up a frame tree that helps verify what the metrics tracks:
+ // 1) frames (12 frames are affected if B process gets killed) or
+ // 2) widgets (10 b widgets and 1 c widget are affected if B is killed) or
+ // 3) crashes (1 crash if B process gets killed)?
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(b,c),b,b,b,b,b,b,b,b,b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Hide the web contents (UpdateWebContentsVisibility is called twice to avoid
+ // hitting the |!did_first_set_visible_| case).
+ web_contents()->UpdateWebContentsVisibility(Visibility::VISIBLE);
+ web_contents()->UpdateWebContentsVisibility(Visibility::HIDDEN);
+
+ // Kill the subframe.
+ base::HistogramTester histograms;
+ RenderProcessHost* child_process =
+ root->child_at(0)->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ child_process->Shutdown(0);
+ crash_observer.Wait();
+
+ // Navigate away - this will trigger logging of the UMA.
+ EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.Visibility",
+ CrossProcessFrameConnector::CrashVisibility::kNeverVisibleAfterCrash, 10);
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ChildFrameCrashMetrics_ScrolledIntoView) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Fill the main frame so that the subframe is pushed below the fold (is
+ // scrolled outside of the current view) and wait until the main frame redraws
+ // itself (i.e. making sure CPFC::OnUpdateViewportIntersection has arrived).
+ std::string filling_script = R"(
+ var frame = document.body.querySelectorAll("iframe")[0];
+ for (var i = 0; i < 100; i++) {
+ var p = document.createElement("p");
+ p.innerText = "blah";
+ document.body.insertBefore(p, frame);
+ }
+ )";
+ EXPECT_TRUE(ExecuteScript(root, filling_script));
+ MainThreadFrameObserver main_widget_observer(
+ root->current_frame_host()->GetRenderWidgetHost());
+ main_widget_observer.Wait();
+
+ // Kill the child frame.
+ base::HistogramTester histograms;
+ RenderProcessHost* child_process =
+ root->child_at(0)->current_frame_host()->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ child_process->Shutdown(0);
+ crash_observer.Wait();
+
+ // Verify that no child frame metrics got logged (yet - while the subframe is
+ // below the fold / is not scrolled into view).
+ histograms.ExpectTotalCount("Stability.ChildFrameCrash.Visibility", 0);
+
+ // Scroll the subframe into view and wait until the scrolled frame draws
+ // itself.
+ std::string scrolling_script = R"(
+ var frame = document.body.querySelectorAll("iframe")[0];
+ frame.scrollIntoView();
+ )";
+ EXPECT_TRUE(ExecuteScript(root, scrolling_script));
+ main_widget_observer.Wait();
+
+ // Verify that the expected metrics got logged.
+ histograms.ExpectUniqueSample(
+ "Stability.ChildFrameCrash.Visibility",
+ CrossProcessFrameConnector::CrashVisibility::kShownAfterCrashing, 1);
+}
+
+// Check that when a frame changes a subframe's size twice and then sends a
+// postMessage to the subframe, the subframe's onmessage handler sees the new
+// size. In particular, ensure that the postMessage won't get reordered with
+// the second resize, which might be throttled if the first resize is still in
+// progress. See https://crbug.com/828529.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ResizeAndCrossProcessPostMessagePreserveOrder) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Add an onmessage handler to the subframe to send back its width.
+ EXPECT_TRUE(ExecuteScript(root->child_at(0), R"(
+ window.addEventListener('message', function(event) {
+ domAutomationController.send(document.body.clientWidth);
+ });)"));
+
+ // Drop the visual properties ACKs from the child renderer. To do this,
+ // unsubscribe the child's RenderWidgetHost from its
+ // RenderFrameMetadataProvider, which ensures that
+ // DidUpdateVisualProperties() won't be called on it, and the ACK won't be
+ // reset. This simulates that the ACK for the first resize below does not
+ // arrive before the second resize IPC arrives from the
+ // parent, and that the second resize IPC early-exits in
+ // SynchronizeVisualProperties() due to the pending visual properties ACK.
+ RenderWidgetHostImpl* rwh =
+ root->child_at(0)->current_frame_host()->GetRenderWidgetHost();
+ rwh->render_frame_metadata_provider_.RemoveObserver(rwh);
+
+ // Now, resize the subframe twice from the main frame and send it a
+ // postMessage. The postMessage handler should see the second updated size.
+ int width = 0;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(root, R"(
+ var f = document.querySelector('iframe');
+ f.width = 500;
+ f.offsetTop; // force layout; this sends a resize IPC for width of 500.
+ f.width = 700;
+ f.offsetTop; // force layout; this sends a resize IPC for width of 700.
+ f.contentWindow.postMessage('foo', '*');)", &width));
+ EXPECT_EQ(width, 700);
+}
+
+class SitePerProcessAndProcessPerSiteBrowserTest
+ : public SitePerProcessBrowserTest {
+ public:
+ SitePerProcessAndProcessPerSiteBrowserTest() {}
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ SitePerProcessBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kProcessPerSite);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SitePerProcessAndProcessPerSiteBrowserTest);
+};
+
+// Verify that when --site-per-process is combined with --process-per-site, a
+// cross-site, browser-initiated navigation with a generated page transition
+// does not stay in the old SiteInstance. See https://crbug.com/825411.
+IN_PROC_BROWSER_TEST_F(SitePerProcessAndProcessPerSiteBrowserTest,
+ GeneratedTransitionsSwapProcesses) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("foo.com", "/title1.html")));
+ scoped_refptr<SiteInstance> foo_site_instance(
+ web_contents()->GetSiteInstance());
+
+ // Navigate cross-site via a generated transition. This would normally
+ // happen for search queries.
+ TestNavigationObserver observer(web_contents());
+ NavigationController::LoadURLParams params(
+ embedded_test_server()->GetURL("bar.com", "/title2.html"));
+ params.transition_type = ui::PAGE_TRANSITION_GENERATED;
+ web_contents()->GetController().LoadURLWithParams(params);
+ observer.Wait();
+
+ // Ensure the original SiteInstance wasn't reused.
+ EXPECT_NE(foo_site_instance, web_contents()->GetSiteInstance());
+
+ // Ensure the new page can access cookies without getting killed.
+ EXPECT_TRUE(ExecuteScript(web_contents(), "document.cookie = 'foo=bar';"));
+ std::string cookie;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ web_contents(), "window.domAutomationController.send(document.cookie);",
+ &cookie));
+ EXPECT_EQ("foo=bar", cookie);
+}
+
+namespace {
+
+// Helper for waiting until next same-document navigation commits in
+// |web_contents|.
+class SameDocumentCommitObserver : public WebContentsObserver {
+ public:
+ SameDocumentCommitObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ message_loop_runner_(new MessageLoopRunner) {
+ EXPECT_TRUE(web_contents);
+ }
+
+ void Wait() { message_loop_runner_->Run(); }
+
+ const GURL& last_committed_url() { return last_committed_url_; }
+
+ private:
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ if (navigation_handle->IsSameDocument()) {
+ last_committed_url_ = navigation_handle->GetURL();
+ message_loop_runner_->Quit();
+ }
+ }
+
+ GURL last_committed_url_;
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(SameDocumentCommitObserver);
+};
+
+} // namespace
+
+// Ensure that a same-document navigation does not cancel an ongoing
+// cross-process navigation. See https://crbug.com/825677.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ ReplaceStateDoesNotCancelCrossSiteNavigation) {
+ GURL url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Give the page a beforeunload handler that does a replaceState. Do this
+ // from setTimeout so that the navigation that triggers beforeunload is
+ // already started when the replaceState happens.
+ EXPECT_TRUE(ExecuteScript(root,
+ "window.onbeforeunload = function (e) {"
+ " setTimeout(() => {"
+ " history.replaceState({}, 'footitle', 'foo');"
+ " }, 0);"
+ "};\n"));
+
+ GURL url2 = embedded_test_server()->GetURL("b.com", "/title1.html");
+ TestNavigationManager cross_site_navigation(web_contents(), url2);
+ SameDocumentCommitObserver replace_state_observer(web_contents());
+
+ // Start a cross-site navigation. Using a renderer-initiated navigation
+ // rather than a browser-initiated one is important here, since
+ // https://crbug.com/825677 was triggered only when replaceState ran while
+ // having a user gesture, which will be the case here since ExecuteScript
+ // runs with a user gesture.
+ EXPECT_TRUE(ExecuteScript(root, "location.href = '" + url2.spec() + "';"));
+ EXPECT_TRUE(cross_site_navigation.WaitForRequestStart());
+
+ // Now wait for the replaceState to commit while the cross-process navigation
+ // is paused.
+ replace_state_observer.Wait();
+ GURL replace_state_url = embedded_test_server()->GetURL("a.com", "/foo");
+ EXPECT_EQ(replace_state_url, replace_state_observer.last_committed_url());
+
+ // The cross-process navigation should not be canceled after the
+ // replaceState.
+ ASSERT_TRUE(root->IsLoading());
+ ASSERT_TRUE(root->navigation_request());
+
+ // Resume and finish the cross-process navigation.
+ cross_site_navigation.ResumeNavigation();
+ cross_site_navigation.WaitForNavigationFinished();
+ EXPECT_TRUE(cross_site_navigation.was_successful());
+ EXPECT_EQ(url2, web_contents()->GetLastCommittedURL());
+}
+
+// Test that a pending frame policy, such as an updated sandbox attribute, does
+// not take effect after a same-document navigation. See
+// https://crbug.com/849311.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SameDocumentNavigationDoesNotCommitPendingFramePolicy) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* subframe = root->child_at(0);
+
+ // The subframe should not be sandboxed.
+ EXPECT_EQ(blink::WebSandboxFlags::kNone,
+ subframe->pending_frame_policy().sandbox_flags);
+ EXPECT_EQ(blink::WebSandboxFlags::kNone,
+ subframe->effective_frame_policy().sandbox_flags);
+
+ // Set the "sandbox" attribute on the subframe; pending policy should update.
+ EXPECT_TRUE(ExecuteScript(
+ root, "document.querySelector('iframe').sandbox = 'allow-scripts';"));
+ // "allow-scripts" resets both SandboxFlags::Scripts and
+ // SandboxFlags::AutomaticFeatures bits per blink::ParseSandboxPolicy().
+ blink::WebSandboxFlags expected_flags =
+ blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
+ ~blink::WebSandboxFlags::kAutomaticFeatures;
+ EXPECT_EQ(expected_flags, subframe->pending_frame_policy().sandbox_flags);
+ EXPECT_EQ(blink::WebSandboxFlags::kNone,
+ subframe->effective_frame_policy().sandbox_flags);
+
+ // Commit a same-document navigation with replaceState. The new sandbox
+ // flags should still be pending but not effective.
+ SameDocumentCommitObserver replace_state_observer(web_contents());
+ EXPECT_TRUE(
+ ExecuteScript(subframe, "history.replaceState({}, 'footitle', 'foo');"));
+ replace_state_observer.Wait();
+
+ EXPECT_EQ(expected_flags, subframe->pending_frame_policy().sandbox_flags);
+ EXPECT_EQ(blink::WebSandboxFlags::kNone,
+ subframe->effective_frame_policy().sandbox_flags);
+
+ // Also try a same-document navigation to a fragment, which also shouldn't
+ // commit the pending sandbox flags.
+ GURL fragment_url = GURL(subframe->current_url().spec() + "#foo");
+ {
+ SameDocumentCommitObserver fragment_observer(web_contents());
+ EXPECT_TRUE(ExecuteScript(
+ subframe, "location.href=\"" + fragment_url.spec() + "\";"));
+ fragment_observer.Wait();
+ EXPECT_EQ(fragment_url, subframe->current_url());
+ }
+
+ EXPECT_EQ(expected_flags, subframe->pending_frame_policy().sandbox_flags);
+ EXPECT_EQ(blink::WebSandboxFlags::kNone,
+ subframe->effective_frame_policy().sandbox_flags);
+}
+
} // namespace content
diff --git a/chromium/content/browser/site_per_process_hit_test_browsertest.cc b/chromium/content/browser/site_per_process_hit_test_browsertest.cc
index f758815ac57..9884d624e54 100644
--- a/chromium/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/chromium/content/browser/site_per_process_hit_test_browsertest.cc
@@ -16,6 +16,7 @@
#include "components/viz/common/features.h"
#include "content/browser/renderer_host/cursor_manager.h"
#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
+#include "content/browser/renderer_host/input/touch_emulator.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/common/frame_messages.h"
@@ -34,6 +35,7 @@
#include "ui/display/display_switches.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#if defined(USE_AURA)
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
@@ -469,6 +471,68 @@ bool ConvertJSONToRect(const std::string& str, gfx::Rect* rect) {
}
#endif // defined(USE_AURA)
+// Class for intercepting SetMouseCapture messages being sent to a
+// RenderWidgetHost. Note that this only works for RenderWidgetHosts that
+// are attached to RenderFrameHosts, and not those for page popups, which
+// use different bindings.
+class SetMouseCaptureInterceptor
+ : public base::RefCountedThreadSafe<SetMouseCaptureInterceptor>,
+ public mojom::WidgetInputHandlerHostInterceptorForTesting {
+ public:
+ SetMouseCaptureInterceptor(RenderWidgetHostImpl* host)
+ : msg_received_(false),
+ capturing_(false),
+ host_(host),
+ impl_(binding().SwapImplForTesting(this)) {}
+
+ bool Capturing() const { return capturing_; }
+
+ void Wait() {
+ DCHECK(!run_loop_);
+ if (msg_received_) {
+ msg_received_ = false;
+ return;
+ }
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ run_loop_.reset();
+ msg_received_ = false;
+ }
+
+ protected:
+ // mojom::WidgetInputHandlerHostInterceptorForTesting:
+ mojom::WidgetInputHandlerHost* GetForwardingInterface() override {
+ return impl_;
+ }
+ void SetMouseCapture(bool capturing) override {
+ capturing_ = capturing;
+ msg_received_ = true;
+ if (run_loop_)
+ run_loop_->Quit();
+ GetForwardingInterface()->SetMouseCapture(capturing);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<SetMouseCaptureInterceptor>;
+
+ ~SetMouseCaptureInterceptor() override {
+ binding().SwapImplForTesting(impl_);
+ }
+
+ mojo::Binding<mojom::WidgetInputHandlerHost>& binding() {
+ return static_cast<InputRouterImpl*>(host_->input_router())
+ ->frame_host_binding_for_testing();
+ }
+
+ std::unique_ptr<base::RunLoop> run_loop_;
+ bool msg_received_;
+ bool capturing_;
+ RenderWidgetHostImpl* host_;
+ mojom::WidgetInputHandlerHost* impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(SetMouseCaptureInterceptor);
+};
+
} // namespace
class SitePerProcessHitTestBrowserTest
@@ -485,6 +549,8 @@ class SitePerProcessHitTestBrowserTest
} else if (std::get<0>(GetParam()) == 2) {
feature_list_.InitAndEnableFeature(
features::kEnableVizHitTestSurfaceLayer);
+ } else {
+ feature_list_.InitAndDisableFeature(features::kEnableVizHitTestDrawQuad);
}
}
@@ -628,7 +694,7 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest,
parent_iframe_node->current_frame_host()
->GetRenderWidgetHost()
->GetView(),
- &nested_in_parent);
+ &nested_in_parent, viz::EventSource::MOUSE);
// Get original scroll position.
double div_scroll_top_start;
@@ -993,6 +1059,157 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
root_scroll_begin_observer.Wait();
}
+class SitePerProcessEmulatedTouchBrowserTest
+ : public SitePerProcessHitTestBrowserTest {
+ public:
+ enum TestType { ScrollBubbling, PinchGoesToMainFrame };
+
+ ~SitePerProcessEmulatedTouchBrowserTest() override {}
+
+ void RunTest(TestType test_type) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_frame.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* iframe_node = root->child_at(0);
+ GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(site_url, iframe_node->current_url());
+
+ RenderWidgetHostViewBase* root_rwhv =
+ static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* child_rwhv =
+ static_cast<RenderWidgetHostViewBase*>(iframe_node->current_frame_host()
+ ->GetRenderWidgetHost()
+ ->GetView());
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetInputEventRouter();
+
+ WaitForChildFrameSurfaceReady(iframe_node->current_frame_host());
+
+ auto expect_gesture_with_position = base::BindRepeating(
+ [](blink::WebInputEvent::Type expected_type,
+ const gfx::Point& expected_position, content::InputEventAckSource,
+ content::InputEventAckState, const blink::WebInputEvent& event) {
+ if (event.GetType() != expected_type)
+ return false;
+
+ const blink::WebGestureEvent& gesture_event =
+ static_cast<const blink::WebGestureEvent&>(event);
+ EXPECT_NEAR(expected_position.x(), gesture_event.PositionInWidget().x,
+ 1);
+ EXPECT_NEAR(expected_position.y(), gesture_event.PositionInWidget().y,
+ 1);
+ EXPECT_EQ(blink::kWebGestureDeviceTouchscreen,
+ gesture_event.SourceDevice());
+ return true;
+ });
+
+ blink::WebInputEvent::Type expected_gesture_type;
+ switch (test_type) {
+ case ScrollBubbling:
+ expected_gesture_type = blink::WebInputEvent::kGestureScrollBegin;
+ break;
+ case PinchGoesToMainFrame:
+ expected_gesture_type = blink::WebInputEvent::kGesturePinchBegin;
+ break;
+ default:
+ ASSERT_TRUE(false);
+ }
+
+ gfx::Point position_in_child(5, 5);
+ InputEventAckWaiter child_gesture_event_observer(
+ child_rwhv->GetRenderWidgetHost(),
+ base::BindRepeating(expect_gesture_with_position, expected_gesture_type,
+ position_in_child));
+
+ gfx::Point position_in_root =
+ child_rwhv->TransformPointToRootCoordSpace(position_in_child);
+ InputEventAckWaiter root_gesture_event_observer(
+ root_rwhv->GetRenderWidgetHost(),
+ base::BindRepeating(expect_gesture_with_position, expected_gesture_type,
+ position_in_root));
+
+ // Enable touch emulation.
+ auto* touch_emulator = router->GetTouchEmulator();
+ ASSERT_TRUE(touch_emulator);
+ touch_emulator->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse,
+ ui::GestureProviderConfigType::CURRENT_PLATFORM);
+
+ // Create mouse events to emulate touch scroll. Since the page has no touch
+ // handlers, these events will be converted into a gesture scroll sequence.
+ base::TimeTicks simulated_event_time = ui::EventTimeForNow();
+ base::TimeDelta simulated_event_time_delta =
+ base::TimeDelta::FromMilliseconds(100);
+ blink::WebMouseEvent mouse_move_event =
+ SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::kMouseMove,
+ position_in_root.x(),
+ position_in_root.y(), 0);
+ mouse_move_event.SetTimeStamp(simulated_event_time);
+
+ int mouse_modifier = (test_type == PinchGoesToMainFrame)
+ ? blink::WebInputEvent::kShiftKey
+ : 0;
+ mouse_modifier |= blink::WebInputEvent::kLeftButtonDown;
+ blink::WebMouseEvent mouse_down_event =
+ SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseDown, position_in_root.x(),
+ position_in_root.y(), mouse_modifier);
+ mouse_down_event.button = blink::WebMouseEvent::Button::kLeft;
+ simulated_event_time += simulated_event_time_delta;
+ mouse_down_event.SetTimeStamp(simulated_event_time);
+
+ blink::WebMouseEvent mouse_drag_event =
+ SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseMove, position_in_root.x(),
+ position_in_root.y() + 20, mouse_modifier);
+ simulated_event_time += simulated_event_time_delta;
+ mouse_drag_event.SetTimeStamp(simulated_event_time);
+ mouse_drag_event.button = blink::WebMouseEvent::Button::kLeft;
+
+ blink::WebMouseEvent mouse_up_event = SyntheticWebMouseEventBuilder::Build(
+ blink::WebInputEvent::kMouseUp, position_in_root.x(),
+ position_in_root.y() + 20, mouse_modifier);
+ mouse_up_event.button = blink::WebMouseEvent::Button::kLeft;
+ simulated_event_time += simulated_event_time_delta;
+ mouse_up_event.SetTimeStamp(simulated_event_time);
+
+ // Send mouse events and wait for GesturePinchBegin.
+ router->RouteMouseEvent(root_rwhv, &mouse_move_event, ui::LatencyInfo());
+ router->RouteMouseEvent(root_rwhv, &mouse_down_event, ui::LatencyInfo());
+ router->RouteMouseEvent(root_rwhv, &mouse_drag_event, ui::LatencyInfo());
+ router->RouteMouseEvent(root_rwhv, &mouse_up_event, ui::LatencyInfo());
+
+ if (test_type == ScrollBubbling) {
+ // Verify child receives GestureScrollBegin.
+ child_gesture_event_observer.Wait();
+ }
+
+ // Verify the root receives the GesturePinchBegin or GestureScrollBegin,
+ // depending on |test_type|.
+ root_gesture_event_observer.Wait();
+
+ // Shut down.
+ touch_emulator->Disable();
+ }
+};
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
+ EmulatedTouchScrollBubbles) {
+ RunTest(ScrollBubbling);
+}
+
+IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest,
+ EmulatedTouchPinchGoesToMainFrame) {
+ RunTest(PinchGoesToMainFrame);
+}
+
#if defined(USE_AURA) || defined(OS_ANDROID)
// When unconsumed scrolls in a child bubble to the root and start an
@@ -1001,6 +1218,14 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// overscroll gesture.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
RootConsumesScrollDuringOverscrollGesture) {
+#if defined(OS_ANDROID)
+ // TODO(835058): Fix flakiness on android with viz hit testing.
+ if (features::IsVizHitTestingEnabled()) {
+ LOG(INFO) << "Skipping test due to https://crbug.com/835058";
+ return;
+ }
+#endif
+
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1207,7 +1432,15 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
// results in a scroll. This is only handled by RenderWidgetHostViewAura
// and is needed for trackpad scrolling on Chromebooks.
#if defined(USE_AURA)
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, ScrollEventToOOPIF) {
+
+#if defined(THREAD_SANITIZER)
+// Flaky: https://crbug.com/833380
+#define MAYBE_ScrollEventToOOPIF DISABLED_ScrollEventToOOPIF
+#else
+#define MAYBE_ScrollEventToOOPIF ScrollEventToOOPIF
+#endif
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ MAYBE_ScrollEventToOOPIF) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1252,8 +1485,17 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, ScrollEventToOOPIF) {
EXPECT_EQ(child_frame_monitor.EventType(), blink::WebInputEvent::kMouseWheel);
}
+#if defined(THREAD_SANITIZER)
+// Flaky: https://crbug.com/833380
+#define MAYBE_InputEventRouterWheelCoalesceTest \
+ DISABLED_InputEventRouterWheelCoalesceTest
+#else
+#define MAYBE_InputEventRouterWheelCoalesceTest \
+ InputEventRouterWheelCoalesceTest
+#endif
+
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- InputEventRouterWheelCoalesceTest) {
+ MAYBE_InputEventRouterWheelCoalesceTest) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1351,13 +1593,19 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
}
// Same test as above, but runs in high-dpi mode.
+// NOTE: This has to be renamed from SurfaceHitTestTest to
+// HighDPISurfaceHitTestTest. Otherwise MAYBE_SurfaceHitTestTest gets #defined
+// twice.
#if defined(OS_ANDROID) || defined(OS_WIN)
// High DPI browser tests are not needed on Android, and confuse some of the
// coordinate calculations. Android uses fixed device scale factor.
// Windows is disabled because of https://crbug.com/545547.
-#define MAYBE_HighDPISurfaceHitTestTest DISABLED_SurfaceHitTestTest
+#define MAYBE_HighDPISurfaceHitTestTest DISABLED_HighDPISurfaceHitTestTest
+#elif defined(THREAD_SANITIZER)
+// Flaky: https://crbug.com/833380
+#define MAYBE_HighDPISurfaceHitTestTest DISABLED_HighDPISurfaceHitTestTest
#else
-#define MAYBE_HighDPISurfaceHitTestTest SurfaceHitTestTest
+#define MAYBE_HighDPISurfaceHitTestTest HighDPISurfaceHitTestTest
#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
MAYBE_HighDPISurfaceHitTestTest) {
@@ -1381,27 +1629,46 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
OverlapSurfaceHitTestHelper(shell(), embedded_test_server());
}
+#if defined(OS_LINUX)
+// Flaky timeouts and failures: https://crbug.com/833380
+#define MAYBE_OverlapSurfaceHitTestTest DISABLED_OverlapSurfaceHitTestTest
+#else
+#define MAYBE_OverlapSurfaceHitTestTest OverlapSurfaceHitTestTest
+#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- OverlapSurfaceHitTestTest) {
+ MAYBE_OverlapSurfaceHitTestTest) {
OverlapSurfaceHitTestHelper(shell(), embedded_test_server());
}
+#if defined(OS_LINUX)
+// Flaky timeouts and failures: https://crbug.com/833380
+#define MAYBE_HitTestLayerSquashing DISABLED_HitTestLayerSquashing
+#else
+#define MAYBE_HitTestLayerSquashing HitTestLayerSquashing
+#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- HitTestLayerSquashing) {
+ MAYBE_HitTestLayerSquashing) {
HitTestLayerSquashing(shell(), embedded_test_server());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- HitTestLayerSquashing) {
+ MAYBE_HitTestLayerSquashing) {
HitTestLayerSquashing(shell(), embedded_test_server());
}
-IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestWatermark) {
+#if defined(OS_LINUX)
+// Flaky timeouts and failures: https://crbug.com/833380
+#define MAYBE_HitTestWatermark DISABLED_HitTestWatermark
+#else
+#define MAYBE_HitTestWatermark HitTestWatermark
+#endif
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ MAYBE_HitTestWatermark) {
HitTestWatermark(shell(), embedded_test_server());
}
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- HitTestWatermark) {
+ MAYBE_HitTestWatermark) {
HitTestWatermark(shell(), embedded_test_server());
}
@@ -1478,10 +1745,18 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_EQ(result.target_location.value(), parent_location);
}
+#if defined(THREAD_SANITIZER)
+// Flaky: https://crbug.com/833380
+#define MAYBE_SurfaceHitTestPointerEventsNone \
+ DISABLED_SurfaceHitTestPointerEventsNone
+#else
+#define MAYBE_SurfaceHitTestPointerEventsNone SurfaceHitTestPointerEventsNone
+#endif
+
// This test tests that browser process hittesting ignores frames with
// pointer-events: none.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- SurfaceHitTestPointerEventsNone) {
+ MAYBE_SurfaceHitTestPointerEventsNone) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_frame_pointer-events_none.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1718,6 +1993,109 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
}
#endif // !defined(OS_ANDROID)
+#if defined(OS_ANDROID)
+// The following test ensures that we don't get a crash if a tooltip is
+// triggered on Android. This test is nearly identical to
+// SitePerProcessHitTestBrowserTest.CrossProcessTooltipTestAndroid, except
+// it omits the tooltip monitor, and all dereferences of GetCursorManager().
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
+ CrossProcessTooltipTestAndroid) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root));
+
+ FrameTreeNode* b_node = root->child_at(0);
+
+ RenderWidgetHostViewBase* rwhv_a = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_b = static_cast<RenderWidgetHostViewBase*>(
+ b_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ // On Android we don't expect GetCursorManager() to return anything other
+ // than nullptr. If it did, this test would be unnecessary.
+ DCHECK(!rwhv_a->GetCursorManager());
+
+ WaitForChildFrameSurfaceReady(b_node->current_frame_host());
+
+ // Make sure the point_in_a_frame value is outside the default 8px margin
+ // for the body element.
+ gfx::Point point_in_a_frame(10, 10);
+ gfx::Point point_in_b_frame =
+ rwhv_b->TransformPointToRootCoordSpace(gfx::Point(25, 25));
+
+ // Create listeners for mouse events. These are used to verify that the
+ // RenderWidgetHostInputEventRouter is generating MouseLeave, etc for
+ // the right renderers.
+ RenderWidgetHostMouseEventMonitor a_frame_monitor(
+ root->current_frame_host()->GetRenderWidgetHost());
+ RenderWidgetHostMouseEventMonitor b_frame_monitor(
+ b_node->current_frame_host()->GetRenderWidgetHost());
+
+ // Add tooltip text to both the body and the iframe in A.
+ std::string script_a =
+ "body = document.body.setAttribute('title', 'body_a_tooltip');\n"
+ "iframe = document.getElementsByTagName('iframe')[0];\n"
+ "iframe.setAttribute('title','iframe_for_b');";
+ EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script_a));
+ std::string script_b =
+ "body = document.body.setAttribute('title', 'body_b_tooltip');";
+ EXPECT_TRUE(ExecuteScript(b_node->current_frame_host(), script_b));
+
+ // Send mouse events to both A and B.
+ blink::WebMouseEvent mouse_event(
+ blink::WebInputEvent::kMouseMove, blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::GetStaticTimeStampForTests());
+ auto* router = web_contents()->GetInputEventRouter();
+
+ // Alternate mouse moves between main frame and the cross-process iframe to
+ // test that the tool tip in the iframe can override the one set by the main
+ // frame renderer, even on a second entry into the iframe.
+ gfx::Point current_point;
+ for (int iteration = 0; iteration < 2; ++iteration) {
+ // The following is a bit of a hack to prevent hitting the same
+ // position/node check in ChromeClient::SetToolTip().
+ current_point = point_in_a_frame;
+ current_point.Offset(iteration, iteration);
+ SetWebEventPositions(&mouse_event, current_point, rwhv_a);
+ RouteMouseEventAndWaitUntilDispatch(router, rwhv_a, rwhv_a, &mouse_event);
+ EXPECT_TRUE(a_frame_monitor.EventWasReceived());
+ a_frame_monitor.ResetEventReceived();
+ // B will receive a mouseLeave on all but the first iteration.
+ EXPECT_EQ(iteration != 0, b_frame_monitor.EventWasReceived());
+ b_frame_monitor.ResetEventReceived();
+
+ // Next send a MouseMove to B frame, and A should receive a MouseMove event.
+ current_point = point_in_b_frame;
+ current_point.Offset(iteration, iteration);
+ SetWebEventPositions(&mouse_event, current_point, rwhv_a);
+ RouteMouseEventAndWaitUntilDispatch(router, rwhv_a, rwhv_b, &mouse_event);
+ EXPECT_TRUE(a_frame_monitor.EventWasReceived());
+ EXPECT_EQ(a_frame_monitor.event().GetType(),
+ blink::WebInputEvent::kMouseMove);
+ a_frame_monitor.ResetEventReceived();
+ EXPECT_TRUE(b_frame_monitor.EventWasReceived());
+ b_frame_monitor.ResetEventReceived();
+ }
+
+ // This is an (arbitrary) delay to allow the test to crash if it's going to.
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), TestTimeouts::action_max_timeout());
+ run_loop.Run();
+}
+#endif // defined(OS_ANDROID)
+
// This test verifies that MouseEnter and MouseLeave events fire correctly
// when the mouse cursor moves between processes.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
@@ -1833,13 +2211,22 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_TRUE(d_frame_monitor.EventWasReceived());
}
+#if defined(OS_LINUX)
+// Flaky timeouts and failures: https://crbug.com/833380
+#define MAYBE_CrossProcessMouseCapture DISABLED_CrossProcessMouseCapture
+#else
+#define MAYBE_CrossProcessMouseCapture CrossProcessMouseCapture
+#endif
// Verify that mouse capture works on a RenderWidgetHostView level, so that
// dragging scroll bars and selecting text continues even when the mouse
// cursor crosses over cross-process frame boundaries.
+// TODO(kenrb): This currently only works for scrollbar dragging.
+// Other reasons for a node to capture mouse input need to be addressed. See
+// https://crbug.com/647378.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- CrossProcessMouseCapture) {
+ MAYBE_CrossProcessMouseCapture) {
GURL main_url(embedded_test_server()->GetURL(
- "/frame_tree/page_with_positioned_frame.html"));
+ "/frame_tree/page_with_large_scrollable_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
// It is safe to obtain the root frame tree node here, as it doesn't change.
@@ -1847,10 +2234,12 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
ASSERT_EQ(1U, root->child_count());
FrameTreeNode* child_node = root->child_at(0);
- GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
- EXPECT_EQ(site_url, child_node->current_url());
- EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
- child_node->current_frame_host()->GetSiteInstance());
+ ASSERT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://127.0.0.1/\n"
+ " B = http://baz.com/",
+ DepictFrameTree(root));
// Create listeners for mouse events.
RenderWidgetHostMouseEventMonitor main_frame_monitor(
@@ -1896,76 +2285,78 @@ IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
EXPECT_FALSE(main_frame_monitor.EventWasReceived());
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
- // Target MouseMove to main frame. This should still be routed to the
- // child frame because it is now capturing mouse input.
+ // Target MouseMove to main frame. This should be routed to the main frame
+ // because the child frame is not capturing input.
mouse_event.SetType(blink::WebInputEvent::kMouseMove);
mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
SetWebEventPositions(&mouse_event, gfx::Point(1, 1), root_view);
- // Note that this event is sent twice, with the monitors cleared after
- // the first time, because the first MouseMove to the child frame
- // causes a MouseMove to be sent to the main frame also, which we
- // need to ignore.
- router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
- main_frame_monitor.ResetEventReceived();
- child_frame_monitor.ResetEventReceived();
- SetWebEventPositions(&mouse_event, gfx::Point(1, 5), root_view);
- RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
&mouse_event);
- EXPECT_FALSE(main_frame_monitor.EventWasReceived());
- EXPECT_TRUE(child_frame_monitor.EventWasReceived());
-
- // A MouseUp to the child frame should cancel the mouse capture.
- mouse_event.SetType(blink::WebInputEvent::kMouseUp);
- mouse_event.SetModifiers(blink::WebInputEvent::kNoModifiers);
- SetWebEventPositions(&mouse_event,
- gfx::Point(child_frame_target_x, child_frame_target_y),
- root_view);
+ // Dispatch twice because the router generates an extra MouseLeave for the
+ // child frame.
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
&mouse_event);
- EXPECT_FALSE(main_frame_monitor.EventWasReceived());
- EXPECT_TRUE(child_frame_monitor.EventWasReceived());
-
- // Subsequent MouseMove events targeted to the main frame should be routed
- // to that frame.
- mouse_event.SetType(blink::WebInputEvent::kMouseMove);
- SetWebEventPositions(&mouse_event, gfx::Point(1, 10), root_view);
- // Sending the MouseMove twice for the same reason as above.
- router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
- main_frame_monitor.ResetEventReceived();
- child_frame_monitor.ResetEventReceived();
- SetWebEventPositions(&mouse_event, gfx::Point(1, 15), root_view);
- router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
-
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
EXPECT_FALSE(child_frame_monitor.EventWasReceived());
- // Target MouseDown to the main frame to cause it to capture input.
+// Targeting a scrollbar with a click doesn't work on Mac or Android.
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ scoped_refptr<SetMouseCaptureInterceptor> interceptor =
+ new SetMouseCaptureInterceptor(static_cast<RenderWidgetHostImpl*>(
+ root->current_frame_host()->GetRenderWidgetHost()));
+
+ // Now send a MouseDown to target the thumb part of the scroll bar, which
+ // should initiate mouse capture for the main frame.
mouse_event.SetType(blink::WebInputEvent::kMouseDown);
- SetWebEventPositions(&mouse_event, gfx::Point(1, 20), root_view);
- main_frame_monitor.ResetEventReceived();
- child_frame_monitor.ResetEventReceived();
+ SetWebEventPositions(&mouse_event, gfx::Point(100, 25), root_view);
router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
EXPECT_TRUE(main_frame_monitor.EventWasReceived());
- EXPECT_FALSE(child_frame_monitor.EventWasReceived());
- // Sending a MouseMove to the child frame should still result in the main
- // frame receiving the event.
+ // Wait for the mouse capture message.
+ interceptor->Wait();
+ EXPECT_TRUE(interceptor->Capturing());
+
+ // Yield the thread, in order to let the capture message be processed by its
+ // actual handler.
+ {
+ base::RunLoop loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ loop.QuitClosure());
+ loop.Run();
+ }
+
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+
+ // Now that the main frame is capturing, a MouseMove targeted to the child
+ // frame should be received by the main frame.
mouse_event.SetType(blink::WebInputEvent::kMouseMove);
- mouse_event.SetModifiers(blink::WebInputEvent::kLeftButtonDown);
SetWebEventPositions(&mouse_event,
gfx::Point(child_frame_target_x, child_frame_target_y),
root_view);
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
+ &mouse_event);
+ EXPECT_TRUE(main_frame_monitor.EventWasReceived());
+ EXPECT_FALSE(child_frame_monitor.EventWasReceived());
main_frame_monitor.ResetEventReceived();
child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
- EXPECT_TRUE(main_frame_monitor.EventWasReceived());
- EXPECT_FALSE(child_frame_monitor.EventWasReceived());
+ // A MouseUp sent anywhere should cancel the mouse capture.
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
+ SetWebEventPositions(&mouse_event,
+ gfx::Point(child_frame_target_x, child_frame_target_y),
+ root_view);
+ RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
+ &mouse_event);
+
+ interceptor->Wait();
+ EXPECT_FALSE(interceptor->Capturing());
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
}
// There are no cursors on Android.
@@ -2102,14 +2493,16 @@ void CursorUpdateReceivedFromCrossSiteIframeHelper(
} // namespace
+// Flaky: https://crbug.com/833380
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- CursorUpdateReceivedFromCrossSiteIframe) {
+ DISABLED_CursorUpdateReceivedFromCrossSiteIframe) {
CursorUpdateReceivedFromCrossSiteIframeHelper(shell(),
embedded_test_server());
}
+// Flaky: https://crbug.com/833380
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- CursorUpdateReceivedFromCrossSiteIframe) {
+ DISABLED_CursorUpdateReceivedFromCrossSiteIframe) {
CursorUpdateReceivedFromCrossSiteIframeHelper(shell(),
embedded_test_server());
}
@@ -2784,8 +3177,9 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
ui::EventTimeForNow(), 0, 1, 0, 1, 0, 1);
UpdateEventRootLocation(&fling_start, root_view_aura);
TestInputEventObserver target_monitor(expected_target->GetRenderWidgetHost());
- InputEventAckWaiter waiter(expected_target->GetRenderWidgetHost(),
- blink::WebInputEvent::kGestureFlingStart);
+ InputEventAckWaiter fling_start_waiter(
+ expected_target->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureFlingStart);
root_view_aura->OnScrollEvent(&fling_start);
// If the expected target is not the root, then we should be doing async
// targeting first. So event dispatch should not happen synchronously.
@@ -2793,11 +3187,17 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
// such cases.
if (root_view != expected_target)
EXPECT_FALSE(target_monitor.EventWasReceived());
- waiter.Wait();
+ fling_start_waiter.Wait();
EXPECT_TRUE(target_monitor.EventWasReceived());
EXPECT_EQ(expected_target, router_touchpad_gesture_target);
target_monitor.ResetEventsReceived();
+ // Send a GFC event, the fling_controller will process the GFC and stop the
+ // fling by generating a wheel event with phaseEnded. The
+ // mouse_wheel_event_queue will process the wheel event and generate a GSE.
+ InputEventAckWaiter gestrue_scroll_end_waiter(
+ expected_target->GetRenderWidgetHost(),
+ blink::WebInputEvent::kGestureScrollEnd);
ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, gesture_point,
ui::EventTimeForNow(), 0, 1, 0, 1, 0, 1);
UpdateEventRootLocation(&fling_cancel, root_view_aura);
@@ -2806,24 +3206,22 @@ void SendTouchpadFlingSequenceWithExpectedTarget(
EXPECT_TRUE(target_monitor.EventWasReceived());
EXPECT_EQ(target_monitor.EventType(),
blink::WebInputEvent::kGestureFlingCancel);
-
- if (root_view_aura->wheel_scroll_latching_enabled()) {
- blink::WebGestureEvent gesture_event(
- blink::WebGestureEvent::kGestureScrollEnd,
- blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests(),
- blink::kWebGestureDeviceTouchpad);
- gesture_event.SetPositionInWidget(gfx::PointF(gesture_point));
- expected_target->GetRenderWidgetHost()->ForwardGestureEvent(gesture_event);
- }
+ gestrue_scroll_end_waiter.Wait();
}
#endif // !defined(OS_WIN)
} // anonymous namespace
// Flaky, see https://crbug.com/823578
+#if defined(OS_WIN)
+#define MAYBE_InputEventRouterGestureTargetMapTest \
+ DISABLED_InputEventRouterGestureTargetMapTest
+#else
+#define MAYBE_InputEventRouterGestureTargetMapTest \
+ InputEventRouterGestureTargetMapTest
+#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- DISABLED_InputEventRouterGestureTargetMapTest) {
+ MAYBE_InputEventRouterGestureTargetMapTest) {
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_nested_frames.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2996,6 +3394,14 @@ IN_PROC_BROWSER_TEST_P(
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
InputEventRouterTouchpadGestureTargetTest) {
+#if defined(OS_WIN)
+ // TODO(838835): Flaky with viz hit testing
+ if (features::IsVizHitTestingEnabled()) {
+ LOG(INFO) << "Skipping test due to https://crbug.com/838835";
+ return;
+ }
+#endif
+
GURL main_url(embedded_test_server()->GetURL(
"/frame_tree/page_with_positioned_nested_frames.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -3166,25 +3572,29 @@ void CreateContextMenuTestHelper(
EXPECT_NEAR(point.y(), params.y, 2);
}
+#if defined(OS_ANDROID) || defined(OS_WIN)
+// High DPI tests don't work properly on Android, which has fixed scale factor.
+// Windows is disabled because of https://crbug.com/545547.
+#define MAYBE_CreateContextMenuTest DISABLED_CreateContextMenuTest
+#elif defined(THREAD_SANITIZER)
+// TSAN is flaky on both standard and High DPI: https://crbug.com/833380
+#define MAYBE_CreateContextMenuTest DISABLED_CreateContextMenuTest
+#else
+#define MAYBE_CreateContextMenuTest CreateContextMenuTest
+#endif
+
// Test that a mouse right-click to an out-of-process iframe causes a context
// menu to be generated with the correct screen position.
IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
- CreateContextMenuTest) {
+ MAYBE_CreateContextMenuTest) {
CreateContextMenuTestHelper(shell(), embedded_test_server());
}
// Test that a mouse right-click to an out-of-process iframe causes a context
// menu to be generated with the correct screen position on a screen with
// non-default scale factor.
-#if defined(OS_ANDROID) || defined(OS_WIN)
-// High DPI tests don't work properly on Android, which has fixed scale factor.
-// Windows is disabled because of https://crbug.com/545547.
-#define MAYBE_HighDPICreateContextMenuTest DISABLED_HighDPICreateContextMenuTest
-#else
-#define MAYBE_HighDPICreateContextMenuTest HighDPICreateContextMenuTest
-#endif
IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest,
- MAYBE_HighDPICreateContextMenuTest) {
+ MAYBE_CreateContextMenuTest) {
CreateContextMenuTestHelper(shell(), embedded_test_server());
}
@@ -3469,6 +3879,7 @@ class SitePerProcessGestureHitTestBrowserTest
ui::ET_GESTURE_SCROLL_BEGIN);
gesture_scroll_begin_details.set_device_type(
ui::GestureDeviceType::DEVICE_TOUCHSCREEN);
+ gesture_scroll_begin_details.set_touch_points(2);
ui::GestureEvent gesture_scroll_begin(
position.x(), position.y(), 0, ui::EventTimeForNow(),
gesture_scroll_begin_details, touch_pressed.unique_event_id());
@@ -3859,6 +4270,10 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */,
SitePerProcessNonIntegerScaleFactorHitTestBrowserTest,
testing::Combine(testing::ValuesIn(kHitTestOption),
testing::ValuesIn(kOneScale)));
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+ SitePerProcessEmulatedTouchBrowserTest,
+ testing::Combine(testing::ValuesIn(kHitTestOption),
+ testing::ValuesIn(kOneScale)));
#if defined(USE_AURA)
static const float kMultiScale[] = {1.f, 1.5f, 2.f};
diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/speech_recognition_browsertest.cc
index fc367e3d119..90bf96296dc 100644
--- a/chromium/content/browser/speech/speech_recognition_browsertest.cc
+++ b/chromium/content/browser/speech/speech_recognition_browsertest.cc
@@ -32,20 +32,98 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
-#include "media/audio/audio_system_impl.h"
-#include "media/audio/audio_thread_impl.h"
-#include "media/audio/mock_audio_manager.h"
-#include "media/audio/test_audio_input_controller_factory.h"
+#include "media/audio/audio_system.h"
+#include "media/base/audio_capturer_source.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::RunLoop;
+using CaptureCallback = media::AudioCapturerSource::CaptureCallback;
namespace content {
namespace {
+// TODO(https://crbug.com/841818) Use FakeSystemInfo instead.
+class MockAudioSystem : public media::AudioSystem {
+ public:
+ MockAudioSystem() = default;
+
+ // AudioSystem implementation.
+ void GetInputStreamParameters(const std::string& device_id,
+ OnAudioParamsCallback on_params_cb) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Posting callback to allow current SpeechRecognizerImpl dispatching event
+ // to complete before transitioning to the next FSM state.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::BindOnce(std::move(on_params_cb),
+ media::AudioParameters::UnavailableDeviceParams()));
+ }
+
+ MOCK_METHOD2(GetOutputStreamParameters,
+ void(const std::string& device_id,
+ OnAudioParamsCallback on_params_cb));
+ MOCK_METHOD1(HasInputDevices, void(OnBoolCallback on_has_devices_cb));
+ MOCK_METHOD1(HasOutputDevices, void(OnBoolCallback on_has_devices_cb));
+ MOCK_METHOD2(GetDeviceDescriptions,
+ void(bool for_input,
+ OnDeviceDescriptionsCallback on_descriptions_cp));
+ MOCK_METHOD2(GetAssociatedOutputDeviceID,
+ void(const std::string& input_device_id,
+ OnDeviceIdCallback on_device_id_cb));
+ MOCK_METHOD2(GetInputDeviceInfo,
+ void(const std::string& input_device_id,
+ OnInputDeviceInfoCallback on_input_device_info_cb));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockAudioSystem);
+};
+
+class MockCapturerSource : public media::AudioCapturerSource {
+ public:
+ using StartCallback =
+ base::OnceCallback<void(const media::AudioParameters& audio_parameters,
+ CaptureCallback* capture_callback)>;
+ using StopCallback = base::OnceCallback<void()>;
+
+ MockCapturerSource(StartCallback start_callback, StopCallback stop_callback) {
+ start_callback_ = std::move(start_callback);
+ stop_callback_ = std::move(stop_callback);
+ }
+
+ void Initialize(const media::AudioParameters& params,
+ CaptureCallback* callback) {
+ audio_parameters_ = params;
+ capture_callback_ = callback;
+ }
+
+ void Start() override {
+ std::move(start_callback_).Run(audio_parameters_, capture_callback_);
+ }
+
+ void Stop() override { std::move(stop_callback_).Run(); }
+
+ MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
+ MOCK_METHOD1(SetVolume, void(double volume));
+ MOCK_METHOD1(SetOutputDeviceForAec,
+ void(const std::string& output_device_id));
+
+ protected:
+ ~MockCapturerSource() override = default;
+
+ private:
+ StartCallback start_callback_;
+ StopCallback stop_callback_;
+ CaptureCallback* capture_callback_;
+ media::AudioParameters audio_parameters_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockCapturerSource);
+};
+
std::string MakeGoodResponse() {
proto::SpeechRecognitionEvent proto_event;
proto_event.set_status(proto::SpeechRecognitionEvent::STATUS_SUCCESS);
@@ -75,46 +153,14 @@ std::string MakeGoodResponse() {
} // namespace
-class SpeechRecognitionBrowserTest
- : public ContentBrowserTest,
- public media::TestAudioInputControllerDelegate {
+class SpeechRecognitionBrowserTest : public ContentBrowserTest {
public:
enum StreamingServerState {
kIdle,
- kTestAudioControllerOpened,
- kTestAudioControllerClosed,
+ kTestAudioCapturerSourceOpened,
+ kTestAudioCapturerSourceClosed,
};
- // media::TestAudioInputControllerDelegate methods.
- void TestAudioControllerOpened(
- media::TestAudioInputController* controller) override {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ASSERT_EQ(kIdle, streaming_server_state_);
- streaming_server_state_ = kTestAudioControllerOpened;
- const int capture_packet_interval_ms =
- (1000 * controller->audio_parameters().frames_per_buffer()) /
- controller->audio_parameters().sample_rate();
- ASSERT_EQ(SpeechRecognitionEngine::kAudioPacketIntervalMs,
- capture_packet_interval_ms);
- FeedAudioController(500 /* ms */, /*noise=*/ false);
- FeedAudioController(1000 /* ms */, /*noise=*/ true);
- FeedAudioController(1000 /* ms */, /*noise=*/ false);
- }
-
- void TestAudioControllerClosed(
- media::TestAudioInputController* controller) override {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ASSERT_EQ(kTestAudioControllerOpened, streaming_server_state_);
- streaming_server_state_ = kTestAudioControllerClosed;
-
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(&SpeechRecognitionBrowserTest::SendResponse,
- base::Unretained(this)));
- }
-
- void SendResponse() {}
-
// Helper methods used by test fixtures.
GURL GetTestUrlFromFragment(const std::string& fragment) {
return GURL(GetTestUrl("speech", "web_speech_recognition.html").spec() +
@@ -132,39 +178,67 @@ class SpeechRecognitionBrowserTest
protected:
// ContentBrowserTest methods.
void SetUpOnMainThread() override {
- test_audio_input_controller_factory_.set_delegate(this);
- media::AudioInputController::set_factory_for_testing(
- &test_audio_input_controller_factory_);
streaming_server_state_ = kIdle;
ASSERT_TRUE(SpeechRecognitionManagerImpl::GetInstance());
- media::AudioManager::StartHangMonitorIfNeeded(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
- audio_manager_ = std::make_unique<media::MockAudioManager>(
- std::make_unique<media::AudioThreadImpl>());
- audio_manager_->SetInputStreamParameters(
- media::AudioParameters::UnavailableDeviceParams());
- audio_system_ =
- std::make_unique<media::AudioSystemImpl>(audio_manager_.get());
- SpeechRecognizerImpl::SetAudioEnvironmentForTesting(audio_system_.get(),
- audio_manager_.get());
+ audio_system_ = std::make_unique<MockAudioSystem>();
+ audio_capturer_source_ = base::MakeRefCounted<MockCapturerSource>(
+ base::BindOnce(&SpeechRecognitionBrowserTest::OnCapturerSourceStart,
+ base::Unretained(this)),
+ base::BindOnce(&SpeechRecognitionBrowserTest::OnCapturerSourceStop,
+ base::Unretained(this)));
+ SpeechRecognizerImpl::SetAudioEnvironmentForTesting(
+ audio_system_.get(),
+ static_cast<media::AudioCapturerSource*>(audio_capturer_source_.get()));
}
void TearDownOnMainThread() override {
SpeechRecognizerImpl::SetAudioEnvironmentForTesting(nullptr, nullptr);
+ }
- audio_manager_->Shutdown();
+ private:
+ void OnCapturerSourceStart(const media::AudioParameters& audio_parameters,
+ CaptureCallback* capture_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ASSERT_EQ(kIdle, streaming_server_state_);
+ streaming_server_state_ = kTestAudioCapturerSourceOpened;
- test_audio_input_controller_factory_.set_delegate(nullptr);
+ const int capture_packet_interval_ms =
+ (1000 * audio_parameters.frames_per_buffer()) /
+ audio_parameters.sample_rate();
+ ASSERT_EQ(SpeechRecognitionEngine::kAudioPacketIntervalMs,
+ capture_packet_interval_ms);
+ FeedAudioCapturerSource(audio_parameters, capture_callback, 500 /* ms */,
+ /*noise=*/false);
+ FeedAudioCapturerSource(audio_parameters, capture_callback, 1000 /* ms */,
+ /*noise=*/true);
+ FeedAudioCapturerSource(audio_parameters, capture_callback, 1000 /* ms */,
+ /*noise=*/false);
}
- private:
- static void FeedSingleBufferToAudioController(
- scoped_refptr<media::TestAudioInputController> controller,
+ void OnCapturerSourceStop() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ASSERT_EQ(kTestAudioCapturerSourceOpened, streaming_server_state_);
+ streaming_server_state_ = kTestAudioCapturerSourceClosed;
+
+ // Reset capturer source so SpeechRecognizerImpl destructor doesn't call
+ // AudioCaptureSourcer::Stop() again.
+ SpeechRecognizerImpl::SetAudioEnvironmentForTesting(nullptr, nullptr);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SpeechRecognitionBrowserTest::SendResponse,
+ base::Unretained(this)));
+ }
+
+ void SendResponse() {}
+
+ static void FeedSingleBufferToAudioCapturerSource(
+ const media::AudioParameters& audio_params,
+ CaptureCallback* capture_callback,
size_t buffer_size,
bool fill_with_noise) {
- DCHECK(controller.get());
- const media::AudioParameters& audio_params = controller->audio_parameters();
+ DCHECK(capture_callback);
std::unique_ptr<uint8_t[]> audio_buffer(new uint8_t[buffer_size]);
if (fill_with_noise) {
for (size_t i = 0; i < buffer_size; ++i)
@@ -176,21 +250,19 @@ class SpeechRecognitionBrowserTest
std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(audio_params);
- audio_bus->FromInterleaved(&audio_buffer.get()[0],
- audio_bus->frames(),
- audio_params.bits_per_sample() / 8);
- controller->sync_writer()->Write(audio_bus.get(), 0.0, false,
- base::TimeTicks::Now());
+ audio_bus->FromInterleaved<media::SignedInt16SampleTypeTraits>(
+ reinterpret_cast<int16_t*>(&audio_buffer.get()[0]),
+ audio_bus->frames());
+ capture_callback->Capture(audio_bus.get(), 0, 0.0, false);
}
- void FeedAudioController(int duration_ms, bool feed_with_noise) {
- media::TestAudioInputController* controller =
- test_audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- const media::AudioParameters& audio_params = controller->audio_parameters();
- const size_t buffer_size = audio_params.GetBytesPerBuffer();
- const int ms_per_buffer = audio_params.frames_per_buffer() * 1000 /
- audio_params.sample_rate();
+ void FeedAudioCapturerSource(const media::AudioParameters& audio_params,
+ CaptureCallback* capture_callback,
+ int duration_ms,
+ bool feed_with_noise) {
+ const size_t buffer_size =
+ audio_params.GetBytesPerBuffer(media::kSampleFormatS16);
+ const int ms_per_buffer = audio_params.GetBufferDuration().InMilliseconds();
// We can only simulate durations that are integer multiples of the
// buffer size. In this regard see
// SpeechRecognitionEngine::GetDesiredAudioChunkDurationMs().
@@ -200,18 +272,14 @@ class SpeechRecognitionBrowserTest
for (int i = 0; i < n_buffers; ++i) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(
- &FeedSingleBufferToAudioController,
- scoped_refptr<media::TestAudioInputController>(controller),
- buffer_size, feed_with_noise));
+ base::BindOnce(&FeedSingleBufferToAudioCapturerSource, audio_params,
+ capture_callback, buffer_size, feed_with_noise));
}
}
- std::unique_ptr<media::MockAudioManager> audio_manager_;
std::unique_ptr<media::AudioSystem> audio_system_;
+ scoped_refptr<MockCapturerSource> audio_capturer_source_;
StreamingServerState streaming_server_state_;
-
- media::TestAudioInputControllerFactory test_audio_input_controller_factory_;
};
// Simply loads the test page and checks if it was able to create a Speech
@@ -274,7 +342,7 @@ IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, MAYBE_OneShotRecognition) {
navigation_observer.Wait();
- EXPECT_EQ(kTestAudioControllerClosed, streaming_server_state());
+ EXPECT_EQ(kTestAudioCapturerSourceClosed, streaming_server_state());
EXPECT_EQ("goodresult1", GetPageFragment());
// Remove reference to URL string that's on the stack.
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
index 1e34625f16b..410717dee0f 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -15,88 +15,85 @@
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/speech_recognition_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/speech_recognition_manager_delegate.h"
#include "content/public/browser/speech_recognition_session_config.h"
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/common/content_switches.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
namespace content {
SpeechRecognitionDispatcherHost::SpeechRecognitionDispatcherHost(
int render_process_id,
- net::URLRequestContextGetter* context_getter)
- : BrowserMessageFilter(SpeechRecognitionMsgStart),
- render_process_id_(render_process_id),
- context_getter_(context_getter),
+ int render_frame_id,
+ scoped_refptr<net::URLRequestContextGetter> context_getter)
+ : render_process_id_(render_process_id),
+ render_frame_id_(render_frame_id),
+ context_getter_(std::move(context_getter)),
weak_factory_(this) {
// Do not add any non-trivial initialization here, instead do it lazily when
// required (e.g. see the method |SpeechRecognitionManager::GetInstance()|) or
// add an Init() method.
}
-SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {
+// static
+void SpeechRecognitionDispatcherHost::Create(
+ int render_process_id,
+ int render_frame_id,
+ scoped_refptr<net::URLRequestContextGetter> context_getter,
+ mojom::SpeechRecognizerRequest request) {
+ mojo::MakeStrongBinding(
+ std::make_unique<SpeechRecognitionDispatcherHost>(
+ render_process_id, render_frame_id, std::move(context_getter)),
+ std::move(request));
}
+SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {}
+
base::WeakPtr<SpeechRecognitionDispatcherHost>
SpeechRecognitionDispatcherHost::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-void SpeechRecognitionDispatcherHost::OnDestruct() const {
- BrowserThread::DeleteOnIOThread::Destruct(this);
-}
-
-bool SpeechRecognitionDispatcherHost::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SpeechRecognitionDispatcherHost, message)
- IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StartRequest,
- OnStartRequest)
- IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortRequest,
- OnAbortRequest)
- IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_StopCaptureRequest,
- OnStopCaptureRequest)
- IPC_MESSAGE_HANDLER(SpeechRecognitionHostMsg_AbortAllRequests,
- OnAbortAllRequests)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void SpeechRecognitionDispatcherHost::OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) {
- if (message.type() == SpeechRecognitionHostMsg_StartRequest::ID)
- *thread = BrowserThread::UI;
-}
+// -------- mojom::SpeechRecognizer interface implementation ------------------
-void SpeechRecognitionDispatcherHost::OnChannelClosing() {
- weak_factory_.InvalidateWeakPtrs();
-}
-
-void SpeechRecognitionDispatcherHost::OnStartRequest(
- const SpeechRecognitionHostMsg_StartRequest_Params& params) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void SpeechRecognitionDispatcherHost::Start(
+ mojom::StartSpeechRecognitionRequestParamsPtr params) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Check that the origin specified by the renderer process is one
// that it is allowed to access.
- if (params.origin_url != "null" &&
+ if (!params->origin.unique() &&
!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
- render_process_id_, GURL(params.origin_url))) {
+ render_process_id_, params->origin.GetURL())) {
LOG(ERROR) << "SRDH::OnStartRequest, disallowed origin: "
- << params.origin_url;
+ << params->origin.Serialize();
return;
}
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&SpeechRecognitionDispatcherHost::StartRequestOnUI,
+ AsWeakPtr(), render_process_id_, render_frame_id_,
+ std::move(params)));
+}
+
+// static
+void SpeechRecognitionDispatcherHost::StartRequestOnUI(
+ base::WeakPtr<SpeechRecognitionDispatcherHost>
+ speech_recognition_dispatcher_host,
+ int render_process_id,
+ int render_frame_id,
+ mojom::StartSpeechRecognitionRequestParamsPtr params) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
int embedder_render_process_id = 0;
int embedder_render_frame_id = MSG_ROUTING_NONE;
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(WebContentsImpl::FromRenderFrameHostID(
- render_process_id_, params.render_frame_id));
+ render_process_id, render_frame_id));
if (!web_contents) {
// The render frame id is renderer-provided. If it's invalid, don't crash.
DLOG(ERROR) << "SRDH::OnStartRequest, invalid frame";
@@ -132,153 +129,127 @@ void SpeechRecognitionDispatcherHost::OnStartRequest(
bool filter_profanities =
SpeechRecognitionManagerImpl::GetInstance() &&
SpeechRecognitionManagerImpl::GetInstance()->delegate() &&
- SpeechRecognitionManagerImpl::GetInstance()->delegate()->
- FilterProfanities(render_process_id_);
-
- SpeechRecognitionSessionContext context;
- context.context_name = params.origin_url;
- context.render_process_id = render_process_id_;
- context.render_frame_id = params.render_frame_id;
- context.embedder_render_process_id = embedder_render_process_id;
- context.embedder_render_frame_id = embedder_render_frame_id;
- context.request_id = params.request_id;
+ SpeechRecognitionManagerImpl::GetInstance()
+ ->delegate()
+ ->FilterProfanities(embedder_render_process_id);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SpeechRecognitionDispatcherHost::StartSession,
- base::Unretained(this), params, context,
+ base::BindOnce(&SpeechRecognitionDispatcherHost::StartSessionOnIO,
+ speech_recognition_dispatcher_host, std::move(params),
+ embedder_render_process_id, embedder_render_frame_id,
filter_profanities));
}
-void SpeechRecognitionDispatcherHost::StartSession(
- const SpeechRecognitionHostMsg_StartRequest_Params& params,
- const SpeechRecognitionSessionContext& context,
+void SpeechRecognitionDispatcherHost::StartSessionOnIO(
+ mojom::StartSpeechRecognitionRequestParamsPtr params,
+ int embedder_render_process_id,
+ int embedder_render_frame_id,
bool filter_profanities) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ SpeechRecognitionSessionContext context;
+ context.security_origin = params->origin;
+ context.render_process_id = render_process_id_;
+ context.render_frame_id = render_frame_id_;
+ context.embedder_render_process_id = embedder_render_process_id;
+ context.embedder_render_frame_id = embedder_render_frame_id;
+
+ auto session =
+ std::make_unique<SpeechRecognitionSession>(std::move(params->client));
+
SpeechRecognitionSessionConfig config;
- config.language = params.language;
- config.grammars = params.grammars;
- config.max_hypotheses = params.max_hypotheses;
- config.origin_url = params.origin_url;
+ config.language = params->language;
+ config.max_hypotheses = params->max_hypotheses;
+ config.origin = params->origin;
config.initial_context = context;
config.url_request_context_getter = context_getter_.get();
config.filter_profanities = filter_profanities;
- config.continuous = params.continuous;
- config.interim_results = params.interim_results;
- config.event_listener = AsWeakPtr();
+ config.continuous = params->continuous;
+ config.interim_results = params->interim_results;
+ config.event_listener = session->AsWeakPtr();
- int session_id = SpeechRecognitionManager::GetInstance()->CreateSession(
- config);
+ for (mojom::SpeechRecognitionGrammarPtr& grammar_ptr : params->grammars) {
+ config.grammars.push_back(*grammar_ptr);
+ }
+
+ int session_id =
+ SpeechRecognitionManager::GetInstance()->CreateSession(config);
DCHECK_NE(session_id, SpeechRecognitionManager::kSessionIDInvalid);
+ session->SetSessionId(session_id);
+ mojo::MakeStrongBinding(std::move(session),
+ std::move(params->session_request));
+
SpeechRecognitionManager::GetInstance()->StartSession(session_id);
}
-void SpeechRecognitionDispatcherHost::OnAbortRequest(int render_frame_id,
- int request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
+// ---------------------- SpeechRecognizerSession -----------------------------
- int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
- render_process_id_, render_frame_id, request_id);
+SpeechRecognitionSession::SpeechRecognitionSession(
+ mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info)
+ : session_id_(SpeechRecognitionManager::kSessionIDInvalid),
+ client_(std::move(client_ptr_info)),
+ weak_factory_(this) {}
- // The renderer might provide an invalid |request_id| if the session was not
- // started as expected, e.g., due to unsatisfied security requirements.
- if (session_id != SpeechRecognitionManager::kSessionIDInvalid)
- SpeechRecognitionManager::GetInstance()->AbortSession(session_id);
-}
+SpeechRecognitionSession::~SpeechRecognitionSession() = default;
-void SpeechRecognitionDispatcherHost::OnAbortAllRequests(int render_frame_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- SpeechRecognitionManager::GetInstance()->AbortAllSessionsForRenderFrame(
- render_process_id_, render_frame_id);
+base::WeakPtr<SpeechRecognitionSession> SpeechRecognitionSession::AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
}
-void SpeechRecognitionDispatcherHost::OnStopCaptureRequest(int render_frame_id,
- int request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- int session_id = SpeechRecognitionManager::GetInstance()->GetSession(
- render_process_id_, render_frame_id, request_id);
+void SpeechRecognitionSession::Abort() {
+ SpeechRecognitionManager::GetInstance()->AbortSession(session_id_);
+}
- // The renderer might provide an invalid |request_id| if the session was not
- // started as expected, e.g., due to unsatisfied security requirements.
- if (session_id != SpeechRecognitionManager::kSessionIDInvalid) {
- SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
- session_id);
- }
+void SpeechRecognitionSession::StopCapture() {
+ SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
+ session_id_);
}
// -------- SpeechRecognitionEventListener interface implementation -----------
-void SpeechRecognitionDispatcherHost::OnRecognitionStart(int session_id) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_Started(context.render_frame_id,
- context.request_id));
+void SpeechRecognitionSession::OnRecognitionStart(int session_id) {
+ client_->Started();
}
-void SpeechRecognitionDispatcherHost::OnAudioStart(int session_id) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_AudioStarted(context.render_frame_id,
- context.request_id));
+void SpeechRecognitionSession::OnAudioStart(int session_id) {
+ client_->AudioStarted();
}
-void SpeechRecognitionDispatcherHost::OnSoundStart(int session_id) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_SoundStarted(context.render_frame_id,
- context.request_id));
+void SpeechRecognitionSession::OnSoundStart(int session_id) {
+ client_->SoundStarted();
}
-void SpeechRecognitionDispatcherHost::OnSoundEnd(int session_id) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_SoundEnded(context.render_frame_id,
- context.request_id));
+void SpeechRecognitionSession::OnSoundEnd(int session_id) {
+ client_->SoundEnded();
}
-void SpeechRecognitionDispatcherHost::OnAudioEnd(int session_id) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_AudioEnded(context.render_frame_id,
- context.request_id));
+void SpeechRecognitionSession::OnAudioEnd(int session_id) {
+ client_->AudioEnded();
}
-void SpeechRecognitionDispatcherHost::OnRecognitionEnd(int session_id) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_Ended(context.render_frame_id,
- context.request_id));
+void SpeechRecognitionSession::OnRecognitionEnd(int session_id) {
+ client_->Ended();
}
-void SpeechRecognitionDispatcherHost::OnRecognitionResults(
+void SpeechRecognitionSession::OnRecognitionResults(
int session_id,
const SpeechRecognitionResults& results) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_ResultRetrieved(context.render_frame_id,
- context.request_id, results));
+ client_->ResultRetrieved(results);
}
-void SpeechRecognitionDispatcherHost::OnRecognitionError(
+void SpeechRecognitionSession::OnRecognitionError(
int session_id,
const SpeechRecognitionError& error) {
- const SpeechRecognitionSessionContext& context =
- SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id);
- Send(new SpeechRecognitionMsg_ErrorOccurred(context.render_frame_id,
- context.request_id, error));
+ client_->ErrorOccurred(error);
}
// The events below are currently not used by speech JS APIs implementation.
-void SpeechRecognitionDispatcherHost::OnAudioLevelsChange(int session_id,
- float volume,
- float noise_volume) {
-}
+void SpeechRecognitionSession::OnAudioLevelsChange(int session_id,
+ float volume,
+ float noise_volume) {}
-void SpeechRecognitionDispatcherHost::OnEnvironmentEstimationComplete(
- int session_id) {
+void SpeechRecognitionSession::OnEnvironmentEstimationComplete(int session_id) {
}
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
index babf35dc9b4..bce40c3ad6d 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
@@ -10,32 +10,80 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "content/common/speech_recognizer.mojom.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/speech_recognition_event_listener.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "net/url_request/url_request_context_getter.h"
-struct SpeechRecognitionHostMsg_StartRequest_Params;
-
namespace content {
+class SpeechRecognitionSession;
class SpeechRecognitionManager;
-struct SpeechRecognitionSessionContext;
-// SpeechRecognitionDispatcherHost is a delegate for Speech API messages used by
-// RenderMessageFilter. Basically it acts as a proxy, relaying the events coming
-// from the SpeechRecognitionManager to IPC messages (and vice versa).
-// It's the complement of SpeechRecognitionDispatcher (owned by RenderFrame).
+// SpeechRecognitionDispatcherHost is an implementation of the SpeechRecognizer
+// interface that allows a RenderFrame to start a speech recognition session
+// in the browser process, by communicating with SpeechRecognitionManager.
class CONTENT_EXPORT SpeechRecognitionDispatcherHost
- : public BrowserMessageFilter,
- public SpeechRecognitionEventListener {
+ : public mojom::SpeechRecognizer {
public:
SpeechRecognitionDispatcherHost(
int render_process_id,
- net::URLRequestContextGetter* context_getter);
-
+ int render_frame_id,
+ scoped_refptr<net::URLRequestContextGetter> context_getter);
+ ~SpeechRecognitionDispatcherHost() override;
+ static void Create(int render_process_id,
+ int render_frame_id,
+ scoped_refptr<net::URLRequestContextGetter> context_getter,
+ mojom::SpeechRecognizerRequest request);
base::WeakPtr<SpeechRecognitionDispatcherHost> AsWeakPtr();
+ // mojom::SpeechRecognizer implementation
+ void Start(mojom::StartSpeechRecognitionRequestParamsPtr params) override;
+
+ private:
+ static void StartRequestOnUI(
+ base::WeakPtr<SpeechRecognitionDispatcherHost>
+ speech_recognition_dispatcher_host,
+ int render_process_id,
+ int render_frame_id,
+ mojom::StartSpeechRecognitionRequestParamsPtr params);
+ void StartSessionOnIO(mojom::StartSpeechRecognitionRequestParamsPtr params,
+ int embedder_render_process_id,
+ int embedder_render_frame_id,
+ bool filter_profanities);
+
+ const int render_process_id_;
+ const int render_frame_id_;
+ scoped_refptr<net::URLRequestContextGetter> context_getter_;
+
+ // Used for posting asynchronous tasks (on the IO thread) without worrying
+ // about this class being destroyed in the meanwhile (due to browser shutdown)
+ // since tasks pending on a destroyed WeakPtr are automatically discarded.
+ base::WeakPtrFactory<SpeechRecognitionDispatcherHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionDispatcherHost);
+};
+
+// SpeechRecognitionSession implements the mojom::SpeechRecognitionSession
+// interface for a particular session. It also acts as a proxy for events sent
+// from SpeechRecognitionManager, and forwards the events to the renderer using
+// a SpeechRecognitionSessionClientPtr (that is passed from the render process).
+class SpeechRecognitionSession : public mojom::SpeechRecognitionSession,
+ public SpeechRecognitionEventListener {
+ public:
+ explicit SpeechRecognitionSession(
+ mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info);
+ ~SpeechRecognitionSession() override;
+ base::WeakPtr<SpeechRecognitionSession> AsWeakPtr();
+
+ void SetSessionId(int session_id) { session_id_ = session_id; }
+
+ // mojom::SpeechRecognitionSession implementation.
+ void Abort() override;
+ void StopCapture() override;
+
// SpeechRecognitionEventListener methods.
void OnRecognitionStart(int session_id) override;
void OnAudioStart(int session_id) override;
@@ -52,38 +100,11 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
float volume,
float noise_volume) override;
- // BrowserMessageFilter implementation.
- void OnDestruct() const override;
- bool OnMessageReceived(const IPC::Message& message) override;
- void OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) override;
-
- void OnChannelClosing() override;
-
private:
- friend class base::DeleteHelper<SpeechRecognitionDispatcherHost>;
- friend class BrowserThread;
-
- ~SpeechRecognitionDispatcherHost() override;
-
- void OnStartRequest(
- const SpeechRecognitionHostMsg_StartRequest_Params& params);
- void StartSession(const SpeechRecognitionHostMsg_StartRequest_Params& params,
- const SpeechRecognitionSessionContext& context,
- bool filter_profanities);
- void OnAbortRequest(int render_frame_id, int request_id);
- void OnStopCaptureRequest(int render_frame_id, int request_id);
- void OnAbortAllRequests(int render_frame_id);
+ int session_id_;
+ mojom::SpeechRecognitionSessionClientPtr client_;
- int render_process_id_;
- scoped_refptr<net::URLRequestContextGetter> context_getter_;
-
- // Used for posting asynchronous tasks (on the IO thread) without worrying
- // about this class being destroyed in the meanwhile (due to browser shutdown)
- // since tasks pending on a destroyed WeakPtr are automatically discarded.
- base::WeakPtrFactory<SpeechRecognitionDispatcherHost> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionDispatcherHost);
+ base::WeakPtrFactory<SpeechRecognitionSession> weak_factory_;
};
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognition_engine.cc b/chromium/content/browser/speech/speech_recognition_engine.cc
index 856f9a1df55..e05de0f8484 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.cc
+++ b/chromium/content/browser/speech/speech_recognition_engine.cc
@@ -418,9 +418,9 @@ SpeechRecognitionEngine::ConnectBothStreams(const FSMEventArgs&) {
base::UintToString(max_alternatives));
}
upstream_args.push_back("app=chromium");
- for (const SpeechRecognitionGrammar& grammar : config_.grammars) {
+ for (const mojom::SpeechRecognitionGrammar& grammar : config_.grammars) {
std::string grammar_value(base::NumberToString(grammar.weight) + ":" +
- grammar.url);
+ grammar.url.spec());
upstream_args.push_back(
"grammar=" + net::EscapeQueryParamValue(grammar_value, true));
}
diff --git a/chromium/content/browser/speech/speech_recognition_engine.h b/chromium/content/browser/speech/speech_recognition_engine.h
index 6ac7f2528b4..8a28cb6f86a 100644
--- a/chromium/content/browser/speech/speech_recognition_engine.h
+++ b/chromium/content/browser/speech/speech_recognition_engine.h
@@ -18,7 +18,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/speech_recognition_session_preamble.h"
#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_grammar.h"
+#include "content/public/common/speech_recognition_grammar.mojom.h"
#include "content/public/common/speech_recognition_result.h"
#include "net/url_request/url_fetcher_delegate.h"
@@ -78,7 +78,7 @@ class CONTENT_EXPORT SpeechRecognitionEngine : public net::URLFetcherDelegate {
~Config();
std::string language;
- SpeechRecognitionGrammarArray grammars;
+ std::vector<mojom::SpeechRecognitionGrammar> grammars;
bool filter_profanities;
bool continuous;
bool interim_results;
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.cc b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
index b197c9c5535..e04810d1d03 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
@@ -218,10 +218,8 @@ SpeechRecognitionManagerImpl* SpeechRecognitionManagerImpl::GetInstance() {
SpeechRecognitionManagerImpl::SpeechRecognitionManagerImpl(
media::AudioSystem* audio_system,
- media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager)
: audio_system_(audio_system),
- audio_manager_(audio_manager),
media_stream_manager_(media_stream_manager),
primary_session_id_(kSessionIDInvalid),
last_session_id_(kSessionIDInvalid),
@@ -277,7 +275,7 @@ int SpeechRecognitionManagerImpl::CreateSession(
remote_engine_config.continuous = config.continuous;
remote_engine_config.interim_results = config.interim_results;
remote_engine_config.max_hypotheses = config.max_hypotheses;
- remote_engine_config.origin_url = config.origin_url;
+ remote_engine_config.origin_url = config.origin.Serialize();
remote_engine_config.auth_token = config.auth_token;
remote_engine_config.auth_scope = config.auth_scope;
remote_engine_config.preamble = config.preamble;
@@ -287,7 +285,7 @@ int SpeechRecognitionManagerImpl::CreateSession(
google_remote_engine->SetConfig(remote_engine_config);
session->recognizer = new SpeechRecognizerImpl(
- this, audio_system_, audio_manager_, session_id, config.continuous,
+ this, audio_system_, session_id, config.continuous,
config.interim_results, google_remote_engine);
#else
session->recognizer = new SpeechRecognizerImplAndroid(this, session_id);
@@ -348,9 +346,8 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id,
if (ask_user) {
SpeechRecognitionSessionContext& context = session->context;
context.label = media_stream_manager_->MakeMediaAccessRequest(
- context.render_process_id, context.render_frame_id, context.request_id,
- StreamControls(true, false),
- url::Origin::Create(GURL(context.context_name)),
+ context.render_process_id, context.render_frame_id, session_id,
+ StreamControls(true, false), context.security_origin,
base::BindOnce(
&SpeechRecognitionManagerImpl::MediaRequestPermissionCallback,
weak_factory_.GetWeakPtr(), session_id));
@@ -592,26 +589,6 @@ void SpeechRecognitionManagerImpl::OnRecognitionEnd(int session_id) {
EVENT_RECOGNITION_ENDED));
}
-int SpeechRecognitionManagerImpl::GetSession(int render_process_id,
- int render_frame_id,
- int request_id) const {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- auto iter = std::find_if(
- sessions_.begin(), sessions_.end(),
- [render_process_id, render_frame_id, request_id](
- const std::pair<int, std::unique_ptr<Session>>& session_pair) {
- const SpeechRecognitionSessionContext& context =
- session_pair.second->context;
- return context.render_process_id == render_process_id &&
- context.render_frame_id == render_frame_id &&
- context.request_id == request_id;
- });
- if (iter == sessions_.end())
- return kSessionIDInvalid;
-
- return iter->first;
-}
-
SpeechRecognitionSessionContext
SpeechRecognitionManagerImpl::GetSessionContext(int session_id) const {
return GetSession(session_id)->context;
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.h b/chromium/content/browser/speech/speech_recognition_manager_impl.h
index 89a8f048a54..cf4468d3bef 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.h
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.h
@@ -20,7 +20,6 @@
namespace media {
class AudioSystem;
-class AudioManager;
}
namespace content {
@@ -68,9 +67,6 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl
int session_id) const override;
SpeechRecognitionSessionContext GetSessionContext(
int session_id) const override;
- int GetSession(int render_process_id,
- int render_frame_id,
- int request_id) const override;
// SpeechRecognitionEventListener methods.
void OnRecognitionStart(int session_id) override;
@@ -99,7 +95,6 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl
friend class base::DeleteHelper<content::SpeechRecognitionManagerImpl>;
SpeechRecognitionManagerImpl(media::AudioSystem* audio_system,
- media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager);
~SpeechRecognitionManagerImpl() override;
@@ -183,7 +178,6 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl
frame_deletion_observer_;
media::AudioSystem* audio_system_;
- media::AudioManager* audio_manager_;
MediaStreamManager* media_stream_manager_;
base::flat_map<int, std::unique_ptr<Session>> sessions_;
int primary_session_id_;
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index 7cb388ad30a..e05b95b8d48 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -14,12 +14,16 @@
#include "build/build_config.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/media/media_internals.h"
+#include "content/browser/service_manager/service_manager_context.h"
#include "content/browser/speech/audio_buffer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/speech_recognition_event_listener.h"
-#include "media/audio/audio_manager.h"
#include "media/audio/audio_system.h"
#include "media/base/audio_converter.h"
+#include "media/mojo/interfaces/audio_logging.mojom.h"
+#include "services/audio/public/cpp/audio_system_factory.h"
+#include "services/audio/public/cpp/device_factory.h"
+#include "services/service_manager/public/mojom/connector.mojom.h"
#if defined(OS_WIN)
#include "media/audio/win/core_audio_util_win.h"
@@ -27,8 +31,6 @@
using media::AudioBus;
using media::AudioConverter;
-using media::AudioInputController;
-using media::AudioManager;
using media::AudioParameters;
using media::ChannelLayout;
@@ -103,9 +105,6 @@ bool DetectClipping(const AudioChunk& chunk) {
return false;
}
-void KeepAudioControllerRefcountedForDtor(scoped_refptr<AudioInputController>) {
-}
-
} // namespace
const int SpeechRecognizerImpl::kAudioSampleRate = 16000;
@@ -115,10 +114,8 @@ const int SpeechRecognizerImpl::kNumBitsPerAudioSample = 16;
const int SpeechRecognizerImpl::kNoSpeechTimeoutMs = 8000;
const int SpeechRecognizerImpl::kEndpointerEstimationTimeMs = 300;
media::AudioSystem* SpeechRecognizerImpl::audio_system_for_tests_ = nullptr;
-media::AudioManager* SpeechRecognizerImpl::audio_manager_for_tests_ = nullptr;
-
-static_assert(SpeechRecognizerImpl::kNumBitsPerAudioSample % 8 == 0,
- "kNumBitsPerAudioSample must be a multiple of 8");
+media::AudioCapturerSource*
+ SpeechRecognizerImpl::audio_capturer_source_for_tests_ = nullptr;
// SpeechRecognizerImpl::OnDataConverter implementation
@@ -156,12 +153,15 @@ scoped_refptr<AudioChunk> SpeechRecognizerImpl::OnDataConverter::Convert(
// See http://crbug.com/506051 for details.
audio_converter_.Convert(output_bus_.get());
// Create an audio chunk based on the converted result.
- scoped_refptr<AudioChunk> chunk(
- new AudioChunk(output_parameters_.GetBytesPerBuffer(),
- output_parameters_.bits_per_sample() / 8));
- output_bus_->ToInterleaved(output_bus_->frames(),
- output_parameters_.bits_per_sample() / 8,
- chunk->writable_data());
+ scoped_refptr<AudioChunk> chunk(new AudioChunk(
+ output_parameters_.GetBytesPerBuffer(media::kSampleFormatS16),
+ kNumBitsPerAudioSample / 8));
+
+ static_assert(SpeechRecognizerImpl::kNumBitsPerAudioSample == 16,
+ "kNumBitsPerAudioSample must match interleaving type.");
+ output_bus_->ToInterleaved<media::SignedInt16SampleTypeTraits>(
+ output_bus_->frames(),
+ reinterpret_cast<int16_t*>(chunk->writable_data()));
return chunk;
}
@@ -180,26 +180,23 @@ double SpeechRecognizerImpl::OnDataConverter::ProvideInput(
SpeechRecognizerImpl::SpeechRecognizerImpl(
SpeechRecognitionEventListener* listener,
media::AudioSystem* audio_system,
- media::AudioManager* audio_manager,
int session_id,
bool continuous,
bool provisional_results,
SpeechRecognitionEngine* engine)
: SpeechRecognizer(listener, session_id),
audio_system_(audio_system),
- audio_manager_(audio_manager),
recognition_engine_(engine),
endpointer_(kAudioSampleRate),
- audio_log_(MediaInternals::GetInstance()->CreateMojoAudioLog(
- media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
- 0 /* component_id */)),
is_dispatching_event_(false),
provisional_results_(provisional_results),
end_of_utterance_(false),
state_(STATE_IDLE),
weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(recognition_engine_ != nullptr);
DCHECK(audio_system_ != nullptr);
+
if (!continuous) {
// In single shot (non-continous) recognition,
// the session is automatically ended after:
@@ -261,8 +258,6 @@ bool SpeechRecognizerImpl::IsCapturingAudio() const {
DCHECK_CURRENTLY_ON(BrowserThread::IO); // See IsActive().
const bool is_capturing_audio = state_ >= STATE_STARTING &&
state_ <= STATE_RECOGNIZING;
- DCHECK((is_capturing_audio && (audio_controller_.get() != nullptr)) ||
- (!is_capturing_audio && audio_controller_.get() == nullptr));
return is_capturing_audio;
}
@@ -274,26 +269,16 @@ SpeechRecognizerImpl::recognition_engine() const {
SpeechRecognizerImpl::~SpeechRecognizerImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
endpointer_.EndSession();
- if (audio_controller_.get()) {
- audio_controller_->Close(base::BindOnce(
- &KeepAudioControllerRefcountedForDtor, audio_controller_));
- audio_log_->OnClosed();
+ if (GetAudioCapturerSource()) {
+ GetAudioCapturerSource()->Stop();
+ audio_capturer_source_ = nullptr;
}
}
-// Invoked in the audio thread.
-void SpeechRecognizerImpl::OnError(
- media::AudioInputController::ErrorCode error_code) {
- FSMEventArgs event_args(EVENT_AUDIO_ERROR);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
-}
-
-void SpeechRecognizerImpl::Write(const AudioBus* data,
- double volume,
- bool key_pressed,
- base::TimeTicks capture_time) {
+void SpeechRecognizerImpl::Capture(const AudioBus* data,
+ int audio_delay_milliseconds,
+ double volume,
+ bool key_pressed) {
// Convert audio from native format to fixed format used by WebSpeech.
FSMEventArgs event_args(EVENT_AUDIO_DATA);
event_args.audio_data = audio_converter_->Convert(data);
@@ -313,9 +298,12 @@ void SpeechRecognizerImpl::Write(const AudioBus* data,
CHECK(audio_converter_->data_was_converted());
}
-void SpeechRecognizerImpl::Close() {}
-
-void SpeechRecognizerImpl::OnAudioClosed(AudioInputController*) {}
+void SpeechRecognizerImpl::OnCaptureError(const std::string& message) {
+ FSMEventArgs event_args(EVENT_AUDIO_ERROR);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SpeechRecognizerImpl::DispatchEvent, this, event_args));
+}
void SpeechRecognizerImpl::OnSpeechRecognitionEngineResults(
const SpeechRecognitionResults& results) {
@@ -344,13 +332,10 @@ void SpeechRecognizerImpl::OnSpeechRecognitionEngineError(
// TODO(primiano): After the changes in the media package (r129173), this class
// slightly violates the SpeechRecognitionEventListener interface contract. In
// particular, it is not true anymore that this class can be freed after the
-// OnRecognitionEnd event, since the audio_controller_.Close() asynchronous
+// OnRecognitionEnd event, since the audio_capturer_source_->Stop() asynchronous
// call can be still in progress after the end event. Currently, it does not
// represent a problem for the browser itself, since refcounting protects us
// against such race conditions. However, we should fix this in the next CLs.
-// For instance, tests are currently working just because the
-// TestAudioInputController is not closing asynchronously as the real controller
-// does, but they will become flaky if TestAudioInputController will be fixed.
void SpeechRecognizerImpl::DispatchEvent(const FSMEventArgs& event_args) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -526,7 +511,6 @@ SpeechRecognizerImpl::ExecuteTransitionAndGetNextState(
// - Are guaranteed to be not reentrant (themselves and each other);
// - event_args members are guaranteed to be stable during the call;
// - The class won't be freed in the meanwhile due to callbacks;
-// - IsCapturingAudio() returns true if and only if audio_controller_ != NULL.
// TODO(primiano): the audio pipeline is currently serial. However, the
// clipper->endpointer->vumeter chain and the sr_engine could be parallelized.
@@ -568,6 +552,7 @@ SpeechRecognizerImpl::FSMState SpeechRecognizerImpl::PrepareRecognition(
DCHECK(state_ == STATE_IDLE);
DCHECK(recognition_engine_.get() != nullptr);
DCHECK(!IsCapturingAudio());
+
GetAudioSystem()->GetInputStreamParameters(
device_id_, base::BindOnce(&SpeechRecognizerImpl::OnDeviceInfo,
weak_ptr_factory_.GetWeakPtr()));
@@ -598,9 +583,9 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) {
// Audio converter shall provide audio based on these parameters as output.
// Hard coded, WebSpeech specific parameters are utilized here.
int frames_per_buffer = (kAudioSampleRate * chunk_duration_ms) / 1000;
- AudioParameters output_parameters = AudioParameters(
- AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, kAudioSampleRate,
- kNumBitsPerAudioSample, frames_per_buffer);
+ AudioParameters output_parameters =
+ AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout,
+ kAudioSampleRate, frames_per_buffer);
DVLOG(1) << "SRI::output_parameters: "
<< output_parameters.AsHumanReadableString();
@@ -639,24 +624,16 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) {
audio_converter_.reset(
new OnDataConverter(input_parameters, output_parameters));
- audio_controller_ = AudioInputController::Create(
- GetAudioManager(), this, this, nullptr, input_parameters, device_id_,
- /*agc_is_enabled*/ false);
-
- if (!audio_controller_.get()) {
- return Abort(
- SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE));
- }
-
- audio_log_->OnCreated(input_parameters, device_id_);
-
// The endpointer needs to estimate the environment/background noise before
// starting to treat the audio as user input. We wait in the state
// ESTIMATING_ENVIRONMENT until such interval has elapsed before switching
// to user input mode.
endpointer_.SetEnvironmentEstimationMode();
- audio_controller_->Record();
- audio_log_->OnStarted();
+
+ CreateAudioCapturerSource();
+ GetAudioCapturerSource()->Initialize(input_parameters, this);
+ GetAudioCapturerSource()->Start();
+
return STATE_STARTING;
}
@@ -710,7 +687,7 @@ SpeechRecognizerImpl::StopCaptureAndWaitForResult(const FSMEventArgs&) {
DCHECK(state_ >= STATE_ESTIMATING_ENVIRONMENT && state_ <= STATE_RECOGNIZING);
DVLOG(1) << "Concluding recognition";
- CloseAudioControllerAsynchronously();
+ CloseAudioCapturerSource();
recognition_engine_->AudioChunksEnded();
if (state_ > STATE_WAITING_FOR_SPEECH)
@@ -743,7 +720,7 @@ SpeechRecognizerImpl::FSMState SpeechRecognizerImpl::Abort(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (IsCapturingAudio())
- CloseAudioControllerAsynchronously();
+ CloseAudioCapturerSource();
DVLOG(1) << "SpeechRecognizerImpl canceling recognition. ";
@@ -848,18 +825,11 @@ SpeechRecognizerImpl::NotFeasible(const FSMEventArgs& event_args) {
return state_;
}
-void SpeechRecognizerImpl::CloseAudioControllerAsynchronously() {
+void SpeechRecognizerImpl::CloseAudioCapturerSource() {
DCHECK(IsCapturingAudio());
- DVLOG(1) << "SpeechRecognizerImpl closing audio controller.";
- // Issues a Close on the audio controller, passing an empty callback. The only
- // purpose of such callback is to keep the audio controller refcounted until
- // Close has completed (in the audio thread) and automatically destroy it
- // afterwards (upon return from OnAudioClosed).
- audio_controller_->Close(
- base::BindOnce(&SpeechRecognizerImpl::OnAudioClosed, this,
- base::RetainedRef(audio_controller_)));
- audio_controller_ = nullptr; // The controller is still refcounted by Bind.
- audio_log_->OnClosed();
+ DVLOG(1) << "SpeechRecognizerImpl closing audio capturer source.";
+ GetAudioCapturerSource()->Stop();
+ audio_capturer_source_ = nullptr;
}
int SpeechRecognizerImpl::GetElapsedTimeMs() const {
@@ -890,17 +860,30 @@ void SpeechRecognizerImpl::UpdateSignalAndNoiseLevels(const float& rms,
void SpeechRecognizerImpl::SetAudioEnvironmentForTesting(
media::AudioSystem* audio_system,
- media::AudioManager* audio_manager) {
+ media::AudioCapturerSource* audio_capturer_source) {
audio_system_for_tests_ = audio_system;
- audio_manager_for_tests_ = audio_manager;
+ audio_capturer_source_for_tests_ = audio_capturer_source;
}
media::AudioSystem* SpeechRecognizerImpl::GetAudioSystem() {
return audio_system_for_tests_ ? audio_system_for_tests_ : audio_system_;
}
-media::AudioManager* SpeechRecognizerImpl::GetAudioManager() {
- return audio_manager_for_tests_ ? audio_manager_for_tests_ : audio_manager_;
+void SpeechRecognizerImpl::CreateAudioCapturerSource() {
+ service_manager::Connector* connector =
+ ServiceManagerContext::GetConnectorForIOThread();
+ if (connector) {
+ audio_capturer_source_ = audio::CreateInputDevice(
+ connector->Clone(), device_id_,
+ MediaInternals::GetInstance()->CreateMojoAudioLog(
+ media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
+ 0 /* component_id */));
+ }
+}
+
+media::AudioCapturerSource* SpeechRecognizerImpl::GetAudioCapturerSource() {
+ return audio_capturer_source_for_tests_ ? audio_capturer_source_for_tests_
+ : audio_capturer_source_.get();
}
SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(FSMEvent event_value)
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.h b/chromium/content/browser/speech/speech_recognizer_impl.h
index 9fed72910dd..d489585409f 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl.h
@@ -16,8 +16,7 @@
#include "content/browser/speech/speech_recognizer.h"
#include "content/public/common/speech_recognition_error.h"
#include "content/public/common/speech_recognition_result.h"
-#include "media/audio/audio_input_controller.h"
-#include "media/mojo/interfaces/audio_logging.mojom.h"
+#include "media/base/audio_capturer_source.h"
#include "net/url_request/url_request_context_getter.h"
namespace media {
@@ -34,8 +33,7 @@ class SpeechRecognitionEventListener;
// SpeechRecognitionEngine.
class CONTENT_EXPORT SpeechRecognizerImpl
: public SpeechRecognizer,
- public media::AudioInputController::EventHandler,
- public media::AudioInputController::SyncWriter,
+ public media::AudioCapturerSource::CaptureCallback,
public SpeechRecognitionEngine::Delegate {
public:
static const int kAudioSampleRate;
@@ -44,22 +42,24 @@ class CONTENT_EXPORT SpeechRecognizerImpl
static const int kNoSpeechTimeoutMs;
static const int kEndpointerEstimationTimeMs;
- static void SetAudioEnvironmentForTesting(media::AudioSystem* audio_system,
- media::AudioManager* audio_manager);
+ static void SetAudioEnvironmentForTesting(
+ media::AudioSystem* audio_system,
+ media::AudioCapturerSource* capturer_source);
SpeechRecognizerImpl(SpeechRecognitionEventListener* listener,
media::AudioSystem* audio_system,
- media::AudioManager* audio_manager,
int session_id,
bool continuous,
bool provisional_results,
SpeechRecognitionEngine* engine);
+ // SpeechRecognizer methods.
void StartRecognition(const std::string& device_id) override;
void AbortRecognition() override;
void StopAudioCapture() override;
bool IsActive() const override;
bool IsCapturingAudio() const override;
+
const SpeechRecognitionEngine& recognition_engine() const;
private:
@@ -138,23 +138,16 @@ class CONTENT_EXPORT SpeechRecognizerImpl
// OnAudioLevelsChange event accordingly.
void UpdateSignalAndNoiseLevels(const float& rms, bool clip_detected);
- void CloseAudioControllerAsynchronously();
-
- // Callback called on IO thread by audio_controller->Close().
- void OnAudioClosed(media::AudioInputController*);
+ void CloseAudioCapturerSource();
- // AudioInputController::EventHandler methods.
- void OnCreated(bool initially_muted) override {}
- void OnError(media::AudioInputController::ErrorCode error_code) override;
- void OnLog(base::StringPiece) override {}
- void OnMuted(bool is_muted) override {}
-
- // AudioInputController::SyncWriter methods.
- void Write(const media::AudioBus* data,
- double volume,
- bool key_pressed,
- base::TimeTicks capture_time) override;
- void Close() override;
+ // media::AudioCapturerSource::CaptureCallback methods.
+ void OnCaptureStarted() final {}
+ void Capture(const media::AudioBus* audio_bus,
+ int audio_delay_milliseconds,
+ double volume,
+ bool key_pressed) final;
+ void OnCaptureError(const std::string& message) final;
+ void OnCaptureMuted(bool is_muted) final {}
// SpeechRecognitionEngineDelegate methods.
void OnSpeechRecognitionEngineResults(
@@ -164,17 +157,17 @@ class CONTENT_EXPORT SpeechRecognizerImpl
const SpeechRecognitionError& error) override;
media::AudioSystem* GetAudioSystem();
- media::AudioManager* GetAudioManager();
+ void CreateAudioCapturerSource();
+ media::AudioCapturerSource* GetAudioCapturerSource();
- // Substitutes the real audio system in browser tests.
+ // Substitute the real audio system and capturer source in browser tests.
static media::AudioSystem* audio_system_for_tests_;
- static media::AudioManager* audio_manager_for_tests_;
+ static media::AudioCapturerSource* audio_capturer_source_for_tests_;
+
media::AudioSystem* audio_system_;
- media::AudioManager* audio_manager_;
std::unique_ptr<SpeechRecognitionEngine> recognition_engine_;
Endpointer endpointer_;
- scoped_refptr<media::AudioInputController> audio_controller_;
- media::mojom::AudioLogPtr audio_log_;
+ scoped_refptr<media::AudioCapturerSource> audio_capturer_source_;
int num_samples_recorded_;
float audio_level_;
bool is_dispatching_event_;
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.cc b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
index 19bec767ab1..5ca639cd1fd 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.cc
@@ -16,9 +16,8 @@
#include "content/public/browser/speech_recognition_event_listener.h"
#include "content/public/browser/speech_recognition_manager.h"
#include "content/public/browser/speech_recognition_session_config.h"
-#include "content/public/common/speech_recognition_grammar.h"
#include "content/public/common/speech_recognition_result.h"
-#include "jni/SpeechRecognition_jni.h"
+#include "jni/SpeechRecognitionImpl_jni.h"
using base::android::AppendJavaStringArrayToStringVector;
using base::android::AttachCurrentThread;
@@ -41,15 +40,17 @@ void SpeechRecognizerImplAndroid::StartRecognition(
const std::string& device_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// TODO(xians): Open the correct device for speech on Android.
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
- &SpeechRecognitionEventListener::OnRecognitionStart,
- base::Unretained(listener()),
- session_id()));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SpeechRecognitionEventListener::OnRecognitionStart,
+ base::Unretained(listener()), session_id()));
SpeechRecognitionSessionConfig config =
SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id());
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &content::SpeechRecognizerImplAndroid::StartRecognitionOnUIThread, this,
- config.language, config.continuous, config.interim_results));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &content::SpeechRecognizerImplAndroid::StartRecognitionOnUIThread,
+ this, config.language, config.continuous, config.interim_results));
}
void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread(
@@ -58,9 +59,9 @@ void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread(
bool interim_results) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
- j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition(
+ j_recognition_.Reset(Java_SpeechRecognitionImpl_createSpeechRecognition(
env, reinterpret_cast<intptr_t>(this)));
- Java_SpeechRecognition_startRecognition(
+ Java_SpeechRecognitionImpl_startRecognition(
env, j_recognition_, ConvertUTF8ToJavaString(env, language), continuous,
interim_results);
}
@@ -68,26 +69,30 @@ void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread(
void SpeechRecognizerImplAndroid::AbortRecognition() {
if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
state_ = STATE_IDLE;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &content::SpeechRecognizerImplAndroid::AbortRecognition, this));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&content::SpeechRecognizerImplAndroid::AbortRecognition,
+ this));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
if (!j_recognition_.is_null())
- Java_SpeechRecognition_abortRecognition(env, j_recognition_);
+ Java_SpeechRecognitionImpl_abortRecognition(env, j_recognition_);
}
void SpeechRecognizerImplAndroid::StopAudioCapture() {
if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &content::SpeechRecognizerImplAndroid::StopAudioCapture, this));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&content::SpeechRecognizerImplAndroid::StopAudioCapture,
+ this));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
if (!j_recognition_.is_null())
- Java_SpeechRecognition_stopRecognition(env, j_recognition_);
+ Java_SpeechRecognitionImpl_stopRecognition(env, j_recognition_);
}
bool SpeechRecognizerImplAndroid::IsActive() const {
@@ -106,8 +111,8 @@ void SpeechRecognizerImplAndroid::OnAudioStart(
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&SpeechRecognizerImplAndroid::OnAudioStart, this, nullptr,
- nullptr));
+ base::BindOnce(&SpeechRecognizerImplAndroid::OnAudioStart, this,
+ nullptr, nullptr));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -121,8 +126,8 @@ void SpeechRecognizerImplAndroid::OnSoundStart(
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&SpeechRecognizerImplAndroid::OnSoundStart, this, nullptr,
- nullptr));
+ base::BindOnce(&SpeechRecognizerImplAndroid::OnSoundStart, this,
+ nullptr, nullptr));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -132,9 +137,10 @@ void SpeechRecognizerImplAndroid::OnSoundStart(
void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&SpeechRecognizerImplAndroid::OnSoundEnd,
- this, nullptr, nullptr));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SpeechRecognizerImplAndroid::OnSoundEnd, this, nullptr,
+ nullptr));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -144,9 +150,10 @@ void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env,
void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&SpeechRecognizerImplAndroid::OnAudioEnd,
- this, nullptr, nullptr));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(&SpeechRecognizerImplAndroid::OnAudioEnd, this, nullptr,
+ nullptr));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -176,9 +183,11 @@ void SpeechRecognizerImplAndroid::OnRecognitionResults(
options[i], static_cast<double>(scores[i])));
}
result.is_provisional = provisional;
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
- &SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread,
- this, results));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::BindOnce(
+ &SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread, this,
+ results));
}
void SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread(
@@ -194,8 +203,8 @@ void SpeechRecognizerImplAndroid::OnRecognitionError(
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionError, this,
- nullptr, nullptr, error));
+ base::BindOnce(&SpeechRecognizerImplAndroid::OnRecognitionError, this,
+ nullptr, nullptr, error));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -210,8 +219,8 @@ void SpeechRecognizerImplAndroid::OnRecognitionEnd(
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionEnd, this,
- nullptr, nullptr));
+ base::BindOnce(&SpeechRecognizerImplAndroid::OnRecognitionEnd, this,
+ nullptr, nullptr));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index 2c5928d61f5..21c79cb7445 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -7,6 +7,7 @@
#include <vector>
+#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/sys_byteorder.h"
@@ -22,7 +23,6 @@
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/audio/mock_audio_manager.h"
-#include "media/audio/test_audio_input_controller_factory.h"
#include "media/audio/test_audio_thread.h"
#include "media/base/audio_bus.h"
#include "media/base/test_helpers.h"
@@ -31,20 +31,39 @@
#include "net/url_request/url_request_status.h"
#include "testing/gtest/include/gtest/gtest.h"
-using media::AudioInputController;
using media::AudioInputStream;
using media::AudioOutputStream;
using media::AudioParameters;
-using media::TestAudioInputController;
-using media::TestAudioInputControllerFactory;
namespace content {
+namespace {
+
+class MockCapturerSource : public media::AudioCapturerSource {
+ public:
+ MockCapturerSource() = default;
+ MOCK_METHOD2(Initialize,
+ void(const media::AudioParameters& params,
+ CaptureCallback* callback));
+ MOCK_METHOD0(Start, void());
+ MOCK_METHOD0(Stop, void());
+ MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
+ MOCK_METHOD1(SetVolume, void(double volume));
+ MOCK_METHOD1(SetOutputDeviceForAec,
+ void(const std::string& output_device_id));
+
+ protected:
+ ~MockCapturerSource() override = default;
+};
+
+} // namespace
+
class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
public testing::Test {
public:
SpeechRecognizerImplTest()
- : recognition_started_(false),
+ : audio_capturer_source_(new testing::NiceMock<MockCapturerSource>()),
+ recognition_started_(false),
recognition_ended_(false),
result_received_(false),
audio_started_(false),
@@ -71,9 +90,10 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
media::AudioParameters::UnavailableDeviceParams());
audio_system_ =
std::make_unique<media::AudioSystemImpl>(audio_manager_.get());
+ SpeechRecognizerImpl::SetAudioEnvironmentForTesting(
+ audio_system_.get(), audio_capturer_source_.get());
recognizer_ = new SpeechRecognizerImpl(
- this, audio_system_.get(), audio_manager_.get(), kTestingSessionId,
- false, false, sr_engine);
+ this, audio_system_.get(), kTestingSessionId, false, false, sr_engine);
int audio_packet_length_bytes =
(SpeechRecognizerImpl::kAudioSampleRate *
@@ -90,7 +110,10 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
audio_bus_->Zero();
}
- ~SpeechRecognizerImplTest() override { audio_manager_->Shutdown(); }
+ ~SpeechRecognizerImplTest() override {
+ SpeechRecognizerImpl::SetAudioEnvironmentForTesting(nullptr, nullptr);
+ audio_manager_->Shutdown();
+ }
void CheckEventsConsistency() {
// Note: "!x || y" == "x implies y".
@@ -162,16 +185,6 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
CheckEventsConsistency();
}
- // testing::Test methods.
- void SetUp() override {
- AudioInputController::set_factory_for_testing(
- &audio_input_controller_factory_);
- }
-
- void TearDown() override {
- AudioInputController::set_factory_for_testing(nullptr);
- }
-
void CopyPacketToAudioBus() {
// Copy the created signal into an audio bus in a deinterleaved format.
audio_bus_->FromInterleaved(
@@ -195,10 +208,18 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
CopyPacketToAudioBus();
}
- void OnData(media::AudioBus* data) {
- auto* writer =
- static_cast<AudioInputController::SyncWriter*>(recognizer_.get());
- writer->Write(data, 0.0, false, base::TimeTicks::Now());
+ void Capture(media::AudioBus* data) {
+ auto* capture_callback =
+ static_cast<media::AudioCapturerSource::CaptureCallback*>(
+ recognizer_.get());
+ capture_callback->Capture(data, 0, 0.0, false);
+ }
+
+ void OnCaptureError() {
+ auto* capture_callback =
+ static_cast<media::AudioCapturerSource::CaptureCallback*>(
+ recognizer_.get());
+ capture_callback->OnCaptureError("");
}
void WaitForAudioThreadToPostDeviceInfo() {
@@ -216,6 +237,7 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
scoped_refptr<SpeechRecognizerImpl> recognizer_;
std::unique_ptr<media::MockAudioManager> audio_manager_;
std::unique_ptr<media::AudioSystem> audio_system_;
+ scoped_refptr<MockCapturerSource> audio_capturer_source_;
bool recognition_started_;
bool recognition_ended_;
bool result_received_;
@@ -225,7 +247,6 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
bool sound_ended_;
SpeechRecognitionErrorCode error_;
net::TestURLFetcherFactory url_fetcher_factory_;
- TestAudioInputControllerFactory audio_input_controller_factory_;
std::vector<uint8_t> audio_packet_;
std::unique_ptr<media::AudioBus> audio_bus_;
int bytes_per_sample_;
@@ -343,9 +364,6 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
// Try sending 5 chunks of mock audio data and verify that each of them
// resulted immediately in a packet sent out via the network. This verifies
@@ -353,7 +371,7 @@ TEST_F(SpeechRecognizerImplTest, StopWithData) {
// full recording to complete.
const size_t kNumChunks = 5;
for (size_t i = 0; i < kNumChunks; ++i) {
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
@@ -407,10 +425,7 @@ TEST_F(SpeechRecognizerImplTest, CancelWithData) {
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
recognizer_->AbortRecognition();
base::RunLoop().RunUntilIdle();
@@ -430,10 +445,7 @@ TEST_F(SpeechRecognizerImplTest, ConnectionError) {
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
@@ -468,10 +480,7 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
@@ -497,42 +506,18 @@ TEST_F(SpeechRecognizerImplTest, ServerError) {
CheckFinalEventsConsistency();
}
-TEST_F(SpeechRecognizerImplTest, AudioControllerErrorNoData) {
+TEST_F(SpeechRecognizerImplTest, OnCaptureError_PropagatesError) {
// Check if things tear down properly if AudioInputController threw an error.
recognizer_->StartRecognition(
media::AudioDeviceDescription::kDefaultDeviceId);
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- controller->event_handler()->OnError(AudioInputController::UNKNOWN_ERROR);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(recognition_started_);
- EXPECT_FALSE(audio_started_);
- EXPECT_FALSE(result_received_);
- EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, error_);
- CheckFinalEventsConsistency();
-}
-TEST_F(SpeechRecognizerImplTest, AudioControllerErrorWithData) {
- // Check if things tear down properly if AudioInputController threw an error
- // after giving some audio data.
- recognizer_->StartRecognition(
- media::AudioDeviceDescription::kDefaultDeviceId);
- base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
- WaitForAudioThreadToPostDeviceInfo();
- base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- OnData(audio_bus_.get());
- controller->event_handler()->OnError(AudioInputController::UNKNOWN_ERROR);
+ OnCaptureError();
base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(url_fetcher_factory_.GetFetcherByID(0));
EXPECT_TRUE(recognition_started_);
- EXPECT_TRUE(audio_started_);
+ EXPECT_FALSE(audio_started_);
EXPECT_FALSE(result_received_);
EXPECT_EQ(SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE, error_);
CheckFinalEventsConsistency();
@@ -546,15 +531,12 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackIssued) {
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
int num_packets = (SpeechRecognizerImpl::kNoSpeechTimeoutMs) /
SpeechRecognitionEngine::kAudioPacketIntervalMs + 1;
// The vector is already filled with zero value samples on create.
for (int i = 0; i < num_packets; ++i) {
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
}
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recognition_started_);
@@ -574,23 +556,18 @@ TEST_F(SpeechRecognizerImplTest, NoSpeechCallbackNotIssued) {
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- controller = audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
int num_packets = (SpeechRecognizerImpl::kNoSpeechTimeoutMs) /
SpeechRecognitionEngine::kAudioPacketIntervalMs;
// The vector is already filled with zero value samples on create.
for (int i = 0; i < num_packets / 2; ++i) {
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
}
FillPacketWithTestWaveform();
for (int i = 0; i < num_packets / 2; ++i) {
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
}
base::RunLoop().RunUntilIdle();
@@ -613,29 +590,24 @@ TEST_F(SpeechRecognizerImplTest, SetInputVolumeCallback) {
base::RunLoop().RunUntilIdle(); // EVENT_PREPARE processing.
WaitForAudioThreadToPostDeviceInfo();
base::RunLoop().RunUntilIdle(); // EVENT_START processing.
- TestAudioInputController* controller =
- audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
- controller = audio_input_controller_factory_.controller();
- ASSERT_TRUE(controller);
// Feed some samples to begin with for the endpointer to do noise estimation.
int num_packets = SpeechRecognizerImpl::kEndpointerEstimationTimeMs /
SpeechRecognitionEngine::kAudioPacketIntervalMs;
FillPacketWithNoise();
for (int i = 0; i < num_packets; ++i) {
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
}
base::RunLoop().RunUntilIdle();
EXPECT_EQ(-1.0f, volume_); // No audio volume set yet.
// The vector is already filled with zero value samples on create.
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
EXPECT_FLOAT_EQ(0.74939233f, volume_);
FillPacketWithTestWaveform();
- OnData(audio_bus_.get());
+ Capture(audio_bus_.get());
base::RunLoop().RunUntilIdle();
EXPECT_NEAR(0.89926866f, volume_, 0.00001f);
EXPECT_FLOAT_EQ(0.75071919f, noise_volume_);
diff --git a/chromium/content/browser/startup_task_runner.cc b/chromium/content/browser/startup_task_runner.cc
index 5adeb6ae6e1..36259dd2ec7 100644
--- a/chromium/content/browser/startup_task_runner.cc
+++ b/chromium/content/browser/startup_task_runner.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/message_loop/message_loop.h"
namespace content {
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index 9f0423752c5..b9165dd4ab7 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <set>
+#include <utility>
#include <vector>
#include "base/barrier_closure.h"
@@ -17,12 +18,14 @@
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/syslog_logging.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/blob_storage/blob_registry_wrapper.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/browsing_data/storage_partition_http_cache_data_remover.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
@@ -44,10 +47,10 @@
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
#include "net/cookies/canonical_cookie.h"
-#include "net/cookies/cookie_monster.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/buildflags/buildflags.h"
+#include "services/network/cookie_manager.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
@@ -66,6 +69,9 @@
#include "content/browser/plugin_private_storage_helper.h"
#endif // BUILDFLAG(ENABLE_PLUGINS)
+using CookieDeletionFilter = network::mojom::CookieDeletionFilter;
+using CookieDeletionFilterPtr = network::mojom::CookieDeletionFilterPtr;
+
namespace content {
namespace {
@@ -73,11 +79,6 @@ namespace {
base::LazyInstance<StoragePartitionImpl::CreateNetworkFactoryCallback>::Leaky
g_url_loader_factory_callback_for_test = LAZY_INSTANCE_INITIALIZER;
-bool DoesCookieMatchHost(const std::string& host,
- const net::CanonicalCookie& cookie) {
- return cookie.IsHostCookie() && cookie.IsDomainMatch(host);
-}
-
void OnClearedCookies(base::OnceClosure callback, uint32_t num_deleted) {
// The final callback needs to happen from UI thread.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
@@ -90,38 +91,6 @@ void OnClearedCookies(base::OnceClosure callback, uint32_t num_deleted) {
std::move(callback).Run();
}
-// Cookie matcher and storage_origin are never both populated.
-void ClearCookiesOnIOThread(
- const scoped_refptr<net::URLRequestContextGetter>& rq_context,
- const base::Time begin,
- const base::Time end,
- const GURL& storage_origin,
- const StoragePartition::CookieMatcherFunction& cookie_matcher,
- base::OnceClosure callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(cookie_matcher.is_null() || storage_origin.is_empty());
- net::CookieStore* cookie_store =
- rq_context->GetURLRequestContext()->cookie_store();
- if (!cookie_matcher.is_null()) {
- cookie_store->DeleteAllCreatedBetweenWithPredicateAsync(
- begin, end, cookie_matcher,
- base::BindOnce(&OnClearedCookies, std::move(callback)));
- return;
- }
- if (!storage_origin.is_empty()) {
- // TODO(mkwst): It's not clear whether removing host cookies is the correct
- // behavior. We might want to remove all domain-matching cookies instead.
- // Also, this code path may be dead anyways.
- cookie_store->DeleteAllCreatedBetweenWithPredicateAsync(
- begin, end,
- StoragePartitionImpl::CreatePredicateForHostCookies(storage_origin),
- base::BindOnce(&OnClearedCookies, std::move(callback)));
- return;
- }
- cookie_store->DeleteAllCreatedBetweenAsync(
- begin, end, base::BindOnce(&OnClearedCookies, std::move(callback)));
-}
-
void CheckQuotaManagedDataDeletionStatus(size_t* deletion_task_count,
const base::Closure& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -278,7 +247,7 @@ class StoragePartitionImpl::NetworkContextOwner {
context_getter_ = std::move(context_getter);
network_context_ = std::make_unique<network::NetworkContext>(
GetNetworkServiceImpl(), std::move(network_context_request),
- context_getter_);
+ context_getter_->GetURLRequestContext());
}
private:
@@ -300,6 +269,7 @@ class StoragePartitionImpl::URLLoaderFactoryForBrowserProcess
: storage_partition_(storage_partition) {}
// mojom::URLLoaderFactory implementation:
+
void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
@@ -317,6 +287,13 @@ class StoragePartitionImpl::URLLoaderFactoryForBrowserProcess
traffic_annotation);
}
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+ if (!storage_partition_)
+ return;
+ storage_partition_->GetURLLoaderFactoryForBrowserProcessInternal()->Clone(
+ std::move(request));
+ }
+
// SharedURLLoaderFactory implementation:
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
NOTREACHED() << "This isn't supported. If you need a SharedURLLoaderFactory"
@@ -351,17 +328,13 @@ int StoragePartitionImpl::GenerateQuotaClientMask(uint32_t remove_mask) {
quota_client_mask |= storage::QuotaClient::kServiceWorker;
if (remove_mask & StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE)
quota_client_mask |= storage::QuotaClient::kServiceWorkerCache;
+ if (remove_mask & StoragePartition::REMOVE_DATA_MASK_BACKGROUND_FETCH)
+ quota_client_mask |= storage::QuotaClient::kBackgroundFetch;
return quota_client_mask;
}
// static
-net::CookieStore::CookiePredicate
-StoragePartitionImpl::CreatePredicateForHostCookies(const GURL& url) {
- return base::Bind(&DoesCookieMatchHost, url.host());
-}
-
-// static
void StoragePartitionImpl::
SetGetURLLoaderFactoryForBrowserProcessCallbackForTesting(
const CreateNetworkFactoryCallback& url_loader_factory_callback) {
@@ -443,7 +416,7 @@ class StoragePartitionImpl::DataDeletionHelper {
// to the DataDeletionHelper.
class OwnsReference {
public:
- OwnsReference(DataDeletionHelper* helper) : helper_(helper) {
+ explicit OwnsReference(DataDeletionHelper* helper) : helper_(helper) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
helper->IncrementTaskCountOnUI();
}
@@ -471,13 +444,14 @@ class StoragePartitionImpl::DataDeletionHelper {
void ClearDataOnUIThread(
const GURL& storage_origin,
const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
+ CookieDeletionFilterPtr cookie_deletion_filter,
const base::FilePath& path,
net::URLRequestContextGetter* rq_context,
DOMStorageContextWrapper* dom_storage_context,
storage::QuotaManager* quota_manager,
storage::SpecialStoragePolicy* special_storage_policy,
storage::FileSystemContext* filesystem_context,
+ network::mojom::CookieManager* cookie_manager,
const base::Time begin,
const base::Time end);
@@ -658,7 +632,8 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->background_fetch_context_ =
new BackgroundFetchContext(context, partition->service_worker_context_);
- partition->background_sync_context_ = new BackgroundSyncContext();
+ partition->background_sync_context_ =
+ base::MakeRefCounted<BackgroundSyncContext>();
partition->background_sync_context_->Init(partition->service_worker_context_);
partition->payment_app_context_ = new PaymentAppContextImpl();
@@ -677,11 +652,11 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
base::BindOnce(&BlobStorageContextGetterForStorage, blob_context);
partition->blob_url_loader_factory_ =
BlobURLLoaderFactory::Create(std::move(blob_getter));
-
- partition->url_loader_factory_getter_ = new URLLoaderFactoryGetter();
- partition->url_loader_factory_getter_->Initialize(partition.get());
}
+ partition->url_loader_factory_getter_ = new URLLoaderFactoryGetter();
+ partition->url_loader_factory_getter_->Initialize(partition.get());
+
partition->service_worker_context_->Init(
path, quota_manager_proxy.get(), context->GetSpecialStoragePolicy(),
blob_context.get(), partition->url_loader_factory_getter_.get());
@@ -696,6 +671,14 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
base::MakeRefCounted<PrefetchURLLoaderService>(
partition->url_loader_factory_getter_);
+ partition->cookie_store_context_ = base::MakeRefCounted<CookieStoreContext>();
+ // Unit tests use the Initialize() callback to crash early if restoring the
+ // CookieManagerStore's state from ServiceWorkerStorage fails. Production and
+ // browser tests rely on CookieStoreManager's well-defined behavior when
+ // restoring the state fails.
+ partition->cookie_store_context_->Initialize(
+ partition->service_worker_context_, base::DoNothing());
+
return partition;
}
@@ -856,12 +839,17 @@ PrefetchURLLoaderService* StoragePartitionImpl::GetPrefetchURLLoaderService() {
return prefetch_url_loader_service_.get();
}
+CookieStoreContext* StoragePartitionImpl::GetCookieStoreContext() {
+ return cookie_store_context_.get();
+}
+
void StoragePartitionImpl::OpenLocalStorage(
const url::Origin& origin,
mojom::LevelDBWrapperRequest request) {
int process_id = bindings_.dispatch_context();
if (!ChildProcessSecurityPolicy::GetInstance()->CanAccessDataForOrigin(
process_id, origin.GetURL())) {
+ SYSLOG(WARNING) << "Killing renderer: illegal localStorage request.";
bindings_.ReportBadMessage("Access denied for localStorage request");
return;
}
@@ -881,7 +869,7 @@ void StoragePartitionImpl::ClearDataImpl(
uint32_t quota_storage_remove_mask,
const GURL& storage_origin,
const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
+ CookieDeletionFilterPtr cookie_deletion_filter,
const base::Time begin,
const base::Time end,
base::OnceClosure callback) {
@@ -894,9 +882,11 @@ void StoragePartitionImpl::ClearDataImpl(
// DataDeletionHelper::DecrementTaskCount().
deletion_helpers_running_++;
helper->ClearDataOnUIThread(
- storage_origin, origin_matcher, cookie_matcher, GetPath(),
- GetURLRequestContext(), dom_storage_context_.get(), quota_manager_.get(),
- special_storage_policy_.get(), filesystem_context_.get(), begin, end);
+ storage_origin, origin_matcher, std::move(cookie_deletion_filter),
+ GetPath(), GetURLRequestContext(), dom_storage_context_.get(),
+ quota_manager_.get(), special_storage_policy_.get(),
+ filesystem_context_.get(), GetCookieManagerForBrowserProcess(), begin,
+ end);
}
void StoragePartitionImpl::DeletionHelperDone(base::OnceClosure callback) {
@@ -1041,13 +1031,14 @@ void StoragePartitionImpl::DataDeletionHelper::DecrementTaskCount() {
void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
const GURL& storage_origin,
const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
+ CookieDeletionFilterPtr cookie_deletion_filter,
const base::FilePath& path,
net::URLRequestContextGetter* rq_context,
DOMStorageContextWrapper* dom_storage_context,
storage::QuotaManager* quota_manager,
storage::SpecialStoragePolicy* special_storage_policy,
storage::FileSystemContext* filesystem_context,
+ network::mojom::CookieManager* cookie_manager,
const base::Time begin,
const base::Time end) {
DCHECK_NE(remove_mask_, 0u);
@@ -1058,12 +1049,21 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
&DataDeletionHelper::DecrementTaskCount, base::Unretained(this));
if (remove_mask_ & REMOVE_DATA_MASK_COOKIES) {
- // Handle the cookies.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ // The CookieDeletionFilter has a redundant time interval to |begin| and
+ // |end|. Ensure that the filter has no time interval specified to help
+ // callers detect when they are using the wrong interval values.
+ DCHECK(!cookie_deletion_filter->created_after_time.has_value());
+ DCHECK(!cookie_deletion_filter->created_before_time.has_value());
+
+ if (!begin.is_null())
+ cookie_deletion_filter->created_after_time = begin;
+ if (!end.is_null())
+ cookie_deletion_filter->created_before_time = end;
+
+ cookie_manager->DeleteCookies(
+ std::move(cookie_deletion_filter),
base::BindOnce(
- &ClearCookiesOnIOThread, base::WrapRefCounted(rq_context), begin,
- end, storage_origin, cookie_matcher,
+ &OnClearedCookies,
// Use OwnsReference instead of Increment/DecrementTaskCount*
// to handle the cookie store being destroyed and the callback
// thus not being called.
@@ -1132,9 +1132,12 @@ void StoragePartitionImpl::ClearDataForOrigin(
uint32_t quota_storage_remove_mask,
const GURL& storage_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
+ if (!storage_origin.host().empty())
+ deletion_filter->host_name = storage_origin.host();
ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin,
- OriginMatcherFunction(), CookieMatcherFunction(), base::Time(),
- base::Time::Max(), base::DoNothing());
+ OriginMatcherFunction(), std::move(deletion_filter),
+ base::Time(), base::Time::Max(), base::DoNothing());
}
void StoragePartitionImpl::ClearData(
@@ -1145,8 +1148,11 @@ void StoragePartitionImpl::ClearData(
const base::Time begin,
const base::Time end,
base::OnceClosure callback) {
+ CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
+ if (!storage_origin.host().empty())
+ deletion_filter->host_name = storage_origin.host();
ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin,
- origin_matcher, CookieMatcherFunction(), begin, end,
+ origin_matcher, std::move(deletion_filter), begin, end,
std::move(callback));
}
@@ -1154,12 +1160,13 @@ void StoragePartitionImpl::ClearData(
uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
+ network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,
const base::Time begin,
const base::Time end,
base::OnceClosure callback) {
ClearDataImpl(remove_mask, quota_storage_remove_mask, GURL(), origin_matcher,
- cookie_matcher, begin, end, std::move(callback));
+ std::move(cookie_deletion_filter), begin, end,
+ std::move(callback));
}
void StoragePartitionImpl::ClearHttpAndMediaCaches(
@@ -1247,15 +1254,20 @@ StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
return url_loader_factory_for_browser_process_.get();
}
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = network::mojom::kBrowserProcessId;
+ params->is_corb_enabled = false;
if (g_url_loader_factory_callback_for_test.Get().is_null()) {
GetNetworkContext()->CreateURLLoaderFactory(
- mojo::MakeRequest(&url_loader_factory_for_browser_process_), 0);
+ mojo::MakeRequest(&url_loader_factory_for_browser_process_),
+ std::move(params));
return url_loader_factory_for_browser_process_.get();
}
network::mojom::URLLoaderFactoryPtr original_factory;
GetNetworkContext()->CreateURLLoaderFactory(
- mojo::MakeRequest(&original_factory), 0);
+ mojo::MakeRequest(&original_factory), std::move(params));
url_loader_factory_for_browser_process_ =
g_url_loader_factory_callback_for_test.Get().Run(
std::move(original_factory));
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index 38d0aadaad6..102e3ff8e47 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -35,7 +35,6 @@
#include "content/common/storage_partition_service.mojom.h"
#include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/binding_set.h"
-#include "net/cookies/cookie_store.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "storage/browser/quota/special_storage_policy.h"
@@ -47,6 +46,7 @@
namespace content {
class BackgroundFetchContext;
+class CookieStoreContext;
class BlobRegistryWrapper;
class BlobURLLoaderFactory;
class PrefetchURLLoaderService;
@@ -65,12 +65,6 @@ class CONTENT_EXPORT StoragePartitionImpl
// StoragePartition uses. This method generates that mask.
static int GenerateQuotaClientMask(uint32_t remove_mask);
- // This creates a CookiePredicate that matches all host (NOT domain) cookies
- // that match the host of |url|. This is intended to be used with
- // DeleteAllCreatedBetweenWithPredicateAsync.
- static net::CookieStore::CookiePredicate
- CreatePredicateForHostCookies(const GURL& url);
-
// Allows overriding the URLLoaderFactory creation for
// GetURLLoaderFactoryForBrowserProcess.
// Passing a null callback will restore the default behavior.
@@ -127,7 +121,7 @@ class CONTENT_EXPORT StoragePartitionImpl
void ClearData(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
+ network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,
const base::Time begin,
const base::Time end,
base::OnceClosure callback) override;
@@ -149,6 +143,7 @@ class CONTENT_EXPORT StoragePartitionImpl
BlobURLLoaderFactory* GetBlobURLLoaderFactory();
BlobRegistryWrapper* GetBlobRegistry();
PrefetchURLLoaderService* GetPrefetchURLLoaderService();
+ CookieStoreContext* GetCookieStoreContext();
// mojom::StoragePartitionService interface.
void OpenLocalStorage(const url::Origin& origin,
@@ -194,6 +189,7 @@ class CONTENT_EXPORT StoragePartitionImpl
friend class BackgroundSyncManagerTest;
friend class BackgroundSyncServiceImplTest;
+ friend class CookieStoreManagerTest;
friend class PaymentAppContentUnitTestBase;
friend class StoragePartitionImplMap;
friend class URLLoaderFactoryForBrowserProcess;
@@ -222,7 +218,8 @@ class CONTENT_EXPORT StoragePartitionImpl
RemoveQuotaManagedIgnoreDevTools);
FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest, RemoveCookieForever);
FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest, RemoveCookieLastHour);
- FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest, RemoveCookieWithMatcher);
+ FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
+ RemoveCookieWithDeleteInfo);
FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
RemoveUnprotectedLocalStorageForever);
FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
@@ -246,14 +243,15 @@ class CONTENT_EXPORT StoragePartitionImpl
storage::SpecialStoragePolicy* special_storage_policy);
// We will never have both remove_origin be populated and a cookie_matcher.
- void ClearDataImpl(uint32_t remove_mask,
- uint32_t quota_storage_remove_mask,
- const GURL& remove_origin,
- const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
- const base::Time begin,
- const base::Time end,
- base::OnceClosure callback);
+ void ClearDataImpl(
+ uint32_t remove_mask,
+ uint32_t quota_storage_remove_mask,
+ const GURL& remove_origin,
+ const OriginMatcherFunction& origin_matcher,
+ network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,
+ const base::Time begin,
+ const base::Time end,
+ base::OnceClosure callback);
void DeletionHelperDone(base::OnceClosure callback);
@@ -314,6 +312,7 @@ class CONTENT_EXPORT StoragePartitionImpl
scoped_refptr<BlobURLLoaderFactory> blob_url_loader_factory_;
scoped_refptr<BlobRegistryWrapper> blob_registry_;
scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
+ scoped_refptr<CookieStoreContext> cookie_store_context_;
// BindingSet for StoragePartitionService, using the process id as the
// binding context type. The process id can subsequently be used during
diff --git a/chromium/content/browser/storage_partition_impl_browsertest.cc b/chromium/content/browser/storage_partition_impl_browsertest.cc
index 07f74ad1900..e2d5a2c13db 100644
--- a/chromium/content/browser/storage_partition_impl_browsertest.cc
+++ b/chromium/content/browser/storage_partition_impl_browsertest.cc
@@ -12,6 +12,8 @@
#include "content/public/browser/web_contents.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "content/test/storage_partition_test_utils.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/http/http_response_headers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -42,6 +44,12 @@ class StoragePartititionImplBrowsertest
}
~StoragePartititionImplBrowsertest() override {}
+ GURL GetTestURL() const {
+ // Use '/echoheader' instead of '/echo' to avoid a disk_cache bug.
+ // See https://crbug.com/792255.
+ return embedded_test_server()->GetURL("/echoheader");
+ }
+
private:
base::test::ScopedFeatureList feature_list_;
};
@@ -52,11 +60,16 @@ class StoragePartititionImplBrowsertest
IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest, NetworkContext) {
ASSERT_TRUE(embedded_test_server()->Start());
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = network::mojom::kBrowserProcessId;
+ params->is_corb_enabled = false;
network::mojom::URLLoaderFactoryPtr loader_factory;
BrowserContext::GetDefaultStoragePartition(
shell()->web_contents()->GetBrowserContext())
->GetNetworkContext()
- ->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), 0);
+ ->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory),
+ std::move(params));
network::ResourceRequest request;
network::TestURLLoaderClient client;
@@ -80,6 +93,71 @@ IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest, NetworkContext) {
EXPECT_EQ("bar", foo_header_value);
}
+// Make sure the factory info returned from
+// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| works.
+IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest,
+ GetURLLoaderFactoryForBrowserProcessIOThread) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ auto shared_url_loader_factory_info =
+ BrowserContext::GetDefaultStoragePartition(
+ shell()->web_contents()->GetBrowserContext())
+ ->GetURLLoaderFactoryForBrowserProcessIOThread();
+
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ std::move(shared_url_loader_factory_info));
+
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
+}
+
+// Make sure the factory info returned from
+// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| doesn't
+// crash if it's called after the StoragePartition is deleted.
+IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest,
+ BrowserIOFactoryInfoAfterStoragePartitionGone) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ std::unique_ptr<ShellBrowserContext> browser_context =
+ std::make_unique<ShellBrowserContext>(true, nullptr);
+ auto* partition =
+ BrowserContext::GetDefaultStoragePartition(browser_context.get());
+ auto shared_url_loader_factory_info =
+ partition->GetURLLoaderFactoryForBrowserProcessIOThread();
+
+ browser_context.reset();
+
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ std::move(shared_url_loader_factory_info));
+
+ EXPECT_EQ(net::ERR_FAILED,
+ factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
+}
+
+// Make sure the factory constructed from
+// |StoragePartition::GetURLLoaderFactoryForBrowserProcessIOThread()| doesn't
+// crash if it's called after the StoragePartition is deleted.
+IN_PROC_BROWSER_TEST_P(StoragePartititionImplBrowsertest,
+ BrowserIOFactoryAfterStoragePartitionGone) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ std::unique_ptr<ShellBrowserContext> browser_context =
+ std::make_unique<ShellBrowserContext>(true, nullptr);
+ auto* partition =
+ BrowserContext::GetDefaultStoragePartition(browser_context.get());
+ auto factory_owner = IOThreadSharedURLLoaderFactoryOwner::Create(
+ partition->GetURLLoaderFactoryForBrowserProcessIOThread());
+
+ EXPECT_EQ(net::OK, factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
+
+ browser_context.reset();
+
+ EXPECT_EQ(net::ERR_FAILED,
+ factory_owner->LoadBasicRequestOnIOThread(GetTestURL()));
+}
+
// NetworkServiceState::kEnabled currently DCHECKs on Android, as Android isn't
// expected to create extra processes.
#if defined(OS_ANDROID)
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index 7225a2a55d2..3be6979bde8 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -25,6 +25,7 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/devtools/devtools_url_request_interceptor.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
@@ -37,17 +38,18 @@
#include "content/browser/streams/stream_registry.h"
#include "content/browser/streams/stream_url_request_job.h"
#include "content/browser/webui/url_data_manager_backend.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/origin_trial_policy.h"
#include "content/public/common/url_constants.h"
#include "crypto/sha2.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/features.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/blob/blob_url_request_job_factory.h"
#include "storage/browser/fileapi/file_system_url_request_job_factory.h"
@@ -434,6 +436,18 @@ StoragePartitionImpl* StoragePartitionImplMap::Get(
browser_context_->CreateMediaRequestContext() :
browser_context_->CreateMediaRequestContextForStoragePartition(
partition->GetPath(), in_memory));
+ partition->GetCookieStoreContext()->ListenToCookieChanges(
+ partition->GetNetworkContext(), base::DoNothing());
+
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ // This needs to happen after SetURLRequestContext() since we need this
+ // code path only for non-NetworkService cases where NetworkContext needs to
+ // be initialized using |url_request_context_|, which is initialized by
+ // SetURLRequestContext().
+ DCHECK(partition->url_loader_factory_getter());
+ DCHECK(partition->url_request_context_);
+ partition->url_loader_factory_getter()->HandleFactoryRequests();
+ }
PostCreateInitialization(partition, in_memory);
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index b51d8011af8..b151ad3c097 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -8,7 +8,6 @@
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
@@ -29,6 +28,7 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/buildflags/buildflags.h"
+#include "services/network/cookie_manager.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/test/mock_quota_manager.h"
#include "storage/browser/test/mock_special_storage_policy.h"
@@ -44,6 +44,8 @@
#endif // BUILDFLAG(ENABLE_PLUGINS)
using net::CanonicalCookie;
+using CookieDeletionFilter = network::mojom::CookieDeletionFilter;
+using CookieDeletionFilterPtr = network::mojom::CookieDeletionFilterPtr;
namespace content {
namespace {
@@ -80,14 +82,6 @@ const uint32_t kAllQuotaRemoveMask =
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
StoragePartition::REMOVE_DATA_MASK_WEBSQL;
-bool AlwaysTrueCookiePredicate(const net::CanonicalCookie& cookie) {
- return true;
-}
-
-bool AlwaysFalseCookiePredicate(const net::CanonicalCookie& cookie) {
- return false;
-}
-
class AwaitCompletionHelper {
public:
AwaitCompletionHelper() : start_(false), already_quit_(false) {}
@@ -573,16 +567,19 @@ void ClearCookies(content::StoragePartition* partition,
delete_begin, delete_end, run_loop->QuitClosure());
}
-void ClearCookiesWithMatcher(
- content::StoragePartition* partition,
- const base::Time delete_begin,
- const base::Time delete_end,
- const StoragePartition::CookieMatcherFunction& cookie_matcher,
- base::RunLoop* run_loop) {
+void ClearCookiesMatchingInfo(content::StoragePartition* partition,
+ CookieDeletionFilterPtr delete_filter,
+ base::RunLoop* run_loop) {
+ base::Time delete_begin;
+ if (delete_filter->created_after_time.has_value())
+ delete_begin = delete_filter->created_after_time.value();
+ base::Time delete_end;
+ if (delete_filter->created_before_time.has_value())
+ delete_end = delete_filter->created_before_time.value();
partition->ClearData(StoragePartition::REMOVE_DATA_MASK_COOKIES,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
StoragePartition::OriginMatcherFunction(),
- cookie_matcher, delete_begin, delete_end,
+ std::move(delete_filter), delete_begin, delete_end,
run_loop->QuitClosure());
}
@@ -622,6 +619,11 @@ void ClearPluginPrivateData(content::StoragePartition* partition,
}
#endif // BUILDFLAG(ENABLE_PLUGINS)
+bool FilterMatchesCookie(const CookieDeletionFilterPtr& filter,
+ const net::CanonicalCookie& cookie) {
+ return network::DeletionFilterToInfo(filter.Clone()).Matches(cookie);
+}
+
} // namespace
class StoragePartitionImplTest : public testing::Test {
@@ -1130,13 +1132,8 @@ TEST_F(StoragePartitionImplTest, RemoveCookieLastHour) {
EXPECT_FALSE(tester.ContainsCookie());
}
-TEST_F(StoragePartitionImplTest, RemoveCookieWithMatcher) {
+TEST_F(StoragePartitionImplTest, RemoveCookieWithDeleteInfo) {
RemoveCookieTester tester(browser_context());
- StoragePartition::CookieMatcherFunction true_predicate =
- base::Bind(&AlwaysTrueCookiePredicate);
-
- StoragePartition::CookieMatcherFunction false_predicate =
- base::Bind(&AlwaysFalseCookiePredicate);
tester.AddCookie();
ASSERT_TRUE(tester.ContainsCookie());
@@ -1145,21 +1142,10 @@ TEST_F(StoragePartitionImplTest, RemoveCookieWithMatcher) {
BrowserContext::GetDefaultStoragePartition(browser_context()));
partition->SetURLRequestContext(browser_context()->GetRequestContext());
- // Return false from our predicate, and make sure the cookies is still around.
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&ClearCookiesWithMatcher, partition, base::Time(),
- base::Time::Max(), std::move(false_predicate), &run_loop));
- run_loop.RunUntilIdle();
- EXPECT_TRUE(tester.ContainsCookie());
-
- // Now we return true from our predicate.
base::RunLoop run_loop2;
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&ClearCookiesWithMatcher, partition, base::Time(),
- base::Time::Max(), std::move(true_predicate), &run_loop2));
+ FROM_HERE, base::BindOnce(&ClearCookiesMatchingInfo, partition,
+ CookieDeletionFilter::New(), &run_loop2));
run_loop2.RunUntilIdle();
EXPECT_FALSE(tester.ContainsCookie());
}
@@ -1397,8 +1383,8 @@ TEST(StoragePartitionImplStaticTest, CreatePredicateForHostCookies) {
GURL url3("https://www.google.com/");
net::CookieOptions options;
- net::CookieStore::CookiePredicate predicate =
- StoragePartitionImpl::CreatePredicateForHostCookies(url);
+ CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
+ deletion_filter->host_name = url.host();
base::Time now = base::Time::Now();
std::vector<std::unique_ptr<CanonicalCookie>> valid_cookies;
@@ -1413,10 +1399,14 @@ TEST(StoragePartitionImplStaticTest, CreatePredicateForHostCookies) {
CanonicalCookie::Create(url2, "A=B;domain=.example.com", now, options));
invalid_cookies.push_back(CanonicalCookie::Create(url3, "A=B", now, options));
- for (const auto& cookie : valid_cookies)
- EXPECT_TRUE(predicate.Run(*cookie)) << cookie->DebugString();
- for (const auto& cookie : invalid_cookies)
- EXPECT_FALSE(predicate.Run(*cookie)) << cookie->DebugString();
+ for (const auto& cookie : valid_cookies) {
+ EXPECT_TRUE(FilterMatchesCookie(deletion_filter, *cookie))
+ << cookie->DebugString();
+ }
+ for (const auto& cookie : invalid_cookies) {
+ EXPECT_FALSE(FilterMatchesCookie(deletion_filter, *cookie))
+ << cookie->DebugString();
+ }
}
} // namespace content
diff --git a/chromium/content/browser/streams/stream.cc b/chromium/content/browser/streams/stream.cc
index 8a018a7895f..8ce10de0d94 100644
--- a/chromium/content/browser/streams/stream.cc
+++ b/chromium/content/browser/streams/stream.cc
@@ -42,10 +42,10 @@ Stream::Stream(StreamRegistry* registry,
&writer_, &reader_);
// Setup callback for writing.
- writer_->RegisterCallback(base::Bind(&Stream::OnSpaceAvailable,
- weak_ptr_factory_.GetWeakPtr()));
- reader_->RegisterCallback(base::Bind(&Stream::OnDataAvailable,
- weak_ptr_factory_.GetWeakPtr()));
+ writer_->RegisterCallback(base::BindRepeating(
+ &Stream::OnSpaceAvailable, weak_ptr_factory_.GetWeakPtr()));
+ reader_->RegisterCallback(base::BindRepeating(
+ &Stream::OnDataAvailable, weak_ptr_factory_.GetWeakPtr()));
registry_->RegisterStream(this);
}
diff --git a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
index ead569f8522..374da5bb307 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -107,16 +107,13 @@ class BackgroundTracingManagerBrowserTest : public ContentBrowserTest {
class BackgroundTracingManagerUploadConfigWrapper {
public:
- BackgroundTracingManagerUploadConfigWrapper(const base::Closure& callback)
- : callback_(callback), receive_count_(0) {
- receive_callback_ =
- base::Bind(&BackgroundTracingManagerUploadConfigWrapper::Upload,
- base::Unretained(this));
- }
+ BackgroundTracingManagerUploadConfigWrapper(base::OnceClosure callback)
+ : callback_(std::move(callback)), receive_count_(0) {}
- void Upload(const scoped_refptr<base::RefCountedString>& file_contents,
- std::unique_ptr<const base::DictionaryValue> metadata,
- base::Callback<void()> done_callback) {
+ void Upload(
+ const scoped_refptr<base::RefCountedString>& file_contents,
+ std::unique_ptr<const base::DictionaryValue> metadata,
+ BackgroundTracingManager::FinishedProcessingCallback done_callback) {
receive_count_ += 1;
EXPECT_TRUE(file_contents);
@@ -142,8 +139,9 @@ class BackgroundTracingManagerUploadConfigWrapper {
last_file_contents_.assign(output_str.data(), bytes_written);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- std::move(done_callback));
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback_);
+ base::BindOnce(std::move(done_callback), true));
+ CHECK(callback_);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback_));
}
bool TraceHasMatchingString(const char* str) {
@@ -152,14 +150,13 @@ class BackgroundTracingManagerUploadConfigWrapper {
int get_receive_count() const { return receive_count_; }
- const BackgroundTracingManager::ReceiveCallback& get_receive_callback()
- const {
- return receive_callback_;
+ BackgroundTracingManager::ReceiveCallback get_receive_callback() {
+ return base::BindOnce(&BackgroundTracingManagerUploadConfigWrapper::Upload,
+ base::Unretained(this));
}
private:
- BackgroundTracingManager::ReceiveCallback receive_callback_;
- base::Closure callback_;
+ base::OnceClosure callback_;
int receive_count_;
std::string last_file_contents_;
};
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.cc b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
index 6fd8e9c19e2..c6aefd65be1 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -25,7 +25,7 @@
#include "content/public/browser/tracing_delegate.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
-#include "services/tracing/public/cpp/chrome_trace_event_agent.h"
+#include "services/tracing/public/cpp/trace_event_agent.h"
namespace content {
@@ -44,8 +44,10 @@ enum BackgroundTracingMetrics {
FINALIZATION_ALLOWED = 5,
FINALIZATION_DISALLOWED = 6,
FINALIZATION_STARTED = 7,
- FINALIZATION_COMPLETE = 8,
+ OBSOLETE_FINALIZATION_COMPLETE = 8,
SCENARIO_ACTION_FAILED_LOWRES_CLOCK = 9,
+ UPLOAD_FAILED = 10,
+ UPLOAD_SUCCEEDED = 11,
NUMBER_OF_BACKGROUND_TRACING_METRICS,
};
@@ -105,9 +107,11 @@ BackgroundTracingManagerImpl::~BackgroundTracingManagerImpl() {
}
void BackgroundTracingManagerImpl::AddMetadataGeneratorFunction() {
- tracing::ChromeTraceEventAgent::GetInstance()->AddMetadataGeneratorFunction(
- base::BindRepeating(&BackgroundTracingManagerImpl::GenerateMetadataDict,
- base::Unretained(this)));
+ TracingControllerImpl::GetInstance()
+ ->GetTraceEventAgent()
+ ->AddMetadataGeneratorFunction(base::BindRepeating(
+ &BackgroundTracingManagerImpl::GenerateMetadataDict,
+ base::Unretained(this)));
}
void BackgroundTracingManagerImpl::WhenIdle(
@@ -118,7 +122,7 @@ void BackgroundTracingManagerImpl::WhenIdle(
bool BackgroundTracingManagerImpl::SetActiveScenario(
std::unique_ptr<BackgroundTracingConfig> config,
- const BackgroundTracingManager::ReceiveCallback& receive_callback,
+ BackgroundTracingManager::ReceiveCallback receive_callback,
DataFiltering data_filtering) {
CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
RecordBackgroundTracingMetric(SCENARIO_ACTIVATION_REQUESTED);
@@ -178,7 +182,7 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
}
config_ = std::move(config_impl);
- receive_callback_ = receive_callback;
+ receive_callback_ = std::move(receive_callback);
requires_anonymized_data_ = requires_anonymized_data;
if (config_) {
@@ -503,21 +507,21 @@ void BackgroundTracingManagerImpl::OnFinalizeStarted(
file_contents->size() / 1024);
if (!receive_callback_.is_null()) {
- receive_callback_.Run(
- file_contents, std::move(metadata),
- base::Bind(&BackgroundTracingManagerImpl::OnFinalizeComplete,
- base::Unretained(this)));
+ std::move(receive_callback_)
+ .Run(file_contents, std::move(metadata),
+ base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
+ base::Unretained(this)));
}
if (!started_finalizing_closure.is_null())
std::move(started_finalizing_closure).Run();
}
-void BackgroundTracingManagerImpl::OnFinalizeComplete() {
+void BackgroundTracingManagerImpl::OnFinalizeComplete(bool success) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&BackgroundTracingManagerImpl::OnFinalizeComplete,
- base::Unretained(this)));
+ base::Unretained(this), success));
return;
}
@@ -541,7 +545,11 @@ void BackgroundTracingManagerImpl::OnFinalizeComplete() {
AbortScenario();
}
- RecordBackgroundTracingMetric(FINALIZATION_COMPLETE);
+ if (success) {
+ RecordBackgroundTracingMetric(UPLOAD_SUCCEEDED);
+ } else {
+ RecordBackgroundTracingMetric(UPLOAD_FAILED);
+ }
}
bool BackgroundTracingManagerImpl::IsAllowedFinalization() const {
@@ -560,9 +568,10 @@ BackgroundTracingManagerImpl::GenerateMetadataDict() {
auto config_dict = std::make_unique<base::DictionaryValue>();
config_->IntoDict(config_dict.get());
metadata_dict->Set("config", std::move(config_dict));
+ metadata_dict->SetString("scenario_name", config_->scenario_name());
}
if (last_triggered_rule_)
- metadata_dict->Set("last_triggered_rule_", std::move(last_triggered_rule_));
+ metadata_dict->Set("last_triggered_rule", std::move(last_triggered_rule_));
return metadata_dict;
}
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.h b/chromium/content/browser/tracing/background_tracing_manager_impl.h
index d99219b37db..d5c8fe92c1b 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.h
@@ -58,7 +58,7 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
CONTENT_EXPORT static BackgroundTracingManagerImpl* GetInstance();
bool SetActiveScenario(std::unique_ptr<BackgroundTracingConfig>,
- const ReceiveCallback&,
+ ReceiveCallback,
DataFiltering data_filtering) override;
void WhenIdle(IdleCallback idle_callback) override;
@@ -104,7 +104,7 @@ class BackgroundTracingManagerImpl : public BackgroundTracingManager {
void OnFinalizeStarted(base::Closure started_finalizing_closure,
std::unique_ptr<const base::DictionaryValue> metadata,
base::RefCountedString*);
- void OnFinalizeComplete();
+ void OnFinalizeComplete(bool success);
void BeginFinalizing(StartedFinalizingCallback);
void ValidateStartupScenario();
diff --git a/chromium/content/browser/tracing/cast_tracing_agent.cc b/chromium/content/browser/tracing/cast_tracing_agent.cc
index a281910d210..41b62141455 100644
--- a/chromium/content/browser/tracing/cast_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cast_tracing_agent.cc
@@ -55,19 +55,18 @@ CastTracingAgent::CastTracingAgent(service_manager::Connector* connector)
CastTracingAgent::~CastTracingAgent() = default;
// tracing::mojom::Agent. Called by Mojo internals on the UI thread.
-void CastTracingAgent::StartTracing(
- const std::string& config,
- base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) {
+void CastTracingAgent::StartTracing(const std::string& config,
+ base::TimeTicks coordinator_time,
+ Agent::StartTracingCallback callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::trace_event::TraceConfig trace_config(config);
if (!trace_config.IsSystraceEnabled()) {
- callback.Run(false /* success */);
+ std::move(callback).Run(false /* success */);
return;
}
- start_tracing_callback_ = callback;
+ start_tracing_callback_ = std::move(callback);
task_runner_->PostTask(FROM_HERE,
base::BindOnce(&CastTracingAgent::StartTracingOnIO,
@@ -86,9 +85,8 @@ void CastTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {
base::ThreadTaskRunnerHandle::Get()));
}
-void CastTracingAgent::GetCategories(
- const Agent::GetCategoriesCallback& callback) {
- callback.Run(GetAllTracingCategories());
+void CastTracingAgent::GetCategories(Agent::GetCategoriesCallback callback) {
+ std::move(callback).Run(GetAllTracingCategories());
}
void CastTracingAgent::StartTracingOnIO(
@@ -116,7 +114,8 @@ void CastTracingAgent::FinishStartOnIO(
void CastTracingAgent::FinishStart(chromecast::SystemTracer::Status status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- start_tracing_callback_.Run(status == chromecast::SystemTracer::Status::OK);
+ std::move(start_tracing_callback_)
+ .Run(status == chromecast::SystemTracer::Status::OK);
}
void CastTracingAgent::StopAndFlushOnIO(
diff --git a/chromium/content/browser/tracing/cast_tracing_agent.h b/chromium/content/browser/tracing/cast_tracing_agent.h
index b26a3bde810..1604d951de3 100644
--- a/chromium/content/browser/tracing/cast_tracing_agent.h
+++ b/chromium/content/browser/tracing/cast_tracing_agent.h
@@ -31,9 +31,9 @@ class CastTracingAgent : public tracing::BaseAgent {
// tracing::mojom::Agent. Called by Mojo internals on the UI thread.
void StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) override;
+ Agent::StartTracingCallback callback) override;
void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
- void GetCategories(const Agent::GetCategoriesCallback& callback) override;
+ void GetCategories(Agent::GetCategoriesCallback callback) override;
void StartTracingOnIO(scoped_refptr<base::TaskRunner> reply_task_runner,
const std::string& categories);
diff --git a/chromium/content/browser/tracing/cros_tracing_agent.cc b/chromium/content/browser/tracing/cros_tracing_agent.cc
index bb6fd6545d2..30bb8757a81 100644
--- a/chromium/content/browser/tracing/cros_tracing_agent.cc
+++ b/chromium/content/browser/tracing/cros_tracing_agent.cc
@@ -31,35 +31,35 @@ CrOSTracingAgent::CrOSTracingAgent(service_manager::Connector* connector)
CrOSTracingAgent::~CrOSTracingAgent() = default;
// tracing::mojom::Agent. Called by Mojo internals on the UI thread.
-void CrOSTracingAgent::StartTracing(
- const std::string& config,
- base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) {
+void CrOSTracingAgent::StartTracing(const std::string& config,
+ base::TimeTicks coordinator_time,
+ Agent::StartTracingCallback callback) {
base::trace_event::TraceConfig trace_config(config);
debug_daemon_ = chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
if (!trace_config.IsSystraceEnabled() || !debug_daemon_) {
- callback.Run(false /* success */);
+ std::move(callback).Run(false /* success */);
return;
}
- start_tracing_callback_ = std::move(callback);
debug_daemon_->SetStopAgentTracingTaskRunner(
base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}));
debug_daemon_->StartAgentTracing(
trace_config,
- base::BindRepeating(&CrOSTracingAgent::StartTracingCallbackProxy,
- base::Unretained(this)));
+ base::BindOnce(&CrOSTracingAgent::StartTracingCallbackProxy,
+ base::Unretained(this), std::move(callback)));
}
void CrOSTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {
DCHECK(debug_daemon_);
recorder_ = std::move(recorder);
- debug_daemon_->StopAgentTracing(base::BindRepeating(
- &CrOSTracingAgent::RecorderProxy, base::Unretained(this)));
+ debug_daemon_->StopAgentTracing(
+ base::BindOnce(&CrOSTracingAgent::RecorderProxy, base::Unretained(this)));
}
-void CrOSTracingAgent::StartTracingCallbackProxy(const std::string& agent_name,
- bool success) {
- start_tracing_callback_.Run(success);
+void CrOSTracingAgent::StartTracingCallbackProxy(
+ Agent::StartTracingCallback callback,
+ const std::string& agent_name,
+ bool success) {
+ std::move(callback).Run(success);
}
void CrOSTracingAgent::RecorderProxy(
diff --git a/chromium/content/browser/tracing/cros_tracing_agent.h b/chromium/content/browser/tracing/cros_tracing_agent.h
index 2bf56ab1ff8..182163621af 100644
--- a/chromium/content/browser/tracing/cros_tracing_agent.h
+++ b/chromium/content/browser/tracing/cros_tracing_agent.h
@@ -37,16 +37,17 @@ class CrOSTracingAgent : public tracing::BaseAgent {
// tracing::mojom::Agent. Called by Mojo internals on the UI thread.
void StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) override;
+ Agent::StartTracingCallback callback) override;
void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
- void StartTracingCallbackProxy(const std::string& agent_name, bool success);
+ void StartTracingCallbackProxy(Agent::StartTracingCallback callback,
+ const std::string& agent_name,
+ bool success);
void RecorderProxy(const std::string& event_name,
const std::string& events_label,
const scoped_refptr<base::RefCountedString>& events);
chromeos::DebugDaemonClient* debug_daemon_ = nullptr;
- Agent::StartTracingCallback start_tracing_callback_;
tracing::mojom::RecorderPtr recorder_;
DISALLOW_COPY_AND_ASSIGN(CrOSTracingAgent);
diff --git a/chromium/content/browser/tracing/etw_tracing_agent_win.cc b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
index adc428b6a9c..f25811775f2 100644
--- a/chromium/content/browser/tracing/etw_tracing_agent_win.cc
+++ b/chromium/content/browser/tracing/etw_tracing_agent_win.cc
@@ -59,14 +59,13 @@ EtwTracingAgent::~EtwTracingAgent() {
g_etw_tracing_agent = nullptr;
}
-void EtwTracingAgent::StartTracing(
- const std::string& config,
- base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) {
+void EtwTracingAgent::StartTracing(const std::string& config,
+ base::TimeTicks coordinator_time,
+ Agent::StartTracingCallback callback) {
base::trace_event::TraceConfig trace_config(config);
// Activate kernel tracing.
if (!trace_config.IsSystraceEnabled() || !StartKernelSessionTracing()) {
- callback.Run(false /* success */);
+ std::move(callback).Run(false /* success */);
return;
}
is_tracing_ = true;
@@ -77,9 +76,9 @@ void EtwTracingAgent::StartTracing(
// Tracing agents, e.g. this, live as long as BrowserMainLoop lives and so
// using base::Unretained here is safe.
thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&EtwTracingAgent::TraceAndConsumeOnThread,
- base::Unretained(this)));
- callback.Run(true /* success */);
+ FROM_HERE, base::BindOnce(&EtwTracingAgent::TraceAndConsumeOnThread,
+ base::Unretained(this)));
+ std::move(callback).Run(true /* success */);
}
void EtwTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {
@@ -93,7 +92,7 @@ void EtwTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {
// BrowserMainLoop lives and so using base::Unretained here is safe.
thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&EtwTracingAgent::FlushOnThread, base::Unretained(this)));
+ base::BindOnce(&EtwTracingAgent::FlushOnThread, base::Unretained(this)));
}
void EtwTracingAgent::OnStopSystemTracingDone(const std::string& output) {
diff --git a/chromium/content/browser/tracing/etw_tracing_agent_win.h b/chromium/content/browser/tracing/etw_tracing_agent_win.h
index 5136a197539..f9e78372bdb 100644
--- a/chromium/content/browser/tracing/etw_tracing_agent_win.h
+++ b/chromium/content/browser/tracing/etw_tracing_agent_win.h
@@ -43,7 +43,7 @@ class EtwTracingAgent : public base::win::EtwTraceConsumerBase<EtwTracingAgent>,
// tracing::mojom::Agent. Called by Mojo internals on the UI thread.
void StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) override;
+ Agent::StartTracingCallback callback) override;
void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
// Static override of EtwTraceConsumerBase::ProcessEvent.
diff --git a/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc b/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc
index 5ebe6aa5eb3..1eeb12aa138 100644
--- a/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc
+++ b/chromium/content/browser/tracing/memory_instrumentation_browsertest.cc
@@ -27,7 +27,7 @@ namespace content {
class MemoryInstrumentationTest : public ContentBrowserTest {
protected:
void Navigate(Shell* shell) {
- NavigateToURL(shell, GetTestUrl("", "title.html"));
+ EXPECT_TRUE(NavigateToURL(shell, GetTestUrl("", "title1.html")));
}
};
@@ -72,7 +72,7 @@ std::unique_ptr<GlobalMemoryDump> DoGlobalDump() {
defined(THREAD_SANITIZER)
#define MAYBE_PrivateFootprintComputation DISABLED_PrivateFootprintComputation
#else
-#define MAYBE_PrivateFootprintComputation PrivateFootprintComputatio
+#define MAYBE_PrivateFootprintComputation PrivateFootprintComputation
#endif
// Despite the location, this test is not tracing related.
@@ -96,7 +96,7 @@ IN_PROC_BROWSER_TEST_F(MemoryInstrumentationTest,
content::WebContents* web_contents = shell()->web_contents();
base::ProcessId renderer_pid =
- base::GetProcId(web_contents->GetMainFrame()->GetProcess()->GetHandle());
+ web_contents->GetMainFrame()->GetProcess()->GetProcess().Pid();
// Should allocate at least 4*10^6 / 1024 = 4000kb.
EXPECT_TRUE(content::ExecuteScript(web_contents,
diff --git a/chromium/content/browser/tracing/power_tracing_agent.cc b/chromium/content/browser/tracing/power_tracing_agent.cc
index af496fb0d81..2ae2a4d50da 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.cc
+++ b/chromium/content/browser/tracing/power_tracing_agent.cc
@@ -51,46 +51,46 @@ PowerTracingAgent::PowerTracingAgent(service_manager::Connector* connector)
PowerTracingAgent::PowerTracingAgent() : binding_(this) {}
PowerTracingAgent::~PowerTracingAgent() = default;
-void PowerTracingAgent::StartTracing(
- const std::string& config,
- base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) {
+void PowerTracingAgent::StartTracing(const std::string& config,
+ base::TimeTicks coordinator_time,
+ Agent::StartTracingCallback callback) {
base::trace_event::TraceConfig trace_config(config);
if (!trace_config.IsSystraceEnabled()) {
- callback.Run(false /* success */);
+ std::move(callback).Run(false /* success */);
return;
}
base::PostTaskWithTraits(
FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
base::BindOnce(&PowerTracingAgent::FindBattOrOnBackgroundThread,
- base::Unretained(this), callback));
+ base::Unretained(this), std::move(callback)));
}
void PowerTracingAgent::FindBattOrOnBackgroundThread(
- const Agent::StartTracingCallback& callback) {
+ Agent::StartTracingCallback callback) {
std::string path = battor::BattOrFinder::FindBattOr();
if (path.empty()) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback, false /* success */));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(callback), false /* success */));
return;
}
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&PowerTracingAgent::StartTracingOnIOThread,
- base::Unretained(this), path, callback));
+ base::Unretained(this), path, std::move(callback)));
}
void PowerTracingAgent::StartTracingOnIOThread(
const std::string& path,
- const Agent::StartTracingCallback& callback) {
+ Agent::StartTracingCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
battor_agent_.reset(new battor::BattOrAgent(
path, this, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)));
- start_tracing_callback_ = callback;
+ start_tracing_callback_ = std::move(callback);
battor_agent_->StartTracing();
}
@@ -101,9 +101,9 @@ void PowerTracingAgent::OnStartTracingComplete(battor::BattOrError error) {
if (!success)
battor_agent_.reset();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(start_tracing_callback_, success));
- start_tracing_callback_.Reset();
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(start_tracing_callback_), success));
}
void PowerTracingAgent::StopAndFlush(tracing::mojom::RecorderPtr recorder) {
@@ -137,27 +137,28 @@ void PowerTracingAgent::OnStopTracingComplete(
void PowerTracingAgent::RequestClockSyncMarker(
const std::string& sync_id,
- const Agent::RequestClockSyncMarkerCallback& callback) {
+ Agent::RequestClockSyncMarkerCallback callback) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&PowerTracingAgent::RequestClockSyncMarkerOnIOThread,
- base::Unretained(this), sync_id, callback));
+ base::Unretained(this), sync_id, std::move(callback)));
}
void PowerTracingAgent::RequestClockSyncMarkerOnIOThread(
const std::string& sync_id,
- const Agent::RequestClockSyncMarkerCallback& callback) {
+ Agent::RequestClockSyncMarkerCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// This makes sense only when the battor agent exists.
if (!battor_agent_) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback, base::TimeTicks(), base::TimeTicks()));
+ base::BindOnce(std::move(callback), base::TimeTicks(),
+ base::TimeTicks()));
return;
}
- request_clock_sync_marker_callback_ = callback;
+ request_clock_sync_marker_callback_ = std::move(callback);
request_clock_sync_marker_start_time_ = TRACE_TIME_TICKS_NOW();
battor_agent_->RecordClockSyncMarker(sync_id);
}
@@ -172,11 +173,10 @@ void PowerTracingAgent::OnRecordClockSyncMarkerComplete(
if (error != battor::BATTOR_ERROR_NONE)
issue_start_ts = issue_end_ts = base::TimeTicks();
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(request_clock_sync_marker_callback_,
- issue_start_ts, issue_end_ts));
-
- request_clock_sync_marker_callback_.Reset();
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(std::move(request_clock_sync_marker_callback_),
+ issue_start_ts, issue_end_ts));
request_clock_sync_marker_start_time_ = base::TimeTicks();
}
@@ -185,14 +185,13 @@ void PowerTracingAgent::OnGetFirmwareGitHashComplete(
return;
}
-void PowerTracingAgent::GetCategories(
- const Agent::GetCategoriesCallback& callback) {
- callback.Run("");
+void PowerTracingAgent::GetCategories(Agent::GetCategoriesCallback callback) {
+ std::move(callback).Run("");
}
void PowerTracingAgent::RequestBufferStatus(
- const Agent::RequestBufferStatusCallback& callback) {
- callback.Run(0, 0);
+ Agent::RequestBufferStatusCallback callback) {
+ std::move(callback).Run(0, 0);
}
} // namespace content
diff --git a/chromium/content/browser/tracing/power_tracing_agent.h b/chromium/content/browser/tracing/power_tracing_agent.h
index 5e7f9a33440..6623bc121d5 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.h
+++ b/chromium/content/browser/tracing/power_tracing_agent.h
@@ -57,23 +57,22 @@ class PowerTracingAgent : public Agent, public battor::BattOrAgent::Listener {
// tracing::mojom::Agent. Called by Mojo internals on the UI thread.
void StartTracing(const std::string& config,
base::TimeTicks coordinator_time,
- const Agent::StartTracingCallback& callback) override;
+ Agent::StartTracingCallback callback) override;
void StopAndFlush(tracing::mojom::RecorderPtr recorder) override;
void RequestClockSyncMarker(
const std::string& sync_id,
- const Agent::RequestClockSyncMarkerCallback& callback) override;
- void GetCategories(const Agent::GetCategoriesCallback& callback) override;
+ Agent::RequestClockSyncMarkerCallback callback) override;
+ void GetCategories(Agent::GetCategoriesCallback callback) override;
void RequestBufferStatus(
- const Agent::RequestBufferStatusCallback& callback) override;
+ Agent::RequestBufferStatusCallback callback) override;
- void FindBattOrOnBackgroundThread(
- const Agent::StartTracingCallback& callback);
+ void FindBattOrOnBackgroundThread(Agent::StartTracingCallback callback);
void StartTracingOnIOThread(const std::string& path,
- const Agent::StartTracingCallback& callback);
+ Agent::StartTracingCallback callback);
void StopAndFlushOnIOThread(tracing::mojom::RecorderPtr recorder);
void RequestClockSyncMarkerOnIOThread(
const std::string& sync_id,
- const Agent::RequestClockSyncMarkerCallback& callback);
+ Agent::RequestClockSyncMarkerCallback callback);
// Returns the path of a BattOr (e.g. /dev/ttyUSB0), or an empty string if
// none are found.
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index ba83d7cfed8..680c54845a5 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -23,7 +23,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/test_content_browser_client.h"
-#include "services/tracing/public/cpp/chrome_trace_event_agent.h"
+#include "services/tracing/public/cpp/trace_event_agent.h"
using base::trace_event::RECORD_CONTINUOUSLY;
using base::trace_event::RECORD_UNTIL_FULL;
@@ -236,10 +236,9 @@ class TracingControllerTest : public ContentBrowserTest {
base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
base::Bind(&IsTraceEventArgsWhitelisted));
- TracingController* controller = TracingController::GetInstance();
- tracing::ChromeTraceEventAgent::GetInstance()->AddMetadataGeneratorFunction(
- base::Bind(&TracingControllerTest::GenerateMetadataDict,
- base::Unretained(this)));
+ TracingControllerImpl* controller = TracingControllerImpl::GetInstance();
+ controller->GetTraceEventAgent()->AddMetadataGeneratorFunction(base::Bind(
+ &TracingControllerTest::GenerateMetadataDict, base::Unretained(this)));
{
base::RunLoop run_loop;
@@ -391,9 +390,6 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, DisableRecordingStoresMetadata) {
std::string os_name;
last_metadata()->GetString("os-name", &os_name);
EXPECT_TRUE(os_name.length() > 0);
- std::string cpu_brand;
- last_metadata()->GetString("cpu-brand", &cpu_brand);
- EXPECT_TRUE(cpu_brand.length() > 0);
std::string command_line;
last_metadata()->GetString("command_line", &command_line);
EXPECT_TRUE(command_line.length() > 0);
@@ -408,10 +404,6 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest,
TestStartAndStopTracingStringWithFilter();
// Check that a number of important keys exist in the metadata dictionary.
EXPECT_TRUE(last_metadata() != nullptr);
- std::string cpu_brand;
- last_metadata()->GetString("cpu-brand", &cpu_brand);
- EXPECT_TRUE(cpu_brand.length() > 0);
- EXPECT_TRUE(cpu_brand != "__stripped__");
std::string network_type;
last_metadata()->GetString("network-type", &network_type);
EXPECT_TRUE(network_type.length() > 0);
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index 14eff00db8c..0ae496ae61e 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -20,7 +20,7 @@
#include "base/trace_event/trace_config.h"
#include "base/values.h"
#include "build/build_config.h"
-#include "components/tracing/common/trace_config_file.h"
+#include "components/tracing/common/trace_startup_config.h"
#include "content/browser/tracing/file_tracing_provider_impl.h"
#include "content/browser/tracing/tracing_ui.h"
#include "content/public/browser/browser_thread.h"
@@ -34,7 +34,7 @@
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/network_change_notifier.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "services/tracing/public/cpp/chrome_trace_event_agent.h"
+#include "services/tracing/public/cpp/trace_event_agent.h"
#include "services/tracing/public/mojom/constants.mojom.h"
#include "v8/include/v8-version-string.h"
@@ -61,6 +61,13 @@
#include "content/browser/tracing/etw_tracing_agent_win.h"
#endif
+#if defined(OS_ANDROID)
+#include "base/debug/elf_reader_linux.h"
+
+// Symbol with virtual address of the start of ELF header of the current binary.
+extern char __ehdr_start;
+#endif // defined(OS_ANDROID)
+
namespace content {
namespace {
@@ -146,18 +153,24 @@ void TracingControllerImpl::AddAgents() {
agents_.push_back(std::make_unique<EtwTracingAgent>(connector));
#endif
- auto chrome_agent = std::make_unique<tracing::ChromeTraceEventAgent>(
+ auto trace_event_agent = tracing::TraceEventAgent::Create(
connector, true /* request_clock_sync_marker_on_android */);
+
// For adding general CPU, network, OS, and other system information to the
// metadata.
- chrome_agent->AddMetadataGeneratorFunction(base::BindRepeating(
+ trace_event_agent->AddMetadataGeneratorFunction(base::BindRepeating(
&TracingControllerImpl::GenerateMetadataDict, base::Unretained(this)));
if (delegate_) {
- chrome_agent->AddMetadataGeneratorFunction(
+ trace_event_agent->AddMetadataGeneratorFunction(
base::BindRepeating(&TracingDelegate::GenerateMetadataDict,
base::Unretained(delegate_.get())));
}
- agents_.push_back(std::move(chrome_agent));
+ trace_event_agent_ = std::move(trace_event_agent);
+}
+
+tracing::TraceEventAgent* TracingControllerImpl::GetTraceEventAgent() const {
+ DCHECK(trace_event_agent_);
+ return trace_event_agent_.get();
}
std::unique_ptr<base::DictionaryValue>
@@ -179,6 +192,17 @@ TracingControllerImpl::GenerateMetadataDict() const {
metadata_dict->SetString("v8-version", V8_VERSION_STRING);
metadata_dict->SetString("user-agent", GetContentClient()->GetUserAgent());
+#if defined(OS_ANDROID)
+ // The library name is used for symbolizing heap profiles. This cannot be
+ // obtained from process maps since library can be mapped from apk directly.
+ // This is not added as part of memory-infra os dumps since it is special case
+ // only for chrome library.
+ base::Optional<std::string> soname =
+ base::debug::ReadElfLibraryName(&__ehdr_start);
+ if (soname)
+ metadata_dict->SetString("chrome-library-name", soname.value());
+#endif // defined(OS_ANDROID)
+
// OS
#if defined(OS_CHROMEOS)
metadata_dict->SetString("os-name", "CrOS");
@@ -326,7 +350,7 @@ bool TracingControllerImpl::StopTracing(
return false;
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- tracing::TraceConfigFile::GetInstance()->SetDisabled();
+ tracing::TraceStartupConfig::GetInstance()->SetDisabled();
trace_data_endpoint_ = std::move(trace_data_endpoint);
is_data_complete_ = false;
is_metadata_available_ = false;
@@ -406,8 +430,7 @@ void TracingControllerImpl::OnDataComplete() {
CompleteFlush();
}
-void TracingControllerImpl::OnMetadataAvailable(
- std::unique_ptr<base::DictionaryValue> metadata) {
+void TracingControllerImpl::OnMetadataAvailable(base::Value metadata) {
DCHECK(!filtered_metadata_);
is_metadata_available_ = true;
MetadataFilterPredicate metadata_filter;
@@ -416,16 +439,15 @@ void TracingControllerImpl::OnMetadataAvailable(
metadata_filter = delegate_->GetMetadataFilterPredicate();
}
if (metadata_filter.is_null()) {
- filtered_metadata_ = std::move(metadata);
+ filtered_metadata_ = base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(std::move(metadata)));
} else {
filtered_metadata_ = std::make_unique<base::DictionaryValue>();
- for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd();
- it.Advance()) {
- if (metadata_filter.Run(it.key())) {
- filtered_metadata_->Set(
- it.key(), std::make_unique<base::Value>(it.value().Clone()));
+ for (auto it : metadata.DictItems()) {
+ if (metadata_filter.Run(it.first)) {
+ filtered_metadata_->SetKey(it.first, std::move(it.second));
} else {
- filtered_metadata_->SetString(it.key(), "__stripped__");
+ filtered_metadata_->SetKey(it.first, base::Value("__stripped__"));
}
}
}
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index ea35ddd324c..356253a594b 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -26,6 +26,10 @@ class DictionaryValue;
class RefCountedString;
} // namespace base
+namespace tracing {
+class TraceEventAgent;
+} // namespace tracing
+
namespace content {
class TracingDelegate;
@@ -43,7 +47,7 @@ class TracingControllerImpl : public TracingController,
CreateCompressedStringEndpoint(scoped_refptr<TraceDataEndpoint> endpoint,
bool compress_with_background_priority);
- static TracingControllerImpl* GetInstance();
+ CONTENT_EXPORT static TracingControllerImpl* GetInstance();
// Should be called on the UI thread.
TracingControllerImpl();
@@ -62,6 +66,8 @@ class TracingControllerImpl : public TracingController,
void RegisterTracingUI(TracingUI* tracing_ui);
void UnregisterTracingUI(TracingUI* tracing_ui);
+ CONTENT_EXPORT tracing::TraceEventAgent* GetTraceEventAgent() const;
+
private:
friend std::default_delete<TracingControllerImpl>;
@@ -73,13 +79,14 @@ class TracingControllerImpl : public TracingController,
void OnDataAvailable(const void* data, size_t num_bytes) override;
void OnDataComplete() override;
- void OnMetadataAvailable(std::unique_ptr<base::DictionaryValue> metadata);
+ void OnMetadataAvailable(base::Value metadata);
void CompleteFlush();
tracing::mojom::AgentRegistryPtr agent_registry_;
tracing::mojom::CoordinatorPtr coordinator_;
std::vector<std::unique_ptr<tracing::mojom::Agent>> agents_;
+ std::unique_ptr<tracing::TraceEventAgent> trace_event_agent_;
std::unique_ptr<TracingDelegate> delegate_;
std::unique_ptr<base::trace_event::TraceConfig> trace_config_;
std::unique_ptr<mojo::DataPipeDrainer> drainer_;
diff --git a/chromium/content/browser/url_loader_factory_getter.cc b/chromium/content/browser/url_loader_factory_getter.cc
index 2a6b4f38ccb..e0593366a2a 100644
--- a/chromium/content/browser/url_loader_factory_getter.cc
+++ b/chromium/content/browser/url_loader_factory_getter.cc
@@ -4,9 +4,15 @@
#include "content/browser/url_loader_factory_getter.h"
+#include <memory>
+#include <utility>
+
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/lazy_instance.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/common/service_worker/service_worker_utils.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/network_service.mojom.h"
@@ -71,6 +77,12 @@ class URLLoaderFactoryGetter::URLLoaderFactoryForIOThread
std::move(client), traffic_annotation);
}
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override {
+ if (!factory_getter_)
+ return;
+ factory_getter_->GetURLLoaderFactory()->Clone(std::move(request));
+ }
+
// SharedURLLoaderFactory implementation:
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
NOTREACHED() << "This isn't supported. If you need a SharedURLLoaderFactory"
@@ -101,14 +113,19 @@ URLLoaderFactoryGetter::URLLoaderFactoryGetter() {}
void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) {
DCHECK(partition);
- partition_ = partition;
+ DCHECK(!pending_network_factory_request_.is_pending());
+ DCHECK(!pending_blob_factory_request_.is_pending());
+ partition_ = partition;
network::mojom::URLLoaderFactoryPtr network_factory;
- HandleNetworkFactoryRequestOnUIThread(MakeRequest(&network_factory));
-
network::mojom::URLLoaderFactoryPtr blob_factory;
- partition_->GetBlobURLLoaderFactory()->HandleRequest(
- mojo::MakeRequest(&blob_factory));
+ pending_network_factory_request_ = MakeRequest(&network_factory);
+ pending_blob_factory_request_ = mojo::MakeRequest(&blob_factory);
+
+ // If NetworkService is disabled, HandleFactoryRequests should be called after
+ // NetworkContext in |partition_| is ready.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService))
+ HandleFactoryRequests();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -117,6 +134,24 @@ void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) {
blob_factory.PassInterface()));
}
+void URLLoaderFactoryGetter::HandleFactoryRequests() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(pending_network_factory_request_.is_pending());
+ DCHECK(pending_blob_factory_request_.is_pending());
+ HandleNetworkFactoryRequestOnUIThread(
+ std::move(pending_network_factory_request_));
+
+ // |partition->blob_url_loader_factory_| is not available without the feature.
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+ ServiceWorkerUtils::IsServicificationEnabled()) {
+ DCHECK(partition_->GetBlobURLLoaderFactory());
+ partition_->GetBlobURLLoaderFactory()->HandleRequest(
+ std::move(pending_blob_factory_request_));
+ } else {
+ pending_blob_factory_request_ = nullptr;
+ }
+}
+
void URLLoaderFactoryGetter::OnStoragePartitionDestroyed() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
partition_ = nullptr;
@@ -214,8 +249,12 @@ void URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread(
// still held by consumers.
if (!partition_)
return;
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = network::mojom::kBrowserProcessId;
+ params->is_corb_enabled = false;
partition_->GetNetworkContext()->CreateURLLoaderFactory(
- std::move(network_factory_request), 0);
+ std::move(network_factory_request), std::move(params));
}
} // namespace content
diff --git a/chromium/content/browser/url_loader_factory_getter.h b/chromium/content/browser/url_loader_factory_getter.h
index 2386c82bd4c..da31f8cf52e 100644
--- a/chromium/content/browser/url_loader_factory_getter.h
+++ b/chromium/content/browser/url_loader_factory_getter.h
@@ -31,10 +31,19 @@ class URLLoaderFactoryGetter
CONTENT_EXPORT URLLoaderFactoryGetter();
// Initializes this object on the UI thread. The |partition| is used to
- // initialize the URLLoaderFactories for the network service and AppCache, and
- // will be cached to recover from connection error.
+ // initialize the URLLoaderFactories for the network service, AppCache, and
+ // ServiceWorkers, and will be cached to recover from connection error.
+ // After Initialize(), you can get URLLoaderFactories from this
+ // getter. However, any messages on it will be queued until
+ // HandleFactoryRequests() is called.
void Initialize(StoragePartitionImpl* partition);
+ // Called on the UI thread to actually instantiate factories whose pointers
+ // are to be exposed by this getter. This must be called after NetworkContext
+ // is initialized.
+ // TODO(shimazu): Remove this once NetworkService is shipped.
+ void HandleFactoryRequests();
+
// Clear the cached pointer to |StoragePartitionImpl| on the UI thread. Should
// be called when the partition is going away.
void OnStoragePartitionDestroyed();
@@ -58,7 +67,8 @@ class URLLoaderFactoryGetter
network::mojom::URLLoaderFactoryRequest network_factory_request);
// Called on the IO thread to get the URLLoaderFactory to the blob service.
- // The pointer shouldn't be cached.
+ // Must be used only if the network service or servicified service worker is
+ // enabled. The pointer shouldn't be cached.
CONTENT_EXPORT network::mojom::URLLoaderFactory* GetBlobFactory();
// Overrides the network URLLoaderFactory for subsequent requests. Passing a
@@ -106,6 +116,10 @@ class URLLoaderFactoryGetter
// Call |network_factory_.FlushForTesting()|. For test use only.
void FlushNetworkInterfaceForTesting();
+ // Bound with appropriate URLLoaderFactories at HandleFactoryRequests().
+ network::mojom::URLLoaderFactoryRequest pending_network_factory_request_;
+ network::mojom::URLLoaderFactoryRequest pending_blob_factory_request_;
+
// Only accessed on IO thread.
network::mojom::URLLoaderFactoryPtr network_factory_;
network::mojom::URLLoaderFactoryPtr blob_factory_;
diff --git a/chromium/content/browser/utility_process_host.cc b/chromium/content/browser/utility_process_host.cc
index 39b89cd36c3..3b6dfc16d83 100644
--- a/chromium/content/browser/utility_process_host.cc
+++ b/chromium/content/browser/utility_process_host.cc
@@ -28,21 +28,24 @@
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
-#include "content/public/common/zygote_buildflags.h"
#include "media/base/media_switches.h"
#include "services/network/public/cpp/network_switches.h"
+#include "services/service_manager/embedder/switches.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/service_manager/sandbox/sandbox_type.h"
+#include "services/service_manager/sandbox/switches.h"
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gl/gl_switches.h"
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_types.h"
+#include "services/network/network_sandbox_win.h"
#endif
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
-#include "content/public/common/zygote_handle.h"
+#include "services/service_manager/zygote/common/zygote_handle.h" // nogncheck
#endif
namespace content {
@@ -84,16 +87,21 @@ class UtilitySandboxedProcessLauncherDelegate
service_manager::SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES;
}
- bool PreSpawnTarget(sandbox::TargetPolicy* policy) override { return true; }
+ bool PreSpawnTarget(sandbox::TargetPolicy* policy) override {
+ if (sandbox_type_ == service_manager::SANDBOX_TYPE_NETWORK)
+ return network::NetworkPreSpawnTarget(policy);
+
+ return true;
+ }
#endif // OS_WIN
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
- ZygoteHandle GetZygote() override {
+ service_manager::ZygoteHandle GetZygote() override {
if (service_manager::IsUnsandboxedSandboxType(sandbox_type_) ||
sandbox_type_ == service_manager::SANDBOX_TYPE_NETWORK) {
return nullptr;
}
- return GetGenericZygote();
+ return service_manager::GetGenericZygote();
}
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
@@ -267,13 +275,14 @@ bool UtilityProcessHost::StartProcess() {
network::switches::kIgnoreCertificateErrorsSPKIList,
network::switches::kLogNetLog,
network::switches::kNoReferrers,
+ service_manager::switches::kNoSandbox,
+#if defined(OS_MACOSX)
+ service_manager::switches::kEnableSandboxLogging,
+#endif
switches::kIgnoreCertificateErrors,
- switches::kNoSandbox,
switches::kOverrideUseSoftwareGLForTests,
+ switches::kOverrideEnabledCdmInterfaceVersion,
switches::kProxyServer,
-#if defined(OS_MACOSX)
- switches::kEnableSandboxLogging,
-#endif
switches::kUseFakeDeviceForMediaStream,
switches::kUseFileForFakeVideoCapture,
switches::kUseMockCertVerifierForTesting,
@@ -282,6 +291,23 @@ bool UtilityProcessHost::StartProcess() {
#if defined(OS_ANDROID)
switches::kOrderfileMemoryOptimization,
#endif
+ // These flags are used by the audio service:
+ switches::kAudioBufferSize,
+ switches::kAudioServiceQuitTimeoutMs,
+ switches::kDisableAudioOutput,
+ switches::kFailAudioStreamCreation,
+ switches::kMuteAudio,
+ switches::kUseFileForFakeAudioCapture,
+#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS)
+ switches::kAlsaInputDevice,
+ switches::kAlsaOutputDevice,
+#endif
+#if defined(OS_WIN)
+ switches::kEnableExclusiveAudio,
+ switches::kForceWaveAudio,
+ switches::kTrySupportedChannelLayouts,
+ switches::kWaveOutBuffers,
+#endif
};
cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
arraysize(kSwitchNames));
diff --git a/chromium/content/browser/utility_process_host.h b/chromium/content/browser/utility_process_host.h
index 2ef900333a2..0185b68cc8a 100644
--- a/chromium/content/browser/utility_process_host.h
+++ b/chromium/content/browser/utility_process_host.h
@@ -71,6 +71,8 @@ class CONTENT_EXPORT UtilityProcessHost
// SANDBOX_TYPE_NO_SANDBOX is specified.
void SetSandboxType(service_manager::SandboxType sandbox_type);
+ service_manager::SandboxType sandbox_type() const { return sandbox_type_; }
+
// Returns information about the utility child process.
const ChildProcessData& GetData();
#if defined(OS_POSIX)
diff --git a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
index 0b87944e8da..d63a632d9ef 100644
--- a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
+++ b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "content/browser/web_contents/web_contents_impl.h"
diff --git a/chromium/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc b/chromium/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc
index 9864bef84fc..f3da97e61f9 100644
--- a/chromium/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/gesture_nav_simple_unittest.cc
@@ -19,16 +19,24 @@ namespace {
// A subclass of TestWebContents that offers a fake content window.
class GestureNavTestWebContents : public TestWebContents {
public:
+ explicit GestureNavTestWebContents(
+ BrowserContext* browser_context,
+ std::unique_ptr<aura::Window> fake_native_view,
+ std::unique_ptr<aura::Window> fake_contents_window)
+ : TestWebContents(browser_context),
+ fake_native_view_(std::move(fake_native_view)),
+ fake_contents_window_(std::move(fake_contents_window)) {}
~GestureNavTestWebContents() override {}
- static GestureNavTestWebContents* Create(
+ static std::unique_ptr<GestureNavTestWebContents> Create(
BrowserContext* browser_context,
scoped_refptr<SiteInstance> instance,
std::unique_ptr<aura::Window> fake_native_view,
std::unique_ptr<aura::Window> fake_contents_window) {
- auto* web_contents = new GestureNavTestWebContents(
- browser_context, std::move(fake_native_view),
- std::move(fake_contents_window));
+ std::unique_ptr<GestureNavTestWebContents> web_contents =
+ std::make_unique<GestureNavTestWebContents>(
+ browser_context, std::move(fake_native_view),
+ std::move(fake_contents_window));
web_contents->Init(
WebContents::CreateParams(browser_context, std::move(instance)));
return web_contents;
@@ -41,15 +49,6 @@ class GestureNavTestWebContents : public TestWebContents {
return fake_contents_window_.get();
}
- protected:
- explicit GestureNavTestWebContents(
- BrowserContext* browser_context,
- std::unique_ptr<aura::Window> fake_native_view,
- std::unique_ptr<aura::Window> fake_contents_window)
- : TestWebContents(browser_context),
- fake_native_view_(std::move(fake_native_view)),
- fake_contents_window_(std::move(fake_contents_window)) {}
-
private:
std::unique_ptr<aura::Window> fake_native_view_;
std::unique_ptr<aura::Window> fake_contents_window_;
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index 110658ebc58..559ee9bdcfd 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -71,16 +71,25 @@ class ImmediateLoadObserver : WebContentsObserver {
// A subclass of TestWebContents that offers a fake content window.
class OverscrollTestWebContents : public TestWebContents {
public:
+ explicit OverscrollTestWebContents(
+ BrowserContext* browser_context,
+ std::unique_ptr<aura::Window> fake_native_view,
+ std::unique_ptr<aura::Window> fake_contents_window)
+ : TestWebContents(browser_context),
+ fake_native_view_(std::move(fake_native_view)),
+ fake_contents_window_(std::move(fake_contents_window)),
+ is_being_destroyed_(false) {}
~OverscrollTestWebContents() override {}
- static OverscrollTestWebContents* Create(
+ static std::unique_ptr<OverscrollTestWebContents> Create(
BrowserContext* browser_context,
scoped_refptr<SiteInstance> instance,
std::unique_ptr<aura::Window> fake_native_view,
std::unique_ptr<aura::Window> fake_contents_window) {
- OverscrollTestWebContents* web_contents = new OverscrollTestWebContents(
- browser_context, std::move(fake_native_view),
- std::move(fake_contents_window));
+ std::unique_ptr<OverscrollTestWebContents> web_contents =
+ std::make_unique<OverscrollTestWebContents>(
+ browser_context, std::move(fake_native_view),
+ std::move(fake_contents_window));
web_contents->Init(
WebContents::CreateParams(browser_context, std::move(instance)));
return web_contents;
@@ -100,16 +109,6 @@ class OverscrollTestWebContents : public TestWebContents {
bool IsBeingDestroyed() const override { return is_being_destroyed_; }
- protected:
- explicit OverscrollTestWebContents(
- BrowserContext* browser_context,
- std::unique_ptr<aura::Window> fake_native_view,
- std::unique_ptr<aura::Window> fake_contents_window)
- : TestWebContents(browser_context),
- fake_native_view_(std::move(fake_native_view)),
- fake_contents_window_(std::move(fake_contents_window)),
- is_being_destroyed_(false) {}
-
private:
std::unique_ptr<aura::Window> fake_native_view_;
std::unique_ptr<aura::Window> fake_contents_window_;
@@ -247,13 +246,15 @@ class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
// Receive a paint update. This is necessary to make sure the size is set
// correctly in RenderWidgetHostImpl.
- ViewHostMsg_ResizeOrRepaint_ACK_Params params;
- params.view_size = gfx::Size(10, 10);
- ViewHostMsg_ResizeOrRepaint_ACK rect(test_rvh()->GetRoutingID(), params);
- RenderViewHostTester::TestOnMessageReceived(test_rvh(), rect);
+ viz::LocalSurfaceId local_surface_id(10, 10,
+ base::UnguessableToken::Create());
+ cc::RenderFrameMetadata metadata;
+ metadata.viewport_size_in_pixels = gfx::Size(10, 10);
+ metadata.local_surface_id = local_surface_id;
+ test_rvh()->GetWidget()->DidUpdateVisualProperties(metadata);
// Reset pending flags for size/paint.
- test_rvh()->GetWidget()->ResetSizeAndRepaintPendingFlags();
+ test_rvh()->GetWidget()->ResetSentVisualProperties();
// Create the overlay, and set the contents of the overlay window.
overlay_.reset(new OverscrollNavigationOverlay(contents(), root_window()));
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index 5ebf1918903..634d995b762 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -17,11 +17,11 @@
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/metrics/user_metrics.h"
#include "base/task_scheduler/post_task.h"
#include "content/browser/accessibility/browser_accessibility_android.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/browser/android/content_view_core.h"
-#include "content/browser/android/interstitial_page_delegate_android.h"
#include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
@@ -41,8 +41,9 @@
#include "content/public/common/content_switches.h"
#include "jni/WebContentsImpl_jni.h"
#include "net/android/network_library.h"
+#include "ui/accessibility/ax_assistant_structure.h"
#include "ui/accessibility/ax_node_data.h"
-#include "ui/accessibility/platform/ax_snapshot_node_android_platform.h"
+#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h"
#include "ui/android/overscroll_refresh_handler.h"
#include "ui/android/window_android.h"
#include "ui/gfx/android/java_bitmap.h"
@@ -81,16 +82,20 @@ void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
void SmartClipCallback(const ScopedJavaGlobalRef<jobject>& callback,
const base::string16& text,
- const base::string16& html) {
+ const base::string16& html,
+ const gfx::Rect& clip_rect) {
JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
- ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
- Java_WebContentsImpl_onSmartClipDataExtracted(env, jtext, jhtml, callback);
+ ScopedJavaLocalRef<jstring> j_text = ConvertUTF16ToJavaString(env, text);
+ ScopedJavaLocalRef<jstring> j_html = ConvertUTF16ToJavaString(env, html);
+ Java_WebContentsImpl_onSmartClipDataExtracted(
+ env, j_text, j_html, clip_rect.x(), clip_rect.y(), clip_rect.right(),
+ clip_rect.bottom(), callback);
}
ScopedJavaLocalRef<jobject> JNI_WebContentsImpl_CreateJavaAXSnapshot(
JNIEnv* env,
- const ui::AXSnapshotNodeAndroid* node,
+ const ui::AssistantTree* tree,
+ const ui::AssistantNode* node,
bool is_root) {
ScopedJavaLocalRef<jstring> j_text =
ConvertUTF16ToJavaString(env, node->text);
@@ -103,15 +108,16 @@ ScopedJavaLocalRef<jobject> JNI_WebContentsImpl_CreateJavaAXSnapshot(
node->text_size, node->bold, node->italic, node->underline,
node->line_through, j_class);
- if (node->has_selection) {
+ if (node->selection.has_value()) {
Java_WebContentsImpl_setAccessibilitySnapshotSelection(
- env, j_node, node->start_selection, node->end_selection);
+ env, j_node, node->selection->start(), node->selection->end());
}
- for (auto& child : node->children) {
+ for (int child : node->children_indices) {
Java_WebContentsImpl_addAccessibilityNodeAsChild(
env, j_node,
- JNI_WebContentsImpl_CreateJavaAXSnapshot(env, child.get(), false));
+ JNI_WebContentsImpl_CreateJavaAXSnapshot(
+ env, tree, tree->nodes[child].get(), false));
}
return j_node;
}
@@ -127,10 +133,10 @@ void AXTreeSnapshotCallback(const ScopedJavaGlobalRef<jobject>& callback,
std::unique_ptr<BrowserAccessibilityManagerAndroid> manager(
static_cast<BrowserAccessibilityManagerAndroid*>(
BrowserAccessibilityManager::Create(result, nullptr)));
- auto snapshot = ui::AXSnapshotNodeAndroid::Create(
- result, manager->ShouldExposePasswordText());
- ScopedJavaLocalRef<jobject> j_root =
- JNI_WebContentsImpl_CreateJavaAXSnapshot(env, snapshot.get(), true);
+ std::unique_ptr<ui::AssistantTree> assistant_tree =
+ ui::CreateAssistantTree(result, manager->ShouldExposePasswordText());
+ ScopedJavaLocalRef<jobject> j_root = JNI_WebContentsImpl_CreateJavaAXSnapshot(
+ env, assistant_tree.get(), assistant_tree->nodes.front().get(), true);
Java_WebContentsImpl_onAccessibilitySnapshot(env, j_root, callback);
}
@@ -266,6 +272,31 @@ WebContentsAndroid::GetTopLevelNativeWindow(JNIEnv* env,
return window_android->GetJavaObject();
}
+void WebContentsAndroid::SetTopLevelNativeWindow(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobject>& jwindow_android) {
+ ui::WindowAndroid* window =
+ ui::WindowAndroid::FromJavaWindowAndroid(jwindow_android);
+ auto* old_window = web_contents_->GetTopLevelNativeWindow();
+ if (window == old_window)
+ return;
+
+ auto* view = web_contents_->GetNativeView();
+ if (old_window)
+ view->RemoveFromParent();
+ if (window)
+ window->AddChild(view);
+}
+
+void WebContentsAndroid::SetViewAndroidDelegate(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jobject>& jview_delegate) {
+ ui::ViewAndroid* view_android = web_contents_->GetView()->GetNativeView();
+ view_android->SetDelegate(jview_delegate);
+}
+
ScopedJavaLocalRef<jobject> WebContentsAndroid::GetMainFrame(
JNIEnv* env,
const JavaParamRef<jobject>& obj) const {
@@ -353,9 +384,9 @@ RenderWidgetHostViewAndroid*
jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
- if (!rwhva)
+ if (!rwhva || !rwhva->GetCachedBackgroundColor())
return SK_ColorWHITE;
- return rwhva->GetCachedBackgroundColor();
+ return *rwhva->GetCachedBackgroundColor();
}
ScopedJavaLocalRef<jstring> WebContentsAndroid::GetLastCommittedURL(
@@ -387,8 +418,9 @@ void WebContentsAndroid::OnShow(JNIEnv* env, const JavaParamRef<jobject>& obj) {
void WebContentsAndroid::SetImportance(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
- jint importance) {
- web_contents_->SetImportance(static_cast<ChildProcessImportance>(importance));
+ jint main_frame_importance) {
+ web_contents_->SetMainFrameImportance(
+ static_cast<ChildProcessImportance>(main_frame_importance));
}
void WebContentsAndroid::SuspendAllMediaPlayers(
@@ -404,19 +436,6 @@ void WebContentsAndroid::SetAudioMuted(JNIEnv* env,
web_contents_->SetAudioMuted(mute);
}
-void WebContentsAndroid::ShowInterstitialPage(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jstring>& jurl,
- jlong delegate_ptr) {
- GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
- InterstitialPageDelegateAndroid* delegate =
- reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
- InterstitialPage* interstitial = InterstitialPage::Create(
- web_contents_, false, url, delegate);
- delegate->set_interstitial_page(interstitial);
- interstitial->Show();
-}
-
jboolean WebContentsAndroid::IsShowingInterstitialPage(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
@@ -802,4 +821,40 @@ void WebContentsAndroid::SetMediaSession(
Java_WebContentsImpl_setMediaSession(env, obj_, j_media_session);
}
+void WebContentsAndroid::SendOrientationChangeEvent(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ jint orientation) {
+ base::RecordAction(base::UserMetricsAction("ScreenOrientationChange"));
+ WebContentsViewAndroid* view =
+ static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
+ view->set_device_orientation(orientation);
+ RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
+ if (rwhva)
+ rwhva->UpdateScreenInfo(web_contents_->GetView()->GetNativeView());
+
+ web_contents_->OnScreenOrientationChange();
+}
+
+void WebContentsAndroid::OnScaleFactorChanged(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
+ if (rwhva) {
+ // |SendScreenRects()| indirectly calls GetViewSize() that asks Java layer.
+ web_contents_->SendScreenRects();
+ rwhva->SynchronizeVisualProperties();
+ }
+}
+
+int WebContentsAndroid::GetTopControlsShrinkBlinkHeightPixForTesting(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
+ float scale = web_contents_->GetNativeView()->GetDipScale();
+ return (rwhva && rwhva->DoBrowserControlsShrinkBlinkSize())
+ ? rwhva->GetTopControlsHeight() * scale
+ : 0;
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index 2896fa2a5ec..04455bd0666 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -41,6 +41,14 @@ class CONTENT_EXPORT WebContentsAndroid
base::android::ScopedJavaLocalRef<jobject> GetTopLevelNativeWindow(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
+ void SetTopLevelNativeWindow(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jobject>& jwindow_android);
+ void SetViewAndroidDelegate(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jobject>& jview_delegate);
base::android::ScopedJavaLocalRef<jobject> GetMainFrame(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) const;
@@ -92,10 +100,6 @@ class CONTENT_EXPORT WebContentsAndroid
const base::android::JavaParamRef<jobject>& jobj,
jboolean mute);
- void ShowInterstitialPage(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- const base::android::JavaParamRef<jstring>& jurl,
- jlong delegate_ptr);
jboolean IsShowingInterstitialPage(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
@@ -225,6 +229,20 @@ class CONTENT_EXPORT WebContentsAndroid
void SetMediaSession(
const base::android::ScopedJavaLocalRef<jobject>& j_media_session);
+ void SendOrientationChangeEvent(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jint orientation);
+
+ void OnScaleFactorChanged(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
+
+ // Returns the amount of the top controls height if controls are in the state
+ // of shrinking Blink's view size, otherwise 0.
+ int GetTopControlsShrinkBlinkHeightPixForTesting(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
+
private:
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
@@ -242,6 +260,7 @@ class CONTENT_EXPORT WebContentsAndroid
const std::vector<gfx::Size>& sizes);
WebContentsImpl* web_contents_;
+
NavigationControllerAndroid navigation_controller_;
base::android::ScopedJavaGlobalRef<jobject> obj_;
diff --git a/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc b/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc
index 1845a660f90..f6d6593e8ec 100644
--- a/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_delegate_unittest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/test_browser_context.h"
#include "content/test/test_render_view_host.h"
@@ -22,44 +21,48 @@ class WebContentsDelegateTest : public RenderViewHostImplTestHarness {
};
TEST_F(WebContentsDelegateTest, UnregisterInDestructor) {
- std::unique_ptr<WebContentsImpl> contents_a(static_cast<WebContentsImpl*>(
- WebContents::Create(WebContents::CreateParams(browser_context()))));
- std::unique_ptr<WebContentsImpl> contents_b(static_cast<WebContentsImpl*>(
- WebContents::Create(WebContents::CreateParams(browser_context()))));
- EXPECT_EQ(nullptr, contents_a->GetDelegate());
- EXPECT_EQ(nullptr, contents_b->GetDelegate());
+ std::unique_ptr<WebContents> contents_a(
+ WebContents::Create(WebContents::CreateParams(browser_context())));
+ WebContentsImpl* raw_contents_a =
+ static_cast<WebContentsImpl*>(contents_a.get());
+ std::unique_ptr<WebContents> contents_b(
+ WebContents::Create(WebContents::CreateParams(browser_context())));
+ WebContentsImpl* raw_contents_b =
+ static_cast<WebContentsImpl*>(contents_b.get());
+ EXPECT_EQ(nullptr, raw_contents_a->GetDelegate());
+ EXPECT_EQ(nullptr, raw_contents_b->GetDelegate());
std::unique_ptr<MockWebContentsDelegate> delegate(
new MockWebContentsDelegate());
// Setting a delegate should work correctly.
- contents_a->SetDelegate(delegate.get());
- EXPECT_EQ(delegate.get(), contents_a->GetDelegate());
- EXPECT_TRUE(contents_b->GetDelegate() == nullptr);
+ raw_contents_a->SetDelegate(delegate.get());
+ EXPECT_EQ(delegate.get(), raw_contents_a->GetDelegate());
+ EXPECT_TRUE(raw_contents_b->GetDelegate() == nullptr);
// A delegate can be a delegate to multiple WebContentsImpl.
- contents_b->SetDelegate(delegate.get());
- EXPECT_EQ(delegate.get(), contents_a->GetDelegate());
- EXPECT_EQ(delegate.get(), contents_b->GetDelegate());
+ raw_contents_b->SetDelegate(delegate.get());
+ EXPECT_EQ(delegate.get(), raw_contents_a->GetDelegate());
+ EXPECT_EQ(delegate.get(), raw_contents_b->GetDelegate());
// Setting the same delegate multiple times should work correctly.
- contents_b->SetDelegate(delegate.get());
- EXPECT_EQ(delegate.get(), contents_a->GetDelegate());
- EXPECT_EQ(delegate.get(), contents_b->GetDelegate());
+ raw_contents_b->SetDelegate(delegate.get());
+ EXPECT_EQ(delegate.get(), raw_contents_a->GetDelegate());
+ EXPECT_EQ(delegate.get(), raw_contents_b->GetDelegate());
// Setting delegate to NULL should work correctly.
- contents_b->SetDelegate(nullptr);
- EXPECT_EQ(delegate.get(), contents_a->GetDelegate());
- EXPECT_TRUE(contents_b->GetDelegate() == nullptr);
+ raw_contents_b->SetDelegate(nullptr);
+ EXPECT_EQ(delegate.get(), raw_contents_a->GetDelegate());
+ EXPECT_TRUE(raw_contents_b->GetDelegate() == nullptr);
// Destroying the delegate while it is still the delegate for a
// WebContentsImpl should unregister it.
- contents_b->SetDelegate(delegate.get());
- EXPECT_EQ(delegate.get(), contents_a->GetDelegate());
- EXPECT_EQ(delegate.get(), contents_b->GetDelegate());
+ raw_contents_b->SetDelegate(delegate.get());
+ EXPECT_EQ(delegate.get(), raw_contents_a->GetDelegate());
+ EXPECT_EQ(delegate.get(), raw_contents_b->GetDelegate());
delegate.reset(nullptr);
- EXPECT_TRUE(contents_a->GetDelegate() == nullptr);
- EXPECT_TRUE(contents_b->GetDelegate() == nullptr);
+ EXPECT_TRUE(raw_contents_a->GetDelegate() == nullptr);
+ EXPECT_TRUE(raw_contents_b->GetDelegate() == nullptr);
// Destroy the WebContentses and run the message loop to prevent leaks.
contents_a.reset();
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 942a35d355a..6ae9bf2f9c6 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -60,6 +60,7 @@
#include "content/browser/loader/loader_io_thread_notifier.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/manifest/manifest_manager_host.h"
+#include "content/browser/media/audio_stream_broker.h"
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/capture/web_contents_audio_muter.h"
#include "content/browser/media/media_web_contents_observer.h"
@@ -264,14 +265,16 @@ class CloseDialogCallbackWrapper
} // namespace
-WebContents* WebContents::Create(const WebContents::CreateParams& params) {
+std::unique_ptr<WebContents> WebContents::Create(
+ const WebContents::CreateParams& params) {
return WebContentsImpl::CreateWithOpener(params, FindOpenerRFH(params));
}
-WebContents* WebContents::CreateWithSessionStorage(
+std::unique_ptr<WebContents> WebContents::CreateWithSessionStorage(
const WebContents::CreateParams& params,
const SessionStorageNamespaceMap& session_storage_namespace_map) {
- WebContentsImpl* new_contents = new WebContentsImpl(params.browser_context);
+ std::unique_ptr<WebContentsImpl> new_contents(
+ new WebContentsImpl(params.browser_context));
RenderFrameHostImpl* opener_rfh = FindOpenerRFH(params);
FrameTreeNode* opener = nullptr;
if (opener_rfh)
@@ -286,6 +289,12 @@ WebContents* WebContents::CreateWithSessionStorage(
.SetSessionStorageNamespace(it->first, it->second.get());
}
+ if (params.guest_delegate) {
+ // This makes |new_contents| act as a guest.
+ // For more info, see comment above class BrowserPluginGuest.
+ BrowserPluginGuest::Create(new_contents.get(), params.guest_delegate);
+ }
+
new_contents->Init(params);
return new_contents;
}
@@ -514,6 +523,8 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
audio_stream_monitor_(this),
bluetooth_connected_device_count_(0),
+ media_device_group_id_salt_base_(
+ BrowserContext::CreateRandomMediaDeviceIDSalt()),
#if !defined(OS_ANDROID)
page_scale_factor_is_one_(true),
#endif // !defined(OS_ANDROID)
@@ -638,14 +649,15 @@ WebContentsImpl::~WebContentsImpl() {
SetDelegate(nullptr);
}
-WebContentsImpl* WebContentsImpl::CreateWithOpener(
+std::unique_ptr<WebContentsImpl> WebContentsImpl::CreateWithOpener(
const WebContents::CreateParams& params,
RenderFrameHostImpl* opener_rfh) {
TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
FrameTreeNode* opener = nullptr;
if (opener_rfh)
opener = opener_rfh->frame_tree_node();
- WebContentsImpl* new_contents = new WebContentsImpl(params.browser_context);
+ std::unique_ptr<WebContentsImpl> new_contents(
+ new WebContentsImpl(params.browser_context));
new_contents->SetOpenerForNewContents(opener, params.opener_suppressed);
// If the opener is sandboxed, a new popup must inherit the opener's sandbox
@@ -679,7 +691,7 @@ WebContentsImpl* WebContentsImpl::CreateWithOpener(
if (params.guest_delegate) {
// This makes |new_contents| act as a guest.
// For more info, see comment above class BrowserPluginGuest.
- BrowserPluginGuest::Create(new_contents, params.guest_delegate);
+ BrowserPluginGuest::Create(new_contents.get(), params.guest_delegate);
// We are instantiating a WebContents for browser plugin. Set its subframe
// bit to true.
new_contents->is_subframe_ = true;
@@ -830,12 +842,6 @@ bool WebContentsImpl::OnMessageReceived(RenderFrameHostImpl* render_frame_host,
OnBrowserPluginMessage(render_frame_host,
message))
#endif
-#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(FrameHostMsg_FindMatchRects_Reply,
- OnFindMatchRectsReply)
- IPC_MESSAGE_HANDLER(FrameHostMsg_GetNearestFindResult_Reply,
- OnGetNearestFindResultReply)
-#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -1244,6 +1250,10 @@ const PageImportanceSignals& WebContentsImpl::GetPageImportanceSignals() const {
return page_importance_signals_;
}
+const std::string& WebContentsImpl::GetMediaDeviceGroupIDSaltBase() const {
+ return media_device_group_id_salt_base_;
+}
+
const base::string16& WebContentsImpl::GetTitle() const {
// Transient entries take precedence. They are used for interstitial pages
// that are shown on top of existing pages.
@@ -1391,6 +1401,9 @@ bool WebContentsImpl::IsBeingCaptured() const {
}
bool WebContentsImpl::IsAudioMuted() const {
+ if (base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams)) {
+ return audio_stream_factory_ && audio_stream_factory_->IsMuted();
+ }
return audio_muter_.get() && audio_muter_->is_muting();
}
@@ -1401,13 +1414,17 @@ void WebContentsImpl::SetAudioMuted(bool mute) {
if (mute == IsAudioMuted())
return;
- if (mute) {
- if (!audio_muter_)
- audio_muter_.reset(new WebContentsAudioMuter(this));
- audio_muter_->StartMuting();
+ if (base::FeatureList::IsEnabled(features::kAudioServiceAudioStreams)) {
+ GetAudioStreamFactory()->SetMuted(mute);
} else {
- DCHECK(audio_muter_);
- audio_muter_->StopMuting();
+ if (mute) {
+ if (!audio_muter_)
+ audio_muter_.reset(new WebContentsAudioMuter(this));
+ audio_muter_->StartMuting();
+ } else {
+ DCHECK(audio_muter_);
+ audio_muter_->StopMuting();
+ }
}
for (auto& observer : observers_)
@@ -1425,6 +1442,19 @@ bool WebContentsImpl::IsConnectedToBluetoothDevice() const {
return bluetooth_connected_device_count_ > 0;
}
+bool WebContentsImpl::HasPictureInPictureVideo() const {
+ return has_picture_in_picture_video_;
+}
+
+void WebContentsImpl::SetHasPictureInPictureVideo(
+ bool has_picture_in_picture_video) {
+ // If status of |this| is already accurate, there is no need to update.
+ if (has_picture_in_picture_video == has_picture_in_picture_video_)
+ return;
+ has_picture_in_picture_video_ = has_picture_in_picture_video;
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+}
+
bool WebContentsImpl::IsCrashed() const {
return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
@@ -1480,8 +1510,8 @@ void WebContentsImpl::OnAudioStateChanged(bool is_audible) {
was_ever_audible_ = was_ever_audible_ || is_audible;
- if (delegate_)
- delegate_->OnAudioStateChanged(this, is_audible);
+ for (auto& observer : observers_)
+ observer.OnAudioStateChanged(is_audible);
}
base::TimeTicks WebContentsImpl::GetLastActiveTime() const {
@@ -1509,6 +1539,19 @@ void WebContentsImpl::WasShown() {
last_active_time_ = base::TimeTicks::Now();
SetVisibility(Visibility::VISIBLE);
+
+ for (FrameTreeNode* node : frame_tree_.Nodes()) {
+ RenderFrameProxyHost* parent = node->render_manager()->GetProxyToParent();
+ if (!parent)
+ continue;
+
+ if (parent->cross_process_frame_connector()->IsVisible()) {
+ // MaybeLogCrash will check 1) if there was a crash or not and 2) if the
+ // crash might have been already logged earlier as kCrashedWhileVisible.
+ parent->cross_process_frame_connector()->MaybeLogCrash(
+ CrossProcessFrameConnector::CrashVisibility::kShownAfterCrashing);
+ }
+ }
}
void WebContentsImpl::WasHidden() {
@@ -1548,31 +1591,14 @@ bool WebContentsImpl::HasRecentInteractiveInputEvent() const {
}
#if defined(OS_ANDROID)
-std::set<RenderWidgetHostImpl*> WebContentsImpl::GetAllRenderWidgetHosts() {
- std::set<RenderWidgetHostImpl*> set;
+void WebContentsImpl::SetMainFrameImportance(
+ ChildProcessImportance importance) {
+ GetMainFrame()->GetRenderWidgetHost()->SetImportance(importance);
if (ShowingInterstitialPage()) {
- auto* host =
- static_cast<RenderFrameHostImpl*>(interstitial_page_->GetMainFrame())
- ->GetRenderWidgetHost();
- DCHECK(host);
- set.insert(host);
- }
- for (RenderFrameHost* rfh : GetAllFrames()) {
- auto* host = static_cast<RenderFrameHostImpl*>(rfh)->GetRenderWidgetHost();
- DCHECK(host);
- set.insert(host);
+ static_cast<RenderFrameHostImpl*>(interstitial_page_->GetMainFrame())
+ ->GetRenderWidgetHost()
+ ->SetImportance(importance);
}
- return set;
-}
-
-void WebContentsImpl::SetImportance(ChildProcessImportance importance) {
- // Importance should be set on interstitial page as well, which is included
- // the set returned by |GetAllRenderWidgetHosts()|.
- for (auto* host : GetAllRenderWidgetHosts())
- host->SetImportance(importance);
-
- // TODO(boliu): If this is ever used on platforms other than Android, make
- // sure to also update inner WebContents.
}
#endif
@@ -1588,15 +1614,40 @@ Visibility WebContentsImpl::GetVisibility() const {
return visibility_;
}
+// TODO(alexmos): rename to NeedToFireBeforeUnloadOrUnload().
bool WebContentsImpl::NeedToFireBeforeUnload() {
// TODO(creis): Should we fire even for interstitial pages?
- return WillNotifyDisconnection() && !ShowingInterstitialPage() &&
- !GetRenderViewHost()->SuddenTerminationAllowed();
+ if (ShowingInterstitialPage())
+ return false;
+
+ if (!WillNotifyDisconnection())
+ return false;
+
+ // Don't fire if the main frame's RenderViewHost indicates that beforeunload
+ // and unload have already executed (e.g., after receiving a ClosePage ACK)
+ // or should be ignored.
+ if (GetRenderViewHost()->SuddenTerminationAllowed())
+ return false;
+
+ // TODO(alexmos): This checks for both beforeunload and unload handlers from
+ // the whole main frame process. Remove this and explicitly check whether
+ // the main frame has each of these handlers. This can be done for
+ // beforeunload via RenderFrameHostImpl::ShouldDispatchBeforeUnload(), and
+ // something similar is needed for unload.
+ if (!GetMainFrame()->GetProcess()->SuddenTerminationAllowed())
+ return true;
+
+ // Check whether any subframes need to run beforeunload handlers.
+ //
+ // TODO(alexmos): Also check whether subframes need to run unload handlers in
+ // addition to beforeunload.
+ return GetMainFrame()->ShouldDispatchBeforeUnload(
+ true /* check_subframes_only */);
}
void WebContentsImpl::DispatchBeforeUnload() {
- bool for_cross_site_transition = false;
- GetMainFrame()->DispatchBeforeUnload(for_cross_site_transition, false);
+ GetMainFrame()->DispatchBeforeUnload(
+ RenderFrameHostImpl::BeforeUnloadType::TAB_CLOSE, false);
}
void WebContentsImpl::AttachToOuterWebContentsFrame(
@@ -1679,15 +1730,10 @@ void WebContentsImpl::DidChangeVisibleSecurityState() {
void WebContentsImpl::NotifyPreferencesChanged() {
std::set<RenderViewHost*> render_view_host_set;
for (FrameTreeNode* node : frame_tree_.Nodes()) {
- RenderWidgetHost* render_widget_host =
- node->current_frame_host()->GetRenderWidgetHost();
- if (!render_widget_host)
- continue;
- RenderViewHost* render_view_host = RenderViewHost::From(render_widget_host);
- if (!render_view_host)
- continue;
- render_view_host_set.insert(render_view_host);
+ render_view_host_set.insert(
+ node->current_frame_host()->GetRenderViewHost());
}
+
for (RenderViewHost* render_view_host : render_view_host_set)
render_view_host->OnWebkitPreferencesChanged();
}
@@ -1703,7 +1749,7 @@ void WebContentsImpl::FreezePage() {
SendPageMessage(new PageMsg_FreezePage(MSG_ROUTING_NONE));
}
-WebContents* WebContentsImpl::Clone() {
+std::unique_ptr<WebContents> WebContentsImpl::Clone() {
// We use our current SiteInstance since the cloned entry will use it anyway.
// We pass our own opener so that the cloned page can access it if it was set
// before.
@@ -1713,10 +1759,11 @@ WebContents* WebContentsImpl::Clone() {
RenderFrameHostImpl* opener_rfh = nullptr;
if (opener)
opener_rfh = opener->current_frame_host();
- WebContentsImpl* tc = CreateWithOpener(create_params, opener_rfh);
+ std::unique_ptr<WebContentsImpl> tc =
+ CreateWithOpener(create_params, opener_rfh);
tc->GetController().CopyStateFrom(controller_, true);
for (auto& observer : observers_)
- observer.DidCloneToNewWebContents(this, tc);
+ observer.DidCloneToNewWebContents(this, tc.get());
return tc;
}
@@ -1772,6 +1819,10 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
scoped_refptr<SiteInstance> site_instance = params.site_instance;
if (!site_instance)
site_instance = SiteInstance::Create(params.browser_context);
+ if (params.desired_renderer_state == CreateParams::kNoRendererProcess) {
+ static_cast<SiteInstanceImpl*>(site_instance.get())
+ ->PreventAssociationWithSpareProcess();
+ }
// A main RenderFrameHost always has a RenderWidgetHost, since it is always a
// local root by definition.
@@ -1850,7 +1901,8 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
}
// Create the renderer process in advance if requested.
- if (params.initialize_renderer) {
+ if (params.desired_renderer_state ==
+ CreateParams::kInitializeAndWarmupRendererProcess) {
if (!GetRenderManager()->current_frame_host()->IsRenderFrameLive()) {
GetRenderManager()->InitRenderView(GetRenderViewHost(), nullptr);
}
@@ -1870,8 +1922,12 @@ void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) {
// Clear a pending contents that has been closed before being shown.
for (auto iter = pending_contents_.begin(); iter != pending_contents_.end();
++iter) {
- if (iter->second != web_contents)
+ if (iter->second.get() != web_contents)
continue;
+
+ // Someone else has deleted the WebContents. That should never happen!
+ // TODO(erikchen): Fix semantics here. https://crbug.com/832879.
+ iter->second.release();
pending_contents_.erase(iter);
return;
}
@@ -1961,7 +2017,7 @@ void WebContentsImpl::RenderWidgetDeleted(
if (render_widget_host == mouse_lock_widget_)
LostMouseLock(mouse_lock_widget_);
- CancelKeyboardLock(keyboard_lock_widget_);
+ CancelKeyboardLock(render_widget_host);
}
void WebContentsImpl::RenderWidgetGotFocus(
@@ -2120,7 +2176,9 @@ RenderWidgetHostImpl* WebContentsImpl::GetRenderWidgetHostWithPageFocus() {
return focused_web_contents->GetMainFrame()->GetRenderWidgetHost();
}
-void WebContentsImpl::EnterFullscreenMode(const GURL& origin) {
+void WebContentsImpl::EnterFullscreenMode(
+ const GURL& origin,
+ const blink::WebFullscreenOptions& options) {
// This method is being called to enter renderer-initiated fullscreen mode.
// Make sure any existing fullscreen widget is shut down first.
RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
@@ -2130,7 +2188,7 @@ void WebContentsImpl::EnterFullscreenMode(const GURL& origin) {
}
if (delegate_) {
- delegate_->EnterFullscreenModeForTab(this, origin);
+ delegate_->EnterFullscreenModeForTab(this, origin, options);
if (keyboard_lock_widget_)
delegate_->RequestKeyboardLock(this, esc_key_locked_);
@@ -2173,7 +2231,7 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
if (!will_cause_resize) {
if (RenderWidgetHostView* rwhv = GetRenderWidgetHostView()) {
if (RenderWidgetHost* render_widget_host = rwhv->GetRenderWidgetHost())
- render_widget_host->WasResized();
+ render_widget_host->SynchronizeVisualProperties();
}
}
@@ -2409,31 +2467,32 @@ void WebContentsImpl::CreateNewWindow(
create_params.renderer_initiated_creation =
main_frame_route_id != MSG_ROUTING_NONE;
- WebContentsImpl* new_contents = nullptr;
+ std::unique_ptr<WebContents> new_contents;
if (!is_guest) {
create_params.context = view_->GetNativeView();
create_params.initial_size = GetContainerBounds().size();
- new_contents = static_cast<WebContentsImpl*>(
- WebContents::Create(create_params));
+ new_contents = WebContents::Create(create_params);
} else {
- new_contents = GetBrowserPluginGuest()->CreateNewGuestWindow(create_params);
+ new_contents = base::WrapUnique(
+ GetBrowserPluginGuest()->CreateNewGuestWindow(create_params));
}
- new_contents->GetController().SetSessionStorageNamespace(
- partition_id,
- session_storage_namespace);
+ WebContentsImpl* raw_new_contents =
+ static_cast<WebContentsImpl*>(new_contents.get());
+ raw_new_contents->GetController().SetSessionStorageNamespace(
+ partition_id, session_storage_namespace);
// If the new frame has a name, make sure any SiteInstances that can find
// this named frame have proxies for it. Must be called after
// SetSessionStorageNamespace, since this calls CreateRenderView, which uses
// GetSessionStorageNamespace.
if (!params.frame_name.empty())
- new_contents->GetRenderManager()->CreateProxiesForNewNamedFrame();
+ raw_new_contents->GetRenderManager()->CreateProxiesForNewNamedFrame();
// Save the window for later if we're not suppressing the opener (since it
// will be shown immediately).
if (!params.opener_suppressed) {
if (!is_guest) {
- WebContentsView* new_view = new_contents->view_.get();
+ WebContentsView* new_view = raw_new_contents->view_.get();
// TODO(brettw): It seems bogus that we have to call this function on the
// newly created object and give it one of its own member variables.
@@ -2443,20 +2502,21 @@ void WebContentsImpl::CreateNewWindow(
// Save the created window associated with the route so we can show it
// later.
DCHECK_NE(MSG_ROUTING_NONE, main_frame_widget_route_id);
- pending_contents_[std::make_pair(
- render_process_id, main_frame_widget_route_id)] = new_contents;
- AddDestructionObserver(new_contents);
+ pending_contents_[std::make_pair(render_process_id,
+ main_frame_widget_route_id)] =
+ std::move(new_contents);
+ AddDestructionObserver(raw_new_contents);
}
if (delegate_) {
delegate_->WebContentsCreated(this, render_process_id,
opener->GetRoutingID(), params.frame_name,
- params.target_url, new_contents);
+ params.target_url, raw_new_contents);
}
if (opener) {
for (auto& observer : observers_) {
- observer.DidOpenRequestedURL(new_contents, opener, params.target_url,
+ observer.DidOpenRequestedURL(raw_new_contents, opener, params.target_url,
params.referrer, params.disposition,
ui::PAGE_TRANSITION_LINK,
false, // started_from_context_menu
@@ -2473,18 +2533,19 @@ void WebContentsImpl::CreateNewWindow(
// When the opener is suppressed, the original renderer cannot access the
// new window. As a result, we need to show and navigate the window here.
bool was_blocked = false;
+
+ base::WeakPtr<WebContentsImpl> weak_new_contents =
+ raw_new_contents->weak_factory_.GetWeakPtr();
if (delegate_) {
gfx::Rect initial_rect;
- base::WeakPtr<WebContentsImpl> weak_new_contents =
- new_contents->weak_factory_.GetWeakPtr();
-
- delegate_->AddNewContents(
- this, new_contents, params.disposition, initial_rect,
- params.user_gesture, &was_blocked);
+ delegate_->AddNewContents(this, std::move(new_contents),
+ params.disposition, initial_rect,
+ params.user_gesture, &was_blocked);
if (!weak_new_contents)
return; // The delegate deleted |new_contents| during AddNewContents().
}
+
if (!was_blocked) {
OpenURLParams open_params(params.target_url, params.referrer,
WindowOpenDisposition::CURRENT_TAB,
@@ -2494,11 +2555,12 @@ void WebContentsImpl::CreateNewWindow(
if (delegate_ && !is_guest &&
!delegate_->ShouldResumeRequestsForCreatedWindow()) {
+ DCHECK(weak_new_contents);
// We are in asynchronous add new contents path, delay opening url
- new_contents->delayed_open_url_params_.reset(
+ weak_new_contents->delayed_open_url_params_.reset(
new OpenURLParams(open_params));
} else {
- new_contents->OpenURL(open_params);
+ weak_new_contents->OpenURL(open_params);
}
}
}
@@ -2555,24 +2617,26 @@ void WebContentsImpl::ShowCreatedWindow(int process_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {
- WebContentsImpl* popup =
+ std::unique_ptr<WebContents> popup =
GetCreatedWindow(process_id, main_frame_widget_route_id);
if (popup) {
+ WebContentsImpl* raw_popup = static_cast<WebContentsImpl*>(popup.get());
WebContentsDelegate* delegate = GetDelegate();
- popup->is_resume_pending_ = true;
+ raw_popup->is_resume_pending_ = true;
if (!delegate || delegate->ShouldResumeRequestsForCreatedWindow())
- popup->ResumeLoadingCreatedWebContents();
+ raw_popup->ResumeLoadingCreatedWebContents();
+ base::WeakPtr<WebContentsImpl> weak_popup =
+ raw_popup->weak_factory_.GetWeakPtr();
if (delegate) {
- base::WeakPtr<WebContentsImpl> weak_popup =
- popup->weak_factory_.GetWeakPtr();
- delegate->AddNewContents(this, popup, disposition, initial_rect,
- user_gesture, nullptr);
+ delegate->AddNewContents(this, std::move(popup), disposition,
+ initial_rect, user_gesture, nullptr);
if (!weak_popup)
return; // The delegate deleted |popup| during AddNewContents().
}
- RenderWidgetHostImpl* rwh = popup->GetMainFrame()->GetRenderWidgetHost();
+ RenderWidgetHostImpl* rwh =
+ weak_popup->GetMainFrame()->GetRenderWidgetHost();
DCHECK_EQ(main_frame_widget_route_id, rwh->GetRoutingID());
rwh->Send(new ViewMsg_Move_ACK(rwh->GetRoutingID()));
}
@@ -2614,7 +2678,8 @@ void WebContentsImpl::ShowCreatedWidget(int process_id,
fullscreen_widget_routing_id_ = route_id;
if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
- delegate_->EnterFullscreenModeForTab(this, GURL());
+ delegate_->EnterFullscreenModeForTab(this, GURL(),
+ blink::WebFullscreenOptions());
} else {
widget_host_view->InitAsFullscreen(view);
}
@@ -2633,7 +2698,7 @@ void WebContentsImpl::ShowCreatedWidget(int process_id,
render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
}
-WebContentsImpl* WebContentsImpl::GetCreatedWindow(
+std::unique_ptr<WebContents> WebContentsImpl::GetCreatedWindow(
int process_id,
int main_frame_widget_route_id) {
auto key = std::make_pair(process_id, main_frame_widget_route_id);
@@ -2644,17 +2709,18 @@ WebContentsImpl* WebContentsImpl::GetCreatedWindow(
if (iter == pending_contents_.end())
return nullptr;
- WebContentsImpl* new_contents = iter->second;
+ std::unique_ptr<WebContents> new_contents = std::move(iter->second);
pending_contents_.erase(key);
- RemoveDestructionObserver(new_contents);
+ WebContentsImpl* raw_new_contents =
+ static_cast<WebContentsImpl*>(new_contents.get());
+ RemoveDestructionObserver(raw_new_contents);
// Don't initialize the guest WebContents immediately.
- if (BrowserPluginGuest::IsGuest(new_contents))
+ if (BrowserPluginGuest::IsGuest(raw_new_contents))
return new_contents;
if (!new_contents->GetMainFrame()->GetProcess()->HasConnection() ||
!new_contents->GetMainFrame()->GetView()) {
- // TODO(nick): http://crbug.com/674318 -- Who deletes |new_contents|?
return nullptr;
}
@@ -2848,8 +2914,11 @@ TextInputManager* WebContentsImpl::GetTextInputManager() {
if (GetOuterWebContents())
return GetOuterWebContents()->GetTextInputManager();
- if (!text_input_manager_)
- text_input_manager_.reset(new TextInputManager());
+ if (!text_input_manager_) {
+ text_input_manager_.reset(new TextInputManager(
+ GetBrowserContext() &&
+ !GetBrowserContext()->IsOffTheRecord()) /* should_do_learning */);
+ }
return text_input_manager_.get();
}
@@ -2939,8 +3008,7 @@ void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
void WebContentsImpl::ResizeDueToAutoResize(
RenderWidgetHostImpl* render_widget_host,
- const gfx::Size& new_size,
- uint64_t sequence_number) {
+ const gfx::Size& new_size) {
if (render_widget_host != GetRenderViewHost()->GetWidget())
return;
@@ -2954,7 +3022,7 @@ void WebContentsImpl::ResizeDueToAutoResize(
RenderWidgetHostImpl* host =
node->current_frame_host()->GetRenderWidgetHost();
if (host != render_widget_host)
- host->WasResized();
+ host->SynchronizeVisualProperties();
}
}
@@ -3904,6 +3972,9 @@ void WebContentsImpl::DidNavigateMainFramePreCommit(
if (IsFullscreenForCurrentTab())
ExitFullscreen(false);
DCHECK(!IsFullscreenForCurrentTab());
+
+ // Clean up keyboard lock state when navigating.
+ CancelKeyboardLock(keyboard_lock_widget_);
}
void WebContentsImpl::DidNavigateMainFramePostCommit(
@@ -4103,7 +4174,8 @@ void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) {
auto navigation_entry = std::make_unique<NavigationEntryImpl>(
site_instance_for_view_source, frame_entry->url(),
referrer_for_view_source, title_for_view_source, ui::PAGE_TRANSITION_LINK,
- /* is_renderer_initiated = */ false);
+ /* is_renderer_initiated = */ false,
+ /* blob_url_loader_factory = */ nullptr);
navigation_entry->SetVirtualURL(GURL(content::kViewSourceScheme +
std::string(":") +
frame_entry->url().spec()));
@@ -4120,8 +4192,8 @@ void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) {
new_frame_entry->SetPageState(new_page_state);
// Create a new WebContents, which is used to display the source code.
- WebContentsImpl* view_source_contents =
- static_cast<WebContentsImpl*>(Create(CreateParams(GetBrowserContext())));
+ std::unique_ptr<WebContents> view_source_contents =
+ Create(CreateParams(GetBrowserContext()));
// Restore the previously created NavigationEntry.
std::vector<std::unique_ptr<NavigationEntry>> navigation_entries;
@@ -4133,7 +4205,7 @@ void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) {
gfx::Rect initial_rect;
constexpr bool kUserGesture = true;
bool ignored_was_blocked;
- delegate_->AddNewContents(this, view_source_contents,
+ delegate_->AddNewContents(this, std::move(view_source_contents),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
initial_rect, kUserGesture, &ignored_was_blocked);
// Note that the |delegate_| could have deleted |view_source_contents| during
@@ -4147,9 +4219,10 @@ void WebContentsImpl::SubresourceResponseStarted(const GURL& url,
}
void WebContentsImpl::ResourceLoadComplete(
+ RenderFrameHost* render_frame_host,
mojom::ResourceLoadInfoPtr resource_load_info) {
for (auto& observer : observers_) {
- observer.ResourceLoadComplete(*resource_load_info);
+ observer.ResourceLoadComplete(render_frame_host, *resource_load_info);
}
}
@@ -4175,18 +4248,6 @@ void WebContentsImpl::PrintCrossProcessSubframe(
subframe_host);
}
-void WebContentsImpl::UpdatePictureInPictureSurfaceId(
- const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size) {
- if (delegate_)
- delegate_->UpdatePictureInPictureSurfaceId(surface_id, natural_size);
-}
-
-void WebContentsImpl::ExitPictureInPicture() {
- if (delegate_)
- delegate_->ExitPictureInPicture();
-}
-
#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject>
WebContentsImpl::GetJavaRenderFrameHostDelegate() {
@@ -4338,22 +4399,6 @@ void WebContentsImpl::OnFindReply(RenderFrameHostImpl* source,
}
#if defined(OS_ANDROID)
-void WebContentsImpl::OnFindMatchRectsReply(
- RenderFrameHostImpl* source,
- int version,
- const std::vector<gfx::RectF>& rects,
- const gfx::RectF& active_rect) {
- GetOrCreateFindRequestManager()->OnFindMatchRectsReply(source, version, rects,
- active_rect);
-}
-
-void WebContentsImpl::OnGetNearestFindResultReply(RenderFrameHostImpl* source,
- int request_id,
- float distance) {
- GetOrCreateFindRequestManager()->OnGetNearestFindResultReply(
- source, request_id, distance);
-}
-
void WebContentsImpl::OnOpenDateTimeDialog(
RenderViewHostImpl* source,
const ViewHostMsg_DateTimeDialogValue_Params& value) {
@@ -4662,16 +4707,13 @@ void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
RenderFrameHost* new_host) {
#if defined(OS_ANDROID)
- // Try to copy importance from either |old_host| or parent of |new_host|.
- // If both are null, then this is the very first frame host created from Init.
- // There is no need to pass importance in this case because there is no chance
- // for anything to call SetImportance yet.
- RenderFrameHostImpl* importance_host = static_cast<RenderFrameHostImpl*>(
- old_host ? old_host : new_host->GetParent());
- if (importance_host) {
+ // Copy importance from |old_host| if |new_host| is a main frame.
+ if (old_host && !new_host->GetParent()) {
static_cast<RenderFrameHostImpl*>(new_host)
->GetRenderWidgetHost()
- ->SetImportance(importance_host->GetRenderWidgetHost()->importance());
+ ->SetImportance(static_cast<RenderFrameHostImpl*>(old_host)
+ ->GetRenderWidgetHost()
+ ->importance());
}
#endif
for (auto& observer : observers_)
@@ -5788,7 +5830,7 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
RenderWidgetHostView* rwh_view = render_view_host->GetWidget()->GetView();
if (rwh_view) {
if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
- render_widget_host->WasResized();
+ render_widget_host->SynchronizeVisualProperties();
}
#endif
@@ -6113,6 +6155,18 @@ void WebContentsImpl::BrowserPluginGuestWillDetach() {
outermost->SetAsFocusedWebContentsIfNecessary();
}
+gfx::Size WebContentsImpl::EnterPictureInPicture(
+ const viz::SurfaceId& surface_id,
+ const gfx::Size& natural_size) {
+ return delegate_ ? delegate_->EnterPictureInPicture(surface_id, natural_size)
+ : gfx::Size();
+}
+
+void WebContentsImpl::ExitPictureInPicture() {
+ if (delegate_)
+ delegate_->ExitPictureInPicture();
+}
+
#if defined(OS_ANDROID)
void WebContentsImpl::NotifyFindMatchRectsReply(
int version,
@@ -6158,6 +6212,19 @@ void WebContentsImpl::ClearDeviceEmulationSize() {
view_size_before_emulation_ = gfx::Size();
}
+ForwardingAudioStreamFactory* WebContentsImpl::GetAudioStreamFactory() {
+ if (!audio_stream_factory_) {
+ audio_stream_factory_.emplace(
+ this,
+ content::ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->Clone(),
+ AudioStreamBrokerFactory::CreateImpl());
+ }
+
+ return &*audio_stream_factory_;
+}
+
void WebContentsImpl::MediaStartedPlaying(
const WebContentsObserver::MediaPlayerInfo& media_info,
const WebContentsObserver::MediaPlayerId& id) {
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index aeda7bbac34..cd1c992c773 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -19,6 +19,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/observer_list.h"
+#include "base/optional.h"
#include "base/process/process.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -33,6 +34,7 @@
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/media/audio_stream_monitor.h"
+#include "content/browser/media/forwarding_audio_stream_factory.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -137,7 +139,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
~WebContentsImpl() override;
- static WebContentsImpl* CreateWithOpener(
+ static std::unique_ptr<WebContentsImpl> CreateWithOpener(
const WebContents::CreateParams& params,
RenderFrameHostImpl* opener_rfh);
@@ -286,16 +288,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
return manifest_manager_host_.get();
}
- // TODO(https://crbug.com/826293): This is a simple mitigation to validate
- // that an action that requires a user gesture actually has one in the
- // trustworthy browser process, rather than relying on the untrustworthy
- // renderer. This should be eventually merged into and accounted for in the
- // user activation work.
- bool HasRecentInteractiveInputEvent() const;
-
#if defined(OS_ANDROID)
- std::set<RenderWidgetHostImpl*> GetAllRenderWidgetHosts();
- void SetImportance(ChildProcessImportance importance);
+ void SetMainFrameImportance(ChildProcessImportance importance);
#endif
// WebContents ------------------------------------------------------
@@ -355,6 +349,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void SetAudioMuted(bool mute) override;
bool IsCurrentlyAudible() override;
bool IsConnectedToBluetoothDevice() const override;
+ bool HasPictureInPictureVideo() const override;
bool IsCrashed() const override;
void SetIsCrashed(base::TerminationStatus status, int error_code) override;
base::TerminationStatus GetCrashedStatus() const override;
@@ -379,7 +374,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void Stop() override;
void FreezePage() override;
- WebContents* Clone() override;
+ std::unique_ptr<WebContents> Clone() override;
void ReloadFocusedFrame(bool bypass_cache) override;
void Undo() override;
void Redo() override;
@@ -480,6 +475,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
bool CompletedFirstVisuallyNonEmptyPaint() const override;
#endif
+ bool HasRecentInteractiveInputEvent() const override;
+
// Implementation of PageNavigator.
WebContents* OpenURL(const OpenURLParams& params) override;
@@ -538,7 +535,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
#if defined(OS_ANDROID)
void GetNFC(device::mojom::NFCRequest request) override;
#endif
- void EnterFullscreenMode(const GURL& origin) override;
+ void EnterFullscreenMode(const GURL& origin,
+ const blink::WebFullscreenOptions& options) override;
void ExitFullscreenMode(bool will_cause_resize) override;
bool ShouldRouteMessageEvent(
RenderFrameHost* target_rfh,
@@ -584,11 +582,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void SubresourceResponseStarted(const GURL& url,
net::CertStatus cert_status) override;
void ResourceLoadComplete(
+ RenderFrameHost* render_frame_host,
mojom::ResourceLoadInfoPtr resource_load_information) override;
- void UpdatePictureInPictureSurfaceId(const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size) override;
- void ExitPictureInPicture() override;
-
// RenderViewHostDelegate ----------------------------------------------------
RenderViewHostDelegateView* GetDelegateView() override;
bool OnMessageReceived(RenderViewHostImpl* render_view_host,
@@ -696,8 +691,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
const ScreenInfo& screen_info,
bool width_changed) override;
void ResizeDueToAutoResize(RenderWidgetHostImpl* render_widget_host,
- const gfx::Size& new_size,
- uint64_t sequence_number) override;
+ const gfx::Size& new_size) override;
gfx::Size GetAutoResizeSize() override;
void ResetAutoResizeSize() override;
KeyboardEventProcessingResult PreHandleKeyboardEvent(
@@ -871,6 +865,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
return &audio_stream_monitor_;
}
+ ForwardingAudioStreamFactory* GetAudioStreamFactory();
+
// Called by MediaWebContentsObserver when playback starts or stops. See the
// WebContentsObserver function stubs for more details.
void MediaStartedPlaying(
@@ -936,6 +932,20 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// that the guest will be detached.
void BrowserPluginGuestWillDetach();
+ // Notifies the Picture-in-Picture controller that there is a new player
+ // entering Picture-in-Picture.
+ // Returns the size of the Picture-in-Picture window.
+ gfx::Size EnterPictureInPicture(const viz::SurfaceId&,
+ const gfx::Size& natural_size);
+
+ // Updates the Picture-in-Picture controller with a signal that
+ // Picture-in-Picture mode has ended.
+ void ExitPictureInPicture();
+
+ // Updates the tracking information for |this| to know if there is
+ // a video currently in Picture-in-Picture mode.
+ void SetHasPictureInPictureVideo(bool has_picture_in_picture_video);
+
#if defined(OS_ANDROID)
// Called by FindRequestManager when all of the find match rects are in.
void NotifyFindMatchRectsReply(int version,
@@ -943,10 +953,16 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
const gfx::RectF& active_rect);
#endif
+ // Returns a base salt used to generate group IDs for media-device
+ // enumerations.
+ const std::string& GetMediaDeviceGroupIDSaltBase() const;
+
private:
friend class WebContentsObserver;
friend class WebContents; // To implement factory methods.
+ friend class RenderFrameHostImplBeforeUnloadBrowserTest;
+
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, NoJSMessageOnInterstitials);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, UpdateTitle);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, FindOpenerRVHWhenPending);
@@ -1147,13 +1163,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
int active_match_ordinal,
bool final_update);
#if defined(OS_ANDROID)
- void OnFindMatchRectsReply(RenderFrameHostImpl* source,
- int version,
- const std::vector<gfx::RectF>& rects,
- const gfx::RectF& active_rect);
- void OnGetNearestFindResultReply(RenderFrameHostImpl* source,
- int request_id,
- float distance);
void OnOpenDateTimeDialog(
RenderViewHostImpl* source,
const ViewHostMsg_DateTimeDialogValue_Params& value);
@@ -1260,8 +1269,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Finds the new WebContentsImpl by |main_frame_widget_route_id|, initializes
// it for renderer-initiated creation, and returns it. Note that this can only
// be called once as this call also removes it from the internal map.
- WebContentsImpl* GetCreatedWindow(int process_id,
- int main_frame_widget_route_id);
+ std::unique_ptr<WebContents> GetCreatedWindow(int process_id,
+ int main_frame_widget_route_id);
// Sends a Page message IPC.
void SendPageMessage(IPC::Message* msg);
@@ -1380,7 +1389,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Tracks created WebContentsImpl objects that have not been shown yet. They
// are identified by the process ID and routing ID passed to CreateNewWindow.
typedef std::pair<int, int> ProcessRoutingIdPair;
- std::map<ProcessRoutingIdPair, WebContentsImpl*> pending_contents_;
+ std::map<ProcessRoutingIdPair, std::unique_ptr<WebContents>>
+ pending_contents_;
// This map holds widgets that were created on behalf of the renderer but
// haven't been shown yet.
@@ -1644,11 +1654,16 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Monitors power levels for audio streams associated with this WebContents.
AudioStreamMonitor audio_stream_monitor_;
+ // Coordinates all the audio streams for this WebContents. Lazily initialized.
+ base::Optional<ForwardingAudioStreamFactory> audio_stream_factory_;
+
// Created on-demand to mute all audio output from this WebContents.
std::unique_ptr<WebContentsAudioMuter> audio_muter_;
size_t bluetooth_connected_device_count_;
+ bool has_picture_in_picture_video_ = false;
+
// Notifies ResourceDispatcherHostImpl of various events related to loading.
std::unique_ptr<LoaderIOThreadNotifier> loader_io_thread_notifier_;
@@ -1668,6 +1683,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
PageImportanceSignals page_importance_signals_;
+ std::string media_device_group_id_salt_base_;
+
#if !defined(OS_ANDROID)
bool page_scale_factor_is_one_;
#endif // !defined(OS_ANDROID)
diff --git a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
index 5a902419130..7c85b1f8fe1 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -2,15 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <array>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
+#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/pattern.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -23,6 +26,7 @@
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/load_notification_details.h"
#include "content/public/browser/navigation_controller.h"
@@ -35,6 +39,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
@@ -45,6 +50,7 @@
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/test_content_browser_client.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -78,6 +84,28 @@ void ResizeWebContentsView(Shell* shell, const gfx::Size& size,
#endif // defined(OS_MACOSX)
}
+// Class to test that OverrideWebkitPrefs has been called for all relevant
+// RenderViewHosts.
+class NotifyPreferencesChangedTestContentBrowserClient
+ : public TestContentBrowserClient {
+ public:
+ NotifyPreferencesChangedTestContentBrowserClient() = default;
+
+ void OverrideWebkitPrefs(RenderViewHost* render_view_host,
+ WebPreferences* prefs) override {
+ override_webkit_prefs_rvh_set_.insert(render_view_host);
+ }
+
+ const std::unordered_set<RenderViewHost*>& override_webkit_prefs_rvh_set() {
+ return override_webkit_prefs_rvh_set_;
+ }
+
+ private:
+ std::unordered_set<RenderViewHost*> override_webkit_prefs_rvh_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotifyPreferencesChangedTestContentBrowserClient);
+};
+
class WebContentsImplBrowserTest : public ContentBrowserTest {
public:
WebContentsImplBrowserTest() {}
@@ -87,8 +115,6 @@ class WebContentsImplBrowserTest : public ContentBrowserTest {
}
void SetUpOnMainThread() override {
- host_resolver()->AddRuleWithLatency("slow.com", "127.0.0.1",
- 1000 * 60 * 60 /* ms */);
// Setup the server to allow serving separate sites, so we can perform
// cross-process navigation.
host_resolver()->AddRule("*", "127.0.0.1");
@@ -629,40 +655,71 @@ class ResourceLoadObserver : public WebContentsObserver {
return resource_load_infos_;
}
+ const std::vector<bool>& resource_is_associated_with_main_frame() const {
+ return resource_is_associated_with_main_frame_;
+ }
+
const std::vector<GURL>& memory_cached_loaded_urls() const {
return memory_cached_loaded_urls_;
}
// Use this method with the SCOPED_TRACE macro, so it shows the caller context
// if it fails.
- void CheckResourceLoaded(const GURL& url,
- const GURL& referrer,
- const std::string& load_method,
- content::ResourceType resource_type,
- const std::string& mime_type,
- const std::string& ip_address,
- bool was_cached,
- bool first_network_request,
- const base::TimeTicks& before_request,
- const base::TimeTicks& after_request) {
+ void CheckResourceLoaded(
+ const GURL& url,
+ const GURL& referrer,
+ const std::string& load_method,
+ content::ResourceType resource_type,
+ const base::FilePath::StringPieceType& served_file_name,
+ const std::string& mime_type,
+ const std::string& ip_address,
+ bool was_cached,
+ bool first_network_request,
+ const base::TimeTicks& before_request,
+ const base::TimeTicks& after_request) {
bool resource_load_info_found = false;
for (const auto& resource_load_info : resource_load_infos_) {
- if (resource_load_info->url == url) {
- resource_load_info_found = true;
- EXPECT_EQ(referrer, resource_load_info->referrer);
- EXPECT_EQ(load_method, resource_load_info->method);
- EXPECT_EQ(resource_type, resource_load_info->resource_type);
- if (!first_network_request)
- EXPECT_GT(resource_load_info->request_id, 0);
- EXPECT_EQ(mime_type, resource_load_info->mime_type);
- if (!ip_address.empty()) {
- ASSERT_TRUE(resource_load_info->ip);
- EXPECT_EQ(ip_address, resource_load_info->ip->ToString());
- }
- EXPECT_EQ(was_cached, resource_load_info->was_cached);
- // Simple sanity check of the request start time.
- EXPECT_GT(resource_load_info->request_start, before_request);
- EXPECT_GT(after_request, resource_load_info->request_start);
+ if (resource_load_info->url != url)
+ continue;
+
+ resource_load_info_found = true;
+ int64_t file_size = -1;
+ if (!served_file_name.empty()) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath test_dir;
+ ASSERT_TRUE(base::PathService::Get(content::DIR_TEST_DATA, &test_dir));
+ base::FilePath served_file = test_dir.Append(served_file_name);
+ ASSERT_TRUE(GetFileSize(served_file, &file_size));
+ }
+ EXPECT_EQ(referrer, resource_load_info->referrer);
+ EXPECT_EQ(load_method, resource_load_info->method);
+ EXPECT_EQ(resource_type, resource_load_info->resource_type);
+ if (!first_network_request)
+ EXPECT_GT(resource_load_info->request_id, 0);
+ EXPECT_EQ(mime_type, resource_load_info->mime_type);
+ ASSERT_TRUE(resource_load_info->network_info->ip_port_pair);
+ EXPECT_EQ(ip_address,
+ resource_load_info->network_info->ip_port_pair->host());
+ EXPECT_EQ(was_cached, resource_load_info->was_cached);
+ // Simple sanity check of the load timing info.
+ auto CheckTime = [before_request, after_request](auto actual) {
+ EXPECT_LE(before_request, actual);
+ EXPECT_GT(after_request, actual);
+ };
+ const net::LoadTimingInfo& timing = resource_load_info->load_timing_info;
+ CheckTime(timing.request_start);
+ CheckTime(timing.receive_headers_end);
+ CheckTime(timing.send_start);
+ CheckTime(timing.send_end);
+ if (!was_cached) {
+ CheckTime(timing.connect_timing.dns_start);
+ CheckTime(timing.connect_timing.dns_end);
+ CheckTime(timing.connect_timing.connect_start);
+ CheckTime(timing.connect_timing.connect_end);
+ }
+ if (file_size != -1) {
+ EXPECT_EQ(file_size, resource_load_info->raw_body_bytes);
+ EXPECT_LT(file_size, resource_load_info->total_received_bytes);
}
}
EXPECT_TRUE(resource_load_info_found);
@@ -671,13 +728,18 @@ class ResourceLoadObserver : public WebContentsObserver {
void Reset() {
resource_load_infos_.clear();
memory_cached_loaded_urls_.clear();
+ resource_is_associated_with_main_frame_.clear();
}
private:
// WebContentsObserver implementation:
void ResourceLoadComplete(
+ content::RenderFrameHost* render_frame_host,
const mojom::ResourceLoadInfo& resource_load_info) override {
+ EXPECT_NE(nullptr, render_frame_host);
resource_load_infos_.push_back(resource_load_info.Clone());
+ resource_is_associated_with_main_frame_.push_back(
+ render_frame_host->GetParent() == nullptr);
}
void DidLoadResourceFromMemoryCache(const GURL& url,
@@ -688,6 +750,7 @@ class ResourceLoadObserver : public WebContentsObserver {
std::vector<GURL> memory_cached_loaded_urls_;
std::vector<mojom::ResourceLoadInfoPtr> resource_load_infos_;
+ std::vector<bool> resource_is_associated_with_main_frame_;
DISALLOW_COPY_AND_ASSIGN(ResourceLoadObserver);
};
@@ -701,23 +764,19 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ResourceLoadComplete) {
NavigateToURL(shell(), page_url);
base::TimeTicks after = base::TimeTicks::Now();
ASSERT_EQ(3U, observer.resource_load_infos().size());
- // TODO(crbug.com/826082): we should test the IP address/MIME type parameters
- // for frames once they are reported correctly.
SCOPE_TRACED(observer.CheckResourceLoaded(
page_url, /*referrer=*/GURL(), "GET", content::RESOURCE_TYPE_MAIN_FRAME,
- /*mime-type*/ "",
- /*ip_address=*/"",
+ FILE_PATH_LITERAL("page_with_iframe.html"), "text/html", "127.0.0.1",
/*was_cached=*/false, /*first_network_request=*/true, before, after));
SCOPE_TRACED(observer.CheckResourceLoaded(
embedded_test_server()->GetURL("/image.jpg"),
- /*referrer=*/page_url, "GET", content::RESOURCE_TYPE_IMAGE, "image/jpeg",
- "127.0.0.1",
+ /*referrer=*/page_url, "GET", content::RESOURCE_TYPE_IMAGE,
+ FILE_PATH_LITERAL("image.jpg"), "image/jpeg", "127.0.0.1",
/*was_cached=*/false, /*first_network_request=*/false, before, after));
SCOPE_TRACED(observer.CheckResourceLoaded(
embedded_test_server()->GetURL("/title1.html"),
/*referrer=*/page_url, "GET", content::RESOURCE_TYPE_SUB_FRAME,
- /*mime_type=*/"",
- /*ip_address=*/"",
+ FILE_PATH_LITERAL("title1.html"), "text/html", "127.0.0.1",
/*was_cached=*/false, /*first_network_request=*/false, before, after));
}
@@ -733,20 +792,20 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
NavigateToURL(shell(), page_url);
base::TimeTicks after = base::TimeTicks::Now();
- // TODO(crbug.com/826082): we should test the IP address/MIME type parameters
- // for frames once they are reported correctly.
GURL resource_url = embedded_test_server()->GetURL("/cachetime");
ASSERT_EQ(2U, observer.resource_load_infos().size());
SCOPE_TRACED(observer.CheckResourceLoaded(
page_url, /*referrer=*/GURL(), "GET", content::RESOURCE_TYPE_MAIN_FRAME,
- /*mime-type*/ "",
- /*ip_address=*/"", /*was_cached=*/false, /*first_network_request=*/true,
- before, after));
+ /*served_file_name=*/FILE_PATH_LITERAL(""), "text/html", "127.0.0.1",
+ /*was_cached=*/false,
+ /*first_network_request=*/true, before, after));
+
SCOPE_TRACED(observer.CheckResourceLoaded(
resource_url, /*referrer=*/page_url, "GET", content::RESOURCE_TYPE_SCRIPT,
- "text/html", "127.0.0.1",
+ /*served_file_name=*/FILE_PATH_LITERAL(""), "text/html", "127.0.0.1",
/*was_cached=*/false, /*first_network_request=*/false, before, after));
- EXPECT_TRUE(observer.resource_load_infos()[1]->network_accessed);
+ EXPECT_TRUE(
+ observer.resource_load_infos()[1]->network_info->network_accessed);
EXPECT_TRUE(observer.memory_cached_loaded_urls().empty());
observer.Reset();
@@ -757,7 +816,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
ASSERT_EQ(1U, observer.resource_load_infos().size());
SCOPE_TRACED(observer.CheckResourceLoaded(
page_url, /*referrer=*/GURL(), "GET", content::RESOURCE_TYPE_MAIN_FRAME,
- /*mime-type*/ "", /*ip_address=*/"",
+ /*served_file_name=*/FILE_PATH_LITERAL(""), "text/html", "127.0.0.1",
/*was_cached=*/false, /*first_network_request=*/false, before, after));
ASSERT_EQ(1U, observer.memory_cached_loaded_urls().size());
EXPECT_EQ(resource_url, observer.memory_cached_loaded_urls()[0]);
@@ -774,14 +833,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
ASSERT_EQ(2U, observer.resource_load_infos().size());
SCOPE_TRACED(observer.CheckResourceLoaded(
page_url, /*referrer=*/GURL(), "GET", content::RESOURCE_TYPE_MAIN_FRAME,
- /*mime-type*/ "", /*ip_address=*/"",
+ /*served_file_name=*/FILE_PATH_LITERAL(""), "text/html", "127.0.0.1",
/*was_cached=*/false, /*first_network_request=*/true, before, after));
SCOPE_TRACED(observer.CheckResourceLoaded(
resource_url, /*referrer=*/page_url, "GET", content::RESOURCE_TYPE_SCRIPT,
- "text/html", "127.0.0.1",
+ /*served_file_name=*/FILE_PATH_LITERAL(""), "text/html", "127.0.0.1",
/*was_cached=*/true, /*first_network_request=*/false, before, after));
EXPECT_TRUE(observer.memory_cached_loaded_urls().empty());
- EXPECT_FALSE(observer.resource_load_infos()[1]->network_accessed);
+ EXPECT_FALSE(
+ observer.resource_load_infos()[1]->network_info->network_accessed);
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
@@ -791,16 +851,17 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
NavigateToURL(shell(),
GURL(embedded_test_server()->GetURL("/page_with_image.html")));
ASSERT_EQ(2U, observer.resource_load_infos().size());
- // TODO(crbug.com/826082): network_accessed should be true on the frame.
- EXPECT_FALSE(observer.resource_load_infos()[0]->network_accessed);
- EXPECT_TRUE(observer.resource_load_infos()[1]->network_accessed);
+ EXPECT_TRUE(
+ observer.resource_load_infos()[0]->network_info->network_accessed);
+ EXPECT_TRUE(
+ observer.resource_load_infos()[1]->network_info->network_accessed);
observer.Reset();
NavigateToURL(shell(), GURL("chrome://gpu"));
ASSERT_LE(1U, observer.resource_load_infos().size());
for (const mojom::ResourceLoadInfoPtr& resource_load_info :
observer.resource_load_infos()) {
- EXPECT_FALSE(resource_load_info->network_accessed);
+ EXPECT_FALSE(resource_load_info->network_info->network_accessed);
}
}
@@ -818,9 +879,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
ASSERT_EQ(2U, observer.resource_load_infos().size());
const mojom::ResourceLoadInfoPtr& page_load_info =
observer.resource_load_infos()[0];
- // TODO(crbug.com/826082): turn this back on when the ResourceDispatcher
- // receives redirects for the main frame.
- // EXPECT_EQ(page_destination_url, page_load_info->url);
+ EXPECT_EQ(page_destination_url, page_load_info->url);
EXPECT_EQ(page_original_url, page_load_info->original_url);
GURL image_destination_url(embedded_test_server()->GetURL("/blank.jpg"));
@@ -866,6 +925,87 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
observer.resource_load_infos()[1]->net_error);
}
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ ResourceLoadCompleteAlwaysAccessNetwork) {
+ ResourceLoadObserver observer(shell());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL cacheable_url(embedded_test_server()->GetURL("/set-header"));
+ NavigateToURL(shell(), cacheable_url);
+ ASSERT_EQ(1U, observer.resource_load_infos().size());
+ EXPECT_FALSE(
+ observer.resource_load_infos()[0]->network_info->always_access_network);
+ observer.Reset();
+
+ std::array<std::string, 3> headers = {
+ "cache-control: no-cache", "cache-control: no-store", "pragma: no-cache"};
+ for (const std::string& header : headers) {
+ GURL no_cache_url(embedded_test_server()->GetURL("/set-header?" + header));
+ NavigateToURL(shell(), no_cache_url);
+ ASSERT_EQ(1U, observer.resource_load_infos().size());
+ EXPECT_TRUE(
+ observer.resource_load_infos()[0]->network_info->always_access_network);
+ observer.Reset();
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ ResourceLoadCompleteWithRedirects) {
+ ResourceLoadObserver observer(shell());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL target_url(embedded_test_server()->GetURL("/title1.html"));
+ GURL intermediate_url(
+ embedded_test_server()->GetURL("/server-redirect?" + target_url.spec()));
+ GURL start_url(embedded_test_server()->GetURL("/server-redirect?" +
+ intermediate_url.spec()));
+
+ NavigateToURL(shell(), start_url);
+
+ ASSERT_EQ(1U, observer.resource_load_infos().size());
+ EXPECT_EQ(target_url, observer.resource_load_infos()[0]->url);
+
+ ASSERT_EQ(2U, observer.resource_load_infos()[0]->redirect_info_chain.size());
+ EXPECT_EQ(intermediate_url,
+ observer.resource_load_infos()[0]->redirect_info_chain[0]->url);
+ EXPECT_TRUE(observer.resource_load_infos()[0]
+ ->redirect_info_chain[0]
+ ->network_info->network_accessed);
+ EXPECT_FALSE(observer.resource_load_infos()[0]
+ ->redirect_info_chain[0]
+ ->network_info->always_access_network);
+ EXPECT_EQ(target_url,
+ observer.resource_load_infos()[0]->redirect_info_chain[1]->url);
+ EXPECT_TRUE(observer.resource_load_infos()[0]
+ ->redirect_info_chain[1]
+ ->network_info->network_accessed);
+ EXPECT_FALSE(observer.resource_load_infos()[0]
+ ->redirect_info_chain[1]
+ ->network_info->always_access_network);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ ResourceLoadCompleteIsMainFrame) {
+ ResourceLoadObserver observer(shell());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(embedded_test_server()->GetURL("/page_with_image.html"));
+ NavigateToURL(shell(), url);
+ ASSERT_EQ(2U, observer.resource_load_infos().size());
+ EXPECT_EQ(url, observer.resource_load_infos()[0]->url);
+ EXPECT_TRUE(observer.resource_is_associated_with_main_frame()[0]);
+ EXPECT_TRUE(observer.resource_is_associated_with_main_frame()[1]);
+ observer.Reset();
+
+ // Load that same page inside an iframe.
+ GURL data_url("data:text/html,<iframe src='" + url.spec() + "'></iframe>");
+ NavigateToURL(shell(), data_url);
+ ASSERT_EQ(2U, observer.resource_load_infos().size());
+ EXPECT_EQ(url, observer.resource_load_infos()[0]->url);
+ EXPECT_FALSE(observer.resource_is_associated_with_main_frame()[0]);
+ EXPECT_FALSE(observer.resource_is_associated_with_main_frame()[1]);
+}
+
struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
public WebContentsObserver {
explicit LoadProgressDelegateAndObserver(Shell* shell)
@@ -1062,7 +1202,11 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangeDisplayMode) {
delegate.set_mode(blink::kWebDisplayModeFullscreen);
// Simulate widget is entering fullscreen (changing size is enough).
- shell()->web_contents()->GetRenderViewHost()->GetWidget()->WasResized();
+ shell()
+ ->web_contents()
+ ->GetRenderViewHost()
+ ->GetWidget()
+ ->SynchronizeVisualProperties();
ASSERT_TRUE(ExecuteScript(shell(),
"document.title = "
@@ -1393,8 +1537,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
return this;
}
- void EnterFullscreenModeForTab(WebContents* web_contents,
- const GURL& origin) override {
+ void EnterFullscreenModeForTab(
+ WebContents* web_contents,
+ const GURL& origin,
+ const blink::WebFullscreenOptions& options) override {
is_fullscreen_ = true;
}
@@ -1411,12 +1557,12 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
}
void AddNewContents(WebContents* source,
- WebContents* new_contents,
+ std::unique_ptr<WebContents> new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture,
bool* was_blocked) override {
- popup_.reset(new_contents);
+ popup_ = std::move(new_contents);
if (waiting_for_ == kNewContents)
run_loop_->Quit();
@@ -1569,10 +1715,10 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
WebContents* base_web_contents = shell()->web_contents();
ASSERT_TRUE(base_web_contents);
- GURL url(embedded_test_server()->GetURL("c.com", "/title3.html"));
WebContents::CreateParams create_params(
base_web_contents->GetBrowserContext());
- create_params.initialize_renderer = true;
+ create_params.desired_renderer_state =
+ WebContents::CreateParams::kInitializeAndWarmupRendererProcess;
create_params.initial_size =
base_web_contents->GetContainerBounds().size();
std::unique_ptr<WebContents> web_contents(WebContents::Create(create_params));
@@ -1581,11 +1727,18 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// There is no navigation (to about:blank or something like that).
EXPECT_FALSE(web_contents->IsLoading());
+ // The WebContents have an associated main frame and a renderer process that
+ // has either already launched (or is in the process of being launched).
ASSERT_TRUE(web_contents->GetMainFrame());
EXPECT_TRUE(web_contents->GetMainFrame()->IsRenderFrameLive());
EXPECT_TRUE(web_contents->GetController().IsInitialBlankNavigation());
- int renderer_id = web_contents->GetMainFrame()->GetProcess()->GetID();
+ RenderProcessHost* process = web_contents->GetMainFrame()->GetProcess();
+ int renderer_id = process->GetID();
+ ASSERT_TRUE(process);
+ EXPECT_TRUE(process->HasConnection());
+ // Navigate the WebContents.
+ GURL url(embedded_test_server()->GetURL("c.com", "/title3.html"));
TestNavigationObserver same_tab_observer(web_contents.get());
NavigationController::LoadURLParams params(url);
params.transition_type = ui::PageTransitionFromInt(
@@ -1595,6 +1748,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(same_tab_observer.last_navigation_succeeded());
// Check that pre-warmed process is used.
+ EXPECT_EQ(process, web_contents->GetMainFrame()->GetProcess());
EXPECT_EQ(renderer_id, web_contents->GetMainFrame()->GetProcess()->GetID());
EXPECT_EQ(1, web_contents->GetController().GetEntryCount());
NavigationEntry* entry =
@@ -1603,6 +1757,67 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_EQ(url, entry->GetURL());
}
+// Regression test for https://crbug.com/840409.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ CreateWebContentsWithoutRendererProcess) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContents* base_web_contents = shell()->web_contents();
+ ASSERT_TRUE(base_web_contents);
+
+ for (int i = 1; i <= 2; i++) {
+ SCOPED_TRACE(testing::Message() << "Iteration #" << i);
+
+ WebContents::CreateParams create_params(
+ base_web_contents->GetBrowserContext());
+ create_params.desired_renderer_state =
+ WebContents::CreateParams::kNoRendererProcess;
+ create_params.initial_size = base_web_contents->GetContainerBounds().size();
+ std::unique_ptr<WebContents> web_contents(
+ WebContents::Create(create_params));
+ ASSERT_TRUE(web_contents);
+ base::RunLoop().RunUntilIdle();
+
+ // There is no navigation (to about:blank or something like that) yet.
+ EXPECT_FALSE(web_contents->IsLoading());
+
+ // The WebContents have an associated main frame and a RenderProcessHost
+ // object, but no actual OS process has been launched yet.
+ ASSERT_TRUE(web_contents->GetMainFrame());
+ EXPECT_FALSE(web_contents->GetMainFrame()->IsRenderFrameLive());
+ EXPECT_TRUE(web_contents->GetController().IsInitialBlankNavigation());
+ RenderProcessHost* process = web_contents->GetMainFrame()->GetProcess();
+ int renderer_id = process->GetID();
+ ASSERT_TRUE(process);
+ EXPECT_FALSE(process->HasConnection());
+ EXPECT_EQ(base::kNullProcessHandle, process->GetProcess().Handle());
+
+ // Navigate the WebContents.
+ GURL url(embedded_test_server()->GetURL("c.com", "/title3.html"));
+ TestNavigationObserver same_tab_observer(web_contents.get());
+ NavigationController::LoadURLParams params(url);
+ params.transition_type = ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
+ web_contents->GetController().LoadURLWithParams(params);
+ same_tab_observer.Wait();
+ EXPECT_TRUE(same_tab_observer.last_navigation_succeeded());
+
+ // The process should be launched now.
+ EXPECT_TRUE(process->HasConnection());
+ EXPECT_NE(base::kNullProcessHandle, process->GetProcess().Handle());
+
+ // Check that the RenderProcessHost and its ID didn't change.
+ EXPECT_EQ(process, web_contents->GetMainFrame()->GetProcess());
+ EXPECT_EQ(renderer_id, web_contents->GetMainFrame()->GetProcess()->GetID());
+
+ // Verify that the navigation succeeded.
+ EXPECT_EQ(1, web_contents->GetController().GetEntryCount());
+ NavigationEntry* entry =
+ web_contents->GetController().GetLastCommittedEntry();
+ ASSERT_TRUE(entry);
+ EXPECT_EQ(url, entry->GetURL());
+ }
+}
+
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
NavigatingToWebUIDoesNotUsePreWarmedProcess) {
GURL web_ui_url(std::string(kChromeUIScheme) + "://" +
@@ -1613,7 +1828,8 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
WebContents::CreateParams create_params(
base_web_contents->GetBrowserContext());
- create_params.initialize_renderer = true;
+ create_params.desired_renderer_state =
+ WebContents::CreateParams::kInitializeAndWarmupRendererProcess;
create_params.initial_size =
base_web_contents->GetContainerBounds().size();
std::unique_ptr<WebContents> web_contents(WebContents::Create(create_params));
@@ -1859,7 +2075,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url));
// alert
- wc->EnterFullscreenMode(url);
+ wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
std::string script = "alert('hi')";
test_delegate.WillWaitForDialog();
@@ -1868,7 +2084,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
// confirm
- wc->EnterFullscreenMode(url);
+ wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
script = "confirm('hi')";
test_delegate.WillWaitForDialog();
@@ -1877,7 +2093,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
// prompt
- wc->EnterFullscreenMode(url);
+ wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
script = "prompt('hi')";
test_delegate.WillWaitForDialog();
@@ -1886,7 +2102,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
// beforeunload
- wc->EnterFullscreenMode(url);
+ wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
// Disable the hang monitor (otherwise there will be a race between the
// beforeunload dialog and the beforeunload hang timer) and give the page a
@@ -1915,7 +2131,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(NavigateToURL(shell(), url));
// popup
- wc->EnterFullscreenMode(url);
+ wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
std::string script = "window.open('', '', 'width=200,height=100')";
test_delegate.WillWaitForNewContents();
@@ -1945,7 +2161,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
test_delegate.Wait();
// Put the main contents into fullscreen ...
- wc->EnterFullscreenMode(url);
+ wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
// ... and ensure that a call to window.focus() from it causes loss of
@@ -1984,7 +2200,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
class UpdateTargetURLWaiter : public WebContentsDelegate {
public:
- UpdateTargetURLWaiter(WebContents* web_contents) {
+ explicit UpdateTargetURLWaiter(WebContents* web_contents) {
web_contents->SetDelegate(this);
}
@@ -2034,126 +2250,171 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UpdateTargetURL) {
target_url_waiter.WaitForUpdatedTargetURL());
}
-// TODO(mmenke): Beef up testing of LoadState a little. In particular, check
-// LoadState itself, not just the host name, check upload progress, check the
-// param, and make sure RDH pushes the data to the browser process.
+namespace {
+
+class LoadStateWaiter : public WebContentsDelegate {
+ public:
+ explicit LoadStateWaiter(content::WebContents* contents)
+ : web_contents_(contents) {
+ contents->SetDelegate(this);
+ }
+ ~LoadStateWaiter() override = default;
+
+ // Waits until the WebContents changes its LoadStateHost to |host|.
+ void Wait(net::LoadState load_state, const base::string16& host) {
+ waiting_host_ = host;
+ waiting_state_ = load_state;
+ if (!LoadStateMatches(web_contents_)) {
+ base::RunLoop run_loop;
+ quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ DCHECK(LoadStateMatches(web_contents_));
+ }
+ }
+
+ // WebContentsDelegate:
+ void NavigationStateChanged(WebContents* source,
+ InvalidateTypes changed_flags) override {
+ if (!quit_closure_)
+ return;
+ if (!(changed_flags & INVALIDATE_TYPE_LOAD))
+ return;
+ if (LoadStateMatches(source))
+ std::move(quit_closure_).Run();
+ }
+
+ private:
+ bool LoadStateMatches(content::WebContents* contents) {
+ DCHECK(contents == web_contents_);
+ return waiting_host_ == contents->GetLoadStateHost() &&
+ waiting_state_ == contents->GetLoadState().state;
+ }
+ base::OnceClosure quit_closure_;
+ content::WebContents* web_contents_ = nullptr;
+ base::string16 waiting_host_;
+ net::LoadState waiting_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(LoadStateWaiter);
+};
+
+} // namespace
+
+// TODO(csharrison,mmenke): Beef up testing of LoadState a little. In
+// particular, check upload progress and check the LoadState param.
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UpdateLoadState) {
+ base::string16 a_host = url_formatter::IDNToUnicode("a.com");
+ base::string16 b_host = url_formatter::IDNToUnicode("b.com");
+ base::string16 paused_host = url_formatter::IDNToUnicode("paused.com");
+
// Controlled responses for image requests made in the test. They will
// alternate being the "most interesting" for the purposes of notifying the
// WebContents.
auto a_response =
std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), "/a_img");
- auto slow_response =
- std::make_unique<net::test_server::ControllableHttpResponse>(
- embedded_test_server(), "/slow_img");
- auto c_response =
+ auto b_response =
std::make_unique<net::test_server::ControllableHttpResponse>(
- embedded_test_server(), "/c_img");
- ASSERT_TRUE(embedded_test_server()->Start());
+ embedded_test_server(), "/b_img");
- // This is a hack to ensure that the resource scheduler has at least one
- // loading client for the duration of the test. Could alternatively delay some
- // subresources on the main target page, but it would require care to ensure
- // *all* other resources are completed before the test properly gets started.
- Shell* popup = CreateBrowser();
- const GURL kPopupUrl(embedded_test_server()->GetURL("/title1.html"));
- TestNavigationManager popup_delayer(popup->web_contents(), kPopupUrl);
- popup->LoadURL(kPopupUrl);
- EXPECT_TRUE(popup_delayer.WaitForResponse());
+ LoadStateWaiter waiter(shell()->web_contents());
+ ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL(
- "a.com", "/cross_site_iframe_factory.html?a(b(c))")));
+ "a.com", "/cross_site_iframe_factory.html?a(b)")));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
FrameTreeNode* a_frame = web_contents->GetFrameTree()->root();
- FrameTreeNode* slow_frame = a_frame->child_at(0);
- FrameTreeNode* c_frame = slow_frame->child_at(0);
+ FrameTreeNode* b_frame = a_frame->child_at(0);
// Start loading the respective resources in each frame.
auto load_resource = [](FrameTreeNode* frame, const std::string url) {
- std::string partial_script = R"(
+ const char kLoadResourceScript[] = R"(
var img = new Image();
img.src = '%s';
document.body.appendChild(img);
)";
- std::string script =
- base::StringPrintf(partial_script.c_str(), url.c_str());
+ std::string script = base::StringPrintf(kLoadResourceScript, url.c_str());
EXPECT_TRUE(ExecuteScript(frame, script));
};
- // Blocks until the img element in |frame| finishes.
- auto wait_for_img_finished = [](FrameTreeNode* frame) {
- bool finished = false;
- std::string script = R"(
- var img = document.getElementsByTagName('img')[0];
- if (img.complete)
- window.domAutomationController.send(true);
- else
- img.onload = img.onerror = window.domAutomationController.send(true);
- )";
- EXPECT_TRUE(ExecuteScriptAndExtractBool(frame, script.c_str(), &finished));
- };
-
- // Requests a load state notification from the RDHI and waits until the update
- // is posted back on the UI thread. Due to PostTaskAndReply, relies on
- // UpdateLoadInfo synchronously posting a task to the WebContents.
- auto update_load_state_and_wait = []() {
- base::RunLoop run_loop;
- BrowserThread::PostTaskAndReply(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ResourceDispatcherHostImpl::UpdateLoadInfo,
- base::Unretained(ResourceDispatcherHostImpl::Get())),
- run_loop.QuitClosure());
- run_loop.Run();
- };
-
// There should be no outgoing requests, so the load state should be empty.
- update_load_state_and_wait();
- EXPECT_TRUE(web_contents->GetLoadStateHost().empty());
- EXPECT_EQ(url_formatter::IDNToUnicode(kPopupUrl.host()),
- popup->web_contents()->GetLoadStateHost());
+ waiter.Wait(net::LOAD_STATE_IDLE, base::string16());
+
+ // The |frame_pauser| pauses the navigation after every step. It will only
+ // finish by calling WaitForNavigationFinished or ResumeNavigation.
+ GURL paused_url(embedded_test_server()->GetURL("paused.com", "/title1.html"));
+ TestNavigationManager frame_pauser(web_contents, paused_url);
+ const char kLoadFrameScript[] = R"(
+ var frame = document.createElement('iframe');
+ frame.src = "%s";
+ document.body.appendChild(frame);
+ )";
+ EXPECT_TRUE(ExecuteScript(
+ web_contents,
+ base::StringPrintf(kLoadFrameScript, paused_url.spec().c_str())));
+
+ // Wait for the response to be ready, but never finish it.
+ EXPECT_TRUE(frame_pauser.WaitForResponse());
+ EXPECT_FALSE(frame_pauser.was_successful());
+ waiter.Wait(net::LOAD_STATE_WAITING_FOR_DELEGATE, paused_host);
load_resource(a_frame, "/a_img");
a_response->WaitForRequest();
- update_load_state_and_wait();
- EXPECT_EQ(url_formatter::IDNToUnicode("a.com"),
- web_contents->GetLoadStateHost());
-
- // slow_img should never get past DNS resolution for the remainder of the
- // test. Ensure that a_img is further along (and therefore more interesting).
- load_resource(slow_frame, "http://slow.com/slow_img");
- update_load_state_and_wait();
- EXPECT_EQ(url_formatter::IDNToUnicode("a.com"),
- web_contents->GetLoadStateHost());
-
- // Finish a_img and start c_img, ensure it passes slow_img.
+ waiter.Wait(net::LOAD_STATE_WAITING_FOR_RESPONSE, a_host);
+
+ // Start loading b_img and have it pass a_img by providing one byte of data.
+ load_resource(b_frame, "/b_img");
+ b_response->WaitForRequest();
+
+ const char kPartialResponse[] = "HTTP/1.1 200 OK\r\n\r\nx";
+ b_response->Send(kPartialResponse);
+ waiter.Wait(net::LOAD_STATE_READING_RESPONSE, b_host);
+
+ // Finish b_img and expect that a_img is back to being most interesting.
+ b_response->Done();
+ waiter.Wait(net::LOAD_STATE_WAITING_FOR_RESPONSE, a_host);
+
+ // Advance and finish a_img.
+ a_response->Send(kPartialResponse);
+ waiter.Wait(net::LOAD_STATE_READING_RESPONSE, a_host);
a_response->Done();
- load_resource(c_frame, "/c_img");
- wait_for_img_finished(a_frame);
- c_response->WaitForRequest();
- update_load_state_and_wait();
- EXPECT_EQ(url_formatter::IDNToUnicode("c.com"),
- web_contents->GetLoadStateHost());
-
- // Finish c_img and ensure slow_img (the last outgoing request) is the most
- // interesting.
- c_response->Done();
- wait_for_img_finished(c_frame);
- update_load_state_and_wait();
- EXPECT_EQ(url_formatter::IDNToUnicode("slow.com"),
- web_contents->GetLoadStateHost());
+
+ // Now the only request in flight should be the delayed frame.
+ waiter.Wait(net::LOAD_STATE_WAITING_FOR_DELEGATE, paused_host);
+ frame_pauser.ResumeNavigation();
+ waiter.Wait(net::LOAD_STATE_IDLE, base::string16());
}
-// Disabled due to flakes on Linux. https://crbug.com/832191
-#if defined(OS_LINUX)
-#define MAYBE_PausePageScheduledTasks DISABLED_PausePageScheduledTasks
-#else
-#define MAYBE_PausePageScheduledTasks PausePageScheduledTasks
-#endif
-IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
- MAYBE_PausePageScheduledTasks) {
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NotifyPreferencesChanged) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHost* main_frame = web_contents->GetMainFrame();
+
+ // Navigate to a site with two iframes in different origins.
+ GURL url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b,c)");
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ auto* main_frame_rvh = main_frame->GetRenderViewHost();
+ auto* b_subframe_rvh = ChildFrameAt(main_frame, 0)->GetRenderViewHost();
+ auto* c_subframe_rvh = ChildFrameAt(main_frame, 1)->GetRenderViewHost();
+
+ NotifyPreferencesChangedTestContentBrowserClient new_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+ web_contents->NotifyPreferencesChanged();
+
+ // We should have updated the preferences for all three RenderViewHosts.
+ EXPECT_EQ(std::unordered_set<RenderViewHost*>(
+ {main_frame_rvh, b_subframe_rvh, c_subframe_rvh}),
+ new_client.override_webkit_prefs_rvh_set());
+
+ SetBrowserClientForTesting(old_client);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, PausePageScheduledTasks) {
EXPECT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("/pause_schedule_task.html");
@@ -2161,23 +2422,31 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
int text_length;
- EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
- shell(),
- "domAutomationController.send(document.getElementById('textfield')."
- "value.length)",
- &text_length));
- EXPECT_GT(text_length, 0);
+ while (true) {
+ EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
+ shell(),
+ "domAutomationController.send(document.getElementById('textfield')."
+ "value.length)",
+ &text_length));
+
+ // Wait until |text_length| exceed 0.
+ if (text_length > 0)
+ break;
+ }
// Suspend blink schedule tasks.
shell()->web_contents()->PausePageScheduledTasks(true);
- EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
- shell(),
- "domAutomationController.send(document.getElementById('textfield')."
- "value.length)",
- &text_length));
- EXPECT_GT(text_length, 0);
+ // Make the javascript work.
+ for (int i = 0; i < 10; i++) {
+ EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
+ shell(),
+ "domAutomationController.send(document.getElementById('textfield')."
+ "value.length)",
+ &text_length));
+ }
+ // Check if |next_text_length| is equal to |text_length|.
int next_text_length;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
@@ -2189,16 +2458,21 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// Resume the paused blink schedule tasks.
shell()->web_contents()->PausePageScheduledTasks(false);
- // We call a document.getElementById five times in order to give the
- // javascript time to run with DOM again.
- for (int i = 0; i < 5; i++) {
+ // Wait for an amount of time in order to give the javascript time to
+ // work again. If the javascript doesn't work again, the test will fail due to
+ // the time out.
+ while (true) {
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
"domAutomationController.send(document.getElementById('textfield')."
"value.length)",
&next_text_length));
+ if (next_text_length > text_length)
+ break;
}
+ // Check if |next_text_length| exceeds |text_length| because the blink
+ // schedule tasks have resumed.
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
"domAutomationController.send(document.getElementById('textfield')."
diff --git a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
index b88f6ee6a1c..9b07e24d464 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -56,6 +56,7 @@
#include "content/test/test_web_contents.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -318,8 +319,10 @@ class FakeFullscreenDelegate : public WebContentsDelegate {
FakeFullscreenDelegate() : fullscreened_contents_(nullptr) {}
~FakeFullscreenDelegate() override {}
- void EnterFullscreenModeForTab(WebContents* web_contents,
- const GURL& origin) override {
+ void EnterFullscreenModeForTab(
+ WebContents* web_contents,
+ const GURL& origin,
+ const blink::WebFullscreenOptions& options) override {
fullscreened_contents_ = web_contents;
}
@@ -836,9 +839,10 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredSitelessUrl) {
const GURL native_url("non-site-url://stuffandthings");
std::vector<std::unique_ptr<NavigationEntry>> entries;
std::unique_ptr<NavigationEntry> new_entry =
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
native_url, Referrer(), ui::PAGE_TRANSITION_LINK, false,
- std::string(), browser_context());
+ std::string(), browser_context(),
+ nullptr /* blob_url_loader_factory */);
entries.push_back(std::move(new_entry));
controller().Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -883,9 +887,10 @@ TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
const GURL regular_url("http://www.yahoo.com");
std::vector<std::unique_ptr<NavigationEntry>> entries;
std::unique_ptr<NavigationEntry> new_entry =
- NavigationControllerImpl::CreateNavigationEntry(
+ NavigationController::CreateNavigationEntry(
regular_url, Referrer(), ui::PAGE_TRANSITION_LINK, false,
- std::string(), browser_context());
+ std::string(), browser_context(),
+ nullptr /* blob_url_loader_factory */);
entries.push_back(std::move(new_entry));
controller().Restore(0, RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
ASSERT_EQ(0u, entries.size());
@@ -1487,8 +1492,8 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
- orig_rfh->OnMessageReceived(
- FrameHostMsg_ToggleFullscreen(orig_rfh->GetRoutingID(), true));
+ orig_rfh->OnMessageReceived(FrameHostMsg_EnterFullscreen(
+ orig_rfh->GetRoutingID(), blink::WebFullscreenOptions()));
EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
@@ -1543,8 +1548,8 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
for (int i = 0; i < 2; ++i) {
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
- orig_rfh->OnMessageReceived(
- FrameHostMsg_ToggleFullscreen(orig_rfh->GetRoutingID(), true));
+ orig_rfh->OnMessageReceived(FrameHostMsg_EnterFullscreen(
+ orig_rfh->GetRoutingID(), blink::WebFullscreenOptions()));
EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
@@ -1587,8 +1592,8 @@ TEST_F(WebContentsImplTest, CrashExitsFullscreen) {
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
EXPECT_FALSE(fake_delegate.IsFullscreenForTabOrPending(contents()));
- main_test_rfh()->OnMessageReceived(FrameHostMsg_ToggleFullscreen(
- main_test_rfh()->GetRoutingID(), true));
+ main_test_rfh()->OnMessageReceived(FrameHostMsg_EnterFullscreen(
+ main_test_rfh()->GetRoutingID(), blink::WebFullscreenOptions()));
EXPECT_TRUE(contents()->IsFullscreenForCurrentTab());
EXPECT_TRUE(fake_delegate.IsFullscreenForTabOrPending(contents()));
@@ -2580,7 +2585,7 @@ TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
// Create another NavigationController.
GURL url3("http://foo2");
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_contents->ExpectSetHistoryOffsetAndLength(1, 2);
@@ -2605,7 +2610,7 @@ TEST_F(WebContentsImplTest, CopyStateFromAndPruneTargetInterstitial) {
// Create another NavigationController.
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
NavigationControllerImpl& other_controller = other_contents->GetController();
// Navigate it to url2.
@@ -2655,7 +2660,7 @@ TEST_F(WebContentsImplTest, FilterURLs) {
// Create and navigate another WebContents.
std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
+ static_cast<TestWebContents*>(CreateTestWebContents().release()));
TestWebContentsObserver other_observer(other_contents.get());
other_contents->NavigateAndCommit(url_normalized);
@@ -2667,29 +2672,38 @@ TEST_F(WebContentsImplTest, FilterURLs) {
// Test that if a pending contents is deleted before it is shown, we don't
// crash.
TEST_F(WebContentsImplTest, PendingContentsDestroyed) {
- std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
- contents()->AddPendingContents(other_contents.get());
+ std::unique_ptr<WebContentsImpl> other_contents(
+ static_cast<WebContentsImpl*>(CreateTestWebContents().release()));
+ content::TestWebContents* raw_other_contents =
+ static_cast<TestWebContents*>(other_contents.get());
+ contents()->AddPendingContents(std::move(other_contents));
RenderWidgetHost* widget =
- other_contents->GetMainFrame()->GetRenderWidgetHost();
+ raw_other_contents->GetMainFrame()->GetRenderWidgetHost();
int process_id = widget->GetProcess()->GetID();
int widget_id = widget->GetRoutingID();
- other_contents.reset();
+
+ // TODO(erikchen): Fix ownership semantics of WebContents. Nothing should be
+ // able to delete it beside from the owner. https://crbug.com/832879.
+ delete raw_other_contents;
EXPECT_EQ(nullptr, contents()->GetCreatedWindow(process_id, widget_id));
}
TEST_F(WebContentsImplTest, PendingContentsShown) {
- std::unique_ptr<TestWebContents> other_contents(
- static_cast<TestWebContents*>(CreateTestWebContents()));
- contents()->AddPendingContents(other_contents.get());
+ std::unique_ptr<WebContents> other_contents(
+ static_cast<WebContents*>(CreateTestWebContents().release()));
+ content::WebContents* raw_other_contents = other_contents.get();
+ content::TestWebContents* test_web_contents =
+ static_cast<content::TestWebContents*>(other_contents.get());
+ contents()->AddPendingContents(std::move(other_contents));
+
RenderWidgetHost* widget =
- other_contents->GetMainFrame()->GetRenderWidgetHost();
+ test_web_contents->GetMainFrame()->GetRenderWidgetHost();
int process_id = widget->GetProcess()->GetID();
int widget_id = widget->GetRoutingID();
// The first call to GetCreatedWindow pops it off the pending list.
- EXPECT_EQ(other_contents.get(),
- contents()->GetCreatedWindow(process_id, widget_id));
+ EXPECT_EQ(raw_other_contents,
+ contents()->GetCreatedWindow(process_id, widget_id).get());
// A second call should return nullptr, verifying that it's been forgotten.
EXPECT_EQ(nullptr, contents()->GetCreatedWindow(process_id, widget_id));
}
@@ -3463,6 +3477,30 @@ TEST_F(WebContentsImplTest, MediaWakeLock) {
EXPECT_TRUE(has_video_wake_lock());
EXPECT_FALSE(has_audio_wake_lock());
+ viz::SurfaceId surface_id =
+ viz::SurfaceId(viz::FrameSinkId(1, 1),
+ viz::LocalSurfaceId(
+ 11, base::UnguessableToken::Deserialize(0x111111, 0)));
+
+ // Send the video in Picture-in-Picture mode, power blocker should still be
+ // on.
+ rfh->OnMessageReceived(
+ MediaPlayerDelegateHostMsg_OnPictureInPictureModeStarted(
+ 0, kPlayerAudioVideoId, surface_id, gfx::Size(), 0));
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
+
+ // Hiding the window should keep the power blocker.
+ contents()->WasHidden();
+ EXPECT_TRUE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
+
+ // Leaving Picture-in-Picture should reset the power blocker.
+ rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnPictureInPictureModeEnded(
+ 0, kPlayerAudioVideoId, 1 /* request_id */));
+ EXPECT_FALSE(has_video_wake_lock());
+ EXPECT_FALSE(has_audio_wake_lock());
+
// Crash the renderer.
main_test_rfh()->GetProcess()->SimulateCrash();
@@ -3506,9 +3544,23 @@ TEST_F(WebContentsImplTest, ThemeColorChangeDependingOnFirstVisiblePaint) {
EXPECT_EQ(SK_ColorGREEN, observer.last_theme_color());
}
-TEST_F(WebContentsImplTest, PictureInPictureMediaPlayerIdWasChanged) {
+class PictureInPictureDelegate : public WebContentsDelegate {
+ public:
+ PictureInPictureDelegate() = default;
+
+ MOCK_METHOD2(EnterPictureInPicture,
+ gfx::Size(const viz::SurfaceId&, const gfx::Size&));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PictureInPictureDelegate);
+};
+
+TEST_F(WebContentsImplTest, EnterPictureInPicture) {
const int kPlayerVideoOnlyId = 30; /* arbitrary and used for tests */
+ PictureInPictureDelegate delegate;
+ contents()->SetDelegate(&delegate);
+
MediaWebContentsObserver* observer =
contents()->media_web_contents_observer();
TestRenderFrameHost* rfh = main_test_rfh();
@@ -3518,18 +3570,27 @@ TEST_F(WebContentsImplTest, PictureInPictureMediaPlayerIdWasChanged) {
// set.
EXPECT_FALSE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
+ viz::SurfaceId surface_id =
+ viz::SurfaceId(viz::FrameSinkId(1, 1),
+ viz::LocalSurfaceId(
+ 11, base::UnguessableToken::Deserialize(0x111111, 0)));
+
+ EXPECT_CALL(delegate, EnterPictureInPicture(surface_id, gfx::Size(42, 42)));
+
rfh->OnMessageReceived(
- MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged(
- rfh->GetRoutingID(), kPlayerVideoOnlyId));
+ MediaPlayerDelegateHostMsg_OnPictureInPictureModeStarted(
+ rfh->GetRoutingID(), kPlayerVideoOnlyId, surface_id /* surface_id */,
+ gfx::Size(42, 42) /* natural_size */, 1 /* request_id */));
EXPECT_TRUE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
EXPECT_EQ(kPlayerVideoOnlyId,
observer->GetPictureInPictureVideoMediaPlayerId()->second);
- // Picture-in-Picture media player id should be reset when the media is
- // destroyed.
+ // Picture-in-Picture media player id should not be reset when the media is
+ // destroyed (e.g. video stops playing). This allows the Picture-in-Picture
+ // window to continue to control the media.
rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaDestroyed(
rfh->GetRoutingID(), kPlayerVideoOnlyId));
- EXPECT_FALSE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
+ EXPECT_TRUE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
}
TEST_F(WebContentsImplTest, ParseDownloadHeaders) {
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.cc b/chromium/content/browser/web_contents/web_contents_view_android.cc
index 4f8a55220b8..28c90658587 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -11,6 +11,7 @@
#include "cc/layers/layer.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/browser/android/content_feature_list.h"
+#include "content/browser/android/content_ui_event_handler.h"
#include "content/browser/android/gesture_listener_manager.h"
#include "content/browser/android/select_popup.h"
#include "content/browser/android/selection/selection_popup_controller.h"
@@ -29,6 +30,8 @@
#include "ui/base/clipboard/clipboard.h"
#include "ui/display/screen.h"
#include "ui/events/android/drag_event_android.h"
+#include "ui/events/android/gesture_event_android.h"
+#include "ui/events/android/key_event_android.h"
#include "ui/events/android/motion_event_android.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/image/image_skia.h"
@@ -103,14 +106,21 @@ WebContentsViewAndroid::WebContentsViewAndroid(
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
- view_(this, ui::ViewAndroid::LayoutType::NORMAL),
+ view_(ui::ViewAndroid::LayoutType::NORMAL),
synchronous_compositor_client_(nullptr) {
view_.SetLayer(cc::Layer::Create());
+ view_.set_event_handler(this);
}
WebContentsViewAndroid::~WebContentsViewAndroid() {
if (view_.GetLayer())
view_.GetLayer()->RemoveFromParent();
+ view_.set_event_handler(nullptr);
+}
+
+void WebContentsViewAndroid::SetContentUiEventHandler(
+ std::unique_ptr<ContentUiEventHandler> handler) {
+ content_ui_event_handler_ = std::move(handler);
}
void WebContentsViewAndroid::SetSelectPopup(
@@ -507,11 +517,43 @@ bool WebContentsViewAndroid::OnMouseEvent(const ui::MotionEventAndroid& event) {
return manager && manager->OnHoverEvent(event);
}
+bool WebContentsViewAndroid::OnGenericMotionEvent(
+ const ui::MotionEventAndroid& event) {
+ if (content_ui_event_handler_)
+ return content_ui_event_handler_->OnGenericMotionEvent(event);
+ return false;
+}
+
+bool WebContentsViewAndroid::OnKeyUp(const ui::KeyEventAndroid& event) {
+ if (content_ui_event_handler_)
+ return content_ui_event_handler_->OnKeyUp(event);
+ return false;
+}
+
+bool WebContentsViewAndroid::DispatchKeyEvent(
+ const ui::KeyEventAndroid& event) {
+ if (content_ui_event_handler_)
+ return content_ui_event_handler_->DispatchKeyEvent(event);
+ return false;
+}
+
+bool WebContentsViewAndroid::ScrollBy(float delta_x, float delta_y) {
+ if (content_ui_event_handler_)
+ content_ui_event_handler_->ScrollBy(delta_x, delta_y);
+ return false;
+}
+
+bool WebContentsViewAndroid::ScrollTo(float x, float y) {
+ if (content_ui_event_handler_)
+ content_ui_event_handler_->ScrollTo(x, y);
+ return false;
+}
+
void WebContentsViewAndroid::OnSizeChanged() {
auto* rwhv = ::content::GetRenderWidgetHostViewAndroid(web_contents_);
if (rwhv) {
web_contents_->SendScreenRects();
- rwhv->WasResized();
+ rwhv->SynchronizeVisualProperties();
}
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.h b/chromium/content/browser/web_contents/web_contents_view_android.h
index 9c21662393b..3b6ab05eeac 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -15,10 +15,12 @@
#include "content/public/common/drop_data.h"
#include "ui/android/overscroll_refresh.h"
#include "ui/android/view_android.h"
-#include "ui/android/view_client.h"
+#include "ui/android/view_android_observer.h"
+#include "ui/events/android/event_handler_android.h"
#include "ui/gfx/geometry/rect_f.h"
namespace content {
+class ContentUiEventHandler;
class RenderWidgetHostViewAndroid;
class SelectPopup;
class SelectionPopupController;
@@ -28,12 +30,14 @@ class WebContentsImpl;
// Android-specific implementation of the WebContentsView.
class WebContentsViewAndroid : public WebContentsView,
public RenderViewHostDelegateView,
- public ui::ViewClient {
+ public ui::EventHandlerAndroid {
public:
WebContentsViewAndroid(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate);
~WebContentsViewAndroid() override;
+ void SetContentUiEventHandler(std::unique_ptr<ContentUiEventHandler> handler);
+
// Sets the object that show/hide popup view for <select> tag.
void SetSelectPopup(std::unique_ptr<SelectPopup> select_popup);
@@ -106,13 +110,23 @@ class WebContentsViewAndroid : public WebContentsView,
int GetBottomControlsHeight() const override;
bool DoBrowserControlsShrinkBlinkSize() const override;
- // ui::ViewClient implementation.
+ // ui::EventHandlerAndroid implementation.
bool OnTouchEvent(const ui::MotionEventAndroid& event) override;
bool OnMouseEvent(const ui::MotionEventAndroid& event) override;
bool OnDragEvent(const ui::DragEventAndroid& event) override;
+ bool OnGenericMotionEvent(const ui::MotionEventAndroid& event) override;
+ bool OnKeyUp(const ui::KeyEventAndroid& event) override;
+ bool DispatchKeyEvent(const ui::KeyEventAndroid& event) override;
+ bool ScrollBy(float delta_x, float delta_y) override;
+ bool ScrollTo(float x, float y) override;
void OnSizeChanged() override;
void OnPhysicalBackingSizeChanged() override;
+ void set_device_orientation(int orientation) {
+ device_orientation_ = orientation;
+ }
+ int device_orientation() { return device_orientation_; }
+
private:
void OnDragEntered(const std::vector<DropData::Metadata>& metadata,
const gfx::PointF& location,
@@ -129,6 +143,9 @@ class WebContentsViewAndroid : public WebContentsView,
// The WebContents whose contents we display.
WebContentsImpl* web_contents_;
+ // Handles UI events in Java layer when necessary.
+ std::unique_ptr<ContentUiEventHandler> content_ui_event_handler_;
+
// Handles "overscroll to refresh" events
std::unique_ptr<ui::OverscrollRefreshHandler> overscroll_refresh_handler_;
@@ -143,6 +160,8 @@ class WebContentsViewAndroid : public WebContentsView,
SelectionPopupController* selection_popup_controller_ = nullptr;
+ int device_orientation_ = 0;
+
// Show/hide popup UI for <select> tag.
std::unique_ptr<SelectPopup> select_popup_;
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.cc b/chromium/content/browser/web_contents/web_contents_view_aura.cc
index 3aea2d29dc4..984fa41d064 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -11,7 +11,7 @@
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
@@ -932,8 +932,7 @@ void WebContentsViewAura::StartDragging(
int result_op = 0;
{
gfx::NativeView content_native_view = GetContentNativeView();
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
+ base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
result_op = aura::client::GetDragDropClient(root_window)
->StartDragAndDrop(data,
root_window,
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 35a9c560d09..dbc35b6c764 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -122,56 +122,6 @@ class ScreenshotTracker : public NavigationEntryScreenshotManager {
DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker);
};
-class InputEventMessageFilterWaitsForAcks : public BrowserMessageFilter {
- public:
- InputEventMessageFilterWaitsForAcks()
- : BrowserMessageFilter(InputMsgStart),
- type_(blink::WebInputEvent::kUndefined),
- state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
-
- void WaitForAck(blink::WebInputEvent::Type type) {
- base::RunLoop run_loop;
- base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
- base::AutoReset<blink::WebInputEvent::Type> reset_type(&type_, type);
- run_loop.Run();
- }
-
- InputEventAckState last_ack_state() const { return state_; }
-
- protected:
- ~InputEventMessageFilterWaitsForAcks() override {}
-
- private:
- void ReceivedEventAck(blink::WebInputEvent::Type type,
- InputEventAckState state) {
- if (type_ == type) {
- state_ = state;
- quit_.Run();
- }
- }
-
- // BrowserMessageFilter:
- bool OnMessageReceived(const IPC::Message& message) override {
- if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
- InputHostMsg_HandleInputEvent_ACK::Param params;
- InputHostMsg_HandleInputEvent_ACK::Read(&message, &params);
- blink::WebInputEvent::Type type = std::get<0>(params).type;
- InputEventAckState ack = std::get<0>(params).state;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&InputEventMessageFilterWaitsForAcks::ReceivedEventAck,
- this, type, ack));
- }
- return false;
- }
-
- base::Closure quit_;
- blink::WebInputEvent::Type type_;
- InputEventAckState state_;
-
- DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilterWaitsForAcks);
-};
-
class WebContentsViewAuraTest : public ContentBrowserTest {
public:
WebContentsViewAuraTest() : screenshot_manager_(nullptr) {}
@@ -338,12 +288,8 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
GetRenderViewHost()->GetWidget()->GetView());
}
- InputEventMessageFilterWaitsForAcks* filter() {
- return filter_.get();
- }
-
void WaitAFrame() {
- while (!GetRenderWidgetHost()->ScheduleComposite())
+ while (!GetRenderWidgetHost()->RequestRepaintForTesting())
GiveItSomeTime();
frame_observer_->WaitForAnyFrameSubmission();
}
@@ -356,11 +302,6 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
screenshot_manager_->SetScreenshotInterval(interval_ms);
}
- void AddInputEventMessageFilter() {
- filter_ = new InputEventMessageFilterWaitsForAcks();
- GetRenderWidgetHost()->GetProcess()->AddFilter(filter_.get());
- }
-
// ContentBrowserTest:
void PostRunTestOnMainThread() override {
// Delete this before the WebContents is destroyed.
@@ -370,7 +311,6 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
private:
ScreenshotTracker* screenshot_manager_;
- scoped_refptr<InputEventMessageFilterWaitsForAcks> filter_;
std::unique_ptr<RenderFrameSubmissionObserver> frame_observer_;
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
@@ -965,8 +905,6 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
MAYBE_OverscrollNavigationTouchThrottling) {
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
- AddInputEventMessageFilter();
-
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
aura::Window* content = web_contents->GetContentNativeView();
@@ -984,24 +922,35 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
ExecuteSyncJSFunction(web_contents->GetMainFrame(),
"reset_touchmove_count()");
}
+ InputEventAckWaiter touch_start_waiter(
+ GetRenderWidgetHost(),
+ base::BindRepeating([](content::InputEventAckSource,
+ content::InputEventAckState state,
+ const blink::WebInputEvent& event) {
+ return event.GetType() == blink::WebGestureEvent::kTouchStart &&
+ state == content::INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+ }));
// Send touch press.
SyntheticWebTouchEvent touch;
touch.PressPoint(bounds.x() + 2, bounds.y() + 10);
GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
ui::LatencyInfo());
- filter()->WaitForAck(blink::WebInputEvent::kTouchStart);
+ touch_start_waiter.Wait();
WaitAFrame();
- // Assert on the ack, because we'll end up waiting for acks that will never
- // come if this is not true.
- ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
-
// Send first touch move, and then a scroll begin.
touch.MovePoint(0, bounds.x() + 20 + 1 * dx, bounds.y() + 100);
+ InputEventAckWaiter touch_move_waiter(
+ GetRenderWidgetHost(),
+ base::BindRepeating([](content::InputEventAckSource,
+ content::InputEventAckState state,
+ const blink::WebInputEvent& event) {
+ return event.GetType() == blink::WebGestureEvent::kTouchMove &&
+ state == content::INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+ }));
GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
ui::LatencyInfo());
- filter()->WaitForAck(blink::WebInputEvent::kTouchMove);
- ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
+ touch_move_waiter.Wait();
blink::WebGestureEvent scroll_begin =
SyntheticWebGestureEventBuilder::BuildScrollBegin(
@@ -1034,10 +983,9 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
ui::LatencyInfo());
WaitAFrame();
- blink::WebGestureEvent scroll_end(
- blink::WebInputEvent::kGestureScrollEnd,
- blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebGestureEvent scroll_end(blink::WebInputEvent::kGestureScrollEnd,
+ blink::WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
scroll_end, ui::LatencyInfo());
WaitAFrame();
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.h b/chromium/content/browser/web_contents/web_contents_view_mac.h
index 968c5157ab4..4640550b848 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -35,6 +35,10 @@ namespace gfx {
class Vector2d;
}
+namespace ui {
+class Layer;
+}
+
CONTENT_EXPORT
@interface WebContentsViewCocoa : BaseView {
@private
@@ -128,6 +132,8 @@ class WebContentsViewMac : public WebContentsView,
// CloseTabAfterEventTracking() implementation.
void CloseTab();
+ void SetParentUiLayer(ui::Layer* parent_ui_layer);
+
WebContentsImpl* web_contents() { return web_contents_; }
WebContentsViewDelegate* delegate() { return delegate_.get(); }
@@ -156,6 +162,8 @@ class WebContentsViewMac : public WebContentsView,
// Whether to allow other views.
bool allow_other_views_;
+ ui::Layer* parent_ui_layer_ = nullptr;
+
std::unique_ptr<PopupMenuHelper> popup_menu_helper_;
DISALLOW_COPY_AND_ASSIGN(WebContentsViewMac);
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.mm b/chromium/content/browser/web_contents/web_contents_view_mac.mm
index 6a9ee15776b..00b2d2a729d 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -11,7 +11,7 @@
#import "base/mac/mac_util.h"
#import "base/mac/scoped_sending_event.h"
#include "base/mac/sdk_forward_declarations.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#import "base/message_loop/message_pump_mac.h"
#include "content/browser/frame_host/popup_menu_helper_mac.h"
#include "content/browser/renderer_host/display_util.h"
@@ -28,6 +28,7 @@
#include "skia/ext/skia_utils_mac.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "ui/base/clipboard/custom_data_helper.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/display/screen.h"
#include "ui/gfx/image/image_skia_util_mac.h"
@@ -164,8 +165,7 @@ void WebContentsViewMac::StartDragging(
// The drag invokes a nested event loop, arrange to continue
// processing events.
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
+ base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
NSDragOperation mask = static_cast<NSDragOperation>(allowed_operations);
NSPoint offset = NSPointFromCGPoint(
gfx::PointAtOffsetFromOrigin(image_offset).ToCGPoint());
@@ -318,9 +318,11 @@ void WebContentsViewMac::OnMenuClosed() {
}
gfx::Rect WebContentsViewMac::GetViewBounds() const {
- // This method is not currently used on mac.
- NOTIMPLEMENTED();
- return gfx::Rect();
+ NSRect window_bounds =
+ [cocoa_view_ convertRect:[cocoa_view_ bounds] toView:nil];
+ window_bounds.origin = ui::ConvertPointFromWindowToScreen(
+ [cocoa_view_ window], window_bounds.origin);
+ return gfx::ScreenRectFromNSRect(window_bounds);
}
void WebContentsViewMac::SetAllowOtherViews(bool allow) {
@@ -371,6 +373,8 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
view->SetDelegate(rw_delegate.get());
}
view->SetAllowPauseForResizeOrRepaint(!allow_other_views_);
+ if (parent_ui_layer_)
+ view->SetParentUiLayer(parent_ui_layer_);
// Fancy layout comes later; for now just make it our size and resize it
// with us. In case there are other siblings of the content area, we want
@@ -444,6 +448,14 @@ void WebContentsViewMac::CloseTab() {
web_contents_->Close(web_contents_->GetRenderViewHost());
}
+void WebContentsViewMac::SetParentUiLayer(ui::Layer* parent_ui_layer) {
+ parent_ui_layer_ = parent_ui_layer;
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ web_contents_->GetRenderWidgetHostView());
+ if (view)
+ view->SetParentUiLayer(parent_ui_layer);
+}
+
} // namespace content
@implementation WebContentsViewCocoa
@@ -658,6 +670,11 @@ void WebContentsViewMac::CloseTab() {
FocusThroughTabTraversal(direction == NSSelectingPrevious);
}
+- (void)cr_setParentUiLayer:(ui::Layer*)parentUiLayer {
+ if (webContentsView_)
+ webContentsView_->SetParentUiLayer(parentUiLayer);
+}
+
- (void)updateWebContentsVisibility {
WebContentsImpl* webContents = [self webContents];
if (!webContents || webContents->IsBeingDestroyed())
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.mm b/chromium/content/browser/web_contents/web_drag_source_mac.mm
index d8dd5f43252..4ef9fcdda1c 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -145,12 +145,8 @@ void PromiseWriterHelper(const DropData& drop_data,
// If NSURL creation failed, check for a badly-escaped JavaScript URL.
// Strip out any existing escapes and then re-escape uniformly.
if (!url && dropData_->url.SchemeIs(url::kJavaScriptScheme)) {
- net::UnescapeRule::Type unescapeRules =
- net::UnescapeRule::SPACES | net::UnescapeRule::PATH_SEPARATORS |
- net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
- net::UnescapeRule::SPOOFING_AND_CONTROL_CHARS;
std::string unescapedUrlString =
- net::UnescapeURLComponent(dropData_->url.spec(), unescapeRules);
+ net::UnescapeBinaryURLComponent(dropData_->url.spec());
std::string escapedUrlString =
net::EscapeUrlEncodedData(unescapedUrlString, false);
url = [NSURL URLWithString:SysUTF8ToNSString(escapedUrlString)];
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
index 30b0a30eb6b..083d6c6fa95 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -11,6 +11,7 @@
#include "base/trace_event/trace_event.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/common/resource_type.h"
@@ -69,15 +70,16 @@ SignedExchangeCertFetcher::CreateAndStart(
const GURL& cert_url,
url::Origin request_initiator,
bool force_fetch,
+ SignedExchangeVersion version,
CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+ SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeCertFetcher::CreateAndStart");
std::unique_ptr<SignedExchangeCertFetcher> cert_fetcher(
new SignedExchangeCertFetcher(
std::move(shared_url_loader_factory), std::move(throttles), cert_url,
- std::move(request_initiator), force_fetch, std::move(callback),
- std::move(error_message_callback)));
+ std::move(request_initiator), force_fetch, version,
+ std::move(callback), devtools_proxy));
cert_fetcher->Start();
return cert_fetcher;
}
@@ -88,13 +90,15 @@ SignedExchangeCertFetcher::SignedExchangeCertFetcher(
const GURL& cert_url,
url::Origin request_initiator,
bool force_fetch,
+ SignedExchangeVersion version,
CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback)
+ SignedExchangeDevToolsProxy* devtools_proxy)
: shared_url_loader_factory_(std::move(shared_url_loader_factory)),
throttles_(std::move(throttles)),
resource_request_(std::make_unique<network::ResourceRequest>()),
+ version_(version),
callback_(std::move(callback)),
- error_message_callback_(std::move(error_message_callback)) {
+ devtools_proxy_(devtools_proxy) {
// TODO(https://crbug.com/803774): Revisit more ResourceRequest flags.
resource_request_->url = cert_url;
resource_request_->request_initiator = std::move(request_initiator);
@@ -109,11 +113,20 @@ SignedExchangeCertFetcher::SignedExchangeCertFetcher(
net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_CACHE;
}
resource_request_->render_frame_id = MSG_ROUTING_NONE;
+ if (devtools_proxy_) {
+ cert_request_id_ = base::UnguessableToken::Create();
+ resource_request_->enable_load_timing = true;
+ }
}
SignedExchangeCertFetcher::~SignedExchangeCertFetcher() = default;
void SignedExchangeCertFetcher::Start() {
+ if (devtools_proxy_) {
+ DCHECK(cert_request_id_);
+ devtools_proxy_->CertificateRequestSent(*cert_request_id_,
+ *resource_request_);
+ }
url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
std::move(shared_url_loader_factory_), std::move(throttles_),
0 /* routing_id */,
@@ -130,6 +143,7 @@ void SignedExchangeCertFetcher::Abort() {
body_.reset();
handle_watcher_ = nullptr;
body_string_.clear();
+ devtools_proxy_ = nullptr;
std::move(callback_).Run(nullptr);
}
@@ -143,10 +157,10 @@ void SignedExchangeCertFetcher::OnHandleReady(MojoResult result) {
if (rv == MOJO_RESULT_OK) {
if (body_string_.size() + num_bytes > g_max_cert_size_for_signed_exchange) {
body_->EndReadData(num_bytes);
- Abort();
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeCertFetcher::OnHandleReady", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_, "SignedExchangeCertFetcher::OnHandleReady",
"The response body size of certificate message exceeds the limit.");
+ Abort();
return;
}
body_string_.append(static_cast<const char*>(buffer), num_bytes);
@@ -169,13 +183,15 @@ void SignedExchangeCertFetcher::OnDataComplete() {
handle_watcher_ = nullptr;
std::unique_ptr<SignedExchangeCertificateChain> cert_chain =
- SignedExchangeCertificateChain::Parse(body_string_);
+ SignedExchangeCertificateChain::Parse(
+ version_, base::as_bytes(base::make_span(body_string_)),
+ devtools_proxy_);
body_string_.clear();
if (!cert_chain) {
- std::move(callback_).Run(nullptr);
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeCertFetcher::OnDataComplete", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_, "SignedExchangeCertFetcher::OnDataComplete",
"Failed to get certificate chain from message.");
+ std::move(callback_).Run(nullptr);
return;
}
std::move(callback_).Run(std::move(cert_chain));
@@ -187,26 +203,29 @@ void SignedExchangeCertFetcher::OnDataComplete() {
void SignedExchangeCertFetcher::OnReceiveResponse(
const network::ResourceResponseHead& head,
network::mojom::DownloadedTempFilePtr downloaded_file) {
+ if (devtools_proxy_) {
+ DCHECK(cert_request_id_);
+ devtools_proxy_->CertificateResponseReceived(*cert_request_id_,
+ resource_request_->url, head);
+ }
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeCertFetcher::OnReceiveResponse");
if (head.headers->response_code() != net::HTTP_OK) {
- Abort();
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeCertFetcher::OnReceiveResponse", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_, "SignedExchangeCertFetcher::OnReceiveResponse",
base::StringPrintf("Invalid reponse code: %d",
head.headers->response_code()));
+ Abort();
return;
}
if (head.content_length > 0) {
if (base::checked_cast<size_t>(head.content_length) >
g_max_cert_size_for_signed_exchange) {
- Abort();
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeCertFetcher::OnReceiveResponse",
- error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_, "SignedExchangeCertFetcher::OnReceiveResponse",
base::StringPrintf("Invalid content length: %" PRIu64,
head.content_length));
-
+ Abort();
return;
}
body_string_.reserve(head.content_length);
@@ -267,6 +286,10 @@ void SignedExchangeCertFetcher::OnComplete(
const network::URLLoaderCompletionStatus& status) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeCertFetcher::OnComplete");
+ if (devtools_proxy_) {
+ DCHECK(cert_request_id_);
+ devtools_proxy_->CertificateRequestCompleted(*cert_request_id_, status);
+ }
if (!handle_watcher_)
Abort();
}
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
index 55f77debb9d..23de0610fb8 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher.h
@@ -12,8 +12,8 @@
#include "base/callback_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/content_export.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "url/origin.h"
@@ -28,6 +28,7 @@ class SimpleWatcher;
namespace content {
+class SignedExchangeDevToolsProxy;
class ThrottlingURLLoader;
class URLLoaderThrottle;
@@ -51,8 +52,9 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
const GURL& cert_url,
url::Origin request_initiator,
bool force_fetch,
+ SignedExchangeVersion version,
CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback);
+ SignedExchangeDevToolsProxy* devtools_proxy);
~SignedExchangeCertFetcher() override;
@@ -72,8 +74,9 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
const GURL& cert_url,
url::Origin request_initiator,
bool force_fetch,
+ SignedExchangeVersion version,
CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback);
+ SignedExchangeDevToolsProxy* devtools_proxy);
void Start();
void Abort();
void OnHandleReady(MojoResult result);
@@ -98,14 +101,18 @@ class CONTENT_EXPORT SignedExchangeCertFetcher
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles_;
std::unique_ptr<network::ResourceRequest> resource_request_;
+ const SignedExchangeVersion version_;
CertificateCallback callback_;
- signed_exchange_utils::LogCallback error_message_callback_;
std::unique_ptr<ThrottlingURLLoader> url_loader_;
mojo::ScopedDataPipeConsumerHandle body_;
std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
std::string body_string_;
+ // This is owned by SignedExchangeHandler which is the owner of |this|.
+ SignedExchangeDevToolsProxy* devtools_proxy_;
+ base::Optional<base::UnguessableToken> cert_request_id_;
+
DISALLOW_COPY_AND_ASSIGN(SignedExchangeCertFetcher);
};
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
index 40d63e33e51..20234806225 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
@@ -25,9 +25,9 @@ class SignedExchangeCertFetcherFactoryImpl
std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
+ SignedExchangeVersion version,
SignedExchangeCertFetcher::CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback)
- override;
+ SignedExchangeDevToolsProxy* devtools_proxy) override;
private:
url::Origin request_initiator_;
@@ -39,16 +39,17 @@ std::unique_ptr<SignedExchangeCertFetcher>
SignedExchangeCertFetcherFactoryImpl::CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
+ SignedExchangeVersion version,
SignedExchangeCertFetcher::CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+ SignedExchangeDevToolsProxy* devtools_proxy) {
DCHECK(url_loader_factory_);
DCHECK(url_loader_throttles_getter_);
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles =
std::move(url_loader_throttles_getter_).Run();
return SignedExchangeCertFetcher::CreateAndStart(
std::move(url_loader_factory_), std::move(throttles), cert_url,
- std::move(request_initiator_), force_fetch, std::move(callback),
- std::move(error_message_callback));
+ std::move(request_initiator_), force_fetch, version, std::move(callback),
+ devtools_proxy);
}
// static
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
index 4567bf09a74..dc01c1c3bd2 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
@@ -10,7 +10,6 @@
#include "base/callback_forward.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/content_export.h"
#include "url/origin.h"
@@ -20,6 +19,7 @@ class SharedURLLoaderFactory;
namespace content {
+class SignedExchangeDevToolsProxy;
class SignedExchangeCertFetcher;
class URLLoaderThrottle;
@@ -32,8 +32,9 @@ class CONTENT_EXPORT SignedExchangeCertFetcherFactory {
virtual std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
+ SignedExchangeVersion version,
SignedExchangeCertFetcher::CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback) = 0;
+ SignedExchangeDevToolsProxy* devtools_proxy) = 0;
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
diff --git a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
index ea7c1eba82e..19e3ed513c7 100644
--- a/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
@@ -9,16 +9,15 @@
#include "base/strings/string_piece.h"
#include "base/test/scoped_task_environment.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/url_loader_throttle.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/base/load_flags.h"
#include "net/cert/x509_util.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -76,7 +75,8 @@ class MockURLLoader final : public network::mojom::URLLoader {
: binding_(this, std::move(url_loader_request)) {}
~MockURLLoader() override = default;
- MOCK_METHOD0(FollowRedirect, void());
+ MOCK_METHOD1(FollowRedirect,
+ void(const base::Optional<net::HttpRequestHeaders>&));
MOCK_METHOD0(ProceedWithResponse, void());
MOCK_METHOD2(SetPriority,
void(net::RequestPriority priority,
@@ -208,10 +208,11 @@ class SignedExchangeCertFetcherTest : public testing::Test {
base::Unretained(&cert_result_));
return SignedExchangeCertFetcher::CreateAndStart(
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&mock_loader_factory_),
std::move(throttles_), url_, request_initiator_, force_fetch,
- std::move(callback), signed_exchange_utils::LogCallback());
+ SignedExchangeVersion::kB0, std::move(callback),
+ nullptr /* devtools_proxy */);
}
void CallOnReceiveResponse() {
@@ -317,7 +318,7 @@ TEST_F(SignedExchangeCertFetcherTest, ForceFetchAndFail) {
mock_loader_factory_.url_request()->load_flags);
mock_loader_factory_.client_ptr()->OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ network::URLLoaderCompletionStatus(net::ERR_INVALID_SIGNED_EXCHANGE));
RunUntilIdle();
EXPECT_TRUE(callback_called_);
@@ -534,7 +535,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRequest) {
CreateFetcherAndStart(false /* force_fetch */);
RunUntilIdle();
- throttle->delegate()->CancelWithError(net::ERR_FAILED);
+ throttle->delegate()->CancelWithError(net::ERR_INVALID_SIGNED_EXCHANGE);
RunUntilIdle();
@@ -561,7 +562,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRedirect) {
EXPECT_TRUE(throttle->will_redirect_request_called());
- throttle->delegate()->CancelWithError(net::ERR_FAILED);
+ throttle->delegate()->CancelWithError(net::ERR_INVALID_SIGNED_EXCHANGE);
RunUntilIdle();
EXPECT_TRUE(callback_called_);
@@ -593,7 +594,7 @@ TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnResponse) {
EXPECT_FALSE(callback_called_);
- throttle->delegate()->CancelWithError(net::ERR_FAILED);
+ throttle->delegate()->CancelWithError(net::ERR_INVALID_SIGNED_EXCHANGE);
RunUntilIdle();
EXPECT_TRUE(callback_called_);
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
index ea587d6979d..d94125eae13 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.cc
@@ -5,9 +5,13 @@
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
#include "base/command_line.h"
+#include "base/format_macros.h"
#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
+#include "components/cbor/cbor_reader.h"
#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/common/content_switches.h"
#include "net/cert/x509_certificate.h"
@@ -15,54 +19,225 @@ namespace content {
namespace {
-bool ConsumeByte(base::StringPiece* data, uint8_t* out) {
+bool ConsumeByte(base::span<const uint8_t>* data, uint8_t* out) {
if (data->empty())
return false;
*out = (*data)[0];
- data->remove_prefix(1);
+ *data = data->subspan(1);
return true;
}
-bool Consume2Bytes(base::StringPiece* data, uint16_t* out) {
+bool Consume2Bytes(base::span<const uint8_t>* data, uint16_t* out) {
if (data->size() < 2)
return false;
- *out = (static_cast<uint8_t>((*data)[0]) << 8) |
- static_cast<uint8_t>((*data)[1]);
- data->remove_prefix(2);
+ *out = ((*data)[0] << 8) | (*data)[1];
+ *data = data->subspan(2);
return true;
}
-bool Consume3Bytes(base::StringPiece* data, uint32_t* out) {
+bool Consume3Bytes(base::span<const uint8_t>* data, uint32_t* out) {
if (data->size() < 3)
return false;
- *out = (static_cast<uint8_t>((*data)[0]) << 16) |
- (static_cast<uint8_t>((*data)[1]) << 8) |
- static_cast<uint8_t>((*data)[2]);
- data->remove_prefix(3);
+ *out = ((*data)[0] << 16) | ((*data)[1] << 8) | (*data)[2];
+ *data = data->subspan(3);
return true;
}
-} // namespace
-
-// static
-std::unique_ptr<SignedExchangeCertificateChain>
-SignedExchangeCertificateChain::Parse(base::StringPiece cert_response_body) {
+std::unique_ptr<SignedExchangeCertificateChain> ParseB0(
+ base::span<const uint8_t> message,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
+ TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertificateChain::ParseB0");
base::Optional<std::vector<base::StringPiece>> der_certs =
- GetCertChainFromMessage(cert_response_body);
- if (!der_certs)
+ SignedExchangeCertificateChain::GetCertChainFromMessage(message);
+ if (!der_certs) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB0",
+ "Failed to parse the response as a TLS 1.3 Certificate message.");
return nullptr;
+ }
scoped_refptr<net::X509Certificate> cert =
net::X509Certificate::CreateFromDERCertChain(*der_certs);
- if (!cert)
+ if (!cert) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB0",
+ "X509Certificate::CreateFromDERCertChain failed.");
+ return nullptr;
+ }
+
+ TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertificateChain::ParseB1");
+ // The V0 certificate format doesn't support OCSP nor SCT.
+ return base::WrapUnique(
+ new SignedExchangeCertificateChain(cert, "" /* ocsp */, "" /* sct */));
+}
+
+// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
+std::unique_ptr<SignedExchangeCertificateChain> ParseB1(
+ base::span<const uint8_t> message,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
+ TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertificateChain::ParseB1");
+
+ cbor::CBORReader::DecoderError error;
+ base::Optional<cbor::CBORValue> value =
+ cbor::CBORReader::Read(message, &error);
+ if (!value.has_value()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ base::StringPrintf("Failed to decode CBORValue. CBOR error: %s",
+ cbor::CBORReader::ErrorCodeToString(error)));
+ return nullptr;
+ }
+ if (!value->is_array()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ base::StringPrintf(
+ "Expected top-level CBORValue to be an array. Actual type: %d",
+ static_cast<int>(value->type())));
+ return nullptr;
+ }
+
+ const cbor::CBORValue::ArrayValue& top_level_array = value->GetArray();
+ // Expect at least 2 elements (magic string and main certificate).
+ if (top_level_array.size() < 2) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ base::StringPrintf(
+ "Expected top-level array to have at least 2 elements."
+ "Actual element count: %" PRIuS,
+ top_level_array.size()));
+ return nullptr;
+ }
+ if (!top_level_array[0].is_string() ||
+ top_level_array[0].GetString() != kCertChainCborMagic) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ "First element of cert chain CBOR does not match the magic string.");
+ return nullptr;
+ }
+
+ std::vector<base::StringPiece> der_certs;
+ der_certs.reserve(top_level_array.size() - 1);
+ std::string ocsp;
+ std::string sct;
+
+ for (size_t i = 1; i < top_level_array.size(); i++) {
+ if (!top_level_array[i].is_map()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ base::StringPrintf(
+ "Expected certificate map, got non-map type at index %zu."
+ " Actual type: %d",
+ i, static_cast<int>(top_level_array[i].type())));
+ return nullptr;
+ }
+ const cbor::CBORValue::MapValue& cert_map = top_level_array[i].GetMap();
+
+ // Step 1. Each cert value MUST be a DER-encoded X.509v3 certificate
+ // ([RFC5280]). Other key/value pairs in the same array item define
+ // properties of this certificate. [spec text]
+ auto cert_iter = cert_map.find(cbor::CBORValue(kCertKey));
+ if (cert_iter == cert_map.end() || !cert_iter->second.is_bytestring()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ base::StringPrintf(
+ "cert is not found or not a bytestring, at index %zu.", i));
+ return nullptr;
+ }
+ der_certs.push_back(cert_iter->second.GetBytestringAsString());
+
+ auto ocsp_iter = cert_map.find(cbor::CBORValue(kOcspKey));
+ if (i == 1) {
+ // Step 2. The first certificate’s ocsp value if any MUST be a complete,
+ // DER-encoded OCSP response for that certificate (using the ASN.1 type
+ // OCSPResponse defined in [RFC2560]). ... [spec text]
+ if (ocsp_iter == cert_map.end() || !ocsp_iter->second.is_bytestring()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ "ocsp is not a bytestring, or not found in the first cert map.");
+ return nullptr;
+ }
+ ocsp = ocsp_iter->second.GetBytestringAsString().as_string();
+ if (ocsp.empty()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ "ocsp must not be empty.");
+ return nullptr;
+ }
+ } else if (ocsp_iter != cert_map.end()) {
+ // Step 2. ... Subsequent certificates MUST NOT have an ocsp value. [spec
+ // text]
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ base::StringPrintf(
+ "ocsp value found in a subsequent cert map, at index %zu.", i));
+ return nullptr;
+ }
+
+ // Step 3. Each certificate’s sct value MUST be a
+ // SignedCertificateTimestampList for that certificate as defined by Section
+ // 3.3 of [RFC6962]. [spec text]
+ //
+ // We use SCTs only of the main certificate.
+ // TODO(crbug.com/815025): Update the spec text once
+ // https://github.com/WICG/webpackage/issues/175 is resolved.
+ if (i == 1) {
+ auto sct_iter = cert_map.find(cbor::CBORValue(kSctKey));
+ if (sct_iter != cert_map.end()) {
+ if (!sct_iter->second.is_bytestring()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ "sct is not a bytestring.");
+ return nullptr;
+ }
+ sct = sct_iter->second.GetBytestringAsString().as_string();
+ if (sct.empty()) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ "sct must not be empty.");
+ return nullptr;
+ }
+ }
+ }
+ }
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateFromDERCertChain(der_certs);
+ if (!cert) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeCertificateChain::ParseB1",
+ "X509Certificate::CreateFromDERCertChain failed.");
return nullptr;
- return base::WrapUnique(new SignedExchangeCertificateChain(cert));
+ }
+
+ TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "SignedExchangeCertificateChain::ParseB1");
+ return base::WrapUnique(new SignedExchangeCertificateChain(cert, ocsp, sct));
+}
+
+} // namespace
+
+// static
+std::unique_ptr<SignedExchangeCertificateChain>
+SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion version,
+ base::span<const uint8_t> cert_response_body,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
+ switch (version) {
+ case SignedExchangeVersion::kB0:
+ return ParseB0(cert_response_body, devtools_proxy);
+ case SignedExchangeVersion::kB1:
+ return ParseB1(cert_response_body, devtools_proxy);
+ }
+ NOTREACHED();
+ return nullptr;
}
// static
base::Optional<std::vector<base::StringPiece>>
SignedExchangeCertificateChain::GetCertChainFromMessage(
- base::StringPiece message) {
+ base::span<const uint8_t> message) {
uint8_t cert_request_context_size = 0;
if (!ConsumeByte(&message, &cert_request_context_size)) {
DVLOG(1) << "Can't read certificate request request context size.";
@@ -79,9 +254,9 @@ SignedExchangeCertificateChain::GetCertChainFromMessage(
return base::nullopt;
}
- if (cert_list_size != message.length()) {
+ if (cert_list_size != message.size()) {
DVLOG(1) << "Certificate list size error: cert_list_size=" << cert_list_size
- << " remaining=" << message.length();
+ << " remaining=" << message.size();
return base::nullopt;
}
@@ -92,32 +267,35 @@ SignedExchangeCertificateChain::GetCertChainFromMessage(
DVLOG(1) << "Can't read certificate data size.";
return base::nullopt;
}
- if (message.length() < cert_data_size) {
+ if (message.size() < cert_data_size) {
DVLOG(1) << "Certificate data size error: cert_data_size="
- << cert_data_size << " remaining=" << message.length();
+ << cert_data_size << " remaining=" << message.size();
return base::nullopt;
}
- certs.emplace_back(message.substr(0, cert_data_size));
- message.remove_prefix(cert_data_size);
+ certs.emplace_back(base::StringPiece(
+ reinterpret_cast<const char*>(message.data()), cert_data_size));
+ message = message.subspan(cert_data_size);
uint16_t extensions_size = 0;
if (!Consume2Bytes(&message, &extensions_size)) {
DVLOG(1) << "Can't read extensions size.";
return base::nullopt;
}
- if (message.length() < extensions_size) {
+ if (message.size() < extensions_size) {
DVLOG(1) << "Extensions size error: extensions_size=" << extensions_size
- << " remaining=" << message.length();
+ << " remaining=" << message.size();
return base::nullopt;
}
- message.remove_prefix(extensions_size);
+ message = message.subspan(extensions_size);
}
return certs;
}
SignedExchangeCertificateChain::SignedExchangeCertificateChain(
- scoped_refptr<net::X509Certificate> cert)
- : cert_(cert) {
+ scoped_refptr<net::X509Certificate> cert,
+ const std::string& ocsp,
+ const std::string& sct)
+ : cert_(cert), ocsp_(ocsp), sct_(sct) {
DCHECK(cert);
}
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
index d98d57e5e73..7b6ece476c3 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain.h
@@ -11,6 +11,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/strings/string_piece_forward.h"
+#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/common/content_export.h"
namespace net {
@@ -19,28 +20,41 @@ class X509Certificate;
namespace content {
+class SignedExchangeDevToolsProxy;
+
// SignedExchangeCertificateChain contains all information in signed exchange
// certificate chain.
// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
class CONTENT_EXPORT SignedExchangeCertificateChain {
public:
static std::unique_ptr<SignedExchangeCertificateChain> Parse(
- base::StringPiece cert_response_body);
+ SignedExchangeVersion version,
+ base::span<const uint8_t> cert_response_body,
+ SignedExchangeDevToolsProxy* devtools_proxy);
+
+ // Regular consumers should use the static Parse() rather than directly
+ // calling this.
+ SignedExchangeCertificateChain(scoped_refptr<net::X509Certificate> cert,
+ const std::string& ocsp,
+ const std::string& sct);
// Parses a TLS 1.3 Certificate message containing X.509v3 certificates and
// returns a vector of cert_data. Returns nullopt when failed to parse.
static base::Optional<std::vector<base::StringPiece>> GetCertChainFromMessage(
- base::StringPiece message);
+ base::span<const uint8_t> message);
~SignedExchangeCertificateChain();
const scoped_refptr<net::X509Certificate>& cert() const { return cert_; }
+ const std::string& ocsp() const { return ocsp_; }
+ const std::string& sct() const { return sct_; }
private:
- explicit SignedExchangeCertificateChain(
- scoped_refptr<net::X509Certificate> cert);
-
scoped_refptr<net::X509Certificate> cert_;
+
+ // Version b1 specific fields:
+ std::string ocsp_;
+ std::string sct_;
};
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
index e2ccc4ba21e..56d34a6ad96 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain_fuzzer.cc
@@ -9,8 +9,10 @@
namespace content {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- base::StringPiece input(reinterpret_cast<const char*>(data), size);
- SignedExchangeCertificateChain::GetCertChainFromMessage(input);
+ SignedExchangeCertificateChain::Parse(SignedExchangeVersion::kB0,
+ base::make_span(data, size), nullptr);
+ SignedExchangeCertificateChain::Parse(SignedExchangeVersion::kB1,
+ base::make_span(data, size), nullptr);
return 0;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc b/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
index 1dd2681422e..932f1cbf474 100644
--- a/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_certificate_chain_unittest.cc
@@ -4,8 +4,16 @@
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/optional.h"
+#include "base/path_service.h"
#include "base/strings/string_piece.h"
+#include "components/cbor/cbor_values.h"
+#include "components/cbor/cbor_writer.h"
+#include "content/public/common/content_paths.h"
+#include "net/cert/x509_util.h"
+#include "net/test/cert_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,12 +25,16 @@ base::Optional<std::vector<base::StringPiece>> GetCertChain(
const uint8_t* input,
size_t input_size) {
return SignedExchangeCertificateChain::GetCertChainFromMessage(
- base::StringPiece(reinterpret_cast<const char*>(input), input_size));
+ base::make_span(input, input_size));
+}
+
+cbor::CBORValue CBORByteString(base::StringPiece str) {
+ return cbor::CBORValue(str, cbor::CBORValue::Type::BYTE_STRING);
}
} // namespace
-TEST(SignedExchangeCertificateParseTest, OneCert) {
+TEST(SignedExchangeCertificateParseB0Test, OneCert) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -46,7 +58,7 @@ TEST(SignedExchangeCertificateParseTest, OneCert) {
testing::ElementsAreArray(kExpected, arraysize(kExpected)));
}
-TEST(SignedExchangeCertificateParseTest, OneCertWithExtension) {
+TEST(SignedExchangeCertificateParseB0Test, OneCertWithExtension) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -71,7 +83,7 @@ TEST(SignedExchangeCertificateParseTest, OneCertWithExtension) {
testing::ElementsAreArray(kExpected, arraysize(kExpected)));
}
-TEST(SignedExchangeCertificateParseTest, TwoCerts) {
+TEST(SignedExchangeCertificateParseB0Test, TwoCerts) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -163,11 +175,11 @@ TEST(SignedExchangeCertificateParseTest, TwoCerts) {
testing::ElementsAreArray(kExpected2, arraysize(kExpected2)));
}
-TEST(SignedExchangeCertificateParseTest, Empty) {
+TEST(SignedExchangeCertificateParseB0Test, Empty) {
EXPECT_FALSE(GetCertChain(nullptr, 0));
}
-TEST(SignedExchangeCertificateParseTest, InvalidRequestContextSize) {
+TEST(SignedExchangeCertificateParseB0Test, InvalidRequestContextSize) {
const uint8_t input[] = {
// clang-format off
0x01, // request context size: must be zero
@@ -177,7 +189,7 @@ TEST(SignedExchangeCertificateParseTest, InvalidRequestContextSize) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
-TEST(SignedExchangeCertificateParseTest, CanNotReadCertListSize1) {
+TEST(SignedExchangeCertificateParseB0Test, CanNotReadCertListSize1) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -187,7 +199,7 @@ TEST(SignedExchangeCertificateParseTest, CanNotReadCertListSize1) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
-TEST(SignedExchangeCertificateParseTest, CanNotReadCertListSize2) {
+TEST(SignedExchangeCertificateParseB0Test, CanNotReadCertListSize2) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -197,7 +209,7 @@ TEST(SignedExchangeCertificateParseTest, CanNotReadCertListSize2) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
-TEST(SignedExchangeCertificateParseTest, CertListSizeError) {
+TEST(SignedExchangeCertificateParseB0Test, CertListSizeError) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -211,7 +223,7 @@ TEST(SignedExchangeCertificateParseTest, CertListSizeError) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
-TEST(SignedExchangeCertificateParseTest, CanNotReadCertDataSize) {
+TEST(SignedExchangeCertificateParseB0Test, CanNotReadCertDataSize) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -223,7 +235,7 @@ TEST(SignedExchangeCertificateParseTest, CanNotReadCertDataSize) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
-TEST(SignedExchangeCertificateParseTest, CertDataSizeError) {
+TEST(SignedExchangeCertificateParseB0Test, CertDataSizeError) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -236,7 +248,7 @@ TEST(SignedExchangeCertificateParseTest, CertDataSizeError) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
-TEST(SignedExchangeCertificateParseTest, CanNotReadExtensionsSize) {
+TEST(SignedExchangeCertificateParseB0Test, CanNotReadExtensionsSize) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -250,7 +262,7 @@ TEST(SignedExchangeCertificateParseTest, CanNotReadExtensionsSize) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
-TEST(SignedExchangeCertificateParseTest, ExtensionsSizeError) {
+TEST(SignedExchangeCertificateParseB0Test, ExtensionsSizeError) {
const uint8_t input[] = {
// clang-format off
0x00, // request context size
@@ -264,4 +276,183 @@ TEST(SignedExchangeCertificateParseTest, ExtensionsSizeError) {
EXPECT_FALSE(GetCertChain(input, arraysize(input)));
}
+TEST(SignedExchangeCertificateParseB1Test, Empty) {
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::span<const uint8_t>(), nullptr);
+ EXPECT_FALSE(parsed);
+}
+
+TEST(SignedExchangeCertificateParseB1Test, EmptyChain) {
+ cbor::CBORValue::ArrayValue cbor_array;
+ cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
+
+ auto serialized =
+ cbor::CBORWriter::Write(cbor::CBORValue(std::move(cbor_array)));
+ ASSERT_TRUE(serialized.has_value());
+
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ EXPECT_FALSE(parsed);
+}
+
+TEST(SignedExchangeCertificateParseB1Test, MissingCert) {
+ cbor::CBORValue::MapValue cbor_map;
+ cbor_map[cbor::CBORValue("sct")] = CBORByteString("SCT");
+ cbor_map[cbor::CBORValue("ocsp")] = CBORByteString("OCSP");
+
+ cbor::CBORValue::ArrayValue cbor_array;
+ cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map)));
+
+ auto serialized =
+ cbor::CBORWriter::Write(cbor::CBORValue(std::move(cbor_array)));
+ ASSERT_TRUE(serialized.has_value());
+
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ EXPECT_FALSE(parsed);
+}
+
+TEST(SignedExchangeCertificateParseB1Test, OneCert) {
+ net::CertificateList certs;
+ ASSERT_TRUE(
+ net::LoadCertificateFiles({"subjectAltName_sanity_check.pem"}, &certs));
+ ASSERT_EQ(1U, certs.size());
+ base::StringPiece cert_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
+
+ cbor::CBORValue::MapValue cbor_map;
+ cbor_map[cbor::CBORValue("sct")] = CBORByteString("SCT");
+ cbor_map[cbor::CBORValue("cert")] = CBORByteString(cert_der);
+ cbor_map[cbor::CBORValue("ocsp")] = CBORByteString("OCSP");
+
+ cbor::CBORValue::ArrayValue cbor_array;
+ cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map)));
+
+ auto serialized =
+ cbor::CBORWriter::Write(cbor::CBORValue(std::move(cbor_array)));
+ ASSERT_TRUE(serialized.has_value());
+
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ ASSERT_TRUE(parsed);
+ EXPECT_EQ(cert_der, net::x509_util::CryptoBufferAsStringPiece(
+ parsed->cert()->cert_buffer()));
+ ASSERT_EQ(0U, parsed->cert()->intermediate_buffers().size());
+ EXPECT_EQ(parsed->ocsp(), base::make_optional<std::string>("OCSP"));
+ EXPECT_EQ(parsed->sct(), base::make_optional<std::string>("SCT"));
+}
+
+TEST(SignedExchangeCertificateParseB1Test, MissingOCSPInFirstCert) {
+ net::CertificateList certs;
+ ASSERT_TRUE(
+ net::LoadCertificateFiles({"subjectAltName_sanity_check.pem"}, &certs));
+ ASSERT_EQ(1U, certs.size());
+ base::StringPiece cert_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
+
+ cbor::CBORValue::MapValue cbor_map;
+ cbor_map[cbor::CBORValue("sct")] = CBORByteString("SCT");
+ cbor_map[cbor::CBORValue("cert")] = CBORByteString(cert_der);
+
+ cbor::CBORValue::ArrayValue cbor_array;
+ cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map)));
+
+ auto serialized =
+ cbor::CBORWriter::Write(cbor::CBORValue(std::move(cbor_array)));
+ ASSERT_TRUE(serialized.has_value());
+
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ EXPECT_FALSE(parsed);
+}
+
+TEST(SignedExchangeCertificateParseB1Test, TwoCerts) {
+ net::CertificateList certs;
+ ASSERT_TRUE(net::LoadCertificateFiles(
+ {"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
+ ASSERT_EQ(2U, certs.size());
+ base::StringPiece cert1_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
+ base::StringPiece cert2_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer());
+
+ cbor::CBORValue::MapValue cbor_map1;
+ cbor_map1[cbor::CBORValue("sct")] = CBORByteString("SCT");
+ cbor_map1[cbor::CBORValue("cert")] = CBORByteString(cert1_der);
+ cbor_map1[cbor::CBORValue("ocsp")] = CBORByteString("OCSP");
+
+ cbor::CBORValue::MapValue cbor_map2;
+ cbor_map2[cbor::CBORValue("cert")] = CBORByteString(cert2_der);
+
+ cbor::CBORValue::ArrayValue cbor_array;
+ cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map1)));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map2)));
+
+ auto serialized =
+ cbor::CBORWriter::Write(cbor::CBORValue(std::move(cbor_array)));
+ ASSERT_TRUE(serialized.has_value());
+
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ ASSERT_TRUE(parsed);
+ EXPECT_EQ(cert1_der, net::x509_util::CryptoBufferAsStringPiece(
+ parsed->cert()->cert_buffer()));
+ ASSERT_EQ(1U, parsed->cert()->intermediate_buffers().size());
+ EXPECT_EQ(cert2_der, net::x509_util::CryptoBufferAsStringPiece(
+ parsed->cert()->intermediate_buffers()[0].get()));
+ EXPECT_EQ(parsed->ocsp(), base::make_optional<std::string>("OCSP"));
+ EXPECT_EQ(parsed->sct(), base::make_optional<std::string>("SCT"));
+}
+
+TEST(SignedExchangeCertificateParseB1Test, HavingOCSPInSecnodCert) {
+ net::CertificateList certs;
+ ASSERT_TRUE(net::LoadCertificateFiles(
+ {"subjectAltName_sanity_check.pem", "root_ca_cert.pem"}, &certs));
+ ASSERT_EQ(2U, certs.size());
+ base::StringPiece cert1_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[0]->cert_buffer());
+ base::StringPiece cert2_der =
+ net::x509_util::CryptoBufferAsStringPiece(certs[1]->cert_buffer());
+
+ cbor::CBORValue::MapValue cbor_map1;
+ cbor_map1[cbor::CBORValue("sct")] = CBORByteString("SCT");
+ cbor_map1[cbor::CBORValue("cert")] = CBORByteString(cert1_der);
+ cbor_map1[cbor::CBORValue("ocsp")] = CBORByteString("OCSP1");
+
+ cbor::CBORValue::MapValue cbor_map2;
+ cbor_map2[cbor::CBORValue("cert")] = CBORByteString(cert2_der);
+ cbor_map2[cbor::CBORValue("ocsp")] = CBORByteString("OCSP2");
+
+ cbor::CBORValue::ArrayValue cbor_array;
+ cbor_array.push_back(cbor::CBORValue(u8"\U0001F4DC\u26D3"));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map1)));
+ cbor_array.push_back(cbor::CBORValue(std::move(cbor_map2)));
+
+ auto serialized =
+ cbor::CBORWriter::Write(cbor::CBORValue(std::move(cbor_array)));
+ ASSERT_TRUE(serialized.has_value());
+
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::make_span(*serialized), nullptr);
+ EXPECT_FALSE(parsed);
+}
+
+TEST(SignedExchangeCertificateParseB1Test, ParseGoldenFile) {
+ base::FilePath path;
+ base::PathService::Get(content::DIR_TEST_DATA, &path);
+ path = path.AppendASCII("htxg").AppendASCII(
+ "wildcard_example.org.public.pem.cbor");
+ std::string contents;
+ ASSERT_TRUE(base::ReadFileToString(path, &contents));
+
+ auto parsed = SignedExchangeCertificateChain::Parse(
+ SignedExchangeVersion::kB1, base::as_bytes(base::make_span(contents)),
+ nullptr);
+ ASSERT_TRUE(parsed);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_consts.h b/chromium/content/browser/web_package/signed_exchange_consts.h
index a289b8d015d..9dedf00f449 100644
--- a/chromium/content/browser/web_package/signed_exchange_consts.h
+++ b/chromium/content/browser/web_package/signed_exchange_consts.h
@@ -10,18 +10,27 @@ namespace content {
constexpr char kAcceptHeaderSignedExchangeSuffix[] =
",application/signed-exchange;v=b0";
+enum class SignedExchangeVersion { kB0, kB1 };
+
// Field names defined in the application/signed-exchange content type:
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#application-signed-exchange
constexpr char kCertSha256Key[] = "certSha256";
+constexpr char kCertUrl[] = "certUrl";
constexpr char kDateKey[] = "date";
constexpr char kExpiresKey[] = "expires";
constexpr char kHeadersKey[] = "headers";
+constexpr char kIntegrity[] = "integrity";
constexpr char kMethodKey[] = ":method";
constexpr char kSignature[] = "signature";
+constexpr char kSig[] = "sig";
constexpr char kStatusKey[] = ":status";
constexpr char kUrlKey[] = ":url";
constexpr char kValidityUrlKey[] = "validityUrl";
+constexpr char kCertChainCborMagic[] = u8"\U0001F4DC\u26D3"; // "📜⛓"
+constexpr char kCertKey[] = "cert";
+constexpr char kOcspKey[] = "ocsp";
+constexpr char kSctKey[] = "sct";
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
new file mode 100644
index 00000000000..3a04504e15d
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.cc
@@ -0,0 +1,185 @@
+// 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/web_package/signed_exchange_devtools_proxy.h"
+
+#include "base/trace_event/trace_event.h"
+#include "content/browser/devtools/render_frame_devtools_agent_host.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/web_package/signed_exchange_header.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+
+namespace {
+
+void AddErrorMessageToConsoleOnUI(
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ std::string error_message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ WebContents* web_contents =
+ WebContents::FromFrameTreeNodeId(frame_tree_node_id_getter.Run());
+ if (!web_contents)
+ return;
+ web_contents->GetMainFrame()->AddMessageToConsole(
+ content::CONSOLE_MESSAGE_LEVEL_ERROR, error_message);
+}
+
+void CertificateRequestSentOnUI(
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ const base::UnguessableToken& request_id,
+ const base::UnguessableToken& loader_id,
+ const network::ResourceRequest& request,
+ const GURL& signed_exchange_url) {
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
+ if (!frame_tree_node)
+ return;
+ RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestSent(
+ frame_tree_node, request_id, loader_id, request, signed_exchange_url);
+}
+
+void CertificateResponseReceivedOnUI(
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ const base::UnguessableToken& request_id,
+ const base::UnguessableToken& loader_id,
+ const GURL& url,
+ scoped_refptr<network::ResourceResponse> response) {
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
+ if (!frame_tree_node)
+ return;
+ RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateResponseReceived(
+ frame_tree_node, request_id, loader_id, url, response->head);
+}
+
+void CertificateRequestCompletedOnUI(
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ const base::UnguessableToken& request_id,
+ const network::URLLoaderCompletionStatus& status) {
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
+ if (!frame_tree_node)
+ return;
+ RenderFrameDevToolsAgentHost::OnSignedExchangeCertificateRequestCompleted(
+ frame_tree_node, request_id, status);
+}
+
+void OnSignedExchangeReceivedOnUI(
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ const GURL& outer_request_url,
+ scoped_refptr<network::ResourceResponse> outer_response,
+ base::Optional<const base::UnguessableToken> devtools_navigation_token,
+ base::Optional<SignedExchangeHeader> header,
+ base::Optional<net::SSLInfo> ssl_info,
+ std::vector<std::string> error_messages) {
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_getter.Run());
+ if (!frame_tree_node)
+ return;
+ RenderFrameDevToolsAgentHost::OnSignedExchangeReceived(
+ frame_tree_node, devtools_navigation_token, outer_request_url,
+ outer_response->head, header, ssl_info, error_messages);
+}
+
+} // namespace
+
+SignedExchangeDevToolsProxy::SignedExchangeDevToolsProxy(
+ const GURL& outer_request_url,
+ const network::ResourceResponseHead& outer_response,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ base::Optional<const base::UnguessableToken> devtools_navigation_token,
+ bool report_raw_headers)
+ : outer_request_url_(outer_request_url),
+ outer_response_(outer_response),
+ frame_tree_node_id_getter_(frame_tree_node_id_getter),
+ devtools_navigation_token_(devtools_navigation_token),
+ devtools_enabled_(report_raw_headers) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+SignedExchangeDevToolsProxy::~SignedExchangeDevToolsProxy() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+void SignedExchangeDevToolsProxy::ReportErrorMessage(
+ const std::string& message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ error_messages_.push_back(message);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&AddErrorMessageToConsoleOnUI, frame_tree_node_id_getter_,
+ std::move(message)));
+}
+
+void SignedExchangeDevToolsProxy::CertificateRequestSent(
+ const base::UnguessableToken& request_id,
+ const network::ResourceRequest& request) {
+ if (!devtools_enabled_)
+ return;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &CertificateRequestSentOnUI, frame_tree_node_id_getter_, request_id,
+ devtools_navigation_token_ ? *devtools_navigation_token_ : request_id,
+ request, outer_request_url_));
+}
+
+void SignedExchangeDevToolsProxy::CertificateResponseReceived(
+ const base::UnguessableToken& request_id,
+ const GURL& url,
+ const network::ResourceResponseHead& head) {
+ if (!devtools_enabled_)
+ return;
+
+ // Make a deep copy of ResourceResponseHead before passing it cross-thread.
+ auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
+ resource_response->head = head;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(
+ &CertificateResponseReceivedOnUI, frame_tree_node_id_getter_,
+ request_id,
+ devtools_navigation_token_ ? *devtools_navigation_token_ : request_id,
+ url, resource_response->DeepCopy()));
+}
+
+void SignedExchangeDevToolsProxy::CertificateRequestCompleted(
+ const base::UnguessableToken& request_id,
+ const network::URLLoaderCompletionStatus& status) {
+ if (!devtools_enabled_)
+ return;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&CertificateRequestCompletedOnUI,
+ frame_tree_node_id_getter_, request_id, status));
+}
+
+void SignedExchangeDevToolsProxy::OnSignedExchangeReceived(
+ const base::Optional<SignedExchangeHeader>& header,
+ const net::SSLInfo* ssl_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!devtools_enabled_)
+ return;
+ base::Optional<net::SSLInfo> ssl_info_opt;
+ if (ssl_info)
+ ssl_info_opt = *ssl_info;
+
+ // Make a deep copy of ResourceResponseHead before passing it cross-thread.
+ auto resource_response = base::MakeRefCounted<network::ResourceResponse>();
+ resource_response->head = outer_response_;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&OnSignedExchangeReceivedOnUI, frame_tree_node_id_getter_,
+ outer_request_url_, resource_response->DeepCopy(),
+ devtools_navigation_token_, header,
+ std::move(ssl_info_opt), std::move(error_messages_)));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_devtools_proxy.h b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.h
new file mode 100644
index 00000000000..e73b1119ec5
--- /dev/null
+++ b/chromium/content/browser/web_package/signed_exchange_devtools_proxy.h
@@ -0,0 +1,86 @@
+// 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_WEB_PACKAGE_SIGNED_EXCHANGE_DEVTOOLS_PROXY_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_DEVTOOLS_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
+#include "content/common/content_export.h"
+#include "services/network/public/cpp/resource_response.h"
+
+class GURL;
+
+namespace base {
+class UnguessableToken;
+} // namespace base
+
+namespace net {
+class SSLInfo;
+} // namespace net
+
+namespace network {
+struct ResourceRequest;
+struct ResourceResponseHead;
+struct URLLoaderCompletionStatus;
+} // namespace network
+
+namespace content {
+class SignedExchangeHeader;
+
+// SignedExchangeDevToolsProxy lives on the IO thread and sends messages to
+// DevTools via the UI thread to show signed exchange related information.
+class CONTENT_EXPORT SignedExchangeDevToolsProxy {
+ public:
+ // |frame_tree_node_id_getter| callback will be called on the UI thread to get
+ // the frame tree node ID. Note: We are using callback beause when Network
+ // Service is not enabled the ID is not available while handling prefetch
+ // requests on the IO thread.
+ // When the signed exchange request is a navigation request,
+ // |devtools_navigation_token| can be used to find the matching request in
+ // DevTools. But when the signed exchange request is a prefetch request, the
+ // browser process doesn't know the request id used in DevTools. So DevTools
+ // looks up the inflight requests using |outer_request_url| to find the
+ // matching request.
+ SignedExchangeDevToolsProxy(
+ const GURL& outer_request_url,
+ const network::ResourceResponseHead& outer_response,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ base::Optional<const base::UnguessableToken> devtools_navigation_token,
+ bool report_raw_headers);
+ ~SignedExchangeDevToolsProxy();
+
+ void ReportErrorMessage(const std::string& message);
+ void CertificateRequestSent(const base::UnguessableToken& request_id,
+ const network::ResourceRequest& request);
+ void CertificateResponseReceived(const base::UnguessableToken& request_id,
+ const GURL& url,
+ const network::ResourceResponseHead& head);
+ void CertificateRequestCompleted(
+ const base::UnguessableToken& request_id,
+ const network::URLLoaderCompletionStatus& status);
+
+ void OnSignedExchangeReceived(
+ const base::Optional<SignedExchangeHeader>& header,
+ const net::SSLInfo* ssl_info);
+
+ private:
+ const GURL outer_request_url_;
+ const network::ResourceResponseHead outer_response_;
+ const base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
+ const base::Optional<const base::UnguessableToken> devtools_navigation_token_;
+ const bool devtools_enabled_;
+ std::vector<std::string> error_messages_;
+
+ DISALLOW_COPY_AND_ASSIGN(SignedExchangeDevToolsProxy);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_DEVTOOLS_PROXY_H_
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.cc b/chromium/content/browser/web_package/signed_exchange_handler.cc
index d4e878f17b2..52e127a28e9 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler.cc
@@ -4,24 +4,23 @@
#include "content/browser/web_package/signed_exchange_handler.h"
-#include "base/feature_list.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/loader/merkle_integrity_source_stream.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
#include "content/browser/web_package/signed_exchange_certificate_chain.h"
-#include "content/browser/web_package/signed_exchange_consts.h"
+#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_header.h"
#include "content/browser/web_package/signed_exchange_signature_verifier.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_features.h"
#include "content/public/common/url_loader_throttle.h"
#include "mojo/public/cpp/system/string_data_pipe_producer.h"
#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/x509_certificate.h"
@@ -56,26 +55,6 @@ base::Time GetVerificationTime() {
return base::Time::Now();
}
-void AddErrorMessageToConsole(int frame_tree_node_id,
- const std::string& message) {
- // |frame_tree_node_id| is -1 for unittests.
- if (frame_tree_node_id == -1)
- return;
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::BindOnce(&AddErrorMessageToConsole, frame_tree_node_id, message));
- return;
- }
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- WebContents* web_contents =
- WebContents::FromFrameTreeNodeId(frame_tree_node_id);
- if (!web_contents)
- return;
- web_contents->GetMainFrame()->AddMessageToConsole(
- content::CONSOLE_MESSAGE_LEVEL_ERROR, message);
-}
-
} // namespace
// static
@@ -96,7 +75,7 @@ SignedExchangeHandler::SignedExchangeHandler(
ExchangeHeadersCallback headers_callback,
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- int frame_tree_node_id)
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy)
: headers_callback_(std::move(headers_callback)),
source_(std::move(body)),
cert_fetcher_factory_(std::move(cert_fetcher_factory)),
@@ -104,45 +83,42 @@ SignedExchangeHandler::SignedExchangeHandler(
net_log_(net::NetLogWithSource::Make(
request_context_getter_->GetURLRequestContext()->net_log(),
net::NetLogSourceType::CERT_VERIFIER_JOB)),
- error_message_callback_(
- base::BindRepeating(&AddErrorMessageToConsole, frame_tree_node_id)),
+ devtools_proxy_(std::move(devtools_proxy)),
weak_factory_(this) {
- DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
+ DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::SignedExchangeHandler");
- base::Optional<std::string> content_type_version_param;
- if (!SignedExchangeHeaderParser::GetVersionParamFromContentType(
- content_type, &content_type_version_param) ||
- !content_type_version_param || *content_type_version_param != "b0") {
+ if (!SignedExchangeHeaderParser::GetVersionParamFromContentType(content_type,
+ &version_) ||
+ (version_ != SignedExchangeVersion::kB0 &&
+ version_ != SignedExchangeVersion::kB1)) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SignedExchangeHandler::RunErrorCallback,
- weak_factory_.GetWeakPtr(), net::ERR_FAILED));
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::SignedExchangeHandler", error_message_callback_,
+ weak_factory_.GetWeakPtr(),
+ net::ERR_INVALID_SIGNED_EXCHANGE));
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::SignedExchangeHandler",
base::StringPrintf("Unsupported version of the content type. Currentry "
"content type must be "
- "\"application/signed-exchange;v=b0\". But the "
+ "\"application/signed-exchange;v={b0,b1}\". But the "
"response content type was \"%s\"",
content_type.c_str()));
return;
}
// Triggering the read (asynchronously) for the encoded header length.
- SetupBuffers(SignedExchangeHeader::kEncodedHeaderLengthInBytes);
+ SetupBuffers(SignedExchangeHeader::kEncodedLengthInBytes);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&SignedExchangeHandler::DoHeaderLoop,
weak_factory_.GetWeakPtr()));
TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::SignedExchangeHandler");
+ "SignedExchangeHandler::SignedExchangeHandler");
}
SignedExchangeHandler::~SignedExchangeHandler() = default;
-SignedExchangeHandler::SignedExchangeHandler()
- : error_message_callback_(base::BindRepeating(&AddErrorMessageToConsole,
- -1 /* frame_tree_node_id */)),
- weak_factory_(this) {}
+SignedExchangeHandler::SignedExchangeHandler() : weak_factory_(this) {}
void SignedExchangeHandler::SetupBuffers(size_t size) {
header_buf_ = base::MakeRefCounted<net::IOBuffer>(size);
@@ -165,18 +141,18 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::DidReadHeader");
if (result < 0) {
- RunErrorCallback(static_cast<net::Error>(result));
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::DidReadHeader", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::DidReadHeader",
base::StringPrintf("Error reading body stream. result: %d", result));
+ RunErrorCallback(static_cast<net::Error>(result));
return;
}
if (result == 0) {
- RunErrorCallback(net::ERR_FAILED);
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::DidReadHeader", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::DidReadHeader",
"Stream ended while reading signed exchange header.");
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
@@ -185,11 +161,11 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
switch (state_) {
case State::kReadingHeadersLength:
if (!ParseHeadersLength())
- RunErrorCallback(net::ERR_FAILED);
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
break;
case State::kReadingHeaders:
if (!ParseHeadersAndFetchCertificate())
- RunErrorCallback(net::ERR_FAILED);
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
break;
default:
NOTREACHED();
@@ -213,20 +189,20 @@ void SignedExchangeHandler::DidReadHeader(bool completed_syncly, int result) {
DoHeaderLoop();
}
TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::DidReadHeader");
+ "SignedExchangeHandler::DidReadHeader");
}
bool SignedExchangeHandler::ParseHeadersLength() {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeHandler::ParseHeadersLength");
+ "SignedExchangeHandler::ParseEncodedLength");
DCHECK_EQ(state_, State::kReadingHeadersLength);
- headers_length_ = SignedExchangeHeader::ParseHeadersLength(
+ headers_length_ = SignedExchangeHeader::ParseEncodedLength(
base::make_span(reinterpret_cast<uint8_t*>(header_buf_->data()),
- SignedExchangeHeader::kEncodedHeaderLengthInBytes));
+ SignedExchangeHeader::kEncodedLengthInBytes));
if (headers_length_ == 0 || headers_length_ > kMaxHeadersCBORLength) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::ParseHeadersLength", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::ParseEncodedLength",
base::StringPrintf("Invalid CBOR header length: %zu", headers_length_));
return false;
}
@@ -235,7 +211,7 @@ bool SignedExchangeHandler::ParseHeadersLength() {
SetupBuffers(headers_length_);
state_ = State::kReadingHeaders;
TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
- "SignedExchangeCertFetcher::ParseHeadersLength");
+ "SignedExchangeHandler::ParseEncodedLength");
return true;
}
@@ -247,13 +223,14 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
header_ = SignedExchangeHeader::Parse(
base::make_span(reinterpret_cast<uint8_t*>(header_buf_->data()),
headers_length_),
- error_message_callback_);
+ devtools_proxy_.get());
header_read_buf_ = nullptr;
header_buf_ = nullptr;
if (!header_) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(),
"SignedExchangeHandler::ParseHeadersAndFetchCertificate",
- error_message_callback_, "Failed to parse SignedExchange header.");
+ "Failed to parse SignedExchange header.");
return false;
}
@@ -261,14 +238,15 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
// TODO(https://crbug.com/819467): When we will support ed25519Key, |cert_url|
// may be empty.
DCHECK(cert_url.is_valid());
+ DCHECK(version_.has_value());
DCHECK(cert_fetcher_factory_);
cert_fetcher_ = std::move(cert_fetcher_factory_)
->CreateFetcherAndStart(
- cert_url, false,
+ cert_url, false, *version_,
base::BindOnce(&SignedExchangeHandler::OnCertReceived,
base::Unretained(this)),
- error_message_callback_);
+ devtools_proxy_.get());
state_ = State::kFetchingCertificate;
TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"),
@@ -278,6 +256,8 @@ bool SignedExchangeHandler::ParseHeadersAndFetchCertificate() {
void SignedExchangeHandler::RunErrorCallback(net::Error error) {
DCHECK_NE(state_, State::kHeadersCallbackCalled);
+ if (devtools_proxy_)
+ devtools_proxy_->OnSignedExchangeReceived(header_, nullptr);
std::move(headers_callback_)
.Run(error, GURL(), std::string(), network::ResourceResponseHead(),
nullptr);
@@ -290,30 +270,30 @@ void SignedExchangeHandler::OnCertReceived(
"SignedExchangeHandler::OnCertReceived");
DCHECK_EQ(state_, State::kFetchingCertificate);
if (!cert_chain) {
- RunErrorCallback(net::ERR_FAILED);
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::OnCertReceived", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::OnCertReceived",
"Failed to fetch the certificate.");
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
if (SignedExchangeSignatureVerifier::Verify(*header_, cert_chain->cert(),
GetVerificationTime(),
- error_message_callback_) !=
+ devtools_proxy_.get()) !=
SignedExchangeSignatureVerifier::Result::kSuccess) {
- RunErrorCallback(net::ERR_FAILED);
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::OnCertReceived", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::OnCertReceived",
"Failed to verify the signed exchange header.");
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
net::URLRequestContext* request_context =
request_context_getter_->GetURLRequestContext();
if (!request_context) {
- RunErrorCallback(net::ERR_CONTEXT_SHUT_DOWN);
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::OnCertReceived", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::OnCertReceived",
"No request context available.");
+ RunErrorCallback(net::ERR_CONTEXT_SHUT_DOWN);
return;
}
@@ -325,13 +305,10 @@ void SignedExchangeHandler::OnCertReceived(
net::CertVerifier* cert_verifier = g_cert_verifier_for_testing
? g_cert_verifier_for_testing
: request_context->cert_verifier();
- // TODO(https://crbug.com/815024): Get the OCSP response from the
- // “status_request” extension of the main-certificate, and check the lifetime
- // (nextUpdate - thisUpdate) is less than 7 days.
int result = cert_verifier->Verify(
net::CertVerifier::RequestParams(
unverified_cert_chain_->cert(), header_->request_url().host(),
- config.GetCertVerifyFlags(), std::string() /* ocsp_response */,
+ config.GetCertVerifyFlags(), unverified_cert_chain_->ocsp(),
net::CertificateList()),
net::SSLConfigService::GetCRLSet().get(), &cert_verify_result_,
base::BindRepeating(&SignedExchangeHandler::OnCertVerifyComplete,
@@ -346,15 +323,48 @@ void SignedExchangeHandler::OnCertReceived(
"SignedExchangeHandler::OnCertReceived");
}
+bool SignedExchangeHandler::CheckOCSPStatus(
+ const net::OCSPVerifyResult& ocsp_result) {
+ // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cross-origin-trust
+ // Step 6.3 Validate that main-certificate has an ocsp property (Section 3.3)
+ // with a valid OCSP response whose lifetime (nextUpdate - thisUpdate) is less
+ // than 7 days ([RFC6960]). [spec text]
+ //
+ // OCSP verification is done in CertVerifier::Verify(), so we just check the
+ // result here.
+
+ // The b0 implementation checkpoint has no OCSP check.
+ if (version_ == SignedExchangeVersion::kB0)
+ return true;
+
+ if (ocsp_result.response_status != net::OCSPVerifyResult::PROVIDED ||
+ ocsp_result.revocation_status != net::OCSPRevocationStatus::GOOD)
+ return false;
+
+ return true;
+}
+
void SignedExchangeHandler::OnCertVerifyComplete(int result) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHandler::OnCertVerifyComplete");
if (result != net::OK) {
- RunErrorCallback(static_cast<net::Error>(result));
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::OnCertVerifyComplete", error_message_callback_,
- base::StringPrintf("Certificate verification error: %d", result));
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::OnCertVerifyComplete",
+ base::StringPrintf("Certificate verification error: %s",
+ net::ErrorToShortString(result).c_str()));
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
+ return;
+ }
+
+ if (!CheckOCSPStatus(cert_verify_result_.ocsp_result)) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::OnCertVerifyComplete",
+ base::StringPrintf(
+ "OCSP check failed. response status: %d, revocation status: %d",
+ cert_verify_result_.ocsp_result.response_status,
+ cert_verify_result_.ocsp_result.revocation_status));
+ RunErrorCallback(static_cast<net::Error>(net::ERR_FAILED));
return;
}
@@ -375,10 +385,10 @@ void SignedExchangeHandler::OnCertVerifyComplete(int result) {
std::string mi_header_value;
if (!response_head.headers->EnumerateHeader(nullptr, kMiHeader,
&mi_header_value)) {
- RunErrorCallback(net::ERR_FAILED);
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHandler::OnCertVerifyComplete", error_message_callback_,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy_.get(), "SignedExchangeHandler::OnCertVerifyComplete",
"Signed exchange has no MI: header");
+ RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE);
return;
}
auto mi_stream = std::make_unique<MerkleIntegritySourceStream>(
@@ -395,6 +405,10 @@ void SignedExchangeHandler::OnCertVerifyComplete(int result) {
ssl_info.is_fatal_cert_error =
net::IsCertStatusError(ssl_info.cert_status) &&
!net::IsCertStatusMinorError(ssl_info.cert_status);
+
+ if (devtools_proxy_)
+ devtools_proxy_->OnSignedExchangeReceived(header_, &ssl_info);
+
response_head.ssl_info = std::move(ssl_info);
// TODO(https://crbug.com/815025): Verify the Certificate Transparency status.
std::move(headers_callback_)
diff --git a/chromium/content/browser/web_package/signed_exchange_handler.h b/chromium/content/browser/web_package/signed_exchange_handler.h
index 84f9fe4bd6f..d1df8d39d5b 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler.h
+++ b/chromium/content/browser/web_package/signed_exchange_handler.h
@@ -10,8 +10,8 @@
#include "base/callback.h"
#include "base/optional.h"
#include "base/time/time.h"
+#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_header.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/completion_callback.h"
@@ -28,6 +28,7 @@ class CertVerifyResult;
class DrainableIOBuffer;
class SourceStream;
class URLRequestContextGetter;
+struct OCSPVerifyResult;
} // namespace net
namespace network {
@@ -39,6 +40,7 @@ namespace content {
class SignedExchangeCertFetcher;
class SignedExchangeCertFetcherFactory;
class SignedExchangeCertificateChain;
+class SignedExchangeDevToolsProxy;
// IMPORTANT: Currenly SignedExchangeHandler partially implements the verifying
// logic.
@@ -70,7 +72,7 @@ class CONTENT_EXPORT SignedExchangeHandler {
ExchangeHeadersCallback headers_callback,
std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- int frame_tree_node_id);
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy);
~SignedExchangeHandler();
protected:
@@ -94,8 +96,10 @@ class CONTENT_EXPORT SignedExchangeHandler {
void OnCertReceived(
std::unique_ptr<SignedExchangeCertificateChain> cert_chain);
void OnCertVerifyComplete(int result);
+ bool CheckOCSPStatus(const net::OCSPVerifyResult& ocsp_result);
ExchangeHeadersCallback headers_callback_;
+ base::Optional<SignedExchangeVersion> version_;
std::unique_ptr<net::SourceStream> source_;
State state_ = State::kReadingHeadersLength;
@@ -123,7 +127,7 @@ class CONTENT_EXPORT SignedExchangeHandler {
// with Network Service.
net::NetLogWithSource net_log_;
- signed_exchange_utils::LogCallback error_message_callback_;
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy_;
base::WeakPtrFactory<SignedExchangeHandler> weak_factory_;
diff --git a/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc b/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
index fbcb5b29a0b..46b4a38736b 100644
--- a/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -12,7 +12,7 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "net/base/io_buffer.h"
@@ -22,8 +22,15 @@
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using testing::_;
+using testing::Property;
+using testing::Return;
+using testing::SetArgPointee;
+using testing::Truly;
+
namespace content {
namespace {
@@ -33,7 +40,7 @@ const int kOutputBufferSize = 4096;
std::string GetTestFileContents(base::StringPiece name) {
base::FilePath path;
- PathService::Get(content::DIR_TEST_DATA, &path);
+ base::PathService::Get(content::DIR_TEST_DATA, &path);
path = path.AppendASCII("htxg").AppendASCII(name);
std::string contents;
@@ -60,12 +67,13 @@ class MockSignedExchangeCertFetcherFactory
std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
const GURL& cert_url,
bool force_fetch,
+ SignedExchangeVersion version,
SignedExchangeCertFetcher::CertificateCallback callback,
- const signed_exchange_utils::LogCallback& error_message_callback)
- override {
+ SignedExchangeDevToolsProxy* devtools_proxy) override {
EXPECT_EQ(cert_url, expected_cert_url_);
- auto cert_chain = SignedExchangeCertificateChain::Parse(cert_str_);
+ auto cert_chain = SignedExchangeCertificateChain::Parse(
+ version, base::as_bytes(base::make_span(cert_str_)), devtools_proxy);
EXPECT_TRUE(cert_chain);
base::SequencedTaskRunnerHandle::Get()->PostTask(
@@ -78,18 +86,31 @@ class MockSignedExchangeCertFetcherFactory
std::string cert_str_;
};
+class GMockCertVerifier : public net::CertVerifier {
+ public:
+ MOCK_METHOD6(Verify,
+ int(const net::CertVerifier::RequestParams& params,
+ net::CRLSet* crl_set,
+ net::CertVerifyResult* verify_result,
+ const net::CompletionCallback& callback,
+ std::unique_ptr<net::CertVerifier::Request>* out_req,
+ const net::NetLogWithSource& net_log));
+};
+
} // namespace
class SignedExchangeHandlerTest
: public ::testing::TestWithParam<net::MockSourceStream::Mode> {
public:
SignedExchangeHandlerTest()
- : mock_cert_verifier_(std::make_unique<net::MockCertVerifier>()),
- request_initiator_(
+ : request_initiator_(
url::Origin::Create(GURL("https://htxg.example.com/test.htxg"))) {}
+ virtual std::string ContentType() {
+ return "application/signed-exchange;v=b0";
+ }
+
void SetUp() override {
- SignedExchangeHandler::SetCertVerifierForTesting(mock_cert_verifier_.get());
SignedExchangeHandler::SetVerificationTimeForTesting(
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(kSignatureHeaderDate));
@@ -104,11 +125,11 @@ class SignedExchangeHandlerTest
request_context_getter_ = new net::TestURLRequestContextGetter(
scoped_task_environment_.GetMainThreadTaskRunner());
handler_ = std::make_unique<SignedExchangeHandler>(
- "application/signed-exchange;v=b0", std::move(source),
+ ContentType(), std::move(source),
base::BindOnce(&SignedExchangeHandlerTest::OnHeaderFound,
base::Unretained(this)),
std::move(cert_fetcher_factory), request_context_getter_,
- -1 /* frame_tree_node_id */);
+ nullptr /* devtools_proxy */);
}
void TearDown() override {
@@ -117,6 +138,11 @@ class SignedExchangeHandlerTest
base::Optional<base::Time>());
}
+ void SetCertVerifier(std::unique_ptr<net::CertVerifier> cert_verifier) {
+ cert_verifier_ = std::move(cert_verifier);
+ SignedExchangeHandler::SetCertVerifierForTesting(cert_verifier_.get());
+ }
+
// Reads from |stream| until an error occurs or the EOF is reached.
// When an error occurs, returns the net error code. When an EOF is reached,
// returns the number of bytes read. If |output| is non-null, appends data
@@ -166,7 +192,7 @@ class SignedExchangeHandlerTest
protected:
MockSignedExchangeCertFetcherFactory* mock_cert_fetcher_factory_;
- std::unique_ptr<net::MockCertVerifier> mock_cert_verifier_;
+ std::unique_ptr<net::CertVerifier> cert_verifier_;
net::MockSourceStream* source_;
std::unique_ptr<SignedExchangeHandler> handler_;
@@ -193,13 +219,19 @@ class SignedExchangeHandlerTest
std::unique_ptr<net::SourceStream> payload_stream_;
};
+class SignedExchangeHandlerB1Test : public SignedExchangeHandlerTest {
+ std::string ContentType() override {
+ return "application/signed-exchange;v=b1";
+ }
+};
+
TEST_P(SignedExchangeHandlerTest, Empty) {
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
}
TEST_P(SignedExchangeHandlerTest, Simple) {
@@ -214,8 +246,10 @@ TEST_P(SignedExchangeHandlerTest, Simple) {
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
- mock_cert_verifier_->AddResultForCertAndHost(original_cert, "*.example.org",
- dummy_result, net::OK);
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
std::string contents = GetTestFileContents("test.example.org_test.htxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
@@ -248,7 +282,10 @@ TEST_P(SignedExchangeHandlerTest, MimeType) {
GURL("https://cert.example.org/cert.msg"),
GetTestFileContents("wildcard_example.org.public.pem.msg"));
- mock_cert_verifier_->set_default_result(net::OK);
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->set_default_result(net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
std::string contents = GetTestFileContents("test.example.org_hello.txt.htxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
source_->AddReadResult(nullptr, 0, net::OK, GetParam());
@@ -277,7 +314,7 @@ TEST_P(SignedExchangeHandlerTest, ParseError) {
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
}
TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
@@ -289,7 +326,7 @@ TEST_P(SignedExchangeHandlerTest, TruncatedInHeader) {
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
}
TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
@@ -302,7 +339,9 @@ TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
// Set the default result of MockCertVerifier to OK, to check that the
// verification of SignedExchange must fail even if the certificate is valid.
- mock_cert_verifier_->set_default_result(net::OK);
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->set_default_result(net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
std::string contents = GetTestFileContents("test.example.org_test.htxg");
source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
@@ -311,7 +350,7 @@ TEST_P(SignedExchangeHandlerTest, CertSha256Mismatch) {
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_FAILED, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
@@ -328,8 +367,10 @@ TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
net::CertVerifyResult dummy_result;
dummy_result.verified_cert = original_cert;
dummy_result.cert_status = net::OK;
- mock_cert_verifier_->AddResultForCertAndHost(original_cert, "*.example.org",
- dummy_result, net::OK);
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
// The certificate is for "*.example.com". But the request URL of the htxg
// file is "https://test.example.com/test/". So the certification verification
@@ -342,14 +383,243 @@ TEST_P(SignedExchangeHandlerTest, VerifyCertFailure) {
WaitForHeader();
ASSERT_TRUE(read_header());
- EXPECT_EQ(net::ERR_CERT_INVALID, error());
+ EXPECT_EQ(net::ERR_INVALID_SIGNED_EXCHANGE, error());
+ // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+ ReadStream(source_, nullptr);
+}
+
+TEST_P(SignedExchangeHandlerB1Test, Simple) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
+ // "*.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("wildcard.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::OK, error());
+ EXPECT_EQ(200, resource_response().headers->response_code());
+ EXPECT_EQ("text/html", resource_response().mime_type);
+ EXPECT_EQ("utf-8", resource_response().charset);
+ EXPECT_FALSE(resource_response().load_timing.request_start_time.is_null());
+ EXPECT_FALSE(resource_response().load_timing.request_start.is_null());
+ EXPECT_FALSE(resource_response().load_timing.send_start.is_null());
+ EXPECT_FALSE(resource_response().load_timing.send_end.is_null());
+ EXPECT_FALSE(resource_response().load_timing.receive_headers_end.is_null());
+
+ std::string payload;
+ int rv = ReadPayloadStream(&payload);
+
+ std::string expected_payload = GetTestFileContents("test.html");
+
+ EXPECT_EQ(payload, expected_payload);
+ EXPECT_EQ(rv, static_cast<int>(expected_payload.size()));
+}
+
+TEST_P(SignedExchangeHandlerB1Test, OCSPNotChecked) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
+ // "*.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("wildcard.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::NOT_CHECKED;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::ERR_FAILED, error());
+ // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+ ReadStream(source_, nullptr);
+}
+
+TEST_P(SignedExchangeHandlerB1Test, OCSPNotProvided) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
+ // "*.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("wildcard.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::MISSING;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::ERR_FAILED, error());
+ // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+ ReadStream(source_, nullptr);
+}
+
+TEST_P(SignedExchangeHandlerB1Test, OCSPInvalid) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
+ // "*.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("wildcard.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status =
+ net::OCSPVerifyResult::INVALID_DATE;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::ERR_FAILED, error());
+ // Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
+ ReadStream(source_, nullptr);
+}
+
+TEST_P(SignedExchangeHandlerB1Test, OCSPRevoked) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+
+ // Make the MockCertVerifier treat the certificate "wildcard.pem" as valid for
+ // "*.example.org".
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("wildcard.pem");
+ net::CertVerifyResult dummy_result;
+ dummy_result.verified_cert = original_cert;
+ dummy_result.cert_status = net::OK;
+ dummy_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ dummy_result.ocsp_result.revocation_status =
+ net::OCSPRevocationStatus::REVOKED;
+ auto mock_cert_verifier = std::make_unique<net::MockCertVerifier>();
+ mock_cert_verifier->AddResultForCertAndHost(original_cert, "*.example.org",
+ dummy_result, net::OK);
+ SetCertVerifier(std::move(mock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::ERR_FAILED, error());
// Drain the MockSourceStream, otherwise its destructer causes DCHECK failure.
ReadStream(source_, nullptr);
}
+// Test that fetching a signed exchange properly extracts and
+// attempts to verify both the certificate and the OCSP response.
+TEST_P(SignedExchangeHandlerB1Test, CertVerifierParams) {
+ mock_cert_fetcher_factory_->ExpectFetch(
+ GURL("https://cert.example.org/cert.msg"),
+ GetTestFileContents("wildcard_example.org.public.pem.cbor"));
+
+ scoped_refptr<net::X509Certificate> original_cert =
+ LoadCertificate("wildcard.pem");
+ net::CertVerifyResult fake_result;
+ fake_result.verified_cert = original_cert;
+ fake_result.cert_status = net::OK;
+ fake_result.ocsp_result.response_status = net::OCSPVerifyResult::PROVIDED;
+ fake_result.ocsp_result.revocation_status = net::OCSPRevocationStatus::GOOD;
+
+ // "wildcard_example.org.public.pem.cbor" has this dummy data instead of a
+ // real OCSP response.
+ constexpr base::StringPiece kExpectedOCSPDer = "OCSP";
+
+ std::unique_ptr<GMockCertVerifier> gmock_cert_verifier =
+ std::make_unique<GMockCertVerifier>();
+ EXPECT_CALL(
+ *gmock_cert_verifier,
+ Verify(
+ AllOf(Property(&net::CertVerifier::RequestParams::ocsp_response,
+ kExpectedOCSPDer),
+ Property(
+ &net::CertVerifier::RequestParams::certificate,
+ Truly([&original_cert](
+ const scoped_refptr<net::X509Certificate>& cert) {
+ return original_cert->EqualsIncludingChain(cert.get());
+ })),
+ Property(&net::CertVerifier::RequestParams::hostname,
+ "test.example.org")),
+ _ /* crl_set */, _ /* verify_result */, _ /* callback */,
+ _ /* out_req */, _ /* net_log */
+ ))
+ .WillOnce(DoAll(SetArgPointee<2>(fake_result), Return(net::OK)));
+ SetCertVerifier(std::move(gmock_cert_verifier));
+
+ std::string contents = GetTestFileContents("test.example.org_test.htxg");
+ source_->AddReadResult(contents.data(), contents.size(), net::OK, GetParam());
+ source_->AddReadResult(nullptr, 0, net::OK, GetParam());
+
+ WaitForHeader();
+
+ ASSERT_TRUE(read_header());
+ EXPECT_EQ(net::OK, error());
+ std::string payload;
+ int rv = ReadPayloadStream(&payload);
+ std::string expected_payload = GetTestFileContents("test.html");
+
+ EXPECT_EQ(expected_payload, payload);
+ EXPECT_EQ(static_cast<int>(expected_payload.size()), rv);
+}
+
INSTANTIATE_TEST_CASE_P(SignedExchangeHandlerTests,
SignedExchangeHandlerTest,
::testing::Values(net::MockSourceStream::SYNC,
net::MockSourceStream::ASYNC));
+INSTANTIATE_TEST_CASE_P(SignedExchangeHandlerB1Tests,
+ SignedExchangeHandlerB1Test,
+ ::testing::Values(net::MockSourceStream::SYNC,
+ net::MockSourceStream::ASYNC));
+
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_header.cc b/chromium/content/browser/web_package/signed_exchange_header.cc
index a97e746c4eb..e0bfe678b2a 100644
--- a/chromium/content/browser/web_package/signed_exchange_header.cc
+++ b/chromium/content/browser/web_package/signed_exchange_header.cc
@@ -67,14 +67,13 @@ bool IsMethodCacheable(base::StringPiece method) {
return method == "GET" || method == "HEAD" || method == "POST";
}
-bool ParseRequestMap(
- const cbor::CBORValue& value,
- SignedExchangeHeader* out,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+bool ParseRequestMap(const cbor::CBORValue& value,
+ SignedExchangeHeader* out,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseRequestMap");
if (!value.is_map()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
base::StringPrintf(
"Expected request map, got non-map type. Actual type: %d",
static_cast<int>(value.type())));
@@ -86,21 +85,20 @@ bool ParseRequestMap(
auto url_iter = request_map.find(
cbor::CBORValue(kUrlKey, cbor::CBORValue::Type::BYTE_STRING));
if (url_iter == request_map.end() || !url_iter->second.is_bytestring()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
":url is not found or not a bytestring.");
return false;
}
out->set_request_url(GURL(url_iter->second.GetBytestringAsString()));
if (!out->request_url().is_valid()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback, ":url is not a valid URL.");
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap", ":url is not a valid URL.");
return false;
}
if (out->request_url().has_ref()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
- ":url can't have a fragment.");
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap", ":url can't have a fragment.");
return false;
}
@@ -108,8 +106,8 @@ bool ParseRequestMap(
cbor::CBORValue(kMethodKey, cbor::CBORValue::Type::BYTE_STRING));
if (method_iter == request_map.end() ||
!method_iter->second.is_bytestring()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
":method is not found or not a bytestring.");
return false;
}
@@ -119,8 +117,8 @@ bool ParseRequestMap(
// [spec text]
if (!net::HttpUtil::IsMethodSafe(method_str.as_string()) ||
!IsMethodCacheable(method_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
base::StringPrintf(
"Request method is not safe or not cacheable. method: %s",
method_str.as_string().c_str()));
@@ -130,8 +128,8 @@ bool ParseRequestMap(
for (const auto& it : request_map) {
if (!it.first.is_bytestring() || !it.second.is_bytestring()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
"Non-bytestring value in the request map.");
return false;
}
@@ -142,8 +140,8 @@ bool ParseRequestMap(
// TODO(kouhei): Add spec ref here once
// https://github.com/WICG/webpackage/issues/161 is resolved.
if (name_str != base::ToLowerASCII(name_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
base::StringPrintf(
"Request header name should be lower-cased. header name: %s",
name_str.as_string().c_str()));
@@ -153,8 +151,8 @@ bool ParseRequestMap(
// 4. If exchange’s headers contain a stateful header field, as defined in
// Section 4.1, return “invalid”. [spec text]
if (IsStatefulRequestHeader(name_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
base::StringPrintf(
"Exchange contains stateful request header. header name: %s",
name_str.as_string().c_str()));
@@ -166,14 +164,13 @@ bool ParseRequestMap(
return true;
}
-bool ParseResponseMap(
- const cbor::CBORValue& value,
- SignedExchangeHeader* out,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+bool ParseResponseMap(const cbor::CBORValue& value,
+ SignedExchangeHeader* out,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseResponseMap");
if (!value.is_map()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseResponseMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseResponseMap",
base::StringPrintf(
"Expected request map, got non-map type. Actual type: %d",
static_cast<int>(value.type())));
@@ -185,8 +182,8 @@ bool ParseResponseMap(
cbor::CBORValue(kStatusKey, cbor::CBORValue::Type::BYTE_STRING));
if (status_iter == response_map.end() ||
!status_iter->second.is_bytestring()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
":status is not found or not a bytestring.");
return false;
}
@@ -194,8 +191,8 @@ bool ParseResponseMap(
status_iter->second.GetBytestringAsString();
int response_code;
if (!base::StringToInt(response_code_str, &response_code)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
"Failed to parse status code to integer.");
return false;
}
@@ -203,8 +200,8 @@ bool ParseResponseMap(
for (const auto& it : response_map) {
if (!it.first.is_bytestring() || !it.second.is_bytestring()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap",
"Non-bytestring value in the response map.");
return false;
}
@@ -212,8 +209,8 @@ bool ParseResponseMap(
if (name_str == kStatusKey)
continue;
if (!net::HttpUtil::IsValidHeaderName(name_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseResponseMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseResponseMap",
base::StringPrintf("Invalid header name. header_name: %s",
name_str.as_string().c_str()));
return false;
@@ -222,8 +219,8 @@ bool ParseResponseMap(
// TODO(kouhei): Add spec ref here once
// https://github.com/WICG/webpackage/issues/161 is resolved.
if (name_str != base::ToLowerASCII(name_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseResponseMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseResponseMap",
base::StringPrintf(
"Response header name should be lower-cased. header_name: %s",
name_str.as_string().c_str()));
@@ -233,8 +230,8 @@ bool ParseResponseMap(
// 4. If exchange’s headers contain a stateful header field, as defined in
// Section 4.1, return “invalid”. [spec text]
if (IsStatefulResponseHeader(name_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseResponseMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseResponseMap",
base::StringPrintf(
"Exchange contains stateful response header. header_name: %s",
name_str.as_string().c_str()));
@@ -243,13 +240,13 @@ bool ParseResponseMap(
base::StringPiece value_str = it.second.GetBytestringAsString();
if (!net::HttpUtil::IsValidHeaderValue(value_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseRequestMap", error_message_callback, "Invalid header value.");
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseRequestMap", "Invalid header value.");
return false;
}
if (!out->AddResponseHeader(name_str, value_str)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "ParseResponseMap", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "ParseResponseMap",
base::StringPrintf("Duplicate header value. header_name: %s",
name_str.as_string().c_str()));
return false;
@@ -262,12 +259,12 @@ bool ParseResponseMap(
} // namespace
-constexpr size_t SignedExchangeHeader::kEncodedHeaderLengthInBytes;
+constexpr size_t SignedExchangeHeader::kEncodedLengthInBytes;
// static
-size_t SignedExchangeHeader::ParseHeadersLength(
+size_t SignedExchangeHeader::ParseEncodedLength(
base::span<const uint8_t> input) {
- DCHECK_EQ(input.size(), SignedExchangeHeader::kEncodedHeaderLengthInBytes);
+ DCHECK_EQ(input.size(), SignedExchangeHeader::kEncodedLengthInBytes);
return static_cast<size_t>(input[0]) << 16 |
static_cast<size_t>(input[1]) << 8 | static_cast<size_t>(input[2]);
}
@@ -275,21 +272,21 @@ size_t SignedExchangeHeader::ParseHeadersLength(
// static
base::Optional<SignedExchangeHeader> SignedExchangeHeader::Parse(
base::span<const uint8_t> input,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+ SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHeader::Parse");
cbor::CBORReader::DecoderError error;
base::Optional<cbor::CBORValue> value = cbor::CBORReader::Read(input, &error);
if (!value.has_value()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeader::Parse", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeader::Parse",
base::StringPrintf("Failed to decode CBORValue. CBOR error: %s",
cbor::CBORReader::ErrorCodeToString(error)));
return base::nullopt;
}
if (!value->is_array()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeader::Parse", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeader::Parse",
base::StringPrintf(
"Expected top-level CBORValue to be an array. Actual type : %d",
static_cast<int>(value->type())));
@@ -299,8 +296,8 @@ base::Optional<SignedExchangeHeader> SignedExchangeHeader::Parse(
const cbor::CBORValue::ArrayValue& top_level_array = value->GetArray();
constexpr size_t kTopLevelArraySize = 2;
if (top_level_array.size() != kTopLevelArraySize) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeader::Parse", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeader::Parse",
base::StringPrintf("Expected top-level array to have 2 elements. "
"Actual element count: %" PRIuS,
top_level_array.size()));
@@ -309,33 +306,33 @@ base::Optional<SignedExchangeHeader> SignedExchangeHeader::Parse(
SignedExchangeHeader ret;
- if (!ParseRequestMap(top_level_array[0], &ret, error_message_callback)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeader::Parse", error_message_callback,
+ if (!ParseRequestMap(top_level_array[0], &ret, devtools_proxy)) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeader::Parse",
"Failed to parse request map.");
return base::nullopt;
}
- if (!ParseResponseMap(top_level_array[1], &ret, error_message_callback)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeader::Parse", error_message_callback,
+ if (!ParseResponseMap(top_level_array[1], &ret, devtools_proxy)) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeader::Parse",
"Failed to parse response map.");
return base::nullopt;
}
auto signature_iter = ret.response_headers_.find(kSignature);
if (signature_iter == ret.response_headers_.end()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeader::Parse", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeader::Parse",
"No signature header found.");
return base::nullopt;
}
base::Optional<std::vector<SignedExchangeHeaderParser::Signature>>
signatures = SignedExchangeHeaderParser::ParseSignature(
- signature_iter->second, error_message_callback);
+ signature_iter->second, devtools_proxy);
if (!signatures || signatures->empty()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeader::Parse", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeader::Parse",
"Failed to parse signature.");
return base::nullopt;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_header.h b/chromium/content/browser/web_package/signed_exchange_header.h
index 7c31a43806f..e544f17994e 100644
--- a/chromium/content/browser/web_package/signed_exchange_header.h
+++ b/chromium/content/browser/web_package/signed_exchange_header.h
@@ -14,7 +14,6 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "content/browser/web_package/signed_exchange_header_parser.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/content_export.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
@@ -22,17 +21,18 @@
namespace content {
+class SignedExchangeDevToolsProxy;
+
// SignedExchangeHeader contains all information captured in signed exchange
// envelope but the payload.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html
class CONTENT_EXPORT SignedExchangeHeader {
public:
- static constexpr size_t kEncodedHeaderLengthInBytes = 3;
- // Parse big-endian encoded length of the following CBOR-encoded
- // signed exchange header.
+ static constexpr size_t kEncodedLengthInBytes = 3;
+ // Parse encoded length of the variable-length field in the signed exchange.
// Note: |input| must be pointing to a valid memory address that has at least
- // |kEncodedHeaderLengthInBytes|.
- static size_t ParseHeadersLength(base::span<const uint8_t> input);
+ // |kEncodedLengthInBytes|.
+ static size_t ParseEncodedLength(base::span<const uint8_t> input);
using HeaderMap = std::map<std::string, std::string>;
@@ -43,7 +43,7 @@ class CONTENT_EXPORT SignedExchangeHeader {
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cross-origin-trust
static base::Optional<SignedExchangeHeader> Parse(
base::span<const uint8_t> input,
- const signed_exchange_utils::LogCallback& error_message_callback);
+ SignedExchangeDevToolsProxy* devtools_proxy);
SignedExchangeHeader();
SignedExchangeHeader(const SignedExchangeHeader&);
SignedExchangeHeader(SignedExchangeHeader&&);
diff --git a/chromium/content/browser/web_package/signed_exchange_header_parser.cc b/chromium/content/browser/web_package/signed_exchange_header_parser.cc
index 310d29f4450..97cc0a4c7e3 100644
--- a/chromium/content/browser/web_package/signed_exchange_header_parser.cc
+++ b/chromium/content/browser/web_package/signed_exchange_header_parser.cc
@@ -195,7 +195,7 @@ class StructuredHeaderParser {
base::Optional<std::vector<SignedExchangeHeaderParser::Signature>>
SignedExchangeHeaderParser::ParseSignature(
base::StringPiece signature_str,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+ SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeHeaderParser::ParseSignature");
@@ -203,8 +203,8 @@ SignedExchangeHeaderParser::ParseSignature(
std::vector<ParameterisedLabel> values;
parser.ParseParameterisedLabelList(&values);
if (!parser.ParsedSuccessfully()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"Failed to parse signature header.");
return base::nullopt;
}
@@ -215,35 +215,35 @@ SignedExchangeHeaderParser::ParseSignature(
signatures.push_back(Signature());
Signature& sig = signatures.back();
sig.label = value.label;
- sig.sig = value.params["sig"];
+ sig.sig = value.params[kSig];
if (sig.sig.empty()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'sig' parameter is not set,");
return base::nullopt;
}
- sig.integrity = value.params["integrity"];
+ sig.integrity = value.params[kIntegrity];
if (sig.integrity.empty()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'integrity' parameter is not set.");
return base::nullopt;
}
- sig.cert_url = GURL(value.params["certUrl"]);
+ sig.cert_url = GURL(value.params[kCertUrl]);
if (!sig.cert_url.is_valid() || sig.cert_url.has_ref()) {
// TODO(https://crbug.com/819467) : When we will support "ed25519Key", the
// params may not have "certUrl".
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'certUrl' parameter is not a valid URL.");
return base::nullopt;
}
- const std::string cert_sha256_string = value.params["certSha256"];
+ const std::string cert_sha256_string = value.params[kCertSha256Key];
if (cert_sha256_string.size() != crypto::kSHA256Length) {
// TODO(https://crbug.com/819467) : When we will support "ed25519Key", the
// params may not have "certSha256".
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'certSha256' parameter is not a SHA-256 digest.");
return base::nullopt;
}
@@ -252,28 +252,28 @@ SignedExchangeHeaderParser::ParseSignature(
sig.cert_sha256 = std::move(cert_sha256);
// TODO(https://crbug.com/819467): Support ed25519key.
// sig.ed25519_key = value.params["ed25519Key"];
- sig.validity_url = GURL(value.params["validityUrl"]);
+ sig.validity_url = GURL(value.params[kValidityUrlKey]);
if (!sig.validity_url.is_valid()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'validityUrl' parameter is not a valid URL.");
return base::nullopt;
}
if (sig.validity_url.has_ref()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'validityUrl' parameter can't have a fragment.");
return base::nullopt;
}
- if (!base::StringToUint64(value.params["date"], &sig.date)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ if (!base::StringToUint64(value.params[kDateKey], &sig.date)) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'date' parameter is not a number.");
return base::nullopt;
}
- if (!base::StringToUint64(value.params["expires"], &sig.expires)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeHeaderParser::ParseSignature", error_message_callback,
+ if (!base::StringToUint64(value.params[kExpiresKey], &sig.expires)) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeHeaderParser::ParseSignature",
"'expires' parameter is not a number.");
return base::nullopt;
}
@@ -286,7 +286,7 @@ SignedExchangeHeaderParser::ParseSignature(
// static
bool SignedExchangeHeaderParser::GetVersionParamFromContentType(
base::StringPiece content_type,
- base::Optional<std::string>* version_param) {
+ base::Optional<SignedExchangeVersion>* version_param) {
DCHECK(version_param);
StructuredHeaderParser parser(content_type);
ParameterisedLabel parameterised_label;
@@ -297,7 +297,12 @@ bool SignedExchangeHeaderParser::GetVersionParamFromContentType(
if (it == parameterised_label.params.end()) {
*version_param = base::nullopt;
} else {
- *version_param = it->second;
+ if (it->second == "b0")
+ *version_param = SignedExchangeVersion::kB0;
+ else if (it->second == "b1")
+ *version_param = SignedExchangeVersion::kB1;
+ else
+ return false;
}
return true;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_header_parser.h b/chromium/content/browser/web_package/signed_exchange_header_parser.h
index 68b23813eb1..01697eb5362 100644
--- a/chromium/content/browser/web_package/signed_exchange_header_parser.h
+++ b/chromium/content/browser/web_package/signed_exchange_header_parser.h
@@ -13,13 +13,15 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string_piece.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/common/content_export.h"
#include "net/base/hash_value.h"
#include "url/gurl.h"
namespace content {
+class SignedExchangeDevToolsProxy;
+
// Provide parsers for signed-exchange headers.
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html
class CONTENT_EXPORT SignedExchangeHeaderParser {
@@ -45,14 +47,14 @@ class CONTENT_EXPORT SignedExchangeHeaderParser {
// https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#signature-header
static base::Optional<std::vector<Signature>> ParseSignature(
base::StringPiece signature_str,
- const signed_exchange_utils::LogCallback& error_message_callback);
+ SignedExchangeDevToolsProxy* devtools_proxy);
// Parses |content_type| to get the value of "v=" parameter of the signed
- // exchange. Example: "b0" for "application/signed-exchange;v=b0". Returns
- // false if failed to parse.
+ // exchange, and converts to SignedExchangeVersion. Returns false if failed to
+ // parse.
static bool GetVersionParamFromContentType(
base::StringPiece content_type,
- base::Optional<std::string>* version_param);
+ base::Optional<SignedExchangeVersion>* version_param);
};
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc b/chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc
index a433f84d124..32f912e9490 100644
--- a/chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_header_parser_unittest.cc
@@ -5,7 +5,6 @@
#include "content/browser/web_package/signed_exchange_header_parser.h"
#include "base/callback.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -58,7 +57,7 @@ TEST_F(SignedExchangeHeaderParserTest, ParseSignature) {
0x00, 0x63, 0xf7, 0xd0, 0xe5, 0x62, 0x9e, 0x1f, 0x11, 0x7c}};
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
ASSERT_TRUE(signatures.has_value());
ASSERT_EQ(signatures->size(), 2u);
@@ -98,7 +97,7 @@ TEST_F(SignedExchangeHeaderParserTest, IncompleteSignature) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -114,7 +113,7 @@ TEST_F(SignedExchangeHeaderParserTest, DuplicatedParam) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -129,7 +128,7 @@ TEST_F(SignedExchangeHeaderParserTest, InvalidCertURL) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -144,7 +143,7 @@ TEST_F(SignedExchangeHeaderParserTest, CertURLWithFragment) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -159,7 +158,7 @@ TEST_F(SignedExchangeHeaderParserTest, RelativeCertURL) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -174,7 +173,7 @@ TEST_F(SignedExchangeHeaderParserTest, InvalidValidityUrl) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -189,7 +188,7 @@ TEST_F(SignedExchangeHeaderParserTest, ValidityUrlWithFragment) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -204,7 +203,7 @@ TEST_F(SignedExchangeHeaderParserTest, RelativeValidityUrl) {
" certSha256=*W7uB969dFW3Mb5ZefPS9Tq5ZbH5iSmOILpjv2qEArmI;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
@@ -219,20 +218,20 @@ TEST_F(SignedExchangeHeaderParserTest, InvalidCertSHA256) {
" certSha256=*W7uB969dFW3Mb5ZefPS9;"
" date=1511128380; expires=1511733180";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
TEST_F(SignedExchangeHeaderParserTest, OpenQuoteAtEnd) {
const char hdr_string[] = "sig1; sig=\"";
auto signatures = SignedExchangeHeaderParser::ParseSignature(
- hdr_string, signed_exchange_utils::LogCallback());
+ hdr_string, nullptr /* devtools_proxy */);
EXPECT_FALSE(signatures.has_value());
}
TEST_F(SignedExchangeHeaderParserTest, VersionParam_None) {
const char content_type[] = "application/signed-exchange";
- base::Optional<std::string> version;
+ base::Optional<SignedExchangeVersion> version;
EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
content_type, &version));
EXPECT_FALSE(version);
@@ -240,43 +239,43 @@ TEST_F(SignedExchangeHeaderParserTest, VersionParam_None) {
TEST_F(SignedExchangeHeaderParserTest, VersionParam_NoneWithSemicolon) {
const char content_type[] = "application/signed-exchange;";
- base::Optional<std::string> version;
+ base::Optional<SignedExchangeVersion> version;
EXPECT_FALSE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
content_type, &version));
}
TEST_F(SignedExchangeHeaderParserTest, VersionParam_EmptyString) {
const char content_type[] = "application/signed-exchange;v=";
- base::Optional<std::string> version;
+ base::Optional<SignedExchangeVersion> version;
EXPECT_FALSE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
content_type, &version));
}
TEST_F(SignedExchangeHeaderParserTest, VersionParam_Simple) {
const char content_type[] = "application/signed-exchange;v=b0";
- base::Optional<std::string> version;
+ base::Optional<SignedExchangeVersion> version;
EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
content_type, &version));
ASSERT_TRUE(version);
- EXPECT_EQ(*version, "b0");
+ EXPECT_EQ(*version, SignedExchangeVersion::kB0);
}
TEST_F(SignedExchangeHeaderParserTest, VersionParam_SimpleWithSpace) {
- const char content_type[] = "application/signed-exchange; v=b0";
- base::Optional<std::string> version;
+ const char content_type[] = "application/signed-exchange; v=b1";
+ base::Optional<SignedExchangeVersion> version;
EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
content_type, &version));
ASSERT_TRUE(version);
- EXPECT_EQ(*version, "b0");
+ EXPECT_EQ(*version, SignedExchangeVersion::kB1);
}
TEST_F(SignedExchangeHeaderParserTest, VersionParam_SimpleWithDoublequotes) {
const char content_type[] = "application/signed-exchange;v=\"b0\"";
- base::Optional<std::string> version;
+ base::Optional<SignedExchangeVersion> version;
EXPECT_TRUE(SignedExchangeHeaderParser::GetVersionParamFromContentType(
content_type, &version));
ASSERT_TRUE(version);
- EXPECT_EQ(*version, "b0");
+ EXPECT_EQ(*version, SignedExchangeVersion::kB0);
}
} // namespace content
diff --git a/chromium/content/browser/web_package/signed_exchange_header_unittest.cc b/chromium/content/browser/web_package/signed_exchange_header_unittest.cc
index a12c0c7f2a4..9c532156460 100644
--- a/chromium/content/browser/web_package/signed_exchange_header_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_header_unittest.cc
@@ -11,7 +11,6 @@
#include "components/cbor/cbor_values.h"
#include "components/cbor/cbor_writer.h"
#include "content/browser/web_package/signed_exchange_consts.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/common/content_paths.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -50,14 +49,14 @@ base::Optional<SignedExchangeHeader> GenerateHeaderAndParse(
auto serialized = cbor::CBORWriter::Write(cbor::CBORValue(std::move(array)));
return SignedExchangeHeader::Parse(
base::make_span(serialized->data(), serialized->size()),
- signed_exchange_utils::LogCallback());
+ nullptr /* devtools_proxy */);
}
} // namespace
-TEST(SignedExchangeHeaderTest, ParseHeaderLength) {
+TEST(SignedExchangeHeaderTest, ParseEncodedLength) {
constexpr struct {
- uint8_t bytes[SignedExchangeHeader::kEncodedHeaderLengthInBytes];
+ uint8_t bytes[SignedExchangeHeader::kEncodedLengthInBytes];
size_t expected;
} kTestCases[] = {
{{0x00, 0x00, 0x01}, 1u}, {{0x01, 0xe2, 0x40}, 123456u},
@@ -66,14 +65,14 @@ TEST(SignedExchangeHeaderTest, ParseHeaderLength) {
int test_element_index = 0;
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(testing::Message() << "testing case " << test_element_index++);
- EXPECT_EQ(SignedExchangeHeader::ParseHeadersLength(test_case.bytes),
+ EXPECT_EQ(SignedExchangeHeader::ParseEncodedLength(test_case.bytes),
test_case.expected);
}
}
TEST(SignedExchangeHeaderTest, ParseGoldenFile) {
base::FilePath test_htxg_path;
- PathService::Get(content::DIR_TEST_DATA, &test_htxg_path);
+ base::PathService::Get(content::DIR_TEST_DATA, &test_htxg_path);
test_htxg_path = test_htxg_path.AppendASCII("htxg").AppendASCII(
"test.example.org_test.htxg");
@@ -81,18 +80,17 @@ TEST(SignedExchangeHeaderTest, ParseGoldenFile) {
ASSERT_TRUE(base::ReadFileToString(test_htxg_path, &contents));
auto* contents_bytes = reinterpret_cast<const uint8_t*>(contents.data());
- ASSERT_GT(contents.size(), SignedExchangeHeader::kEncodedHeaderLengthInBytes);
- size_t header_size = SignedExchangeHeader::ParseHeadersLength(base::make_span(
- contents_bytes, SignedExchangeHeader::kEncodedHeaderLengthInBytes));
+ ASSERT_GT(contents.size(), SignedExchangeHeader::kEncodedLengthInBytes);
+ size_t header_size = SignedExchangeHeader::ParseEncodedLength(base::make_span(
+ contents_bytes, SignedExchangeHeader::kEncodedLengthInBytes));
ASSERT_GT(contents.size(),
- SignedExchangeHeader::kEncodedHeaderLengthInBytes + header_size);
+ SignedExchangeHeader::kEncodedLengthInBytes + header_size);
const auto cbor_bytes = base::make_span<const uint8_t>(
- contents_bytes + SignedExchangeHeader::kEncodedHeaderLengthInBytes,
+ contents_bytes + SignedExchangeHeader::kEncodedLengthInBytes,
header_size);
const base::Optional<SignedExchangeHeader> header =
- SignedExchangeHeader::Parse(cbor_bytes,
- signed_exchange_utils::LogCallback());
+ SignedExchangeHeader::Parse(cbor_bytes, nullptr /* devtools_proxy */);
ASSERT_TRUE(header.has_value());
EXPECT_EQ(header->request_url(), GURL("https://test.example.org/test/"));
EXPECT_EQ(header->request_method(), "GET");
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
index bbc94fbeaf9..cf1322d96aa 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.cc
@@ -20,6 +20,10 @@
#include "crypto/signature_verifier.h"
#include "net/cert/asn1_util.h"
#include "net/cert/x509_util.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
namespace content {
@@ -138,48 +142,65 @@ base::Optional<cbor::CBORValue> GenerateSignedMessageCBOR(
return cbor::CBORValue(map);
}
-bool VerifySignature(
- base::span<const uint8_t> sig,
- base::span<const uint8_t> msg,
- scoped_refptr<net::X509Certificate> cert,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+bool VerifySignature(base::span<const uint8_t> sig,
+ base::span<const uint8_t> msg,
+ scoped_refptr<net::X509Certificate> cert,
+ SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"), "VerifySignature");
base::StringPiece spki;
if (!net::asn1::ExtractSPKIFromDERCert(
net::x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()),
&spki)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "VerifySignature", error_message_callback, "Failed to extract SPKI.");
+ TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"), "VerifySignature",
+ "error", "Failed to extract SPKI.");
return false;
}
- size_t size_bits;
- net::X509Certificate::PublicKeyType type;
- net::X509Certificate::GetPublicKeyInfo(cert->cert_buffer(), &size_bits,
- &type);
- if (type != net::X509Certificate::kPublicKeyTypeRSA) {
- // TODO(crbug.com/803774): Add support for ecdsa_secp256r1_sha256 and
- // ecdsa_secp384r1_sha384.
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "VerifySignature", error_message_callback,
- base::StringPrintf("Unsupported public key type: %d", type));
+ crypto::SignatureVerifier::SignatureAlgorithm algorithm;
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki.data()), spki.size());
+ bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
+ if (!pkey || CBS_len(&cbs) != 0) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "VerifySignature", "Failed to parse public key.");
return false;
}
+ switch (EVP_PKEY_id(pkey.get())) {
+ case EVP_PKEY_RSA:
+ algorithm = crypto::SignatureVerifier::RSA_PSS_SHA256;
+ break;
+ case EVP_PKEY_EC: {
+ const EC_GROUP* group =
+ EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey.get()));
+ switch (EC_GROUP_get_curve_name(group)) {
+ case NID_X9_62_prime256v1:
+ algorithm = crypto::SignatureVerifier::ECDSA_SHA256;
+ break;
+ default:
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "VerifySignature", "Unsupported EC group.");
+ return false;
+ }
+ break;
+ }
+ default:
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "VerifySignature", "Unsupported public key type.");
+ return false;
+ }
- // TODO(crbug.com/803774): This is missing the digitalSignature key usage bit
- // check.
crypto::SignatureVerifier verifier;
- if (!verifier.VerifyInit(
- crypto::SignatureVerifier::RSA_PSS_SHA256, sig.data(), sig.size(),
- reinterpret_cast<const uint8_t*>(spki.data()), spki.size())) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "VerifySignature", error_message_callback, "VerifyInit failed.");
+ if (!net::x509_util::SignatureVerifierInitWithCertificate(
+ &verifier, algorithm, sig, cert->cert_buffer())) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "VerifySignature",
+ "SignatureVerifierInitWithCertificate failed.");
return false;
}
- verifier.VerifyUpdate(msg.data(), msg.size());
+ verifier.VerifyUpdate(msg);
if (!verifier.VerifyFinal()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "VerifySignature", error_message_callback, "VerifyFinal failed.");
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "VerifySignature", "VerifyFinal failed.");
return false;
}
TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"), "VerifySignature");
@@ -264,13 +285,13 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
const SignedExchangeHeader& header,
scoped_refptr<net::X509Certificate> certificate,
const base::Time& verification_time,
- const signed_exchange_utils::LogCallback& error_message_callback) {
+ SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangeSignatureVerifier::Verify");
if (!VerifyTimestamps(header, verification_time)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeSignatureVerifier::Verify", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
base::StringPrintf(
"Invalid timestamp. creation_time: %" PRIu64
", expires_time: %" PRIu64 ", verification_time: %" PRIu64,
@@ -280,15 +301,15 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
}
if (!certificate) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeSignatureVerifier::Verify", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
"No certificate set.");
return Result::kErrNoCertificate;
}
if (!header.signature().cert_sha256.has_value()) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeSignatureVerifier::Verify", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
"No certSha256 set.");
return Result::kErrNoCertificateSHA256;
}
@@ -297,16 +318,16 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
if (*header.signature().cert_sha256 !=
net::X509Certificate::CalculateFingerprint256(
certificate->cert_buffer())) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeSignatureVerifier::Verify", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
"certSha256 mismatch.");
return Result::kErrCertificateSHA256Mismatch;
}
auto message = GenerateSignedMessage(header);
if (!message) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeSignatureVerifier::Verify", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
"Failed to reconstruct signed message.");
return Result::kErrInvalidSignatureFormat;
}
@@ -315,16 +336,16 @@ SignedExchangeSignatureVerifier::Result SignedExchangeSignatureVerifier::Verify(
if (!VerifySignature(
base::make_span(reinterpret_cast<const uint8_t*>(sig.data()),
sig.size()),
- *message, certificate, error_message_callback)) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeSignatureVerifier::Verify", error_message_callback,
+ *message, certificate, devtools_proxy)) {
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
"Failed to verify signature \"sig\".");
return Result::kErrSignatureVerificationFailed;
}
if (!base::EqualsCaseInsensitiveASCII(header.signature().integrity, "mi")) {
- signed_exchange_utils::RunErrorMessageCallbackAndEndTraceEvent(
- "SignedExchangeSignatureVerifier::Verify", error_message_callback,
+ signed_exchange_utils::ReportErrorAndEndTraceEvent(
+ devtools_proxy, "SignedExchangeSignatureVerifier::Verify",
"The current implemention only supports \"mi\" integrity scheme.");
return Result::kErrInvalidSignatureIntegrity;
}
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_verifier.h b/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
index 42260d2d767..fe8da78f44a 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/common/content_export.h"
#include "net/cert/x509_certificate.h"
@@ -23,6 +22,7 @@ class Time;
namespace content {
class SignedExchangeHeader;
+class SignedExchangeDevToolsProxy;
// SignedExchangeSignatureVerifier verifies the signature of the given
// signed exchange. This is done by reconstructing the signed message
@@ -47,11 +47,10 @@ class CONTENT_EXPORT SignedExchangeSignatureVerifier final {
kErrInvalidTimestamp
};
- static Result Verify(
- const SignedExchangeHeader& header,
- scoped_refptr<net::X509Certificate> certificate,
- const base::Time& verification_time,
- const signed_exchange_utils::LogCallback& error_message_callback);
+ static Result Verify(const SignedExchangeHeader& header,
+ scoped_refptr<net::X509Certificate> certificate,
+ const base::Time& verification_time,
+ SignedExchangeDevToolsProxy* devtools_proxy);
static base::Optional<std::vector<uint8_t>> EncodeCanonicalExchangeHeaders(
const SignedExchangeHeader& header);
diff --git a/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc b/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc
index a2d952aba1a..b902e1e9f9b 100644
--- a/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc
@@ -7,7 +7,6 @@
#include "base/callback.h"
#include "content/browser/web_package/signed_exchange_header.h"
#include "content/browser/web_package/signed_exchange_header_parser.h"
-#include "content/browser/web_package/signed_exchange_utils.h"
#include "net/cert/x509_certificate.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -64,7 +63,7 @@ const uint64_t kSignatureHeaderDate = 1517892341;
const uint64_t kSignatureHeaderExpires = 1517895941;
// clang-format off
-constexpr char kSignatureHeader[] =
+constexpr char kSignatureHeaderRSA[] =
"sig; "
"sig=*RhjjWuXi87riQUu90taBHFJgTo8XBhiCe9qTJMP7/XVPu2diRGipo06HoGsyXkidHiiW"
"743JgoNmO7CjfeVXLXQgKDxtGidATtPsVadAT4JpBDZJWSUg5qAbWcASXjyO38Uhq9gJkeu4w"
@@ -78,6 +77,32 @@ constexpr char kSignatureHeader[] =
"date=1517892341; expires=1517895941";
// clang-format on
+// See content/testdata/htxg/README on how to generate this data.
+// clang-format off
+constexpr char kSignatureHeaderECDSAP256[] =
+ "label; "
+ "sig=*MEYCIQDQYQAHAlpznkP/btvuNnvGY5ycO+NOOTFXsoBjF22UhAIhAMyzyMikudaQeIPYB"
+ "fh2JdqZVBwgsQ6a3Cn8lFA0XYGW; "
+ "validityUrl=\"https://example.com/resource.validity.msg\"; "
+ "integrity=\"mi\"; "
+ "certUrl=\"https://example.com/cert.msg\"; "
+ "certSha256=*CfDj40tr5B7oo6IaWwQF2L1uDgsHH0fA2YOCB7E0tAQ; "
+ "date=1517892341; expires=1517895941";
+// clang-format on
+
+// See content/testdata/htxg/README on how to generate this data.
+// clang-format off
+constexpr char kSignatureHeaderECDSAP384[] =
+ "label; "
+ "sig=*MGQCMDtOqWBsWjx1+WZta9tBpuuMJMLMwp8/eHu+PwNw95qCMMjD1xJiLIm0HUtFzdzSC"
+ "wIwVxSUD9IB2t4JIHz6IJPddqR1ex38kkSvOYSmFEwqVPRM1sqAcEtvwdpSU+cLJYbS; "
+ "validityUrl=\"https://example.com/resource.validity.msg\"; "
+ "integrity=\"mi\"; "
+ "certUrl=\"https://example.com/cert.msg\"; "
+ "certSha256=*8X8y8nj8vDJHSSa0cxn+TCu+8zGpIJfbdzAnd5cW+jA; "
+ "date=1517892341; expires=1517895941";
+// clang-format on
+
// |expires| (1518497142) is more than 7 days (604800 seconds) after |date|
// (1517892341).
// clang-format off
@@ -95,7 +120,7 @@ constexpr char kSignatureHeaderInvalidExpires[] =
"date=1517892341; expires=1518497142";
// clang-format on
-constexpr char kCertPEM[] = R"(
+constexpr char kCertPEMRSA[] = R"(
-----BEGIN CERTIFICATE-----
MIID9zCCAt+gAwIBAgIUde2ndSB4271TAGDk0Ft+WuCCGnMwDQYJKoZIhvcNAQEL
BQAwUDELMAkGA1UEBhMCSlAxEjAQBgNVBAgTCU1pbmF0by1rdTEOMAwGA1UEBxMF
@@ -121,18 +146,137 @@ U0/55zFz2OzNoAHaoBzMRxn4ZSc3+lxl0K1+cCP8ivhwkxdz/vhz5RfOjpSinxqt
wYxI2+BLS6X5NpI=
-----END CERTIFICATE-----)";
-TEST(SignedExchangeSignatureVerifier, Verify) {
- base::Time verification_time =
- base::Time::UnixEpoch() +
- base::TimeDelta::FromSeconds(kSignatureHeaderDate);
+constexpr char kCertPEMECDSAP256[] = R"(
+-----BEGIN CERTIFICATE-----
+MIICQzCCASsCAQEwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxEzARBgNV
+BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoM
+B1Rlc3QgQ0ExFTATBgNVBAMMDFRlc3QgUm9vdCBDQTAeFw0xODAzMjMwNDU3MzRa
+Fw0xOTAzMTgwNDU3MzRaMDcxGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5vcmcxDTAL
+BgNVBAoMBFRlc3QxCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAECQYn3HDPPhtMv2hzyjI7E3FU89EjnzTtvLd9OP55GLAsaE/FCTWbx6rKOxF7
+O4jP0N3PsIzr+nT1lIix+HpxujANBgkqhkiG9w0BAQsFAAOCAQEAhKdVMvKm7gBz
+af6nfCkLGRo56KJasi6lJh2byF17vdqq+mSXR+jHZtsRsRZJyl+C+jaSzrT0TnMA
+kLg+U4ZnKZD5sTo7TWnRlTA4G4tOrWaq1tn89FWqe+hbvn6dEyTZ1XFPaO6hzeNH
+ZM5H+bIpngvGmP1lf7K6PtC3Tx/S938zBdQrfKz/4ZB0S5cmIyIUBnlj3PDWtLsB
+KS4wvSnjPj1EyVKxTQH1PdB2NqC4eT8bgFcryNWrkMOWdOUNhGWB55nVwI8yNPQO
+4OrKJLsDZir3v7dzcU9U1erBp4+udGFIfW86g24FX1gn3SavtO6lZt59AFLptyQ6
+LWh1CMv1aQ==
+-----END CERTIFICATE-----)";
+
+constexpr char kCertPEMECDSAP384[] = R"(
+-----BEGIN CERTIFICATE-----
+MIICYDCCAUgCAQEwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxEzARBgNV
+BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoM
+B1Rlc3QgQ0ExFTATBgNVBAMMDFRlc3QgUm9vdCBDQTAeFw0xODA0MDkwMTUyMzVa
+Fw0xOTA0MDQwMTUyMzVaMDcxGTAXBgNVBAMMEHRlc3QuZXhhbXBsZS5vcmcxDTAL
+BgNVBAoMBFRlc3QxCzAJBgNVBAYTAlVTMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE
+YK0FPc6B2UkDO3GHS95PLss9e82f8RdQDIZE9UPUSOJ1UISOT19j/SJq3gyoY+pK
+J818LhVe+ywgdH+tKosO6v1l2o/EffIRDjCfN/aSUuQjkkSwgyL62/9687+486z6
+MA0GCSqGSIb3DQEBCwUAA4IBAQB61Q+/68hsD5OapG+2CDsJI+oR91H+Jv+tRMby
+of47O0hJGISuAB9xcFhIcMKwBReODpBmzwSO713NNU/oaG/XysHH1TNZZodTtWD9
+Z1g5AJamfwvFS+ObqzOtyFUdFS4NBAE4lXi5XnHa2hU2Bkm+abVYLqyAGw1kh2ES
+DGC2vA1lb2Uy9bgLCYYkZoESjb/JYRQjCmqlwYKOozU7ZbIe3zJPjRWYP1Tuany5
++rYllWk/DJlMVjs/fbf0jj32vrevCgul43iWMgprOw1ncuK8l5nND/o5aN2mwMDw
+Xhe5DP7VATeQq3yGV3ps+rCTHDP6qSHDEWP7DqHQdSsxtI0E
+-----END CERTIFICATE-----)";
+
+class SignedExchangeSignatureVerifierTest : public ::testing::Test {
+ protected:
+ SignedExchangeSignatureVerifierTest() {}
+
+ const base::Time VerificationTime() {
+ return base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kSignatureHeaderDate);
+ }
+
+ void TestVerifierGivenValidInput(
+ const SignedExchangeHeader& header,
+ scoped_refptr<net::X509Certificate> certificate) {
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
+ SignedExchangeSignatureVerifier::Verify(
+ header, certificate, VerificationTime(),
+ nullptr /* devtools_proxy */));
+
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
+ SignedExchangeSignatureVerifier::Verify(
+ header, certificate,
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kSignatureHeaderDate - 1),
+ nullptr /* devtools_proxy */
+ ));
+
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
+ SignedExchangeSignatureVerifier::Verify(
+ header, certificate,
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kSignatureHeaderExpires),
+ nullptr /* devtools_proxy */
+ ));
+
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
+ SignedExchangeSignatureVerifier::Verify(
+ header, certificate,
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromSeconds(kSignatureHeaderExpires + 1),
+ nullptr /* devtools_proxy */
+ ));
+
+ SignedExchangeHeader invalid_expires_header(header);
+ auto invalid_expires_signature = SignedExchangeHeaderParser::ParseSignature(
+ kSignatureHeaderInvalidExpires, nullptr /* devtools_proxy */);
+ ASSERT_TRUE(invalid_expires_signature.has_value());
+ ASSERT_EQ(1u, invalid_expires_signature->size());
+ invalid_expires_header.SetSignatureForTesting(
+ (*invalid_expires_signature)[0]);
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
+ SignedExchangeSignatureVerifier::Verify(
+ invalid_expires_header, certificate, VerificationTime(),
+ nullptr /* devtools_proxy */
+ ));
+
+ SignedExchangeHeader corrupted_header(header);
+ corrupted_header.set_request_url(GURL("https://example.com/bad.html"));
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::
+ kErrSignatureVerificationFailed,
+ SignedExchangeSignatureVerifier::Verify(
+ corrupted_header, certificate, VerificationTime(),
+ nullptr /* devtools_proxy */
+ ));
+
+ SignedExchangeHeader badsig_header(header);
+ SignedExchangeHeaderParser::Signature badsig = header.signature();
+ badsig.sig[0]++;
+ badsig_header.SetSignatureForTesting(badsig);
+ EXPECT_EQ(SignedExchangeSignatureVerifier::Result::
+ kErrSignatureVerificationFailed,
+ SignedExchangeSignatureVerifier::Verify(
+ badsig_header, certificate, VerificationTime(),
+ nullptr /* devtools_proxy */
+ ));
+
+ SignedExchangeHeader badsigsha256_header(header);
+ SignedExchangeHeaderParser::Signature badsigsha256 = header.signature();
+ badsigsha256.cert_sha256->data[0]++;
+ badsigsha256_header.SetSignatureForTesting(badsigsha256);
+ EXPECT_EQ(
+ SignedExchangeSignatureVerifier::Result::kErrCertificateSHA256Mismatch,
+ SignedExchangeSignatureVerifier::Verify(badsigsha256_header,
+ certificate, VerificationTime(),
+ nullptr /* devtools_proxy */
+ ));
+ }
+};
+
+TEST_F(SignedExchangeSignatureVerifierTest, VerifyRSA) {
auto signature = SignedExchangeHeaderParser::ParseSignature(
- kSignatureHeader, signed_exchange_utils::LogCallback());
+ kSignatureHeaderRSA, nullptr /* devtools_proxy */);
ASSERT_TRUE(signature.has_value());
ASSERT_EQ(1u, signature->size());
net::CertificateList certlist =
net::X509Certificate::CreateCertificateListFromBytes(
- kCertPEM, arraysize(kCertPEM), net::X509Certificate::FORMAT_AUTO);
+ kCertPEMRSA, base::size(kCertPEMRSA),
+ net::X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1u, certlist.size());
SignedExchangeHeader header;
@@ -145,73 +289,63 @@ TEST(SignedExchangeSignatureVerifier, Verify) {
"mi", "mi-sha256=4ld4G-h-sQSoLBD39ndIO15O_82NXSzq9UMFEYI02JQ");
header.SetSignatureForTesting((*signature)[0]);
- auto certificate = certlist[0];
-
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
- SignedExchangeSignatureVerifier::Verify(
- header, certificate, verification_time,
- signed_exchange_utils::LogCallback()));
-
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
- SignedExchangeSignatureVerifier::Verify(
- header, certificate,
- base::Time::UnixEpoch() +
- base::TimeDelta::FromSeconds(kSignatureHeaderDate - 1),
- signed_exchange_utils::LogCallback()));
-
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kSuccess,
- SignedExchangeSignatureVerifier::Verify(
- header, certificate,
- base::Time::UnixEpoch() +
- base::TimeDelta::FromSeconds(kSignatureHeaderExpires),
- signed_exchange_utils::LogCallback()));
-
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
- SignedExchangeSignatureVerifier::Verify(
- header, certificate,
- base::Time::UnixEpoch() +
- base::TimeDelta::FromSeconds(kSignatureHeaderExpires + 1),
- signed_exchange_utils::LogCallback()));
-
- SignedExchangeHeader invalid_expires_header(header);
- auto invalid_expires_signature = SignedExchangeHeaderParser::ParseSignature(
- kSignatureHeaderInvalidExpires, signed_exchange_utils::LogCallback());
- ASSERT_TRUE(invalid_expires_signature.has_value());
- ASSERT_EQ(1u, invalid_expires_signature->size());
- invalid_expires_header.SetSignatureForTesting(
- (*invalid_expires_signature)[0]);
- EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrInvalidTimestamp,
- SignedExchangeSignatureVerifier::Verify(
- invalid_expires_header, certificate, verification_time,
- signed_exchange_utils::LogCallback()));
-
- SignedExchangeHeader corrupted_header(header);
- corrupted_header.set_request_url(GURL("https://example.com/bad.html"));
- EXPECT_EQ(
- SignedExchangeSignatureVerifier::Result::kErrSignatureVerificationFailed,
- SignedExchangeSignatureVerifier::Verify(
- corrupted_header, certificate, verification_time,
- signed_exchange_utils::LogCallback()));
-
- SignedExchangeHeader badsig_header(header);
- SignedExchangeHeaderParser::Signature badsig = header.signature();
- badsig.sig[0]++;
- badsig_header.SetSignatureForTesting(badsig);
+ TestVerifierGivenValidInput(header, certlist[0]);
+}
+
+TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP256) {
+ auto signature = SignedExchangeHeaderParser::ParseSignature(
+ kSignatureHeaderECDSAP256, nullptr /* devtools_proxy */);
+ ASSERT_TRUE(signature.has_value());
+ ASSERT_EQ(1u, signature->size());
+
+ net::CertificateList certlist =
+ net::X509Certificate::CreateCertificateListFromBytes(
+ kCertPEMECDSAP256, base::size(kCertPEMECDSAP256),
+ net::X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1u, certlist.size());
+
+ SignedExchangeHeader header;
+ header.set_request_method("GET");
+ header.set_request_url(GURL("https://test.example.org/test/"));
+ header.set_response_code(net::HTTP_OK);
+ header.AddResponseHeader("content-type", "text/html; charset=utf-8");
+ header.AddResponseHeader("content-encoding", "mi-sha256");
+ header.AddResponseHeader(
+ "mi", "mi-sha256=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI");
+
+ header.SetSignatureForTesting((*signature)[0]);
+
+ TestVerifierGivenValidInput(header, certlist[0]);
+}
+
+TEST_F(SignedExchangeSignatureVerifierTest, VerifyECDSAP384) {
+ auto signature = SignedExchangeHeaderParser::ParseSignature(
+ kSignatureHeaderECDSAP384, nullptr /* devtools_proxy */);
+ ASSERT_TRUE(signature.has_value());
+ ASSERT_EQ(1u, signature->size());
+
+ net::CertificateList certlist =
+ net::X509Certificate::CreateCertificateListFromBytes(
+ kCertPEMECDSAP384, base::size(kCertPEMECDSAP384),
+ net::X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1u, certlist.size());
+
+ SignedExchangeHeader header;
+ header.set_request_method("GET");
+ header.set_request_url(GURL("https://test.example.org/test/"));
+ header.set_response_code(net::HTTP_OK);
+ header.AddResponseHeader("content-type", "text/html; charset=utf-8");
+ header.AddResponseHeader("content-encoding", "mi-sha256");
+ header.AddResponseHeader(
+ "mi", "mi-sha256=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RIG");
+
+ header.SetSignatureForTesting((*signature)[0]);
+
EXPECT_EQ(
SignedExchangeSignatureVerifier::Result::kErrSignatureVerificationFailed,
- SignedExchangeSignatureVerifier::Verify(
- badsig_header, certificate, verification_time,
- signed_exchange_utils::LogCallback()));
-
- SignedExchangeHeader badsigsha256_header(header);
- SignedExchangeHeaderParser::Signature badsigsha256 = header.signature();
- badsigsha256.cert_sha256->data[0]++;
- badsigsha256_header.SetSignatureForTesting(badsigsha256);
- EXPECT_EQ(
- SignedExchangeSignatureVerifier::Result::kErrCertificateSHA256Mismatch,
- SignedExchangeSignatureVerifier::Verify(
- badsigsha256_header, certificate, verification_time,
- signed_exchange_utils::LogCallback()));
+ SignedExchangeSignatureVerifier::Verify(header, certlist[0],
+ VerificationTime(),
+ nullptr /* devtools_proxy */));
}
} // namespace
diff --git a/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.cc b/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.cc
index ce2bce7b937..08476ba6348 100644
--- a/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.cc
+++ b/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.cc
@@ -7,6 +7,7 @@
#include "base/feature_list.h"
#include "content/browser/loader/resource_requester_info.h"
#include "content/browser/loader/url_loader_factory_impl.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/common/content_features.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
@@ -20,7 +21,7 @@ SignedExchangeURLLoaderFactoryForNonNetworkService::
: resource_context_(resource_context),
url_request_context_getter_(url_request_context_getter) {
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
- DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
+ DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
}
SignedExchangeURLLoaderFactoryForNonNetworkService::
@@ -50,6 +51,11 @@ void SignedExchangeURLLoaderFactoryForNonNetworkService::CreateLoaderAndStart(
std::move(client), traffic_annotation);
}
+void SignedExchangeURLLoaderFactoryForNonNetworkService::Clone(
+ network::mojom::URLLoaderFactoryRequest request) {
+ NOTREACHED();
+}
+
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
SignedExchangeURLLoaderFactoryForNonNetworkService::Clone() {
NOTREACHED();
diff --git a/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h b/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h
index e101f3d060e..f29ecdb4fe2 100644
--- a/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h
+++ b/chromium/content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h
@@ -34,6 +34,7 @@ class SignedExchangeURLLoaderFactoryForNonNetworkService
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override;
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
private:
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.cc b/chromium/content/browser/web_package/signed_exchange_utils.cc
index 5fa03263441..4086fd67a6c 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.cc
+++ b/chromium/content/browser/web_package/signed_exchange_utils.cc
@@ -4,20 +4,51 @@
#include "content/browser/web_package/signed_exchange_utils.h"
-#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
+#include "content/browser/web_package/web_package_request_handler.h"
+#include "content/public/common/content_features.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
namespace content {
namespace signed_exchange_utils {
-void RunErrorMessageCallbackAndEndTraceEvent(const char* name,
- const LogCallback& callback,
- const std::string& error_message) {
- if (callback)
- callback.Run(error_message);
+void ReportErrorAndEndTraceEvent(SignedExchangeDevToolsProxy* devtools_proxy,
+ const char* trace_event_name,
+ const std::string& error_message) {
+ if (devtools_proxy)
+ devtools_proxy->ReportErrorMessage(error_message);
+ TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"), trace_event_name,
+ "error", error_message);
+}
+
+bool IsSignedExchangeHandlingEnabled() {
+ return base::FeatureList::IsEnabled(features::kSignedHTTPExchange) ||
+ base::FeatureList::IsEnabled(features::kSignedHTTPExchangeOriginTrial);
+}
- TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("loading"), name, "error",
- error_message);
+bool ShouldHandleAsSignedHTTPExchange(
+ const GURL& request_url,
+ const network::ResourceResponseHead& head) {
+ // Currently we don't support the signed exchange which is returned from a
+ // service worker.
+ // TODO(crbug/803774): Decide whether we should support it or not.
+ if (head.was_fetched_via_service_worker)
+ return false;
+ if (!WebPackageRequestHandler::IsSupportedMimeType(head.mime_type))
+ return false;
+ if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
+ return true;
+ if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchangeOriginTrial))
+ return false;
+ std::unique_ptr<blink::TrialTokenValidator> validator =
+ std::make_unique<blink::TrialTokenValidator>();
+ return validator->RequestEnablesFeature(request_url, head.headers.get(),
+ features::kSignedHTTPExchange.name,
+ base::Time::Now());
}
} // namespace signed_exchange_utils
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.h b/chromium/content/browser/web_package/signed_exchange_utils.h
index d48d8347ad1..b5c4220daba 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.h
+++ b/chromium/content/browser/web_package/signed_exchange_utils.h
@@ -7,19 +7,36 @@
#include <string>
-#include "base/callback_forward.h"
+class GURL;
+
+namespace network {
+struct ResourceResponseHead;
+} // namespace network
namespace content {
-namespace signed_exchange_utils {
-using LogCallback = base::RepeatingCallback<void(const std::string&)>;
+class SignedExchangeDevToolsProxy;
+
+namespace signed_exchange_utils {
-// Runs |callback| with |error_message| if |callback| is not null. And calls
-// TRACE_EVENT_END() with "disabled-by-default-loading" category, |name| and
-// |error_meassage|.
-void RunErrorMessageCallbackAndEndTraceEvent(const char* name,
- const LogCallback& callback,
- const std::string& error_message);
+// Utility method to call SignedExchangeDevToolsProxy::ReportErrorMessage() and
+// TRACE_EVENT_END() to report the error to both DevTools and about:tracing. If
+// |devtools_proxy| is nullptr, it just calls TRACE_EVENT_END().
+void ReportErrorAndEndTraceEvent(SignedExchangeDevToolsProxy* devtools_proxy,
+ const char* trace_event_name,
+ const std::string& error_message);
+
+// Returns true when SignedHTTPExchange feature or SignedHTTPExchangeOriginTrial
+// feature is enabled.
+bool IsSignedExchangeHandlingEnabled();
+
+// Returns true when the response should be handled as a signed exchange by
+// checking the mime type and the feature flags. When SignedHTTPExchange feature
+// is not enabled and SignedHTTPExchangeOriginTrial feature is enabled, this
+// method also checks the Origin Trial header.
+bool ShouldHandleAsSignedHTTPExchange(
+ const GURL& request_url,
+ const network::ResourceResponseHead& head);
} // namespace signed_exchange_utils
} // namespace content
diff --git a/chromium/content/browser/web_package/web_package_loader.cc b/chromium/content/browser/web_package/web_package_loader.cc
index 6e563d35a87..ecd1e160eb0 100644
--- a/chromium/content/browser/web_package/web_package_loader.cc
+++ b/chromium/content/browser/web_package/web_package_loader.cc
@@ -6,12 +6,15 @@
#include <memory>
+#include "base/callback.h"
#include "base/feature_list.h"
#include "base/strings/stringprintf.h"
#include "content/browser/loader/data_pipe_to_source_stream.h"
#include "content/browser/loader/source_stream_to_data_pipe.h"
#include "content/browser/web_package/signed_exchange_cert_fetcher_factory.h"
+#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_handler.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/public/common/content_features.h"
#include "net/cert/cert_status_flags.h"
#include "net/http/http_util.h"
@@ -75,32 +78,33 @@ class WebPackageLoader::ResponseTimingInfo {
};
WebPackageLoader::WebPackageLoader(
- const network::ResourceResponseHead& original_response,
+ const network::ResourceResponseHead& outer_response,
network::mojom::URLLoaderClientPtr forwarding_client,
network::mojom::URLLoaderClientEndpointsPtr endpoints,
url::Origin request_initiator,
uint32_t url_loader_options,
- int frame_tree_node_id,
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter)
- : original_response_timing_info_(
- std::make_unique<ResponseTimingInfo>(original_response)),
+ : outer_response_timing_info_(
+ std::make_unique<ResponseTimingInfo>(outer_response)),
+ outer_response_(outer_response),
forwarding_client_(std::move(forwarding_client)),
url_loader_client_binding_(this),
request_initiator_(request_initiator),
url_loader_options_(url_loader_options),
- frame_tree_node_id_(frame_tree_node_id),
+ devtools_proxy_(std::move(devtools_proxy)),
url_loader_factory_(std::move(url_loader_factory)),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
request_context_getter_(std::move(request_context_getter)),
weak_factory_(this) {
- DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
+ DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
// Can't use HttpResponseHeaders::GetMimeType() because SignedExchangeHandler
// checks "v=" parameter.
- original_response.headers->EnumerateHeader(nullptr, "content-type",
- &content_type_);
+ outer_response.headers->EnumerateHeader(nullptr, "content-type",
+ &content_type_);
url_loader_.Bind(std::move(endpoints->url_loader));
@@ -185,13 +189,14 @@ void WebPackageLoader::OnStartLoadingResponseBody(
base::BindOnce(&WebPackageLoader::OnHTTPExchangeFound,
weak_factory_.GetWeakPtr()),
std::move(cert_fetcher_factory), std::move(request_context_getter_),
- frame_tree_node_id_);
+ std::move(devtools_proxy_));
}
void WebPackageLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {}
-void WebPackageLoader::FollowRedirect() {
+void WebPackageLoader::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
NOTREACHED();
}
@@ -239,10 +244,10 @@ void WebPackageLoader::OnHTTPExchangeFound(
}
// TODO(https://crbug.com/803774): Handle no-GET request_method as a error.
- DCHECK(original_response_timing_info_);
+ DCHECK(outer_response_timing_info_);
forwarding_client_->OnReceiveRedirect(
CreateRedirectInfo(request_url),
- std::move(original_response_timing_info_)->CreateRedirectResponseHead());
+ std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
forwarding_client_.reset();
const base::Optional<net::SSLInfo>& ssl_info = resource_response.ssl_info;
diff --git a/chromium/content/browser/web_package/web_package_loader.h b/chromium/content/browser/web_package/web_package_loader.h
index 115bc2b8513..0bafea07c9a 100644
--- a/chromium/content/browser/web_package/web_package_loader.h
+++ b/chromium/content/browser/web_package/web_package_loader.h
@@ -5,7 +5,9 @@
#ifndef CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_LOADER_H_
#define CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_LOADER_H_
+#include "base/callback.h"
#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/simple_watcher.h"
@@ -26,6 +28,7 @@ class SharedURLLoaderFactory;
namespace content {
+class SignedExchangeDevToolsProxy;
class SignedExchangeHandler;
class SignedExchangeHandlerFactory;
class URLLoaderThrottle;
@@ -43,12 +46,12 @@ class WebPackageLoader final : public network::mojom::URLLoaderClient,
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
WebPackageLoader(
- const network::ResourceResponseHead& original_response,
+ const network::ResourceResponseHead& outer_response,
network::mojom::URLLoaderClientPtr forwarding_client,
network::mojom::URLLoaderClientEndpointsPtr endpoints,
url::Origin request_initiator,
uint32_t url_loader_options,
- int frame_tree_node_id,
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
@@ -73,7 +76,8 @@ class WebPackageLoader final : public network::mojom::URLLoaderClient,
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
// network::mojom::URLLoader implementation
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int intra_priority_value) override;
@@ -101,7 +105,10 @@ class WebPackageLoader final : public network::mojom::URLLoaderClient,
void FinishReadingBody(int result);
// This timing info is used to create a dummy redirect response.
- std::unique_ptr<const ResponseTimingInfo> original_response_timing_info_;
+ std::unique_ptr<const ResponseTimingInfo> outer_response_timing_info_;
+
+ // The outer response of signed HTTP exchange which was received from network.
+ const network::ResourceResponseHead outer_response_;
// This client is alive until OnHTTPExchangeFound() is called.
network::mojom::URLLoaderClientPtr forwarding_client_;
@@ -126,7 +133,7 @@ class WebPackageLoader final : public network::mojom::URLLoaderClient,
url::Origin request_initiator_;
const uint32_t url_loader_options_;
- const int frame_tree_node_id_;
+ std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
diff --git a/chromium/content/browser/web_package/web_package_prefetch_handler.cc b/chromium/content/browser/web_package/web_package_prefetch_handler.cc
index 40f151b71f0..b8ced15cd0c 100644
--- a/chromium/content/browser/web_package/web_package_prefetch_handler.cc
+++ b/chromium/content/browser/web_package/web_package_prefetch_handler.cc
@@ -4,37 +4,29 @@
#include "content/browser/web_package/web_package_prefetch_handler.h"
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
#include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
#include "content/browser/web_package/web_package_loader.h"
-#include "content/browser/web_package/web_package_request_handler.h"
#include "content/public/common/content_features.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace content {
-bool WebPackagePrefetchHandler::IsResponseForWebPackage(
- const network::ResourceResponseHead& response) {
- std::string mime_type;
- if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange) &&
- !response.was_fetched_via_service_worker && response.headers &&
- response.headers->GetMimeType(&mime_type) &&
- WebPackageRequestHandler::IsSupportedMimeType(mime_type)) {
- return true;
- }
- return false;
-}
-
WebPackagePrefetchHandler::WebPackagePrefetchHandler(
- int frame_tree_node_id,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ bool report_raw_headers,
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr network_loader,
network::mojom::URLLoaderClientRequest network_client_request,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
url::Origin request_initiator,
+ const GURL& outer_request_url,
URLLoaderThrottlesGetter loader_throttles_getter,
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
@@ -57,8 +49,11 @@ WebPackagePrefetchHandler::WebPackagePrefetchHandler(
web_package_loader_ = std::make_unique<WebPackageLoader>(
response, std::move(client), std::move(endpoints),
std::move(request_initiator), network::mojom::kURLLoadOptionNone,
- frame_tree_node_id, std::move(url_loader_factory),
- loader_throttles_getter, request_context_getter);
+ std::make_unique<SignedExchangeDevToolsProxy>(
+ outer_request_url, response, std::move(frame_tree_node_id_getter),
+ base::nullopt /* devtools_navigation_token */, report_raw_headers),
+ std::move(url_loader_factory), loader_throttles_getter,
+ request_context_getter);
}
WebPackagePrefetchHandler::~WebPackagePrefetchHandler() = default;
diff --git a/chromium/content/browser/web_package/web_package_prefetch_handler.h b/chromium/content/browser/web_package/web_package_prefetch_handler.h
index cd69ad6c9b8..f6fc27cbdca 100644
--- a/chromium/content/browser/web_package/web_package_prefetch_handler.h
+++ b/chromium/content/browser/web_package/web_package_prefetch_handler.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_PREFETCH_HANDLER_H_
#define CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_PREFETCH_HANDLER_H_
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -29,20 +30,19 @@ class WebPackagePrefetchHandler final : public network::mojom::URLLoaderClient {
using URLLoaderThrottlesGetter = base::RepeatingCallback<
std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
- static bool IsResponseForWebPackage(
- const network::ResourceResponseHead& response);
-
// This takes |network_loader| and |network_client| to set up the
// WebPackageLoader (so that the loader can load data from the network).
// |forwarding_client| is a pointer to the downstream client (typically who
// creates this handler).
WebPackagePrefetchHandler(
- int frame_tree_node_id,
+ base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
+ bool report_raw_headers,
const network::ResourceResponseHead& response,
network::mojom::URLLoaderPtr network_loader,
network::mojom::URLLoaderClientRequest network_client_request,
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
url::Origin request_initiator,
+ const GURL& outer_request_url,
URLLoaderThrottlesGetter loader_throttles_getter,
ResourceContext* resource_context,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
diff --git a/chromium/content/browser/web_package/web_package_request_handler.cc b/chromium/content/browser/web_package/web_package_request_handler.cc
index 8eadeabc9f2..f67d3068b54 100644
--- a/chromium/content/browser/web_package/web_package_request_handler.cc
+++ b/chromium/content/browser/web_package/web_package_request_handler.cc
@@ -8,6 +8,8 @@
#include "base/bind.h"
#include "base/feature_list.h"
+#include "content/browser/web_package/signed_exchange_devtools_proxy.h"
+#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/browser/web_package/web_package_loader.h"
#include "content/common/throttling_url_loader.h"
#include "content/public/common/content_features.h"
@@ -17,31 +19,37 @@
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
namespace content {
// static
bool WebPackageRequestHandler::IsSupportedMimeType(
const std::string& mime_type) {
- DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
return mime_type == "application/signed-exchange";
}
WebPackageRequestHandler::WebPackageRequestHandler(
url::Origin request_initiator,
+ const GURL& url,
uint32_t url_loader_options,
int frame_tree_node_id,
+ const base::UnguessableToken& devtools_navigation_token,
+ bool report_raw_headers,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter)
: request_initiator_(std::move(request_initiator)),
+ url_(url),
url_loader_options_(url_loader_options),
frame_tree_node_id_(frame_tree_node_id),
+ devtools_navigation_token_(devtools_navigation_token),
+ report_raw_headers_(report_raw_headers),
url_loader_factory_(url_loader_factory),
url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
request_context_getter_(std::move(request_context_getter)),
weak_factory_(this) {
- DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
+ DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
}
WebPackageRequestHandler::~WebPackageRequestHandler() = default;
@@ -68,10 +76,8 @@ bool WebPackageRequestHandler::MaybeCreateLoaderForResponse(
network::mojom::URLLoaderPtr* loader,
network::mojom::URLLoaderClientRequest* client_request,
ThrottlingURLLoader* url_loader) {
- std::string mime_type;
- if (response.was_fetched_via_service_worker || !response.headers ||
- !response.headers->GetMimeType(&mime_type) ||
- !IsSupportedMimeType(mime_type)) {
+ if (!signed_exchange_utils::ShouldHandleAsSignedHTTPExchange(
+ request_initiator_.GetURL(), response)) {
return false;
}
@@ -83,7 +89,11 @@ bool WebPackageRequestHandler::MaybeCreateLoaderForResponse(
// to support SafeBrowsing checking of the content of the WebPackage.
web_package_loader_ = std::make_unique<WebPackageLoader>(
response, std::move(client), url_loader->Unbind(),
- std::move(request_initiator_), url_loader_options_, frame_tree_node_id_,
+ std::move(request_initiator_), url_loader_options_,
+ std::make_unique<SignedExchangeDevToolsProxy>(
+ std::move(url_), response,
+ base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
+ std::move(devtools_navigation_token_), report_raw_headers_),
std::move(url_loader_factory_), std::move(url_loader_throttles_getter_),
std::move(request_context_getter_));
return true;
diff --git a/chromium/content/browser/web_package/web_package_request_handler.h b/chromium/content/browser/web_package/web_package_request_handler.h
index d988475af35..40f75c63441 100644
--- a/chromium/content/browser/web_package/web_package_request_handler.h
+++ b/chromium/content/browser/web_package/web_package_request_handler.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_REQUEST_HANDLER_H_
#include "base/memory/weak_ptr.h"
+#include "base/unguessable_token.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/public/common/resource_type.h"
#include "url/origin.h"
@@ -32,8 +33,11 @@ class WebPackageRequestHandler final : public NavigationLoaderInterceptor {
WebPackageRequestHandler(
url::Origin request_initiator,
+ const GURL& url,
uint32_t url_loader_options,
int frame_tree_node_id,
+ const base::UnguessableToken& devtools_navigation_token,
+ bool report_raw_headers,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
URLLoaderThrottlesGetter url_loader_throttles_getter,
scoped_refptr<net::URLRequestContextGetter> request_context_getter);
@@ -59,8 +63,11 @@ class WebPackageRequestHandler final : public NavigationLoaderInterceptor {
std::unique_ptr<WebPackageLoader> web_package_loader_;
url::Origin request_initiator_;
+ GURL url_;
const uint32_t url_loader_options_;
const int frame_tree_node_id_;
+ base::Optional<const base::UnguessableToken> devtools_navigation_token_;
+ const bool report_raw_headers_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
URLLoaderThrottlesGetter url_loader_throttles_getter_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
diff --git a/chromium/content/browser/web_package/web_package_request_handler_browsertest.cc b/chromium/content/browser/web_package/web_package_request_handler_browsertest.cc
index 038e49d457f..993fb9234c6 100644
--- a/chromium/content/browser/web_package/web_package_request_handler_browsertest.cc
+++ b/chromium/content/browser/web_package/web_package_request_handler_browsertest.cc
@@ -133,7 +133,7 @@ class WebPackageRequestHandlerBrowserTest
static std::string ReadFile(const std::string& data_path) {
base::ScopedAllowBlockingForTesting allow_io;
base::FilePath root_path;
- CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
std::string contents;
CHECK(base::ReadFileToString(root_path.AppendASCII(data_path), &contents));
return contents;
@@ -143,7 +143,7 @@ class WebPackageRequestHandlerBrowserTest
std::string header_file_relative_path = data_path + kMockHeaderFileSuffix;
base::ScopedAllowBlockingForTesting allow_io;
base::FilePath root_path;
- CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
if (!base::PathExists(root_path.AppendASCII(header_file_relative_path)))
return "HTTP/1.0 200 OK\n";
return ReadFile(header_file_relative_path);
@@ -153,7 +153,7 @@ class WebPackageRequestHandlerBrowserTest
const std::string& data_path) {
DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
base::FilePath root_path;
- CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path));
net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
url, net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
root_path.AppendASCII(data_path)));
diff --git a/chromium/content/browser/webauth/authenticator_impl.cc b/chromium/content/browser/webauth/authenticator_impl.cc
index 08a8a7be414..2cc796d08e2 100644
--- a/chromium/content/browser/webauth/authenticator_impl.cc
+++ b/chromium/content/browser/webauth/authenticator_impl.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/timer/timer.h"
+#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/webauth/authenticator_type_converters.h"
#include "content/public/browser/content_browser_client.h"
@@ -240,6 +241,13 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
request_parameter.SetUserVerification(
mojo::ConvertTo<device::UserVerificationRequirement>(
options->user_verification));
+
+ if (!options->cable_authentication_data.empty()) {
+ request_parameter.SetCableExtension(
+ mojo::ConvertTo<
+ std::vector<device::FidoCableDiscovery::CableDiscoveryData>>(
+ options->cable_authentication_data));
+ }
return request_parameter;
}
@@ -328,19 +336,9 @@ std::string Base64UrlEncode(const base::span<const uint8_t> input) {
} // namespace
AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host)
- : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
- render_frame_host_(render_frame_host),
- timer_(std::make_unique<base::OneShotTimer>()),
- binding_(this),
- weak_factory_(this) {
- DCHECK(render_frame_host_);
- DCHECK(timer_);
-
- protocols_.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
- if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
- protocols_.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
- }
-}
+ : AuthenticatorImpl(render_frame_host,
+ nullptr /* connector */,
+ std::make_unique<base::OneShotTimer>()) {}
AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host,
service_manager::Connector* connector,
@@ -353,6 +351,21 @@ AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host,
weak_factory_(this) {
DCHECK(render_frame_host_);
DCHECK(timer_);
+
+ protocols_.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
+ if (base::FeatureList::IsEnabled(features::kWebAuthBle)) {
+ protocols_.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
+ }
+
+ if (base::FeatureList::IsEnabled(features::kWebAuthCable)) {
+ protocols_.insert(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
+ }
+#if defined(OS_MACOSX)
+ if (base::FeatureList::IsEnabled(features::kWebAuthTouchId)) {
+ protocols_.insert(device::FidoTransportProtocol::kInternal);
+ }
+#endif
}
AuthenticatorImpl::~AuthenticatorImpl() {}
@@ -378,14 +391,13 @@ std::string AuthenticatorImpl::SerializeCollectedClientDataToJson(
client_data.SetKey(kChallengeKey, base::Value(Base64UrlEncode(challenge)));
client_data.SetKey(kOriginKey, base::Value(origin.Serialize()));
- base::DictionaryValue token_binding_dict;
- static constexpr char kTokenBindingStatusKey[] = "status";
- static constexpr char kTokenBindingIdKey[] = "id";
- static constexpr char kTokenBindingSupportedStatus[] = "supported";
- static constexpr char kTokenBindingNotSupportedStatus[] = "not-supported";
- static constexpr char kTokenBindingPresentStatus[] = "present";
-
if (token_binding) {
+ base::DictionaryValue token_binding_dict;
+ static constexpr char kTokenBindingStatusKey[] = "status";
+ static constexpr char kTokenBindingIdKey[] = "id";
+ static constexpr char kTokenBindingSupportedStatus[] = "supported";
+ static constexpr char kTokenBindingPresentStatus[] = "present";
+
if (token_binding->empty()) {
token_binding_dict.SetKey(kTokenBindingStatusKey,
base::Value(kTokenBindingSupportedStatus));
@@ -395,12 +407,9 @@ std::string AuthenticatorImpl::SerializeCollectedClientDataToJson(
token_binding_dict.SetKey(kTokenBindingIdKey,
base::Value(Base64UrlEncode(*token_binding)));
}
- } else {
- token_binding_dict.SetKey(kTokenBindingStatusKey,
- base::Value(kTokenBindingNotSupportedStatus));
- }
- client_data.SetKey(kTokenBindingKey, std::move(token_binding_dict));
+ client_data.SetKey(kTokenBindingKey, std::move(token_binding_dict));
+ }
if (base::RandDouble() < 0.2) {
// An extra key is sometimes added to ensure that RPs do not make
@@ -510,6 +519,11 @@ void AuthenticatorImpl::MakeCredential(
attestation_preference_ = options->attestation;
+ // Communication using Cable protocol is only supported for GetAssertion
+ // request on CTAP2 devices.
+ protocols_.erase(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
+
if (base::FeatureList::IsEnabled(features::kWebAuthCtap2)) {
auto authenticator_selection_criteria =
options->authenticator_selection
@@ -603,18 +617,19 @@ void AuthenticatorImpl::GetAssertion(
FilterCredentialList(std::move(options->allow_credentials));
// There are two different descriptions of what should happen when
- // "allowCredentials" is empty.
+ // "allowCredentials" is empty for U2F.
// a) WebAuthN 6.2.3 step 6[1] implies "NotAllowedError".
// b) CTAP step 7.2 step 2[2] says the device should error out with
// "CTAP2_ERR_OPTION_NOT_SUPPORTED". This also resolves to "NotAllowedError".
// The behavior in both cases is consistent with the current implementation.
- // TODO(crbug.com/831712): When CTAP2 authenticators are supported, this check
- // should be enforced by handlers in fido/device on a per-device basis.
+ // When CTAP2 is enabled, however, this check is done by handlers in
+ // fido/device on a per-device basis.
// [1] https://w3c.github.io/webauthn/#authenticatorgetassertion
// [2]
// https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html
- if (handles.empty()) {
+ if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
+ handles.empty()) {
InvokeCallbackAndCleanup(
std::move(callback),
webauth::mojom::AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS, nullptr);
@@ -646,6 +661,10 @@ void AuthenticatorImpl::GetAssertion(
base::BindOnce(&AuthenticatorImpl::OnSignResponse,
weak_factory_.GetWeakPtr()));
} else {
+ // Communication using Cable protocol is only supported for CTAP2 devices.
+ protocols_.erase(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
+
u2f_request_ = device::U2fSign::TrySign(
connector_, protocols_, handles,
ConstructClientDataHash(client_data_json_), application_parameter,
diff --git a/chromium/content/browser/webauth/authenticator_impl_unittest.cc b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
index f309233ee08..26ad5fd258c 100644
--- a/chromium/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/chromium/content/browser/webauth/authenticator_impl_unittest.cc
@@ -69,8 +69,8 @@ typedef struct {
constexpr char kTestOrigin1[] = "https://a.google.com";
constexpr char kTestRelyingPartyId[] = "google.com";
-// Test data. CBOR test data can be built using the given diagnostic strings
-// and the utility at "http://cbor.me/".
+// Test data. CBOR test data can be built using the given
+// diagnostic strings and the utility at "http://CBOR.me/".
constexpr int32_t kCoseEs256 = -7;
constexpr uint8_t kTestChallengeBytes[] = {
@@ -80,13 +80,11 @@ constexpr uint8_t kTestChallengeBytes[] = {
constexpr char kTestRegisterClientDataJsonString[] =
R"({"challenge":"aHE0loIi7BcgLkJQX47SsWriLxa7BbiMJdueYCZF8UE","origin":)"
- R"("https://a.google.com","tokenBinding":{"status":"not-supported"},)"
- R"("type":"webauthn.create"})";
+ R"("https://a.google.com", "type":"webauthn.create"})";
constexpr char kTestSignClientDataJsonString[] =
R"({"challenge":"aHE0loIi7BcgLkJQX47SsWriLxa7BbiMJdueYCZF8UE","origin":)"
- R"("https://a.google.com","tokenBinding":{"status":"not-supported"},)"
- R"("type":"webauthn.get"})";
+ R"("https://a.google.com", "type":"webauthn.get"})";
constexpr OriginClaimedAuthorityPair kValidRelyingPartyTestCases[] = {
{"http://localhost", "localhost"},
@@ -337,11 +335,16 @@ class AuthenticatorImplTest : public content::RenderViewHostTestHarness {
options->relying_party_id = origin_url.host();
options->appid = appid;
- TestGetAssertionCallback cb;
- authenticator->GetAssertion(std::move(options), cb.callback());
- cb.WaitForCallback();
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
- return cb.status();
+ return callback_receiver.status();
+ }
+
+ bool SupportsTransportProtocol(::device::FidoTransportProtocol protocol) {
+ return base::ContainsKey(authenticator_impl_->protocols_, protocol);
}
private:
@@ -361,10 +364,11 @@ TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
options->relying_party->id = test_case.claimed_authority;
- TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(options), cb.callback());
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, cb.status());
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, callback_receiver.status());
}
// These instances pass the origin and relying party checks and return at
@@ -380,10 +384,12 @@ TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
options->relying_party->id = test_case.claimed_authority;
options->public_key_parameters = GetTestPublicKeyCredentialParameters(123);
- TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(options), cb.callback());
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED, cb.status());
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED,
+ callback_receiver.status());
}
}
@@ -397,10 +403,12 @@ TEST_F(AuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
GetTestPublicKeyCredentialCreationOptions();
options->public_key_parameters = GetTestPublicKeyCredentialParameters(123);
- TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(options), cb.callback());
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED, cb.status());
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED,
+ callback_receiver.status());
}
// Test that service returns USER_VERIFICATION_UNSUPPORTED if user verification
@@ -413,10 +421,11 @@ TEST_F(AuthenticatorImplTest, GetAssertionUserVerification) {
GetTestPublicKeyCredentialRequestOptions();
options->user_verification =
webauth::mojom::UserVerificationRequirement::REQUIRED;
- TestGetAssertionCallback cb;
- authenticator->GetAssertion(std::move(options), cb.callback());
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED, cb.status());
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED,
+ callback_receiver.status());
}
// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if user
@@ -430,11 +439,12 @@ TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
options->authenticator_selection->user_verification =
webauth::mojom::UserVerificationRequirement::REQUIRED;
- TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(options), cb.callback());
- cb.WaitForCallback();
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
- cb.status());
+ callback_receiver.status());
}
// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if resident key
@@ -447,11 +457,12 @@ TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
GetTestPublicKeyCredentialCreationOptions();
options->authenticator_selection->require_resident_key = true;
- TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(options), cb.callback());
- cb.WaitForCallback();
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
- cb.status());
+ callback_receiver.status());
}
// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if a platform
@@ -465,11 +476,12 @@ TEST_F(AuthenticatorImplTest, MakeCredentialPlatformAuthenticator) {
options->authenticator_selection->authenticator_attachment =
webauth::mojom::AuthenticatorAttachment::PLATFORM;
- TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(options), cb.callback());
- cb.WaitForCallback();
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
- cb.status());
+ callback_receiver.status());
}
// Parses its arguments as JSON and expects that all the keys in the first are
@@ -515,8 +527,7 @@ TEST_F(AuthenticatorImplTest, TestTokenBindingClientData) {
const std::vector<
std::pair<base::Optional<std::vector<uint8_t>>, const char*>>
kTestCases = {
- std::make_pair(base::nullopt,
- R"({"tokenBinding":{"status":"not-supported"}})"),
+ std::make_pair(base::nullopt, ""),
std::make_pair(std::vector<uint8_t>{},
R"({"tokenBinding":{"status":"supported"}})"),
std::make_pair(
@@ -528,9 +539,15 @@ TEST_F(AuthenticatorImplTest, TestTokenBindingClientData) {
const auto& token_binding = test.first;
const std::string expected_json_subset = test.second;
SCOPED_TRACE(expected_json_subset);
+ const std::string client_data =
+ GetTokenBindingTestClientDataJSON(token_binding);
- CheckJSONIsSubsetOfJSON(expected_json_subset,
- GetTokenBindingTestClientDataJSON(token_binding));
+ if (!expected_json_subset.empty()) {
+ CheckJSONIsSubsetOfJSON(expected_json_subset, client_data);
+ } else {
+ EXPECT_TRUE(client_data.find("tokenBinding") == std::string::npos)
+ << client_data;
+ }
}
}
@@ -538,7 +555,7 @@ TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
- TestMakeCredentialCallback cb;
+ TestMakeCredentialCallback callback_receiver;
// Set up service_manager::Connector for tests.
auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
@@ -560,13 +577,14 @@ TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) {
AuthenticatorPtr authenticator =
ConnectToAuthenticator(connector.get(), std::move(timer));
- authenticator->MakeCredential(std::move(options), cb.callback());
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
// Verify behavior for various combinations of origins and RP IDs.
@@ -584,10 +602,11 @@ TEST_F(AuthenticatorImplTest, GetAssertionOriginAndRpIds) {
GetTestPublicKeyCredentialRequestOptions();
options->relying_party_id = test_case.claimed_authority;
- TestGetAssertionCallback cb;
- authenticator->GetAssertion(std::move(options), cb.callback());
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, cb.status());
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, callback_receiver.status());
}
}
@@ -640,7 +659,7 @@ TEST_F(AuthenticatorImplTest, TestGetAssertionTimeout) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
- TestGetAssertionCallback cb;
+ TestGetAssertionCallback callback_receiver;
// Set up service_manager::Connector for tests.
auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
@@ -662,13 +681,13 @@ TEST_F(AuthenticatorImplTest, TestGetAssertionTimeout) {
AuthenticatorPtr authenticator =
ConnectToAuthenticator(connector.get(), std::move(timer));
- authenticator->GetAssertion(std::move(options), cb.callback());
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
@@ -698,18 +717,148 @@ TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
options->allow_credentials.emplace_back(std::move(credential));
- TestGetAssertionCallback cb;
- authenticator->GetAssertion(std::move(options), cb.callback());
- cb.WaitForCallback();
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
if (should_be_valid) {
- EXPECT_EQ(AuthenticatorStatus::SUCCESS, cb.status());
+ EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
} else {
- EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED, cb.status());
+ EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED,
+ callback_receiver.status());
}
}
}
+TEST_F(AuthenticatorImplTest, TestCableDiscoveryEnabledWithSwitch) {
+ TestServiceManagerContext service_manager_context;
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ std::vector<base::Feature>{features::kWebAuthCtap2,
+ features::kWebAuthCable},
+ std::vector<base::Feature>{});
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ TestGetAssertionCallback callback_receiver;
+
+ // Set up service_manager::Connector for tests.
+ auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
+ service_manager::mojom::ConnectorRequest request;
+ auto connector = service_manager::Connector::Create(&request);
+ service_manager::Connector::TestApi test_api(connector.get());
+ test_api.OverrideBinderForTesting(
+ service_manager::Identity(device::mojom::kServiceName),
+ device::mojom::HidManager::Name_,
+ base::Bind(&device::FakeHidManager::AddBinding,
+ base::Unretained(fake_hid_manager.get())));
+
+ // Set up a timer for testing.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto timer =
+ std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
+ timer->SetTaskRunner(task_runner);
+ AuthenticatorPtr authenticator =
+ ConnectToAuthenticator(connector.get(), std::move(timer));
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+ EXPECT_TRUE(SupportsTransportProtocol(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+}
+
+TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledForMakeCredential) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ std::vector<base::Feature>{features::kWebAuthCtap2,
+ features::kWebAuthCable},
+ std::vector<base::Feature>{});
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+ TestMakeCredentialCallback callback_receiver;
+
+ // Set up service_manager::Connector for tests.
+ auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
+ service_manager::mojom::ConnectorRequest request;
+ auto connector = service_manager::Connector::Create(&request);
+ service_manager::Connector::TestApi test_api(connector.get());
+ test_api.OverrideBinderForTesting(
+ service_manager::Identity(device::mojom::kServiceName),
+ device::mojom::HidManager::Name_,
+ base::Bind(&device::FakeHidManager::AddBinding,
+ base::Unretained(fake_hid_manager.get())));
+
+ // Set up a timer for testing.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto timer =
+ std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
+ timer->SetTaskRunner(task_runner);
+ AuthenticatorPtr authenticator =
+ ConnectToAuthenticator(connector.get(), std::move(timer));
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+ EXPECT_FALSE(SupportsTransportProtocol(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+}
+
+TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutSwitch) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ TestGetAssertionCallback callback_receiver;
+
+ // Set up service_manager::Connector for tests.
+ auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
+ service_manager::mojom::ConnectorRequest request;
+ auto connector = service_manager::Connector::Create(&request);
+ service_manager::Connector::TestApi test_api(connector.get());
+ test_api.OverrideBinderForTesting(
+ service_manager::Identity(device::mojom::kServiceName),
+ device::mojom::HidManager::Name_,
+ base::Bind(&device::FakeHidManager::AddBinding,
+ base::Unretained(fake_hid_manager.get())));
+
+ // Set up a timer for testing.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto timer =
+ std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
+ timer->SetTaskRunner(task_runner);
+ AuthenticatorPtr authenticator =
+ ConnectToAuthenticator(connector.get(), std::move(timer));
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+ EXPECT_FALSE(SupportsTransportProtocol(
+ device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
+}
+
TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportMakeCredential) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
@@ -717,7 +866,7 @@ TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportMakeCredential) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialCreationOptionsPtr options =
GetTestPublicKeyCredentialCreationOptions();
- TestMakeCredentialCallback cb;
+ TestMakeCredentialCallback callback_receiver;
// Set up service_manager::Connector for tests.
auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
@@ -734,13 +883,14 @@ TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportMakeCredential) {
ConnectToAuthenticator(connector.get(), std::move(timer));
device::test::ScopedVirtualFidoDevice virtual_device;
- authenticator->MakeCredential(std::move(options), cb.callback());
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportGetAssertion) {
@@ -750,7 +900,7 @@ TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportGetAssertion) {
SimulateNavigation(GURL(kTestOrigin1));
PublicKeyCredentialRequestOptionsPtr options =
GetTestPublicKeyCredentialRequestOptions();
- TestGetAssertionCallback cb;
+ TestGetAssertionCallback callback_receiver;
// Set up service_manager::Connector for tests.
auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
@@ -767,13 +917,49 @@ TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportGetAssertion) {
ConnectToAuthenticator(connector.get(), std::move(timer));
device::test::ScopedVirtualFidoDevice virtual_device;
- authenticator->GetAssertion(std::move(options), cb.callback());
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
// Trigger timer.
base::RunLoop().RunUntilIdle();
task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
- cb.WaitForCallback();
- EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.status());
+ callback_receiver.WaitForCallback();
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+}
+
+TEST_F(AuthenticatorImplTest, Ctap2AcceptsEmptyAllowCredentials) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ options->allow_credentials.clear();
+ TestGetAssertionCallback callback_receiver;
+
+ // Set up service_manager::Connector for tests.
+ auto fake_hid_manager = std::make_unique<device::FakeHidManager>();
+ service_manager::mojom::ConnectorRequest request;
+ auto connector = service_manager::Connector::Create(&request);
+
+ // Set up a timer for testing.
+ auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ auto timer =
+ std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
+ timer->SetTaskRunner(task_runner);
+ AuthenticatorPtr authenticator =
+ ConnectToAuthenticator(connector.get(), std::move(timer));
+
+ device::test::ScopedVirtualFidoDevice virtual_device;
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+ // Trigger timer.
+ base::RunLoop().RunUntilIdle();
+ task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
+ callback_receiver.WaitForCallback();
+ // Doesn't error out with EMPTY_ALLOW_CREDENTIALS but continues to a
+ // NOT_ALLOWED_ERROR.
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
}
TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
@@ -786,11 +972,122 @@ TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
GetTestPublicKeyCredentialRequestOptions();
options->allow_credentials.clear();
- TestGetAssertionCallback cb;
- authenticator->GetAssertion(std::move(options), cb.callback());
- cb.WaitForCallback();
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS,
+ callback_receiver.status());
+}
+
+TEST_F(AuthenticatorImplTest, MakeCredentialAlreadyRegistered) {
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ TestServiceManagerContext service_manager_context;
- EXPECT_EQ(AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS, cb.status());
+ SimulateNavigation(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+
+ // Exclude the one already registered credential.
+ options->exclude_credentials = GetTestAllowCredentials();
+ ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration(
+ options->exclude_credentials[0]->id, kTestRelyingPartyId));
+
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_EXCLUDED,
+ callback_receiver.status());
+}
+
+TEST_F(AuthenticatorImplTest, MakeCredentialPendingRequest) {
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ TestServiceManagerContext service_manager_context;
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ // Make first request.
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+
+ // Make second request.
+ // TODO(crbug.com/785955): Rework to ensure there are potential race
+ // conditions once we have VirtualAuthenticatorEnvironment.
+ PublicKeyCredentialCreationOptionsPtr options2 =
+ GetTestPublicKeyCredentialCreationOptions();
+ TestMakeCredentialCallback callback_receiver2;
+ authenticator->MakeCredential(std::move(options2),
+ callback_receiver2.callback());
+ callback_receiver2.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver2.status());
+}
+
+TEST_F(AuthenticatorImplTest, GetAssertionPendingRequest) {
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ TestServiceManagerContext service_manager_context;
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ // Make first request.
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+ // Make second request.
+ // TODO(crbug.com/785955): Rework to ensure there are potential race
+ // conditions once we have VirtualAuthenticatorEnvironment.
+ PublicKeyCredentialRequestOptionsPtr options2 =
+ GetTestPublicKeyCredentialRequestOptions();
+ TestGetAssertionCallback callback_receiver2;
+ authenticator->GetAssertion(std::move(options2),
+ callback_receiver2.callback());
+ callback_receiver2.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver2.status());
+}
+
+TEST_F(AuthenticatorImplTest, InvalidResponse) {
+ device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+ TestServiceManagerContext service_manager_context;
+
+ scoped_virtual_device.mutable_state()->simulate_invalid_response = true;
+
+ SimulateNavigation(GURL(kTestOrigin1));
+ AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+ {
+ PublicKeyCredentialRequestOptionsPtr options =
+ GetTestPublicKeyCredentialRequestOptions();
+ TestGetAssertionCallback callback_receiver;
+ authenticator->GetAssertion(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
+ callback_receiver.status());
+ }
+
+ {
+ PublicKeyCredentialCreationOptionsPtr options =
+ GetTestPublicKeyCredentialCreationOptions();
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+
+ EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
+ callback_receiver.status());
+ }
}
enum class IndividualAttestation {
@@ -894,10 +1191,11 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
options->relying_party->id = "example.com";
options->adjusted_timeout = base::TimeDelta::FromSeconds(1);
options->attestation = test.attestation_requested;
- TestMakeCredentialCallback cb;
- authenticator->MakeCredential(std::move(options), cb.callback());
- cb.WaitForCallback();
- ASSERT_EQ(test.expected_status, cb.status());
+ TestMakeCredentialCallback callback_receiver;
+ authenticator->MakeCredential(std::move(options),
+ callback_receiver.callback());
+ callback_receiver.WaitForCallback();
+ ASSERT_EQ(test.expected_status, callback_receiver.status());
if (test.expected_status != AuthenticatorStatus::SUCCESS) {
ASSERT_STREQ("", test.expected_attestation_format);
@@ -905,7 +1203,7 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
}
base::Optional<CBORValue> attestation_value =
- CBORReader::Read(cb.value()->attestation_object);
+ CBORReader::Read(callback_receiver.value()->attestation_object);
ASSERT_TRUE(attestation_value);
ASSERT_TRUE(attestation_value->is_map());
const auto& attestation = attestation_value->GetMap();
@@ -954,8 +1252,8 @@ class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
<< "', but expected to find '" << expected << "'";
}
- // Asserts that the webauthn attestation CBOR map in |attestation| contains
- // a single X.509 certificate containing |substring|.
+ // Asserts that the webauthn attestation CBOR map in
+ // |attestation| contains a single X.509 certificate containing |substring|.
static void ExpectCertificateContainingSubstring(
const CBORValue::MapValue& attestation,
const std::string& substring) {
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.cc b/chromium/content/browser/webauth/authenticator_type_converters.cc
index c8d238b97ad..47f14b163a7 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.cc
+++ b/chromium/content/browser/webauth/authenticator_type_converters.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "device/fido/fido_constants.h"
+#include "device/fido/fido_parsing_utils.h"
namespace mojo {
@@ -19,6 +20,7 @@ using ::webauth::mojom::PublicKeyCredentialDescriptorPtr;
using ::webauth::mojom::AuthenticatorSelectionCriteriaPtr;
using ::webauth::mojom::AuthenticatorAttachment;
using ::webauth::mojom::UserVerificationRequirement;
+using ::webauth::mojom::CableAuthenticationPtr;
// static
::device::FidoTransportProtocol
@@ -77,9 +79,7 @@ TypeConverter<std::vector<::device::PublicKeyCredentialDescriptor>,
for (const auto& credential : input) {
credential_descriptors.emplace_back(::device::PublicKeyCredentialDescriptor(
- device::to_string(
- ConvertTo<::device::CredentialType>(credential->type)),
- credential->id));
+ ConvertTo<::device::CredentialType>(credential->type), credential->id));
}
return credential_descriptors;
}
@@ -161,4 +161,35 @@ TypeConverter<::device::PublicKeyCredentialUserEntity,
return user_entity;
}
+// static
+std::vector<::device::FidoCableDiscovery::CableDiscoveryData>
+TypeConverter<std::vector<::device::FidoCableDiscovery::CableDiscoveryData>,
+ std::vector<CableAuthenticationPtr>>::
+ Convert(const std::vector<CableAuthenticationPtr>& input) {
+ std::vector<::device::FidoCableDiscovery::CableDiscoveryData> discovery_data;
+ discovery_data.reserve(input.size());
+
+ for (const auto& data : input) {
+ ::device::FidoCableDiscovery::EidArray client_eid;
+ DCHECK_EQ(client_eid.size(), data->client_eid.size());
+ std::copy(data->client_eid.begin(), data->client_eid.end(),
+ client_eid.begin());
+
+ ::device::FidoCableDiscovery::EidArray authenticator_eid;
+ DCHECK_EQ(authenticator_eid.size(), data->authenticator_eid.size());
+ std::copy(data->authenticator_eid.begin(), data->authenticator_eid.end(),
+ authenticator_eid.begin());
+
+ ::device::FidoCableDiscovery::SessionKeyArray session_key;
+ DCHECK_EQ(session_key.size(), data->session_pre_key.size());
+ std::copy(data->session_pre_key.begin(), data->session_pre_key.end(),
+ session_key.begin());
+
+ discovery_data.push_back(::device::FidoCableDiscovery::CableDiscoveryData{
+ data->version, client_eid, authenticator_eid, session_key});
+ }
+
+ return discovery_data;
+}
+
} // namespace mojo
diff --git a/chromium/content/browser/webauth/authenticator_type_converters.h b/chromium/content/browser/webauth/authenticator_type_converters.h
index 0f5c2a1a13c..97431318615 100644
--- a/chromium/content/browser/webauth/authenticator_type_converters.h
+++ b/chromium/content/browser/webauth/authenticator_type_converters.h
@@ -8,6 +8,7 @@
#include <vector>
#include "device/fido/authenticator_selection_criteria.h"
+#include "device/fido/fido_cable_discovery.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h"
@@ -89,6 +90,14 @@ struct TypeConverter<::device::PublicKeyCredentialUserEntity,
const ::webauth::mojom::PublicKeyCredentialUserEntityPtr& input);
};
+template <>
+struct TypeConverter<
+ std::vector<::device::FidoCableDiscovery::CableDiscoveryData>,
+ std::vector<::webauth::mojom::CableAuthenticationPtr>> {
+ static std::vector<::device::FidoCableDiscovery::CableDiscoveryData> Convert(
+ const std::vector<::webauth::mojom::CableAuthenticationPtr>& input);
+};
+
} // namespace mojo
#endif // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_TYPE_CONVERTERS_H_
diff --git a/chromium/content/browser/webauth/virtual_authenticator.cc b/chromium/content/browser/webauth/virtual_authenticator.cc
index f830a24927a..71cdfac4400 100644
--- a/chromium/content/browser/webauth/virtual_authenticator.cc
+++ b/chromium/content/browser/webauth/virtual_authenticator.cc
@@ -9,6 +9,7 @@
#include "base/guid.h"
#include "crypto/ec_private_key.h"
+#include "device/fido/virtual_u2f_device.h"
namespace content {
@@ -26,7 +27,7 @@ void VirtualAuthenticator::AddBinding(
}
std::unique_ptr<::device::FidoDevice> VirtualAuthenticator::ConstructDevice() {
- return std::make_unique<::device::VirtualFidoDevice>(state_);
+ return std::make_unique<::device::VirtualU2fDevice>(state_);
}
void VirtualAuthenticator::GetUniqueId(GetUniqueIdCallback callback) {
diff --git a/chromium/content/browser/webauth/webauth_browsertest.cc b/chromium/content/browser/webauth/webauth_browsertest.cc
index b86f292e90d..59b558ffc01 100644
--- a/chromium/content/browser/webauth/webauth_browsertest.cc
+++ b/chromium/content/browser/webauth/webauth_browsertest.cc
@@ -311,7 +311,8 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
std::move(rp), std::move(user), kTestChallenge, std::move(parameters),
base::TimeDelta::FromSeconds(30),
std::vector<webauth::mojom::PublicKeyCredentialDescriptorPtr>(),
- nullptr, webauth::mojom::AttestationConveyancePreference::NONE);
+ nullptr, webauth::mojom::AttestationConveyancePreference::NONE,
+ nullptr);
return mojo_options;
}
@@ -333,8 +334,8 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
auto mojo_options = webauth::mojom::PublicKeyCredentialRequestOptions::New(
kTestChallenge, base::TimeDelta::FromSeconds(30), "acme.com",
std::move(credentials),
- webauth::mojom::UserVerificationRequirement::PREFERRED, base::nullopt);
-
+ webauth::mojom::UserVerificationRequirement::PREFERRED, base::nullopt,
+ std::vector<webauth::mojom::CableAuthenticationPtr>());
return mojo_options;
}
diff --git a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
index 5b66e50b2a3..1a57c79ba8c 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_browsertest.cc
@@ -4,10 +4,12 @@
#include "base/command_line.h"
#include "base/files/file_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/webrtc/webrtc_content_browsertest_base.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/webrtc_ip_handling_policy.h"
#include "content/public/test/browser_test_utils.h"
@@ -15,22 +17,28 @@
#include "content/public/test/test_utils.h"
#include "media/base/media_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest-param-test.h"
namespace content {
-#if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
-// Renderer crashes under Android ASAN: https://crbug.com/408496.
-#define MAYBE_WebRtcAudioBrowserTest DISABLED_WebRtcAudioBrowserTest
-#else
-#define MAYBE_WebRtcAudioBrowserTest WebRtcAudioBrowserTest
-#endif
-
// This class tests the scenario when permission to access mic or camera is
// granted.
-class MAYBE_WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase {
+class WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase,
+ public testing::WithParamInterface<bool> {
public:
- MAYBE_WebRtcAudioBrowserTest() {}
- ~MAYBE_WebRtcAudioBrowserTest() override {}
+ WebRtcAudioBrowserTest() {
+ std::vector<base::Feature> audio_service_oop_features = {
+ features::kAudioServiceAudioStreams,
+ features::kAudioServiceOutOfProcess};
+ if (GetParam()) {
+ // Force audio service out of process to enabled.
+ audio_service_features_.InitWithFeatures(audio_service_oop_features, {});
+ } else {
+ // Force audio service out of process to disabled.
+ audio_service_features_.InitWithFeatures({}, audio_service_oop_features);
+ }
+ }
+ ~WebRtcAudioBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
WebRtcContentBrowserTestBase::SetUpCommandLine(command_line);
@@ -59,60 +67,76 @@ class MAYBE_WebRtcAudioBrowserTest : public WebRtcContentBrowserTestBase {
MakeTypicalCall(javascript, "/media/peerconnection-call-audio.html");
}
+
+ private:
+ base::test::ScopedFeatureList audio_service_features_;
};
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
CanMakeVideoCallAndThenRenegotiateToAudio) {
MakeAudioDetectingPeerConnectionCall(
"callAndRenegotiateToAudio({audio: true, video:true}, {audio: true});");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EstablishAudioVideoCallAndEnsureAudioIsPlaying) {
MakeAudioDetectingPeerConnectionCall(
"callAndEnsureAudioIsPlaying({audio:true, video:true});");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EstablishAudioOnlyCallAndEnsureAudioIsPlaying) {
MakeAudioDetectingPeerConnectionCall(
"callAndEnsureAudioIsPlaying({audio:true});");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EstablishIsac16KCallAndEnsureAudioIsPlaying) {
MakeAudioDetectingPeerConnectionCall(
"callWithIsac16KAndEnsureAudioIsPlaying({audio:true});");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EstablishAudioVideoCallAndVerifyRemoteMutingWorks) {
MakeAudioDetectingPeerConnectionCall(
"callAndEnsureRemoteAudioTrackMutingWorks();");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EstablishAudioVideoCallAndVerifyLocalMutingWorks) {
MakeAudioDetectingPeerConnectionCall(
"callAndEnsureLocalAudioTrackMutingWorks();");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EnsureLocalVideoMuteDoesntMuteAudio) {
MakeAudioDetectingPeerConnectionCall(
"callAndEnsureLocalVideoMutingDoesntMuteAudio();");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EnsureRemoteVideoMuteDoesntMuteAudio) {
MakeAudioDetectingPeerConnectionCall(
"callAndEnsureRemoteVideoMutingDoesntMuteAudio();");
}
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcAudioBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
EstablishAudioVideoCallAndVerifyUnmutingWorks) {
MakeAudioDetectingPeerConnectionCall(
"callAndEnsureAudioTrackUnmutingWorks();");
}
+// We run these tests with the audio service both in and out of the the browser
+// process to have waterfall coverage while the feature rolls out. It should be
+// removed after launch.
+#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
+// Supported platforms.
+INSTANTIATE_TEST_CASE_P(, WebRtcAudioBrowserTest, ::testing::Bool());
+#elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
+// Renderer crashes under Android ASAN: https://crbug.com/408496.
+#else
+// Platforms where the out of process audio service isn't supported
+INSTANTIATE_TEST_CASE_P(, WebRtcAudioBrowserTest, ::testing::Values(false));
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc b/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
index 09e55b0a0f0..965c78d992f 100644
--- a/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
@@ -38,7 +38,7 @@ const base::FilePath::CharType kBaseFilename[] =
bool GetRenderProcessHostId(base::ProcessId* id) {
content::RenderProcessHost::iterator it(
content::RenderProcessHost::AllHostsIterator());
- *id = base::GetProcId(it.GetCurrentValue()->GetHandle());
+ *id = it.GetCurrentValue()->GetProcess().Pid();
EXPECT_NE(base::kNullProcessId, *id);
if (*id == base::kNullProcessId)
return false;
@@ -343,7 +343,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
base::FilePath file_path;
for (; !it.IsAtEnd(); it.Advance()) {
base::ProcessId render_process_id =
- base::GetProcId(it.GetCurrentValue()->GetHandle());
+ it.GetCurrentValue()->GetProcess().Pid();
EXPECT_NE(base::kNullProcessId, render_process_id);
file_path = GetExpectedAecDumpFileName(base_file_path, render_process_id);
diff --git a/chromium/content/browser/webrtc/webrtc_browsertest.cc b/chromium/content/browser/webrtc/webrtc_browsertest.cc
index 820322191dc..cbbb5ee815c 100644
--- a/chromium/content/browser/webrtc/webrtc_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_browsertest.cc
@@ -15,6 +15,7 @@
#include "content/public/test/test_utils.h"
#include "media/audio/audio_manager.h"
#include "media/base/media_switches.h"
+#include "media/media_buildflags.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
namespace content {
@@ -103,16 +104,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
MakeTypicalPeerConnectionCall(javascript);
}
-
-#if defined(OS_WIN) && !defined(NVALGRIND)
-// Times out on Dr. Memory bots: https://crbug.com/545740
-#define MAYBE_CanSetupCallAndSendDtmf DISABLED_CanSetupCallAndSendDtmf
-#else
-#define MAYBE_CanSetupCallAndSendDtmf CanSetupCallAndSendDtmf
-#endif
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
- MAYBE_CanSetupCallAndSendDtmf) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, CanSetupCallAndSendDtmf) {
MakeTypicalPeerConnectionCall("callAndSendDtmf(\'123,ABC\');");
}
@@ -241,7 +233,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
"testGetSettingsWhenRemoteDimensionsUnknown();");
}
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) && BUILDFLAG(USE_PROPRIETARY_CODECS)
// This test is to make sure HW H264 work normally on supported devices, since
// there is no SW H264 fallback available on Android.
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
diff --git a/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
index d4d59b8c93a..7b67681f34c 100644
--- a/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -109,8 +109,8 @@ IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
}
IN_PROC_BROWSER_TEST_F(WebRtcCaptureFromElementBrowserTest,
- VerifyCanvasCaptureOffscreenCanvasCommitFrames) {
- MakeTypicalCall("testCanvasCapture(drawOffscreenCanvasCommit);",
+ VerifyCanvasCaptureOffscreenCanvasFrames) {
+ MakeTypicalCall("testCanvasCapture(drawOffscreenCanvas);",
kCanvasCaptureTestHtmlFile);
}
diff --git a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 254ff38788f..339d6f044fb 100644
--- a/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/json/json_reader.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -15,6 +16,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/webrtc/webrtc_content_browsertest_base.h"
#include "content/browser/webrtc/webrtc_internals.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -22,7 +24,9 @@
#include "content/shell/browser/shell.h"
#include "media/audio/audio_manager.h"
#include "media/audio/fake_audio_input_stream.h"
+#include "media/base/media_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest-param-test.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
@@ -94,11 +98,22 @@ bool VerifyDisableLocalEcho(bool expect_value,
namespace content {
-class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase {
+class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase,
+ public testing::WithParamInterface<bool> {
public:
WebRtcGetUserMediaBrowserTest() {
// Automatically grant device permission.
AppendUseFakeUIForMediaStreamFlag();
+ std::vector<base::Feature> audio_service_oop_features = {
+ features::kAudioServiceAudioStreams,
+ features::kAudioServiceOutOfProcess};
+ if (GetParam()) {
+ // Force audio service out of process to enabled.
+ audio_service_features_.InitWithFeatures(audio_service_oop_features, {});
+ } else {
+ // Force audio service out of process to disabled.
+ audio_service_features_.InitWithFeatures({}, audio_service_oop_features);
+ }
}
~WebRtcGetUserMediaBrowserTest() override {}
@@ -158,6 +173,9 @@ class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase {
ASSERT_FALSE(audio_ids->empty());
ASSERT_FALSE(video_ids->empty());
}
+
+ private:
+ base::test::ScopedFeatureList audio_service_features_;
};
// These tests will all make a getUserMedia call with different constraints and
@@ -170,7 +188,7 @@ class WebRtcGetUserMediaBrowserTest : public WebRtcContentBrowserTestBase {
#else
#define MAYBE_GetVideoStreamAndStop GetVideoStreamAndStop
#endif
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
MAYBE_GetVideoStreamAndStop) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -189,7 +207,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
#define MAYBE_RenderSameTrackMediastreamAndStop \
RenderSameTrackMediastreamAndStop
#endif
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
MAYBE_RenderSameTrackMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -201,7 +219,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
kRenderSameTrackMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
RenderClonedMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -214,7 +232,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
kRenderClonedMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
kRenderClonedTrackMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -226,7 +244,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
kRenderClonedTrackMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
kRenderDuplicatedMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -238,7 +256,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
kRenderDuplicatedMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetAudioAndVideoStreamAndStop) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -249,7 +267,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
"%s({video: true, audio: true});", kGetUserMediaAndStop));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetAudioAndVideoStreamAndClone) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -260,7 +278,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
}
// TODO(crbug.com/803516) : Flaky on all platforms.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
DISABLED_RenderVideoTrackInMultipleTagsAndPause) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -278,7 +296,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
#define MAYBE_GetUserMediaWithMandatorySourceID \
GetUserMediaWithMandatorySourceID
#endif
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
MAYBE_GetUserMediaWithMandatorySourceID) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -304,7 +322,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
}
#undef MAYBE_GetUserMediaWithMandatorySourceID
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetUserMediaWithInvalidMandatorySourceID) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -336,7 +354,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
kGetUserMediaAndExpectFailure, "", video_ids[0])));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetUserMediaWithInvalidOptionalSourceID) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -369,8 +387,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
video_ids[0])));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
- TwoGetUserMediaAndStop) {
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -380,7 +397,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
"twoGetUserMediaAndStop({video: true, audio: true});");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
TwoGetUserMediaWithEqualConstraints) {
std::string constraints1 = "{video: true, audio: true}";
const std::string& constraints2 = constraints1;
@@ -390,7 +407,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
expected_result);
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
TwoGetUserMediaWithSecondVideoCropped) {
std::string constraints1 = "{video: true}";
std::string constraints2 =
@@ -408,7 +425,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
#define MAYBE_TwoGetUserMediaWithFirstHdSecondVga \
TwoGetUserMediaWithFirstHdSecondVga
#endif
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
MAYBE_TwoGetUserMediaWithFirstHdSecondVga) {
std::string constraints1 =
"{video: {width : {exact: 1280}, height: {exact: 720}}}";
@@ -421,7 +438,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
// Timing out on Windows 7 bot: http://crbug.com/443294
// Flaky: http://crbug.com/660656; possible the test is too perf sensitive.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
DISABLED_TwoGetUserMediaWithFirst1080pSecondVga) {
std::string constraints1 =
"{video: {mandatory: {maxWidth:1920 , minWidth:1920 , maxHeight: 1080, "
@@ -433,7 +450,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
expected_result);
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetUserMediaWithTooHighVideoConstraintsValues) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -452,16 +469,16 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
EXPECT_EQ("OverconstrainedError", ExecuteJavascriptAndReturnResult(call));
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetUserMediaFailToAccessAudioDevice) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
- // Set the maximum allowed input and output streams to 0
- // so that the call to create a new audio input stream will fail.
- media::AudioManager::Get()->SetMaxStreamCountForTesting(0, 0);
+ // Make sure we'll fail creating the audio stream.
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kFailAudioStreamCreation);
const std::string call = base::StringPrintf(
"%s({video: false, audio: true});", kGetUserMediaAndExpectFailure);
@@ -471,7 +488,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
// This test makes two getUserMedia requests, one with impossible constraints
// that should trigger an error, and one with valid constraints. The test
// verifies getUserMedia can succeed after being given impossible constraints.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
TwoGetUserMediaAndCheckCallbackAfterFailure) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -507,7 +524,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
#endif
// This test calls getUserMedia and checks for aspect ratio behavior.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
TestGetUserMediaAspectRatio4To3) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -522,7 +539,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
}
// This test calls getUserMedia and checks for aspect ratio behavior.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
TestGetUserMediaAspectRatio16To9) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -537,7 +554,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
}
// This test calls getUserMedia and checks for aspect ratio behavior.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
TestGetUserMediaAspectRatio1To1) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -554,7 +571,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
// This test calls getUserMedia in an iframe and immediately close the iframe
// in the scope of the success callback.
// Flaky: crbug.com/727601.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
DISABLED_AudioInIFrameAndCloseInSuccessCb) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -567,7 +584,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
}
// Flaky: crbug.com/807638
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
DISABLED_VideoInIFrameAndCloseInSuccessCb) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -581,7 +598,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
// This test calls getUserMedia in an iframe and immediately close the iframe
// in the scope of the failure callback.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
VideoWithBadConstraintsInIFrameAndCloseInFailureCb) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -601,7 +618,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk(call);
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
InvalidSourceIdInIFrameAndCloseInFailureCb) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -615,7 +632,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk(call);
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
DisableLocalEchoParameter) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
@@ -628,13 +645,13 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
BrowserMainLoop::GetInstance()->media_stream_manager();
manager->SetGenerateStreamCallbackForTesting(
- base::Bind(&VerifyDisableLocalEcho, false));
+ base::BindOnce(&VerifyDisableLocalEcho, false));
std::string call = GenerateGetUserMediaWithDisableLocalEcho(
"getUserMediaAndExpectSuccess", "false");
ExecuteJavascriptAndWaitForOk(call);
manager->SetGenerateStreamCallbackForTesting(
- base::Bind(&VerifyDisableLocalEcho, true));
+ base::BindOnce(&VerifyDisableLocalEcho, true));
call = GenerateGetUserMediaWithDisableLocalEcho(
"getUserMediaAndExpectSuccess", "true");
ExecuteJavascriptAndWaitForOk(call);
@@ -643,14 +660,14 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
MediaStreamManager::GenerateStreamTestCallback());
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetAudioSettingsDefault) {
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, GetAudioSettingsDefault) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
ExecuteJavascriptAndWaitForOk("getAudioSettingsDefault()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetAudioSettingsNoEchoCancellation) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -658,7 +675,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("getAudioSettingsNoEchoCancellation()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetAudioSettingsDeviceId) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -666,72 +683,39 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("getAudioSettingsDeviceId()");
}
-
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
- GetAudioStreamAndCheckMutingInitiallyUnmuted) {
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, SrcObjectAddVideoTrack) {
ASSERT_TRUE(embedded_test_server()->Start());
-
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
-
- // Expect stream to initially not be muted
- media::FakeAudioInputStream::SetGlobalMutedState(false);
- ExecuteJavascriptAndWaitForOk(
- base::StringPrintf("%s(false);", kGetUserMediaForAudioMutingTest));
-
- // Mute
- media::FakeAudioInputStream::SetGlobalMutedState(true);
- EXPECT_EQ("onmute: muted=true, readyState=live",
- ExecuteJavascriptAndReturnResult(
- "failTestAfterTimeout('Got no mute event', 1500);"));
- // Unmute
- media::FakeAudioInputStream::SetGlobalMutedState(false);
- EXPECT_EQ("onunmute: muted=false, readyState=live",
- ExecuteJavascriptAndReturnResult(
- "failTestAfterTimeout('Got no unmute event', 1500);"));
-}
-
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
- GetAudioStreamAndCheckMutingInitiallyMuted) {
- ASSERT_TRUE(embedded_test_server()->Start());
-
- GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
- NavigateToURL(shell(), url);
-
- // Expect stream to initially be muted
- media::FakeAudioInputStream::SetGlobalMutedState(true);
- ExecuteJavascriptAndWaitForOk(
- base::StringPrintf("%s(true);", kGetUserMediaForAudioMutingTest));
-
- // Unmute
- media::FakeAudioInputStream::SetGlobalMutedState(false);
- EXPECT_EQ("onunmute: muted=false, readyState=live",
- ExecuteJavascriptAndReturnResult(
- "failTestAfterTimeout('Got no unmute event', 1500);"));
-
- // Mute
- media::FakeAudioInputStream::SetGlobalMutedState(true);
- EXPECT_EQ("onmute: muted=true, readyState=live",
- ExecuteJavascriptAndReturnResult(
- "failTestAfterTimeout('Got no mute event', 1500);"));
+ ExecuteJavascriptAndWaitForOk("srcObjectAddVideoTrack()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, SrcObjectAddVideoTrack) {
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+ SrcObjectReplaceInactiveTracks) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
- ExecuteJavascriptAndWaitForOk("srcObjectAddVideoTrack()");
+ ExecuteJavascriptAndWaitForOk("srcObjectReplaceInactiveTracks()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
- SrcObjectRemoveVideoTrack) {
+// Flaky on all platforms. https://crbug.com/835332
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+ DISABLED_SrcObjectRemoveVideoTrack) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
ExecuteJavascriptAndWaitForOk("srcObjectRemoveVideoTrack()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+// Flaky on memory and leak sanitizers. https://crbug.com/843844
+#if defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER)
+#define MAYBE_SrcObjectRemoveFirstOfTwoVideoTracks \
+ DISABLED_SrcObjectRemoveFirstOfTwoVideoTracks
+#else
+#define MAYBE_SrcObjectRemoveFirstOfTwoVideoTracks \
+ SrcObjectRemoveFirstOfTwoVideoTracks
+#endif
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
SrcObjectRemoveFirstOfTwoVideoTracks) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -743,7 +727,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
// when a straightforward mechanism to detect the presence/absence of audio in a
// media element with an assigned MediaStream becomes available.
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
SrcObjectReassignSameObject) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -751,14 +735,14 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("srcObjectReassignSameObject()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, ApplyConstraintsVideo) {
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, ApplyConstraintsVideo) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
NavigateToURL(shell(), url);
ExecuteJavascriptAndWaitForOk("applyConstraintsVideo()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
ApplyConstraintsVideoTwoStreams) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -766,7 +750,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("applyConstraintsVideoTwoStreams()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
ApplyConstraintsVideoOverconstrained) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -774,7 +758,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("applyConstraintsVideoOverconstrained()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
ApplyConstraintsNonDevice) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -782,7 +766,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("applyConstraintsNonDevice()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
ConcurrentGetUserMediaStop) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -790,7 +774,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("concurrentGetUserMediaStop()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetUserMediaAfterStopElementCapture) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -798,7 +782,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("getUserMediaAfterStopCanvasCapture()");
}
-IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
GetUserMediaEchoCancellationOnAndOff) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -806,4 +790,77 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("getUserMediaEchoCancellationOnAndOff()");
}
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+ GetAudioStreamAndCheckMutingInitiallyUnmuted) {
+ // Muting tests do not work with the out-of-process audio service.
+ // https://crbug.com/843490.
+ if (GetParam())
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ // Expect stream to initially not be muted
+ media::FakeAudioInputStream::SetGlobalMutedState(false);
+ ExecuteJavascriptAndWaitForOk(
+ base::StringPrintf("%s(false);", kGetUserMediaForAudioMutingTest));
+
+ // Mute
+ media::FakeAudioInputStream::SetGlobalMutedState(true);
+ EXPECT_EQ("onmute: muted=true, readyState=live",
+ ExecuteJavascriptAndReturnResult(
+ "failTestAfterTimeout('Got no mute event', 1500);"));
+ // Unmute
+ media::FakeAudioInputStream::SetGlobalMutedState(false);
+ EXPECT_EQ("onunmute: muted=false, readyState=live",
+ ExecuteJavascriptAndReturnResult(
+ "failTestAfterTimeout('Got no unmute event', 1500);"));
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+ GetAudioStreamAndCheckMutingInitiallyMuted) {
+ // Muting tests do not work with the out-of-process audio service.
+ // https://crbug.com/843490.
+ if (GetParam())
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ // Expect stream to initially be muted
+ media::FakeAudioInputStream::SetGlobalMutedState(true);
+ ExecuteJavascriptAndWaitForOk(
+ base::StringPrintf("%s(true);", kGetUserMediaForAudioMutingTest));
+
+ // Unmute
+ media::FakeAudioInputStream::SetGlobalMutedState(false);
+ EXPECT_EQ("onunmute: muted=false, readyState=live",
+ ExecuteJavascriptAndReturnResult(
+ "failTestAfterTimeout('Got no unmute event', 1500);"));
+
+ // Mute
+ media::FakeAudioInputStream::SetGlobalMutedState(true);
+ EXPECT_EQ("onmute: muted=true, readyState=live",
+ ExecuteJavascriptAndReturnResult(
+ "failTestAfterTimeout('Got no mute event', 1500);"));
+}
+
+// We run these tests with the audio service both in and out of the the browser
+// process to have waterfall coverage while the feature rolls out. It should be
+// removed after launch.
+#if (defined(OS_LINUX) && !defined(CHROME_OS)) || defined(OS_MACOSX) || \
+ defined(OS_WIN)
+// Supported platforms.
+INSTANTIATE_TEST_CASE_P(, WebRtcGetUserMediaBrowserTest, ::testing::Bool());
+#else
+// Platforms where the out of process audio service is not supported
+INSTANTIATE_TEST_CASE_P(,
+ WebRtcGetUserMediaBrowserTest,
+ ::testing::Values(false));
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/webrtc/webrtc_internals.cc b/chromium/content/browser/webrtc/webrtc_internals.cc
index eb7e04af19b..b8e4b8b1cc5 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals.cc
@@ -109,10 +109,6 @@ WebRTCInternals::WebRTCInternals(int aggregate_updates_ms,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!g_webrtc_internals);
-// TODO(grunell): Shouldn't all the webrtc_internals* files be excluded from the
-// build if WebRTC is disabled?
-// https://crbug.com/817446
-#if BUILDFLAG(ENABLE_WEBRTC)
audio_debug_recordings_file_path_ =
GetContentClient()->browser()->GetDefaultDownloadDirectory();
event_log_recordings_file_path_ = audio_debug_recordings_file_path_;
@@ -143,7 +139,6 @@ WebRTCInternals::WebRTCInternals(int aggregate_updates_ms,
event_log_recordings_ = true;
event_log_recordings_file_path_.clear();
}
-#endif // BUILDFLAG(ENABLE_WEBRTC)
g_webrtc_internals = this;
}
@@ -333,7 +328,6 @@ void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) {
void WebRTCInternals::EnableAudioDebugRecordings(
content::WebContents* web_contents) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-#if BUILDFLAG(ENABLE_WEBRTC)
#if defined(OS_ANDROID)
EnableAudioDebugRecordingsOnAllRenderProcessHosts();
#else
@@ -346,12 +340,10 @@ void WebRTCInternals::EnableAudioDebugRecordings(
base::FilePath::StringType(), web_contents->GetTopLevelNativeWindow(),
nullptr);
#endif
-#endif
}
void WebRTCInternals::DisableAudioDebugRecordings() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-#if BUILDFLAG(ENABLE_WEBRTC)
if (!audio_debug_recording_session_)
return;
audio_debug_recording_session_.reset();
@@ -365,7 +357,6 @@ void WebRTCInternals::DisableAudioDebugRecordings() {
!i.IsAtEnd(); i.Advance()) {
i.GetCurrentValue()->DisableAudioDebugRecordings();
}
-#endif
}
bool WebRTCInternals::IsAudioDebugRecordingsEnabled() const {
@@ -382,7 +373,6 @@ void WebRTCInternals::EnableLocalEventLogRecordings(
content::WebContents* web_contents) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(CanToggleEventLogRecordings());
-#if BUILDFLAG(ENABLE_WEBRTC)
#if defined(OS_ANDROID)
WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
if (logger) {
@@ -398,11 +388,9 @@ void WebRTCInternals::EnableLocalEventLogRecordings(
event_log_recordings_file_path_, nullptr, 0, FILE_PATH_LITERAL(""),
web_contents->GetTopLevelNativeWindow(), nullptr);
#endif
-#endif
}
void WebRTCInternals::DisableLocalEventLogRecordings() {
-#if BUILDFLAG(ENABLE_WEBRTC)
event_log_recordings_ = false;
// Tear down the dialog since the user has unchecked the event log checkbox.
select_file_dialog_ = nullptr;
@@ -411,7 +399,6 @@ void WebRTCInternals::DisableLocalEventLogRecordings() {
if (logger) {
logger->DisableLocalLogging();
}
-#endif
}
bool WebRTCInternals::IsEventLogRecordingsEnabled() const {
@@ -440,9 +427,9 @@ void WebRTCInternals::SendUpdate(const char* command,
}
}
-void WebRTCInternals::RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {
+void WebRTCInternals::RenderProcessExited(
+ RenderProcessHost* host,
+ const ChildProcessTerminationInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
OnRendererExit(host->GetID());
render_process_id_set_.erase(host->GetID());
@@ -452,7 +439,6 @@ void WebRTCInternals::RenderProcessExited(RenderProcessHost* host,
void WebRTCInternals::FileSelected(const base::FilePath& path,
int /* unused_index */,
void* /*unused_params */) {
-#if BUILDFLAG(ENABLE_WEBRTC)
DCHECK_CURRENTLY_ON(BrowserThread::UI);
switch (selection_type_) {
case SelectionType::kRtcEventLogs: {
@@ -471,11 +457,9 @@ void WebRTCInternals::FileSelected(const base::FilePath& path,
}
default: { NOTREACHED(); }
}
-#endif
}
void WebRTCInternals::FileSelectionCanceled(void* params) {
-#if BUILDFLAG(ENABLE_WEBRTC)
DCHECK_CURRENTLY_ON(BrowserThread::UI);
switch (selection_type_) {
case SelectionType::kRtcEventLogs:
@@ -488,7 +472,6 @@ void WebRTCInternals::FileSelectionCanceled(void* params) {
NOTREACHED();
}
select_file_dialog_ = nullptr;
-#endif
}
void WebRTCInternals::OnRendererExit(int render_process_id) {
@@ -544,7 +527,6 @@ void WebRTCInternals::OnRendererExit(int render_process_id) {
}
}
-#if BUILDFLAG(ENABLE_WEBRTC)
void WebRTCInternals::EnableAudioDebugRecordingsOnAllRenderProcessHosts() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!audio_debug_recording_session_);
@@ -561,7 +543,6 @@ void WebRTCInternals::EnableAudioDebugRecordingsOnAllRenderProcessHosts() {
audio_debug_recordings_file_path_);
}
}
-#endif
void WebRTCInternals::MaybeClosePeerConnection(base::DictionaryValue* record) {
bool is_open;
diff --git a/chromium/content/browser/webrtc/webrtc_internals.h b/chromium/content/browser/webrtc/webrtc_internals.h
index 04c8e2a2342..b8b0c6097c1 100644
--- a/chromium/content/browser/webrtc/webrtc_internals.h
+++ b/chromium/content/browser/webrtc/webrtc_internals.h
@@ -151,8 +151,7 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
// RenderProcessHostObserver implementation.
void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) override;
+ const ChildProcessTerminationInfo& info) override;
// ui::SelectFileDialog::Listener implementation.
void FileSelected(const base::FilePath& path,
@@ -163,11 +162,9 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
// Called when a renderer exits (including crashes).
void OnRendererExit(int render_process_id);
-#if BUILDFLAG(ENABLE_WEBRTC)
// Enables diagnostic audio recordings on all render process hosts using
// |audio_debug_recordings_file_path_|.
void EnableAudioDebugRecordingsOnAllRenderProcessHosts();
-#endif
// Updates the number of open PeerConnections. Called when a PeerConnection
// is stopped or removed.
diff --git a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
index fc9d9402e38..8e4dd0a0687 100644
--- a/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
+++ b/chromium/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <string>
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "content/browser/webrtc/webrtc_internals_ui_observer.h"
diff --git a/chromium/content/browser/websockets/README.md b/chromium/content/browser/websockets/README.md
index 80f5e442af1..67593763a49 100644
--- a/chromium/content/browser/websockets/README.md
+++ b/chromium/content/browser/websockets/README.md
@@ -1,5 +1,5 @@
# WebSocket service
-This directory contains the network::mojom::WebSocket implementation. It hosts
+This directory contains the network.mojom.WebSocket implementation. It hosts
the WebSocket API implementations in Blink over Mojo, and exports the WebSocket
protocol implementation in net/websockets/ as a service.
diff --git a/chromium/content/browser/websockets/websocket_manager.cc b/chromium/content/browser/websockets/websocket_manager.cc
index fad1a1d3cb4..c1ae8621402 100644
--- a/chromium/content/browser/websockets/websocket_manager.cc
+++ b/chromium/content/browser/websockets/websocket_manager.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
@@ -23,6 +24,8 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/storage_partition.h"
+#include "services/network/network_context.h"
+#include "services/network/public/cpp/features.h"
namespace content {
@@ -63,11 +66,8 @@ class WebSocketManager::Delegate final : public network::WebSocket::Delegate {
void ReportBadMessage(BadMessageReason reason,
network::WebSocket* impl) override {
bad_message::BadMessageReason reason_to_pass =
- bad_message::WSI_INVALID_HEADER_VALUE;
+ bad_message::WSI_UNEXPECTED_ADD_CHANNEL_REQUEST;
switch (reason) {
- case BadMessageReason::kInvalidHeaderValue:
- reason_to_pass = bad_message::WSI_INVALID_HEADER_VALUE;
- break;
case BadMessageReason::kUnexpectedAddChannelRequest:
reason_to_pass = bad_message::WSI_UNEXPECTED_ADD_CHANNEL_REQUEST;
break;
@@ -157,31 +157,25 @@ class WebSocketManager::Handle : public base::SupportsUserData::Data,
};
// static
-void WebSocketManager::CreateWebSocketForFrame(
+void WebSocketManager::CreateWebSocket(
int process_id,
int frame_id,
- network::mojom::WebSocketRequest request) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // ForFrame() implies a frame: DCHECK this pre-condition.
- RenderFrameHost* frame = RenderFrameHost::FromID(process_id, frame_id);
- DCHECK(frame);
-
- CreateWebSocketWithOrigin(process_id, frame->GetLastCommittedOrigin(),
- std::move(request), frame_id);
-}
-
-// static
-void WebSocketManager::CreateWebSocketWithOrigin(
- int process_id,
url::Origin origin,
- network::mojom::WebSocketRequest request,
- int frame_id) {
+ network::mojom::WebSocketRequest request) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RenderProcessHost* host = RenderProcessHost::FromID(process_id);
DCHECK(host);
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ StoragePartition* storage_partition = host->GetStoragePartition();
+ network::mojom::NetworkContext* network_context =
+ storage_partition->GetNetworkContext();
+ network_context->CreateWebSocket(std::move(request), process_id, frame_id,
+ origin);
+ return;
+ }
+
// Maintain a WebSocketManager per RenderProcessHost. While the instance of
// WebSocketManager is allocated on the UI thread, it must only be used and
// deleted from the IO thread.
@@ -255,7 +249,7 @@ void WebSocketManager::DoCreateWebSocket(
// Keep all network::WebSockets alive until either the client drops its
// connection (see OnLostConnectionToClient) or we need to shutdown.
- impls_.insert(CreateWebSocket(
+ impls_.insert(DoCreateWebSocketInternal(
std::make_unique<Delegate>(this), std::move(request),
throttler_.IssuePendingConnectionTracker(), process_id_, frame_id,
std::move(origin), throttler_.CalculateDelay()));
@@ -275,7 +269,7 @@ void WebSocketManager::ThrottlingPeriodTimerCallback() {
throttling_period_timer_.Stop();
}
-std::unique_ptr<network::WebSocket> WebSocketManager::CreateWebSocket(
+std::unique_ptr<network::WebSocket> WebSocketManager::DoCreateWebSocketInternal(
std::unique_ptr<network::WebSocket::Delegate> delegate,
network::mojom::WebSocketRequest request,
network::WebSocketThrottler::PendingConnection pending_connection_tracker,
diff --git a/chromium/content/browser/websockets/websocket_manager.h b/chromium/content/browser/websockets/websocket_manager.h
index 089368539cd..006b5bd6ae9 100644
--- a/chromium/content/browser/websockets/websocket_manager.h
+++ b/chromium/content/browser/websockets/websocket_manager.h
@@ -29,18 +29,15 @@ class StoragePartition;
class CONTENT_EXPORT WebSocketManager
: public net::URLRequestContextGetterObserver {
public:
- // Called on the UI thread: create a websocket for a frame.
- static void CreateWebSocketForFrame(int process_id,
- int frame_id,
- network::mojom::WebSocketRequest request);
-
- // Called on the UI thread: create a websocket for a worker. Web workers of
- // any type (dedicated, shared, service worker) do not have a frame.
- static void CreateWebSocketWithOrigin(
- int process_id,
- url::Origin origin,
- network::mojom::WebSocketRequest request,
- int frame_id = MSG_ROUTING_NONE);
+ // Called on the UI thread: create a websocket.
+ // - For frames, |frame_id| should be their own id.
+ // - For dedicated workers, |frame_id| should be its parent frame's id.
+ // - For shared workers and service workers, |frame_id| should be
+ // MSG_ROUTING_NONE because they do not have a frame.
+ static void CreateWebSocket(int process_id,
+ int frame_id,
+ url::Origin origin,
+ network::mojom::WebSocketRequest request);
// net::URLRequestContextGetterObserver implementation.
void OnContextShuttingDown() override;
@@ -62,7 +59,7 @@ class CONTENT_EXPORT WebSocketManager
void ThrottlingPeriodTimerCallback();
// This is virtual to support testing.
- virtual std::unique_ptr<network::WebSocket> CreateWebSocket(
+ virtual std::unique_ptr<network::WebSocket> DoCreateWebSocketInternal(
std::unique_ptr<network::WebSocket::Delegate> delegate,
network::mojom::WebSocketRequest request,
network::WebSocketThrottler::PendingConnection pending_connection_tracker,
diff --git a/chromium/content/browser/websockets/websocket_manager_unittest.cc b/chromium/content/browser/websockets/websocket_manager_unittest.cc
index 75c97090474..1cee833398c 100644
--- a/chromium/content/browser/websockets/websocket_manager_unittest.cc
+++ b/chromium/content/browser/websockets/websocket_manager_unittest.cc
@@ -76,7 +76,7 @@ class TestWebSocketManager : public WebSocketManager {
}
private:
- std::unique_ptr<network::WebSocket> CreateWebSocket(
+ std::unique_ptr<network::WebSocket> DoCreateWebSocketInternal(
std::unique_ptr<network::WebSocket::Delegate> delegate,
network::mojom::WebSocketRequest request,
network::WebSocketThrottler::PendingConnection pending_connection_tracker,
diff --git a/chromium/content/browser/webui/content_web_ui_controller_factory.cc b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
index 0f8982a83ef..d741b28c8be 100644
--- a/chromium/content/browser/webui/content_web_ui_controller_factory.cc
+++ b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
@@ -8,21 +8,20 @@
#include "content/browser/accessibility/accessibility_ui.h"
#include "content/browser/appcache/appcache_internals_ui.h"
#include "content/browser/gpu/gpu_internals_ui.h"
+#include "content/browser/histograms_internals_ui.h"
#include "content/browser/indexed_db/indexed_db_internals_ui.h"
#include "content/browser/media/media_internals_ui.h"
#include "content/browser/net/network_errors_listing_ui.h"
+#include "content/browser/process_internals/process_internals_ui.h"
#include "content/browser/service_worker/service_worker_internals_ui.h"
#include "content/browser/tracing/tracing_ui.h"
+#include "content/browser/webrtc/webrtc_internals_ui.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/url_constants.h"
#include "media/media_buildflags.h"
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "content/browser/webrtc/webrtc_internals_ui.h"
-#endif
-
namespace content {
WebUI::TypeID ContentWebUIControllerFactory::GetWebUIType(
@@ -35,12 +34,14 @@ WebUI::TypeID ContentWebUIControllerFactory::GetWebUIType(
url.host_piece() == kChromeUITracingHost ||
#endif
url.host_piece() == kChromeUIGpuHost ||
+ url.host_piece() == kChromeUIHistogramHost ||
url.host_piece() == kChromeUIIndexedDBInternalsHost ||
url.host_piece() == kChromeUIMediaInternalsHost ||
url.host_piece() == kChromeUIServiceWorkerInternalsHost ||
url.host_piece() == kChromeUIAccessibilityHost ||
url.host_piece() == kChromeUIAppCacheInternalsHost ||
- url.host_piece() == kChromeUINetworkErrorsListingHost) {
+ url.host_piece() == kChromeUINetworkErrorsListingHost ||
+ url.host_piece() == kChromeUIProcessInternalsHost) {
return const_cast<ContentWebUIControllerFactory*>(this);
}
return WebUI::kNoWebUI;
@@ -65,6 +66,8 @@ WebUIController* ContentWebUIControllerFactory::CreateWebUIControllerForURL(
return new AppCacheInternalsUI(web_ui);
if (url.host_piece() == kChromeUIGpuHost)
return new GpuInternalsUI(web_ui);
+ if (url.host_piece() == kChromeUIHistogramHost)
+ return new HistogramsInternalsUI(web_ui);
if (url.host_piece() == kChromeUIIndexedDBInternalsHost)
return new IndexedDBInternalsUI(web_ui);
if (url.host_piece() == kChromeUIMediaInternalsHost)
@@ -79,11 +82,10 @@ WebUIController* ContentWebUIControllerFactory::CreateWebUIControllerForURL(
if (url.host_piece() == kChromeUITracingHost)
return new TracingUI(web_ui);
#endif
-
-#if BUILDFLAG(ENABLE_WEBRTC)
if (url.host_piece() == kChromeUIWebRTCInternalsHost)
return new WebRTCInternalsUI(web_ui);
-#endif
+ if (url.host_piece() == kChromeUIProcessInternalsHost)
+ return new ProcessInternalsUI(web_ui);
return nullptr;
}
diff --git a/chromium/content/browser/webui/url_data_manager.cc b/chromium/content/browser/webui/url_data_manager.cc
index a2d542f817e..ce87d5984c0 100644
--- a/chromium/content/browser/webui/url_data_manager.cc
+++ b/chromium/content/browser/webui/url_data_manager.cc
@@ -12,7 +12,6 @@
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "content/browser/resource_context_impl.h"
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 8ecdc60b491..96d91340510 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -25,7 +25,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
-#include "content/browser/histogram_internals_request_job.h"
#include "content/browser/net/view_blob_internals_job_factory.h"
#include "content/browser/resource_context_impl.h"
#include "content/browser/webui/shared_resources_data_source.h"
@@ -358,12 +357,6 @@ class ChromeProtocolHandler
request, network_delegate, blob_storage_context_->context());
}
- // Next check for chrome://histograms/, which uses its own job type.
- if (request->url().SchemeIs(kChromeUIScheme) &&
- request->url().host_piece() == kChromeUIHistogramHost) {
- return new HistogramInternalsRequestJob(request, network_delegate);
- }
-
// Check for chrome://network-error/, which uses its own job type.
if (request->url().SchemeIs(kChromeUIScheme) &&
request->url().host_piece() == kChromeUINetworkErrorHost) {
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.cc b/chromium/content/browser/webui/web_ui_data_source_impl.cc
index ab6ccbba485..5dad37af6f2 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -43,6 +43,15 @@ void WebUIDataSource::Update(BrowserContext* browser_context,
std::move(update));
}
+namespace {
+
+std::string CleanUpPath(const std::string& path) {
+ // Remove the query string for named resource lookups.
+ return path.substr(0, path.find_first_of('?'));
+}
+
+} // namespace
+
// Internal class to hide the fact that WebUIDataSourceImpl implements
// URLDataSource.
class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
@@ -88,8 +97,7 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
return parent_->deny_xframe_options_;
}
bool IsGzipped(const std::string& path) const override {
- return parent_->use_gzip_ &&
- parent_->excluded_paths_.find(path) == parent_->excluded_paths_.end();
+ return parent_->IsGzipped(path);
}
private:
@@ -275,8 +283,7 @@ void WebUIDataSourceImpl::StartDataRequest(
int resource_id = default_resource_;
std::map<std::string, int>::iterator result;
// Remove the query string for named resource lookups.
- std::string file_path = path.substr(0, path.find_first_of('?'));
- result = path_to_idr_map_.find(file_path);
+ result = path_to_idr_map_.find(CleanUpPath(path));
if (result != path_to_idr_map_.end())
resource_id = result->second;
DCHECK_NE(resource_id, -1);
@@ -292,4 +299,8 @@ void WebUIDataSourceImpl::SendLocalizedStringsAsJSON(
callback.Run(base::RefCountedString::TakeString(&template_data));
}
+bool WebUIDataSourceImpl::IsGzipped(const std::string& path) const {
+ return use_gzip_ && excluded_paths_.count(CleanUpPath(path)) == 0;
+}
+
} // namespace content
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.h b/chromium/content/browser/webui/web_ui_data_source_impl.h
index 18c48754437..06c1bd9af05 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/values.h"
#include "content/browser/webui/url_data_manager.h"
@@ -69,6 +70,8 @@ class CONTENT_EXPORT WebUIDataSourceImpl : public URLDataSourceImpl,
friend class WebUIDataSource;
friend class WebUIDataSourceTest;
+ FRIEND_TEST_ALL_PREFIXES(WebUIDataSourceTest, IsGzipped);
+
explicit WebUIDataSourceImpl(const std::string& source_name);
// Methods that match URLDataSource which are called by
@@ -85,6 +88,8 @@ class CONTENT_EXPORT WebUIDataSourceImpl : public URLDataSourceImpl,
add_load_time_data_defaults_ = false;
}
+ bool IsGzipped(const std::string& path) const;
+
// The name of this source.
// E.g., for favicons, this could be "favicon", which results in paths for
// specific resources like "favicon/34" getting sent to this source.
diff --git a/chromium/content/browser/webui/web_ui_data_source_unittest.cc b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
index f2974ff7f75..6125eb9562e 100644
--- a/chromium/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
@@ -212,4 +212,24 @@ TEST_F(WebUIDataSourceTest, MimeType) {
EXPECT_EQ(GetMimeType("foo.js?abc?abc"), js);
}
+TEST_F(WebUIDataSourceTest, IsGzipped) {
+ EXPECT_FALSE(source()->IsGzipped("foobar"));
+
+ source()->AddResourcePath("foobar", kDummyResourceId);
+ source()->SetDefaultResource(kDummyDefaultResourceId);
+ source()->SetJsonPath("strings.js");
+ source()->UseGzip({"json/special/path"});
+
+ EXPECT_TRUE(source()->IsGzipped("foobar"));
+ EXPECT_TRUE(source()->IsGzipped("foobar?query"));
+
+ EXPECT_TRUE(source()->IsGzipped("unknown_path"));
+ EXPECT_TRUE(source()->IsGzipped("unknown_path?query"));
+
+ EXPECT_FALSE(source()->IsGzipped("json/special/path"));
+ EXPECT_FALSE(source()->IsGzipped("json/special/path?query"));
+ EXPECT_FALSE(source()->IsGzipped("strings.js"));
+ EXPECT_FALSE(source()->IsGzipped("strings.js?query"));
+}
+
} // namespace content
diff --git a/chromium/content/browser/webui/web_ui_impl.cc b/chromium/content/browser/webui/web_ui_impl.cc
index d759aba3325..ceac82cbc8d 100644
--- a/chromium/content/browser/webui/web_ui_impl.cc
+++ b/chromium/content/browser/webui/web_ui_impl.cc
@@ -106,9 +106,14 @@ bool WebUIImpl::OnMessageReceived(const IPC::Message& message,
}
void WebUIImpl::OnWebUISend(RenderFrameHost* sender,
- const GURL& source_url,
const std::string& message,
const base::ListValue& args) {
+ // Ignore IPCs from frames that are pending deletion. See also
+ // https://crbug.com/780920.
+ if (!sender->IsCurrent())
+ return;
+
+ const GURL& source_url = sender->GetLastCommittedURL();
if (!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
sender->GetProcess()->GetID()) ||
!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
@@ -119,10 +124,6 @@ void WebUIImpl::OnWebUISend(RenderFrameHost* sender,
return;
}
- // Ignore IPCs from swapped-out frames. See also https://crbug.com/780920.
- if (!sender->IsCurrent())
- return;
-
if (base::EndsWith(message, "RequiringGesture",
base::CompareCase::SENSITIVE) &&
!web_contents_->HasRecentInteractiveInputEvent()) {
diff --git a/chromium/content/browser/webui/web_ui_impl.h b/chromium/content/browser/webui/web_ui_impl.h
index 556102626b3..484f918c98c 100644
--- a/chromium/content/browser/webui/web_ui_impl.h
+++ b/chromium/content/browser/webui/web_ui_impl.h
@@ -86,7 +86,6 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// IPC message handling.
void OnWebUISend(RenderFrameHost* sender,
- const GURL& source_url,
const std::string& message,
const base::ListValue& args);
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index 12e4cdf43fc..cf09e884aed 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -48,7 +48,7 @@ base::FilePath GetFilePathForJSResource(const std::string& path) {
base::ReplaceChars(binding_path, "//", "\\", &binding_path);
#endif
base::FilePath exe_dir;
- PathService::Get(base::DIR_EXE, &exe_dir);
+ base::PathService::Get(base::DIR_EXE, &exe_dir);
return exe_dir.AppendASCII(binding_path);
}
diff --git a/chromium/content/browser/webui/web_ui_url_loader_factory.cc b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
index fb7a2fe41f9..baa74f4c5e5 100644
--- a/chromium/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/chromium/content/browser/webui/web_ui_url_loader_factory.cc
@@ -7,6 +7,7 @@
#include <map>
#include "base/bind.h"
+#include "base/debug/crash_logging.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
@@ -17,7 +18,6 @@
#include "content/browser/blob_storage/blob_internals_url_loader.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/histogram_internals_url_loader.h"
#include "content/browser/resource_context_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/webui/network_error_url_loader.h"
@@ -257,6 +257,11 @@ class WebUIURLLoaderFactory : public network::mojom::URLLoaderFactory,
if (!allowed_hosts_.empty() &&
(!request.url.has_host() ||
allowed_hosts_.find(request.url.host()) == allowed_hosts_.end())) {
+ // Temporary reporting the bad WebUI host for for http://crbug.com/837328.
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
+ "webui_url", base::debug::CrashKeySize::Size64);
+ base::debug::SetCrashKeyString(crash_key, request.url.spec());
+
DVLOG(1) << "Bad host: \"" << request.url.host() << '"';
ReceivedBadMessage(render_frame_host_->GetProcess(),
bad_message::WEBUI_BAD_HOST_ACCESS);
@@ -280,11 +285,6 @@ class WebUIURLLoaderFactory : public network::mojom::URLLoaderFactory,
return;
}
- if (request.url.host_piece() == kChromeUIHistogramHost) {
- StartHistogramInternalsURLLoader(request, std::move(client));
- return;
- }
-
// We pass the FrameTreeNode ID to get to the WebContents because requests
// from frames can happen while the RFH is changed for a cross-process
// navigation. The URLDataSources just need the WebContents; the specific
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.cc b/chromium/content/browser/zygote_host/zygote_communication_linux.cc
deleted file mode 100644
index f389abaf2fc..00000000000
--- a/chromium/content/browser/zygote_host/zygote_communication_linux.cc
+++ /dev/null
@@ -1,323 +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.
-
-#include "content/browser/zygote_host/zygote_communication_linux.h"
-
-#include <string.h>
-#include <sys/socket.h>
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/i18n/unicodestring.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/path_service.h"
-#include "base/pickle.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/unix_domain_socket.h"
-#include "content/common/zygote_commands_linux.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/result_codes.h"
-#include "services/service_manager/embedder/switches.h"
-#include "services/service_manager/sandbox/switches.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-namespace content {
-
-ZygoteCommunication::ZygoteCommunication()
- : control_fd_(),
- control_lock_(),
- pid_(),
- list_of_running_zygote_children_(),
- child_tracking_lock_(),
- sandbox_status_(0),
- have_read_sandbox_status_word_(false),
- init_(false) {}
-
-ZygoteCommunication::~ZygoteCommunication() {}
-
-bool ZygoteCommunication::SendMessage(const base::Pickle& data,
- const std::vector<int>* fds) {
- DCHECK(control_fd_.is_valid());
- CHECK(data.size() <= kZygoteMaxMessageLength)
- << "Trying to send too-large message to zygote (sending " << data.size()
- << " bytes, max is " << kZygoteMaxMessageLength << ")";
- CHECK(!fds || fds->size() <= base::UnixDomainSocket::kMaxFileDescriptors)
- << "Trying to send message with too many file descriptors to zygote "
- << "(sending " << fds->size() << ", max is "
- << base::UnixDomainSocket::kMaxFileDescriptors << ")";
-
- return base::UnixDomainSocket::SendMsg(control_fd_.get(), data.data(),
- data.size(),
- fds ? *fds : std::vector<int>());
-}
-
-ssize_t ZygoteCommunication::ReadSandboxStatus() {
- DCHECK(control_fd_.is_valid());
- // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote,
- // but don't wait for the reply. Thus, the first time that we read from the
- // zygote, we get the reply to that request.
- ssize_t bytes_read = HANDLE_EINTR(
- read(control_fd_.get(), &sandbox_status_, sizeof(sandbox_status_)));
- if (bytes_read != sizeof(sandbox_status_)) {
- return -1;
- }
- return bytes_read;
-}
-
-ssize_t ZygoteCommunication::ReadReply(void* buf, size_t buf_len) {
- DCHECK(control_fd_.is_valid());
- if (!have_read_sandbox_status_word_) {
- if (ReadSandboxStatus() == -1) {
- return -1;
- }
- have_read_sandbox_status_word_ = true;
- base::UmaHistogramSparse("Linux.SandboxStatus", sandbox_status_);
- }
-
- return HANDLE_EINTR(read(control_fd_.get(), buf, buf_len));
-}
-
-pid_t ZygoteCommunication::ForkRequest(
- const std::vector<std::string>& argv,
- const base::FileHandleMappingVector& mapping,
- const std::string& process_type) {
- DCHECK(init_);
-
- base::Pickle pickle;
- int raw_socks[2];
- PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks));
- base::ScopedFD my_sock(raw_socks[0]);
- base::ScopedFD peer_sock(raw_socks[1]);
- CHECK(base::UnixDomainSocket::EnableReceiveProcessId(my_sock.get()));
-
- pickle.WriteInt(kZygoteCommandFork);
- pickle.WriteString(process_type);
- pickle.WriteInt(argv.size());
- for (std::vector<std::string>::const_iterator i = argv.begin();
- i != argv.end(); ++i)
- pickle.WriteString(*i);
- if (process_type == switches::kRendererProcess) {
- std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createDefault());
- icu::UnicodeString timezone_id;
- pickle.WriteString16(
- base::i18n::UnicodeStringToString16(timezone->getID(timezone_id)));
- }
-
- // Fork requests contain one file descriptor for the PID oracle, and one
- // more for each file descriptor mapping for the child process.
- const size_t num_fds_to_send = 1 + mapping.size();
- pickle.WriteInt(num_fds_to_send);
-
- std::vector<int> fds;
-
- // First FD to send is peer_sock.
- // TODO(morrita): Ideally, this should be part of the mapping so that
- // PosixFileDescriptorInfo can manages its lifetime.
- fds.push_back(peer_sock.get());
-
- // The rest come from mapping.
- for (const auto& item : mapping) {
- fds.push_back(item.first);
- pickle.WriteUInt32(item.second);
- }
-
- // Sanity check that we've populated |fds| correctly.
- DCHECK_EQ(num_fds_to_send, fds.size());
-
- pid_t pid;
- {
- base::AutoLock lock(control_lock_);
- if (!SendMessage(pickle, &fds))
- return base::kNullProcessHandle;
- peer_sock.reset();
-
- {
- char buf[sizeof(kZygoteChildPingMessage) + 1];
- std::vector<base::ScopedFD> recv_fds;
- base::ProcessId real_pid;
-
- ssize_t n = base::UnixDomainSocket::RecvMsgWithPid(
- my_sock.get(), buf, sizeof(buf), &recv_fds, &real_pid);
- if (n != sizeof(kZygoteChildPingMessage) ||
- 0 != memcmp(buf, kZygoteChildPingMessage,
- sizeof(kZygoteChildPingMessage))) {
- // Zygote children should still be trustworthy when they're supposed to
- // ping us, so something's broken if we don't receive a valid ping.
- LOG(ERROR) << "Did not receive ping from zygote child";
- NOTREACHED();
- real_pid = -1;
- }
- my_sock.reset();
-
- // Always send PID back to zygote.
- base::Pickle pid_pickle;
- pid_pickle.WriteInt(kZygoteCommandForkRealPID);
- pid_pickle.WriteInt(real_pid);
- if (!SendMessage(pid_pickle, nullptr))
- return base::kNullProcessHandle;
- }
-
- // Read the reply, which pickles the PID and an optional UMA enumeration.
- static const unsigned kMaxReplyLength = 2048;
- char buf[kMaxReplyLength];
- const ssize_t len = ReadReply(buf, sizeof(buf));
-
- base::Pickle reply_pickle(buf, len);
- base::PickleIterator iter(reply_pickle);
- if (len <= 0 || !iter.ReadInt(&pid))
- return base::kNullProcessHandle;
-
- // If there is a nonempty UMA name string, then there is a UMA
- // enumeration to record.
- std::string uma_name;
- int uma_sample;
- int uma_boundary_value;
- if (iter.ReadString(&uma_name) && !uma_name.empty() &&
- iter.ReadInt(&uma_sample) && iter.ReadInt(&uma_boundary_value)) {
- // We cannot use the UMA_HISTOGRAM_ENUMERATION macro here,
- // because that's only for when the name is the same every time.
- // Here we're using whatever name we got from the other side.
- // But since it's likely that the same one will be used repeatedly
- // (even though it's not guaranteed), we cache it here.
- static base::HistogramBase* uma_histogram;
- if (!uma_histogram || uma_histogram->histogram_name() != uma_name) {
- uma_histogram = base::LinearHistogram::FactoryGet(
- uma_name, 1, uma_boundary_value, uma_boundary_value + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- }
- uma_histogram->Add(uma_sample);
- }
-
- if (pid <= 0)
- return base::kNullProcessHandle;
- }
-
- ZygoteChildBorn(pid);
- return pid;
-}
-
-void ZygoteCommunication::EnsureProcessTerminated(pid_t process) {
- DCHECK(init_);
- base::Pickle pickle;
-
- pickle.WriteInt(kZygoteCommandReap);
- pickle.WriteInt(process);
- if (!SendMessage(pickle, nullptr))
- LOG(ERROR) << "Failed to send Reap message to zygote";
- ZygoteChildDied(process);
-}
-
-void ZygoteCommunication::ZygoteChildBorn(pid_t process) {
- base::AutoLock lock(child_tracking_lock_);
- bool new_element_inserted =
- list_of_running_zygote_children_.insert(process).second;
- DCHECK(new_element_inserted);
-}
-
-void ZygoteCommunication::ZygoteChildDied(pid_t process) {
- base::AutoLock lock(child_tracking_lock_);
- size_t num_erased = list_of_running_zygote_children_.erase(process);
- DCHECK_EQ(1U, num_erased);
-}
-
-void ZygoteCommunication::Init(
- base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)> launcher) {
- CHECK(!init_);
-
- base::FilePath chrome_path;
- CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
-
- base::CommandLine cmd_line(chrome_path);
- cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess);
-
- const base::CommandLine& browser_command_line =
- *base::CommandLine::ForCurrentProcess();
- if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) {
- cmd_line.PrependWrapper(
- browser_command_line.GetSwitchValueNative(switches::kZygoteCmdPrefix));
- }
- // Append any switches from the service manager that need to be forwarded on
- // to the zygote/renderers.
- static const char* const kForwardSwitches[] = {
- service_manager::switches::kAllowSandboxDebugging,
- service_manager::switches::kDisableInProcessStackTraces,
- service_manager::switches::kDisableSeccompFilterSandbox,
- service_manager::switches::kNoSandbox,
- };
- cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
- arraysize(kForwardSwitches));
-
- pid_ = std::move(launcher).Run(&cmd_line, &control_fd_);
-
- base::Pickle pickle;
- pickle.WriteInt(kZygoteCommandGetSandboxStatus);
- if (!SendMessage(pickle, nullptr))
- LOG(FATAL) << "Cannot communicate with zygote";
-
- init_ = true;
-}
-
-base::TerminationStatus ZygoteCommunication::GetTerminationStatus(
- base::ProcessHandle handle,
- bool known_dead,
- int* exit_code) {
- DCHECK(init_);
- base::Pickle pickle;
- pickle.WriteInt(kZygoteCommandGetTerminationStatus);
- pickle.WriteBool(known_dead);
- pickle.WriteInt(handle);
-
- static const unsigned kMaxMessageLength = 128;
- char buf[kMaxMessageLength];
- ssize_t len;
- {
- base::AutoLock lock(control_lock_);
- if (!SendMessage(pickle, nullptr))
- LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote";
- len = ReadReply(buf, sizeof(buf));
- }
-
- // Set this now to handle the error cases.
- if (exit_code)
- *exit_code = RESULT_CODE_NORMAL_EXIT;
- int status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
-
- if (len == -1) {
- LOG(WARNING) << "Error reading message from zygote: " << errno;
- } else if (len == 0) {
- LOG(WARNING) << "Socket closed prematurely.";
- } else {
- base::Pickle read_pickle(buf, len);
- int tmp_status, tmp_exit_code;
- base::PickleIterator iter(read_pickle);
- if (!iter.ReadInt(&tmp_status) || !iter.ReadInt(&tmp_exit_code)) {
- LOG(WARNING)
- << "Error parsing GetTerminationStatus response from zygote.";
- } else {
- if (exit_code)
- *exit_code = tmp_exit_code;
- status = tmp_status;
- }
- }
-
- if (status != base::TERMINATION_STATUS_STILL_RUNNING) {
- ZygoteChildDied(handle);
- }
- return static_cast<base::TerminationStatus>(status);
-}
-
-int ZygoteCommunication::GetSandboxStatus() {
- if (have_read_sandbox_status_word_) {
- return sandbox_status_;
- }
- if (ReadSandboxStatus() == -1) {
- return 0;
- }
- have_read_sandbox_status_word_ = true;
- base::UmaHistogramSparse("Linux.SandboxStatus", sandbox_status_);
- return sandbox_status_;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.h b/chromium/content/browser/zygote_host/zygote_communication_linux.h
deleted file mode 100644
index 13185255fdc..00000000000
--- a/chromium/content/browser/zygote_host/zygote_communication_linux.h
+++ /dev/null
@@ -1,103 +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 CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
-#define CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <sys/types.h>
-
-#include "base/callback.h"
-#include "base/files/scoped_file.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/process/process_handle.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-
-namespace base {
-class Pickle;
-} // namespace base
-
-namespace content {
-
-// Handles interprocess communication with the Linux zygote process. The zygote
-// does not use standard Chrome IPC or mojo, see:
-// https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
-class CONTENT_EXPORT ZygoteCommunication {
- public:
- ZygoteCommunication();
- ~ZygoteCommunication();
-
- void Init(
- base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)> launcher);
-
- // Tries to start a process of type indicated by process_type.
- // Returns its pid on success, otherwise base::kNullProcessHandle;
- pid_t ForkRequest(const std::vector<std::string>& command_line,
- const base::FileHandleMappingVector& mapping,
- const std::string& process_type);
-
- void EnsureProcessTerminated(pid_t process);
-
- // Should be called every time a Zygote child died.
- void ZygoteChildDied(pid_t process);
-
- // Get the termination status (and, optionally, the exit code) of
- // the process. |exit_code| is set to the exit code of the child
- // process. (|exit_code| may be NULL.)
- // Unfortunately the Zygote can not accurately figure out if a process
- // is already dead without waiting synchronously for it.
- // |known_dead| should be set to true when we already know that the process
- // is dead. When |known_dead| is false, processes could be seen as
- // still running, even when they're not. When |known_dead| is true, the
- // process will be SIGKILL-ed first (which should have no effect if it was
- // really dead). This is to prevent a waiting waitpid() from blocking in
- // a single-threaded Zygote. See crbug.com/157458.
- base::TerminationStatus GetTerminationStatus(base::ProcessHandle handle,
- bool known_dead,
- int* exit_code);
-
- // Returns the sandbox status of this zygote.
- int GetSandboxStatus();
-
- private:
- // Should be called every time a Zygote child is born.
- void ZygoteChildBorn(pid_t process);
-
- // Read the reply from the zygote.
- ssize_t ReadReply(void* buf, size_t buf_len);
-
- // Sends |data| to the zygote via |control_fd_|. If |fds| is non-NULL, the
- // included file descriptors will also be passed. The caller is responsible
- // for acquiring |control_lock_|.
- bool SendMessage(const base::Pickle& data, const std::vector<int>* fds);
-
- // Get the sandbox status from the zygote.
- ssize_t ReadSandboxStatus();
-
- base::ScopedFD control_fd_; // the socket to the zygote.
- // A lock protecting all communication with the zygote. This lock must be
- // acquired before sending a command and released after the result has been
- // received.
- base::Lock control_lock_;
- // The pid of the zygote.
- pid_t pid_;
- // The list of running zygote children.
- std::set<pid_t> list_of_running_zygote_children_;
- // The lock to guard the list of running zygote children.
- base::Lock child_tracking_lock_;
- int sandbox_status_;
- bool have_read_sandbox_status_word_;
- // Set to true when the zygote is initialized successfully.
- bool init_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
diff --git a/chromium/content/browser/zygote_host/zygote_handle_linux.cc b/chromium/content/browser/zygote_host/zygote_handle_linux.cc
deleted file mode 100644
index 14eabaec1d0..00000000000
--- a/chromium/content/browser/zygote_host/zygote_handle_linux.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 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/public/common/zygote_handle.h"
-
-#include "content/browser/zygote_host/zygote_communication_linux.h"
-
-namespace content {
-namespace {
-
-// Intentionally leaked.
-ZygoteHandle g_generic_zygote = nullptr;
-
-} // namespace
-
-ZygoteHandle CreateGenericZygote(
- base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)> launcher) {
- CHECK(!g_generic_zygote);
- g_generic_zygote = new ZygoteCommunication();
- g_generic_zygote->Init(std::move(launcher));
- return g_generic_zygote;
-}
-
-ZygoteHandle GetGenericZygote() {
- CHECK(g_generic_zygote);
- return g_generic_zygote;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
deleted file mode 100644
index 0b764578eca..00000000000
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/zygote_host/zygote_host_impl_linux.h"
-
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include "base/allocator/allocator_extension.h"
-#include "base/files/file_enumerator.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/process/kill.h"
-#include "base/process/memory.h"
-#include "base/strings/string_number_conversions.h"
-#include "content/common/zygote_commands_linux.h"
-#include "content/public/common/content_switches.h"
-#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
-#include "sandbox/linux/suid/common/sandbox.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/switches.h"
-
-namespace content {
-
-namespace {
-
-// Receive a fixed message on fd and return the sender's PID.
-// Returns true if the message received matches the expected message.
-bool ReceiveFixedMessage(int fd,
- const char* expect_msg,
- size_t expect_len,
- base::ProcessId* sender_pid) {
- // Allocate an extra byte of buffer space so we can check that we received
- // exactly |expect_len| bytes, and the message wasn't just truncated to fit.
- char buf[expect_len + 1];
- std::vector<base::ScopedFD> fds_vec;
-
- const ssize_t len = base::UnixDomainSocket::RecvMsgWithPid(
- fd, buf, sizeof(buf), &fds_vec, sender_pid);
- if (static_cast<size_t>(len) != expect_len)
- return false;
- if (memcmp(buf, expect_msg, expect_len) != 0)
- return false;
- if (!fds_vec.empty())
- return false;
- return true;
-}
-
-} // namespace
-
-// static
-ZygoteHost* ZygoteHost::GetInstance() {
- return ZygoteHostImpl::GetInstance();
-}
-
-ZygoteHostImpl::ZygoteHostImpl()
- : use_namespace_sandbox_(false),
- use_suid_sandbox_(false),
- use_suid_sandbox_for_adj_oom_score_(false),
- sandbox_binary_(),
- zygote_pids_lock_(),
- zygote_pids_() {}
-
-ZygoteHostImpl::~ZygoteHostImpl() {}
-
-// static
-ZygoteHostImpl* ZygoteHostImpl::GetInstance() {
- return base::Singleton<ZygoteHostImpl>::get();
-}
-
-void ZygoteHostImpl::Init(const base::CommandLine& command_line) {
- if (command_line.HasSwitch(switches::kNoSandbox)) {
- return;
- }
-
- // Exit early if running as root without --no-sandbox. See crbug.com/638180.
- // When running as root with the sandbox enabled, the browser process
- // crashes on zygote initialization. Running as root with the sandbox
- // is not supported, and if Chrome were able to display UI it would be showing
- // an error message. With the zygote crashing it doesn't even get to that,
- // so print an error message on the console.
- uid_t uid = 0;
- gid_t gid = 0;
- if (!sandbox::Credentials::GetRESIds(&uid, &gid) || uid == 0) {
- LOG(ERROR) << "Running as root without --" << switches::kNoSandbox
- << " is not supported. See https://crbug.com/638180.";
- exit(EXIT_FAILURE);
- }
-
- {
- std::unique_ptr<sandbox::SetuidSandboxHost> setuid_sandbox_host(
- sandbox::SetuidSandboxHost::Create());
- sandbox_binary_ = setuid_sandbox_host->GetSandboxBinaryPath().value();
- }
-
- if (!command_line.HasSwitch(switches::kDisableNamespaceSandbox) &&
- sandbox::Credentials::CanCreateProcessInNewUserNS()) {
- use_namespace_sandbox_ = true;
-
-#if defined(OS_CHROMEOS)
- // Chrome OS has a kernel patch that restricts oom_score_adj. See
- // crbug.com/576409 for details.
- if (!sandbox_binary_.empty()) {
- use_suid_sandbox_for_adj_oom_score_ = true;
- } else {
- LOG(ERROR) << "SUID sandbox binary is missing. Won't be able to adjust "
- "OOM scores.";
- }
-#endif
- } else if (!command_line.HasSwitch(
- service_manager::switches::kDisableSetuidSandbox) &&
- !sandbox_binary_.empty()) {
- use_suid_sandbox_ = true;
-
- // Use the SUID sandbox for adjusting OOM scores when we are using
- // the setuid sandbox. This is needed beacuse the processes are
- // non-dumpable, so /proc/pid/oom_score_adj can only be written by
- // root.
- use_suid_sandbox_for_adj_oom_score_ = use_suid_sandbox_;
- } else {
- LOG(FATAL)
- << "No usable sandbox! Update your kernel or see "
- "https://chromium.googlesource.com/chromium/src/+/master/"
- "docs/linux_suid_sandbox_development.md for more information on "
- "developing with the SUID sandbox. "
- "If you want to live dangerously and need an immediate workaround, "
- "you can try using --"
- << switches::kNoSandbox << ".";
- }
-}
-
-void ZygoteHostImpl::AddZygotePid(pid_t pid) {
- base::AutoLock lock(zygote_pids_lock_);
- zygote_pids_.insert(pid);
-}
-
-bool ZygoteHostImpl::IsZygotePid(pid_t pid) {
- base::AutoLock lock(zygote_pids_lock_);
- return zygote_pids_.find(pid) != zygote_pids_.end();
-}
-
-void ZygoteHostImpl::SetRendererSandboxStatus(int status) {
- renderer_sandbox_status_ = status;
-}
-
-int ZygoteHostImpl::GetRendererSandboxStatus() const {
- return renderer_sandbox_status_;
-}
-
-pid_t ZygoteHostImpl::LaunchZygote(
- base::CommandLine* cmd_line,
- base::ScopedFD* control_fd,
- base::FileHandleMappingVector additional_remapped_fds) {
- int fds[2];
- CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
- CHECK(base::UnixDomainSocket::EnableReceiveProcessId(fds[0]));
-
- base::LaunchOptions options;
- options.fds_to_remap = std::move(additional_remapped_fds);
- options.fds_to_remap.emplace_back(fds[1], kZygoteSocketPairFd);
-
- base::ScopedFD dummy_fd;
- if (use_suid_sandbox_) {
- std::unique_ptr<sandbox::SetuidSandboxHost> sandbox_host(
- sandbox::SetuidSandboxHost::Create());
- sandbox_host->PrependWrapper(cmd_line);
- sandbox_host->SetupLaunchOptions(&options, &dummy_fd);
- sandbox_host->SetupLaunchEnvironment();
- }
-
- base::Process process =
- use_namespace_sandbox_
- ? sandbox::NamespaceSandbox::LaunchProcess(*cmd_line, options)
- : base::LaunchProcess(*cmd_line, options);
- CHECK(process.IsValid()) << "Failed to launch zygote process";
-
- dummy_fd.reset();
- close(fds[1]);
- control_fd->reset(fds[0]);
-
- pid_t pid = process.Pid();
-
- if (use_namespace_sandbox_ || use_suid_sandbox_) {
- // The namespace and SUID sandbox will execute the zygote in a new
- // PID namespace, and the main zygote process will then fork from
- // there. Watch now our elaborate dance to find and validate the
- // zygote's PID.
-
- // First we receive a message from the zygote boot process.
- base::ProcessId boot_pid;
- CHECK(ReceiveFixedMessage(fds[0], kZygoteBootMessage,
- sizeof(kZygoteBootMessage), &boot_pid));
-
- // Within the PID namespace, the zygote boot process thinks it's PID 1,
- // but its real PID can never be 1. This gives us a reliable test that
- // the kernel is translating the sender's PID to our namespace.
- CHECK_GT(boot_pid, 1)
- << "Received invalid process ID for zygote; kernel might be too old? "
- "See crbug.com/357670 or try using --"
- << switches::kNoSandbox << " to workaround.";
-
- // Now receive the message that the zygote's ready to go, along with the
- // main zygote process's ID.
- pid_t real_pid;
- CHECK(ReceiveFixedMessage(fds[0], kZygoteHelloMessage,
- sizeof(kZygoteHelloMessage), &real_pid));
- CHECK_GT(real_pid, 1);
-
- if (real_pid != pid) {
- // Reap the sandbox.
- base::EnsureProcessGetsReaped(std::move(process));
- }
- pid = real_pid;
- }
-
- AddZygotePid(pid);
- return pid;
-}
-
-#if !defined(OS_OPENBSD)
-void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
- int score) {
- // 1) You can't change the oom_score_adj of a non-dumpable process
- // (EPERM) unless you're root. Because of this, we can't set the
- // oom_adj from the browser process.
- //
- // 2) We can't set the oom_score_adj before entering the sandbox
- // because the zygote is in the sandbox and the zygote is as
- // critical as the browser process. Its oom_adj value shouldn't
- // be changed.
- //
- // 3) A non-dumpable process can't even change its own oom_score_adj
- // because it's root owned 0644. The sandboxed processes don't
- // even have /proc, but one could imagine passing in a descriptor
- // from outside.
- //
- // So, in the normal case, we use the SUID binary to change it for us.
- // However, Fedora (and other SELinux systems) don't like us touching other
- // process's oom_score_adj (or oom_adj) values
- // (https://bugzilla.redhat.com/show_bug.cgi?id=581256).
- //
- // The offical way to get the SELinux mode is selinux_getenforcemode, but I
- // don't want to add another library to the build as it's sure to cause
- // problems with other, non-SELinux distros.
- //
- // So we just check for files in /selinux. This isn't foolproof, but it's not
- // bad and it's easy.
-
- static bool selinux;
- static bool selinux_valid = false;
-
- if (!selinux_valid) {
- const base::FilePath kSelinuxPath("/selinux");
- base::FileEnumerator en(kSelinuxPath, false, base::FileEnumerator::FILES);
- bool has_selinux_files = !en.Next().empty();
-
- selinux =
- has_selinux_files && access(kSelinuxPath.value().c_str(), X_OK) == 0;
- selinux_valid = true;
- }
-
- if (!use_suid_sandbox_for_adj_oom_score_) {
- if (!base::AdjustOOMScore(pid, score))
- PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid;
- return;
- }
-
- if (selinux)
- return;
-
- // If heap profiling is running, these processes are not exiting, at least
- // on ChromeOS. The easiest thing to do is not launch them when profiling.
- // TODO(stevenjb): Investigate further and fix.
- if (base::allocator::IsHeapProfilerRunning())
- return;
-
- std::vector<std::string> adj_oom_score_cmdline;
- adj_oom_score_cmdline.push_back(sandbox_binary_);
- adj_oom_score_cmdline.push_back(sandbox::kAdjustOOMScoreSwitch);
- adj_oom_score_cmdline.push_back(base::Int64ToString(pid));
- adj_oom_score_cmdline.push_back(base::IntToString(score));
-
- // sandbox_helper_process is a setuid binary.
- base::LaunchOptions options;
- options.allow_new_privs = true;
-
- base::Process sandbox_helper_process =
- base::LaunchProcess(adj_oom_score_cmdline, options);
- if (sandbox_helper_process.IsValid())
- base::EnsureProcessGetsReaped(std::move(sandbox_helper_process));
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
deleted file mode 100644
index c527996ad37..00000000000
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
-#define CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
-
-#include <sys/types.h>
-
-#include <set>
-#include <string>
-
-#include "base/command_line.h"
-#include "base/files/scoped_file.h"
-#include "base/process/launch.h"
-#include "base/process/process_handle.h"
-#include "base/synchronization/lock.h"
-#include "content/public/browser/zygote_host_linux.h"
-
-namespace base {
-template<typename Type>
-struct DefaultSingletonTraits;
-} // namespace base
-
-namespace content {
-
-class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
- public:
- // Returns the singleton instance.
- static ZygoteHostImpl* GetInstance();
-
- void Init(const base::CommandLine& cmd_line);
-
- // Returns whether or not this pid is the pid of a zygote.
- bool IsZygotePid(pid_t pid) override;
-
- void SetRendererSandboxStatus(int status);
- int GetRendererSandboxStatus() const override;
-
- pid_t LaunchZygote(base::CommandLine* cmd_line,
- base::ScopedFD* control_fd,
- base::FileHandleMappingVector additional_remapped_fds);
-
- void AdjustRendererOOMScore(base::ProcessHandle process_handle,
- int score) override;
-
- private:
- friend struct base::DefaultSingletonTraits<ZygoteHostImpl>;
-
- ZygoteHostImpl();
- ~ZygoteHostImpl() override;
-
- // Tells the ZygoteHost the PIDs of all the zygotes.
- void AddZygotePid(pid_t pid);
-
- int renderer_sandbox_status_;
-
- bool use_namespace_sandbox_;
- bool use_suid_sandbox_;
- bool use_suid_sandbox_for_adj_oom_score_;
- std::string sandbox_binary_;
-
- // This lock protects the |zygote_pids_| set.
- base::Lock zygote_pids_lock_;
- // This is a set of PIDs representing all the running zygotes.
- std::set<pid_t> zygote_pids_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
diff --git a/chromium/content/child/BUILD.gn b/chromium/content/child/BUILD.gn
index fbb110d2d40..7c110b354fa 100644
--- a/chromium/content/child/BUILD.gn
+++ b/chromium/content/child/BUILD.gn
@@ -72,8 +72,6 @@ target(link_target_type, "child") {
"service_factory.h",
"thread_safe_sender.cc",
"thread_safe_sender.h",
- "webfallbackthemeengine_impl.cc",
- "webfallbackthemeengine_impl.h",
"webthemeengine_impl_android.cc",
"webthemeengine_impl_android.h",
"webthemeengine_impl_default.cc",
@@ -106,7 +104,6 @@ target(link_target_type, "child") {
"//gpu/command_buffer/client",
"//media",
"//media/blink",
- "//mojo/common",
"//mojo/edk",
"//net",
"//services/device/public/cpp:device_features",
@@ -148,6 +145,10 @@ target(link_target_type, "child") {
deps += [ "//third_party/android_tools:cpu_features" ]
}
+ if (is_linux) {
+ deps += [ "//services/service_manager/zygote" ]
+ }
+
if (is_win) {
libs = [ "dwrite.lib" ]
}
diff --git a/chromium/content/child/OWNERS b/chromium/content/child/OWNERS
index e9510bd4d17..5d33001f6a8 100644
--- a/chromium/content/child/OWNERS
+++ b/chromium/content/child/OWNERS
@@ -1,12 +1 @@
haraken@chromium.org
-
-# AppCache
-per-file appcache*=michaeln@chromium.org
-
-# WebSQL
-per-file database_*=jsbell@chromium.org
-per-file database_*=michaeln@chromium.org
-per-file db_*=jsbell@chromium.org
-per-file db_*=michaeln@chromium.org
-per-file web_database_*=jsbell@chromium.org
-per-file web_database_*=michaeln@chromium.org
diff --git a/chromium/content/child/assert_matching_enums.cc b/chromium/content/child/assert_matching_enums.cc
index b2b3db58b71..be579b005c8 100644
--- a/chromium/content/child/assert_matching_enums.cc
+++ b/chromium/content/child/assert_matching_enums.cc
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "content/public/common/screen_orientation_values.h"
#include "media/base/mime_util.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
#include "third_party/blink/public/platform/web_menu_source_type.h"
#include "third_party/blink/public/platform/web_text_input_mode.h"
#include "third_party/blink/public/platform/web_text_input_type.h"
diff --git a/chromium/content/child/blink_platform_impl.cc b/chromium/content/child/blink_platform_impl.cc
index aa67eb82782..d15a8c88c11 100644
--- a/chromium/content/child/blink_platform_impl.cc
+++ b/chromium/content/child/blink_platform_impl.cc
@@ -59,7 +59,6 @@
#include "ui/events/keycodes/dom/keycode_converter.h"
using blink::WebData;
-using blink::WebFallbackThemeEngine;
using blink::WebLocalizedString;
using blink::WebString;
using blink::WebThemeEngine;
@@ -366,10 +365,6 @@ void BlinkPlatformImpl::UpdateWebThreadTLS(blink::WebThread* thread,
BlinkPlatformImpl::~BlinkPlatformImpl() {
}
-WebString BlinkPlatformImpl::UserAgent() {
- return blink::WebString::FromUTF8(GetContentClient()->GetUserAgent());
-}
-
std::unique_ptr<blink::WebThread> BlinkPlatformImpl::CreateThread(
const blink::WebThreadCreationParams& params) {
std::unique_ptr<blink::scheduler::WebThreadBase> thread =
@@ -702,16 +697,12 @@ WebThemeEngine* BlinkPlatformImpl::ThemeEngine() {
return &native_theme_engine_;
}
-WebFallbackThemeEngine* BlinkPlatformImpl::FallbackThemeEngine() {
- return &fallback_theme_engine_;
-}
-
blink::Platform::FileHandle BlinkPlatformImpl::DatabaseOpenFile(
const blink::WebString& vfs_file_name,
int desired_flags) {
#if defined(OS_WIN)
return INVALID_HANDLE_VALUE;
-#elif defined(OS_POSIX)
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
return -1;
#endif
}
@@ -742,10 +733,6 @@ bool BlinkPlatformImpl::DatabaseSetFileSize(
return false;
}
-size_t BlinkPlatformImpl::NumberOfProcessors() {
- return static_cast<size_t>(base::SysInfo::NumberOfProcessors());
-}
-
size_t BlinkPlatformImpl::MaxDecodedImageBytes() {
const int kMB = 1024 * 1024;
const int kMaxNumberOfBytesPerPixel = 4;
@@ -781,12 +768,6 @@ bool BlinkPlatformImpl::IsLowEndDevice() {
return base::SysInfo::IsLowEndDevice();
}
-uint32_t BlinkPlatformImpl::GetUniqueIdForProcess() {
- // TODO(rickyz): Replace this with base::GetUniqueIdForProcess when that's
- // ready.
- return base::trace_event::TraceLog::GetInstance()->process_id();
-}
-
bool BlinkPlatformImpl::IsMainThread() const {
return main_thread_task_runner_.get() &&
main_thread_task_runner_->BelongsToCurrentThread();
diff --git a/chromium/content/child/blink_platform_impl.h b/chromium/content/child/blink_platform_impl.h
index f9d13cf958a..4cbfab92679 100644
--- a/chromium/content/child/blink_platform_impl.h
+++ b/chromium/content/child/blink_platform_impl.h
@@ -15,7 +15,6 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/webcrypto/webcrypto_impl.h"
-#include "content/child/webfallbackthemeengine_impl.h"
#include "content/common/content_export.h"
#include "media/blink/webmediacapabilitiesclient_impl.h"
#include "third_party/blink/public/platform/platform.h"
@@ -58,7 +57,6 @@ class CONTENT_EXPORT BlinkPlatformImpl : public blink::Platform {
// Platform methods (partial implementation):
blink::WebThemeEngine* ThemeEngine() override;
- blink::WebFallbackThemeEngine* FallbackThemeEngine() override;
blink::Platform::FileHandle DatabaseOpenFile(
const blink::WebString& vfs_file_name,
int desired_flags) override;
@@ -71,12 +69,9 @@ class CONTENT_EXPORT BlinkPlatformImpl : public blink::Platform {
const blink::WebSecurityOrigin& origin) override;
bool DatabaseSetFileSize(const blink::WebString& vfs_file_name,
long long size) override;
- size_t NumberOfProcessors() override;
size_t MaxDecodedImageBytes() override;
bool IsLowEndDevice() override;
- uint32_t GetUniqueIdForProcess() override;
- blink::WebString UserAgent() override;
std::unique_ptr<blink::WebThread> CreateThread(
const blink::WebThreadCreationParams& params) override;
std::unique_ptr<blink::WebThread> CreateWebAudioThread() override;
@@ -127,7 +122,6 @@ class CONTENT_EXPORT BlinkPlatformImpl : public blink::Platform {
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
WebThemeEngineImpl native_theme_engine_;
- WebFallbackThemeEngineImpl fallback_theme_engine_;
base::ThreadLocalStorage::Slot current_thread_slot_;
webcrypto::WebCryptoImpl web_crypto_;
media::WebMediaCapabilitiesClientImpl media_capabilities_client_;
diff --git a/chromium/content/child/child_histogram_fetcher_impl.cc b/chromium/content/child/child_histogram_fetcher_impl.cc
index 36dbd27bb6f..97283203509 100644
--- a/chromium/content/child/child_histogram_fetcher_impl.cc
+++ b/chromium/content/child/child_histogram_fetcher_impl.cc
@@ -37,7 +37,7 @@ void ChildHistogramFetcherFactoryImpl::CreateFetcher(
const MojoResult result = mojo::UnwrapSharedMemoryHandle(
std::move(buffer_handle), &memory_handle, &memory_size, nullptr);
- if (result == MOJO_RESULT_OK) {
+ if (result == MOJO_RESULT_OK && memory_handle.IsValid()) {
// This message must be received only once. Multiple calls to create a
// global allocator will cause a CHECK() failure.
base::GlobalHistogramAllocator::CreateWithSharedMemoryHandle(memory_handle,
diff --git a/chromium/content/child/child_process.cc b/chromium/content/child/child_process.cc
index 835a59e685a..7f70a3408c6 100644
--- a/chromium/content/child/child_process.cc
+++ b/chromium/content/child/child_process.cc
@@ -101,13 +101,13 @@ void ChildProcess::set_main_thread(ChildThreadImpl* thread) {
void ChildProcess::AddRefProcess() {
DCHECK(!main_thread_.get() || // null in unittests.
- main_thread_->message_loop()->task_runner()->BelongsToCurrentThread());
+ main_thread_->main_thread_runner()->BelongsToCurrentThread());
ref_count_++;
}
void ChildProcess::ReleaseProcess() {
DCHECK(!main_thread_.get() || // null in unittests.
- main_thread_->message_loop()->task_runner()->BelongsToCurrentThread());
+ main_thread_->main_thread_runner()->BelongsToCurrentThread());
DCHECK(ref_count_);
if (--ref_count_)
return;
diff --git a/chromium/content/child/child_process_sandbox_support_impl_linux.cc b/chromium/content/child/child_process_sandbox_support_impl_linux.cc
index 587ddeab58e..7899935f659 100644
--- a/chromium/content/child/child_process_sandbox_support_impl_linux.cc
+++ b/chromium/content/child/child_process_sandbox_support_impl_linux.cc
@@ -15,8 +15,8 @@
#include "base/posix/unix_domain_socket.h"
#include "base/sys_byteorder.h"
#include "base/trace_event/trace_event.h"
-#include "content/public/common/common_sandbox_support_linux.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/blink/public/platform/linux/web_fallback_font.h"
#include "third_party/blink/public/platform/web_font_render_style.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -37,7 +37,7 @@ void GetFallbackFontForCharacter(int32_t character,
uint8_t buf[512];
const ssize_t n = base::UnixDomainSocket::SendRecvMsg(
- GetSandboxFD(), buf, sizeof(buf), nullptr, request);
+ service_manager::GetSandboxFD(), buf, sizeof(buf), nullptr, request);
std::string family_name;
std::string filename;
@@ -88,7 +88,7 @@ void GetRenderStyleForStrike(const char* family,
uint8_t buf[512];
const ssize_t n = base::UnixDomainSocket::SendRecvMsg(
- GetSandboxFD(), buf, sizeof(buf), nullptr, request);
+ service_manager::GetSandboxFD(), buf, sizeof(buf), nullptr, request);
if (n == -1)
return;
@@ -127,8 +127,9 @@ int MatchFontWithFallback(const std::string& face,
request.WriteUInt32(fallback_family);
uint8_t reply_buf[64];
int fd = -1;
- base::UnixDomainSocket::SendRecvMsg(GetSandboxFD(), reply_buf,
- sizeof(reply_buf), &fd, request);
+ base::UnixDomainSocket::SendRecvMsg(service_manager::GetSandboxFD(),
+ reply_buf, sizeof(reply_buf), &fd,
+ request);
return fd;
}
diff --git a/chromium/content/child/child_thread_impl.cc b/chromium/content/child/child_thread_impl.cc
index 2663268bce3..d6898e941c8 100644
--- a/chromium/content/child/child_thread_impl.cc
+++ b/chromium/content/child/child_thread_impl.cc
@@ -17,7 +17,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/message_loop/timer_slack.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
@@ -44,7 +43,6 @@
#include "content/public/common/connection_filter.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_channel_switches.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/simple_connection_filter.h"
@@ -64,6 +62,7 @@
#include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
+#include "services/service_manager/embedder/switches.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/service_manager/runner/common/client_util.h"
@@ -74,13 +73,19 @@
#include "content/public/common/content_descriptors.h"
#endif
-#if defined(OS_MACOSX)
-#include "base/allocator/allocator_interception_mac.h"
+#if defined(CLANG_COVERAGE)
+extern "C" int __llvm_profile_write_file(void);
#endif
namespace content {
namespace {
+void WriteClangCoverageProfile() {
+#if defined(CLANG_COVERAGE)
+ __llvm_profile_write_file();
+#endif
+}
+
// How long to wait for a connection to the browser process before giving up.
const int kConnectionTimeoutS = 15;
@@ -104,6 +109,7 @@ class WaitAndExitDelegate : public base::PlatformThread::Delegate {
void ThreadMain() override {
base::PlatformThread::Sleep(duration_);
+ WriteClangCoverageProfile();
_exit(0);
}
@@ -164,6 +170,7 @@ class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
__lsan_do_leak_check();
#endif
#else
+ WriteClangCoverageProfile();
_exit(0);
#endif
}
@@ -212,7 +219,7 @@ void QuitClosure::BindToMainThread() {
scoped_refptr<base::SingleThreadTaskRunner> task_runner(
base::ThreadTaskRunnerHandle::Get());
base::Closure quit_closure =
- base::MessageLoop::current()->QuitWhenIdleClosure();
+ base::RunLoop::QuitCurrentWhenIdleClosureDeprecated();
closure_ = base::Bind(&QuitClosure::PostClosure, task_runner, quit_closure);
cond_var_.Signal();
}
@@ -232,7 +239,7 @@ base::LazyInstance<QuitClosure>::DestructorAtExit g_quit_closure =
std::unique_ptr<mojo::edk::IncomingBrokerClientInvitation>
InitializeMojoIPCChannel() {
TRACE_EVENT0("startup", "InitializeMojoIPCChannel");
- mojo::edk::ScopedPlatformHandle platform_channel;
+ mojo::edk::ScopedInternalPlatformHandle platform_channel;
#if defined(OS_WIN)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch)) {
@@ -251,8 +258,9 @@ InitializeMojoIPCChannel() {
mojo::edk::PlatformChannelPair::PassClientHandleFromParentProcess(
*base::CommandLine::ForCurrentProcess());
#elif defined(OS_POSIX)
- platform_channel.reset(mojo::edk::PlatformHandle(
- base::GlobalDescriptors::GetInstance()->Get(kMojoIPCChannel)));
+ platform_channel.reset(mojo::edk::InternalPlatformHandle(
+ base::GlobalDescriptors::GetInstance()->Get(
+ service_manager::kMojoIPCChannel)));
#endif
// Mojo isn't supported on all child process types.
// TODO(crbug.com/604282): Support Mojo in the remaining processes.
@@ -432,7 +440,7 @@ void ChildThreadImpl::Init(const Options& options) {
TRACE_EVENT0("startup", "ChildThreadImpl::Init");
g_lazy_tls.Pointer()->Set(this);
on_channel_error_called_ = false;
- message_loop_ = base::MessageLoop::current();
+ main_thread_runner_ = base::ThreadTaskRunnerHandle::Get();
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
// We must make sure to instantiate the IPC Logger *before* we create the
// channel, otherwise we can get a callback on the IO thread which creates
@@ -458,7 +466,7 @@ void ChildThreadImpl::Init(const Options& options) {
std::string service_request_token =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kServiceRequestChannelToken);
+ service_manager::switches::kServiceRequestChannelToken);
if (!service_request_token.empty() && invitation) {
service_request_pipe =
invitation->ExtractMessagePipe(service_request_token);
@@ -476,8 +484,8 @@ void ChildThreadImpl::Init(const Options& options) {
}
sync_message_filter_ = channel_->CreateSyncMessageFilter();
- thread_safe_sender_ = new ThreadSafeSender(
- message_loop_->task_runner(), sync_message_filter_.get());
+ thread_safe_sender_ =
+ new ThreadSafeSender(main_thread_runner_, sync_message_filter_.get());
auto registry = std::make_unique<service_manager::BinderRegistry>();
registry->AddInterface(base::Bind(&ChildHistogramFetcherFactoryImpl::Create),
@@ -562,15 +570,7 @@ void ChildThreadImpl::Init(const Options& options) {
connection_timeout = temp;
}
-#if defined(OS_MACOSX)
- if (base::CommandLine::InitializedForCurrentProcess() &&
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableHeapProfiling)) {
- base::allocator::PeriodicallyShimNewMallocZones();
- }
-#endif
-
- message_loop_->task_runner()->PostDelayedTask(
+ main_thread_runner_->PostDelayedTask(
FROM_HERE,
base::BindOnce(&ChildThreadImpl::EnsureConnected,
channel_connected_factory_->GetWeakPtr()),
@@ -608,7 +608,7 @@ void ChildThreadImpl::InitTracing() {
channel_->AddFilter(new tracing::ChildTraceMessageFilter(
ChildProcess::current()->io_task_runner()));
- chrome_trace_event_agent_ = std::make_unique<tracing::ChromeTraceEventAgent>(
+ trace_event_agent_ = tracing::TraceEventAgent::Create(
GetConnector(), false /* request_clock_sync_marker_on_android */);
}
@@ -632,8 +632,10 @@ ChildThreadImpl::~ChildThreadImpl() {
}
void ChildThreadImpl::Shutdown() {
- // Delete objects that hold references to blink so derived classes can
- // safely shutdown blink in their Shutdown implementation.
+ // The renderer process (and others) can to fast shutdown by calling _exit(0),
+ // in which case the clang-coverage profile does not get written to the file.
+ // So force write the profile here before shutting down.
+ WriteClangCoverageProfile();
}
bool ChildThreadImpl::ShouldBeDestroyed() {
@@ -653,7 +655,7 @@ void ChildThreadImpl::OnChannelError() {
}
bool ChildThreadImpl::Send(IPC::Message* msg) {
- DCHECK(message_loop_->task_runner()->BelongsToCurrentThread());
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
if (!channel_) {
delete msg;
return false;
@@ -713,7 +715,7 @@ service_manager::Connector* ChildThreadImpl::GetConnector() {
}
IPC::MessageRouter* ChildThreadImpl::GetRouter() {
- DCHECK(message_loop_->task_runner()->BelongsToCurrentThread());
+ DCHECK(main_thread_runner_->BelongsToCurrentThread());
return &router_;
}
diff --git a/chromium/content/child/child_thread_impl.h b/chromium/content/child/child_thread_impl.h
index 523af416a39..9f4155dfdcf 100644
--- a/chromium/content/child/child_thread_impl.h
+++ b/chromium/content/child/child_thread_impl.h
@@ -12,6 +12,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
@@ -29,7 +30,7 @@
#include "ipc/message_router.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
-#include "services/tracing/public/cpp/chrome_trace_event_agent.h"
+#include "services/tracing/public/cpp/trace_event_agent.h"
#if defined(OS_WIN)
#include "content/public/common/font_cache_win.mojom.h"
@@ -37,10 +38,6 @@
#include "content/common/font_loader_mac.mojom.h"
#endif
-namespace base {
-class MessageLoop;
-} // namespace base
-
namespace IPC {
class MessageFilter;
class SyncChannel;
@@ -132,7 +129,9 @@ class CONTENT_EXPORT ChildThreadImpl
return thread_safe_sender_.get();
}
- base::MessageLoop* message_loop() const { return message_loop_; }
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner() const {
+ return main_thread_runner_;
+ }
// Returns the one child thread. Can only be called on the main thread.
static ChildThreadImpl* current();
@@ -248,13 +247,14 @@ class CONTENT_EXPORT ChildThreadImpl
// attempt to communicate.
bool on_channel_error_called_;
- base::MessageLoop* message_loop_;
+ // TaskRunner to post tasks to the main thread.
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
std::unique_ptr<base::PowerMonitor> power_monitor_;
scoped_refptr<base::SingleThreadTaskRunner> browser_process_io_runner_;
- std::unique_ptr<tracing::ChromeTraceEventAgent> chrome_trace_event_agent_;
+ std::unique_ptr<tracing::TraceEventAgent> trace_event_agent_;
std::unique_ptr<variations::ChildProcessFieldTrialSyncer> field_trial_syncer_;
diff --git a/chromium/content/child/runtime_features.cc b/chromium/content/child/runtime_features.cc
index 03a522caa66..e999f7b68a5 100644
--- a/chromium/content/child/runtime_features.cc
+++ b/chromium/content/child/runtime_features.cc
@@ -90,14 +90,17 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (enableExperimentalWebPlatformFeatures)
WebRuntimeFeatures::EnableExperimentalFeatures(true);
+ SetRuntimeFeatureDefaultsForPlatform();
+
+ // Begin individual features.
+ // Do not add individual features above this line.
+
WebRuntimeFeatures::EnableOriginTrials(
base::FeatureList::IsEnabled(features::kOriginTrials));
if (!base::FeatureList::IsEnabled(features::kWebUsb))
WebRuntimeFeatures::EnableWebUsb(false);
- SetRuntimeFeatureDefaultsForPlatform();
-
if (command_line.HasSwitch(switches::kDisableDatabases))
WebRuntimeFeatures::EnableDatabase(false);
@@ -138,15 +141,12 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
}
#if defined(OS_MACOSX)
- bool enable_canvas_2d_image_chromium = command_line.HasSwitch(
- switches::kEnableGpuMemoryBufferCompositorResources) &&
+ const bool enable_canvas_2d_image_chromium =
+ command_line.HasSwitch(
+ switches::kEnableGpuMemoryBufferCompositorResources) &&
!command_line.HasSwitch(switches::kDisable2dCanvasImageChromium) &&
- !command_line.HasSwitch(switches::kDisableGpu);
-
- if (enable_canvas_2d_image_chromium) {
- enable_canvas_2d_image_chromium =
- base::FeatureList::IsEnabled(features::kCanvas2DImageChromium);
- }
+ !command_line.HasSwitch(switches::kDisableGpu) &&
+ base::FeatureList::IsEnabled(features::kCanvas2DImageChromium);
#else
bool enable_canvas_2d_image_chromium = false;
#endif
@@ -189,9 +189,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kReducedReferrerGranularity))
WebRuntimeFeatures::EnableReducedReferrerGranularity(true);
- WebRuntimeFeatures::EnableRootLayerScrolling(
- base::FeatureList::IsEnabled(features::kRootLayerScrolling) ||
- enableExperimentalWebPlatformFeatures);
+ WebRuntimeFeatures::EnableIntersectionObserverGeometryMapper(
+ base::FeatureList::IsEnabled(
+ features::kIntersectionObserverGeometryMapper));
if (command_line.HasSwitch(switches::kDisablePermissionsAPI))
WebRuntimeFeatures::EnablePermissionsAPI(false);
@@ -210,14 +210,17 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (base::FeatureList::IsEnabled(features::kWebXrGamepadSupport))
WebRuntimeFeatures::EnableWebXRGamepadSupport(true);
+ if (base::FeatureList::IsEnabled(features::kWebXrHitTest))
+ WebRuntimeFeatures::EnableWebXRHitTest(true);
+
if (command_line.HasSwitch(switches::kDisablePresentationAPI))
WebRuntimeFeatures::EnablePresentationAPI(false);
if (command_line.HasSwitch(switches::kDisableRemotePlaybackAPI))
WebRuntimeFeatures::EnableRemotePlaybackAPI(false);
- WebRuntimeFeatures::EnableScrollAnchoring(
- base::FeatureList::IsEnabled(features::kScrollAnchoring) ||
+ WebRuntimeFeatures::EnableSecMetadata(
+ base::FeatureList::IsEnabled(features::kSecMetadata) ||
enableExperimentalWebPlatformFeatures);
WebRuntimeFeatures::EnableUserActivationV2(
@@ -232,6 +235,10 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
command_line.HasSwitch(switches::kEnableSlimmingPaintV175) ||
enableExperimentalWebPlatformFeatures);
+ WebRuntimeFeatures::EnableFeatureFromString(
+ "BlinkGenPropertyTrees",
+ command_line.HasSwitch(switches::kEnableBlinkGenPropertyTrees));
+
if (command_line.HasSwitch(switches::kEnableSlimmingPaintV2))
WebRuntimeFeatures::EnableSlimmingPaintV2(true);
@@ -297,6 +304,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (base::FeatureList::IsEnabled(features::kGamepadExtensions))
WebRuntimeFeatures::EnableGamepadExtensions(true);
+ if (base::FeatureList::IsEnabled(features::kGamepadVibration))
+ WebRuntimeFeatures::EnableGamepadVibration(true);
+
if (base::FeatureList::IsEnabled(features::kCompositeOpaqueFixedPosition))
WebRuntimeFeatures::EnableFeatureFromString("CompositeOpaqueFixedPosition",
true);
@@ -313,9 +323,6 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableGenericSensorExtraClasses(true);
}
- if (base::FeatureList::IsEnabled(features::kNotificationsWithMojo))
- WebRuntimeFeatures::EnableNotificationsWithMojo(true);
-
if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
WebRuntimeFeatures::EnableOutOfBlinkCORS(true);
@@ -330,10 +337,6 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
false);
}
- if (base::FeatureList::IsEnabled(
- features::kTurnOff2DAndOpacityCompositorAnimations))
- WebRuntimeFeatures::EnableTurnOff2DAndOpacityCompositorAnimations(true);
-
if (base::FeatureList::IsEnabled(features::kRasterInducingScroll))
WebRuntimeFeatures::EnableRasterInducingScroll(true);
@@ -362,10 +365,8 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableResourceLoadScheduler(
base::FeatureList::IsEnabled(features::kResourceLoadScheduler));
- if (command_line.HasSwitch(
- switches::kDisableOriginTrialControlledBlinkFeatures)) {
- WebRuntimeFeatures::EnableOriginTrialControlledFeatures(false);
- }
+ if (base::FeatureList::IsEnabled(features::kLayeredAPI))
+ WebRuntimeFeatures::EnableLayeredAPI(true);
WebRuntimeFeatures::EnableLazyInitializeMediaControls(
base::FeatureList::IsEnabled(features::kLazyInitializeMediaControls));
@@ -402,17 +403,6 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (base::FeatureList::IsEnabled(features::kLazyFrameLoading))
WebRuntimeFeatures::EnableLazyFrameLoading(true);
- // Enable explicitly enabled features, and then disable explicitly disabled
- // ones.
- for (const std::string& feature :
- FeaturesFromSwitch(command_line, switches::kEnableBlinkFeatures)) {
- WebRuntimeFeatures::EnableFeatureFromString(feature, true);
- }
- for (const std::string& feature :
- FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
- WebRuntimeFeatures::EnableFeatureFromString(feature, false);
- }
-
WebRuntimeFeatures::EnableV8ContextSnapshot(
base::FeatureList::IsEnabled(features::kV8ContextSnapshot));
@@ -434,21 +424,47 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnablePictureInPicture(
base::FeatureList::IsEnabled(media::kPictureInPicture));
- WebRuntimeFeatures::EnableCodeCacheAfterExecute(
- base::FeatureList::IsEnabled(features::kCodeCacheAfterExecute));
-
WebRuntimeFeatures::EnableCacheInlineScriptCode(
base::FeatureList::IsEnabled(features::kCacheInlineScriptCode));
- if (base::FeatureList::IsEnabled(features::kUnifiedTouchAdjustment))
- WebRuntimeFeatures::EnableUnifiedTouchAdjustment(true);
-
// Make srcset on link rel=preload work with SignedHTTPExchange flag too.
if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
WebRuntimeFeatures::EnablePreloadImageSrcSetEnabled(true);
WebRuntimeFeatures::EnableOffMainThreadWebSocket(
base::FeatureList::IsEnabled(features::kOffMainThreadWebSocket));
+
+ if (base::FeatureList::IsEnabled(
+ features::kExperimentalProductivityFeatures)) {
+ WebRuntimeFeatures::EnableExperimentalProductivityFeatures(true);
+ }
+
+#if defined(OS_ANDROID)
+ if (base::FeatureList::IsEnabled(features::kDisplayCutoutAPI))
+ WebRuntimeFeatures::EnableDisplayCutoutViewportFit(true);
+#endif
+
+ // End individual features.
+ // Do not add individual features below this line.
+
+ if (command_line.HasSwitch(
+ switches::kDisableOriginTrialControlledBlinkFeatures)) {
+ WebRuntimeFeatures::EnableOriginTrialControlledFeatures(false);
+ }
+
+ WebRuntimeFeatures::EnableAutoplayIgnoresWebAudio(
+ base::FeatureList::IsEnabled(media::kAutoplayIgnoreWebAudio));
+
+ // Enable explicitly enabled features, and then disable explicitly disabled
+ // ones.
+ for (const std::string& feature :
+ FeaturesFromSwitch(command_line, switches::kEnableBlinkFeatures)) {
+ WebRuntimeFeatures::EnableFeatureFromString(feature, true);
+ }
+ for (const std::string& feature :
+ FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
+ WebRuntimeFeatures::EnableFeatureFromString(feature, false);
+ }
};
} // namespace content
diff --git a/chromium/content/child/webfallbackthemeengine_impl.cc b/chromium/content/child/webfallbackthemeengine_impl.cc
deleted file mode 100644
index 5c091bc0a75..00000000000
--- a/chromium/content/child/webfallbackthemeengine_impl.cc
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2014 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/child/webfallbackthemeengine_impl.h"
-
-#include "base/macros.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/platform/web_size.h"
-#include "ui/native_theme/native_theme_base.h"
-
-using blink::WebCanvas;
-using blink::WebColor;
-using blink::WebRect;
-using blink::WebFallbackThemeEngine;
-
-namespace content {
-
-class WebFallbackThemeEngineImpl::WebFallbackNativeTheme
- : public ui::NativeThemeBase {
- public:
- WebFallbackNativeTheme() {}
- ~WebFallbackNativeTheme() override {}
-
- // NativeTheme:
- SkColor GetSystemColor(ColorId color_id) const override {
- // The paint routines in NativeThemeBase only use GetSystemColor for
- // button focus colors and the fallback theme is not used for buttons.
- NOTREACHED();
- return SK_ColorRED;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebFallbackNativeTheme);
-};
-
-static ui::NativeTheme::Part NativeThemePart(
- WebFallbackThemeEngine::Part part) {
- switch (part) {
- case WebFallbackThemeEngine::kPartScrollbarDownArrow:
- return ui::NativeTheme::kScrollbarDownArrow;
- case WebFallbackThemeEngine::kPartScrollbarLeftArrow:
- return ui::NativeTheme::kScrollbarLeftArrow;
- case WebFallbackThemeEngine::kPartScrollbarRightArrow:
- return ui::NativeTheme::kScrollbarRightArrow;
- case WebFallbackThemeEngine::kPartScrollbarUpArrow:
- return ui::NativeTheme::kScrollbarUpArrow;
- case WebFallbackThemeEngine::kPartScrollbarHorizontalThumb:
- return ui::NativeTheme::kScrollbarHorizontalThumb;
- case WebFallbackThemeEngine::kPartScrollbarVerticalThumb:
- return ui::NativeTheme::kScrollbarVerticalThumb;
- case WebFallbackThemeEngine::kPartScrollbarHorizontalTrack:
- return ui::NativeTheme::kScrollbarHorizontalTrack;
- case WebFallbackThemeEngine::kPartScrollbarVerticalTrack:
- return ui::NativeTheme::kScrollbarVerticalTrack;
- case WebFallbackThemeEngine::kPartScrollbarCorner:
- return ui::NativeTheme::kScrollbarCorner;
- case WebFallbackThemeEngine::kPartCheckbox:
- return ui::NativeTheme::kCheckbox;
- case WebFallbackThemeEngine::kPartRadio:
- return ui::NativeTheme::kRadio;
- case WebFallbackThemeEngine::kPartButton:
- return ui::NativeTheme::kPushButton;
- case WebFallbackThemeEngine::kPartTextField:
- return ui::NativeTheme::kTextField;
- case WebFallbackThemeEngine::kPartMenuList:
- return ui::NativeTheme::kMenuList;
- case WebFallbackThemeEngine::kPartSliderTrack:
- return ui::NativeTheme::kSliderTrack;
- case WebFallbackThemeEngine::kPartSliderThumb:
- return ui::NativeTheme::kSliderThumb;
- case WebFallbackThemeEngine::kPartInnerSpinButton:
- return ui::NativeTheme::kInnerSpinButton;
- case WebFallbackThemeEngine::kPartProgressBar:
- return ui::NativeTheme::kProgressBar;
- default:
- return ui::NativeTheme::kScrollbarDownArrow;
- }
-}
-
-static ui::NativeTheme::State NativeThemeState(
- WebFallbackThemeEngine::State state) {
- switch (state) {
- case WebFallbackThemeEngine::kStateDisabled:
- return ui::NativeTheme::kDisabled;
- case WebFallbackThemeEngine::kStateHover:
- return ui::NativeTheme::kHovered;
- case WebFallbackThemeEngine::kStateNormal:
- return ui::NativeTheme::kNormal;
- case WebFallbackThemeEngine::kStatePressed:
- return ui::NativeTheme::kPressed;
- default:
- return ui::NativeTheme::kDisabled;
- }
-}
-
-static void GetNativeThemeExtraParams(
- WebFallbackThemeEngine::Part part,
- WebFallbackThemeEngine::State state,
- const WebFallbackThemeEngine::ExtraParams* extra_params,
- ui::NativeTheme::ExtraParams* native_theme_extra_params) {
- switch (part) {
- case WebFallbackThemeEngine::kPartScrollbarHorizontalTrack:
- case WebFallbackThemeEngine::kPartScrollbarVerticalTrack:
- native_theme_extra_params->scrollbar_track.track_x =
- extra_params->scrollbar_track.track_x;
- native_theme_extra_params->scrollbar_track.track_y =
- extra_params->scrollbar_track.track_y;
- native_theme_extra_params->scrollbar_track.track_width =
- extra_params->scrollbar_track.track_width;
- native_theme_extra_params->scrollbar_track.track_height =
- extra_params->scrollbar_track.track_height;
- break;
- case WebFallbackThemeEngine::kPartCheckbox:
- native_theme_extra_params->button.checked = extra_params->button.checked;
- native_theme_extra_params->button.indeterminate =
- extra_params->button.indeterminate;
- break;
- case WebFallbackThemeEngine::kPartRadio:
- native_theme_extra_params->button.checked = extra_params->button.checked;
- break;
- case WebFallbackThemeEngine::kPartButton:
- native_theme_extra_params->button.is_default =
- extra_params->button.is_default;
- native_theme_extra_params->button.has_border =
- extra_params->button.has_border;
- // Native buttons have a different focus style.
- native_theme_extra_params->button.is_focused = false;
- native_theme_extra_params->button.background_color =
- extra_params->button.background_color;
- break;
- case WebFallbackThemeEngine::kPartTextField:
- native_theme_extra_params->text_field.is_text_area =
- extra_params->text_field.is_text_area;
- native_theme_extra_params->text_field.is_listbox =
- extra_params->text_field.is_listbox;
- native_theme_extra_params->text_field.background_color =
- extra_params->text_field.background_color;
- break;
- case WebFallbackThemeEngine::kPartMenuList:
- native_theme_extra_params->menu_list.has_border =
- extra_params->menu_list.has_border;
- native_theme_extra_params->menu_list.has_border_radius =
- extra_params->menu_list.has_border_radius;
- native_theme_extra_params->menu_list.arrow_x =
- extra_params->menu_list.arrow_x;
- native_theme_extra_params->menu_list.arrow_y =
- extra_params->menu_list.arrow_y;
- native_theme_extra_params->menu_list.arrow_size =
- extra_params->menu_list.arrow_size;
- native_theme_extra_params->menu_list.arrow_color =
- extra_params->menu_list.arrow_color;
- native_theme_extra_params->menu_list.background_color =
- extra_params->menu_list.background_color;
- break;
- case WebFallbackThemeEngine::kPartSliderTrack:
- case WebFallbackThemeEngine::kPartSliderThumb:
- native_theme_extra_params->slider.vertical =
- extra_params->slider.vertical;
- native_theme_extra_params->slider.in_drag = extra_params->slider.in_drag;
- break;
- case WebFallbackThemeEngine::kPartInnerSpinButton:
- native_theme_extra_params->inner_spin.spin_up =
- extra_params->inner_spin.spin_up;
- native_theme_extra_params->inner_spin.read_only =
- extra_params->inner_spin.read_only;
- break;
- case WebFallbackThemeEngine::kPartProgressBar:
- native_theme_extra_params->progress_bar.determinate =
- extra_params->progress_bar.determinate;
- native_theme_extra_params->progress_bar.value_rect_x =
- extra_params->progress_bar.value_rect_x;
- native_theme_extra_params->progress_bar.value_rect_y =
- extra_params->progress_bar.value_rect_y;
- native_theme_extra_params->progress_bar.value_rect_width =
- extra_params->progress_bar.value_rect_width;
- native_theme_extra_params->progress_bar.value_rect_height =
- extra_params->progress_bar.value_rect_height;
- break;
- default:
- break; // Parts that have no extra params get here.
- }
-}
-
-WebFallbackThemeEngineImpl::WebFallbackThemeEngineImpl()
- : theme_(new WebFallbackNativeTheme()) {}
-
-WebFallbackThemeEngineImpl::~WebFallbackThemeEngineImpl() {}
-
-blink::WebSize WebFallbackThemeEngineImpl::GetSize(
- WebFallbackThemeEngine::Part part) {
- ui::NativeTheme::ExtraParams extra;
- return theme_->GetPartSize(NativeThemePart(part),
- ui::NativeTheme::kNormal,
- extra);
-}
-
-void WebFallbackThemeEngineImpl::Paint(
- blink::WebCanvas* canvas,
- WebFallbackThemeEngine::Part part,
- WebFallbackThemeEngine::State state,
- const blink::WebRect& rect,
- const WebFallbackThemeEngine::ExtraParams* extra_params) {
- ui::NativeTheme::ExtraParams native_theme_extra_params;
- GetNativeThemeExtraParams(
- part, state, extra_params, &native_theme_extra_params);
- theme_->Paint(canvas,
- NativeThemePart(part),
- NativeThemeState(state),
- gfx::Rect(rect),
- native_theme_extra_params);
-}
-
-} // namespace content
diff --git a/chromium/content/child/webfallbackthemeengine_impl.h b/chromium/content/child/webfallbackthemeengine_impl.h
deleted file mode 100644
index 53f7b83c2df..00000000000
--- a/chromium/content/child/webfallbackthemeengine_impl.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 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_CHILD_WEBFALLBACKTHEMEENGINE_IMPL_H_
-#define CONTENT_CHILD_WEBFALLBACKTHEMEENGINE_IMPL_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "third_party/blink/public/platform/web_fallback_theme_engine.h"
-
-namespace content {
-
-// This theme should only be used in layout tests in cases the mock theme can't
-// handle (such as zoomed controls).
-class WebFallbackThemeEngineImpl : public blink::WebFallbackThemeEngine {
- public:
- WebFallbackThemeEngineImpl();
- ~WebFallbackThemeEngineImpl();
-
- // WebFallbackThemeEngine methods:
- blink::WebSize GetSize(blink::WebFallbackThemeEngine::Part) override;
- void Paint(
- blink::WebCanvas* canvas,
- blink::WebFallbackThemeEngine::Part part,
- blink::WebFallbackThemeEngine::State state,
- const blink::WebRect& rect,
- const blink::WebFallbackThemeEngine::ExtraParams* extra_params) override;
-
- private:
- class WebFallbackNativeTheme;
- std::unique_ptr<WebFallbackNativeTheme> theme_;
-
- DISALLOW_COPY_AND_ASSIGN(WebFallbackThemeEngineImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEBFALLBACKTHEMEENGINE_IMPL_H_
diff --git a/chromium/content/child/webthemeengine_impl_android.cc b/chromium/content/child/webthemeengine_impl_android.cc
index a66f7fbce54..6b14c3e23d7 100644
--- a/chromium/content/child/webthemeengine_impl_android.cc
+++ b/chromium/content/child/webthemeengine_impl_android.cc
@@ -12,7 +12,6 @@
#include "ui/native_theme/native_theme.h"
using blink::WebCanvas;
-using blink::WebColor;
using blink::WebRect;
using blink::WebThemeEngine;
diff --git a/chromium/content/child/webthemeengine_impl_default.cc b/chromium/content/child/webthemeengine_impl_default.cc
index 6d898cc534c..13e0a6278c9 100644
--- a/chromium/content/child/webthemeengine_impl_default.cc
+++ b/chromium/content/child/webthemeengine_impl_default.cc
@@ -12,7 +12,6 @@
#include "ui/native_theme/overlay_scrollbar_constants_aura.h"
using blink::WebCanvas;
-using blink::WebColor;
using blink::WebRect;
using blink::WebThemeEngine;
using blink::WebScrollbarOverlayColorTheme;
diff --git a/chromium/content/common/BUILD.gn b/chromium/content/common/BUILD.gn
index 397d9172812..de4c4d2af49 100644
--- a/chromium/content/common/BUILD.gn
+++ b/chromium/content/common/BUILD.gn
@@ -7,7 +7,6 @@ import("//build/buildflag_header.gni")
import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//ipc/features.gni")
-import("//media/media_options.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//ppapi/buildflags/buildflags.gni")
import("//sandbox/features.gni")
@@ -65,8 +64,6 @@ source_set("common") {
"browser_plugin/browser_plugin_constants.cc",
"browser_plugin/browser_plugin_constants.h",
"browser_plugin/browser_plugin_messages.h",
- "cache_storage/cache_storage_types.cc",
- "cache_storage/cache_storage_types.h",
"child_process_host_impl.cc",
"child_process_host_impl.h",
"common_sandbox_support_linux.cc",
@@ -138,8 +135,8 @@ source_set("common") {
"frame_owner_properties.h",
"frame_replication_state.cc",
"frame_replication_state.h",
- "frame_resize_params.cc",
- "frame_resize_params.h",
+ "frame_visual_properties.cc",
+ "frame_visual_properties.h",
"gin_java_bridge_messages.h",
"in_process_child_thread_params.cc",
"in_process_child_thread_params.h",
@@ -205,7 +202,6 @@ source_set("common") {
"mac/font_loader.h",
"mac/font_loader.mm",
"media/aec_dump_messages.h",
- "media/audio_messages.h",
"media/cdm_info.cc",
"media/media_devices.cc",
"media/media_devices.h",
@@ -231,9 +227,9 @@ source_set("common") {
"net/url_request_user_data.h",
"notifications/notification_struct_traits.cc",
"notifications/notification_struct_traits.h",
- "origin_trials/trial_policy_impl.cc",
- "origin_trials/trial_policy_impl.h",
"origin_util.cc",
+ "p2p_messages.h",
+ "p2p_socket_type.h",
"page_message_enums.h",
"page_messages.h",
"page_state_serialization.cc",
@@ -250,13 +246,12 @@ source_set("common") {
"plugin_list.h",
"possibly_associated_interface_ptr.h",
"possibly_associated_interface_ptr_info.h",
+ "possibly_associated_wrapper_shared_url_loader_factory.h",
"presentation/presentation_struct_traits.cc",
"presentation/presentation_struct_traits.h",
"process_type.cc",
"render_widget_surface_properties.cc",
"render_widget_surface_properties.h",
- "resize_params.cc",
- "resize_params.h",
"resource_messages.h",
"resource_timing_info.cc",
"resource_timing_info.h",
@@ -264,7 +259,6 @@ source_set("common") {
"sandbox_init_mac.cc",
"sandbox_init_win.cc",
"savable_subframe.h",
- "send_zygote_child_ping_linux.cc",
"service_manager/service_manager_connection_impl.cc",
"service_manager/service_manager_connection_impl.h",
"service_worker/service_worker_loader_helpers.cc",
@@ -280,7 +274,6 @@ source_set("common") {
"service_worker/service_worker_utils.h",
"single_request_url_loader_factory.cc",
"single_request_url_loader_factory.h",
- "speech_recognition_messages.h",
"swapped_out_messages.cc",
"swapped_out_messages.h",
"task_scheduler.cc",
@@ -299,9 +292,8 @@ source_set("common") {
"user_agent.cc",
"view_message_enums.h",
"view_messages.h",
- "wrapper_shared_url_loader_factory.cc",
- "wrapper_shared_url_loader_factory.h",
- "zygote_commands_linux.h",
+ "visual_properties.cc",
+ "visual_properties.h",
]
configs += [
@@ -326,7 +318,6 @@ source_set("common") {
"//base",
"//base/third_party/dynamic_annotations",
"//build/util:webkit_version",
- "//cc/ipc",
"//components/discardable_memory/common",
"//components/services/filesystem/public/interfaces",
"//components/tracing",
@@ -334,9 +325,9 @@ source_set("common") {
"//components/viz/service",
"//content:resources",
"//content/app/resources",
+ "//content/common/service_worker:service_worker_types_proto",
"//content/public/common:interfaces",
"//content/public/common:service_names",
- "//content/public/common:zygote_buildflags",
"//device/base/synchronization",
"//device/bluetooth",
"//gpu",
@@ -372,6 +363,7 @@ source_set("common") {
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
"//services/service_manager/runner/common",
+ "//services/service_manager/zygote:zygote_buildflags",
"//services/ui/public/interfaces",
"//services/video_capture/public/mojom",
"//services/viz/public/interfaces",
@@ -380,6 +372,8 @@ source_set("common") {
"//third_party/angle:angle_gpu_info_util",
"//third_party/boringssl",
"//third_party/icu",
+ "//third_party/webrtc/rtc_base:rtc_base",
+ "//third_party/webrtc_overrides",
"//ui/base",
"//ui/base/ime",
"//ui/display",
@@ -437,17 +431,6 @@ source_set("common") {
deps += [ "//ppapi/proxy:ipc_sources" ]
}
- if (enable_webrtc) {
- sources += [
- "p2p_messages.h",
- "p2p_socket_type.h",
- ]
- deps += [
- "//third_party/webrtc/rtc_base:rtc_base",
- "//third_party/webrtc_overrides",
- ]
- }
-
if (use_ozone) {
deps += [ "//ui/ozone" ]
} else {
@@ -510,6 +493,8 @@ source_set("common") {
"sandbox_policy_fuchsia.cc",
"sandbox_policy_fuchsia.h",
]
+
+ deps += [ "//third_party/fuchsia-sdk:launchpad" ]
}
}
@@ -535,6 +520,8 @@ mojom("mojo_bindings") {
# both a direct and an indirect dependency on the same target
skip_deps_check = true
+ disable_variants = true
+
sources = [
"appcache.mojom",
"associated_interfaces.mojom",
@@ -542,7 +529,6 @@ mojom("mojo_bindings") {
"child_control.mojom",
"child_memory_coordinator.mojom",
"field_trial_recorder.mojom",
- "file_utilities.mojom",
"frame.mojom",
"frame_sink_provider.mojom",
"histogram_fetcher.mojom",
@@ -583,6 +569,7 @@ mojom("mojo_bindings") {
"shared_worker/shared_worker_factory.mojom",
"shared_worker/shared_worker_host.mojom",
"shared_worker/shared_worker_info.mojom",
+ "speech_recognizer.mojom",
"storage_partition_service.mojom",
"url_loader_factory_bundle.mojom",
"widget.mojom",
diff --git a/chromium/content/common/DEPS b/chromium/content/common/DEPS
index 17e3223f618..c6649bd23f8 100644
--- a/chromium/content/common/DEPS
+++ b/chromium/content/common/DEPS
@@ -23,7 +23,6 @@ include_rules = [
"+third_party/blink/public/mojom",
"+third_party/blink/public/platform/WebAddressSpace.h",
"+third_party/blink/public/platform/web_content_security_policy.h",
- "+third_party/blink/public/platform/web_display_mode.h",
"+third_party/blink/public/platform/web_drag_operation.h",
"+third_party/blink/public/platform/web_float_point.h",
"+third_party/blink/public/platform/web_float_rect.h",
@@ -45,6 +44,7 @@ include_rules = [
"+third_party/blink/public/platform/web_screen_info.h",
"+third_party/blink/public/platform/web_scrollbar_buttons_placement.h",
"+third_party/blink/public/platform/web_scroll_into_view_params.h",
+ "+third_party/blink/public/platform/web_scroll_types.h",
"+third_party/blink/public/platform/web_storage_area.h",
"+third_party/blink/public/platform/web_sudden_termination_disabler_type.h",
"+third_party/blink/public/platform/web_touch_event.h",
@@ -64,9 +64,6 @@ include_rules = [
"+third_party/blink/public/platform/modules/presentation/presentation.mojom.h",
"+third_party/blink/public/platform/modules/push_messaging/web_push_error.h",
"+third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_availability.h",
- "+third_party/blink/public/platform/modules/screen_orientation/web_lock_orientation_error.h",
- "+third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h",
- "+third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_type.h",
"+third_party/blink/public/platform/modules/payments/WebPaymentAppRequest.h",
"+third_party/blink/public/platform/modules/serviceworker/WebServiceWorkerClientType.h",
"+third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h",
@@ -76,6 +73,7 @@ include_rules = [
"+third_party/blink/public/web/web_find_options.h",
"+third_party/blink/public/web/web_frame_owner_properties.h",
"+third_party/blink/public/web/web_frame_serializer_cache_control_policy.h",
+ "+third_party/blink/public/web/web_fullscreen_options.h",
"+third_party/blink/public/web/web_ime_text_span.h",
"+third_party/blink/public/web/web_media_player_action.h",
"+third_party/blink/public/web/web_plugin_action.h",
diff --git a/chromium/content/common/OWNERS b/chromium/content/common/OWNERS
index 5baee77702b..c3390635291 100644
--- a/chromium/content/common/OWNERS
+++ b/chromium/content/common/OWNERS
@@ -7,10 +7,14 @@ per-file sandbox_init_win.cc=set noparent
per-file sandbox_init_win.cc=file://sandbox/win/OWNERS
# Mac Sandbox.
-per-file sandbox_init_mac.*=rsesek@chromium.org
-per-file sandbox_mac*=rsesek@chromium.org
+per-file sandbox_init_mac.cc=set noparent
+per-file sandbox_init_mac.cc=file://sandbox/mac/OWNERS
+
+per-file sandbox_mac*=set noparent
+per-file sandbox_mac*=file://sandbox/mac/OWNERS
+
per-file *.sb=set noparent
-per-file *.sb=rsesek@chromium.org
+per-file *.sb=file://sandbox/mac/OWNERS
per-file pepper*=bauerb@chromium.org
per-file plugin*=bauerb@chromium.org
diff --git a/chromium/content/common/associated_interface_provider_impl.h b/chromium/content/common/associated_interface_provider_impl.h
index 91d196c4c90..a46b6575ca5 100644
--- a/chromium/content/common/associated_interface_provider_impl.h
+++ b/chromium/content/common/associated_interface_provider_impl.h
@@ -11,6 +11,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/associated_interfaces.mojom.h"
namespace content {
diff --git a/chromium/content/common/browser_plugin/browser_plugin_messages.h b/chromium/content/common/browser_plugin/browser_plugin_messages.h
index 87991910cd3..bef070d8e16 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_messages.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_messages.h
@@ -9,13 +9,13 @@
#include "base/process/process.h"
#include "base/unguessable_token.h"
-#include "cc/ipc/cc_param_traits.h"
+#include "cc/trees/render_frame_metadata.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
#include "content/common/cursors/webcursor.h"
#include "content/common/edit_command.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/screen_info.h"
#include "ipc/ipc_channel_handle.h"
@@ -156,10 +156,10 @@ IPC_MESSAGE_CONTROL1(BrowserPluginHostMsg_UnlockMouse_ACK,
int /* browser_plugin_instance_id */)
// Sent when plugin's position has changed.
-IPC_MESSAGE_CONTROL3(BrowserPluginHostMsg_UpdateResizeParams,
+IPC_MESSAGE_CONTROL3(BrowserPluginHostMsg_SynchronizeVisualProperties,
int /* browser_plugin_instance_id */,
viz::LocalSurfaceId /* local_surface_id */,
- content::FrameResizeParams /* resize_params */)
+ content::FrameVisualProperties /* resize_params */)
// -----------------------------------------------------------------------------
// These messages are from the browser process to the embedder.
@@ -187,11 +187,10 @@ IPC_MESSAGE_CONTROL2(BrowserPluginMsg_AdvanceFocus,
int /* browser_plugin_instance_id */,
bool /* reverse */)
-// When a guest resizes due to auto-resize, this message informs the
-// BrowserPlugin to request a new viz::LocalSurfaceId.
-IPC_MESSAGE_CONTROL2(BrowserPluginMsg_ResizeDueToAutoResize,
+// Informs the BrowserPlugin that the guest's visual properties have changed.
+IPC_MESSAGE_CONTROL2(BrowserPluginMsg_DidUpdateVisualProperties,
int /* browser_plugin_instance_id */,
- uint64_t /* sequence_number */)
+ cc::RenderFrameMetadata /* metadata */)
// Requests a viz::LocalSurfaceId to enable auto-resize mode from the parent
// renderer.
diff --git a/chromium/content/common/cache_storage/OWNERS b/chromium/content/common/cache_storage/OWNERS
index d55e59d60d9..5e0c72bf2bb 100644
--- a/chromium/content/common/cache_storage/OWNERS
+++ b/chromium/content/common/cache_storage/OWNERS
@@ -1,4 +1,3 @@
-michaeln@chromium.org
nhiroki@chromium.org
jkarlin@chromium.org
jsbell@chromium.org
diff --git a/chromium/content/common/cache_storage/cache_storage.typemap b/chromium/content/common/cache_storage/cache_storage.typemap
deleted file mode 100644
index b04b8896324..00000000000
--- a/chromium/content/common/cache_storage/cache_storage.typemap
+++ /dev/null
@@ -1,19 +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.
-
-mojom = "//third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom"
-public_headers = [
- "//content/common/cache_storage/cache_storage_types.h",
- "//content/common/service_worker/service_worker_types.h",
-]
-traits_headers =
- [ "//content/common/cache_storage/cache_storage_mojom_traits.h" ]
-sources = [
- "//content/common/cache_storage/cache_storage_mojom_traits.cc",
-]
-type_mappings = [
- "blink.mojom.BatchOperation=content::CacheStorageBatchOperation",
- "blink.mojom.OperationType=content::CacheStorageCacheOperationType",
- "blink.mojom.QueryParams=content::CacheStorageCacheQueryParams",
-]
diff --git a/chromium/content/common/cache_storage/cache_storage_mojom_traits.cc b/chromium/content/common/cache_storage/cache_storage_mojom_traits.cc
deleted file mode 100644
index 0face783f87..00000000000
--- a/chromium/content/common/cache_storage/cache_storage_mojom_traits.cc
+++ /dev/null
@@ -1,75 +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/common/cache_storage/cache_storage_mojom_traits.h"
-#include "base/logging.h"
-#include "content/public/common/referrer_struct_traits.h"
-
-namespace mojo {
-
-using blink::mojom::CacheStorageError;
-using blink::mojom::OperationType;
-
-OperationType
-EnumTraits<OperationType, content::CacheStorageCacheOperationType>::ToMojom(
- content::CacheStorageCacheOperationType input) {
- switch (input) {
- case content::CACHE_STORAGE_CACHE_OPERATION_TYPE_UNDEFINED:
- return OperationType::kUndefined;
- case content::CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT:
- return OperationType::kPut;
- case content::CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE:
- return OperationType::kDelete;
- }
- NOTREACHED();
- return OperationType::kUndefined;
-}
-
-bool EnumTraits<OperationType, content::CacheStorageCacheOperationType>::
- FromMojom(OperationType input,
- content::CacheStorageCacheOperationType* out) {
- switch (input) {
- case OperationType::kUndefined:
- *out = content::CACHE_STORAGE_CACHE_OPERATION_TYPE_UNDEFINED;
- return true;
- case OperationType::kPut:
- *out = content::CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- return true;
- case OperationType::kDelete:
- *out = content::CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
- return true;
- }
- return false;
-}
-
-bool StructTraits<blink::mojom::QueryParamsDataView,
- content::CacheStorageCacheQueryParams>::
- Read(blink::mojom::QueryParamsDataView data,
- content::CacheStorageCacheQueryParams* out) {
- base::Optional<base::string16> cache_name;
- if (!data.ReadCacheName(&cache_name))
- return false;
- out->cache_name = base::NullableString16(std::move(cache_name));
- out->ignore_search = data.ignore_search();
- out->ignore_method = data.ignore_method();
- out->ignore_vary = data.ignore_vary();
- return true;
-}
-
-bool StructTraits<blink::mojom::BatchOperationDataView,
- content::CacheStorageBatchOperation>::
- Read(blink::mojom::BatchOperationDataView data,
- content::CacheStorageBatchOperation* out) {
- if (!data.ReadRequest(&out->request))
- return false;
- if (!data.ReadResponse(&out->response))
- return false;
- if (!data.ReadMatchParams(&out->match_params))
- return false;
- if (!data.ReadOperationType(&out->operation_type))
- return false;
- return true;
-}
-
-} // namespace mojo
diff --git a/chromium/content/common/cache_storage/cache_storage_types.cc b/chromium/content/common/cache_storage/cache_storage_types.cc
deleted file mode 100644
index 198e6eaf300..00000000000
--- a/chromium/content/common/cache_storage/cache_storage_types.cc
+++ /dev/null
@@ -1,19 +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.
-
-#include "content/common/cache_storage/cache_storage_types.h"
-
-namespace content {
-
-CacheStorageCacheQueryParams::CacheStorageCacheQueryParams()
- : ignore_search(false), ignore_method(false), ignore_vary(false) {
-}
-
-CacheStorageBatchOperation::CacheStorageBatchOperation() {
-}
-
-CacheStorageBatchOperation::CacheStorageBatchOperation(
- const CacheStorageBatchOperation& other) = default;
-
-} // namespace content
diff --git a/chromium/content/common/cache_storage/cache_storage_types.h b/chromium/content/common/cache_storage/cache_storage_types.h
deleted file mode 100644
index 61d8b769170..00000000000
--- a/chromium/content/common/cache_storage/cache_storage_types.h
+++ /dev/null
@@ -1,52 +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 CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_TYPES_H_
-#define CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_TYPES_H_
-
-#include <map>
-#include <string>
-
-#include "base/strings/nullable_string16.h"
-#include "content/common/content_export.h"
-#include "content/common/service_worker/service_worker_types.h"
-
-// This file is to have common definitions that are to be shared by
-// browser and child process.
-
-namespace content {
-
-// Controls how requests are matched in the Cache API.
-struct CONTENT_EXPORT CacheStorageCacheQueryParams {
- CacheStorageCacheQueryParams();
-
- bool ignore_search = false;
- bool ignore_method = false;
- bool ignore_vary = false;
- base::NullableString16 cache_name;
-};
-
-// The type of a single batch operation in the Cache API.
-enum CacheStorageCacheOperationType {
- CACHE_STORAGE_CACHE_OPERATION_TYPE_UNDEFINED,
- CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT,
- CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE,
- CACHE_STORAGE_CACHE_OPERATION_TYPE_LAST =
- CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE
-};
-
-// A single batch operation for the Cache API.
-struct CONTENT_EXPORT CacheStorageBatchOperation {
- CacheStorageBatchOperation();
- CacheStorageBatchOperation(const CacheStorageBatchOperation& other);
-
- CacheStorageCacheOperationType operation_type;
- ServiceWorkerFetchRequest request;
- ServiceWorkerResponse response;
- CacheStorageCacheQueryParams match_params;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_TYPES_H_
diff --git a/chromium/content/common/child_process_host_impl.cc b/chromium/content/common/child_process_host_impl.cc
index d2b99832168..bc78aba80ac 100644
--- a/chromium/content/common/child_process_host_impl.cc
+++ b/chromium/content/common/child_process_host_impl.cc
@@ -11,7 +11,6 @@
#include "base/files/file_path.h"
#include "base/hash.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/path_service.h"
@@ -68,7 +67,7 @@ base::FilePath ChildProcessHost::GetChildPath(int flags) {
// On most platforms, the child executable is the same as the current
// executable.
if (child_path.empty())
- PathService::Get(CHILD_PROCESS_EXE, &child_path);
+ base::PathService::Get(CHILD_PROCESS_EXE, &child_path);
return child_path;
}
diff --git a/chromium/content/common/child_process_host_impl.h b/chromium/content/common/child_process_host_impl.h
index 659cffaf25d..99644ea03dd 100644
--- a/chromium/content/common/child_process_host_impl.h
+++ b/chromium/content/common/child_process_host_impl.h
@@ -71,6 +71,8 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
+ base::Process& peer_process() { return peer_process_; }
+
private:
friend class ChildProcessHost;
diff --git a/chromium/content/common/common_param_traits_unittest.cc b/chromium/content/common/common_param_traits_unittest.cc
index 71b30f65c4d..4d4ee04d13b 100644
--- a/chromium/content/common/common_param_traits_unittest.cc
+++ b/chromium/content/common/common_param_traits_unittest.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/values.h"
+#include "components/viz/common/surfaces/surface_info.h"
#include "content/common/resource_messages.h"
#include "content/public/common/content_constants.h"
#include "ipc/ipc_message.h"
@@ -285,3 +286,24 @@ TEST(IPCMessageTest, RenderWidgetSurfaceProperties) {
output.has_transparent_background);
#endif
}
+
+static constexpr viz::FrameSinkId kArbitraryFrameSinkId(1, 1);
+
+TEST(IPCMessageTest, SurfaceInfo) {
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ const viz::SurfaceId kArbitrarySurfaceId(
+ kArbitraryFrameSinkId,
+ viz::LocalSurfaceId(3, base::UnguessableToken::Create()));
+ constexpr float kArbitraryDeviceScaleFactor = 0.9f;
+ const gfx::Size kArbitrarySize(65, 321);
+ const viz::SurfaceInfo surface_info_in(
+ kArbitrarySurfaceId, kArbitraryDeviceScaleFactor, kArbitrarySize);
+ IPC::ParamTraits<viz::SurfaceInfo>::Write(&msg, surface_info_in);
+
+ viz::SurfaceInfo surface_info_out;
+ base::PickleIterator iter(msg);
+ EXPECT_TRUE(
+ IPC::ParamTraits<viz::SurfaceInfo>::Read(&msg, &iter, &surface_info_out));
+
+ ASSERT_EQ(surface_info_in, surface_info_out);
+}
diff --git a/chromium/content/common/common_sandbox_support_linux.cc b/chromium/content/common/common_sandbox_support_linux.cc
index ed806b7f998..c80e44a6d2b 100644
--- a/chromium/content/common/common_sandbox_support_linux.cc
+++ b/chromium/content/common/common_sandbox_support_linux.cc
@@ -4,21 +4,14 @@
#include "content/public/common/common_sandbox_support_linux.h"
-#include <stddef.h>
#include <sys/stat.h>
#include <limits>
#include <memory>
#include "base/numerics/safe_conversions.h"
-#include "base/pickle.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/posix/global_descriptors.h"
-#include "base/posix/unix_domain_socket.h"
#include "base/sys_byteorder.h"
-#include "base/trace_event/trace_event.h"
-#include "content/public/common/content_descriptors.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
namespace content {
@@ -97,23 +90,4 @@ bool GetFontTable(int fd,
return true;
}
-int MakeSharedMemorySegmentViaIPC(size_t length, bool executable) {
- base::Pickle request;
- request.WriteInt(
- service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT);
- request.WriteUInt32(length);
- request.WriteBool(executable);
- uint8_t reply_buf[10];
- int result_fd;
- ssize_t result = base::UnixDomainSocket::SendRecvMsg(
- GetSandboxFD(), reply_buf, sizeof(reply_buf), &result_fd, request);
- if (result == -1)
- return -1;
- return result_fd;
-}
-
-int GetSandboxFD() {
- return kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor;
-}
-
-} // namespace content
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/common/content_message_generator.h b/chromium/content/common/content_message_generator.h
index ab5609447eb..84e0f51ad8d 100644
--- a/chromium/content/common/content_message_generator.h
+++ b/chromium/content/common/content_message_generator.h
@@ -52,11 +52,6 @@
#ifndef CONTENT_COMMON_MEDIA_AEC_DUMP_MESSAGES_H_
#error "Failed to include content/common/media/aec_dump_messages.h"
#endif
-#undef CONTENT_COMMON_MEDIA_AUDIO_MESSAGES_H_
-#include "content/common/media/audio_messages.h"
-#ifndef CONTENT_COMMON_MEDIA_AUDIO_MESSAGES_H_
-#error "Failed to include content/common/media/audio_messages.h"
-#endif
#undef CONTENT_COMMON_MEDIA_MEDIA_PLAYER_DELEGATE_MESSAGES_H_
#include "content/common/media/media_player_delegate_messages.h"
#ifndef CONTENT_COMMON_MEDIA_MEDIA_PLAYER_DELEGATE_MESSAGES_H_
@@ -94,11 +89,6 @@
#error \
"Failed to include content/common/service_worker/service_worker_messages.h"
#endif
-#undef CONTENT_COMMON_SPEECH_RECOGNITION_MESSAGES_H_
-#include "content/common/speech_recognition_messages.h"
-#ifndef CONTENT_COMMON_SPEECH_RECOGNITION_MESSAGES_H_
-#error "Failed to include content/common/speech_recognition_messages.h"
-#endif
#undef CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
#include "content/common/text_input_client_messages.h"
#ifndef CONTENT_COMMON_TEXT_INPUT_CLIENT_MESSAGES_H_
@@ -117,13 +107,11 @@
#error "Failed to include content/common/input/sync_compositor_messages.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
#undef CONTENT_COMMON_P2P_MESSAGES_H_
#include "content/common/p2p_messages.h"
#ifndef CONTENT_COMMON_P2P_MESSAGES_H_
#error "Failed to include content/common/p2p_messages.h"
#endif
-#endif
#if defined(OS_ANDROID)
#undef CONTENT_COMMON_GIN_JAVA_BRIDGE_MESSAGES_H_
diff --git a/chromium/content/common/content_param_traits.cc b/chromium/content/common/content_param_traits.cc
index be32e05f410..310cd7f7c6f 100644
--- a/chromium/content/common/content_param_traits.cc
+++ b/chromium/content/common/content_param_traits.cc
@@ -7,6 +7,11 @@
#include <stddef.h>
#include "base/strings/string_number_conversions.h"
+#include "base/unguessable_token.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
+#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/common/surfaces/surface_info.h"
#include "content/common/frame_message_structs.h"
#include "ipc/ipc_mojo_message_helper.h"
#include "ipc/ipc_mojo_param_traits.h"
@@ -17,6 +22,7 @@
#include "ui/accessibility/ax_modes.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/blink/web_input_event_traits.h"
+// #include "ui/gfx/ipc/geometry/gfx_param_traits.h"
namespace IPC {
@@ -61,7 +67,7 @@ void ParamTraits<WebInputEventPointer>::Log(const param_type& p,
l->append(", ");
LogParam(p->GetType(), l);
l->append(", ");
- LogParam(p->TimeStampSeconds(), l);
+ LogParam(p->TimeStamp(), l);
l->append(")");
}
@@ -240,6 +246,139 @@ void ParamTraits<scoped_refptr<
l->append("<blink::TransferableMessage>");
}
+void ParamTraits<viz::FrameSinkId>::Write(base::Pickle* m,
+ const param_type& p) {
+ DCHECK(p.is_valid());
+ WriteParam(m, p.client_id());
+ WriteParam(m, p.sink_id());
+}
+
+bool ParamTraits<viz::FrameSinkId>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p) {
+ uint32_t client_id;
+ if (!ReadParam(m, iter, &client_id))
+ return false;
+
+ uint32_t sink_id;
+ if (!ReadParam(m, iter, &sink_id))
+ return false;
+
+ *p = viz::FrameSinkId(client_id, sink_id);
+ return p->is_valid();
+}
+
+void ParamTraits<viz::FrameSinkId>::Log(const param_type& p, std::string* l) {
+ l->append("viz::FrameSinkId(");
+ LogParam(p.client_id(), l);
+ l->append(", ");
+ LogParam(p.sink_id(), l);
+ l->append(")");
+}
+
+void ParamTraits<viz::LocalSurfaceId>::Write(base::Pickle* m,
+ const param_type& p) {
+ DCHECK(p.is_valid());
+ WriteParam(m, p.parent_sequence_number());
+ WriteParam(m, p.child_sequence_number());
+ WriteParam(m, p.embed_token());
+}
+
+bool ParamTraits<viz::LocalSurfaceId>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p) {
+ uint32_t parent_sequence_number;
+ if (!ReadParam(m, iter, &parent_sequence_number))
+ return false;
+
+ uint32_t child_sequence_number;
+ if (!ReadParam(m, iter, &child_sequence_number))
+ return false;
+
+ base::UnguessableToken embed_token;
+ if (!ReadParam(m, iter, &embed_token))
+ return false;
+
+ *p = viz::LocalSurfaceId(parent_sequence_number, child_sequence_number,
+ embed_token);
+ return p->is_valid();
+}
+
+void ParamTraits<viz::LocalSurfaceId>::Log(const param_type& p,
+ std::string* l) {
+ l->append("viz::LocalSurfaceId(");
+ LogParam(p.parent_sequence_number(), l);
+ l->append(", ");
+ LogParam(p.child_sequence_number(), l);
+ l->append(", ");
+ LogParam(p.embed_token(), l);
+ l->append(")");
+}
+
+void ParamTraits<viz::SurfaceId>::Write(base::Pickle* m, const param_type& p) {
+ WriteParam(m, p.frame_sink_id());
+ WriteParam(m, p.local_surface_id());
+}
+
+bool ParamTraits<viz::SurfaceId>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p) {
+ viz::FrameSinkId frame_sink_id;
+ if (!ReadParam(m, iter, &frame_sink_id))
+ return false;
+
+ viz::LocalSurfaceId local_surface_id;
+ if (!ReadParam(m, iter, &local_surface_id))
+ return false;
+
+ *p = viz::SurfaceId(frame_sink_id, local_surface_id);
+ return true;
+}
+
+void ParamTraits<viz::SurfaceId>::Log(const param_type& p, std::string* l) {
+ l->append("viz::SurfaceId(");
+ LogParam(p.frame_sink_id(), l);
+ l->append(", ");
+ LogParam(p.local_surface_id(), l);
+ l->append(")");
+}
+
+void ParamTraits<viz::SurfaceInfo>::Write(base::Pickle* m,
+ const param_type& p) {
+ WriteParam(m, p.id());
+ WriteParam(m, p.device_scale_factor());
+ WriteParam(m, p.size_in_pixels());
+}
+
+bool ParamTraits<viz::SurfaceInfo>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p) {
+ viz::SurfaceId surface_id;
+ if (!ReadParam(m, iter, &surface_id))
+ return false;
+
+ float device_scale_factor;
+ if (!ReadParam(m, iter, &device_scale_factor))
+ return false;
+
+ gfx::Size size_in_pixels;
+ if (!ReadParam(m, iter, &size_in_pixels))
+ return false;
+
+ *p = viz::SurfaceInfo(surface_id, device_scale_factor, size_in_pixels);
+ return p->is_valid();
+}
+
+void ParamTraits<viz::SurfaceInfo>::Log(const param_type& p, std::string* l) {
+ l->append("viz::SurfaceInfo(");
+ LogParam(p.id(), l);
+ l->append(", ");
+ LogParam(p.device_scale_factor(), l);
+ l->append(", ");
+ LogParam(p.size_in_pixels(), l);
+ l->append(")");
+}
+
} // namespace IPC
// Generate param traits write methods.
diff --git a/chromium/content/common/content_param_traits.h b/chromium/content/common/content_param_traits.h
index ffe7fc9edc1..e9a29ff4075 100644
--- a/chromium/content/common/content_param_traits.h
+++ b/chromium/content/common/content_param_traits.h
@@ -30,6 +30,13 @@ namespace content {
struct FrameMsg_ViewChanged_Params;
}
+namespace viz {
+class FrameSinkId;
+class LocalSurfaceId;
+class SurfaceId;
+class SurfaceInfo;
+} // namespace viz
+
namespace IPC {
template <>
@@ -109,6 +116,46 @@ struct CONTENT_EXPORT ParamTraits<content::FrameMsg_ViewChanged_Params> {
static void Log(const param_type& p, std::string* l);
};
+template <>
+struct CONTENT_EXPORT ParamTraits<viz::FrameSinkId> {
+ typedef viz::FrameSinkId param_type;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct CONTENT_EXPORT ParamTraits<viz::LocalSurfaceId> {
+ typedef viz::LocalSurfaceId param_type;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct CONTENT_EXPORT ParamTraits<viz::SurfaceId> {
+ typedef viz::SurfaceId param_type;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct CONTENT_EXPORT ParamTraits<viz::SurfaceInfo> {
+ typedef viz::SurfaceInfo param_type;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
} // namespace IPC
#endif // CONTENT_COMMON_CONTENT_PARAM_TRAITS_H_
diff --git a/chromium/content/common/content_param_traits_macros.h b/chromium/content/common/content_param_traits_macros.h
index 9dd58cf6618..65199c2f005 100644
--- a/chromium/content/common/content_param_traits_macros.h
+++ b/chromium/content/common/content_param_traits_macros.h
@@ -8,8 +8,8 @@
#ifndef CONTENT_COMMON_CONTENT_PARAM_TRAITS_MACROS_H_
#define CONTENT_COMMON_CONTENT_PARAM_TRAITS_MACROS_H_
-#include "cc/ipc/cc_param_traits.h"
#include "content/common/content_export.h"
+#include "content/common/content_param_traits.h"
#include "content/common/download/mhtml_save_status.h"
#include "content/common/render_widget_surface_properties.h"
#include "content/public/common/input_event_ack_state.h"
@@ -22,6 +22,7 @@
#include "third_party/blink/public/web/web_ime_text_span.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/ipc/geometry/gfx_param_traits.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -48,6 +49,11 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebImeTextSpan::Type,
IPC_ENUM_TRAITS_MAX_VALUE(ui::mojom::ImeTextSpanThickness,
ui::mojom::ImeTextSpanThickness::kThick)
+IPC_STRUCT_TRAITS_BEGIN(viz::Selection<gfx::SelectionBound>)
+ IPC_STRUCT_TRAITS_MEMBER(start)
+ IPC_STRUCT_TRAITS_MEMBER(end)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(blink::WebImeTextSpan)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(start_offset)
diff --git a/chromium/content/common/content_paths.cc b/chromium/content/common/content_paths.cc
index 60ba02e3a6d..ac594ed5f3c 100644
--- a/chromium/content/common/content_paths.cc
+++ b/chromium/content/common/content_paths.cc
@@ -17,10 +17,10 @@ namespace content {
bool PathProvider(int key, base::FilePath* result) {
switch (key) {
case CHILD_PROCESS_EXE:
- return PathService::Get(base::FILE_EXE, result);
+ return base::PathService::Get(base::FILE_EXE, result);
case DIR_TEST_DATA: {
base::FilePath cur;
- if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
+ if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("content"));
cur = cur.Append(FILE_PATH_LITERAL("test"));
@@ -37,7 +37,7 @@ bool PathProvider(int key, base::FilePath* result) {
*result = result->Append("Libraries");
return true;
#else
- return PathService::Get(base::DIR_MODULE, result);
+ return base::PathService::Get(base::DIR_MODULE, result);
#endif
}
default:
@@ -48,7 +48,7 @@ bool PathProvider(int key, base::FilePath* result) {
// This cannot be done as a static initializer sadly since Visual Studio will
// eliminate this object file if there is no direct entry point into it.
void RegisterPathProvider() {
- PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
+ base::PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
}
} // namespace content
diff --git a/chromium/content/common/content_security_policy/content_security_policy.cc b/chromium/content/common/content_security_policy/content_security_policy.cc
index c0b29bb9466..0a5565c573c 100644
--- a/chromium/content/common/content_security_policy/content_security_policy.cc
+++ b/chromium/content/common/content_security_policy/content_security_policy.cc
@@ -16,6 +16,7 @@ static CSPDirective::Name CSPFallback(CSPDirective::Name directive) {
case CSPDirective::DefaultSrc:
case CSPDirective::FormAction:
case CSPDirective::UpgradeInsecureRequests:
+ case CSPDirective::NavigateTo:
return CSPDirective::Unknown;
case CSPDirective::FrameSrc:
@@ -32,6 +33,19 @@ static CSPDirective::Name CSPFallback(CSPDirective::Name directive) {
return CSPDirective::Unknown;
}
+// Looks by name for a directive in a list of directives.
+// If it is not found, returns nullptr.
+static const CSPDirective* FindDirective(
+ const CSPDirective::Name name,
+ const std::vector<CSPDirective>& directives) {
+ for (const CSPDirective& directive : directives) {
+ if (directive.name == name) {
+ return &directive;
+ }
+ }
+ return nullptr;
+}
+
std::string ElideURLForReportViolation(const GURL& url) {
// TODO(arthursonzogni): the url length should be limited to 1024 char. Find
// a function that will not break the utf8 encoding while eliding the string.
@@ -69,6 +83,8 @@ void ReportViolation(CSPContext* context,
message << "Refused to send form data to '";
else if (directive_name == CSPDirective::FrameSrc)
message << "Refused to frame '";
+ else if (directive_name == CSPDirective::NavigateTo)
+ message << "Refused to navigate to '";
message << ElideURLForReportViolation(safe_url)
<< "' because it violates the following Content Security Policy "
@@ -97,9 +113,12 @@ bool AllowDirective(CSPContext* context,
CSPDirective::Name directive_name,
const GURL& url,
bool is_redirect,
+ bool is_response_check,
const SourceLocation& source_location) {
- if (CSPSourceList::Allow(directive.source_list, url, context, is_redirect))
+ if (CSPSourceList::Allow(directive.source_list, url, context, is_redirect,
+ is_response_check)) {
return true;
+ }
ReportViolation(context, policy, directive, directive_name, url, is_redirect,
source_location);
@@ -146,20 +165,30 @@ bool ContentSecurityPolicy::Allow(const ContentSecurityPolicy& policy,
CSPDirective::Name directive_name,
const GURL& url,
bool is_redirect,
+ bool is_response_check,
CSPContext* context,
- const SourceLocation& source_location) {
- if (ShouldBypassContentSecurityPolicy(context, url)) return true;
+ const SourceLocation& source_location,
+ bool is_form_submission) {
+ if (ShouldBypassContentSecurityPolicy(context, url))
+ return true;
+
+ // 'navigate-to' has no effect when doing a form submission and a
+ // 'form-action' directive is present.
+ if (is_form_submission && directive_name == CSPDirective::Name::NavigateTo &&
+ FindDirective(CSPDirective::Name::FormAction, policy.directives)) {
+ return true;
+ }
CSPDirective::Name current_directive_name = directive_name;
do {
- for (const CSPDirective& directive : policy.directives) {
- if (directive.name == current_directive_name) {
- bool allowed =
- AllowDirective(context, policy, directive, directive_name, url,
- is_redirect, source_location);
- return allowed ||
- policy.header.type == blink::kWebContentSecurityPolicyTypeReport;
- }
+ const CSPDirective* current_directive =
+ FindDirective(current_directive_name, policy.directives);
+ if (current_directive) {
+ bool allowed =
+ AllowDirective(context, policy, *current_directive, directive_name,
+ url, is_redirect, is_response_check, source_location);
+ return allowed ||
+ policy.header.type == blink::kWebContentSecurityPolicyTypeReport;
}
current_directive_name = CSPFallback(current_directive_name);
} while (current_directive_name != CSPDirective::Unknown);
diff --git a/chromium/content/common/content_security_policy/content_security_policy.h b/chromium/content/common/content_security_policy/content_security_policy.h
index 7366f00e2ce..abac1dead71 100644
--- a/chromium/content/common/content_security_policy/content_security_policy.h
+++ b/chromium/content/common/content_security_policy/content_security_policy.h
@@ -45,8 +45,10 @@ struct CONTENT_EXPORT ContentSecurityPolicy {
CSPDirective::Name directive,
const GURL& url,
bool is_redirect,
+ bool is_response_check,
CSPContext* context,
- const SourceLocation& source_location);
+ const SourceLocation& source_location,
+ bool is_form_submission);
// Returns true if |policy| specifies that an insecure HTTP request should be
// upgraded to HTTPS.
diff --git a/chromium/content/common/content_security_policy/content_security_policy_unittest.cc b/chromium/content/common/content_security_policy/content_security_policy_unittest.cc
index a8596b39fac..a7e57115ffc 100644
--- a/chromium/content/common/content_security_policy/content_security_policy_unittest.cc
+++ b/chromium/content/common/content_security_policy/content_security_policy_unittest.cc
@@ -50,9 +50,9 @@ TEST(ContentSecurityPolicy, NoDirective) {
ContentSecurityPolicy policy(EmptyCspHeader(), std::vector<CSPDirective>(),
report_end_points, false);
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FormAction,
- GURL("http://www.example.com"),
- false, &context, SourceLocation()));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FormAction, GURL("http://www.example.com"), false,
+ false, &context, SourceLocation(), true));
ASSERT_EQ(0u, context.violations().size());
}
@@ -62,15 +62,15 @@ TEST(ContentSecurityPolicy, ReportViolation) {
// source = "www.example.com"
CSPSource source("", "www.example.com", false, url::PORT_UNSPECIFIED, false,
"");
- CSPSourceList source_list(false, false, {source});
+ CSPSourceList source_list(false, false, false, {source});
CSPDirective directive(CSPDirective::FormAction, source_list);
std::vector<std::string> report_end_points; // empty
ContentSecurityPolicy policy(EmptyCspHeader(), {directive}, report_end_points,
false);
- EXPECT_FALSE(ContentSecurityPolicy::Allow(policy, CSPDirective::FormAction,
- GURL("http://www.not-example.com"),
- false, &context, SourceLocation()));
+ EXPECT_FALSE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FormAction, GURL("http://www.not-example.com"),
+ false, false, &context, SourceLocation(), true));
ASSERT_EQ(1u, context.violations().size());
const char console_message[] =
@@ -83,8 +83,8 @@ TEST(ContentSecurityPolicy, ReportViolation) {
TEST(ContentSecurityPolicy, DirectiveFallback) {
CSPSource source_a("http", "a.com", false, url::PORT_UNSPECIFIED, false, "");
CSPSource source_b("http", "b.com", false, url::PORT_UNSPECIFIED, false, "");
- CSPSourceList source_list_a(false, false, {source_a});
- CSPSourceList source_list_b(false, false, {source_b});
+ CSPSourceList source_list_a(false, false, false, {source_a});
+ CSPSourceList source_list_b(false, false, false, {source_b});
std::vector<std::string> report_end_points; // Empty.
@@ -94,9 +94,9 @@ TEST(ContentSecurityPolicy, DirectiveFallback) {
EmptyCspHeader(),
{CSPDirective(CSPDirective::DefaultSrc, source_list_a)},
report_end_points, false);
- EXPECT_FALSE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("http://b.com"), false,
- &context, SourceLocation()));
+ EXPECT_FALSE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("http://b.com"), false, false,
+ &context, SourceLocation(), false));
ASSERT_EQ(1u, context.violations().size());
const char console_message[] =
"Refused to frame 'http://b.com/' because it violates "
@@ -104,18 +104,18 @@ TEST(ContentSecurityPolicy, DirectiveFallback) {
"http://a.com\". Note that 'frame-src' was not explicitly "
"set, so 'default-src' is used as a fallback.\n";
EXPECT_EQ(console_message, context.violations()[0].console_message);
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("http://a.com"), false,
- &context, SourceLocation()));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("http://a.com"), false, false,
+ &context, SourceLocation(), false));
}
{
CSPContextTest context;
ContentSecurityPolicy policy(
EmptyCspHeader(), {CSPDirective(CSPDirective::ChildSrc, source_list_a)},
report_end_points, false);
- EXPECT_FALSE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("http://b.com"), false,
- &context, SourceLocation()));
+ EXPECT_FALSE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("http://b.com"), false, false,
+ &context, SourceLocation(), false));
ASSERT_EQ(1u, context.violations().size());
const char console_message[] =
"Refused to frame 'http://b.com/' because it violates "
@@ -123,24 +123,24 @@ TEST(ContentSecurityPolicy, DirectiveFallback) {
"http://a.com\". Note that 'frame-src' was not explicitly "
"set, so 'child-src' is used as a fallback.\n";
EXPECT_EQ(console_message, context.violations()[0].console_message);
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("http://a.com"), false,
- &context, SourceLocation()));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("http://a.com"), false, false,
+ &context, SourceLocation(), false));
}
{
CSPContextTest context;
- CSPSourceList source_list(false, false, {source_a, source_b});
+ CSPSourceList source_list(false, false, false, {source_a, source_b});
ContentSecurityPolicy policy(
EmptyCspHeader(),
{CSPDirective(CSPDirective::FrameSrc, {source_list_a}),
CSPDirective(CSPDirective::ChildSrc, {source_list_b})},
report_end_points, false);
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("http://a.com"), false,
- &context, SourceLocation()));
- EXPECT_FALSE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("http://b.com"), false,
- &context, SourceLocation()));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("http://a.com"), false, false,
+ &context, SourceLocation(), false));
+ EXPECT_FALSE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("http://b.com"), false, false,
+ &context, SourceLocation(), false));
ASSERT_EQ(1u, context.violations().size());
const char console_message[] =
"Refused to frame 'http://b.com/' because it violates "
@@ -155,27 +155,27 @@ TEST(ContentSecurityPolicy, RequestsAllowedWhenBypassingCSP) {
std::vector<std::string> report_end_points; // empty
CSPSource source("https", "example.com", false, url::PORT_UNSPECIFIED, false,
"");
- CSPSourceList source_list(false, false, {source});
+ CSPSourceList source_list(false, false, false, {source});
ContentSecurityPolicy policy(
EmptyCspHeader(), {CSPDirective(CSPDirective::DefaultSrc, source_list)},
report_end_points, false);
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("https://example.com/"), false,
- &context, SourceLocation()));
- EXPECT_FALSE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("https://not-example.com/"),
- false, &context, SourceLocation()));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("https://example.com/"), false,
+ false, &context, SourceLocation(), false));
+ EXPECT_FALSE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("https://not-example.com/"), false,
+ false, &context, SourceLocation(), false));
// Register 'https' as bypassing CSP, which should now bypass is entirely.
context.AddSchemeToBypassCSP("https");
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("https://example.com/"), false,
- &context, SourceLocation()));
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("https://not-example.com/"),
- false, &context, SourceLocation()));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("https://example.com/"), false,
+ false, &context, SourceLocation(), false));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("https://not-example.com/"), false,
+ false, &context, SourceLocation(), false));
}
TEST(ContentSecurityPolicy, FilesystemAllowedWhenBypassingCSP) {
@@ -183,31 +183,31 @@ TEST(ContentSecurityPolicy, FilesystemAllowedWhenBypassingCSP) {
std::vector<std::string> report_end_points; // empty
CSPSource source("https", "example.com", false, url::PORT_UNSPECIFIED, false,
"");
- CSPSourceList source_list(false, false, {source});
+ CSPSourceList source_list(false, false, false, {source});
ContentSecurityPolicy policy(
EmptyCspHeader(), {CSPDirective(CSPDirective::DefaultSrc, source_list)},
report_end_points, false);
EXPECT_FALSE(ContentSecurityPolicy::Allow(
policy, CSPDirective::FrameSrc,
- GURL("filesystem:https://example.com/file.txt"), false, &context,
- SourceLocation()));
+ GURL("filesystem:https://example.com/file.txt"), false, false, &context,
+ SourceLocation(), false));
EXPECT_FALSE(ContentSecurityPolicy::Allow(
policy, CSPDirective::FrameSrc,
- GURL("filesystem:https://not-example.com/file.txt"), false, &context,
- SourceLocation()));
+ GURL("filesystem:https://not-example.com/file.txt"), false, false,
+ &context, SourceLocation(), false));
// Register 'https' as bypassing CSP, which should now bypass is entirely.
context.AddSchemeToBypassCSP("https");
EXPECT_TRUE(ContentSecurityPolicy::Allow(
policy, CSPDirective::FrameSrc,
- GURL("filesystem:https://example.com/file.txt"), false, &context,
- SourceLocation()));
+ GURL("filesystem:https://example.com/file.txt"), false, false, &context,
+ SourceLocation(), false));
EXPECT_TRUE(ContentSecurityPolicy::Allow(
policy, CSPDirective::FrameSrc,
- GURL("filesystem:https://not-example.com/file.txt"), false, &context,
- SourceLocation()));
+ GURL("filesystem:https://not-example.com/file.txt"), false, false,
+ &context, SourceLocation(), false));
}
TEST(ContentSecurityPolicy, BlobAllowedWhenBypassingCSP) {
@@ -215,34 +215,34 @@ TEST(ContentSecurityPolicy, BlobAllowedWhenBypassingCSP) {
std::vector<std::string> report_end_points; // empty
CSPSource source("https", "example.com", false, url::PORT_UNSPECIFIED, false,
"");
- CSPSourceList source_list(false, false, {source});
+ CSPSourceList source_list(false, false, false, {source});
ContentSecurityPolicy policy(
EmptyCspHeader(), {CSPDirective(CSPDirective::DefaultSrc, source_list)},
report_end_points, false);
- EXPECT_FALSE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("blob:https://example.com/"),
- false, &context, SourceLocation()));
+ EXPECT_FALSE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("blob:https://example.com/"), false,
+ false, &context, SourceLocation(), false));
EXPECT_FALSE(ContentSecurityPolicy::Allow(
policy, CSPDirective::FrameSrc, GURL("blob:https://not-example.com/"),
- false, &context, SourceLocation()));
+ false, false, &context, SourceLocation(), false));
// Register 'https' as bypassing CSP, which should now bypass is entirely.
context.AddSchemeToBypassCSP("https");
- EXPECT_TRUE(ContentSecurityPolicy::Allow(policy, CSPDirective::FrameSrc,
- GURL("blob:https://example.com/"),
- false, &context, SourceLocation()));
+ EXPECT_TRUE(ContentSecurityPolicy::Allow(
+ policy, CSPDirective::FrameSrc, GURL("blob:https://example.com/"), false,
+ false, &context, SourceLocation(), false));
EXPECT_TRUE(ContentSecurityPolicy::Allow(
policy, CSPDirective::FrameSrc, GURL("blob:https://not-example.com/"),
- false, &context, SourceLocation()));
+ false, false, &context, SourceLocation(), false));
}
TEST(ContentSecurityPolicy, ShouldUpgradeInsecureRequest) {
std::vector<std::string> report_end_points; // empty
CSPSource source("https", "example.com", false, url::PORT_UNSPECIFIED, false,
"");
- CSPSourceList source_list(false, false, {source});
+ CSPSourceList source_list(false, false, false, {source});
ContentSecurityPolicy policy(
EmptyCspHeader(), {CSPDirective(CSPDirective::DefaultSrc, source_list)},
report_end_points, false);
@@ -254,4 +254,91 @@ TEST(ContentSecurityPolicy, ShouldUpgradeInsecureRequest) {
EXPECT_TRUE(ContentSecurityPolicy::ShouldUpgradeInsecureRequest(policy));
}
+TEST(ContentSecurityPolicy, NavigateToChecks) {
+ CSPContextTest context;
+ std::vector<std::string> report_end_points; // empty
+ CSPSource example("https", "example.test", false, url::PORT_UNSPECIFIED,
+ false, "");
+ CSPSourceList none_source_list(false, false, false, {});
+ CSPSourceList example_source_list(false, false, false, {example});
+ CSPSourceList self_source_list(true, false, false, {});
+ CSPSourceList redirects_source_list(false, false, true, {});
+ CSPSourceList redirects_example_source_list(false, false, true, {example});
+ context.SetSelf(example);
+
+ struct TestCase {
+ const CSPSourceList& navigate_to_list;
+ const GURL& url;
+ bool is_redirect;
+ bool is_response_check;
+ bool expected;
+ bool is_form_submission;
+ const CSPSourceList* form_action_list;
+ } cases[] = {
+ // Basic source matching.
+ {none_source_list, GURL("https://example.test"), false, false, false,
+ false, nullptr},
+ {example_source_list, GURL("https://example.test"), false, false, true,
+ false, nullptr},
+ {example_source_list, GURL("https://not-example.test"), false, false,
+ false, false, nullptr},
+ {self_source_list, GURL("https://example.test"), false, false, true,
+ false, nullptr},
+
+ // Checking allow_redirect flag interactions.
+ {redirects_source_list, GURL("https://example.test"), false, false, true,
+ false, nullptr},
+ {redirects_source_list, GURL("https://example.test"), true, false, true,
+ false, nullptr},
+ {redirects_source_list, GURL("https://example.test"), true, true, true,
+ false, nullptr},
+ {redirects_source_list, GURL("https://example.test"), false, true, false,
+ false, nullptr},
+ {redirects_example_source_list, GURL("https://example.test"), false, true,
+ true, false, nullptr},
+
+ // Interaction with form-action
+
+ // Form submission without form-action present
+ {none_source_list, GURL("https://example.test"), false, false, false,
+ true, nullptr},
+ {example_source_list, GURL("https://example.test"), false, false, true,
+ true, nullptr},
+ {example_source_list, GURL("https://not-example.test"), false, false,
+ false, true, nullptr},
+ {self_source_list, GURL("https://example.test"), false, false, true, true,
+ nullptr},
+
+ // Form submission with form-action present
+ {none_source_list, GURL("https://example.test"), false, false, true, true,
+ &example_source_list},
+ {example_source_list, GURL("https://example.test"), false, false, true,
+ true, &example_source_list},
+ {example_source_list, GURL("https://not-example.test"), false, false,
+ true, true, &example_source_list},
+ {self_source_list, GURL("https://example.test"), false, false, true, true,
+ &example_source_list},
+
+ };
+
+ for (const auto& test : cases) {
+ std::vector<CSPDirective> directives;
+ directives.push_back(
+ CSPDirective(CSPDirective::NavigateTo, test.navigate_to_list));
+
+ if (test.form_action_list)
+ directives.push_back(
+ CSPDirective(CSPDirective::FormAction, *(test.form_action_list)));
+
+ ContentSecurityPolicy policy(EmptyCspHeader(), directives,
+ report_end_points, false);
+
+ EXPECT_EQ(test.expected,
+ ContentSecurityPolicy::Allow(
+ policy, CSPDirective::NavigateTo, test.url, test.is_redirect,
+ test.is_response_check, &context, SourceLocation(),
+ test.is_form_submission));
+ }
+}
+
} // namespace content
diff --git a/chromium/content/common/content_security_policy/csp_context.cc b/chromium/content/common/content_security_policy/csp_context.cc
index 99b8ef4d48a..7791627ad19 100644
--- a/chromium/content/common/content_security_policy/csp_context.cc
+++ b/chromium/content/common/content_security_policy/csp_context.cc
@@ -32,41 +32,48 @@ CSPContext::~CSPContext() {}
bool CSPContext::IsAllowedByCsp(CSPDirective::Name directive_name,
const GURL& url,
bool is_redirect,
+ bool is_response_check,
const SourceLocation& source_location,
- CheckCSPDisposition check_csp_disposition) {
+ CheckCSPDisposition check_csp_disposition,
+ bool is_form_submission) {
if (SchemeShouldBypassCSP(url.scheme_piece()))
return true;
bool allow = true;
for (const auto& policy : policies_) {
if (ShouldCheckPolicy(policy, check_csp_disposition)) {
- allow &= ContentSecurityPolicy::Allow(policy, directive_name, url,
- is_redirect, this, source_location);
+ allow &= ContentSecurityPolicy::Allow(
+ policy, directive_name, url, is_redirect, is_response_check, this,
+ source_location, is_form_submission);
}
}
+
+ DCHECK(allow || check_csp_disposition != CSPContext::CHECK_REPORT_ONLY_CSP);
+
return allow;
}
bool CSPContext::ShouldModifyRequestUrlForCsp(
- const GURL& url,
- bool is_subresource_or_form_submission,
- GURL* new_url) {
+ bool is_subresource_or_form_submission) {
for (const auto& policy : policies_) {
- if (url.scheme() == "http" &&
- ContentSecurityPolicy::ShouldUpgradeInsecureRequest(policy) &&
+ if (ContentSecurityPolicy::ShouldUpgradeInsecureRequest(policy) &&
is_subresource_or_form_submission) {
- *new_url = url;
- GURL::Replacements replacements;
- replacements.SetSchemeStr("https");
- if (url.port() == "80")
- replacements.SetPortStr("443");
- *new_url = new_url->ReplaceComponents(replacements);
return true;
}
}
return false;
}
+void CSPContext::ModifyRequestUrlForCsp(GURL* url) {
+ if (url->scheme() == "http") {
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr("https");
+ if (url->port() == "80")
+ replacements.SetPortStr("443");
+ *url = url->ReplaceComponents(replacements);
+ }
+}
+
void CSPContext::SetSelf(const url::Origin origin) {
self_source_.reset();
@@ -88,6 +95,10 @@ void CSPContext::SetSelf(const url::Origin origin) {
DCHECK_NE("", self_source_->scheme);
}
+void CSPContext::SetSelf(const CSPSource& self_source) {
+ self_source_ = self_source;
+}
+
bool CSPContext::SchemeShouldBypassCSP(const base::StringPiece& scheme) {
return false;
}
diff --git a/chromium/content/common/content_security_policy/csp_context.h b/chromium/content/common/content_security_policy/csp_context.h
index 3697e14c713..e7f1ceedbe9 100644
--- a/chromium/content/common/content_security_policy/csp_context.h
+++ b/chromium/content/common/content_security_policy/csp_context.h
@@ -49,17 +49,21 @@ class CONTENT_EXPORT CSPContext {
bool IsAllowedByCsp(CSPDirective::Name directive_name,
const GURL& url,
bool is_redirect,
+ bool is_response_check,
const SourceLocation& source_location,
- CheckCSPDisposition check_csp_disposition);
+ CheckCSPDisposition check_csp_disposition,
+ bool is_form_submission);
// Returns true if the request URL needs to be modified (e.g. upgraded to
- // HTTPS) according to the CSP. If true, |new_url| will contain the new URL
- // that should be used instead of |url|.
- bool ShouldModifyRequestUrlForCsp(const GURL& url,
- bool is_suresource_or_form_submssion,
- GURL* new_url);
+ // HTTPS) according to the CSP.
+ bool ShouldModifyRequestUrlForCsp(bool is_suresource_or_form_submssion);
+
+ // If the scheme of |url| is HTTP, this upgrades it to HTTPS, otherwise it
+ // doesn't modify it.
+ void ModifyRequestUrlForCsp(GURL* url);
void SetSelf(const url::Origin origin);
+ void SetSelf(const CSPSource& self_source);
// When a CSPSourceList contains 'self', the url is allowed when it match the
// CSPSource returned by this function.
diff --git a/chromium/content/common/content_security_policy/csp_context_unittest.cc b/chromium/content/common/content_security_policy/csp_context_unittest.cc
index d5cf5780947..49ce33e13e1 100644
--- a/chromium/content/common/content_security_policy/csp_context_unittest.cc
+++ b/chromium/content/common/content_security_policy/csp_context_unittest.cc
@@ -60,7 +60,8 @@ ContentSecurityPolicy BuildPolicy(CSPDirective::Name directive_name,
ContentSecurityPolicyHeader(std::string(), // header
blink::kWebContentSecurityPolicyTypeEnforce,
blink::kWebContentSecurityPolicySourceHTTP),
- {CSPDirective(directive_name, CSPSourceList(false, false, sources))},
+ {CSPDirective(directive_name,
+ CSPSourceList(false, false, false, sources))},
std::vector<std::string>(), false); // report_end_points
}
@@ -74,13 +75,13 @@ TEST(CSPContextTest, SchemeShouldBypassCSP) {
EXPECT_FALSE(context.IsAllowedByCsp(
CSPDirective::FrameSrc, GURL("data:text/html,<html></html>"), false,
- SourceLocation(), CSPContext::CHECK_ALL_CSP));
+ false, SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
context.AddSchemeToBypassCSP("data");
EXPECT_TRUE(context.IsAllowedByCsp(
CSPDirective::FrameSrc, GURL("data:text/html,<html></html>"), false,
- SourceLocation(), CSPContext::CHECK_ALL_CSP));
+ false, SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
}
TEST(CSPContextTest, MultiplePolicies) {
@@ -97,17 +98,17 @@ TEST(CSPContextTest, MultiplePolicies) {
BuildPolicy(CSPDirective::FrameSrc, {source_a, source_c}));
EXPECT_TRUE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("http://a.com"), false, SourceLocation(),
- CSPContext::CHECK_ALL_CSP));
+ CSPDirective::FrameSrc, GURL("http://a.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
EXPECT_FALSE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("http://b.com"), false, SourceLocation(),
- CSPContext::CHECK_ALL_CSP));
+ CSPDirective::FrameSrc, GURL("http://b.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
EXPECT_FALSE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation(),
- CSPContext::CHECK_ALL_CSP));
+ CSPDirective::FrameSrc, GURL("http://c.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
EXPECT_FALSE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("http://d.com"), false, SourceLocation(),
- CSPContext::CHECK_ALL_CSP));
+ CSPDirective::FrameSrc, GURL("http://d.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
}
TEST(CSPContextTest, SanitizeDataForUseInCspViolation) {
@@ -126,8 +127,8 @@ TEST(CSPContextTest, SanitizeDataForUseInCspViolation) {
// When the |blocked_url| and |source_location| aren't sensitive information.
{
EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url,
- false, source_location,
- CSPContext::CHECK_ALL_CSP));
+ false, false, source_location,
+ CSPContext::CHECK_ALL_CSP, false));
ASSERT_EQ(1u, context.violations().size());
EXPECT_EQ(context.violations()[0].blocked_url, blocked_url);
EXPECT_EQ(context.violations()[0].source_location.url,
@@ -145,8 +146,8 @@ TEST(CSPContextTest, SanitizeDataForUseInCspViolation) {
// When the |blocked_url| and |source_location| are sensitive information.
{
EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url,
- false, source_location,
- CSPContext::CHECK_ALL_CSP));
+ false, false, source_location,
+ CSPContext::CHECK_ALL_CSP, false));
ASSERT_EQ(2u, context.violations().size());
EXPECT_EQ(context.violations()[1].blocked_url, blocked_url.GetOrigin());
EXPECT_EQ(context.violations()[1].source_location.url, "http://a.com/");
@@ -176,8 +177,8 @@ TEST(CSPContextTest, MultipleInfringement) {
BuildPolicy(CSPDirective::FrameSrc, {source_c}));
EXPECT_FALSE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation(),
- CSPContext::CHECK_ALL_CSP));
+ CSPDirective::FrameSrc, GURL("http://c.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
ASSERT_EQ(2u, context.violations().size());
const char console_message_a[] =
"Refused to frame 'http://c.com/' because it violates the following "
@@ -207,8 +208,8 @@ TEST(CSPContextTest, CheckCSPDisposition) {
// With CHECK_ALL_CSP, both policies should be checked and violations should
// be reported.
EXPECT_FALSE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("https://not-example.com"), false,
- SourceLocation(), CSPContext::CHECK_ALL_CSP));
+ CSPDirective::FrameSrc, GURL("https://not-example.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_ALL_CSP, false));
ASSERT_EQ(2u, context.violations().size());
const char console_message_a[] =
"Refused to frame 'https://not-example.com/' because it violates the "
@@ -229,8 +230,8 @@ TEST(CSPContextTest, CheckCSPDisposition) {
// With CHECK_REPORT_ONLY_CSP, the request should be allowed but reported.
context.ClearViolations();
EXPECT_TRUE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("https://not-example.com"), false,
- SourceLocation(), CSPContext::CHECK_REPORT_ONLY_CSP));
+ CSPDirective::FrameSrc, GURL("https://not-example.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_REPORT_ONLY_CSP, false));
ASSERT_EQ(1u, context.violations().size());
EXPECT_EQ(console_message_b, context.violations()[0].console_message);
@@ -238,8 +239,8 @@ TEST(CSPContextTest, CheckCSPDisposition) {
// enforced policy violation should be reported.
context.ClearViolations();
EXPECT_FALSE(context.IsAllowedByCsp(
- CSPDirective::FrameSrc, GURL("https://not-example.com"), false,
- SourceLocation(), CSPContext::CHECK_ENFORCED_CSP));
+ CSPDirective::FrameSrc, GURL("https://not-example.com"), false, false,
+ SourceLocation(), CSPContext::CHECK_ENFORCED_CSP, false));
ASSERT_EQ(1u, context.violations().size());
EXPECT_EQ(console_message_a, context.violations()[0].console_message);
}
@@ -250,27 +251,40 @@ TEST(CSPContextTest, ShouldModifyRequestUrlForCsp) {
CSPContextTest context;
context.AddContentSecurityPolicy(BuildPolicy(
CSPDirective::UpgradeInsecureRequests, std::vector<CSPSource>()));
- GURL new_url;
// An HTTP subresource or form submission should be upgraded.
- EXPECT_TRUE(context.ShouldModifyRequestUrlForCsp(GURL("http://example.com"),
- true, &new_url));
- EXPECT_EQ(GURL("https://example.com"), new_url);
- EXPECT_TRUE(context.ShouldModifyRequestUrlForCsp(
- GURL("http://example.com:80"), true, &new_url));
- EXPECT_EQ(GURL("https://example.com:443"), new_url);
+ EXPECT_TRUE(context.ShouldModifyRequestUrlForCsp(true));
+
+ // Main-frame navigation requests should not be modified.
+ EXPECT_FALSE(context.ShouldModifyRequestUrlForCsp(false));
+}
+
+// Tests that URLs passed to ModifyRequestUrlForCsp are modified according to
+// the spec for upgrades.
+TEST(CSPContextTest, ModifyRequestUrlForCsp) {
+ CSPContextTest context;
+ GURL test_url;
+
+ test_url = GURL("http://example.com");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("https://example.com"), test_url);
+
+ test_url = GURL("http://example.com:80");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("https://example.com:443"), test_url);
+
// Non-standard ports should not be modified.
- EXPECT_TRUE(context.ShouldModifyRequestUrlForCsp(
- GURL("http://example-weird-port.com:8088"), true, &new_url));
- EXPECT_EQ(GURL("https://example-weird-port.com:8088"), new_url);
+ test_url = GURL("http://example-weird-port.com:8088");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("https://example-weird-port.com:8088"), test_url);
// Non-HTTP URLs don't need to be modified.
- EXPECT_FALSE(context.ShouldModifyRequestUrlForCsp(GURL("https://example.com"),
- true, &new_url));
- EXPECT_FALSE(context.ShouldModifyRequestUrlForCsp(
- GURL("data:text/html,<html></html>"), true, &new_url));
- // Nor do main-frame navigation requests.
- EXPECT_FALSE(context.ShouldModifyRequestUrlForCsp(GURL("http://example.com"),
- false, &new_url));
+ test_url = GURL("https://example.com");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("https://example.com"), test_url);
+
+ test_url = GURL("data:text/html,<html></html>");
+ context.ModifyRequestUrlForCsp(&test_url);
+ EXPECT_EQ(GURL("data:text/html,<html></html>"), test_url);
}
} // namespace content
diff --git a/chromium/content/common/content_security_policy/csp_directive.cc b/chromium/content/common/content_security_policy/csp_directive.cc
index d518a4b5f91..51a6cb23672 100644
--- a/chromium/content/common/content_security_policy/csp_directive.cc
+++ b/chromium/content/common/content_security_policy/csp_directive.cc
@@ -30,6 +30,8 @@ std::string CSPDirective::NameToString(CSPDirective::Name name) {
return "form-action";
case UpgradeInsecureRequests:
return "upgrade-insecure-requests";
+ case NavigateTo:
+ return "navigate-to";
case Unknown:
return "";
}
@@ -49,6 +51,8 @@ CSPDirective::Name CSPDirective::StringToName(const std::string& name) {
return CSPDirective::FormAction;
if (name == "upgrade-insecure-requests")
return CSPDirective::UpgradeInsecureRequests;
+ if (name == "navigate-to")
+ return CSPDirective::NavigateTo;
return CSPDirective::Unknown;
}
diff --git a/chromium/content/common/content_security_policy/csp_directive.h b/chromium/content/common/content_security_policy/csp_directive.h
index 914ab181392..289e5fba4c0 100644
--- a/chromium/content/common/content_security_policy/csp_directive.h
+++ b/chromium/content/common/content_security_policy/csp_directive.h
@@ -27,6 +27,7 @@ struct CONTENT_EXPORT CSPDirective {
FrameSrc,
FormAction,
UpgradeInsecureRequests,
+ NavigateTo,
Unknown,
NameLast = Unknown,
diff --git a/chromium/content/common/content_security_policy/csp_source_list.cc b/chromium/content/common/content_security_policy/csp_source_list.cc
index 905aaae5fdd..4bf358daa1d 100644
--- a/chromium/content/common/content_security_policy/csp_source_list.cc
+++ b/chromium/content/common/content_security_policy/csp_source_list.cc
@@ -22,12 +22,16 @@ bool AllowFromSources(const GURL& url,
}; // namespace
CSPSourceList::CSPSourceList()
- : allow_self(false), allow_star(false), sources() {}
+ : allow_self(false), allow_star(false), allow_redirects(false), sources() {}
CSPSourceList::CSPSourceList(bool allow_self,
bool allow_star,
+ bool allow_redirects,
std::vector<CSPSource> sources)
- : allow_self(allow_self), allow_star(allow_star), sources(sources) {}
+ : allow_self(allow_self),
+ allow_star(allow_star),
+ allow_redirects(allow_redirects),
+ sources(sources) {}
CSPSourceList::CSPSourceList(const CSPSourceList&) = default;
CSPSourceList::~CSPSourceList() = default;
@@ -36,7 +40,23 @@ CSPSourceList::~CSPSourceList() = default;
bool CSPSourceList::Allow(const CSPSourceList& source_list,
const GURL& url,
CSPContext* context,
- bool is_redirect) {
+ bool is_redirect,
+ bool is_response_check) {
+ // If the source list allows all redirects, the decision can't be made until
+ // the response is received.
+ if (source_list.allow_redirects && !is_response_check)
+ return true;
+
+ // If the source list does not allow all redirects, the decision has already
+ // been made when checking the request.
+ if (!source_list.allow_redirects && is_response_check)
+ return true;
+
+ // If the source list allows all redirects, all responses that are a redirect
+ // are allowed.
+ if (source_list.allow_redirects && is_response_check && is_redirect)
+ return true;
+
// Wildcards match network schemes ('http', 'https', 'ftp', 'ws', 'wss'), and
// the scheme of the protected resource:
// https://w3c.github.io/webappsec-csp/#match-url-to-source-expression. Other
diff --git a/chromium/content/common/content_security_policy/csp_source_list.h b/chromium/content/common/content_security_policy/csp_source_list.h
index 4fafb439a0f..94af77554dd 100644
--- a/chromium/content/common/content_security_policy/csp_source_list.h
+++ b/chromium/content/common/content_security_policy/csp_source_list.h
@@ -18,6 +18,7 @@ struct CONTENT_EXPORT CSPSourceList {
CSPSourceList();
CSPSourceList(bool allow_self,
bool allow_star,
+ bool allow_redirects,
std::vector<CSPSource> source_list);
CSPSourceList(const CSPSourceList&);
~CSPSourceList();
@@ -26,6 +27,7 @@ struct CONTENT_EXPORT CSPSourceList {
// on the source list itself.
bool allow_self;
bool allow_star;
+ bool allow_redirects;
std::vector<CSPSource> sources;
std::string ToString() const;
@@ -37,7 +39,8 @@ struct CONTENT_EXPORT CSPSourceList {
static bool Allow(const CSPSourceList& source_list,
const GURL& url,
CSPContext* context,
- bool is_redirect = false);
+ bool is_redirect = false,
+ bool is_response_check = false);
};
} // namespace content
diff --git a/chromium/content/common/content_security_policy/csp_source_list_unittest.cc b/chromium/content/common/content_security_policy/csp_source_list_unittest.cc
index 2e0838d298c..826bf429062 100644
--- a/chromium/content/common/content_security_policy/csp_source_list_unittest.cc
+++ b/chromium/content/common/content_security_policy/csp_source_list_unittest.cc
@@ -15,8 +15,10 @@ namespace {
bool Allow(const CSPSourceList& source_list,
const GURL& url,
CSPContext* context,
- bool is_redirect = false) {
- return CSPSourceList::Allow(source_list, url, context, is_redirect);
+ bool is_redirect = false,
+ bool is_response_check = false) {
+ return CSPSourceList::Allow(source_list, url, context, is_redirect,
+ is_response_check);
}
} // namespace
@@ -26,7 +28,8 @@ TEST(CSPSourceList, MultipleSource) {
context.SetSelf(url::Origin::Create(GURL("http://example.com")));
CSPSourceList source_list(
false, // allow_self
- false, // allow_star:
+ false, // allow_star
+ false, // allow_redirects
{CSPSource("", "a.com", false, url::PORT_UNSPECIFIED, false, ""),
CSPSource("", "b.com", false, url::PORT_UNSPECIFIED, false, "")});
EXPECT_TRUE(Allow(source_list, GURL("http://a.com"), &context));
@@ -38,7 +41,8 @@ TEST(CSPSourceList, AllowStar) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("http://example.com")));
CSPSourceList source_list(false, // allow_self
- true, // allow_star:
+ true, // allow_star
+ false, // allow_redirects
std::vector<CSPSource>()); // source_list
EXPECT_TRUE(Allow(source_list, GURL("http://not-example.com"), &context));
EXPECT_TRUE(Allow(source_list, GURL("https://not-example.com"), &context));
@@ -59,7 +63,8 @@ TEST(CSPSourceList, AllowSelf) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("http://example.com")));
CSPSourceList source_list(true, // allow_self
- false, // allow_star:
+ false, // allow_star
+ false, // allow_redirects
std::vector<CSPSource>()); // source_list
EXPECT_TRUE(Allow(source_list, GURL("http://example.com"), &context));
EXPECT_FALSE(Allow(source_list, GURL("http://not-example.com"), &context));
@@ -72,6 +77,7 @@ TEST(CSPSourceList, AllowStarAndSelf) {
context.SetSelf(url::Origin::Create(GURL("https://a.com")));
CSPSourceList source_list(false, // allow_self
false, // allow_star
+ false, // allow_redirects
std::vector<CSPSource>());
// If the request is allowed by {*} and not by {'self'} then it should be
@@ -91,7 +97,8 @@ TEST(CSPSourceList, AllowSelfWithUnspecifiedPort) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("chrome://print")));
CSPSourceList source_list(true, // allow_self
- false, // allow_star:
+ false, // allow_star
+ false, // allow_redirects
std::vector<CSPSource>()); // source_list
EXPECT_TRUE(
@@ -104,7 +111,8 @@ TEST(CSPSourceList, AllowNone) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("http://example.com")));
CSPSourceList source_list(false, // allow_self
- false, // allow_star:
+ false, // allow_star
+ false, // allow_redirects
std::vector<CSPSource>()); // source_list
EXPECT_FALSE(Allow(source_list, GURL("http://example.com"), &context));
EXPECT_FALSE(Allow(source_list, GURL("https://example.test/"), &context));
@@ -113,7 +121,8 @@ TEST(CSPSourceList, AllowNone) {
TEST(CSPSourceTest, SelfIsUnique) {
// Policy: 'self'
CSPSourceList source_list(true, // allow_self
- false, // allow_star:
+ false, // allow_star
+ false, // allow_redirects
std::vector<CSPSource>()); // source_list
CSPContext context;
diff --git a/chromium/content/common/cursors/webcursor_aura.cc b/chromium/content/common/cursors/webcursor_aura.cc
index 9a3939ecfc7..73e110f8823 100644
--- a/chromium/content/common/cursors/webcursor_aura.cc
+++ b/chromium/content/common/cursors/webcursor_aura.cc
@@ -104,6 +104,11 @@ gfx::NativeCursor WebCursor::GetNativeCursor() {
case WebCursorInfo::kTypeCustom: {
ui::Cursor cursor(ui::CursorType::kCustom);
cursor.SetPlatformCursor(GetPlatformCursor());
+ SkBitmap bitmap;
+ gfx::Point hotspot;
+ CreateScaledBitmapAndHotspotFromCustomData(&bitmap, &hotspot);
+ cursor.set_custom_bitmap(bitmap);
+ cursor.set_custom_hotspot(hotspot);
return cursor;
}
default:
diff --git a/chromium/content/common/dom_storage/OWNERS b/chromium/content/common/dom_storage/OWNERS
index 39d46142947..74dc2f93524 100644
--- a/chromium/content/common/dom_storage/OWNERS
+++ b/chromium/content/common/dom_storage/OWNERS
@@ -1,9 +1,6 @@
dmurph@chromium.org
mek@chromium.org
-# OOO until this comment is removed.
-michaeln@chromium.org
-
per-file *_messages*.h=set noparent
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/content/common/external_ipc_dumper.cc b/chromium/content/common/external_ipc_dumper.cc
index 907ebfd9c52..f9ab7e69bd7 100644
--- a/chromium/content/common/external_ipc_dumper.cc
+++ b/chromium/content/common/external_ipc_dumper.cc
@@ -27,10 +27,11 @@ const char kSetDumpDirectoryEntryName[] = "SetDumpDirectory";
namespace content {
+NO_SANITIZE("cfi-icall")
IPC::ChannelProxy::OutgoingMessageFilter* LoadExternalIPCDumper(
const base::FilePath& dump_directory) {
base::FilePath module_path;
- if (!PathService::Get(base::DIR_MODULE, &module_path)) {
+ if (!base::PathService::Get(base::DIR_MODULE, &module_path)) {
LOG(ERROR) << "Unable to get message dump module directory.";
return NULL;
}
diff --git a/chromium/content/common/file_utilities.mojom b/chromium/content/common/file_utilities.mojom
deleted file mode 100644
index 7ab8354141b..00000000000
--- a/chromium/content/common/file_utilities.mojom
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2017 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.
-
-module content.mojom;
-
-import "mojo/public/mojom/base/file_info.mojom";
-import "mojo/public/mojom/base/file_path.mojom";
-
-// File utilities messages sent from the renderer to the browser.
-interface FileUtilitiesHost {
- [Sync]
- GetFileInfo(mojo_base.mojom.FilePath path) => (
- mojo_base.mojom.FileInfo? result);
-};
diff --git a/chromium/content/common/fileapi/OWNERS b/chromium/content/common/fileapi/OWNERS
index 77d0e9de90c..3a69eb7de67 100644
--- a/chromium/content/common/fileapi/OWNERS
+++ b/chromium/content/common/fileapi/OWNERS
@@ -1,4 +1,4 @@
-michaeln@chromium.org
+mek@chromium.org
jianli@chromium.org
tzik@chromium.org
nhiroki@chromium.org
diff --git a/chromium/content/common/frame.mojom b/chromium/content/common/frame.mojom
index 99ec7e8d799..09b5766c079 100644
--- a/chromium/content/common/frame.mojom
+++ b/chromium/content/common/frame.mojom
@@ -38,7 +38,8 @@ interface Frame {
// Extracts the data at the given rect.
[EnableIf=is_android]
ExtractSmartClipData(gfx.mojom.Rect rect)
- => (mojo_base.mojom.String16 text, mojo_base.mojom.String16 html);
+ => (mojo_base.mojom.String16 text, mojo_base.mojom.String16 html,
+ gfx.mojom.Rect clip_rect);
};
// See src/content/common/navigation_params.h
@@ -54,20 +55,18 @@ struct RequestNavigationParams;
interface FrameNavigationControl {
// Tells the renderer that a navigation is ready to commit.
//
- // The renderer should request |body_url| to get access to the stream
- // containing the body of the response. When the Network Service or
- // NavigationMojoResponse is enabled, |body_url| is not used and instead
- // |url_loader_client_endpoints| provides a way to continue the navigation.
+ // The renderer should bind the |url_loader_client_endpoints| to an
+ // URLLoaderClient implementation to continue loading the document that will
+ // be the result of the committed navigation.
//
- // Note: |body_url| and |url_loader_client_endpoints| will be empty iff the
- // navigation URL wasn't handled by the network stack (i.e. JavaScript URLs,
- // renderer debug URLs, same document navigations, about:blank, ...)
+ // Note: |url_loader_client_endpoints| will be empty iff the navigation URL
+ // wasn't handled by the network stack (i.e. JavaScript URLs, renderer debug
+ // URLs, same document navigations, about:blank, ...)
//
// When the Network Service is enabled, |subresource_loader_factories| may
// also be provided by the browser as a a means for the renderer to load
// subresources where applicable.
//
- // When S13nServiceWorker/NavigationMojoResponse is enabled,
// |controller_service_worker_info| may also be provided by the browser if the
// frame that is being navigated is supposed to be controlled by a Service
// Worker.
@@ -84,7 +83,6 @@ interface FrameNavigationControl {
// navigation token that can be passed from renderer to the browser.
CommitNavigation(
network.mojom.URLResponseHead head,
- url.mojom.Url body_url,
CommonNavigationParams common_params,
RequestNavigationParams request_params,
network.mojom.URLLoaderClientEndpoints? url_loader_client_endpoints,
@@ -327,13 +325,4 @@ interface FrameHost {
// correctly set the initial size of the frame in case of a cross-process
// navigation.
FrameSizeChanged(gfx.mojom.Size size);
-
- // Sent by the renderer to update Picture-in-Picture with SurfaceId and video
- // size to be used to show content in the Picture-in-Picture window.
- OnUpdatePictureInPictureSurfaceId(
- viz.mojom.SurfaceId surface_id,
- gfx.mojom.Size natural_size);
-
- // Sent by the renderer to signal that Picture-in-Picture mode has ended.
- OnExitPictureInPicture();
};
diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h
index cf96a19a4e0..98bc62f6c93 100644
--- a/chromium/content/common/frame_messages.h
+++ b/chromium/content/common/frame_messages.h
@@ -17,6 +17,8 @@
#include "base/optional.h"
#include "build/build_config.h"
+#include "cc/input/touch_action.h"
+#include "cc/trees/render_frame_metadata.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "content/common/buildflags.h"
@@ -29,7 +31,7 @@
#include "content/common/frame_message_structs.h"
#include "content/common/frame_owner_properties.h"
#include "content/common/frame_replication_state.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
#include "content/common/navigation_gesture.h"
#include "content/common/navigation_params.h"
#include "content/common/resource_timing_info.h"
@@ -62,10 +64,12 @@
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "third_party/blink/public/platform/web_intrinsic_sizing_info.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
+#include "third_party/blink/public/platform/web_scroll_types.h"
#include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
#include "third_party/blink/public/web/web_find_options.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_frame_serializer_cache_control_policy.h"
+#include "third_party/blink/public/web/web_fullscreen_options.h"
#include "third_party/blink/public/web/web_tree_scope_type.h"
#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "ui/gfx/geometry/rect.h"
@@ -134,6 +138,12 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::CSPDisposition,
content::CSPDisposition::LAST)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebTriggeringEventInfo,
blink::WebTriggeringEventInfo::kLast)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScrollDirection,
+ blink::kFirstScrollDirection,
+ blink::kLastScrollDirection)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScrollGranularity,
+ blink::kFirstScrollGranularity,
+ blink::kLastScrollGranularity)
IPC_STRUCT_TRAITS_BEGIN(blink::WebFloatSize)
IPC_STRUCT_TRAITS_MEMBER(width)
@@ -154,6 +164,10 @@ IPC_STRUCT_TRAITS_BEGIN(blink::WebFindOptions)
IPC_STRUCT_TRAITS_MEMBER(force)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(blink::WebFullscreenOptions)
+ IPC_STRUCT_TRAITS_MEMBER(prefers_navigation_bar)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(blink::WebScrollIntoViewParams::Alignment)
IPC_STRUCT_TRAITS_MEMBER(rect_visible)
IPC_STRUCT_TRAITS_MEMBER(rect_hidden)
@@ -230,14 +244,25 @@ IPC_STRUCT_TRAITS_BEGIN(content::FrameOwnerProperties)
IPC_STRUCT_TRAITS_MEMBER(required_csp)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::FrameResizeParams)
+IPC_STRUCT_TRAITS_BEGIN(content::FrameVisualProperties)
IPC_STRUCT_TRAITS_MEMBER(screen_info)
IPC_STRUCT_TRAITS_MEMBER(auto_resize_enabled)
IPC_STRUCT_TRAITS_MEMBER(min_size_for_auto_resize)
IPC_STRUCT_TRAITS_MEMBER(max_size_for_auto_resize)
- IPC_STRUCT_TRAITS_MEMBER(auto_resize_sequence_number)
IPC_STRUCT_TRAITS_MEMBER(screen_space_rect)
IPC_STRUCT_TRAITS_MEMBER(local_frame_size)
+ IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(cc::RenderFrameMetadata)
+ IPC_STRUCT_TRAITS_MEMBER(is_scroll_offset_at_top)
+ IPC_STRUCT_TRAITS_MEMBER(root_background_color)
+ IPC_STRUCT_TRAITS_MEMBER(root_scroll_offset)
+ IPC_STRUCT_TRAITS_MEMBER(selection)
+ IPC_STRUCT_TRAITS_MEMBER(is_mobile_optimized)
+ IPC_STRUCT_TRAITS_MEMBER(device_scale_factor)
+ IPC_STRUCT_TRAITS_MEMBER(viewport_size_in_pixels)
+ IPC_STRUCT_TRAITS_MEMBER(local_surface_id)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(blink::FramePolicy)
@@ -426,11 +451,6 @@ IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(FrameMsg_PostMessage_Params)
- // Whether the data format is supplied as serialized script value, or as
- // a simple string. If it is a raw string, must be converted from string to a
- // WebSerializedScriptValue in the renderer process.
- IPC_STRUCT_MEMBER(bool, is_data_raw_string)
-
// When sent to the browser, this is the routing ID of the source frame in
// the source process. The browser replaces it with the routing ID of the
// equivalent frame proxy in the destination process.
@@ -473,7 +493,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(should_check_main_world_csp)
IPC_STRUCT_TRAITS_MEMBER(has_user_gesture)
IPC_STRUCT_TRAITS_MEMBER(started_from_context_menu)
- IPC_STRUCT_TRAITS_MEMBER(suggested_filename)
+ IPC_STRUCT_TRAITS_MEMBER(initiator_csp)
+ IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::NavigationTiming)
@@ -550,7 +571,7 @@ IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params)
IPC_STRUCT_MEMBER(bool, user_gesture)
IPC_STRUCT_MEMBER(bool, is_history_navigation_in_new_child)
IPC_STRUCT_MEMBER(blink::WebTriggeringEventInfo, triggering_event_info)
- IPC_STRUCT_MEMBER(base::Optional<std::string>, suggested_filename)
+ IPC_STRUCT_MEMBER(mojo::MessagePipeHandle, blob_url_token)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(FrameHostMsg_DownloadUrl_Params)
@@ -560,6 +581,7 @@ IPC_STRUCT_BEGIN(FrameHostMsg_DownloadUrl_Params)
IPC_STRUCT_MEMBER(content::Referrer, referrer)
IPC_STRUCT_MEMBER(url::Origin, initiator_origin)
IPC_STRUCT_MEMBER(base::string16, suggested_name)
+ IPC_STRUCT_MEMBER(mojo::MessagePipeHandle, blob_url_token)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(FrameMsg_TextTrackSettings_Params)
@@ -764,9 +786,6 @@ IPC_MESSAGE_ROUTED4(FrameHostMsg_ShowCreatedWindow,
gfx::Rect /* initial_rect */,
bool /* opened_by_user_gesture */)
-// Let the browser know a StreamHandle has been consumed and can be released.
-IPC_MESSAGE_ROUTED1(FrameHostMsg_StreamHandleConsumed, GURL /* stream_url */)
-
#if BUILDFLAG(ENABLE_PLUGINS)
IPC_STRUCT_TRAITS_BEGIN(content::PepperRendererInstanceData)
IPC_STRUCT_TRAITS_MEMBER(render_process_id)
@@ -990,10 +1009,10 @@ IPC_MESSAGE_ROUTED1(FrameMsg_PostMessageEvent, FrameMsg_PostMessage_Params)
// Tells the RenderFrame to clear the focused element (if any).
IPC_MESSAGE_ROUTED0(FrameMsg_ClearFocusedElement)
-// Informs the parent renderer that the child would like a new
-// viz::LocalSurfaceId in response to an auto-resize.
-IPC_MESSAGE_ROUTED1(FrameMsg_ResizeDueToAutoResize,
- uint64_t /* sequence_number */)
+// Informs the parent renderer that the child has completed an autoresize
+// transaction and should update with the provided viz::LocalSurfaceId.
+IPC_MESSAGE_ROUTED1(FrameMsg_DidUpdateVisualProperties,
+ cc::RenderFrameMetadata /* metadata */)
// Requests a viz::LocalSurfaceId to enable auto-resize mode from the parent
// renderer.
@@ -1005,38 +1024,6 @@ IPC_MESSAGE_ROUTED2(FrameMsg_EnableAutoResize,
// renderer.
IPC_MESSAGE_ROUTED0(FrameMsg_DisableAutoResize)
-#if defined(OS_ANDROID)
-// Request the distance to the nearest find result in a frame from the point at
-// (x, y), defined in fractions of the content document's width and height. The
-// distance will be returned via FrameHostMsg_GetNearestFindResult_Reply. Note
-// that |nfr_request_id| is a completely seperate ID from the |request_id| used
-// in other find-related IPCs. It is specifically used to uniquely identify a
-// nearest find result request, rather than a find request.
-IPC_MESSAGE_ROUTED3(FrameMsg_GetNearestFindResult,
- int /* nfr_request_id */,
- float /* x */,
- float /* y */)
-
-// Activates a find result. The point (x,y) is in fractions of the content
-// document's width and height.
-IPC_MESSAGE_ROUTED3(FrameMsg_ActivateNearestFindResult,
- int /* request_id */,
- float /* x */,
- float /* y */)
-
-// Sent when the browser wants the bounding boxes of the current find matches.
-//
-// If match rects are already cached on the browser side, |current_version|
-// should be the version number from the FrameHostMsg_FindMatchRects_Reply
-// they came in, so the renderer can tell if it needs to send updated rects.
-// Otherwise just pass -1 to always receive the list of rects.
-//
-// There must be an active search string (it is probably most useful to call
-// this immediately after a FrameHostMsg_Find_Reply message arrives with
-// final_update set to true).
-IPC_MESSAGE_ROUTED1(FrameMsg_FindMatchRects, int /* current_version */)
-#endif
-
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
#if defined(OS_MACOSX)
IPC_MESSAGE_ROUTED1(FrameMsg_SelectPopupMenuItem,
@@ -1094,11 +1081,6 @@ IPC_MESSAGE_ROUTED3(FrameMsg_Find,
base::string16 /* search_text */,
blink::WebFindOptions)
-// This message notifies the frame that it is no longer the active frame in the
-// current find session, and so it should clear its active find match (and no
-// longer highlight it with special coloring).
-IPC_MESSAGE_ROUTED0(FrameMsg_ClearActiveFindMatch)
-
// This message notifies the frame that the user has closed the find-in-page
// window (and what action to take regarding the selection).
IPC_MESSAGE_ROUTED1(FrameMsg_StopFinding, content::StopFindAction /* action */)
@@ -1171,6 +1153,12 @@ IPC_MESSAGE_ROUTED2(FrameMsg_ScrollRectToVisible,
gfx::Rect /* rect_to_scroll */,
blink::WebScrollIntoViewParams /* properties */)
+// Sent to the parent process of a cross-process frame to continue bubbling
+// a logical scroll.
+IPC_MESSAGE_ROUTED2(FrameMsg_BubbleLogicalScroll,
+ blink::WebScrollDirection /* direction */,
+ blink::WebScrollGranularity /* granularity */)
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
@@ -1497,10 +1485,10 @@ IPC_MESSAGE_ROUTED3(FrameHostMsg_BeforeUnload_ACK,
// Indicates that the current frame has swapped out, after a SwapOut message.
IPC_MESSAGE_ROUTED0(FrameHostMsg_SwapOut_ACK)
-// Tells the browser that a child's resize parameters have changed.
-IPC_MESSAGE_ROUTED2(FrameHostMsg_UpdateResizeParams,
+// Tells the browser that a child's visual properties have changed.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_SynchronizeVisualProperties,
viz::SurfaceId /* surface_id */,
- content::FrameResizeParams)
+ content::FrameVisualProperties)
// Sent by a parent frame to update its child's viewport intersection rect for
// use by the IntersectionObserver API.
@@ -1516,6 +1504,10 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_VisibilityChanged, bool /* visible */)
// Sets or unsets the inert bit on a remote frame.
IPC_MESSAGE_ROUTED1(FrameHostMsg_SetIsInert, bool /* inert */)
+// Sets the inherited effective touch action on a remote frame.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_SetInheritedEffectiveTouchAction,
+ cc::TouchAction)
+
// Toggles render throttling on a remote frame. |is_throttled| indicates
// whether the current frame should be throttled based on its viewport
// visibility, and |subtree_throttled| indicates that an ancestor frame has
@@ -1622,7 +1614,11 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_VisualStateResponse, uint64_t /* id */)
// Puts the browser into "tab fullscreen" mode for the sending renderer.
// See the comment in chrome/browser/ui/browser.h for more details.
-IPC_MESSAGE_ROUTED1(FrameHostMsg_ToggleFullscreen, bool /* enter_fullscreen */)
+IPC_MESSAGE_ROUTED1(FrameHostMsg_EnterFullscreen, blink::WebFullscreenOptions)
+
+// Exits the browser from "tab fullscreen" mode for the sending renderer.
+// See the comment in chrome/browser/ui/browser.h for more details.
+IPC_MESSAGE_ROUTED0(FrameHostMsg_ExitFullscreen)
// Sent when a new sudden termination disabler condition is either introduced or
// removed.
@@ -1735,8 +1731,7 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_UpdateFaviconURL,
// A message from HTML-based UI. When (trusted) Javascript calls
// send(message, args), this message is sent to the browser.
-IPC_MESSAGE_ROUTED3(FrameHostMsg_WebUISend,
- GURL /* source_url */,
+IPC_MESSAGE_ROUTED2(FrameHostMsg_WebUISend,
std::string /* message */,
base::ListValue /* args */)
@@ -1745,6 +1740,12 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_ScrollRectToVisibleInParentFrame,
gfx::Rect /* rect_to_scroll */,
blink::WebScrollIntoViewParams /* properties */)
+// Sent by a local root to continue bubbling a logical scroll in its parent
+// process.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_BubbleLogicalScrollInParentFrame,
+ blink::WebScrollDirection /* direction */,
+ blink::WebScrollGranularity /* granularity */)
+
// Sent to notify that a frame called |window.focus()|.
IPC_MESSAGE_ROUTED0(FrameHostMsg_FrameDidCallFocus)
@@ -1767,34 +1768,6 @@ IPC_MESSAGE_ROUTED0(FrameHostMsg_HidePopup)
#endif
-#if defined(OS_ANDROID)
-// Response to FrameMsg_FindMatchRects.
-//
-// |version| will contain the current version number of the renderer's find
-// match list (incremented whenever they change), which should be passed in the
-// next call to FrameMsg_FindMatchRects.
-//
-// |rects| will either contain a list of the enclosing rects of all matches
-// found by the most recent Find operation, or will be empty if |version| is not
-// greater than the |current_version| passed to FrameMsg_FindMatchRects (hence
-// your locally cached rects should still be valid). The rect coords will be
-// custom normalized fractions of the document size. The rects will be sorted by
-// frame traversal order starting in the main frame, then by dom order.
-//
-// |active_rect| will contain the bounding box of the active find-in-page match
-// marker, in similarly normalized coords (or an empty rect if there isn't one).
-IPC_MESSAGE_ROUTED3(FrameHostMsg_FindMatchRects_Reply,
- int /* version */,
- std::vector<gfx::RectF> /* rects */,
- gfx::RectF /* active_rect */)
-
-// Response to FrameMsg_GetNearestFindResult. |distance| is the distance to the
-// nearest find result in the sending frame.
-IPC_MESSAGE_ROUTED2(FrameHostMsg_GetNearestFindResult_Reply,
- int /* nfr_request_id */,
- float /* distance */)
-#endif
-
// Adding a new message? Stick to the sort order above: first platform
// independent FrameMsg, then ifdefs for platform specific FrameMsg, then
// platform independent FrameHostMsg, then ifdefs for platform specific
diff --git a/chromium/content/common/frame_resize_params.cc b/chromium/content/common/frame_resize_params.cc
deleted file mode 100644
index fc5059d0fc6..00000000000
--- a/chromium/content/common/frame_resize_params.cc
+++ /dev/null
@@ -1,19 +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/common/frame_resize_params.h"
-
-namespace content {
-
-FrameResizeParams::FrameResizeParams()
- : auto_resize_enabled(false), auto_resize_sequence_number(0u) {}
-
-FrameResizeParams::FrameResizeParams(const FrameResizeParams& other) = default;
-
-FrameResizeParams::~FrameResizeParams() {}
-
-FrameResizeParams& FrameResizeParams::operator=(
- const FrameResizeParams& other) = default;
-
-} // namespace content
diff --git a/chromium/content/common/frame_sink_provider.mojom b/chromium/content/common/frame_sink_provider.mojom
index ad84346d80b..003f761e458 100644
--- a/chromium/content/common/frame_sink_provider.mojom
+++ b/chromium/content/common/frame_sink_provider.mojom
@@ -1,3 +1,7 @@
+// 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.
+
module content.mojom;
import "content/common/render_frame_metadata.mojom";
@@ -11,7 +15,10 @@ interface FrameSinkProvider {
CreateForWidget(
int32 widget_id,
viz.mojom.CompositorFrameSink& compositor_frame_sink_request,
- viz.mojom.CompositorFrameSinkClient compositor_frame_sink_client,
+ viz.mojom.CompositorFrameSinkClient compositor_frame_sink_client);
+
+ RegisterRenderFrameMetadataObserver(
+ int32 widget_id,
RenderFrameMetadataObserverClient&
render_frame_metadata_observer_client_request,
RenderFrameMetadataObserver render_frame_metadata_observer);
diff --git a/chromium/content/common/frame_visual_properties.cc b/chromium/content/common/frame_visual_properties.cc
new file mode 100644
index 00000000000..1f1d4f1dbed
--- /dev/null
+++ b/chromium/content/common/frame_visual_properties.cc
@@ -0,0 +1,19 @@
+// 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/common/frame_visual_properties.h"
+
+namespace content {
+
+FrameVisualProperties::FrameVisualProperties() = default;
+
+FrameVisualProperties::FrameVisualProperties(
+ const FrameVisualProperties& other) = default;
+
+FrameVisualProperties::~FrameVisualProperties() = default;
+
+FrameVisualProperties& FrameVisualProperties::operator=(
+ const FrameVisualProperties& other) = default;
+
+} // namespace content
diff --git a/chromium/content/common/frame_resize_params.h b/chromium/content/common/frame_visual_properties.h
index 425590722c0..6dc8da06d92 100644
--- a/chromium/content/common/frame_resize_params.h
+++ b/chromium/content/common/frame_visual_properties.h
@@ -2,29 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_FRAME_RESIZE_PARAMS_H_
-#define CONTENT_COMMON_FRAME_RESIZE_PARAMS_H_
+#ifndef CONTENT_COMMON_FRAME_VISUAL_PROPERTIES_H_
+#define CONTENT_COMMON_FRAME_VISUAL_PROPERTIES_H_
#include "content/common/content_export.h"
#include "content/public/common/screen_info.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
#include "ui/gfx/geometry/size.h"
namespace content {
// TODO(fsamuel): We might want to unify this with content::ResizeParams.
-struct CONTENT_EXPORT FrameResizeParams {
- FrameResizeParams();
- FrameResizeParams(const FrameResizeParams& other);
- ~FrameResizeParams();
+struct CONTENT_EXPORT FrameVisualProperties {
+ FrameVisualProperties();
+ FrameVisualProperties(const FrameVisualProperties& other);
+ ~FrameVisualProperties();
- FrameResizeParams& operator=(const FrameResizeParams& other);
+ FrameVisualProperties& operator=(const FrameVisualProperties& other);
// Information about the screen (dpi, depth, etc..).
ScreenInfo screen_info;
// Whether or not blink should be in auto-resize mode.
- bool auto_resize_enabled;
+ bool auto_resize_enabled = false;
// The minimum size for Blink if auto-resize is enabled.
gfx::Size min_size_for_auto_resize;
@@ -32,16 +31,13 @@ struct CONTENT_EXPORT FrameResizeParams {
// The maximum size for Blink if auto-resize is enabled.
gfx::Size max_size_for_auto_resize;
- // This variable is increased after each auto-resize. If the
- // renderer receives a ResizeParams with stale auto_resize_seqence_number,
- // then the resize request is dropped.
- uint64_t auto_resize_sequence_number;
-
gfx::Rect screen_space_rect;
gfx::Size local_frame_size;
+
+ uint32_t capture_sequence_number = 0u;
};
} // namespace content
-#endif // CONTENT_COMMON_FRAME_RESIZE_PARAMS_H_
+#endif // CONTENT_COMMON_FRAME_VISUAL_PROPERTIES_H_
diff --git a/chromium/content/common/input/event_with_latency_info.h b/chromium/content/common/input/event_with_latency_info.h
index 7dc0e8113ce..0b97bdd35ad 100644
--- a/chromium/content/common/input/event_with_latency_info.h
+++ b/chromium/content/common/input/event_with_latency_info.h
@@ -30,9 +30,9 @@ class EventWithLatencyInfo {
EventWithLatencyInfo(blink::WebInputEvent::Type type,
int modifiers,
- double timeStampSeconds,
+ base::TimeTicks time_stamp,
const ui::LatencyInfo& l)
- : event(type, modifiers, timeStampSeconds), latency(l) {}
+ : event(type, modifiers, time_stamp), latency(l) {}
EventWithLatencyInfo() {}
@@ -54,9 +54,9 @@ class EventWithLatencyInfo {
// New events get coalesced into older events, and the newer timestamp
// should always be preserved.
- const double time_stamp_seconds = other.event.TimeStampSeconds();
+ const base::TimeTicks time_stamp = other.event.TimeStamp();
ui::Coalesce(other.event, &event);
- event.SetTimeStampSeconds(time_stamp_seconds);
+ event.SetTimeStamp(time_stamp);
// When coalescing two input events, we keep the oldest LatencyInfo
// for Telemetry latency tests, since it will represent the longest
diff --git a/chromium/content/common/input/event_with_latency_info_unittest.cc b/chromium/content/common/input/event_with_latency_info_unittest.cc
index 640e42e71fd..2c135593a3e 100644
--- a/chromium/content/common/input/event_with_latency_info_unittest.cc
+++ b/chromium/content/common/input/event_with_latency_info_unittest.cc
@@ -25,16 +25,20 @@ using EventWithLatencyInfoTest = testing::Test;
TouchEventWithLatencyInfo CreateTouchEvent(WebInputEvent::Type type,
double timestamp,
unsigned touch_count = 1) {
- TouchEventWithLatencyInfo touch(type, WebInputEvent::kNoModifiers, timestamp,
- ui::LatencyInfo());
+ TouchEventWithLatencyInfo touch(
+ type, WebInputEvent::kNoModifiers,
+ base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp),
+ ui::LatencyInfo());
touch.event.touches_length = touch_count;
return touch;
}
MouseEventWithLatencyInfo CreateMouseEvent(WebInputEvent::Type type,
double timestamp) {
- return MouseEventWithLatencyInfo(type, WebInputEvent::kNoModifiers, timestamp,
- ui::LatencyInfo());
+ return MouseEventWithLatencyInfo(
+ type, WebInputEvent::kNoModifiers,
+ base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp),
+ ui::LatencyInfo());
}
MouseWheelEventWithLatencyInfo CreateMouseWheelEvent(
@@ -43,7 +47,9 @@ MouseWheelEventWithLatencyInfo CreateMouseWheelEvent(
float deltaY = 0.0f,
int modifiers = WebInputEvent::kNoModifiers) {
MouseWheelEventWithLatencyInfo mouse_wheel(
- WebInputEvent::kMouseWheel, modifiers, timestamp, ui::LatencyInfo());
+ WebInputEvent::kMouseWheel, modifiers,
+ base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp),
+ ui::LatencyInfo());
mouse_wheel.event.delta_x = deltaX;
mouse_wheel.event.delta_y = deltaY;
return mouse_wheel;
@@ -53,8 +59,10 @@ GestureEventWithLatencyInfo CreateGestureEvent(WebInputEvent::Type type,
double timestamp,
float x = 0.0f,
float y = 0.0f) {
- GestureEventWithLatencyInfo gesture(type, WebInputEvent::kNoModifiers,
- timestamp, ui::LatencyInfo());
+ GestureEventWithLatencyInfo gesture(
+ type, WebInputEvent::kNoModifiers,
+ base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp),
+ ui::LatencyInfo());
gesture.event.SetPositionInWidget(gfx::PointF(x, y));
return gesture;
}
@@ -68,7 +76,7 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForMouseEvent) {
ASSERT_TRUE(mouse_0.CanCoalesceWith(mouse_1));
mouse_0.CoalesceWith(mouse_1);
// Coalescing WebMouseEvent preserves newer timestamp.
- EXPECT_EQ(10.0, mouse_0.event.TimeStampSeconds());
+ EXPECT_EQ(10.0, mouse_0.event.TimeStamp().since_origin().InSecondsF());
}
TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForMouseWheelEvent) {
@@ -78,7 +86,7 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForMouseWheelEvent) {
ASSERT_TRUE(mouse_wheel_0.CanCoalesceWith(mouse_wheel_1));
mouse_wheel_0.CoalesceWith(mouse_wheel_1);
// Coalescing WebMouseWheelEvent preserves newer timestamp.
- EXPECT_EQ(10.0, mouse_wheel_0.event.TimeStampSeconds());
+ EXPECT_EQ(10.0, mouse_wheel_0.event.TimeStamp().since_origin().InSecondsF());
}
TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForTouchEvent) {
@@ -90,7 +98,7 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForTouchEvent) {
ASSERT_TRUE(touch_0.CanCoalesceWith(touch_1));
touch_0.CoalesceWith(touch_1);
// Coalescing WebTouchEvent preserves newer timestamp.
- EXPECT_EQ(10.0, touch_0.event.TimeStampSeconds());
+ EXPECT_EQ(10.0, touch_0.event.TimeStamp().since_origin().InSecondsF());
}
TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForGestureEvent) {
@@ -102,14 +110,14 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForGestureEvent) {
ASSERT_TRUE(scroll_0.CanCoalesceWith(scroll_1));
scroll_0.CoalesceWith(scroll_1);
// Coalescing WebGestureEvent preserves newer timestamp.
- EXPECT_EQ(10.0, scroll_0.event.TimeStampSeconds());
+ EXPECT_EQ(10.0, scroll_0.event.TimeStamp().since_origin().InSecondsF());
}
TEST_F(EventWithLatencyInfoTest, LatencyInfoCoalescing) {
MouseEventWithLatencyInfo mouse_0 =
CreateMouseEvent(WebInputEvent::kMouseMove, 5.0);
mouse_0.latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, base::TimeTicks(), 1);
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, base::TimeTicks(), 1);
MouseEventWithLatencyInfo mouse_1 =
CreateMouseEvent(WebInputEvent::kMouseMove, 10.0);
@@ -360,7 +368,7 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescing) {
EXPECT_TRUE(CanCoalesce(mouse_wheel_0, mouse_wheel_1));
Coalesce(mouse_wheel_1, &mouse_wheel_0);
- EXPECT_EQ(10.0, mouse_wheel_0.event.TimeStampSeconds());
+ EXPECT_EQ(10.0, mouse_wheel_0.event.TimeStamp().since_origin().InSecondsF());
}
} // namespace
diff --git a/chromium/content/common/input/input_event_struct_traits.cc b/chromium/content/common/input/input_event_struct_traits.cc
index c1e18caff8c..afa97f2064f 100644
--- a/chromium/content/common/input/input_event_struct_traits.cc
+++ b/chromium/content/common/input/input_event_struct_traits.cc
@@ -6,6 +6,7 @@
#include "base/i18n/char_iterator.h"
#include "content/common/input_messages.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "third_party/blink/public/platform/web_keyboard_event.h"
#include "ui/latency/mojo/latency_info_struct_traits.h"
@@ -88,13 +89,17 @@ bool StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::Read(
if (!event.ReadType(&type))
return false;
+ base::TimeTicks timestamp;
+ if (!event.ReadTimestamp(&timestamp))
+ return false;
+
if (blink::WebInputEvent::IsKeyboardEventType(type)) {
content::mojom::KeyDataPtr key_data;
if (!event.ReadKeyData<content::mojom::KeyDataPtr>(&key_data))
return false;
- (*out)->web_event.reset(new blink::WebKeyboardEvent(
- type, event.modifiers(), event.timestamp_seconds()));
+ (*out)->web_event.reset(
+ new blink::WebKeyboardEvent(type, event.modifiers(), timestamp));
blink::WebKeyboardEvent* key_event =
static_cast<blink::WebKeyboardEvent*>((*out)->web_event.get());
@@ -111,8 +116,7 @@ bool StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::Read(
if (!event.ReadGestureData<content::mojom::GestureDataPtr>(&gesture_data))
return false;
(*out)->web_event.reset(new blink::WebGestureEvent(
- type, event.modifiers(), event.timestamp_seconds(),
- gesture_data->source_device));
+ type, event.modifiers(), timestamp, gesture_data->source_device));
blink::WebGestureEvent* gesture_event =
static_cast<blink::WebGestureEvent*>((*out)->web_event.get());
@@ -258,8 +262,8 @@ bool StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::Read(
if (!event.ReadTouchData<content::mojom::TouchDataPtr>(&touch_data))
return false;
- (*out)->web_event.reset(new blink::WebTouchEvent(
- type, event.modifiers(), event.timestamp_seconds()));
+ (*out)->web_event.reset(
+ new blink::WebTouchEvent(type, event.modifiers(), timestamp));
blink::WebTouchEvent* touch_event =
static_cast<blink::WebTouchEvent*>((*out)->web_event.get());
@@ -287,11 +291,11 @@ bool StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::Read(
return false;
if (blink::WebInputEvent::IsMouseEventType(type)) {
- (*out)->web_event.reset(new blink::WebMouseEvent(
- type, event.modifiers(), event.timestamp_seconds()));
+ (*out)->web_event.reset(
+ new blink::WebMouseEvent(type, event.modifiers(), timestamp));
} else {
- (*out)->web_event.reset(new blink::WebMouseWheelEvent(
- type, event.modifiers(), event.timestamp_seconds()));
+ (*out)->web_event.reset(
+ new blink::WebMouseWheelEvent(type, event.modifiers(), timestamp));
}
blink::WebMouseEvent* mouse_event =
diff --git a/chromium/content/common/input/input_event_struct_traits.h b/chromium/content/common/input/input_event_struct_traits.h
index d63ca68bea7..ca8ea062713 100644
--- a/chromium/content/common/input/input_event_struct_traits.h
+++ b/chromium/content/common/input/input_event_struct_traits.h
@@ -25,8 +25,8 @@ struct StructTraits<content::mojom::EventDataView, InputEventUniquePtr> {
return event->web_event->GetModifiers();
}
- static double timestamp_seconds(const InputEventUniquePtr& event) {
- return event->web_event->TimeStampSeconds();
+ static base::TimeTicks timestamp(const InputEventUniquePtr& event) {
+ return event->web_event->TimeStamp();
}
static const ui::LatencyInfo& latency(const InputEventUniquePtr& event) {
diff --git a/chromium/content/common/input/input_handler.mojom b/chromium/content/common/input/input_handler.mojom
index b5725e1dbf9..9f8a63e8b72 100644
--- a/chromium/content/common/input/input_handler.mojom
+++ b/chromium/content/common/input/input_handler.mojom
@@ -7,6 +7,7 @@ module content.mojom;
import "content/common/input/synchronous_compositor.mojom";
import "content/common/native_types.mojom";
import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/time.mojom";
import "services/ui/public/interfaces/ime/ime.mojom";
import "third_party/blink/public/web/selection_menu_behavior.mojom";
import "ui/events/mojo/event.mojom";
@@ -139,7 +140,7 @@ struct TouchData {
struct Event {
EventType type;
int32 modifiers;
- double timestamp_seconds;
+ mojo_base.mojom.TimeTicks timestamp;
ui.mojom.LatencyInfo latency;
KeyData? key_data;
PointerData? pointer_data;
@@ -187,6 +188,13 @@ interface WidgetInputHandlerHost {
// to always have correct bound info.
ImeCompositionRangeChanged(gfx.mojom.Range range,
array<gfx.mojom.Rect> bounds);
+
+ // Updates the mouse capture state of this widget. While capture is enabled,
+ // all mouse events, including those that don't hittest to this widget, will
+ // be targeted to this widget. This enables Blink to behave correctly when
+ // a scrollbar is being dragged, or text is being drag-highlighted, even
+ // when the mouse passes across different RenderWidget areas.
+ SetMouseCapture(bool capture);
};
// Interface exposed by the renderer to the browser. This class represents
@@ -234,7 +242,7 @@ interface WidgetInputHandler {
RequestTextInputStateUpdate();
// Request from browser to update the cursor and composition information which
- // will be sent through InputHostMsg_ImeCompositionRangeChanged. Setting
+ // will be sent through ImeCompositionRangeChanged. Setting
// |immediate_request| to true will lead to an immediate update. If
// |monitor_updates| is set to true then changes to text selection or regular
// updates in each compositor frame (when there is a change in composition
diff --git a/chromium/content/common/input/input_param_traits_unittest.cc b/chromium/content/common/input/input_param_traits_unittest.cc
deleted file mode 100644
index 81d1d69cd85..00000000000
--- a/chromium/content/common/input/input_param_traits_unittest.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2013 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/common/input/input_param_traits.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "content/common/input/input_event.h"
-#include "content/common/input_messages.h"
-#include "ipc/ipc_message.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_gesture_event.h"
-#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/public/platform/web_keyboard_event.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
-#include "third_party/blink/public/platform/web_touch_event.h"
-
-namespace content {
-namespace {
-
-typedef std::vector<std::unique_ptr<InputEvent>> InputEvents;
-
-class InputParamTraitsTest : public testing::Test {
- protected:
- static void Compare(const InputEvent* a, const InputEvent* b) {
- EXPECT_EQ(!!a->web_event, !!b->web_event);
- if (a->web_event && b->web_event) {
- const size_t a_size = a->web_event->size();
- ASSERT_EQ(a_size, b->web_event->size());
- EXPECT_EQ(0, memcmp(a->web_event.get(), b->web_event.get(), a_size));
- }
- EXPECT_EQ(a->latency_info.latency_components().size(),
- b->latency_info.latency_components().size());
- }
-
- static void Compare(const InputEvents* a, const InputEvents* b) {
- for (size_t i = 0; i < a->size(); ++i)
- Compare((*a)[i].get(), (*b)[i].get());
- }
-
- static void Verify(const InputEvents& events_in) {
- IPC::Message msg;
- IPC::ParamTraits<InputEvents>::Write(&msg, events_in);
-
- InputEvents events_out;
- base::PickleIterator iter(msg);
- EXPECT_TRUE(IPC::ParamTraits<InputEvents>::Read(&msg, &iter, &events_out));
-
- Compare(&events_in, &events_out);
-
- // Perform a sanity check that logging doesn't explode.
- std::string events_in_string;
- IPC::ParamTraits<InputEvents>::Log(events_in, &events_in_string);
- std::string events_out_string;
- IPC::ParamTraits<InputEvents>::Log(events_out, &events_out_string);
- ASSERT_FALSE(events_in_string.empty());
- EXPECT_EQ(events_in_string, events_out_string);
- }
-};
-
-TEST_F(InputParamTraitsTest, UninitializedEvents) {
- InputEvent event;
-
- IPC::Message msg;
- IPC::WriteParam(&msg, event);
-
- InputEvent event_out;
- base::PickleIterator iter(msg);
- EXPECT_FALSE(IPC::ReadParam(&msg, &iter, &event_out));
-}
-
-TEST_F(InputParamTraitsTest, InitializedEvents) {
- InputEvents events;
-
- ui::LatencyInfo latency;
- latency.set_trace_id(5);
-
- blink::WebKeyboardEvent key_event(
- blink::WebInputEvent::kRawKeyDown, blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests());
- key_event.native_key_code = 5;
- events.push_back(std::make_unique<InputEvent>(key_event, latency));
-
- blink::WebMouseWheelEvent wheel_event(
- blink::WebInputEvent::kMouseWheel, blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests());
- wheel_event.delta_x = 10;
- latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 1, 1);
- events.push_back(std::make_unique<InputEvent>(wheel_event, latency));
-
- blink::WebMouseEvent mouse_event(
- blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests());
- mouse_event.SetPositionInWidget(10, 0);
- latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 2, 2);
- events.push_back(std::make_unique<InputEvent>(mouse_event, latency));
-
- blink::WebGestureEvent gesture_event(
- blink::WebInputEvent::kGestureScrollBegin,
- blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests());
- gesture_event.SetPositionInWidget(gfx::PointF(-1, 0));
- events.push_back(std::make_unique<InputEvent>(gesture_event, latency));
-
- blink::WebTouchEvent touch_event(
- blink::WebInputEvent::kTouchStart, blink::WebInputEvent::kNoModifiers,
- blink::WebInputEvent::GetStaticTimeStampForTests());
- touch_event.touches_length = 1;
- touch_event.touches[0].radius_x = 1;
- events.push_back(std::make_unique<InputEvent>(touch_event, latency));
-
- Verify(events);
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/common/input/sync_compositor_messages.h b/chromium/content/common/input/sync_compositor_messages.h
index fcfd89e58d0..a608f7eb160 100644
--- a/chromium/content/common/input/sync_compositor_messages.h
+++ b/chromium/content/common/input/sync_compositor_messages.h
@@ -8,14 +8,9 @@
#include <stddef.h>
#include "base/memory/shared_memory_handle.h"
-#include "base/optional.h"
-#include "components/viz/common/frame_sinks/begin_frame_args.h"
-#include "components/viz/common/quads/compositor_frame.h"
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
-#include "content/public/common/input_event_ack_state.h"
#include "ipc/ipc_message_macros.h"
-#include "third_party/blink/public/platform/web_input_event.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/scroll_offset.h"
@@ -80,10 +75,6 @@ struct SyncCompositorCommonRendererParams {
#endif // INTERNAL_CONTENT_COMMON_SYNC_COMPOSITOR_MESSAGES_H_
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START SyncCompositorMsgStart
-
IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorDemandDrawHwParams)
IPC_STRUCT_TRAITS_MEMBER(viewport_size)
IPC_STRUCT_TRAITS_MEMBER(viewport_rect_for_tile_priority)
@@ -114,77 +105,4 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorCommonRendererParams)
IPC_STRUCT_TRAITS_MEMBER(did_activate_pending_tree_count)
IPC_STRUCT_TRAITS_END()
-// Messages sent from the browser to the renderer.
-// Synchronous IPCs are allowed here to the renderer compositor thread. See
-// design doc https://goo.gl/Tn81FW and https://crbug.com/526842 for details.
-
-IPC_MESSAGE_ROUTED1(SyncCompositorMsg_ComputeScroll, base::TimeTicks)
-
-IPC_MESSAGE_ROUTED1(SyncCompositorMsg_DemandDrawHwAsync,
- content::SyncCompositorDemandDrawHwParams)
-
-IPC_SYNC_MESSAGE_ROUTED1_4(SyncCompositorMsg_DemandDrawHw,
- content::SyncCompositorDemandDrawHwParams,
- content::SyncCompositorCommonRendererParams,
- uint32_t /* layer_tree_frame_sink_id */,
- uint32_t /* metadata_version */,
- base::Optional<viz::CompositorFrame>)
-
-IPC_SYNC_MESSAGE_ROUTED1_2(SyncCompositorMsg_SetSharedMemory,
- content::SyncCompositorSetSharedMemoryParams,
- bool /* success */,
- content::SyncCompositorCommonRendererParams)
-
-IPC_MESSAGE_ROUTED0(SyncCompositorMsg_ZeroSharedMemory)
-
-IPC_SYNC_MESSAGE_ROUTED1_3(SyncCompositorMsg_DemandDrawSw,
- content::SyncCompositorDemandDrawSwParams,
- content::SyncCompositorCommonRendererParams,
- uint32_t /* metadata_version */,
- base::Optional<viz::CompositorFrameMetadata>)
-
-IPC_SYNC_MESSAGE_ROUTED2_1(SyncCompositorMsg_ZoomBy,
- float /* delta */,
- gfx::Point /* anchor */,
- content::SyncCompositorCommonRendererParams)
-
-IPC_MESSAGE_ROUTED1(SyncCompositorMsg_SetMemoryPolicy,
- uint32_t /* bytes_limit */)
-
-IPC_MESSAGE_ROUTED2(SyncCompositorMsg_ReclaimResources,
- uint32_t /* layer_tree_frame_sink_id */,
- std::vector<viz::ReturnedResource> /* resources */)
-
-IPC_MESSAGE_ROUTED1(SyncCompositorMsg_SetScroll, gfx::ScrollOffset)
-
-// Let renderer know begin frame messages won't be sent even if requested.
-IPC_MESSAGE_ROUTED1(SyncCompositorMsg_SetBeginFramePaused, bool /* paused */)
-
-// Sent by the browser when the renderer should generate a new frame.
-IPC_MESSAGE_ROUTED1(SyncCompositorMsg_BeginFrame,
- viz::BeginFrameArgs /* args */)
-
-// -----------------------------------------------------------------------------
-// Messages sent from the renderer to the browser.
-
-IPC_MESSAGE_ROUTED0(SyncCompositorHostMsg_LayerTreeFrameSinkCreated)
-
-IPC_MESSAGE_ROUTED1(SyncCompositorHostMsg_UpdateState,
- content::SyncCompositorCommonRendererParams)
-
-// Response to a begin frame request.
-IPC_MESSAGE_ROUTED1(SyncCompositorHostMsg_BeginFrameResponse,
- content::SyncCompositorCommonRendererParams)
-
-IPC_MESSAGE_ROUTED3(SyncCompositorHostMsg_ReturnFrame,
- uint32_t /* layer_tree_frame_sink_id */,
- uint32_t /* metadata_version */,
- base::Optional<viz::CompositorFrame>)
-
-// Sent by renderer to request a SyncCompositorMsg_BeginFrame message for
-// upcoming display events. If |enabled| is true, the BeginFrame message will
-// continue to be be delivered until the notification is disabled.
-IPC_MESSAGE_ROUTED1(SyncCompositorHostMsg_SetNeedsBeginFrames,
- bool /* enabled */)
-
#endif // CONTENT_COMMON_SYNC_COMPOSITOR_MESSAGES_H_
diff --git a/chromium/content/common/input/synchronous_compositor.typemap b/chromium/content/common/input/synchronous_compositor.typemap
index 6adbf1659d1..cb07fb33228 100644
--- a/chromium/content/common/input/synchronous_compositor.typemap
+++ b/chromium/content/common/input/synchronous_compositor.typemap
@@ -6,7 +6,6 @@ mojom = "//content/common/input/synchronous_compositor.mojom"
public_headers = [ "//content/common/input/sync_compositor_messages.h" ]
traits_headers = [ "//content/common/input/sync_compositor_messages.h" ]
deps = [
- "//cc/ipc",
"//ui/gfx/ipc",
]
type_mappings = [
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders.cc b/chromium/content/common/input/synthetic_web_input_event_builders.cc
index 617d0ea12b5..5cf6591d784 100644
--- a/chromium/content/common/input/synthetic_web_input_event_builders.cc
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.cc
@@ -23,7 +23,7 @@ using blink::WebTouchPoint;
WebMouseEvent SyntheticWebMouseEventBuilder::Build(
blink::WebInputEvent::Type type) {
return WebMouseEvent(type, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ ui::EventTimeForNow());
}
WebMouseEvent SyntheticWebMouseEventBuilder::Build(
@@ -33,9 +33,9 @@ WebMouseEvent SyntheticWebMouseEventBuilder::Build(
int modifiers,
blink::WebPointerProperties::PointerType pointer_type) {
DCHECK(WebInputEvent::IsMouseEventType(type));
- WebMouseEvent result(type, modifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebMouseEvent result(type, modifiers, ui::EventTimeForNow());
result.SetPositionInWidget(window_x, window_y);
+ result.SetPositionInScreen(window_x, window_y);
result.SetModifiers(modifiers);
result.pointer_type = pointer_type;
result.id = ui::MouseEvent::kMousePointerId;
@@ -45,8 +45,7 @@ WebMouseEvent SyntheticWebMouseEventBuilder::Build(
WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(
WebMouseWheelEvent::Phase phase) {
WebMouseWheelEvent result(WebInputEvent::kMouseWheel,
- WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebInputEvent::kNoModifiers, ui::EventTimeForNow());
result.phase = phase;
return result;
}
@@ -69,7 +68,7 @@ WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float x,
int modifiers,
bool precise) {
WebMouseWheelEvent result(WebInputEvent::kMouseWheel, modifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ ui::EventTimeForNow());
result.SetPositionInScreen(global_x, global_y);
result.SetPositionInWidget(x, y);
result.delta_x = dx;
@@ -86,7 +85,7 @@ WebKeyboardEvent SyntheticWebKeyboardEventBuilder::Build(
WebInputEvent::Type type) {
DCHECK(WebInputEvent::IsKeyboardEventType(type));
WebKeyboardEvent result(type, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ ui::EventTimeForNow());
result.windows_key_code = ui::VKEY_L; // non-null made up value.
return result;
}
@@ -96,9 +95,7 @@ WebGestureEvent SyntheticWebGestureEventBuilder::Build(
blink::WebGestureDevice source_device,
int modifiers) {
DCHECK(WebInputEvent::IsGestureEventType(type));
- WebGestureEvent result(type, modifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()),
- source_device);
+ WebGestureEvent result(type, modifiers, ui::EventTimeForNow(), source_device);
if (type == WebInputEvent::kGestureTap ||
type == WebInputEvent::kGestureTapUnconfirmed ||
type == WebInputEvent::kGestureDoubleTap) {
@@ -202,9 +199,9 @@ int SyntheticWebTouchEvent::PressPoint(float x, float y) {
point.rotation_angle = 1.f;
point.force = 1.f;
point.tilt_x = point.tilt_y = 0;
+ point.pointer_type = blink::WebPointerProperties::PointerType::kTouch;
++touches_length;
- WebTouchEventTraits::ResetType(WebInputEvent::kTouchStart, TimeStampSeconds(),
- this);
+ WebTouchEventTraits::ResetType(WebInputEvent::kTouchStart, TimeStamp(), this);
return point.id;
}
@@ -218,8 +215,7 @@ void SyntheticWebTouchEvent::MovePoint(int index, float x, float y) {
point.SetPositionInWidget(x, y);
point.SetPositionInScreen(x, y);
touches[index].state = WebTouchPoint::kStateMoved;
- WebTouchEventTraits::ResetType(WebInputEvent::kTouchMove, TimeStampSeconds(),
- this);
+ WebTouchEventTraits::ResetType(WebInputEvent::kTouchMove, TimeStamp(), this);
}
void SyntheticWebTouchEvent::ReleasePoint(int index) {
@@ -227,20 +223,19 @@ void SyntheticWebTouchEvent::ReleasePoint(int index) {
CHECK_LT(index, kTouchesLengthCap);
touches[index].state = WebTouchPoint::kStateReleased;
touches[index].force = 0.f;
- WebTouchEventTraits::ResetType(WebInputEvent::kTouchEnd, TimeStampSeconds(),
- this);
+ WebTouchEventTraits::ResetType(WebInputEvent::kTouchEnd, TimeStamp(), this);
}
void SyntheticWebTouchEvent::CancelPoint(int index) {
CHECK_GE(index, 0);
CHECK_LT(index, kTouchesLengthCap);
touches[index].state = WebTouchPoint::kStateCancelled;
- WebTouchEventTraits::ResetType(WebInputEvent::kTouchCancel,
- TimeStampSeconds(), this);
+ WebTouchEventTraits::ResetType(WebInputEvent::kTouchCancel, TimeStamp(),
+ this);
}
void SyntheticWebTouchEvent::SetTimestamp(base::TimeTicks timestamp) {
- SetTimeStampSeconds(ui::EventTimeStampToSeconds(timestamp));
+ SetTimeStamp(timestamp);
}
int SyntheticWebTouchEvent::FirstFreeIndex() {
diff --git a/chromium/content/common/input/touch_action_optional_struct_traits.cc b/chromium/content/common/input/touch_action_optional_struct_traits.cc
index b2b4c33e638..3b57659bb1d 100644
--- a/chromium/content/common/input/touch_action_optional_struct_traits.cc
+++ b/chromium/content/common/input/touch_action_optional_struct_traits.cc
@@ -4,7 +4,7 @@
#include "content/common/input/touch_action_optional_struct_traits.h"
-#include "content/common/input_messages.h"
+#include "content/public/common/common_param_traits_macros.h"
namespace mojo {
bool StructTraits<
diff --git a/chromium/content/common/input/web_touch_event_traits.cc b/chromium/content/common/input/web_touch_event_traits.cc
index 897d78e5b58..06972d03654 100644
--- a/chromium/content/common/input/web_touch_event_traits.cc
+++ b/chromium/content/common/input/web_touch_event_traits.cc
@@ -50,7 +50,7 @@ bool WebTouchEventTraits::IsTouchSequenceEnd(const WebTouchEvent& event) {
}
void WebTouchEventTraits::ResetType(WebInputEvent::Type type,
- double timestamp_sec,
+ base::TimeTicks timestamp,
WebTouchEvent* event) {
DCHECK(WebInputEvent::IsTouchEventType(type));
DCHECK(type != WebInputEvent::kTouchScrollStarted);
@@ -59,13 +59,13 @@ void WebTouchEventTraits::ResetType(WebInputEvent::Type type,
event->dispatch_type = type == WebInputEvent::kTouchCancel
? WebInputEvent::kEventNonBlocking
: WebInputEvent::kBlocking;
- event->SetTimeStampSeconds(timestamp_sec);
+ event->SetTimeStamp(timestamp);
}
void WebTouchEventTraits::ResetTypeAndTouchStates(WebInputEvent::Type type,
- double timestamp_sec,
+ base::TimeTicks timestamp,
WebTouchEvent* event) {
- ResetType(type, timestamp_sec, event);
+ ResetType(type, timestamp, event);
WebTouchPoint::State newState = WebTouchPoint::kStateUndefined;
switch (event->GetType()) {
diff --git a/chromium/content/common/input/web_touch_event_traits.h b/chromium/content/common/input/web_touch_event_traits.h
index eac4718d4ff..ff27930e937 100644
--- a/chromium/content/common/input/web_touch_event_traits.h
+++ b/chromium/content/common/input/web_touch_event_traits.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_COMMON_INPUT_WEB_TOUCH_EVENT_TRAITS_H_
#define CONTENT_COMMON_INPUT_WEB_TOUCH_EVENT_TRAITS_H_
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/web_input_event.h"
@@ -32,14 +33,14 @@ class CONTENT_EXPORT WebTouchEventTraits {
// Sets the type of |event| to |type|, resetting any other type-specific
// properties and updating the timestamp.
static void ResetType(blink::WebInputEvent::Type type,
- double timestamp_sec,
+ base::TimeTicks timestamp,
blink::WebTouchEvent* event);
// Like ResetType but also resets the state of all active touches
// to match the event type. This is particularly useful, for example,
// in sending a touchcancel for all active touches.
static void ResetTypeAndTouchStates(blink::WebInputEvent::Type type,
- double timestamp_sec,
+ base::TimeTicks timestamp,
blink::WebTouchEvent* event);
};
diff --git a/chromium/content/common/input_messages.h b/chromium/content/common/input_messages.h
index 89df9cc4f40..81f0759d605 100644
--- a/chromium/content/common/input_messages.h
+++ b/chromium/content/common/input_messages.h
@@ -11,7 +11,6 @@
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "cc/input/overscroll_behavior.h"
-#include "cc/input/touch_action.h"
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
#include "content/common/edit_command.h"
@@ -66,7 +65,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(
content::SyntheticPointerActionParams::Button::BUTTON_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(content::InputEventDispatchType,
content::InputEventDispatchType::DISPATCH_TYPE_MAX)
-IPC_ENUM_TRAITS_MAX_VALUE(cc::TouchAction, cc::kTouchActionMax)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebPointerProperties::Button,
blink::WebPointerProperties::Button::kNoButton,
blink::WebPointerProperties::Button::kLastEntry)
@@ -105,11 +103,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::EditCommand)
IPC_STRUCT_TRAITS_MEMBER(value)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::InputEvent)
- IPC_STRUCT_TRAITS_MEMBER(web_event)
- IPC_STRUCT_TRAITS_MEMBER(latency_info)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(content::SyntheticGestureParams)
IPC_STRUCT_TRAITS_MEMBER(gesture_source_type)
IPC_STRUCT_TRAITS_END()
@@ -154,229 +147,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyntheticPointerActionListParams)
IPC_STRUCT_TRAITS_MEMBER(params)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::InputEventAck)
- IPC_STRUCT_TRAITS_MEMBER(source)
- IPC_STRUCT_TRAITS_MEMBER(type)
- IPC_STRUCT_TRAITS_MEMBER(state)
- IPC_STRUCT_TRAITS_MEMBER(latency)
- IPC_STRUCT_TRAITS_MEMBER(overscroll)
- IPC_STRUCT_TRAITS_MEMBER(unique_touch_event_id)
- IPC_STRUCT_TRAITS_MEMBER(touch_action)
-IPC_STRUCT_TRAITS_END()
-
-// Sends an input event to the render widget. The input event in general
-// contains a list of coalesced events and one event that is representative of
-// all those events (https://w3c.github.io/pointerevents/extension.html).
-IPC_MESSAGE_ROUTED4(
- InputMsg_HandleInputEvent,
- IPC::WebInputEventPointer /* event */,
- std::vector<IPC::WebInputEventPointer> /* coalesced events */,
- ui::LatencyInfo /* latency_info */,
- content::InputEventDispatchType)
-
-// Sends the cursor visibility state to the render widget.
-IPC_MESSAGE_ROUTED1(InputMsg_CursorVisibilityChange,
- bool /* is_visible */)
-
-// Sets the text composition to be between the given start and end offsets in
-// the currently focused editable field.
-IPC_MESSAGE_ROUTED3(InputMsg_SetCompositionFromExistingText,
- int /* start */,
- int /* end */,
- std::vector<blink::WebImeTextSpan> /* ime_text_spans */)
-
-// Deletes the current selection plus the specified number of characters before
-// and after the selection or caret.
-IPC_MESSAGE_ROUTED2(InputMsg_ExtendSelectionAndDelete,
- int /* before */,
- int /* after */)
-
-// Deletes text before and after the current cursor position, excluding the
-// selection. The lengths are supplied in Java chars (UTF-16 Code Unit), not in
-// code points or in glyphs.
-IPC_MESSAGE_ROUTED2(InputMsg_DeleteSurroundingText,
- int /* before */,
- int /* after */)
-
-// Deletes text before and after the current cursor position, excluding the
-// selection. The lengths are supplied in code points, not in Java chars (UTF-16
-// Code Unit) or in glyphs. Does nothing if there are one or more invalid
-// surrogate pairs in the requested range
-IPC_MESSAGE_ROUTED2(InputMsg_DeleteSurroundingTextInCodePoints,
- int /* before */,
- int /* after */)
-
-// Selects between the given start and end offsets in the currently focused
-// editable field.
-IPC_MESSAGE_ROUTED2(InputMsg_SetEditableSelectionOffsets,
- int /* start */,
- int /* end */)
-
-// This message sends a string being composed with an input method.
-IPC_MESSAGE_ROUTED5(InputMsg_ImeSetComposition,
- base::string16, /* text */
- std::vector<blink::WebImeTextSpan>, /* ime_text_spans */
- gfx::Range /* replacement_range */,
- int, /* selectiont_start */
- int /* selection_end */)
-
-// This message deletes the current composition, inserts specified text, and
-// moves the cursor.
-IPC_MESSAGE_ROUTED4(InputMsg_ImeCommitText,
- base::string16 /* text */,
- std::vector<blink::WebImeTextSpan>, /* ime_text_spans */
- gfx::Range /* replacement_range */,
- int /* relative_cursor_pos */)
-
-// This message inserts the ongoing composition.
-IPC_MESSAGE_ROUTED1(InputMsg_ImeFinishComposingText, bool /* keep_selection */)
-
-// This message notifies the renderer that the next key event is bound to one
-// or more pre-defined edit commands. If the next key event is not handled
-// by webkit, the specified edit commands shall be executed against current
-// focused frame.
-// Parameters
-// * edit_commands (see chrome/common/edit_command_types.h)
-// Contains one or more edit commands.
-// See third_party/WebKit/Source/WebCore/editing/EditorCommand.cpp for detailed
-// definition of webkit edit commands.
-//
-// This message must be sent just before sending a key event.
-IPC_MESSAGE_ROUTED1(InputMsg_SetEditCommandsForNextKeyEvent,
- std::vector<content::EditCommand> /* edit_commands */)
-
-// Message payload is the name of a WebCore edit command to execute.
-IPC_MESSAGE_ROUTED1(InputMsg_ExecuteNoValueEditCommand, std::string /* name */)
-
-IPC_MESSAGE_ROUTED0(InputMsg_MouseCaptureLost)
-
-// TODO(darin): figure out how this meshes with RestoreFocus
+// TODO(dtapuska): Remove this as only OOPIF uses this
IPC_MESSAGE_ROUTED1(InputMsg_SetFocus,
bool /* enable */)
-// Tells the renderer to scroll the currently focused node into rect only if
-// the currently focused node is a Text node (textfield, text area or content
-// editable divs).
-IPC_MESSAGE_ROUTED1(InputMsg_ScrollFocusedEditableNodeIntoRect, gfx::Rect)
-
-// These messages are typically generated from context menus and request the
-// renderer to apply the specified operation to the current selection.
-IPC_MESSAGE_ROUTED0(InputMsg_Undo)
-IPC_MESSAGE_ROUTED0(InputMsg_Redo)
-IPC_MESSAGE_ROUTED0(InputMsg_Cut)
-IPC_MESSAGE_ROUTED0(InputMsg_Copy)
-#if defined(OS_MACOSX)
-IPC_MESSAGE_ROUTED0(InputMsg_CopyToFindPboard)
-#endif
-IPC_MESSAGE_ROUTED0(InputMsg_Paste)
-IPC_MESSAGE_ROUTED0(InputMsg_PasteAndMatchStyle)
-// Replaces the selected region or a word around the cursor with the
-// specified string.
-IPC_MESSAGE_ROUTED1(InputMsg_Replace,
- base::string16)
-// Replaces the misspelling in the selected region with the specified string.
-IPC_MESSAGE_ROUTED1(InputMsg_ReplaceMisspelling,
- base::string16)
-IPC_MESSAGE_ROUTED0(InputMsg_Delete)
-IPC_MESSAGE_ROUTED0(InputMsg_SelectAll)
-
-IPC_MESSAGE_ROUTED0(InputMsg_CollapseSelection)
-
-// Requests the renderer to select the region between two points.
-// Expects a SelectRange_ACK message when finished.
-IPC_MESSAGE_ROUTED2(InputMsg_SelectRange,
- gfx::Point /* base */,
- gfx::Point /* extent */)
-
-// Sent by the browser to ask the renderer to adjust the selection start and
-// end points by the given amounts. A negative amount moves the selection
-// towards the beginning of the document, a positive amount moves the selection
-// towards the end of the document. Will send show selection menu event when
-// needed.
-IPC_MESSAGE_ROUTED3(InputMsg_AdjustSelectionByCharacterOffset,
- int /* start_adjust*/,
- int /* end_adjust */,
- bool /* show_selection_menu */)
-
-// Requests the renderer to move the selection extent point to a new position.
-// Expects a MoveRangeSelectionExtent_ACK message when finished.
-IPC_MESSAGE_ROUTED1(InputMsg_MoveRangeSelectionExtent,
- gfx::Point /* extent */)
-
-// Requests the renderer to move the caret selection toward the point.
-// Expects a MoveCaret_ACK message when finished.
-IPC_MESSAGE_ROUTED1(InputMsg_MoveCaret,
- gfx::Point /* location */)
-
-#if defined(OS_ANDROID)
-// Request from browser to update text input state.
-IPC_MESSAGE_ROUTED0(InputMsg_RequestTextInputStateUpdate)
-#endif
-
-// Request from browser to update the cursor and composition information which
-// will be sent through InputHostMsg_ImeCompositionRangeChanged. Setting
-// |immediate_request| to true will lead to an immediate update. If
-// |monitor_updates| is set to true then changes to text selection or regular
-// updates in each compositor frame (when there is a change in composition info)
-// will lead to updates being sent to the browser.
-IPC_MESSAGE_ROUTED2(InputMsg_RequestCompositionUpdates,
- bool /* immediate_request */,
- bool /* monitor_updates */)
-
-// -----------------------------------------------------------------------------
-// Messages sent from the renderer to the browser.
-
-// Acknowledges receipt of a InputMsg_HandleInputEvent message.
-IPC_MESSAGE_ROUTED1(InputHostMsg_HandleInputEvent_ACK,
- content::InputEventAck /* ack */)
-
-// Notifies the allowed touch actions for a new touch point.
-IPC_MESSAGE_ROUTED1(InputHostMsg_SetTouchAction,
- cc::TouchAction /* touch_action */)
-
-// The whitelisted touch action and the associated unique touch event id
-// for a new touch point sent by the compositor. The unique touch event id is
-// only needed to verify that the whitelisted touch action is being associated
-// with the correct touch event. The input event ack state is needed when
-// the touchstart message was not sent to the renderer and the touch
-// actions need to be reset and the touch ack timeout needs to be started.
-IPC_MESSAGE_ROUTED3(InputHostMsg_SetWhiteListedTouchAction,
- cc::TouchAction /* white_listed_touch_action */,
- uint32_t /* unique_touch_event_id */,
- content::InputEventAckState /* ack_result */)
-
-// Sent by the compositor when input scroll events are dropped due to bounds
-// restrictions on the root scroll offset.
-IPC_MESSAGE_ROUTED1(InputHostMsg_DidOverscroll,
- ui::DidOverscrollParams /* params */)
-
-// Sent by the compositor when a fling animation is stopped.
-IPC_MESSAGE_ROUTED0(InputHostMsg_DidStopFlinging)
-
-// Sent by the compositor when a GSB has started scrolling the viewport.
-IPC_MESSAGE_ROUTED0(InputHostMsg_DidStartScrollingViewport)
-
-// Acknowledges receipt of a InputMsg_MoveCaret message.
-IPC_MESSAGE_ROUTED0(InputHostMsg_MoveCaret_ACK)
-
-// Acknowledges receipt of a InputMsg_MoveRangeSelectionExtent message.
-IPC_MESSAGE_ROUTED0(InputHostMsg_MoveRangeSelectionExtent_ACK)
-
-// Acknowledges receipt of a InputMsg_SelectRange message.
-IPC_MESSAGE_ROUTED0(InputHostMsg_SelectRange_ACK)
-
-// Required for cancelling an ongoing input method composition.
-IPC_MESSAGE_ROUTED0(InputHostMsg_ImeCancelComposition)
-
-// This IPC message sends the character bounds after every composition change
-// to always have correct bound info.
-IPC_MESSAGE_ROUTED2(InputHostMsg_ImeCompositionRangeChanged,
- gfx::Range /* composition range */,
- std::vector<gfx::Rect> /* character bounds */)
-
-// Adding a new message? Stick to the sort order above: first platform
-// independent InputMsg, then ifdefs for platform specific InputMsg, then
-// platform independent InputHostMsg, then ifdefs for platform specific
-// InputHostMsg.
-
#endif // CONTENT_COMMON_INPUT_MESSAGES_H_
diff --git a/chromium/content/common/inter_process_time_ticks_converter.cc b/chromium/content/common/inter_process_time_ticks_converter.cc
index be36224a314..128abab37eb 100644
--- a/chromium/content/common/inter_process_time_ticks_converter.cc
+++ b/chromium/content/common/inter_process_time_ticks_converter.cc
@@ -4,84 +4,78 @@
#include "content/common/inter_process_time_ticks_converter.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
namespace content {
InterProcessTimeTicksConverter::InterProcessTimeTicksConverter(
- const LocalTimeTicks& local_lower_bound,
- const LocalTimeTicks& local_upper_bound,
- const RemoteTimeTicks& remote_lower_bound,
- const RemoteTimeTicks& remote_upper_bound)
- : remote_lower_bound_(remote_lower_bound.value_),
- remote_upper_bound_(remote_upper_bound.value_) {
- int64_t target_range = local_upper_bound.value_ - local_lower_bound.value_;
- int64_t source_range = remote_upper_bound.value_ - remote_lower_bound.value_;
- DCHECK_GE(target_range, 0);
- DCHECK_GE(source_range, 0);
- if (source_range <= target_range) {
+ LocalTimeTicks local_lower_bound,
+ LocalTimeTicks local_upper_bound,
+ RemoteTimeTicks remote_lower_bound,
+ RemoteTimeTicks remote_upper_bound)
+ : local_range_(local_upper_bound - local_lower_bound),
+ remote_lower_bound_(remote_lower_bound),
+ remote_upper_bound_(remote_upper_bound) {
+ RemoteTimeDelta remote_range = remote_upper_bound - remote_lower_bound;
+
+ DCHECK_LE(LocalTimeDelta(), local_range_);
+ DCHECK_LE(RemoteTimeDelta(), remote_range);
+
+ if (remote_range.ToTimeDelta() <= local_range_.ToTimeDelta()) {
// We fit! Center the source range on the target range.
- numerator_ = 1;
- denominator_ = 1;
+ range_conversion_rate_ = 1.0;
+ base::TimeDelta diff =
+ local_range_.ToTimeDelta() - remote_range.ToTimeDelta();
+
local_base_time_ =
- local_lower_bound.value_ + (target_range - source_range) / 2;
+ local_lower_bound + LocalTimeDelta::FromTimeDelta(diff / 2);
// When converting times, remote bounds should fall within local bounds.
- DCHECK_LE(local_lower_bound.value_,
- ToLocalTimeTicks(remote_lower_bound).value_);
- DCHECK_GE(local_upper_bound.value_,
- ToLocalTimeTicks(remote_upper_bound).value_);
+ DCHECK_LE(local_lower_bound, ToLocalTimeTicks(remote_lower_bound));
+ DCHECK_LE(ToLocalTimeTicks(remote_upper_bound), local_upper_bound);
return;
}
// Interpolate values so that remote range will be will exactly fit into the
// local range, if possible.
- numerator_ = target_range;
- denominator_ = source_range;
- local_base_time_ = local_lower_bound.value_;
- // When converting times, remote bounds should equal local bounds.
- DCHECK_EQ(local_lower_bound.value_,
- ToLocalTimeTicks(remote_lower_bound).value_);
- DCHECK_EQ(local_upper_bound.value_,
- ToLocalTimeTicks(remote_upper_bound).value_);
- DCHECK_EQ(target_range, Convert(source_range));
+ DCHECK_GT(remote_range.ToTimeDelta().InMicroseconds(), 0);
+ range_conversion_rate_ =
+ static_cast<double>(local_range_.ToTimeDelta().InMicroseconds()) /
+ remote_range.ToTimeDelta().InMicroseconds();
+ local_base_time_ = local_lower_bound;
}
LocalTimeTicks InterProcessTimeTicksConverter::ToLocalTimeTicks(
- const RemoteTimeTicks& remote_ms) const {
+ RemoteTimeTicks remote_time_ticks) const {
// If input time is "null", return another "null" time.
- if (remote_ms.value_ == 0)
- return LocalTimeTicks(0);
+ if (remote_time_ticks.is_null())
+ return LocalTimeTicks();
- RemoteTimeDelta remote_delta = remote_ms - remote_lower_bound_;
-
- DCHECK_LE(remote_ms.value_, remote_upper_bound_);
- // For remote times that come before remote time range, apply just time
- // offset and ignore scaling, so as to avoid extrapolation error for values
- // long in the past.
- if (remote_ms.value_ < remote_lower_bound_)
- return LocalTimeTicks(local_base_time_ + remote_delta.value_);
+ RemoteTimeDelta remote_delta = remote_time_ticks - remote_lower_bound_;
- return LocalTimeTicks(local_base_time_ +
- ToLocalTimeDelta(remote_delta).value_);
+ DCHECK_LE(remote_time_ticks, remote_upper_bound_);
+ return local_base_time_ + ToLocalTimeDelta(remote_delta);
}
LocalTimeDelta InterProcessTimeTicksConverter::ToLocalTimeDelta(
- const RemoteTimeDelta& remote_delta) const {
- DCHECK_GE(remote_upper_bound_, remote_lower_bound_ + remote_delta.value_);
- return LocalTimeDelta(Convert(remote_delta.value_));
-}
+ RemoteTimeDelta remote_delta) const {
+ DCHECK_LE(remote_lower_bound_ + remote_delta, remote_upper_bound_);
-int64_t InterProcessTimeTicksConverter::Convert(int64_t value) const {
- if (value <= 0) {
- return value;
- }
- return numerator_ * value / denominator_;
+ // For remote times that come before remote time range, apply just time
+ // offset and ignore scaling, so as to avoid extrapolation error for values
+ // long in the past.
+ if (remote_delta <= RemoteTimeDelta())
+ return LocalTimeDelta::FromTimeDelta(remote_delta.ToTimeDelta());
+
+ return std::min(local_range_,
+ LocalTimeDelta::FromTimeDelta(remote_delta.ToTimeDelta() *
+ range_conversion_rate_));
}
base::TimeDelta InterProcessTimeTicksConverter::GetSkewForMetrics() const {
- return base::TimeTicks::FromInternalValue(remote_lower_bound_) -
- base::TimeTicks::FromInternalValue(local_base_time_);
+ return remote_lower_bound_.ToTimeTicks() - local_base_time_.ToTimeTicks();
}
} // namespace content
diff --git a/chromium/content/common/inter_process_time_ticks_converter.h b/chromium/content/common/inter_process_time_ticks_converter.h
index bbefaa6aa31..cc2952e4164 100644
--- a/chromium/content/common/inter_process_time_ticks_converter.h
+++ b/chromium/content/common/inter_process_time_ticks_converter.h
@@ -12,10 +12,95 @@
namespace content {
-class LocalTimeDelta;
-class LocalTimeTicks;
-class RemoteTimeDelta;
-class RemoteTimeTicks;
+// SiteSpecificTimeDelta<T> is base::TimeDelta with a type tag. It it
+// essentially base::TimeDelta, but SiteSpecificTimeDelta<T> is different from
+// SiteSpecificTimeDelta<U> if T is different from U.
+template <typename T>
+class SiteSpecificTimeDelta final {
+ public:
+ SiteSpecificTimeDelta() = default;
+ static SiteSpecificTimeDelta<T> FromTimeDelta(base::TimeDelta delta) {
+ return SiteSpecificTimeDelta<T>(delta);
+ }
+ static SiteSpecificTimeDelta<T> FromMicroseconds(int64_t usec) {
+ return SiteSpecificTimeDelta<T>(base::TimeDelta::FromMicroseconds(usec));
+ }
+
+ base::TimeDelta ToTimeDelta() const { return delta_; }
+ bool operator==(const SiteSpecificTimeDelta<T> rhs) const {
+ return delta_ == rhs.delta_;
+ }
+ bool operator<(const SiteSpecificTimeDelta<T> rhs) const {
+ return delta_ < rhs.delta_;
+ }
+ bool operator<=(const SiteSpecificTimeDelta<T> rhs) const {
+ return delta_ <= rhs.delta_;
+ }
+
+ private:
+ explicit SiteSpecificTimeDelta(base::TimeDelta delta) : delta_(delta) {}
+
+ base::TimeDelta delta_;
+};
+
+// For logging use only.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, SiteSpecificTimeDelta<T> delta) {
+ return os << delta.ToTimeDelta();
+}
+
+// SiteSpecificTimeTicks<T> is base::TimeTicks with a type tag. It is
+// essentially base::TimeTicks, but SiteSpecificTimeTicks<T> is different from
+// SiteSpecificTimeTicks<U> if T is different from U.
+template <typename T>
+class SiteSpecificTimeTicks final {
+ public:
+ SiteSpecificTimeTicks() = default;
+ static SiteSpecificTimeTicks<T> FromTimeTicks(base::TimeTicks time_ticks) {
+ return SiteSpecificTimeTicks<T>(time_ticks);
+ }
+
+ base::TimeTicks ToTimeTicks() const { return time_ticks_; }
+ bool is_null() const { return time_ticks_.is_null(); }
+
+ SiteSpecificTimeTicks<T> operator+(SiteSpecificTimeDelta<T> delta) const {
+ return SiteSpecificTimeTicks<T>(time_ticks_ + delta.ToTimeDelta());
+ }
+ SiteSpecificTimeDelta<T> operator-(SiteSpecificTimeTicks<T> rhs) const {
+ return SiteSpecificTimeDelta<T>::FromTimeDelta(time_ticks_ -
+ rhs.time_ticks_);
+ }
+ bool operator<(const SiteSpecificTimeTicks<T> rhs) const {
+ return time_ticks_ < rhs.time_ticks_;
+ }
+ bool operator==(const SiteSpecificTimeTicks<T> rhs) const {
+ return time_ticks_ == rhs.time_ticks_;
+ }
+ bool operator<=(const SiteSpecificTimeTicks<T> rhs) const {
+ return time_ticks_ <= rhs.time_ticks_;
+ }
+
+ private:
+ explicit SiteSpecificTimeTicks(base::TimeTicks time_ticks)
+ : time_ticks_(time_ticks) {}
+
+ base::TimeTicks time_ticks_;
+};
+
+// For logging use only.
+template <typename T>
+std::ostream& operator<<(std::ostream& os,
+ SiteSpecificTimeTicks<T> time_ticks) {
+ return os << time_ticks.ToTimeTicks();
+}
+
+class SiteSpecificTimeLocalTag;
+using LocalTimeTicks = SiteSpecificTimeTicks<SiteSpecificTimeLocalTag>;
+using LocalTimeDelta = SiteSpecificTimeDelta<SiteSpecificTimeLocalTag>;
+
+class SiteSpecificTimeRemoteTag;
+using RemoteTimeTicks = SiteSpecificTimeTicks<SiteSpecificTimeRemoteTag>;
+using RemoteTimeDelta = SiteSpecificTimeDelta<SiteSpecificTimeRemoteTag>;
// On Windows, TimeTicks are not always consistent between processes as
// indicated by |TimeTicks::IsConsistentAcrossProcesses()|. Often, the values on
@@ -51,18 +136,18 @@ class RemoteTimeTicks;
// local's range. Any values converted will be shifted the same amount.
class CONTENT_EXPORT InterProcessTimeTicksConverter {
public:
- InterProcessTimeTicksConverter(const LocalTimeTicks& local_lower_bound,
- const LocalTimeTicks& local_upper_bound,
- const RemoteTimeTicks& remote_lower_bound,
- const RemoteTimeTicks& remote_upper_bound);
+ InterProcessTimeTicksConverter(LocalTimeTicks local_lower_bound,
+ LocalTimeTicks local_upper_bound,
+ RemoteTimeTicks remote_lower_bound,
+ RemoteTimeTicks remote_upper_bound);
// Returns the value within the local's bounds that correlates to
// |remote_ms|.
- LocalTimeTicks ToLocalTimeTicks(const RemoteTimeTicks& remote_ms) const;
+ LocalTimeTicks ToLocalTimeTicks(RemoteTimeTicks remote_ms) const;
// Returns the equivalent delta after applying remote-to-local scaling to
// |remote_delta|.
- LocalTimeDelta ToLocalTimeDelta(const RemoteTimeDelta& remote_delta) const;
+ LocalTimeDelta ToLocalTimeDelta(RemoteTimeDelta remote_delta) const;
// Returns the (remote time) - (local time) difference estimated by the
// converter. This is the constant that is subtracted from remote TimeTicks to
@@ -70,84 +155,14 @@ class CONTENT_EXPORT InterProcessTimeTicksConverter {
base::TimeDelta GetSkewForMetrics() const;
private:
- int64_t Convert(int64_t value) const;
-
// The local time which |remote_lower_bound_| is mapped to.
- int64_t local_base_time_;
-
- int64_t numerator_;
- int64_t denominator_;
-
- int64_t remote_lower_bound_;
- int64_t remote_upper_bound_;
-};
-
-class CONTENT_EXPORT LocalTimeDelta {
- public:
- int ToInt32() const { return value_; }
-
- private:
- friend class InterProcessTimeTicksConverter;
- friend class LocalTimeTicks;
-
- LocalTimeDelta(int value) : value_(value) {}
-
- int value_;
-};
-
-class CONTENT_EXPORT LocalTimeTicks {
- public:
- static LocalTimeTicks FromTimeTicks(const base::TimeTicks& value) {
- return LocalTimeTicks(value.ToInternalValue());
- }
-
- base::TimeTicks ToTimeTicks() {
- return base::TimeTicks::FromInternalValue(value_);
- }
-
- LocalTimeTicks operator+(const LocalTimeDelta& delta) {
- return LocalTimeTicks(value_ + delta.value_);
- }
-
- private:
- friend class InterProcessTimeTicksConverter;
-
- LocalTimeTicks(int64_t value) : value_(value) {}
-
- int64_t value_;
-};
-
-class CONTENT_EXPORT RemoteTimeDelta {
- public:
- static RemoteTimeDelta FromRawDelta(int delta) {
- return RemoteTimeDelta(delta);
- }
-
- private:
- friend class InterProcessTimeTicksConverter;
- friend class RemoteTimeTicks;
-
- RemoteTimeDelta(int value) : value_(value) {}
-
- int value_;
-};
-
-class CONTENT_EXPORT RemoteTimeTicks {
- public:
- static RemoteTimeTicks FromTimeTicks(const base::TimeTicks& ticks) {
- return RemoteTimeTicks(ticks.ToInternalValue());
- }
-
- RemoteTimeDelta operator-(const RemoteTimeTicks& rhs) const {
- return RemoteTimeDelta(value_ - rhs.value_);
- }
-
- private:
- friend class InterProcessTimeTicksConverter;
+ LocalTimeTicks local_base_time_;
+ LocalTimeDelta local_range_;
- RemoteTimeTicks(int64_t value) : value_(value) {}
+ double range_conversion_rate_;
- int64_t value_;
+ RemoteTimeTicks remote_lower_bound_;
+ RemoteTimeTicks remote_upper_bound_;
};
} // namespace content
diff --git a/chromium/content/common/inter_process_time_ticks_converter_unittest.cc b/chromium/content/common/inter_process_time_ticks_converter_unittest.cc
index 0a555e02214..8b8d72157b6 100644
--- a/chromium/content/common/inter_process_time_ticks_converter_unittest.cc
+++ b/chromium/content/common/inter_process_time_ticks_converter_unittest.cc
@@ -16,43 +16,38 @@ namespace content {
namespace {
struct TestParams {
- int64_t local_lower_bound;
- int64_t remote_lower_bound;
- int64_t remote_upper_bound;
- int64_t local_upper_bound;
- int64_t test_time;
- int64_t test_delta;
+ LocalTimeTicks local_lower_bound;
+ RemoteTimeTicks remote_lower_bound;
+ RemoteTimeTicks remote_upper_bound;
+ LocalTimeTicks local_upper_bound;
+ RemoteTimeTicks test_time;
+ RemoteTimeDelta test_delta;
};
struct TestResults {
- int64_t result_time;
- int32_t result_delta;
+ LocalTimeTicks result_time;
+ LocalTimeDelta result_delta;
int64_t skew;
};
-TestResults RunTest(const TestParams& params) {
- TimeTicks local_lower_bound = TimeTicks::FromInternalValue(
- params.local_lower_bound);
- TimeTicks local_upper_bound = TimeTicks::FromInternalValue(
- params.local_upper_bound);
- TimeTicks remote_lower_bound = TimeTicks::FromInternalValue(
- params.remote_lower_bound);
- TimeTicks remote_upper_bound = TimeTicks::FromInternalValue(
- params.remote_upper_bound);
- TimeTicks test_time = TimeTicks::FromInternalValue(params.test_time);
+LocalTimeTicks GetLocalTimeTicks(int64_t value) {
+ return LocalTimeTicks::FromTimeTicks(
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(value));
+}
+
+RemoteTimeTicks GetRemoteTimeTicks(int64_t value) {
+ return RemoteTimeTicks::FromTimeTicks(
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(value));
+}
+TestResults RunTest(const TestParams& params) {
InterProcessTimeTicksConverter converter(
- LocalTimeTicks::FromTimeTicks(local_lower_bound),
- LocalTimeTicks::FromTimeTicks(local_upper_bound),
- RemoteTimeTicks::FromTimeTicks(remote_lower_bound),
- RemoteTimeTicks::FromTimeTicks(remote_upper_bound));
+ params.local_lower_bound, params.local_upper_bound,
+ params.remote_lower_bound, params.remote_upper_bound);
TestResults results;
- results.result_time = converter.ToLocalTimeTicks(
- RemoteTimeTicks::FromTimeTicks(
- test_time)).ToTimeTicks().ToInternalValue();
- results.result_delta = converter.ToLocalTimeDelta(
- RemoteTimeDelta::FromRawDelta(params.test_delta)).ToInt32();
+ results.result_time = converter.ToLocalTimeTicks(params.test_time);
+ results.result_delta = converter.ToLocalTimeDelta(params.test_delta);
results.skew = converter.GetSkewForMetrics().ToInternalValue();
return results;
}
@@ -60,29 +55,29 @@ TestResults RunTest(const TestParams& params) {
TEST(InterProcessTimeTicksConverterTest, NullTime) {
// Null / zero times should remain null.
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 2;
- p.remote_upper_bound = 5;
- p.local_upper_bound = 6;
- p.test_time = 0;
- p.test_delta = 0;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(2);
+ p.remote_upper_bound = GetRemoteTimeTicks(5);
+ p.local_upper_bound = GetLocalTimeTicks(6);
+ p.test_time = GetRemoteTimeTicks(0);
+ p.test_delta = RemoteTimeDelta();
TestResults results = RunTest(p);
- EXPECT_EQ(0, results.result_time);
- EXPECT_EQ(0, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(0), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, NoSkew) {
// All times are monotonic and centered, so no adjustment should occur.
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 2;
- p.remote_upper_bound = 5;
- p.local_upper_bound = 6;
- p.test_time = 3;
- p.test_delta = 1;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(2);
+ p.remote_upper_bound = GetRemoteTimeTicks(5);
+ p.local_upper_bound = GetLocalTimeTicks(6);
+ p.test_time = GetRemoteTimeTicks(3);
+ p.test_delta = RemoteTimeDelta::FromMicroseconds(1);
TestResults results = RunTest(p);
- EXPECT_EQ(3, results.result_time);
- EXPECT_EQ(1, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(3), results.result_time);
+ EXPECT_EQ(LocalTimeDelta::FromMicroseconds(1), results.result_delta);
EXPECT_EQ(0, results.skew);
}
@@ -90,15 +85,15 @@ TEST(InterProcessTimeTicksConverterTest, OffsetMidpoints) {
// All times are monotonic, but not centered. Adjust the |remote_*| times so
// they are centered within the |local_*| times.
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 3;
- p.remote_upper_bound = 6;
- p.local_upper_bound = 6;
- p.test_time = 4;
- p.test_delta = 1;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(3);
+ p.remote_upper_bound = GetRemoteTimeTicks(6);
+ p.local_upper_bound = GetLocalTimeTicks(6);
+ p.test_time = GetRemoteTimeTicks(4);
+ p.test_delta = RemoteTimeDelta::FromMicroseconds(1);
TestResults results = RunTest(p);
- EXPECT_EQ(3, results.result_time);
- EXPECT_EQ(1, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(3), results.result_time);
+ EXPECT_EQ(LocalTimeDelta::FromMicroseconds(1), results.result_delta);
EXPECT_EQ(1, results.skew);
}
@@ -109,15 +104,15 @@ TEST(InterProcessTimeTicksConverterTest, DoubleEndedSkew) {
// doesn't change. The ratio of local time to network time is 1:2, so we scale
// |test_delta| to half.
TestParams p;
- p.local_lower_bound = 3;
- p.remote_lower_bound = 1;
- p.remote_upper_bound = 9;
- p.local_upper_bound = 7;
- p.test_time = 5;
- p.test_delta = 2;
+ p.local_lower_bound = GetLocalTimeTicks(3);
+ p.remote_lower_bound = GetRemoteTimeTicks(1);
+ p.remote_upper_bound = GetRemoteTimeTicks(9);
+ p.local_upper_bound = GetLocalTimeTicks(7);
+ p.test_time = GetRemoteTimeTicks(5);
+ p.test_delta = RemoteTimeDelta::FromMicroseconds(2);
TestResults results = RunTest(p);
- EXPECT_EQ(5, results.result_time);
- EXPECT_EQ(1, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(5), results.result_time);
+ EXPECT_EQ(LocalTimeDelta::FromMicroseconds(1), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, FrontEndSkew) {
@@ -126,30 +121,30 @@ TEST(InterProcessTimeTicksConverterTest, FrontEndSkew) {
// but since we use integers, the numbers truncate from 3.33 to 3 and 1.33
// to 1.
TestParams p;
- p.local_lower_bound = 3;
- p.remote_lower_bound = 1;
- p.remote_upper_bound = 7;
- p.local_upper_bound = 7;
- p.test_time = 3;
- p.test_delta = 2;
+ p.local_lower_bound = GetLocalTimeTicks(3);
+ p.remote_lower_bound = GetRemoteTimeTicks(1);
+ p.remote_upper_bound = GetRemoteTimeTicks(7);
+ p.local_upper_bound = GetLocalTimeTicks(7);
+ p.test_time = GetRemoteTimeTicks(3);
+ p.test_delta = RemoteTimeDelta::FromMicroseconds(2);
TestResults results = RunTest(p);
- EXPECT_EQ(4, results.result_time);
- EXPECT_EQ(1, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(4), results.result_time);
+ EXPECT_EQ(LocalTimeDelta::FromMicroseconds(1), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, BackEndSkew) {
// Like the previous test, but |remote_lower_bound| is coherent and
// |remote_upper_bound| is skewed.
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 1;
- p.remote_upper_bound = 7;
- p.local_upper_bound = 5;
- p.test_time = 3;
- p.test_delta = 2;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(1);
+ p.remote_upper_bound = GetRemoteTimeTicks(7);
+ p.local_upper_bound = GetLocalTimeTicks(5);
+ p.test_time = GetRemoteTimeTicks(3);
+ p.test_delta = RemoteTimeDelta::FromMicroseconds(2);
TestResults results = RunTest(p);
- EXPECT_EQ(2, results.result_time);
- EXPECT_EQ(1, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(2), results.result_time);
+ EXPECT_EQ(LocalTimeDelta::FromMicroseconds(1), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, Instantaneous) {
@@ -157,15 +152,15 @@ TEST(InterProcessTimeTicksConverterTest, Instantaneous) {
// |remote_upper_bound| have the same value. No adjustments should be made and
// no divide-by-zero errors should occur.
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 2;
- p.remote_upper_bound = 2;
- p.local_upper_bound = 3;
- p.test_time = 2;
- p.test_delta = 0;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(2);
+ p.remote_upper_bound = GetRemoteTimeTicks(2);
+ p.local_upper_bound = GetLocalTimeTicks(3);
+ p.test_time = GetRemoteTimeTicks(2);
+ p.test_delta = RemoteTimeDelta();
TestResults results = RunTest(p);
- EXPECT_EQ(2, results.result_time);
- EXPECT_EQ(0, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(2), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, OffsetInstantaneous) {
@@ -174,15 +169,15 @@ TEST(InterProcessTimeTicksConverterTest, OffsetInstantaneous) {
// of |local_lower_bound| and |local_upper_bound|. An offset should be applied
// to make the midpoints line up.
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 3;
- p.remote_upper_bound = 3;
- p.local_upper_bound = 3;
- p.test_time = 3;
- p.test_delta = 0;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(3);
+ p.remote_upper_bound = GetRemoteTimeTicks(3);
+ p.local_upper_bound = GetLocalTimeTicks(3);
+ p.test_time = GetRemoteTimeTicks(3);
+ p.test_delta = RemoteTimeDelta();
TestResults results = RunTest(p);
- EXPECT_EQ(2, results.result_time);
- EXPECT_EQ(0, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(2), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, DisjointInstantaneous) {
@@ -191,15 +186,15 @@ TEST(InterProcessTimeTicksConverterTest, DisjointInstantaneous) {
// local_upper_bound]. So, all of the values should be adjusted so they are
// exactly that value.
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 2;
- p.remote_upper_bound = 2;
- p.local_upper_bound = 1;
- p.test_time = 2;
- p.test_delta = 0;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(2);
+ p.remote_upper_bound = GetRemoteTimeTicks(2);
+ p.local_upper_bound = GetLocalTimeTicks(1);
+ p.test_time = GetRemoteTimeTicks(2);
+ p.test_delta = RemoteTimeDelta();
TestResults results = RunTest(p);
- EXPECT_EQ(1, results.result_time);
- EXPECT_EQ(0, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(1), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, RoundingNearEdges) {
@@ -209,37 +204,69 @@ TEST(InterProcessTimeTicksConverterTest, RoundingNearEdges) {
for (int i = 1; i < kMaxRange; ++i) {
for (int j = 1; j < kMaxRange; ++j) {
TestParams p;
- p.local_lower_bound = 1;
- p.remote_lower_bound = 1;
- p.remote_upper_bound = j;
- p.local_upper_bound = i;
+ p.local_lower_bound = GetLocalTimeTicks(1);
+ p.remote_lower_bound = GetRemoteTimeTicks(1);
+ p.remote_upper_bound = GetRemoteTimeTicks(j);
+ p.local_upper_bound = GetLocalTimeTicks(i);
- p.test_time = 1;
- p.test_delta = 0;
+ p.test_time = GetRemoteTimeTicks(1);
+ p.test_delta = RemoteTimeDelta();
TestResults results = RunTest(p);
- EXPECT_LE(1, results.result_time);
- EXPECT_EQ(0, results.result_delta);
+ EXPECT_LE(GetLocalTimeTicks(1), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
- p.test_time = j;
- p.test_delta = j - 1;
+ p.test_time = GetRemoteTimeTicks(j);
+ p.test_delta = RemoteTimeDelta::FromMicroseconds(j - 1);
results = RunTest(p);
- EXPECT_GE(i, results.result_time);
- EXPECT_GE(i - 1, results.result_delta);
+ EXPECT_LE(results.result_time, GetLocalTimeTicks(i));
+ EXPECT_LE(results.result_delta, LocalTimeDelta::FromMicroseconds(i - 1));
}
}
}
TEST(InterProcessTimeTicksConverterTest, DisjointRanges) {
TestParams p;
- p.local_lower_bound = 10;
- p.remote_lower_bound = 30;
- p.remote_upper_bound = 41;
- p.local_upper_bound = 20;
- p.test_time = 41;
- p.test_delta = 0;
+ p.local_lower_bound = GetLocalTimeTicks(10);
+ p.remote_lower_bound = GetRemoteTimeTicks(30);
+ p.remote_upper_bound = GetRemoteTimeTicks(41);
+ p.local_upper_bound = GetLocalTimeTicks(20);
+ p.test_time = GetRemoteTimeTicks(41);
+ p.test_delta = RemoteTimeDelta();
+ TestResults results = RunTest(p);
+ EXPECT_EQ(GetLocalTimeTicks(20), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
+}
+
+TEST(InterProcessTimeTicksConverterTest, LargeValue_LocalIsLargetThanRemote) {
+ constexpr auto kWeek = base::TimeTicks::kMicrosecondsPerWeek;
+ constexpr auto kHour = base::TimeTicks::kMicrosecondsPerHour;
+ TestParams p;
+ p.local_lower_bound = GetLocalTimeTicks(4 * kWeek);
+ p.remote_lower_bound = GetRemoteTimeTicks(4 * kWeek + 2 * kHour);
+ p.remote_upper_bound = GetRemoteTimeTicks(4 * kWeek + 4 * kHour);
+ p.local_upper_bound = GetLocalTimeTicks(4 * kWeek + 8 * kHour);
+
+ p.test_time = GetRemoteTimeTicks(4 * kWeek + 3 * kHour);
+ p.test_delta = RemoteTimeDelta();
+ TestResults results = RunTest(p);
+ EXPECT_EQ(GetLocalTimeTicks(4 * kWeek + 4 * kHour), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
+}
+
+TEST(InterProcessTimeTicksConverterTest, LargeValue_RemoteIsLargetThanLocal) {
+ constexpr auto kWeek = base::TimeTicks::kMicrosecondsPerWeek;
+ constexpr auto kHour = base::TimeTicks::kMicrosecondsPerHour;
+ TestParams p;
+ p.local_lower_bound = GetLocalTimeTicks(4 * kWeek);
+ p.remote_lower_bound = GetRemoteTimeTicks(5 * kWeek);
+ p.remote_upper_bound = GetRemoteTimeTicks(5 * kWeek + 2 * kHour);
+ p.local_upper_bound = GetLocalTimeTicks(4 * kWeek + kHour);
+
+ p.test_time = GetRemoteTimeTicks(5 * kWeek + kHour);
+ p.test_delta = RemoteTimeDelta();
TestResults results = RunTest(p);
- EXPECT_EQ(20, results.result_time);
- EXPECT_EQ(0, results.result_delta);
+ EXPECT_EQ(GetLocalTimeTicks(4 * kWeek + kHour / 2), results.result_time);
+ EXPECT_EQ(LocalTimeDelta(), results.result_delta);
}
TEST(InterProcessTimeTicksConverterTest, ValuesOutsideOfRange) {
diff --git a/chromium/content/common/manifest_share_target_util_unittest.cc b/chromium/content/common/manifest_share_target_util_unittest.cc
deleted file mode 100644
index edfc6767ea7..00000000000
--- a/chromium/content/common/manifest_share_target_util_unittest.cc
+++ /dev/null
@@ -1,266 +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 <map>
-#include <utility>
-
-#include "content/public/common/manifest_share_target_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace content {
-namespace {
-
-constexpr char kTitle[] = "My title";
-constexpr char kText[] = "My text";
-constexpr char kUrlSpec[] = "https://www.google.com/";
-
-} // namespace
-
-TEST(ManifestShareTargetUtilTest, ReplaceUrlPlaceholdersInvalidTemplate) {
- // Badly nested placeholders.
- GURL url_template = GURL("http://example.com/?q={");
- EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_FALSE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- url_template = GURL("http://example.com/?q={title");
- EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_FALSE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- url_template = GURL("http://example.com/?q={title{text}}");
- EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_FALSE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- url_template = GURL("http://example.com/?q={title{}");
- EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_FALSE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- url_template = GURL("http://example.com/?q={{title}}");
- EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_FALSE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- // Placeholder with non-identifier character.
- url_template = GURL("http://example.com/?q={title?}");
- EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_FALSE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- // Placeholder with digit character.
- url_template = GURL("http://example.com/?q={title1}");
- EXPECT_TRUE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_TRUE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- // Empty placeholder.
- url_template = GURL("http://example.com/?q={}");
- EXPECT_TRUE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_TRUE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- // Invalid placeholder in URL fragment.
- url_template = GURL("http://example.com/#{title?}");
- EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_FALSE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- // { in path.
- url_template = GURL("http://example.com/subpath{/");
- EXPECT_TRUE(ValidateWebShareUrlTemplate(url_template));
- EXPECT_TRUE(
- ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
-
- // Invalid placeholder. Non-empty title, text, share URL and non-empty output
- // parameter.
- GURL url_template_filled;
- url_template = GURL("http://example.com/?q={");
- EXPECT_FALSE(ReplaceWebShareUrlPlaceholders(url_template, "text", "title",
- GURL("http://www.google.com"),
- &url_template_filled));
-}
-
-TEST(ManifestShareTargetUtilTest, ReplaceWebShareUrlPlaceholders) {
- const GURL kUrl(kUrlSpec);
-
- // No placeholders.
- GURL url_template = GURL("http://example.com/?q=a#a");
- GURL url_template_filled;
- bool succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText,
- kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ(url_template, url_template_filled);
-
- // One title placeholder.
- url_template = GURL("http://example.com/#{title}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#My%20title", url_template_filled.spec());
-
- // One text placeholder.
- url_template = GURL("http://example.com/#{text}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#My%20text", url_template_filled.spec());
-
- // One url placeholder.
- url_template = GURL("http://example.com/#{url}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#https%3A%2F%2Fwww.google.com%2F",
- url_template_filled.spec());
-
- // One of each placeholder, in title, text, url order.
- url_template = GURL("http://example.com/#{title}{text}{url}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ(
- "http://example.com/#My%20titleMy%20texthttps%3A%2F%2Fwww.google.com%2F",
- url_template_filled.spec());
-
- // One of each placeholder, in url, text, title order.
- url_template = GURL("http://example.com/#{url}{text}{title}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ(
- "http://example.com/#https%3A%2F%2Fwww.google.com%2FMy%20textMy%20title",
- url_template_filled.spec());
-
- // Two of each placeholder, some next to each other, others not.
- url_template =
- GURL("http://example.com/#{title}{url}{text}{text}{title}{url}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ(
- "http://example.com/"
- "#My%20titlehttps%3A%2F%2Fwww.google.com%2FMy%20textMy%20textMy%"
- "20titlehttps%3A%2F%2Fwww.google.com%2F",
- url_template_filled.spec());
-
- // Placeholders are in a query string, as values. The expected use case.
- // Two of each placeholder, some next to each other, others not.
- url_template = GURL(
- "http://example.com?title={title}&url={url}&text={text}&text={text}&"
- "title={title}&url={url}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ(
- "http://"
- "example.com/?title=My%20title&url=https%3A%2F%2Fwww.google.com%2F&"
- "text=My%20text&"
- "text=My%20text&title=My%20title&url=https%3A%2F%2Fwww.google.com%2F",
- url_template_filled.spec());
-
- // Empty placeholder.
- url_template = GURL("http://example.com/#{}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#", url_template_filled.spec());
-
- // Unexpected placeholders.
- url_template = GURL("http://example.com/#{nonexistentplaceholder}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#", url_template_filled.spec());
-
- // Placeholders should only be replaced in query and fragment.
- url_template = GURL("http://example.com/subpath{title}/?q={title}#{title}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/subpath%7Btitle%7D/?q=My%20title#My%20title",
- url_template_filled.spec());
-
- // Braces in the path, which would be invalid, but should parse fine as they
- // are escaped.
- url_template = GURL("http://example.com/subpath{/?q={title}");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/subpath%7B/?q=My%20title",
- url_template_filled.spec());
-
- // |url_template| with % escapes.
- url_template = GURL("http://example.com#%20{title}%20");
- succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
- &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#%20My%20title%20", url_template_filled.spec());
-}
-
-// Test URL escaping done by ReplaceWebShareUrlPlaceholders().
-TEST(ManifestShareTargetUtilTest, ReplaceWebShareUrlPlaceholders_Escaping) {
- const GURL kUrl(kUrlSpec);
- const GURL kUrlTemplate("http://example.com/#{title}");
-
- // Share data that contains percent escapes.
- GURL url_template_filled;
- bool succeeded = ReplaceWebShareUrlPlaceholders(
- kUrlTemplate, "My%20title", kText, kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#My%2520title", url_template_filled.spec());
-
- // Share data that contains placeholders. These should not be replaced.
- succeeded = ReplaceWebShareUrlPlaceholders(kUrlTemplate, "{title}", kText,
- kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#%7Btitle%7D", url_template_filled.spec());
-
- // All characters that shouldn't be escaped.
- succeeded = ReplaceWebShareUrlPlaceholders(kUrlTemplate,
- "-_.!~*'()0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz",
- kText, kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ(
- "http://example.com/#-_.!~*'()0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz",
- url_template_filled.spec());
-
- // All characters that should be escaped.
- succeeded =
- ReplaceWebShareUrlPlaceholders(kUrlTemplate, " \"#$%&+,/:;<=>?@[\\]^`{|}",
- kText, kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ(
- "http://example.com/"
- "#%20%22%23%24%25%26%2B%2C%2F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%60%7B%7C%"
- "7D",
- url_template_filled.spec());
-
- // Unicode chars.
- // U+263B
- succeeded = ReplaceWebShareUrlPlaceholders(kUrlTemplate, "\xe2\x98\xbb",
- kText, kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#%E2%98%BB", url_template_filled.spec());
-
- // U+00E9
- succeeded = ReplaceWebShareUrlPlaceholders(kUrlTemplate, "\xc3\xa9", kText,
- kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#%C3%A9", url_template_filled.spec());
-
- // U+1F4A9
- succeeded = ReplaceWebShareUrlPlaceholders(kUrlTemplate, "\xf0\x9f\x92\xa9",
- kText, kUrl, &url_template_filled);
- EXPECT_TRUE(succeeded);
- EXPECT_EQ("http://example.com/#%F0%9F%92%A9", url_template_filled.spec());
-}
-
-} // namespace content
diff --git a/chromium/content/common/media/audio_messages.h b/chromium/content/common/media/audio_messages.h
deleted file mode 100644
index c4c2f3535af..00000000000
--- a/chromium/content/common/media/audio_messages.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_MEDIA_AUDIO_MESSAGES_H_
-#define CONTENT_COMMON_MEDIA_AUDIO_MESSAGES_H_
-
-// IPC messages for the audio.
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/memory/shared_memory.h"
-#include "base/sync_socket.h"
-#include "content/common/content_export.h"
-#include "ipc/ipc_message_macros.h"
-#include "media/audio/audio_input_ipc.h"
-#include "media/audio/audio_output_ipc.h"
-#include "media/base/ipc/media_param_traits.h"
-#include "media/base/ipc/media_param_traits_macros.h"
-#include "media/gpu/ipc/common/media_param_traits.h"
-#include "url/origin.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START AudioMsgStart
-
-IPC_STRUCT_BEGIN(AudioInputHostMsg_CreateStream_Config)
- IPC_STRUCT_MEMBER(media::AudioParameters, params)
- IPC_STRUCT_MEMBER(bool, automatic_gain_control)
- IPC_STRUCT_MEMBER(uint32_t, shared_memory_count)
-IPC_STRUCT_END()
-
-// Messages sent from the browser to the renderer.
-
-// Tell the renderer process that an audio output device has been authorized
-// for a given stream. The renderer is given the output parameters for the
-// authorized device.
-IPC_MESSAGE_CONTROL4(AudioMsg_NotifyDeviceAuthorized,
- int /* stream id */,
- media::OutputDeviceStatus /* device_status */,
- media::AudioParameters /* output parameters */,
- std::string /* matched_device_id */)
-
-// Tell the renderer process that an audio stream has been created.
-// The renderer process is given a shared memory handle for the audio data
-// buffer it shares with the browser process. It is also given a SyncSocket that
-// it uses to communicate with the browser process about the state of the
-// buffered audio data.
-IPC_MESSAGE_CONTROL(AudioMsg_NotifyStreamCreated,
- int /* stream id */,
- base::SharedMemoryHandle /* handle */,
- base::SyncSocket::TransitDescriptor /* socket descriptor */)
-
-// Tell the renderer process that an audio input stream has been created.
-// The renderer process would be given a SyncSocket that it should read from
-// from then on. It is also given whether the stream initially is muted.
-IPC_MESSAGE_CONTROL(AudioInputMsg_NotifyStreamCreated,
- int /* stream id */,
- base::SharedMemoryHandle /* handle */,
- base::SyncSocket::TransitDescriptor /* socket descriptor */,
- bool /* initially muted */)
-
-// Notification message sent from AudioRendererHost to renderer for state
-// update on error.
-IPC_MESSAGE_CONTROL1(AudioMsg_NotifyStreamError, int /* stream id */)
-
-// Notification message sent from browser to renderer for state update.
-IPC_MESSAGE_CONTROL1(AudioInputMsg_NotifyStreamError, int /* stream id */)
-
-// Notification message sent from browser to renderer when stream mutes or
-// unmutes.
-IPC_MESSAGE_CONTROL2(AudioInputMsg_NotifyStreamMuted,
- int /* stream id */,
- bool /* is muted? */)
-
-// Messages sent from the renderer to the browser.
-
-// Message sent to the browser to request the use of an audio output
-// device. |render_frame_id| is the routing ID for the RenderFrame producing
-// the audio data.
-IPC_MESSAGE_CONTROL5(AudioHostMsg_RequestDeviceAuthorization,
- int /* stream_id */,
- int /* render_frame_id */,
- int /* session_id */,
- std::string /* device_id */,
- url::Origin /* security_origin */)
-
-// Request that is sent to the browser for creating an audio output stream.
-IPC_MESSAGE_CONTROL3(AudioHostMsg_CreateStream,
- int /* stream_id */,
- int /* render_frame_id */,
- media::AudioParameters /* params */)
-
-// Request that is sent to the browser for creating an audio input stream.
-// |render_frame_id| is the routing ID for the RenderFrame consuming the audio
-// data.
-IPC_MESSAGE_CONTROL4(AudioInputHostMsg_CreateStream,
- int /* stream_id */,
- int /* render_frame_id */,
- int /* session_id */,
- AudioInputHostMsg_CreateStream_Config)
-
-// Start buffering and play the audio stream specified by stream_id.
-IPC_MESSAGE_CONTROL1(AudioHostMsg_PlayStream,
- int /* stream_id */)
-
-// Start recording the audio input stream specified by stream_id.
-IPC_MESSAGE_CONTROL1(AudioInputHostMsg_RecordStream,
- int /* stream_id */)
-
-// Pause the audio stream specified by stream_id.
-IPC_MESSAGE_CONTROL1(AudioHostMsg_PauseStream,
- int /* stream_id */)
-
-// Close an audio stream specified by stream_id.
-IPC_MESSAGE_CONTROL1(AudioHostMsg_CloseStream,
- int /* stream_id */)
-
-// Close an audio input stream specified by stream_id.
-IPC_MESSAGE_CONTROL1(AudioInputHostMsg_CloseStream,
- int /* stream_id */)
-
-// Set audio volume of the stream specified by stream_id.
-// TODO(hclam): change this to vector if we have channel numbers other than 2.
-IPC_MESSAGE_CONTROL2(AudioHostMsg_SetVolume,
- int /* stream_id */,
- double /* volume */)
-
-// Set audio volume of the input stream specified by stream_id.
-IPC_MESSAGE_CONTROL2(AudioInputHostMsg_SetVolume,
- int /* stream_id */,
- double /* volume */)
-
-#endif // CONTENT_COMMON_MEDIA_AUDIO_MESSAGES_H_
diff --git a/chromium/content/common/media/cdm_info.cc b/chromium/content/common/media/cdm_info.cc
index 12b98dc56d1..4e3dbbc1e71 100644
--- a/chromium/content/common/media/cdm_info.cc
+++ b/chromium/content/common/media/cdm_info.cc
@@ -9,15 +9,17 @@
namespace content {
-CdmInfo::CdmInfo(const std::string& name,
- const std::string& guid,
- const base::Version& version,
- const base::FilePath& path,
- const std::string& file_system_id,
- const std::vector<media::VideoCodec>& supported_video_codecs,
- bool supports_persistent_license,
- const std::string& supported_key_system,
- bool supports_sub_key_systems)
+CdmInfo::CdmInfo(
+ const std::string& name,
+ const std::string& guid,
+ const base::Version& version,
+ const base::FilePath& path,
+ const std::string& file_system_id,
+ const std::vector<media::VideoCodec>& supported_video_codecs,
+ bool supports_persistent_license,
+ const base::flat_set<media::EncryptionMode>& supported_encryption_schemes,
+ const std::string& supported_key_system,
+ bool supports_sub_key_systems)
: name(name),
guid(guid),
version(version),
@@ -25,13 +27,15 @@ CdmInfo::CdmInfo(const std::string& name,
file_system_id(file_system_id),
supported_video_codecs(supported_video_codecs),
supports_persistent_license(supports_persistent_license),
+ supported_encryption_schemes(supported_encryption_schemes),
supported_key_system(supported_key_system),
supports_sub_key_systems(supports_sub_key_systems) {
DCHECK(base::IsValidGUID(guid));
+ DCHECK(!supported_encryption_schemes.empty());
}
CdmInfo::CdmInfo(const CdmInfo& other) = default;
-CdmInfo::~CdmInfo() {}
+CdmInfo::~CdmInfo() = default;
} // namespace content
diff --git a/chromium/content/common/media/media_devices.cc b/chromium/content/common/media/media_devices.cc
index 90488d037ad..b2ed9e4e016 100644
--- a/chromium/content/common/media/media_devices.cc
+++ b/chromium/content/common/media/media_devices.cc
@@ -17,11 +17,12 @@ MediaDeviceInfo::MediaDeviceInfo(MediaDeviceInfo&& other) = default;
MediaDeviceInfo::MediaDeviceInfo(const std::string& device_id,
const std::string& label,
- const std::string& group_id)
+ const std::string& group_id,
+ media::VideoFacingMode video_facing)
: device_id(device_id),
label(label),
group_id(group_id),
- video_facing(media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE) {}
+ video_facing(video_facing) {}
MediaDeviceInfo::MediaDeviceInfo(
const media::AudioDeviceDescription& device_description)
@@ -44,9 +45,11 @@ MediaDeviceInfo& MediaDeviceInfo::operator=(const MediaDeviceInfo& other) =
MediaDeviceInfo& MediaDeviceInfo::operator=(MediaDeviceInfo&& other) = default;
bool operator==(const MediaDeviceInfo& first, const MediaDeviceInfo& second) {
- return first.device_id == second.device_id && first.label == second.label &&
- first.group_id == second.group_id &&
- first.video_facing == second.video_facing;
+ // Do not use the |group_id| and |video_facing| fields for equality comparison
+ // since they are currently not fully supported by the video-capture layer.
+ // The modification of those fields by heuristics in upper layers does not
+ // result in a different device.
+ return first.device_id == second.device_id && first.label == second.label;
}
} // namespace content
diff --git a/chromium/content/common/media/media_devices.h b/chromium/content/common/media/media_devices.h
index c0cd354d258..0e3de71288f 100644
--- a/chromium/content/common/media/media_devices.h
+++ b/chromium/content/common/media/media_devices.h
@@ -14,7 +14,7 @@
namespace media {
struct AudioDeviceDescription;
struct VideoCaptureDeviceDescriptor;
-}
+} // namespace media
namespace content {
@@ -29,9 +29,11 @@ struct CONTENT_EXPORT MediaDeviceInfo {
MediaDeviceInfo();
MediaDeviceInfo(const MediaDeviceInfo& other);
MediaDeviceInfo(MediaDeviceInfo&& other);
- MediaDeviceInfo(const std::string& device_id,
- const std::string& label,
- const std::string& group_id);
+ MediaDeviceInfo(
+ const std::string& device_id,
+ const std::string& label,
+ const std::string& group_id,
+ media::VideoFacingMode video_facing = media::MEDIA_VIDEO_FACING_NONE);
explicit MediaDeviceInfo(const media::AudioDeviceDescription& description);
explicit MediaDeviceInfo(
const media::VideoCaptureDeviceDescriptor& descriptor);
diff --git a/chromium/content/common/media/media_player_delegate_messages.h b/chromium/content/common/media/media_player_delegate_messages.h
index 7fd75b9430d..451ecbd4fbb 100644
--- a/chromium/content/common/media/media_player_delegate_messages.h
+++ b/chromium/content/common/media/media_player_delegate_messages.h
@@ -13,6 +13,7 @@
#include <stdint.h>
+#include "components/viz/common/surfaces/surface_id.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#include "media/base/media_content_type.h"
@@ -55,6 +56,26 @@ IPC_MESSAGE_ROUTED2(MediaPlayerDelegateMsg_BecamePersistentVideo,
int /* delegate_id, distinguishes instances */,
double /* is_persistent */)
+IPC_MESSAGE_ROUTED1(MediaPlayerDelegateMsg_EndPictureInPictureMode,
+ int /* delegate_id, distinguishes instances */)
+
+IPC_MESSAGE_ROUTED2(MediaPlayerDelegateMsg_OnPictureInPictureWindowResize,
+ int /* delegate_id, distinguishes instances */,
+ gfx::Size /* window_size */)
+
+// ----------------------------------------------------------------------------
+// Messages from the browser to the renderer acknowledging changes happened.
+// ----------------------------------------------------------------------------
+
+IPC_MESSAGE_ROUTED3(MediaPlayerDelegateMsg_OnPictureInPictureModeStarted_ACK,
+ int /* delegate id */,
+ int /* request_id */,
+ gfx::Size /* window_size */)
+
+IPC_MESSAGE_ROUTED2(MediaPlayerDelegateMsg_OnPictureInPictureModeEnded_ACK,
+ int /* delegate id */,
+ int /* request_id */)
+
// ----------------------------------------------------------------------------
// Messages from the renderer notifying the browser of playback state changes.
// ----------------------------------------------------------------------------
@@ -86,10 +107,19 @@ IPC_MESSAGE_ROUTED2(MediaPlayerDelegateHostMsg_OnMediaSizeChanged,
int /* delegate_id, distinguishes instances */,
gfx::Size /* new size of video */)
-IPC_MESSAGE_ROUTED1(MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged,
- int /* delegate id */)
+IPC_MESSAGE_ROUTED4(MediaPlayerDelegateHostMsg_OnPictureInPictureModeStarted,
+ int /* delegate id */,
+ viz::SurfaceId /* surface_id */,
+ gfx::Size /* natural_size */,
+ int /* request_id */)
+
+IPC_MESSAGE_ROUTED2(MediaPlayerDelegateHostMsg_OnPictureInPictureModeEnded,
+ int /* delegate id */,
+ int /* request_id */)
-IPC_MESSAGE_ROUTED1(MediaPlayerDelegateHostMsg_OnPictureInPictureModeEnded,
- int /* delegate id */)
+IPC_MESSAGE_ROUTED3(MediaPlayerDelegateHostMsg_OnPictureInPictureSurfaceChanged,
+ int /* delegate id */,
+ viz::SurfaceId /* surface_id */,
+ gfx::Size /* natural_size */)
#endif // CONTENT_COMMON_MEDIA_MEDIA_PLAYER_DELEGATE_MESSAGES_H_
diff --git a/chromium/content/common/media/media_stream_param_traits.h b/chromium/content/common/media/media_stream_param_traits.h
index 146f5ceca9f..3b58a31792e 100644
--- a/chromium/content/common/media/media_stream_param_traits.h
+++ b/chromium/content/common/media/media_stream_param_traits.h
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// IPC messages for the media streaming.
-// Multiply-included message file, hence no include guard.
+// no-include-guard-because-multiply-included
#include "content/common/content_export.h"
#include "content/public/common/media_stream_request.h"
@@ -23,6 +23,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(media::VideoFacingMode,
IPC_STRUCT_TRAITS_BEGIN(content::MediaStreamDevice)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(id)
+ IPC_STRUCT_TRAITS_MEMBER(group_id)
IPC_STRUCT_TRAITS_MEMBER(video_facing)
IPC_STRUCT_TRAITS_MEMBER(matched_output_device_id)
IPC_STRUCT_TRAITS_MEMBER(name)
diff --git a/chromium/content/common/media/renderer_audio_input_stream_factory.mojom b/chromium/content/common/media/renderer_audio_input_stream_factory.mojom
index 01a060ff526..63594e29fa6 100644
--- a/chromium/content/common/media/renderer_audio_input_stream_factory.mojom
+++ b/chromium/content/common/media/renderer_audio_input_stream_factory.mojom
@@ -8,6 +8,7 @@ import "media/mojo/interfaces/audio_data_pipe.mojom";
import "media/mojo/interfaces/audio_input_stream.mojom";
import "media/mojo/interfaces/audio_parameters.mojom";
import "media/mojo/interfaces/media_types.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
// This interface is used by the renderer to ask the browser to create input
// streams. The renderer supplies the desired audio parameters, and a client
@@ -20,11 +21,22 @@ interface RendererAudioInputStreamFactory {
media.mojom.AudioParameters params,
bool automatic_gain_control,
uint32 shared_memory_count);
+
+ // Associates an output device with an input stream, so that the input knows
+ // which output device to cancel echo from. |input_stream_id| is the id
+ // returned when the stream was created. |output_device_id| is a device
+ // id HMAC. In case either of the parameters are invalid, the operation will
+ // silently fail.
+ AssociateInputAndOutputForAec(
+ mojo_base.mojom.UnguessableToken input_stream_id,
+ string output_device_id);
};
interface RendererAudioInputStreamFactoryClient {
// Called when a stream has been created. Will only be called once for every
- // CreateStream call.
+ // CreateStream call. |stream_id| is a handle used to refer to the stream,
+ // specifically to be able to associate it with an output device for echo
+ // cancellation. Loopback streams don't have ids.
// TODO(crbug.com/787806): There are plans to allow this function to be called
// serveral times in the future. If the stream is terminated e.g. due to the
// process hosting it crashing, this function should be called again with a
@@ -33,5 +45,6 @@ interface RendererAudioInputStreamFactoryClient {
media.mojom.AudioInputStream stream,
media.mojom.AudioInputStreamClient& client_request,
media.mojom.AudioDataPipe data_pipe,
- bool initially_muted);
+ bool initially_muted,
+ mojo_base.mojom.UnguessableToken? stream_id);
};
diff --git a/chromium/content/common/native_types.mojom b/chromium/content/common/native_types.mojom
index 59aa3bf9d0f..08151055452 100644
--- a/chromium/content/common/native_types.mojom
+++ b/chromium/content/common/native_types.mojom
@@ -18,7 +18,7 @@ struct FrameReplicationState;
struct RendererPreferences;
[Native]
-struct ResizeParams;
+struct VisualProperties;
// NOTE: This type is only mapped and usable on Mac.
[Native]
diff --git a/chromium/content/common/native_types.typemap b/chromium/content/common/native_types.typemap
index 780ba7aa63b..35e7fbb50f7 100644
--- a/chromium/content/common/native_types.typemap
+++ b/chromium/content/common/native_types.typemap
@@ -8,8 +8,8 @@ public_headers = [
"//content/common/edit_command.h",
"//content/common/frame_owner_properties.h",
"//content/common/frame_replication_state.h",
- "//content/common/resize_params.h",
"//content/common/input/input_event.h",
+ "//content/common/visual_properties.h",
"//content/public/common/input_event_ack_source.h",
"//content/public/common/input_event_ack_state.h",
"//content/common/input/synthetic_pinch_gesture_params.h",
@@ -46,7 +46,6 @@ public_deps = [
# includes from //content/common and //content/public/common, this isn't a
# transitive allowance, so those targets' own public_deps aren't included in
# the set of implied dependencies.
- "//cc/ipc",
"//content/common:buildflags",
"//media",
"//media/base/ipc",
@@ -78,7 +77,7 @@ type_mappings = [
"content.mojom.DidOverscrollParams=ui::DidOverscrollParams",
"content.mojom.PointerType=blink::WebPointerProperties::PointerType",
"content.mojom.RendererPreferences=content::RendererPreferences",
- "content.mojom.ResizeParams=content::ResizeParams",
+ "content.mojom.VisualProperties=content::VisualProperties",
"content.mojom.ScrollUnits=blink::WebGestureEvent::ScrollUnits",
"content.mojom.SyntheticSmoothDrag=content::SyntheticSmoothDragGestureParams",
"content.mojom.SyntheticSmoothScroll=content::SyntheticSmoothScrollGestureParams",
diff --git a/chromium/content/common/native_types_mac.typemap b/chromium/content/common/native_types_mac.typemap
index c162fc14e21..c35085535e7 100644
--- a/chromium/content/common/native_types_mac.typemap
+++ b/chromium/content/common/native_types_mac.typemap
@@ -16,7 +16,6 @@ deps = [
# includes from //content/common and //content/public/common, this isn't a
# transitive allowance, so those targets' own public_deps aren't included in
# the set of implied dependencies.
- "//cc/ipc",
"//media",
"//media/base/ipc",
"//net",
diff --git a/chromium/content/common/navigation_params.cc b/chromium/content/common/navigation_params.cc
index 6d18f9fefd8..e11e92e86c9 100644
--- a/chromium/content/common/navigation_params.cc
+++ b/chromium/content/common/navigation_params.cc
@@ -45,7 +45,8 @@ CommonNavigationParams::CommonNavigationParams(
CSPDisposition should_check_main_world_csp,
bool started_from_context_menu,
bool has_user_gesture,
- const base::Optional<std::string>& suggested_filename)
+ const std::vector<ContentSecurityPolicy>& initiator_csp,
+ const base::Optional<CSPSource>& initiator_self_source)
: url(url),
referrer(referrer),
transition(transition),
@@ -64,7 +65,8 @@ CommonNavigationParams::CommonNavigationParams(
should_check_main_world_csp(should_check_main_world_csp),
started_from_context_menu(started_from_context_menu),
has_user_gesture(has_user_gesture),
- suggested_filename(suggested_filename) {
+ initiator_csp(initiator_csp),
+ initiator_self_source(initiator_self_source) {
// |method != "POST"| should imply absence of |post_data|.
if (method != "POST" && post_data) {
NOTREACHED();
diff --git a/chromium/content/common/navigation_params.h b/chromium/content/common/navigation_params.h
index 806969a8e25..e571195b1cb 100644
--- a/chromium/content/common/navigation_params.h
+++ b/chromium/content/common/navigation_params.h
@@ -15,6 +15,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "content/common/content_security_policy/content_security_policy.h"
#include "content/common/content_security_policy/csp_disposition_enum.h"
#include "content/common/frame_message_enums.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -25,6 +26,7 @@
#include "content/public/common/request_context_type.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/resource_response_info.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
#include "ui/base/page_transition_types.h"
@@ -76,7 +78,8 @@ struct CONTENT_EXPORT CommonNavigationParams {
CSPDisposition should_check_main_world_csp,
bool started_from_context_menu,
bool has_user_gesture,
- const base::Optional<std::string>& suggested_filename);
+ const std::vector<ContentSecurityPolicy>& initiator_csp,
+ const base::Optional<CSPSource>& initiator_self_source);
CommonNavigationParams(const CommonNavigationParams& other);
~CommonNavigationParams();
@@ -161,10 +164,9 @@ struct CONTENT_EXPORT CommonNavigationParams {
// True if the request was user initiated.
bool has_user_gesture = false;
- // If the navigation started in response to a HTML anchor element with a
- // download attribute, this is the (possible empty) value of the download
- // attribute.
- base::Optional<std::string> suggested_filename;
+ // We require a copy of the relevant CSP to perform navigation checks.
+ std::vector<ContentSecurityPolicy> initiator_csp;
+ base::Optional<CSPSource> initiator_self_source;
};
// Provided by the browser -----------------------------------------------------
@@ -211,7 +213,7 @@ struct CONTENT_EXPORT RequestNavigationParams {
std::vector<GURL> redirects;
// The ResourceResponseInfos received during redirects.
- std::vector<network::ResourceResponseInfo> redirect_response;
+ std::vector<network::ResourceResponseHead> redirect_response;
// PlzNavigate
// The RedirectInfos received during redirects.
diff --git a/chromium/content/common/navigation_subresource_loader_params.cc b/chromium/content/common/navigation_subresource_loader_params.cc
index b465c0f73f8..7c08e6bdda4 100644
--- a/chromium/content/common/navigation_subresource_loader_params.cc
+++ b/chromium/content/common/navigation_subresource_loader_params.cc
@@ -19,6 +19,7 @@ SubresourceLoaderParams& SubresourceLoaderParams::operator=(
loader_factory_info = std::move(other.loader_factory_info);
controller_service_worker_info =
std::move(other.controller_service_worker_info);
+ controller_service_worker_handle = other.controller_service_worker_handle;
return *this;
}
diff --git a/chromium/content/common/navigation_subresource_loader_params.h b/chromium/content/common/navigation_subresource_loader_params.h
index 2ffa1287594..bb3407579f7 100644
--- a/chromium/content/common/navigation_subresource_loader_params.h
+++ b/chromium/content/common/navigation_subresource_loader_params.h
@@ -5,11 +5,14 @@
#ifndef CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
#define CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
+#include "base/memory/weak_ptr.h"
#include "content/common/service_worker/controller_service_worker.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace content {
+class ServiceWorkerHandle;
+
// For NetworkService glues:
// Navigation parameters that are necessary to set-up a subresource loader
// for the frame that is going to be created by the navigation.
@@ -28,7 +31,13 @@ struct CONTENT_EXPORT SubresourceLoaderParams {
// The controller service worker, non-null if the frame is to be
// controlled by the service worker.
+ //
+ // |controller_service_worker_info->object_info| is "incomplete". It must be
+ // updated before being sent over Mojo and then registered with
+ // |controller_service_worker_handle|. See
+ // ServiceWorkerHandle::CreateIncompleteObjectInfo() for details.
mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info;
+ base::WeakPtr<ServiceWorkerHandle> controller_service_worker_handle;
};
} // namespace content
diff --git a/chromium/content/common/notifications/notification_struct_traits.cc b/chromium/content/common/notifications/notification_struct_traits.cc
index 3e639b63f1d..6c8fa6bb2b7 100644
--- a/chromium/content/common/notifications/notification_struct_traits.cc
+++ b/chromium/content/common/notifications/notification_struct_traits.cc
@@ -35,7 +35,7 @@ bool ValidateActions(
bool ValidateData(const std::vector<char>& data) {
return data.size() <=
- content::PlatformNotificationData::kMaximumDeveloperDataSize;
+ blink::mojom::NotificationData::kMaximumDeveloperDataSize;
}
bool ValidateImage(const SkBitmap& image) {
diff --git a/chromium/content/common/origin_trials/OWNERS b/chromium/content/common/origin_trials/OWNERS
deleted file mode 100644
index 47b509bfe3e..00000000000
--- a/chromium/content/common/origin_trials/OWNERS
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file also covers ownership of the following directories:
-# //chrome/common/origin_trials/
-# //content/renderer/origin_trials/
-# //third_party/blink/common/origin_trials/
-# //third_party/blink/public/common/origin_trials/
-# //tools/origin_trials/
-
-chasej@chromium.org
-iclelland@chromium.org
-mek@chromium.org
-
-# TEAM: experimentation-dev@chromium.org
-# COMPONENT: Internals>OriginTrials
diff --git a/chromium/content/common/origin_trials/trial_policy_impl.cc b/chromium/content/common/origin_trials/trial_policy_impl.cc
deleted file mode 100644
index e85ee25b245..00000000000
--- a/chromium/content/common/origin_trials/trial_policy_impl.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2017 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/common/origin_trials/trial_policy_impl.h"
-
-#include "base/feature_list.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/origin_trial_policy.h"
-#include "content/public/common/origin_util.h"
-#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
-
-namespace content {
-
-bool TrialPolicyImpl::IsOriginTrialsSupported() const {
- // In order for the validator to work these are all required.
- return base::FeatureList::IsEnabled(features::kOriginTrials) && policy() &&
- !GetPublicKey().empty();
-}
-base::StringPiece TrialPolicyImpl::GetPublicKey() const {
- return policy()->GetPublicKey();
-}
-bool TrialPolicyImpl::IsFeatureDisabled(base::StringPiece feature) const {
- return policy()->IsFeatureDisabled(feature);
-}
-bool TrialPolicyImpl::IsTokenDisabled(base::StringPiece token_signature) const {
- return policy()->IsTokenDisabled(token_signature);
-}
-bool TrialPolicyImpl::IsOriginSecure(const GURL& url) const {
- return ::content::IsOriginSecure(url);
-}
-
-const OriginTrialPolicy* TrialPolicyImpl::policy() const {
- return GetContentClient()->GetOriginTrialPolicy();
-}
-
-std::unique_ptr<blink::TrialTokenValidator>
-TrialPolicyImpl::CreateValidatorForPolicy() {
- return std::make_unique<blink::TrialTokenValidator>(
- std::make_unique<TrialPolicyImpl>());
-}
-
-} // namespace content
diff --git a/chromium/content/common/origin_trials/trial_policy_impl.h b/chromium/content/common/origin_trials/trial_policy_impl.h
deleted file mode 100644
index 370c5067b31..00000000000
--- a/chromium/content/common/origin_trials/trial_policy_impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 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_COMMON_ORIGIN_TRIALS_TRIAL_POLICY_IMPL_H_
-#define CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_POLICY_IMPL_H_
-
-#include "base/strings/string_piece.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/common/origin_trials/trial_policy.h"
-
-namespace blink {
-class TrialTokenValidator;
-} // namespace blink
-
-namespace content {
-
-class OriginTrialPolicy;
-
-// TrialPolicyImpl is an adaptor to fit the policy provided by the content
-// embedder via ContentClient to the interface allowed by the DEPS rules of
-// third_party/WebKit/public/common
-// TODO(avallee, kinuko): Plumb the the content embedder policy straight through
-// to the users in third_party/WebKit/public/common/origin_trials.
-class CONTENT_EXPORT TrialPolicyImpl : public blink::TrialPolicy {
- public:
- bool IsOriginTrialsSupported() const override;
-
- base::StringPiece GetPublicKey() const override;
- bool IsFeatureDisabled(base::StringPiece feature) const override;
- bool IsTokenDisabled(base::StringPiece token_signature) const override;
- bool IsOriginSecure(const GURL& url) const override;
-
- static std::unique_ptr<blink::TrialTokenValidator> CreateValidatorForPolicy();
-
- private:
- const OriginTrialPolicy* policy() const;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_POLICY_IMPL_H_
diff --git a/chromium/content/common/origin_util.cc b/chromium/content/common/origin_util.cc
index 66516d0fed2..6cac476bd4b 100644
--- a/chromium/content/common/origin_util.cc
+++ b/chromium/content/common/origin_util.cc
@@ -7,6 +7,7 @@
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/stl_util.h"
+#include "base/strings/pattern.h"
#include "content/common/url_schemes.h"
#include "net/base/url_util.h"
#include "url/gurl.h"
@@ -23,6 +24,17 @@ bool IsOriginUnique(const url::Origin& origin) {
base::ContainsValue(url::GetNoAccessSchemes(), origin.scheme());
}
+bool IsWhitelistedSecureOrigin(const url::Origin& origin) {
+ if (base::ContainsValue(content::GetSecureOriginsAndPatterns(),
+ origin.Serialize()))
+ return true;
+ for (const auto& origin_or_pattern : content::GetSecureOriginsAndPatterns()) {
+ if (base::MatchPattern(origin.host(), origin_or_pattern))
+ return true;
+ }
+ return false;
+}
+
} // namespace
namespace content {
@@ -42,10 +54,7 @@ bool IsOriginSecure(const GURL& url) {
if (base::ContainsValue(url::GetSecureSchemes(), url.scheme()))
return true;
- if (base::ContainsValue(GetSecureOrigins(), url::Origin::Create(url)))
- return true;
-
- return false;
+ return IsWhitelistedSecureOrigin(url::Origin::Create(url));
}
bool OriginCanAccessServiceWorkers(const GURL& url) {
@@ -74,10 +83,7 @@ bool IsPotentiallyTrustworthyOrigin(const url::Origin& origin) {
return true;
}
- if (base::ContainsValue(GetSecureOrigins(), origin))
- return true;
-
- return false;
+ return IsWhitelistedSecureOrigin(origin);
}
} // namespace content
diff --git a/chromium/content/common/page_state_serialization_unittest.cc b/chromium/content/common/page_state_serialization_unittest.cc
index ffd1a65d0f8..79251f47f77 100644
--- a/chromium/content/common/page_state_serialization_unittest.cc
+++ b/chromium/content/common/page_state_serialization_unittest.cc
@@ -203,7 +203,7 @@ class PageStateSerializationTest : public testing::Test {
int version,
ExplodedPageState* page_state) {
base::FilePath path;
- PathService::Get(content::DIR_TEST_DATA, &path);
+ base::PathService::Get(content::DIR_TEST_DATA, &path);
path = path.AppendASCII("page_state")
.AppendASCII(
base::StringPrintf("serialized_%s.dat", suffix.c_str()));
@@ -396,7 +396,7 @@ TEST_F(PageStateSerializationTest, LegacyEncodePageStateFrozen) {
LegacyEncodePageStateForTesting(actual_state, 25, &actual_encoded_state);
base::FilePath path;
- PathService::Get(content::DIR_TEST_DATA, &path);
+ base::PathService::Get(content::DIR_TEST_DATA, &path);
path = path.AppendASCII("page_state").AppendASCII("serialized_v25.dat");
std::string file_contents;
@@ -459,7 +459,7 @@ TEST_F(PageStateSerializationTest, DumpExpectedPageStateForBackwardsCompat) {
base::Base64Encode(encoded, &base64);
base::FilePath path;
- PathService::Get(base::DIR_TEMP, &path);
+ base::PathService::Get(base::DIR_TEMP, &path);
path = path.AppendASCII("expected.dat");
FILE* fp = base::OpenFile(path, "wb");
diff --git a/chromium/content/common/platform_notification_messages.h b/chromium/content/common/platform_notification_messages.h
index 507b4fb0061..b925cdcd4fd 100644
--- a/chromium/content/common/platform_notification_messages.h
+++ b/chromium/content/common/platform_notification_messages.h
@@ -17,19 +17,10 @@
#include "content/public/common/platform_notification_data.h"
#include "ipc/ipc_message_macros.h"
-// Singly-included section for type definitions.
-#ifndef INTERNAL_CONTENT_COMMON_PLATFORM_NOTIFICATION_MESSAGES_H_
-#define INTERNAL_CONTENT_COMMON_PLATFORM_NOTIFICATION_MESSAGES_H_
-
-// Defines the pair of [notification id] => [notification data] used when
-// getting the notifications for a given Service Worker registration.
-using PersistentNotificationInfo =
- std::pair<std::string, content::PlatformNotificationData>;
-
-#endif // INTERNAL_CONTENT_COMMON_PLATFORM_NOTIFICATION_MESSAGES_H_
-
#define IPC_MESSAGE_START PlatformNotificationMsgStart
+// TODO(https://crbug.com/841329): Delete this legacy IPC code, use a pure
+// mojo struct instead from ServiceWorkerEventDispatcher mojo interface.
IPC_ENUM_TRAITS_MAX_VALUE(
content::PlatformNotificationData::Direction,
content::PlatformNotificationData::DIRECTION_LAST)
@@ -63,48 +54,4 @@ IPC_STRUCT_TRAITS_BEGIN(content::PlatformNotificationData)
IPC_STRUCT_TRAITS_MEMBER(actions)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::NotificationResources)
- IPC_STRUCT_TRAITS_MEMBER(image)
- IPC_STRUCT_TRAITS_MEMBER(notification_icon)
- IPC_STRUCT_TRAITS_MEMBER(badge)
- IPC_STRUCT_TRAITS_MEMBER(action_icons)
-IPC_STRUCT_TRAITS_END()
-
-// Messages sent from the browser to the renderer.
-
-// Reply to PlatformNotificationHostMsg_ShowPersistent indicating that a
-// persistent notification has been shown on the platform (if |success| is
-// true), or that an unspecified error occurred.
-IPC_MESSAGE_CONTROL2(PlatformNotificationMsg_DidShowPersistent,
- int /* request_id */,
- bool /* success */)
-
-// Reply to PlatformNotificationHostMsg_GetNotifications sharing a vector of
-// available notifications per the request's constraints.
-IPC_MESSAGE_CONTROL2(PlatformNotificationMsg_DidGetNotifications,
- int /* request_id */,
- std::vector<PersistentNotificationInfo>
- /* notifications */)
-
-// Messages sent from the renderer to the browser.
-
-IPC_MESSAGE_CONTROL5(
- PlatformNotificationHostMsg_ShowPersistent,
- int /* request_id */,
- int64_t /* service_worker_registration_id */,
- GURL /* origin */,
- content::PlatformNotificationData /* notification_data */,
- content::NotificationResources /* notification_resources */)
-
-IPC_MESSAGE_CONTROL4(PlatformNotificationHostMsg_GetNotifications,
- int /* request_id */,
- int64_t /* service_worker_registration_id */,
- GURL /* origin */,
- std::string /* filter_tag */)
-
-IPC_MESSAGE_CONTROL3(PlatformNotificationHostMsg_ClosePersistent,
- GURL /* origin */,
- std::string /* tag */,
- std::string /* notification_id */)
-
#endif // CONTENT_COMMON_PLATFORM_NOTIFICATION_MESSAGES_H_
diff --git a/chromium/content/common/possibly_associated_interface_ptr.h b/chromium/content/common/possibly_associated_interface_ptr.h
index f49afcef703..5c70a46e086 100644
--- a/chromium/content/common/possibly_associated_interface_ptr.h
+++ b/chromium/content/common/possibly_associated_interface_ptr.h
@@ -6,6 +6,7 @@
#define CONTENT_COMMON_POSSIBLY_ASSOCIATED_INTERFACE_PTR_H_
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/possibly_associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
diff --git a/chromium/content/common/possibly_associated_wrapper_shared_url_loader_factory.h b/chromium/content/common/possibly_associated_wrapper_shared_url_loader_factory.h
new file mode 100644
index 00000000000..d162a359c0d
--- /dev/null
+++ b/chromium/content/common/possibly_associated_wrapper_shared_url_loader_factory.h
@@ -0,0 +1,18 @@
+// 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_COMMON_POSSIBLY_ASSOCIATED_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
+#define CONTENT_COMMON_POSSIBLY_ASSOCIATED_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
+
+#include "content/common/possibly_associated_interface_ptr.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
+
+namespace content {
+
+using PossiblyAssociatedWrapperSharedURLLoaderFactory =
+ network::WrapperSharedURLLoaderFactoryBase<PossiblyAssociatedInterfacePtr>;
+
+} // namespace content
+
+#endif // CONTENT_COMMON_POSSIBLY_ASSOCIATED_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/common/presentation/presentation.typemap b/chromium/content/common/presentation/presentation.typemap
index e6d6a8c0f1e..f69f4453021 100644
--- a/chromium/content/common/presentation/presentation.typemap
+++ b/chromium/content/common/presentation/presentation.typemap
@@ -3,20 +3,10 @@
# found in the LICENSE file.
mojom = "//third_party/blink/public/platform/modules/presentation/presentation.mojom"
-public_headers = [
- "//content/public/common/presentation_connection_message.h",
- "//content/public/common/presentation_info.h",
-]
+public_headers = [ "//content/public/common/presentation_connection_message.h" ]
traits_headers =
[ "//content/common/presentation/presentation_struct_traits.h" ]
deps = [
"//url",
]
-type_mappings = [
- "blink.mojom.PresentationConnectionCloseReason=content::PresentationConnectionCloseReason",
- "blink.mojom.PresentationConnectionMessage=content::PresentationConnectionMessage[move_only]",
- "blink.mojom.PresentationConnectionState=content::PresentationConnectionState",
- "blink.mojom.PresentationError=content::PresentationError",
- "blink.mojom.PresentationErrorType=content::PresentationErrorType",
- "blink.mojom.PresentationInfo=content::PresentationInfo",
-]
+type_mappings = [ "blink.mojom.PresentationConnectionMessage=content::PresentationConnectionMessage[move_only]" ]
diff --git a/chromium/content/common/presentation/presentation_struct_traits.cc b/chromium/content/common/presentation/presentation_struct_traits.cc
index 1db986d74c4..484a772a84e 100644
--- a/chromium/content/common/presentation/presentation_struct_traits.cc
+++ b/chromium/content/common/presentation/presentation_struct_traits.cc
@@ -8,40 +8,6 @@
namespace mojo {
-bool StructTraits<blink::mojom::PresentationInfoDataView,
- content::PresentationInfo>::
- Read(blink::mojom::PresentationInfoDataView data,
- content::PresentationInfo* out) {
- if (!data.ReadUrl(&(out->presentation_url)) ||
- !data.ReadId(&(out->presentation_id))) {
- return false;
- }
-
- if (out->presentation_id.empty() ||
- !base::IsStringASCII(out->presentation_id) ||
- out->presentation_id.length() > content::PresentationInfo::kMaxIdLength) {
- return false;
- }
- return true;
-}
-
-bool StructTraits<blink::mojom::PresentationErrorDataView,
- content::PresentationError>::
- Read(blink::mojom::PresentationErrorDataView data,
- content::PresentationError* out) {
- if (!data.ReadErrorType(&(out->error_type)) ||
- !data.ReadMessage(&(out->message))) {
- return false;
- }
-
- if (!base::IsStringUTF8(out->message) ||
- out->message.length() > content::PresentationError::kMaxMessageLength) {
- return false;
- }
-
- return true;
-}
-
bool UnionTraits<blink::mojom::PresentationConnectionMessageDataView,
content::PresentationConnectionMessage>::
Read(blink::mojom::PresentationConnectionMessageDataView data,
diff --git a/chromium/content/common/presentation/presentation_struct_traits.h b/chromium/content/common/presentation/presentation_struct_traits.h
index 13d406efedf..01e5e1ab535 100644
--- a/chromium/content/common/presentation/presentation_struct_traits.h
+++ b/chromium/content/common/presentation/presentation_struct_traits.h
@@ -12,168 +12,12 @@
#include "base/optional.h"
#include "base/strings/string_util.h"
#include "content/public/common/presentation_connection_message.h"
-#include "content/public/common/presentation_info.h"
#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
#include "url/mojom/url.mojom.h"
namespace mojo {
template <>
-struct EnumTraits<blink::mojom::PresentationErrorType,
- content::PresentationErrorType> {
- static blink::mojom::PresentationErrorType ToMojom(
- content::PresentationErrorType input) {
- switch (input) {
- case content::PRESENTATION_ERROR_NO_AVAILABLE_SCREENS:
- return blink::mojom::PresentationErrorType::NO_AVAILABLE_SCREENS;
- case content::PRESENTATION_ERROR_PRESENTATION_REQUEST_CANCELLED:
- return blink::mojom::PresentationErrorType::
- PRESENTATION_REQUEST_CANCELLED;
- case content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND:
- return blink::mojom::PresentationErrorType::NO_PRESENTATION_FOUND;
- case content::PRESENTATION_ERROR_PREVIOUS_START_IN_PROGRESS:
- return blink::mojom::PresentationErrorType::PREVIOUS_START_IN_PROGRESS;
- case content::PRESENTATION_ERROR_UNKNOWN:
- return blink::mojom::PresentationErrorType::UNKNOWN;
- }
- NOTREACHED() << "Unknown content::PresentationErrorType "
- << static_cast<int>(input);
- return blink::mojom::PresentationErrorType::UNKNOWN;
- }
-
- static bool FromMojom(blink::mojom::PresentationErrorType input,
- content::PresentationErrorType* output) {
- switch (input) {
- case blink::mojom::PresentationErrorType::NO_AVAILABLE_SCREENS:
- *output = content::PRESENTATION_ERROR_NO_AVAILABLE_SCREENS;
- return true;
- case blink::mojom::PresentationErrorType::PRESENTATION_REQUEST_CANCELLED:
- *output = content::PRESENTATION_ERROR_PRESENTATION_REQUEST_CANCELLED;
- return true;
- case blink::mojom::PresentationErrorType::NO_PRESENTATION_FOUND:
- *output = content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND;
- return true;
- case blink::mojom::PresentationErrorType::PREVIOUS_START_IN_PROGRESS:
- *output = content::PRESENTATION_ERROR_PREVIOUS_START_IN_PROGRESS;
- return true;
- case blink::mojom::PresentationErrorType::UNKNOWN:
- *output = content::PRESENTATION_ERROR_UNKNOWN;
- return true;
- }
- return false;
- }
-};
-
-template <>
-struct EnumTraits<blink::mojom::PresentationConnectionState,
- content::PresentationConnectionState> {
- static blink::mojom::PresentationConnectionState ToMojom(
- content::PresentationConnectionState input) {
- switch (input) {
- case content::PRESENTATION_CONNECTION_STATE_CONNECTING:
- return blink::mojom::PresentationConnectionState::CONNECTING;
- case content::PRESENTATION_CONNECTION_STATE_CONNECTED:
- return blink::mojom::PresentationConnectionState::CONNECTED;
- case content::PRESENTATION_CONNECTION_STATE_CLOSED:
- return blink::mojom::PresentationConnectionState::CLOSED;
- case content::PRESENTATION_CONNECTION_STATE_TERMINATED:
- return blink::mojom::PresentationConnectionState::TERMINATED;
- }
- NOTREACHED() << "Unknown content::PresentationConnectionState "
- << static_cast<int>(input);
- return blink::mojom::PresentationConnectionState::TERMINATED;
- }
-
- static bool FromMojom(blink::mojom::PresentationConnectionState input,
- content::PresentationConnectionState* output) {
- switch (input) {
- case blink::mojom::PresentationConnectionState::CONNECTING:
- *output = content::PRESENTATION_CONNECTION_STATE_CONNECTING;
- return true;
- case blink::mojom::PresentationConnectionState::CONNECTED:
- *output = content::PRESENTATION_CONNECTION_STATE_CONNECTED;
- return true;
- case blink::mojom::PresentationConnectionState::CLOSED:
- *output = content::PRESENTATION_CONNECTION_STATE_CLOSED;
- return true;
- case blink::mojom::PresentationConnectionState::TERMINATED:
- *output = content::PRESENTATION_CONNECTION_STATE_TERMINATED;
- return true;
- }
- return false;
- }
-};
-
-template <>
-struct EnumTraits<blink::mojom::PresentationConnectionCloseReason,
- content::PresentationConnectionCloseReason> {
- static blink::mojom::PresentationConnectionCloseReason ToMojom(
- content::PresentationConnectionCloseReason input) {
- switch (input) {
- case content::PRESENTATION_CONNECTION_CLOSE_REASON_CONNECTION_ERROR:
- return blink::mojom::PresentationConnectionCloseReason::
- CONNECTION_ERROR;
- case content::PRESENTATION_CONNECTION_CLOSE_REASON_CLOSED:
- return blink::mojom::PresentationConnectionCloseReason::CLOSED;
- case content::PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY:
- return blink::mojom::PresentationConnectionCloseReason::WENT_AWAY;
- }
- NOTREACHED() << "Unknown content::PresentationConnectionCloseReason "
- << static_cast<int>(input);
- return blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR;
- }
-
- static bool FromMojom(blink::mojom::PresentationConnectionCloseReason input,
- content::PresentationConnectionCloseReason* output) {
- switch (input) {
- case blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR:
- *output =
- content::PRESENTATION_CONNECTION_CLOSE_REASON_CONNECTION_ERROR;
- return true;
- case blink::mojom::PresentationConnectionCloseReason::CLOSED:
- *output = content::PRESENTATION_CONNECTION_CLOSE_REASON_CLOSED;
- return true;
- case blink::mojom::PresentationConnectionCloseReason::WENT_AWAY:
- *output = content::PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY;
- return true;
- }
- return false;
- }
-};
-
-template <>
-struct StructTraits<blink::mojom::PresentationInfoDataView,
- content::PresentationInfo> {
- static const GURL& url(const content::PresentationInfo& presentation_info) {
- return presentation_info.presentation_url;
- }
-
- static const std::string& id(
- const content::PresentationInfo& presentation_info) {
- return presentation_info.presentation_id;
- }
-
- static bool Read(blink::mojom::PresentationInfoDataView data,
- content::PresentationInfo* out);
-};
-
-template <>
-struct StructTraits<blink::mojom::PresentationErrorDataView,
- content::PresentationError> {
- static content::PresentationErrorType error_type(
- const content::PresentationError& error) {
- return error.error_type;
- }
-
- static const std::string& message(const content::PresentationError& error) {
- return error.message;
- }
-
- static bool Read(blink::mojom::PresentationErrorDataView data,
- content::PresentationError* out);
-};
-
-template <>
struct UnionTraits<blink::mojom::PresentationConnectionMessageDataView,
content::PresentationConnectionMessage> {
static blink::mojom::PresentationConnectionMessageDataView::Tag GetTag(
diff --git a/chromium/content/common/render_frame_metadata.mojom b/chromium/content/common/render_frame_metadata.mojom
index a2283f9d152..28573c16b7b 100644
--- a/chromium/content/common/render_frame_metadata.mojom
+++ b/chromium/content/common/render_frame_metadata.mojom
@@ -4,6 +4,7 @@
module content.mojom;
+import "services/viz/public/interfaces/compositing/local_surface_id.mojom";
import "services/viz/public/interfaces/compositing/selection.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
@@ -25,6 +26,32 @@ struct RenderFrameMetadata {
// Selection region relative to the current viewport. If the selection is
// empty or otherwise unused, the bound types will indicate such.
viz.mojom.Selection selection;
+
+ // Determines whether the page is mobile optimized or not, which means at
+ // least one of the following has to be true:
+ // - page has a width=device-width or narrower viewport.
+ // - page prevents zooming in or out (i.e. min and max page scale factors
+ // are the same).
+ bool is_mobile_optimized;
+
+ // The device scale factor used to generate CompositorFrame.
+ float device_scale_factor;
+
+ // The size of the viewport used to generate a CompositorFrame.
+ gfx.mojom.Size viewport_size_in_pixels;
+
+ // The last viz::LocalSurfaceId used to submit a CompositorFrame.
+ viz.mojom.LocalSurfaceId? local_surface_id;
+
+ // Used to position the Android location top bar and page content, whose
+ // precise position is computed by the renderer compositor.
+ float top_controls_height;
+ float top_controls_shown_ratio;
+
+ // Used to position Android bottom bar, whose position is computed by the
+ // renderer compositor.
+ float bottom_controls_height;
+ float bottom_controls_shown_ratio;
};
// This interface is provided by the renderer. It can optionally enable
diff --git a/chromium/content/common/render_frame_metadata_struct_traits.cc b/chromium/content/common/render_frame_metadata_struct_traits.cc
index e6129ebf056..f17bfdf991d 100644
--- a/chromium/content/common/render_frame_metadata_struct_traits.cc
+++ b/chromium/content/common/render_frame_metadata_struct_traits.cc
@@ -17,8 +17,16 @@ bool StructTraits<content::mojom::RenderFrameMetadataDataView,
cc::RenderFrameMetadata* out) {
out->root_background_color = data.root_background_color();
out->is_scroll_offset_at_top = data.is_scroll_offset_at_top();
+ out->is_mobile_optimized = data.is_mobile_optimized();
+ out->device_scale_factor = data.device_scale_factor();
+ out->top_controls_height = data.top_controls_height();
+ out->top_controls_shown_ratio = data.top_controls_shown_ratio();
+ out->bottom_controls_height = data.bottom_controls_height();
+ out->bottom_controls_shown_ratio = data.bottom_controls_shown_ratio();
return data.ReadRootScrollOffset(&out->root_scroll_offset) &&
- data.ReadSelection(&out->selection);
+ data.ReadSelection(&out->selection) &&
+ data.ReadViewportSizeInPixels(&out->viewport_size_in_pixels) &&
+ data.ReadLocalSurfaceId(&out->local_surface_id);
}
} // namespace mojo
diff --git a/chromium/content/common/render_frame_metadata_struct_traits.h b/chromium/content/common/render_frame_metadata_struct_traits.h
index de13e7a88c9..fbf17edfa65 100644
--- a/chromium/content/common/render_frame_metadata_struct_traits.h
+++ b/chromium/content/common/render_frame_metadata_struct_traits.h
@@ -8,6 +8,7 @@
#include "base/optional.h"
#include "cc/trees/render_frame_metadata.h"
#include "content/common/render_frame_metadata.mojom-shared.h"
+#include "services/viz/public/cpp/compositing/local_surface_id_struct_traits.h"
namespace mojo {
@@ -33,6 +34,42 @@ struct StructTraits<content::mojom::RenderFrameMetadataDataView,
return metadata.selection;
}
+ static bool is_mobile_optimized(const cc::RenderFrameMetadata& metadata) {
+ return metadata.is_mobile_optimized;
+ }
+
+ static float device_scale_factor(const cc::RenderFrameMetadata& metadata) {
+ return metadata.device_scale_factor;
+ }
+
+ static const gfx::Size& viewport_size_in_pixels(
+ const cc::RenderFrameMetadata& metadata) {
+ return metadata.viewport_size_in_pixels;
+ }
+
+ static const base::Optional<viz::LocalSurfaceId>& local_surface_id(
+ const cc::RenderFrameMetadata& metadata) {
+ return metadata.local_surface_id;
+ }
+
+ static float top_controls_height(const cc::RenderFrameMetadata& metadata) {
+ return metadata.top_controls_height;
+ }
+
+ static float top_controls_shown_ratio(
+ const cc::RenderFrameMetadata& metadata) {
+ return metadata.top_controls_shown_ratio;
+ }
+
+ static float bottom_controls_height(const cc::RenderFrameMetadata& metadata) {
+ return metadata.bottom_controls_height;
+ }
+
+ static float bottom_controls_shown_ratio(
+ const cc::RenderFrameMetadata& metadata) {
+ return metadata.bottom_controls_shown_ratio;
+ }
+
static bool Read(content::mojom::RenderFrameMetadataDataView data,
cc::RenderFrameMetadata* out);
};
diff --git a/chromium/content/common/renderer.mojom b/chromium/content/common/renderer.mojom
index 05886a72fce..2405622dde3 100644
--- a/chromium/content/common/renderer.mojom
+++ b/chromium/content/common/renderer.mojom
@@ -80,16 +80,7 @@ struct CreateViewParams {
bool has_committed_real_load;
// The initial renderer size.
- ResizeParams initial_size;
-
- // Whether to enable auto-resize.
- bool enable_auto_resize;
-
- // The minimum size to layout the page if auto-resize is enabled.
- gfx.mojom.Size min_size;
-
- // The maximum size to layout the page if auto-resize is enabled.
- gfx.mojom.Size max_size;
+ VisualProperties visual_properties;
// The page zoom level.
double page_zoom_level;
@@ -190,13 +181,6 @@ interface Renderer {
// Tells the renderer to create a new RenderFrame.
CreateFrame(CreateFrameParams params);
- // Tells the renderer to create an EmbeddedWorkerInstanceClient, which is what
- // manages service worker startup and shutdown.
- // TODO(shimazu): Create a service worker's execution context by this method
- // instead of just creating an instance of EmbeddedWorkerInstanceClient.
- SetUpEmbeddedWorkerChannelForServiceWorker(
- associated EmbeddedWorkerInstanceClient& client_request);
-
// Tells the renderer to create a new RenderFrameProxy object with
// |routing_id|. |render_view_routing_id| identifies the
// RenderView to be associated with this proxy. The new proxy's opener should
@@ -212,6 +196,13 @@ interface Renderer {
FrameReplicationState replication_state,
mojo_base.mojom.UnguessableToken devtools_frame_token);
+ // Tells the renderer to create an EmbeddedWorkerInstanceClient, which is what
+ // manages service worker startup and shutdown.
+ // TODO(shimazu): Send all params for starting service worker to reduce the
+ // number of IPCs.
+ SetUpEmbeddedWorkerChannelForServiceWorker(
+ EmbeddedWorkerInstanceClient& client_request);
+
// Tells the renderer that the network type has changed so that
// navigator.onLine and navigator.connection can be updated.
OnNetworkConnectionChanged(NetworkConnectionType connection_type,
@@ -234,6 +225,12 @@ interface Renderer {
// Android.
SetWebKitSharedTimersSuspended(bool suspend);
+ // Sets the user-agent string. This is needed because getting the value in the
+ // renderer from the system leads to a wrong value due to sandboxing. This
+ // must be called as early as possible, during the renderer process
+ // initialization.
+ SetUserAgent(string user_agent);
+
// Tells the renderer about a scrollbar appearance change. Only for use on
// OS X.
UpdateScrollbarTheme(UpdateScrollbarThemeParams params);
diff --git a/chromium/content/common/resize_params.cc b/chromium/content/common/resize_params.cc
deleted file mode 100644
index 5e1fd102f66..00000000000
--- a/chromium/content/common/resize_params.cc
+++ /dev/null
@@ -1,25 +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.
-
-#include "content/common/resize_params.h"
-
-namespace content {
-
-ResizeParams::ResizeParams()
- : auto_resize_enabled(false),
- auto_resize_sequence_number(0u),
- browser_controls_shrink_blink_size(false),
- scroll_focused_node_into_view(false),
- top_controls_height(0.f),
- bottom_controls_height(0.f),
- is_fullscreen_granted(false),
- display_mode(blink::kWebDisplayModeUndefined),
- needs_resize_ack(false),
- content_source_id(0u) {}
-
-ResizeParams::ResizeParams(const ResizeParams& other) = default;
-
-ResizeParams::~ResizeParams() {}
-
-} // namespace content
diff --git a/chromium/content/common/resource_messages.h b/chromium/content/common/resource_messages.h
index edcf425d7ea..c31444de9a6 100644
--- a/chromium/content/common/resource_messages.h
+++ b/chromium/content/common/resource_messages.h
@@ -21,7 +21,7 @@
#include "net/base/request_priority.h"
#include "net/http/http_response_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "services/network/public/cpp/network_param_ipc_traits.h"
+#include "services/network/public/cpp/network_ipc_param_traits.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
#ifndef INTERNAL_CONTENT_COMMON_RESOURCE_MESSAGES_H_
diff --git a/chromium/content/common/resource_timing_info.h b/chromium/content/common/resource_timing_info.h
index 78b9a61316f..ccac0850564 100644
--- a/chromium/content/common/resource_timing_info.h
+++ b/chromium/content/common/resource_timing_info.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/optional.h"
+#include "base/time/time.h"
namespace content {
@@ -36,22 +37,22 @@ struct ResourceLoadTiming {
ResourceLoadTiming(const ResourceLoadTiming&);
~ResourceLoadTiming();
- double request_time = 0.0;
- double proxy_start = 0.0;
- double proxy_end = 0.0;
- double dns_start = 0.0;
- double dns_end = 0.0;
- double connect_start = 0.0;
- double connect_end = 0.0;
- double worker_start = 0.0;
- double worker_ready = 0.0;
- double send_start = 0.0;
- double send_end = 0.0;
- double receive_headers_end = 0.0;
- double ssl_start = 0.0;
- double ssl_end = 0.0;
- double push_start = 0.0;
- double push_end = 0.0;
+ base::TimeTicks request_time;
+ base::TimeTicks proxy_start;
+ base::TimeTicks proxy_end;
+ base::TimeTicks dns_start;
+ base::TimeTicks dns_end;
+ base::TimeTicks connect_start;
+ base::TimeTicks connect_end;
+ base::TimeTicks worker_start;
+ base::TimeTicks worker_ready;
+ base::TimeTicks send_start;
+ base::TimeTicks send_end;
+ base::TimeTicks receive_headers_end;
+ base::TimeTicks ssl_start;
+ base::TimeTicks ssl_end;
+ base::TimeTicks push_start;
+ base::TimeTicks push_end;
};
// TODO(dcheng): Migrate this struct over to Mojo so it doesn't need to be
@@ -64,13 +65,13 @@ struct ResourceTimingInfo {
~ResourceTimingInfo();
std::string name;
- double start_time = 0.0;
+ base::TimeTicks start_time;
std::string initiator_type;
std::string alpn_negotiated_protocol;
std::string connection_info;
base::Optional<ResourceLoadTiming> timing;
- double last_redirect_end_time = 0.0;
- double finish_time = 0.0;
+ base::TimeTicks last_redirect_end_time;
+ base::TimeTicks finish_time;
uint64_t transfer_size = 0;
uint64_t encoded_body_size = 0;
uint64_t decoded_body_size = 0;
diff --git a/chromium/content/common/sandbox_init_mac.cc b/chromium/content/common/sandbox_init_mac.cc
index 583e283f276..ee6202e3178 100644
--- a/chromium/content/common/sandbox_init_mac.cc
+++ b/chromium/content/common/sandbox_init_mac.cc
@@ -51,16 +51,22 @@ base::OnceClosure MaybeWrapWithGPUSandboxHook(
gpu::SwitchValueToGpuPreferences(value, &gpu_preferences);
CHECK(success);
}
+ bool needs_more_info = false;
gpu::GpuFeatureInfo gpu_feature_info = gpu::ComputeGpuFeatureInfo(
gpu_info, gpu_preferences.ignore_gpu_blacklist,
gpu_preferences.disable_gpu_driver_bug_workarounds,
gpu_preferences.log_gpu_control_list_decisions, command_line,
- nullptr);
+ &needs_more_info);
gpu::CacheGpuFeatureInfo(gpu_feature_info);
if (gpu::SwitchableGPUsSupported(gpu_info, *command_line)) {
gpu::InitializeSwitchableGPUs(
gpu_feature_info.enabled_gpu_driver_bug_workarounds);
}
+ // Calling ShouldEnableSwiftShader will append the proper command line
+ // switch in order to enable SwiftShader if required.
+ gpu::ShouldEnableSwiftShader(
+ command_line, gpu_feature_info,
+ gpu_preferences.disable_software_rasterizer, needs_more_info);
// Preload either the desktop GL or the osmesa so, depending on the
// --use-gl flag.
gl::init::InitializeGLOneOff();
diff --git a/chromium/content/common/sandbox_policy_fuchsia.cc b/chromium/content/common/sandbox_policy_fuchsia.cc
index acfbbfd12d9..26a202b648c 100644
--- a/chromium/content/common/sandbox_policy_fuchsia.cc
+++ b/chromium/content/common/sandbox_policy_fuchsia.cc
@@ -13,41 +13,32 @@
#include "base/process/launch.h"
#include "base/process/process.h"
#include "content/public/common/content_switches.h"
+#include "services/service_manager/sandbox/switches.h"
namespace content {
void UpdateLaunchOptionsForSandbox(service_manager::SandboxType type,
base::LaunchOptions* options) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox)) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ service_manager::switches::kNoSandbox)) {
type = service_manager::SANDBOX_TYPE_NO_SANDBOX;
}
if (type != service_manager::SANDBOX_TYPE_NO_SANDBOX) {
- auto package_root = base::GetPackageRoot();
- if (!package_root.empty()) {
- // TODO(kmarshall): Build path mappings for each sandbox type.
-
- // Map /pkg (read-only files deployed from the package) and /tmp into the
- // child's namespace.
- options->paths_to_map.push_back(package_root.AsUTF8Unsafe());
- base::FilePath temp_dir;
- base::GetTempDir(&temp_dir);
- options->paths_to_map.push_back(temp_dir.AsUTF8Unsafe());
-
- // Clear environmental variables to better isolate the child from
- // this process.
- options->clear_environ = true;
-
- // Propagate stdout/stderr/stdin to the child.
- options->clone_flags = LP_CLONE_FDIO_STDIO;
- return;
- }
-
- // TODO(crbug.com/750938): Remove this once package deployments become
- // mandatory.
- LOG(ERROR) << "Sandboxing was requested but is not available because"
- << "the parent process is not hosted within a package.";
- type = service_manager::SANDBOX_TYPE_NO_SANDBOX;
+ // Map /pkg (read-only files deployed from the package) and /tmp into the
+ // child's namespace.
+ options->paths_to_map.push_back(base::GetPackageRoot());
+ base::FilePath temp_dir;
+ base::GetTempDir(&temp_dir);
+ options->paths_to_map.push_back(temp_dir);
+
+ // Clear environmental variables to better isolate the child from
+ // this process.
+ options->clear_environ = true;
+
+ // Propagate stdout/stderr/stdin to the child.
+ options->clone_flags = LP_CLONE_FDIO_STDIO;
+ return;
}
DCHECK_EQ(type, service_manager::SANDBOX_TYPE_NO_SANDBOX);
diff --git a/chromium/content/common/send_zygote_child_ping_linux.cc b/chromium/content/common/send_zygote_child_ping_linux.cc
deleted file mode 100644
index f7f1685834b..00000000000
--- a/chromium/content/common/send_zygote_child_ping_linux.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 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/public/common/send_zygote_child_ping_linux.h"
-
-#include <vector>
-
-#include "base/posix/unix_domain_socket.h"
-#include "content/common/zygote_commands_linux.h"
-
-namespace content {
-
-bool SendZygoteChildPing(int fd) {
- return base::UnixDomainSocket::SendMsg(fd,
- kZygoteChildPingMessage,
- sizeof(kZygoteChildPingMessage),
- std::vector<int>());
-}
-
-} // namespace content
diff --git a/chromium/content/common/service_manager/service_manager_connection_impl.cc b/chromium/content/common/service_manager/service_manager_connection_impl.cc
index 49f0da67e49..dac316d7662 100644
--- a/chromium/content/common/service_manager/service_manager_connection_impl.cc
+++ b/chromium/content/common/service_manager/service_manager_connection_impl.cc
@@ -13,9 +13,10 @@
#include "base/callback_helpers.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "content/common/child.mojom.h"
#include "content/public/common/connection_filter.h"
#include "content/public/common/service_names.mojom.h"
@@ -28,6 +29,13 @@
#include "services/service_manager/public/mojom/service_factory.mojom.h"
#include "services/service_manager/runner/common/client_util.h"
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#include "jni/ServiceManagerConnectionImpl_jni.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/mojom/connector.mojom.h"
+#endif
+
namespace content {
namespace {
@@ -133,15 +141,16 @@ class ServiceManagerConnectionImpl::IOThreadContext
private:
friend class base::RefCountedThreadSafe<IOThreadContext>;
- class MessageLoopObserver : public base::MessageLoop::DestructionObserver {
+ class MessageLoopObserver
+ : public base::MessageLoopCurrent::DestructionObserver {
public:
explicit MessageLoopObserver(base::WeakPtr<IOThreadContext> context)
: context_(context) {
- base::MessageLoop::current()->AddDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
}
~MessageLoopObserver() override {
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
}
void ShutDown() {
@@ -350,6 +359,23 @@ class ServiceManagerConnectionImpl::IOThreadContext
DISALLOW_COPY_AND_ASSIGN(IOThreadContext);
};
+#if defined(OS_ANDROID)
+// static
+jint JNI_ServiceManagerConnectionImpl_GetConnectorMessagePipeHandle(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jclass>& jcaller) {
+ DCHECK(ServiceManagerConnection::GetForProcess());
+
+ service_manager::mojom::ConnectorPtrInfo connector_info;
+ ServiceManagerConnection::GetForProcess()
+ ->GetConnector()
+ ->BindConnectorRequest(mojo::MakeRequest(&connector_info));
+
+ return connector_info.PassHandle().release().value();
+}
+
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// ServiceManagerConnection, public:
diff --git a/chromium/content/common/service_worker/BUILD.gn b/chromium/content/common/service_worker/BUILD.gn
new file mode 100644
index 00000000000..65c27c138fc
--- /dev/null
+++ b/chromium/content/common/service_worker/BUILD.gn
@@ -0,0 +1,11 @@
+# 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("//third_party/protobuf/proto_library.gni")
+
+proto_library("service_worker_types_proto") {
+ sources = [
+ "service_worker_types.proto",
+ ]
+}
diff --git a/chromium/content/common/service_worker/dispatch_fetch_event_params.mojom b/chromium/content/common/service_worker/dispatch_fetch_event_params.mojom
index 05d50cc0893..785d219b776 100644
--- a/chromium/content/common/service_worker/dispatch_fetch_event_params.mojom
+++ b/chromium/content/common/service_worker/dispatch_fetch_event_params.mojom
@@ -19,9 +19,23 @@ struct DispatchFetchEventParams {
// FetchEvent#request.
network.mojom.URLRequest request;
- // For Non-S13nServiceWorker these |request_body_*| fields are used to create
- // FetchEvent#request#body. For S13nServiceWorker, the body is provided in
- // |request.request_body|, and these fields are not used.
+ // The following fields are used to create FetchEvent#request#body, depending
+ // on whether S13nServiceWorker/NetworkService are enabled.
+
+ // (A) S13nServiceWorker with NetworkService on:
+ // All information about the request body is provided in
+ // |request.request_body|.
+
+ // (B) S13nServiceWorker with NetworkService off:
+ // All information about the request body except for BlobPtrs is provided in
+ // |request.request_body|. These BlobPtrs need to be passed separately.
+ // Once the NetworkService is enabled, this will be no longer used since all
+ // Blobs are passed as data pipes which can live in |request.request_body|.
+ array<blink.mojom.Blob> request_body_blob_ptrs;
+
+ // (C) non-S13nServiceWorker:
+ // All information to create the request body are packed into a blob. These
+ // params are for passing the blob.
string request_body_blob_uuid;
uint64 request_body_blob_size;
blink.mojom.Blob? request_body_blob;
diff --git a/chromium/content/common/service_worker/embedded_worker.mojom b/chromium/content/common/service_worker/embedded_worker.mojom
index 1dbda4e6cbc..a9c5333ade0 100644
--- a/chromium/content/common/service_worker/embedded_worker.mojom
+++ b/chromium/content/common/service_worker/embedded_worker.mojom
@@ -12,7 +12,6 @@ import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/service_manager/public/mojom/interface_provider.mojom";
-import "third_party/blink/public/mojom/service_worker/service_worker.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom";
import "third_party/blink/public/platform/web_feature.mojom";
import "third_party/blink/public/web/console_message.mojom";
@@ -58,9 +57,6 @@ struct EmbeddedWorkerStartParams {
ControllerServiceWorker& controller_request;
// Information to transfer installed scripts from the browser to the renderer.
blink.mojom.ServiceWorkerInstalledScriptsInfo? installed_scripts_info;
- // Interface for the renderer to ask the browser to do operations needed for
- // ServiceWorkerGlobalScope functionalities.
- associated blink.mojom.ServiceWorkerHost service_worker_host;
// Interface for the renderer to send the status updates to the browser.
associated EmbeddedWorkerInstanceHost instance_host;
// Information for creating ServiceWorkerNetworkProvider on the renderer.
diff --git a/chromium/content/common/service_worker/service_worker_container.mojom b/chromium/content/common/service_worker/service_worker_container.mojom
index 07dc0255a65..ef8136d3e89 100644
--- a/chromium/content/common/service_worker/service_worker_container.mojom
+++ b/chromium/content/common/service_worker/service_worker_container.mojom
@@ -99,7 +99,7 @@ interface ServiceWorkerContainerHost {
// to use this name.
interface ServiceWorkerContainer {
// Corresponds to setting ServiceWorkerContainer#controller.
- // If |controller_info| is invalid (its |handle_id| is invalid), then
+ // If |controller_info| is invalid (its |object_info| is null), then
// ServiceWorkerContainer#controller is cleared.
// If |controller_info| is valid, |used_features| is the set of
// features the controller has used, for UseCounter purposes.
diff --git a/chromium/content/common/service_worker/service_worker_event_dispatcher.mojom b/chromium/content/common/service_worker/service_worker_event_dispatcher.mojom
index 2d97943541e..dc52bf442f0 100644
--- a/chromium/content/common/service_worker/service_worker_event_dispatcher.mojom
+++ b/chromium/content/common/service_worker/service_worker_event_dispatcher.mojom
@@ -8,12 +8,15 @@ import "content/common/service_worker/dispatch_fetch_event_params.mojom";
import "content/common/service_worker/service_worker_fetch_response_callback.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
+import "services/network/public/mojom/cookie_manager.mojom";
import "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom";
import "third_party/blink/public/platform/modules/payments/payment_app.mojom";
import "third_party/blink/public/mojom/message_port/message_port.mojom";
+import "third_party/blink/public/mojom/service_worker/service_worker.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_client.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_object.mojom";
+import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
@@ -63,6 +66,17 @@ const int32 kPushEventTimeoutSeconds = 90;
// 'simple events'. ServiceWorkerVersion::CreateSimpleEventCallback can be used
// to create the callback for these.
interface ServiceWorkerEventDispatcher {
+ // The first message sent on this interface. It is used to associate service
+ // worker-related interfaces together on the service worker thread, as
+ // ServiceWorkerEventDispatcher is the first interface available on the
+ // service worker thread. It establishes the |service_worker_host| connection
+ // and passes information used to populate
+ // ServiceWorkerGlobalScope#registration object. JavaScript execution of the
+ // service worker does not start until this message is received.
+ InitializeGlobalScope(
+ associated blink.mojom.ServiceWorkerHost service_worker_host,
+ blink.mojom.ServiceWorkerRegistrationObjectInfo registration_info);
+
DispatchInstallEvent()
=> (blink.mojom.ServiceWorkerEventStatus status,
bool has_fetch_handler,
@@ -76,7 +90,9 @@ interface ServiceWorkerEventDispatcher {
// The callbacks are called once the event handler has run and waitUntil()
// promise has settled. |developer_id| and |unique_id| are documented in
// content::BackgroundFetchRegistrationId.
- DispatchBackgroundFetchAbortEvent(string developer_id)
+ DispatchBackgroundFetchAbortEvent(string developer_id,
+ string unique_id,
+ array<BackgroundFetchSettledFetch> fetches)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
DispatchBackgroundFetchClickEvent(string developer_id,
@@ -84,6 +100,7 @@ interface ServiceWorkerEventDispatcher {
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
DispatchBackgroundFetchFailEvent(string developer_id,
+ string unique_id,
array<BackgroundFetchSettledFetch> fetches)
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
@@ -93,6 +110,16 @@ interface ServiceWorkerEventDispatcher {
=> (blink.mojom.ServiceWorkerEventStatus status,
mojo_base.mojom.Time dispatch_event_time);
+ // Dispatches the cookie change events in the Async Cookie API specification.
+ // https://github.com/WICG/cookie-store/
+ // The callback is called once the event handler has run and the waitUntil()
+ // promise has settled.
+ DispatchCookieChangeEvent(
+ network.mojom.CanonicalCookie cookie,
+ network.mojom.CookieChangeCause cause)
+ => (blink.mojom.ServiceWorkerEventStatus status,
+ mojo_base.mojom.Time dispatch_event_time);
+
// The Dispatch*FetchEvent() callback is called once the event finishes,
// which means the event handler ran and all outstanding respondWith() and
// waitUntil() promises have settled. |response_callback| is called once the
diff --git a/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.cc b/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.cc
index 28378abbaf7..a6b3557e7e3 100644
--- a/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.cc
+++ b/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.cc
@@ -207,10 +207,12 @@ bool StructTraits<blink::mojom::FetchAPIRequestDataView,
Read(blink::mojom::FetchAPIRequestDataView data,
content::ServiceWorkerFetchRequest* out) {
std::unordered_map<std::string, std::string> headers;
+ blink::mojom::SerializedBlobPtr serialized_blob_ptr;
if (!data.ReadMode(&out->mode) ||
!data.ReadRequestContextType(&out->request_context_type) ||
!data.ReadFrameType(&out->frame_type) || !data.ReadUrl(&out->url) ||
!data.ReadMethod(&out->method) || !data.ReadHeaders(&headers) ||
+ !data.ReadBlob(&serialized_blob_ptr) ||
!data.ReadReferrer(&out->referrer) ||
!data.ReadCredentialsMode(&out->credentials_mode) ||
!data.ReadRedirectMode(&out->redirect_mode) ||
@@ -220,11 +222,7 @@ bool StructTraits<blink::mojom::FetchAPIRequestDataView,
}
// content::ServiceWorkerFetchRequest doesn't support request body.
- base::Optional<std::string> blob_uuid;
- if (data.ReadBlobUuid(&blob_uuid) && blob_uuid && !blob_uuid->empty())
- return false;
- blink::mojom::BlobPtr blob = data.TakeBlob<blink::mojom::BlobPtr>();
- if (blob)
+ if (serialized_blob_ptr)
return false;
out->is_main_resource_load = data.is_main_resource_load();
diff --git a/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.h b/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.h
index 55862700585..fe8cc4e2e27 100644
--- a/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.h
+++ b/chromium/content/common/service_worker/service_worker_fetch_request_mojom_traits.h
@@ -63,18 +63,7 @@ struct StructTraits<blink::mojom::FetchAPIRequestDataView,
}
// content::ServiceWorkerFetchRequest does not support the request body.
- static const std::string& blob_uuid(
- const content::ServiceWorkerFetchRequest& request) {
- return base::EmptyString();
- }
-
- // content::ServiceWorkerFetchRequest does not support the request body.
- static uint64_t blob_size(const content::ServiceWorkerFetchRequest& request) {
- return 0;
- }
-
- // content::ServiceWorkerFetchRequest does not support the request body.
- static blink::mojom::BlobPtr blob(
+ static blink::mojom::SerializedBlobPtr blob(
const content::ServiceWorkerFetchRequest& request) {
return nullptr;
}
diff --git a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc b/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
index 4d615363d26..64a9ed1b85f 100644
--- a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
+++ b/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.cc
@@ -23,24 +23,38 @@ bool StructTraits<blink::mojom::FetchAPIResponseDataView,
content::ServiceWorkerResponse>::
Read(blink::mojom::FetchAPIResponseDataView data,
content::ServiceWorkerResponse* out) {
+ blink::mojom::SerializedBlobPtr serialized_blob_ptr;
+ blink::mojom::SerializedBlobPtr serialized_side_data_blob_ptr;
if (!data.ReadUrlList(&out->url_list) ||
!data.ReadStatusText(&out->status_text) ||
!data.ReadResponseType(&out->response_type) ||
- !data.ReadHeaders(&out->headers) || !data.ReadBlobUuid(&out->blob_uuid) ||
- !data.ReadError(&out->error) ||
+ !data.ReadHeaders(&out->headers) ||
+ !data.ReadBlob(&serialized_blob_ptr) || !data.ReadError(&out->error) ||
!data.ReadResponseTime(&out->response_time) ||
!data.ReadCacheStorageCacheName(&out->cache_storage_cache_name) ||
- !data.ReadCorsExposedHeaderNames(&out->cors_exposed_header_names)) {
+ !data.ReadCorsExposedHeaderNames(&out->cors_exposed_header_names) ||
+ !data.ReadSideDataBlob(&serialized_side_data_blob_ptr)) {
return false;
}
out->status_code = data.status_code();
- out->blob_size = data.blob_size();
out->is_in_cache_storage = data.is_in_cache_storage();
- if (!out->blob_uuid.empty()) {
- blink::mojom::BlobPtr blob = data.TakeBlob<blink::mojom::BlobPtr>();
- out->blob = base::MakeRefCounted<storage::BlobHandle>(std::move(blob));
+ if (serialized_blob_ptr) {
+ out->blob_uuid = serialized_blob_ptr->uuid;
+ out->blob_size = serialized_blob_ptr->size;
+ blink::mojom::BlobPtr blob_ptr;
+ blob_ptr.Bind(std::move(serialized_blob_ptr->blob));
+ out->blob = base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
+ }
+
+ if (serialized_side_data_blob_ptr) {
+ out->side_data_blob_uuid = serialized_side_data_blob_ptr->uuid;
+ out->side_data_blob_size = serialized_side_data_blob_ptr->size;
+ blink::mojom::BlobPtr blob_ptr;
+ blob_ptr.Bind(std::move(serialized_side_data_blob_ptr->blob));
+ out->side_data_blob =
+ base::MakeRefCounted<storage::BlobHandle>(std::move(blob_ptr));
}
return true;
diff --git a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h b/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h
index 51d7d859813..287ac17b670 100644
--- a/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h
+++ b/chromium/content/common/service_worker/service_worker_fetch_response_mojom_traits.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/numerics/safe_conversions.h"
+#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom.h"
@@ -16,8 +17,8 @@
namespace mojo {
template <>
-struct StructTraits<blink::mojom::FetchAPIResponseDataView,
- content::ServiceWorkerResponse> {
+struct CONTENT_EXPORT StructTraits<blink::mojom::FetchAPIResponseDataView,
+ content::ServiceWorkerResponse> {
static const std::vector<GURL>& url_list(
const content::ServiceWorkerResponse& response) {
return response.url_list;
@@ -29,10 +30,15 @@ struct StructTraits<blink::mojom::FetchAPIResponseDataView,
const content::ServiceWorkerResponse& response) {
return response.is_in_cache_storage;
}
- static blink::mojom::BlobPtr blob(
+ static blink::mojom::SerializedBlobPtr blob(
const content::ServiceWorkerResponse& response) {
if (response.blob) {
- return response.blob->Clone();
+ blink::mojom::SerializedBlobPtr serialized_blob_ptr =
+ blink::mojom::SerializedBlob::New();
+ serialized_blob_ptr->uuid = response.blob_uuid;
+ serialized_blob_ptr->size = response.blob_size;
+ serialized_blob_ptr->blob = response.blob->Clone().PassInterface();
+ return serialized_blob_ptr;
}
return nullptr;
}
@@ -50,12 +56,6 @@ struct StructTraits<blink::mojom::FetchAPIResponseDataView,
headers(const content::ServiceWorkerResponse& response) {
return response.headers;
}
- static std::string blob_uuid(const content::ServiceWorkerResponse& response) {
- return response.blob_uuid;
- }
- static uint64_t blob_size(const content::ServiceWorkerResponse& response) {
- return response.blob_size;
- }
static blink::mojom::ServiceWorkerResponseError error(
const content::ServiceWorkerResponse& response) {
return response.error;
@@ -72,6 +72,19 @@ struct StructTraits<blink::mojom::FetchAPIResponseDataView,
const content::ServiceWorkerResponse& response) {
return response.cors_exposed_header_names;
}
+ static blink::mojom::SerializedBlobPtr side_data_blob(
+ const content::ServiceWorkerResponse& response) {
+ if (response.side_data_blob) {
+ blink::mojom::SerializedBlobPtr serialized_blob_ptr =
+ blink::mojom::SerializedBlob::New();
+ serialized_blob_ptr->uuid = response.side_data_blob_uuid;
+ serialized_blob_ptr->size = response.side_data_blob_size;
+ serialized_blob_ptr->blob =
+ response.side_data_blob->Clone().PassInterface();
+ return serialized_blob_ptr;
+ }
+ return nullptr;
+ }
static bool Read(blink::mojom::FetchAPIResponseDataView,
content::ServiceWorkerResponse* output);
};
diff --git a/chromium/content/common/service_worker/service_worker_loader_helpers.cc b/chromium/content/common/service_worker/service_worker_loader_helpers.cc
index 0b4912c8982..738ed311a07 100644
--- a/chromium/content/common/service_worker/service_worker_loader_helpers.cc
+++ b/chromium/content/common/service_worker/service_worker_loader_helpers.cc
@@ -156,47 +156,4 @@ int ServiceWorkerLoaderHelpers::ReadBlobResponseBody(
return net::OK;
}
-// static
-scoped_refptr<network::ResourceRequestBody>
-ServiceWorkerLoaderHelpers::CloneResourceRequestBody(
- const network::ResourceRequestBody* body) {
- auto clone = base::MakeRefCounted<network::ResourceRequestBody>();
-
- clone->set_identifier(body->identifier());
- clone->set_contains_sensitive_info(body->contains_sensitive_info());
- for (const network::DataElement& element : *body->elements()) {
- switch (element.type()) {
- case network::DataElement::TYPE_UNKNOWN:
- NOTREACHED();
- break;
- case network::DataElement::TYPE_DATA_PIPE: {
- clone->AppendDataPipe(element.CloneDataPipeGetter());
- break;
- }
- case network::DataElement::TYPE_RAW_FILE:
- clone->AppendRawFileRange(element.file().Duplicate(), element.path(),
- element.offset(), element.length(),
- element.expected_modification_time());
- break;
- case network::DataElement::TYPE_CHUNKED_DATA_PIPE:
- NOTREACHED() << "There should be no chunked data pipes going through "
- "ServiceWorker";
- break;
- case network::DataElement::TYPE_BLOB:
- NOTREACHED() << "There should be no blob elements in NetworkService";
- break;
- case network::DataElement::TYPE_FILE:
- clone->AppendFileRange(element.path(), element.offset(),
- element.length(),
- element.expected_modification_time());
- break;
- case network::DataElement::TYPE_BYTES:
- clone->AppendBytes(element.bytes(), element.length());
- break;
- }
- }
-
- return clone;
-}
-
} // namespace content
diff --git a/chromium/content/common/service_worker/service_worker_loader_helpers.h b/chromium/content/common/service_worker/service_worker_loader_helpers.h
index 3654e07fcfe..a709385b4f2 100644
--- a/chromium/content/common/service_worker/service_worker_loader_helpers.h
+++ b/chromium/content/common/service_worker/service_worker_loader_helpers.h
@@ -12,7 +12,6 @@
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
namespace network {
-class ResourceRequestBody;
struct ResourceRequest;
struct ResourceResponseHead;
}
@@ -49,15 +48,6 @@ class ServiceWorkerLoaderHelpers {
const net::HttpRequestHeaders& headers,
base::OnceCallback<void(int net_error)> on_blob_read_complete,
mojo::ScopedDataPipeConsumerHandle* handle_out);
-
- // Returns a new copy of the given body. This is useful for service worker
- // with NetworkService because it sends the ResourceRequestBody over Mojo IPC,
- // which moves out the DataPipeGetter elements in the Pickle code in
- // resources_messages.cc. We can't change the Pickle code to call
- // DataPipeGetter's Clone method because that code can run on different thread
- // than the DataPipeGetter.
- static scoped_refptr<network::ResourceRequestBody> CloneResourceRequestBody(
- const network::ResourceRequestBody* body);
};
} // namespace content
diff --git a/chromium/content/common/service_worker/service_worker_messages.h b/chromium/content/common/service_worker/service_worker_messages.h
index 9c6dd91051c..8cba139aba4 100644
--- a/chromium/content/common/service_worker/service_worker_messages.h
+++ b/chromium/content/common/service_worker/service_worker_messages.h
@@ -26,12 +26,8 @@
#define IPC_MESSAGE_START ServiceWorkerMsgStart
-IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::ServiceWorkerErrorType,
- blink::mojom::ServiceWorkerErrorType::kMaxValue)
-
-IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::ServiceWorkerState,
- blink::mojom::ServiceWorkerState::kMaxValue)
-
+// TODO(leonhsl): Figure out what's the purpose of all these traits then
+// eliminate this file finally.
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::ServiceWorkerResponseError,
blink::mojom::ServiceWorkerResponseError::kMaxValue)
@@ -76,18 +72,4 @@ IPC_STRUCT_TRAITS_BEGIN(content::PushEventPayload)
IPC_STRUCT_TRAITS_MEMBER(is_null)
IPC_STRUCT_TRAITS_END()
-//---------------------------------------------------------------------------
-// Messages sent from the browser to the child process.
-//
-// NOTE: All ServiceWorkerMsg messages not sent via EmbeddedWorker must have
-// a thread_id as their first field so that ServiceWorkerMessageFilter can
-// extract it and dispatch the message to the correct ServiceWorkerDispatcher
-// on the correct thread.
-
-// Informs the child process that the ServiceWorker's state has changed.
-IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerStateChanged,
- int /* thread_id */,
- int /* handle_id */,
- blink::mojom::ServiceWorkerState)
-
#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_MESSAGES_H_
diff --git a/chromium/content/common/service_worker/service_worker_provider.mojom b/chromium/content/common/service_worker/service_worker_provider.mojom
index de8bda5821d..17fdfada95a 100644
--- a/chromium/content/common/service_worker/service_worker_provider.mojom
+++ b/chromium/content/common/service_worker/service_worker_provider.mojom
@@ -9,6 +9,7 @@ import "services/network/public/mojom/url_loader_factory.mojom";
import "services/service_manager/public/mojom/interface_provider.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom";
+import "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom";
// The name of the InterfaceProviderSpec in service manifests used by the
// frame tree to expose service-worker-specific interfaces between renderer
@@ -30,9 +31,6 @@ struct ServiceWorkerProviderInfoForSharedWorker {
// worker.
struct ServiceWorkerProviderInfoForStartWorker {
int32 provider_id;
- // |registration| is information about the service worker's
- // registration used to populate ServiceWorkerGlobalScope#registration.
- blink.mojom.ServiceWorkerRegistrationObjectInfo registration;
associated ServiceWorkerContainerHost host_ptr_info;
associated ServiceWorkerContainer& client_request;
@@ -42,6 +40,13 @@ struct ServiceWorkerProviderInfoForStartWorker {
// importScripts().
associated network.mojom.URLLoaderFactory? script_loader_factory_ptr_info;
+ // |cache_storage| is an optional optimization so the service worker can use
+ // the Cache Storage API immediately without using InterfaceProvider. May be
+ // null for service workers created for update checks, as the optimization
+ // would be wasteful because these workers usually are aborted after the
+ // byte-to-byte update check before running.
+ blink.mojom.CacheStorage? cache_storage;
+
service_manager.mojom.InterfaceProvider interface_provider;
};
diff --git a/chromium/content/common/service_worker/service_worker_types.cc b/chromium/content/common/service_worker/service_worker_types.cc
index 4f93a652e54..97f523803f3 100644
--- a/chromium/content/common/service_worker/service_worker_types.cc
+++ b/chromium/content/common/service_worker/service_worker_types.cc
@@ -4,6 +4,7 @@
#include "content/common/service_worker/service_worker_types.h"
+#include "content/common/service_worker/service_worker_types.pb.h"
#include "net/base/load_flags.h"
#include "storage/common/blob_storage/blob_handle.h"
@@ -55,6 +56,28 @@ ServiceWorkerFetchRequest& ServiceWorkerFetchRequest::operator=(
ServiceWorkerFetchRequest::~ServiceWorkerFetchRequest() {}
+std::string ServiceWorkerFetchRequest::Serialize() const {
+ proto::internal::ServiceWorkerFetchRequest request_proto;
+
+ request_proto.set_url(url.spec());
+ request_proto.set_method(method);
+ request_proto.mutable_headers()->insert(headers.begin(), headers.end());
+ request_proto.mutable_referrer()->set_url(referrer.url.spec());
+ request_proto.mutable_referrer()->set_policy(referrer.policy);
+ request_proto.set_is_reload(is_reload);
+ request_proto.set_mode(static_cast<int>(mode));
+ request_proto.set_is_main_resource_load(is_main_resource_load);
+ request_proto.set_request_context_type(request_context_type);
+ request_proto.set_credentials_mode(static_cast<int>(credentials_mode));
+ request_proto.set_cache_mode(static_cast<int>(cache_mode));
+ request_proto.set_redirect_mode(static_cast<int>(redirect_mode));
+ request_proto.set_integrity(integrity);
+ request_proto.set_keepalive(keepalive);
+ request_proto.set_client_id(client_id);
+
+ return request_proto.SerializeAsString();
+}
+
size_t ServiceWorkerFetchRequest::EstimatedStructSize() {
size_t size = sizeof(ServiceWorkerFetchRequest);
size += url.spec().size();
@@ -69,6 +92,40 @@ size_t ServiceWorkerFetchRequest::EstimatedStructSize() {
}
// static
+ServiceWorkerFetchRequest ServiceWorkerFetchRequest::ParseFromString(
+ const std::string& serialized) {
+ proto::internal::ServiceWorkerFetchRequest request_proto;
+ if (!request_proto.ParseFromString(serialized)) {
+ return ServiceWorkerFetchRequest();
+ }
+
+ ServiceWorkerFetchRequest request(
+ GURL(request_proto.url()), request_proto.method(),
+ ServiceWorkerHeaderMap(request_proto.headers().begin(),
+ request_proto.headers().end()),
+ Referrer(GURL(request_proto.referrer().url()),
+ static_cast<blink::WebReferrerPolicy>(
+ request_proto.referrer().policy())),
+ request_proto.is_reload());
+ request.mode =
+ static_cast<network::mojom::FetchRequestMode>(request_proto.mode());
+ request.is_main_resource_load = request_proto.is_main_resource_load();
+ request.request_context_type =
+ static_cast<RequestContextType>(request_proto.request_context_type());
+ request.credentials_mode = static_cast<network::mojom::FetchCredentialsMode>(
+ request_proto.credentials_mode());
+ request.cache_mode =
+ static_cast<blink::mojom::FetchCacheMode>(request_proto.cache_mode());
+ request.redirect_mode = static_cast<network::mojom::FetchRedirectMode>(
+ request_proto.redirect_mode());
+ request.integrity = request_proto.integrity();
+ request.keepalive = request_proto.keepalive();
+ request.client_id = request_proto.client_id();
+
+ return request;
+}
+
+// static
blink::mojom::FetchCacheMode
ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(int load_flags) {
if (load_flags & net::LOAD_DISABLE_CACHE)
diff --git a/chromium/content/common/service_worker/service_worker_types.h b/chromium/content/common/service_worker/service_worker_types.h
index bf4983a15ce..15b83155507 100644
--- a/chromium/content/common/service_worker/service_worker_types.h
+++ b/chromium/content/common/service_worker/service_worker_types.h
@@ -90,10 +90,14 @@ struct CONTENT_EXPORT ServiceWorkerFetchRequest {
ServiceWorkerFetchRequest& operator=(const ServiceWorkerFetchRequest& other);
~ServiceWorkerFetchRequest();
size_t EstimatedStructSize();
+ std::string Serialize() const;
static blink::mojom::FetchCacheMode GetCacheModeFromLoadFlags(int load_flags);
+ static ServiceWorkerFetchRequest ParseFromString(
+ const std::string& serialized);
- // Be sure to update EstimatedStructSize() when adding members.
+ // Be sure to update EstimatedStructSize(), Serialize(), and ParseFromString()
+ // when adding members.
network::mojom::FetchRequestMode mode =
network::mojom::FetchRequestMode::kNoCORS;
bool is_main_resource_load = false;
diff --git a/chromium/content/common/service_worker/service_worker_types.proto b/chromium/content/common/service_worker/service_worker_types.proto
new file mode 100644
index 00000000000..f4470b521f7
--- /dev/null
+++ b/chromium/content/common/service_worker/service_worker_types.proto
@@ -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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content.proto.internal;
+
+// Serializable version of ServiceWorkerFetchRequest.
+//
+// Next Tag: 15
+message ServiceWorkerFetchRequest {
+ // Serializable version of the Referrer struct defined in
+ // https://cs.chromium.org/chromium/src/content/public/common/referrer.h
+ //
+ // Next Tag: 3
+ message Referrer {
+ optional string url = 1;
+ optional int32 policy = 2; // blink::WebReferrerPolicy.
+ }
+
+ // Constructor params.
+ optional string url = 1;
+ optional string method = 2;
+ map<string, string> headers = 3;
+ optional Referrer referrer = 4;
+ optional bool is_reload = 5;
+
+ // Other params.
+ optional int32 mode = 6; // network::mojom::FetchRequestMode.
+ optional bool is_main_resource_load = 7;
+ optional int32 request_context_type = 8; // content::RequestContextType.
+ optional int32 credentials_mode = 9; // network::mojom::FetchCredentialsMode.
+ optional int32 cache_mode = 10; // blink::mojom::FetchCacheMode.
+ optional int32 redirect_mode = 11; // network::mojom::FetchRedirectMode.
+ optional string integrity = 12;
+ optional bool keepalive = 13;
+ optional string client_id = 14;
+} \ No newline at end of file
diff --git a/chromium/content/common/service_worker/service_worker_types_unittest.cc b/chromium/content/common/service_worker/service_worker_types_unittest.cc
index 9a5373ac91c..8a077d53982 100644
--- a/chromium/content/common/service_worker/service_worker_types_unittest.cc
+++ b/chromium/content/common/service_worker/service_worker_types_unittest.cc
@@ -3,7 +3,13 @@
// found in the LICENSE file.
#include "content/common/service_worker/service_worker_types.h"
+#include "base/guid.h"
+#include "content/common/service_worker/service_worker_fetch_response_mojom_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom.h"
+#include "url/mojom/url_gurl_mojom_traits.h"
#include "net/base/load_flags.h"
@@ -39,6 +45,65 @@ TEST(ServiceWorkerFetchRequestTest, CacheModeTest) {
net::LOAD_ONLY_FROM_CACHE | net::LOAD_BYPASS_CACHE));
}
+// Tests that mojo serialization/deserialization of ServiceWorkerResponse works.
+TEST(ServiceWorkerResponseTest, StructTraits) {
+ ServiceWorkerResponse input;
+ ServiceWorkerResponse output;
+
+ input.url_list = {GURL("https://www.google.ca/"),
+ GURL("https://www.google.com")};
+ input.status_code = 200;
+ input.status_text = "status_text";
+ input.response_type = network::mojom::FetchResponseType::kDefault;
+ input.headers.insert(
+ std::pair<std::string, std::string>("header1", "value1"));
+ input.headers.insert(
+ std::pair<std::string, std::string>("header2", "value2"));
+ input.error = blink::mojom::ServiceWorkerResponseError::kUnknown;
+ input.response_time = base::Time::Now();
+ input.is_in_cache_storage = true;
+ input.cache_storage_cache_name = "cache_name";
+
+ mojo::test::SerializeAndDeserialize<blink::mojom::FetchAPIResponse>(&input,
+ &output);
+
+ EXPECT_EQ(input.url_list, output.url_list);
+ EXPECT_EQ(input.status_code, output.status_code);
+ EXPECT_EQ(input.status_text, output.status_text);
+ EXPECT_EQ(input.response_type, output.response_type);
+ EXPECT_EQ(input.headers, output.headers);
+ EXPECT_EQ(input.blob, output.blob);
+ EXPECT_EQ(input.error, output.error);
+ EXPECT_EQ(input.response_time, output.response_time);
+ EXPECT_EQ(input.is_in_cache_storage, output.is_in_cache_storage);
+ EXPECT_EQ(input.cache_storage_cache_name, output.cache_storage_cache_name);
+ EXPECT_EQ(input.cors_exposed_header_names, output.cors_exposed_header_names);
+ EXPECT_EQ(input.side_data_blob, output.side_data_blob);
+}
+
+TEST(ServiceWorkerRequestTest, SerialiazeDeserializeRoundTrip) {
+ ServiceWorkerFetchRequest request(
+ GURL("foo.com"), "GET", {{"User-Agent", "Chrome"}},
+ Referrer(
+ GURL("bar.com"),
+ blink::WebReferrerPolicy::kWebReferrerPolicyNoReferrerWhenDowngrade),
+ true);
+ request.mode = network::mojom::FetchRequestMode::kSameOrigin;
+ request.is_main_resource_load = true;
+ request.request_context_type =
+ RequestContextType::REQUEST_CONTEXT_TYPE_IFRAME;
+ request.credentials_mode = network::mojom::FetchCredentialsMode::kSameOrigin;
+ request.cache_mode = blink::mojom::FetchCacheMode::kForceCache;
+ request.redirect_mode = network::mojom::FetchRedirectMode::kManual;
+ request.integrity = "integrity";
+ request.keepalive = true;
+ request.client_id = "42";
+
+ EXPECT_EQ(request.Serialize(),
+ ServiceWorkerFetchRequest::ParseFromString(request.Serialize())
+ .Serialize());
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/common/service_worker/service_worker_utils.cc b/chromium/content/common/service_worker/service_worker_utils.cc
index 918b5a7dae1..0820aad1064 100644
--- a/chromium/content/common/service_worker/service_worker_utils.cc
+++ b/chromium/content/common/service_worker/service_worker_utils.cc
@@ -186,6 +186,12 @@ bool ServiceWorkerUtils::ExtractSinglePartHttpRange(
const net::HttpByteRange& byte_range = ranges[0];
if (byte_range.first_byte_position() < 0)
return false;
+ // Allow the range [0, -1] to be valid and specify the entire range.
+ if (byte_range.first_byte_position() == 0 &&
+ byte_range.last_byte_position() == -1) {
+ *has_range_out = false;
+ return true;
+ }
if (byte_range.last_byte_position() < 0)
return false;
@@ -206,6 +212,21 @@ bool ServiceWorkerUtils::ExtractSinglePartHttpRange(
return true;
}
+bool ServiceWorkerUtils::ShouldBypassCacheDueToUpdateViaCache(
+ bool is_main_script,
+ blink::mojom::ServiceWorkerUpdateViaCache cache_mode) {
+ switch (cache_mode) {
+ case blink::mojom::ServiceWorkerUpdateViaCache::kImports:
+ return is_main_script;
+ case blink::mojom::ServiceWorkerUpdateViaCache::kNone:
+ return true;
+ case blink::mojom::ServiceWorkerUpdateViaCache::kAll:
+ return false;
+ }
+ NOTREACHED() << static_cast<int>(cache_mode);
+ return false;
+}
+
bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
if (!ServiceWorkerUtils::ScopeMatches(scope, url_))
return false;
diff --git a/chromium/content/common/service_worker/service_worker_utils.h b/chromium/content/common/service_worker/service_worker_utils.h
index 9df6f6668ae..e7ce9c975f1 100644
--- a/chromium/content/common/service_worker/service_worker_utils.h
+++ b/chromium/content/common/service_worker/service_worker_utils.h
@@ -51,7 +51,6 @@ class ServiceWorkerUtils {
// Returns true if servicified service worker is enabled.
CONTENT_EXPORT static bool IsServicificationEnabled();
- // PlzNavigate
// Returns true if the |provider_id| was assigned by the browser process.
static bool IsBrowserAssignedProviderId(int provider_id) {
return provider_id < kInvalidServiceWorkerProviderId;
@@ -71,6 +70,10 @@ class ServiceWorkerUtils {
bool* has_range_out,
uint64_t* offset_out,
uint64_t* size_out);
+
+ static bool ShouldBypassCacheDueToUpdateViaCache(
+ bool is_main_script,
+ blink::mojom::ServiceWorkerUpdateViaCache cache_mode);
};
class CONTENT_EXPORT LongestScopeMatcher {
diff --git a/chromium/content/common/single_request_url_loader_factory.cc b/chromium/content/common/single_request_url_loader_factory.cc
index 1a3828903af..3c1a19b1bd6 100644
--- a/chromium/content/common/single_request_url_loader_factory.cc
+++ b/chromium/content/common/single_request_url_loader_factory.cc
@@ -88,6 +88,11 @@ void SingleRequestURLLoaderFactory::CreateLoaderAndStart(
state_->HandleRequest(std::move(loader), std::move(client));
}
+void SingleRequestURLLoaderFactory::Clone(
+ network::mojom::URLLoaderFactoryRequest request) {
+ NOTREACHED();
+}
+
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
SingleRequestURLLoaderFactory::Clone() {
return std::make_unique<FactoryInfo>(state_);
diff --git a/chromium/content/common/single_request_url_loader_factory.h b/chromium/content/common/single_request_url_loader_factory.h
index 0250e786be4..9069591c060 100644
--- a/chromium/content/common/single_request_url_loader_factory.h
+++ b/chromium/content/common/single_request_url_loader_factory.h
@@ -32,6 +32,7 @@ class SingleRequestURLLoaderFactory : public network::SharedURLLoaderFactory {
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override;
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
private:
diff --git a/chromium/content/common/speech_recognition_messages.h b/chromium/content/common/speech_recognition_messages.h
deleted file mode 100644
index a7843381fac..00000000000
--- a/chromium/content/common/speech_recognition_messages.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_SPEECH_RECOGNITION_MESSAGES_H_
-#define CONTENT_COMMON_SPEECH_RECOGNITION_MESSAGES_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "content/public/common/speech_recognition_error.h"
-#include "content/public/common/speech_recognition_grammar.h"
-#include "content/public/common/speech_recognition_result.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-#include "ui/gfx/geometry/rect.h"
-
-#define IPC_MESSAGE_START SpeechRecognitionMsgStart
-
-IPC_ENUM_TRAITS_MAX_VALUE(content::SpeechAudioErrorDetails,
- content::SPEECH_AUDIO_ERROR_DETAILS_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(content::SpeechRecognitionErrorCode,
- content::SPEECH_RECOGNITION_ERROR_LAST)
-
-IPC_STRUCT_TRAITS_BEGIN(content::SpeechRecognitionError)
- IPC_STRUCT_TRAITS_MEMBER(code)
- IPC_STRUCT_TRAITS_MEMBER(details)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::SpeechRecognitionHypothesis)
- IPC_STRUCT_TRAITS_MEMBER(utterance)
- IPC_STRUCT_TRAITS_MEMBER(confidence)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::SpeechRecognitionResult)
- IPC_STRUCT_TRAITS_MEMBER(is_provisional)
- IPC_STRUCT_TRAITS_MEMBER(hypotheses)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::SpeechRecognitionGrammar)
- IPC_STRUCT_TRAITS_MEMBER(url)
- IPC_STRUCT_TRAITS_MEMBER(weight)
-IPC_STRUCT_TRAITS_END()
-
-// ------- Messages for Speech JS APIs (SpeechRecognitionDispatcher) ----------
-
-// Renderer -> Browser messages.
-
-// Used to start a speech recognition session.
-IPC_STRUCT_BEGIN(SpeechRecognitionHostMsg_StartRequest_Params)
- // The render frame requesting speech recognition.
- IPC_STRUCT_MEMBER(int, render_frame_id)
- // Unique ID associated with the JS object making the calls.
- IPC_STRUCT_MEMBER(int, request_id)
- // Language to use for speech recognition.
- IPC_STRUCT_MEMBER(std::string, language)
- // Speech grammars to use.
- IPC_STRUCT_MEMBER(content::SpeechRecognitionGrammarArray, grammars)
- // URL of the page (or iframe if applicable).
- IPC_STRUCT_MEMBER(std::string, origin_url)
- // Maximum number of hypotheses allowed for each results.
- IPC_STRUCT_MEMBER(uint32_t, max_hypotheses)
- // Whether the user requested continuous recognition or not.
- IPC_STRUCT_MEMBER(bool, continuous)
- // Whether the user requested interim results or not.
- IPC_STRUCT_MEMBER(bool, interim_results)
-IPC_STRUCT_END()
-
-
-// Requests the speech recognition service to start speech recognition.
-IPC_MESSAGE_CONTROL1(SpeechRecognitionHostMsg_StartRequest,
- SpeechRecognitionHostMsg_StartRequest_Params)
-
-// Requests the speech recognition service to abort speech recognition on
-// behalf of the given |render_frame_id| and |request_id|. If there are no
-// sessions associated with the |request_id| in the render frame, this call
-// does nothing.
-IPC_MESSAGE_CONTROL2(SpeechRecognitionHostMsg_AbortRequest,
- int /* render_frame_id */,
- int /* request_id */)
-
-// Requests the speech recognition service to abort all speech recognitions on
-// behalf of the given |render_frame_id|. If speech recognition is not happening
-// or is happening on behalf of some other render frame, this call does nothing.
-IPC_MESSAGE_CONTROL1(SpeechRecognitionHostMsg_AbortAllRequests,
- int /* render_frame_id */)
-
-// Requests the speech recognition service to stop audio capture on behalf of
-// the given |render_frame_id|. Any audio recorded so far will be fed to the
-// speech recognizer. If speech recognition is not happening nor or is
-// happening on behalf of some other render frame, this call does nothing.
-IPC_MESSAGE_CONTROL2(SpeechRecognitionHostMsg_StopCaptureRequest,
- int /* render_frame_id */,
- int /* request_id */)
-
-// Browser -> Renderer messages.
-
-// The messages below follow exactly the same semantic of the corresponding
-// events defined in content/public/browser/speech_recognition_event_listener.h.
-IPC_MESSAGE_ROUTED2(SpeechRecognitionMsg_ResultRetrieved,
- int /* request_id */,
- content::SpeechRecognitionResults /* results */)
-
-IPC_MESSAGE_ROUTED2(SpeechRecognitionMsg_ErrorOccurred,
- int /* request_id */,
- content::SpeechRecognitionError /* error */)
-
-IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_Started, int /* request_id */)
-
-IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_AudioStarted, int /* request_id */)
-
-IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_SoundStarted, int /* request_id */)
-
-IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_SoundEnded, int /* request_id */)
-
-IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_AudioEnded, int /* request_id */)
-
-IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_Ended, int /* request_id */)
-
-#endif // CONTENT_COMMON_SPEECH_RECOGNITION_MESSAGES_H_
diff --git a/chromium/content/common/speech_recognizer.mojom b/chromium/content/common/speech_recognizer.mojom
new file mode 100644
index 00000000000..f790d4c93cb
--- /dev/null
+++ b/chromium/content/common/speech_recognizer.mojom
@@ -0,0 +1,95 @@
+// 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.
+
+module content.mojom;
+
+import "content/public/common/speech_recognition_grammar.mojom";
+import "content/public/common/speech_recognition_result.mojom";
+import "content/public/common/speech_recognition_error.mojom";
+import "url/mojom/origin.mojom";
+
+// Created by the renderer and sent to the browser to start a speech recognition
+// session.
+struct StartSpeechRecognitionRequestParams {
+ // Used to create a connection with a SpeechRecognitionSession implementation
+ // that will be created when the session is created.
+ SpeechRecognitionSession& session_request;
+
+ // Used by the browser to communicate with a SpeechRecognitionSessionClient
+ // implementation created for the new session.
+ SpeechRecognitionSessionClient client;
+
+ // Language to use for speech recognition.
+ string language;
+
+ // Speech grammars to use.
+ array<content.mojom.SpeechRecognitionGrammar> grammars;
+
+ // URL of the page (or iframe if applicable).
+ url.mojom.Origin origin;
+
+ // Maximum number of hypotheses allowed for each results.
+ uint32 max_hypotheses;
+
+ // Whether the user requested continuous recognition.
+ bool continuous;
+
+ // Whether the user requested interim results.
+ bool interim_results;
+};
+
+// API for the renderer process to start a speech recognition session in the
+// browser process.
+interface SpeechRecognizer {
+ // Requests the speech recognition service to start speech recognition.
+ Start(StartSpeechRecognitionRequestParams params);
+};
+
+// API for the renderer process to stop or abort an existing speech recognition
+// session. An InterfaceRequest is sent to the browser process via
+// SpeechRecognizer::Start, and is bound to an implementation there.
+// SpeechRecognitionSession and SpeechRecognitionSessionClient are 1:1 with each
+// other and with WebSpeechRecognitionHandle.
+interface SpeechRecognitionSession {
+ // Requests the speech recognition service to abort speech recognition for the
+ // associated session.
+ Abort();
+
+ // Requests the speech recognition service to stop audio capture for the
+ // associated session.
+ StopCapture();
+};
+
+// API for the browser process to communicate speech recognition related updates
+// with renderer and cause events to be dispatched to the appropriate speech
+// recognition handle. An InterfacePtr for each handle is sent to the browser
+// process via SpeechRecognizer::Start. SpeechRecognitionSession and
+// SpeechRecognitionSessionClient are 1:1 with each other and with
+// WebSpeechRecognitionHandle.
+interface SpeechRecognitionSessionClient {
+ // Called to dispatch the "result" event.
+ ResultRetrieved(array<content.mojom.SpeechRecognitionResult> results);
+
+ // Called to dispatch the "nomatch" event if the error code passed is of types
+ // kNoMatch, otherwise dispatchers an "error" event.
+ ErrorOccurred(content.mojom.SpeechRecognitionError error);
+
+ // Called to dispatch the "start" event.
+ Started();
+
+ // Called to dispatch the "audiostart" event.
+ AudioStarted();
+
+ // Called to dispatch the "soundstart" and "speechstart" events.
+ SoundStarted();
+
+ // Called to dispatch "soundend" and "speechend" events.
+ SoundEnded();
+
+ // Called to dispatch the "audioend" event.
+ AudioEnded();
+
+ // Called to dispatch the "end" event.
+ Ended();
+};
diff --git a/chromium/content/common/swapped_out_messages.cc b/chromium/content/common/swapped_out_messages.cc
index d7747d332a2..65cbd051764 100644
--- a/chromium/content/common/swapped_out_messages.cc
+++ b/chromium/content/common/swapped_out_messages.cc
@@ -6,8 +6,6 @@
#include "content/common/accessibility_messages.h"
#include "content/common/frame_messages.h"
-#include "content/common/input/sync_compositor_messages.h"
-#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_client.h"
@@ -18,10 +16,6 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
// important (e.g., ACKs) for keeping the browser and renderer state
// consistent in case we later return to the same renderer.
switch (msg->type()) {
- // Handled by RenderWidgetHost.
- case InputHostMsg_HandleInputEvent_ACK::ID:
- case SyncCompositorHostMsg_SetNeedsBeginFrames::ID:
- case ViewHostMsg_ResizeOrRepaint_ACK::ID:
// Handled by RenderViewHost.
case FrameHostMsg_RenderProcessGone::ID:
case ViewHostMsg_ClosePage_ACK::ID:
diff --git a/chromium/content/common/throttling_url_loader.cc b/chromium/content/common/throttling_url_loader.cc
index 0d0ba0268bf..28a8b328015 100644
--- a/chromium/content/common/throttling_url_loader.cc
+++ b/chromium/content/common/throttling_url_loader.cc
@@ -181,7 +181,7 @@ ThrottlingURLLoader::~ThrottlingURLLoader() {
void ThrottlingURLLoader::FollowRedirect() {
if (url_loader_)
- url_loader_->FollowRedirect();
+ url_loader_->FollowRedirect(base::nullopt);
}
void ThrottlingURLLoader::SetPriority(net::RequestPriority priority,
diff --git a/chromium/content/common/throttling_url_loader_unittest.cc b/chromium/content/common/throttling_url_loader_unittest.cc
index b7a22c10b4f..3f6b1610048 100644
--- a/chromium/content/common/throttling_url_loader_unittest.cc
+++ b/chromium/content/common/throttling_url_loader_unittest.cc
@@ -9,8 +9,8 @@
#include "base/test/scoped_task_environment.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/url_loader_throttle.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -26,8 +26,9 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
public:
TestURLLoaderFactory() : binding_(this), url_loader_binding_(this) {
binding_.Bind(mojo::MakeRequest(&factory_ptr_));
- shared_factory_ = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
- factory_ptr_.get());
+ shared_factory_ =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ factory_ptr_.get());
}
~TestURLLoaderFactory() override { shared_factory_->Detach(); }
@@ -94,7 +95,8 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
}
// network::mojom::URLLoader implementation.
- void FollowRedirect() override {}
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {}
void ProceedWithResponse() override {}
void SetPriority(net::RequestPriority priority,
@@ -116,7 +118,7 @@ class TestURLLoaderFactory : public network::mojom::URLLoaderFactory,
mojo::Binding<network::mojom::URLLoader> url_loader_binding_;
network::mojom::URLLoaderFactoryPtr factory_ptr_;
network::mojom::URLLoaderClientPtr client_ptr_;
- scoped_refptr<WeakWrapperSharedURLLoaderFactory> shared_factory_;
+ scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> shared_factory_;
DISALLOW_COPY_AND_ASSIGN(TestURLLoaderFactory);
};
diff --git a/chromium/content/common/typemaps.gni b/chromium/content/common/typemaps.gni
index 27721793d20..f1da0657d12 100644
--- a/chromium/content/common/typemaps.gni
+++ b/chromium/content/common/typemaps.gni
@@ -4,7 +4,6 @@
typemaps = [
"//content/common/background_fetch/background_fetch_types.typemap",
- "//content/common/cache_storage/cache_storage.typemap",
"//content/common/frame.typemap",
"//content/common/frame_messages.typemap",
"//content/common/input/synchronous_compositor.typemap",
diff --git a/chromium/content/common/url_loader_factory_bundle.cc b/chromium/content/common/url_loader_factory_bundle.cc
index e3d31d68690..28fd78fde19 100644
--- a/chromium/content/common/url_loader_factory_bundle.cc
+++ b/chromium/content/common/url_loader_factory_bundle.cc
@@ -78,6 +78,11 @@ void URLLoaderFactoryBundle::CreateLoaderAndStart(
traffic_annotation);
}
+void URLLoaderFactoryBundle::Clone(
+ network::mojom::URLLoaderFactoryRequest request) {
+ NOTREACHED();
+}
+
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
URLLoaderFactoryBundle::Clone() {
network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
diff --git a/chromium/content/common/url_loader_factory_bundle.h b/chromium/content/common/url_loader_factory_bundle.h
index 3db8f4fc096..1883f494ebc 100644
--- a/chromium/content/common/url_loader_factory_bundle.h
+++ b/chromium/content/common/url_loader_factory_bundle.h
@@ -81,7 +81,7 @@ class CONTENT_EXPORT URLLoaderFactoryBundle
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
-
+ void Clone(network::mojom::URLLoaderFactoryRequest request) override;
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
// The |info| contains replacement factories for a subset of the existing
diff --git a/chromium/content/common/url_schemes.cc b/chromium/content/common/url_schemes.cc
index a269e1de2cb..8e4a1eb7f38 100644
--- a/chromium/content/common/url_schemes.cc
+++ b/chromium/content/common/url_schemes.cc
@@ -37,10 +37,10 @@ std::vector<std::string>& GetMutableSavableSchemes() {
return *schemes;
}
-// Note we store url::Origins here instead of strings to deal with
-// canonicalization.
-std::vector<url::Origin>& GetMutableSecureOrigins() {
- static base::NoDestructor<std::vector<url::Origin>> origins;
+// This set contains serialized canonicalized origins as well as hostname
+// patterns. The latter are canonicalized by component.
+std::vector<std::string>& GetMutableSecureOriginsAndPatterns() {
+ static base::NoDestructor<std::vector<std::string>> origins;
return *origins;
}
@@ -58,6 +58,7 @@ void RegisterContentSchemes(bool lock_schemes) {
url::AddStandardScheme(kChromeDevToolsScheme, url::SCHEME_WITH_HOST);
url::AddStandardScheme(kChromeUIScheme, url::SCHEME_WITH_HOST);
url::AddStandardScheme(kGuestScheme, url::SCHEME_WITH_HOST);
+ url::AddStandardScheme(kChromeErrorScheme, url::SCHEME_WITH_HOST);
for (auto& scheme : schemes.standard_schemes)
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
@@ -106,16 +107,16 @@ void RegisterContentSchemes(bool lock_schemes) {
GetMutableServiceWorkerSchemes() = std::move(schemes.service_worker_schemes);
- GetMutableSecureOrigins() = std::move(schemes.secure_origins);
- network::cors::legacy::RegisterSecureOrigins(GetSecureOrigins());
+ GetMutableSecureOriginsAndPatterns() = std::move(schemes.secure_origins);
+ network::cors::legacy::RegisterSecureOrigins(GetSecureOriginsAndPatterns());
}
const std::vector<std::string>& GetSavableSchemes() {
return GetMutableSavableSchemes();
}
-const std::vector<url::Origin>& GetSecureOrigins() {
- return GetMutableSecureOrigins();
+const std::vector<std::string>& GetSecureOriginsAndPatterns() {
+ return GetMutableSecureOriginsAndPatterns();
}
const std::vector<std::string>& GetServiceWorkerSchemes() {
diff --git a/chromium/content/common/url_schemes.h b/chromium/content/common/url_schemes.h
index 52ac01845df..802c80b241c 100644
--- a/chromium/content/common/url_schemes.h
+++ b/chromium/content/common/url_schemes.h
@@ -28,7 +28,11 @@ CONTENT_EXPORT void RegisterContentSchemes(bool lock_schemes);
// See comment in ContentClient::AddAdditionalSchemes for explanations. These
// getters can be invoked on any thread.
const std::vector<std::string>& GetSavableSchemes();
-const std::vector<url::Origin>& GetSecureOrigins();
+// Contains serialized canonicalized origins as well as hostname patterns such
+// as "*.foo.com". An origin should be considered secure if it matches an origin
+// in this list or if its hostname matches one of the hostname patterns. The
+// hostname patterns are canonicalized by component.
+const std::vector<std::string>& GetSecureOriginsAndPatterns();
const std::vector<std::string>& GetServiceWorkerSchemes();
} // namespace content
diff --git a/chromium/content/common/user_agent.cc b/chromium/content/common/user_agent.cc
index b071e6ba90d..e4565757f88 100644
--- a/chromium/content/common/user_agent.cc
+++ b/chromium/content/common/user_agent.cc
@@ -13,12 +13,10 @@
#include "build/build_config.h"
#include "build/util/webkit_version.h"
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-#include <sys/utsname.h>
-#endif
-
#if defined(OS_WIN)
#include "base/win/windows_version.h"
+#elif (defined(OS_POSIX) && !defined(OS_MACOSX)) || defined(OS_FUCHSIA)
+#include <sys/utsname.h>
#endif
namespace content {
@@ -47,21 +45,6 @@ std::string BuildOSCpuInfo() {
&os_bugfix_version);
#endif
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
- // Should work on any Posix system.
- struct utsname unixinfo;
- uname(&unixinfo);
-
- std::string cputype;
- // special case for biarch systems
- if (strcmp(unixinfo.machine, "x86_64") == 0 &&
- sizeof(void*) == sizeof(int32_t)) { // NOLINT
- cputype.assign("i686 (x86_64)");
- } else {
- cputype.assign(unixinfo.machine);
- }
-#endif
-
#if defined(OS_WIN)
std::string architecture_token;
base::win::OSInfo* os_info = base::win::OSInfo::GetInstance();
@@ -75,9 +58,7 @@ std::string BuildOSCpuInfo() {
else if (windows_architecture == base::win::OSInfo::IA64_ARCHITECTURE)
architecture_token = "; Win64; IA64";
}
-#endif
-
-#if defined(OS_ANDROID)
+#elif defined(OS_ANDROID)
std::string android_version_str = base::SysInfo::OperatingSystemVersion();
std::string android_info_str;
@@ -99,6 +80,19 @@ std::string BuildOSCpuInfo() {
}
android_info_str += " Build/" + android_build_id;
}
+#elif (defined(OS_POSIX) && !defined(OS_MACOSX)) || defined(OS_FUCHSIA)
+ // Should work on any Posix system.
+ struct utsname unixinfo;
+ uname(&unixinfo);
+
+ std::string cputype;
+ // special case for biarch systems
+ if (strcmp(unixinfo.machine, "x86_64") == 0 &&
+ sizeof(void*) == sizeof(int32_t)) { // NOLINT
+ cputype.assign("i686 (x86_64)");
+ } else {
+ cputype.assign(unixinfo.machine);
+ }
#endif
base::StringAppendF(
@@ -124,10 +118,10 @@ std::string BuildOSCpuInfo() {
"Android %s%s",
android_version_str.c_str(),
android_info_str.c_str()
-#else
- "%s %s",
- unixinfo.sysname, // e.g. Linux
- cputype.c_str() // e.g. i686
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+ "%s %s",
+ unixinfo.sysname, // e.g. Linux
+ cputype.c_str() // e.g. i686
#endif
); // NOLINT
@@ -144,7 +138,7 @@ std::string getUserAgentPlatform() {
"X11; "; // strange, but that's what Firefox uses
#elif defined(OS_ANDROID)
"Linux; ";
-#else
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
"Unknown; ";
#endif
}
diff --git a/chromium/content/common/view_messages.h b/chromium/content/common/view_messages.h
index 1f619836b51..7411a755dd7 100644
--- a/chromium/content/common/view_messages.h
+++ b/chromium/content/common/view_messages.h
@@ -15,10 +15,11 @@
#include <vector>
#include "base/memory/shared_memory.h"
+#include "base/optional.h"
#include "base/process/process.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
-#include "cc/ipc/cc_param_traits.h"
+#include "cc/input/touch_action.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/shared_bitmap.h"
@@ -27,9 +28,9 @@
#include "content/common/date_time_suggestion.h"
#include "content/common/frame_replication_state.h"
#include "content/common/navigation_gesture.h"
-#include "content/common/resize_params.h"
#include "content/common/text_input_state.h"
#include "content/common/view_message_enums.h"
+#include "content/common/visual_properties.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/menu_item.h"
#include "content/public/common/page_state.h"
@@ -45,8 +46,8 @@
#include "media/capture/ipc/capture_param_traits.h"
#include "net/base/network_change_notifier.h"
#include "ppapi/buildflags/buildflags.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_type.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
+#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h"
#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_intrinsic_sizing_info.h"
@@ -160,12 +161,11 @@ IPC_STRUCT_TRAITS_BEGIN(blink::WebDeviceEmulationParams)
IPC_STRUCT_TRAITS_MEMBER(screen_orientation_type)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::ResizeParams)
+IPC_STRUCT_TRAITS_BEGIN(content::VisualProperties)
IPC_STRUCT_TRAITS_MEMBER(screen_info)
IPC_STRUCT_TRAITS_MEMBER(auto_resize_enabled)
IPC_STRUCT_TRAITS_MEMBER(min_size_for_auto_resize)
IPC_STRUCT_TRAITS_MEMBER(max_size_for_auto_resize)
- IPC_STRUCT_TRAITS_MEMBER(auto_resize_sequence_number)
IPC_STRUCT_TRAITS_MEMBER(new_size)
IPC_STRUCT_TRAITS_MEMBER(compositor_viewport_pixel_size)
IPC_STRUCT_TRAITS_MEMBER(browser_controls_shrink_blink_size)
@@ -176,8 +176,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::ResizeParams)
IPC_STRUCT_TRAITS_MEMBER(visible_viewport_size)
IPC_STRUCT_TRAITS_MEMBER(is_fullscreen_granted)
IPC_STRUCT_TRAITS_MEMBER(display_mode)
- IPC_STRUCT_TRAITS_MEMBER(needs_resize_ack)
- IPC_STRUCT_TRAITS_MEMBER(content_source_id)
+ IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::MenuItem)
@@ -281,33 +280,6 @@ IPC_STRUCT_BEGIN(ViewHostMsg_SelectionBounds_Params)
IPC_STRUCT_MEMBER(bool, is_anchor_first)
IPC_STRUCT_END()
-IPC_STRUCT_BEGIN(ViewHostMsg_ResizeOrRepaint_ACK_Params)
- // The size of the RenderView when this message was generated. This is
- // included so the host knows how large the view is from the perspective of
- // the renderer process. This is necessary in case a resize operation is in
- // progress. If auto-resize is enabled, this should update the corresponding
- // view size.
- IPC_STRUCT_MEMBER(gfx::Size, view_size)
-
- // The following describes the various bits that may be set in flags:
- //
- // ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK
- // Indicates that this is a response to a ViewMsg_Resize message.
- //
- // ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_REPAINT_ACK
- // Indicates that this is a response to a ViewMsg_Repaint message.
- //
- // If flags is zero, then this message corresponds to an unsolicited paint
- // request by the render view. Any of the above bits may be set in flags,
- // which would indicate that this paint message is an ACK for multiple
- // request messages.
- IPC_STRUCT_MEMBER(int, flags)
-
- // A unique monotonically increasing sequence number used to identify this
- // ACK.
- IPC_STRUCT_MEMBER(uint64_t, sequence_number)
-IPC_STRUCT_END()
-
// Messages sent from the browser to the renderer.
#if defined(OS_ANDROID)
@@ -340,12 +312,14 @@ IPC_MESSAGE_ROUTED1(ViewMsg_UpdateWebPreferences,
// Expects a Close_ACK message when finished.
IPC_MESSAGE_ROUTED0(ViewMsg_Close)
-// Tells the render view to change its size. A ViewHostMsg_ResizeOrRepaint_ACK
-// message is generated in response provided new_size is not empty and not equal
-// to the view's current size. The generated ViewHostMsg_ResizeOrRepaint_ACK
+// Tells the renderer to update visual properties. A
+// ViewHostMsg_ResizeOrRepaint_ACK message is generated in response provided
+// new_size is not empty and not equal to the view's current size. The
+// generated ViewHostMsg_ResizeOrRepaint_ACK
// message will have the IS_RESIZE_ACK flag set. It also receives the resizer
// rect so that we don't have to fetch it every time WebKit asks for it.
-IPC_MESSAGE_ROUTED1(ViewMsg_Resize, content::ResizeParams /* params */)
+IPC_MESSAGE_ROUTED1(ViewMsg_SynchronizeVisualProperties,
+ content::VisualProperties /* params */)
// Enables device emulation. See WebDeviceEmulationParams for description.
IPC_MESSAGE_ROUTED1(ViewMsg_EnableDeviceEmulation,
@@ -413,11 +387,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_EnumerateDirectoryResponse,
// Expects a ClosePage_ACK message when finished.
IPC_MESSAGE_ROUTED0(ViewMsg_ClosePage)
-// Notifies the renderer that a paint is to be generated for the rectangle
-// passed in.
-IPC_MESSAGE_ROUTED1(ViewMsg_Repaint,
- gfx::Size /* The view size to be repainted */)
-
// Notification that a move or resize renderer's containing window has
// started.
IPC_MESSAGE_ROUTED0(ViewMsg_MoveOrResizeStarted)
@@ -502,7 +471,7 @@ IPC_MESSAGE_ROUTED1(ViewMsg_PpapiBrokerPermissionResult,
// inside the popup, instruct the renderer to generate a synthetic tap at that
// offset.
IPC_MESSAGE_ROUTED3(ViewMsg_ResolveTapDisambiguation,
- double /* timestamp_seconds */,
+ base::TimeTicks /* timestamp */,
gfx::Point /* tap_viewport_offset */,
bool /* is_long_press */)
@@ -523,6 +492,9 @@ IPC_MESSAGE_ROUTED2(ViewMsg_SetViewportIntersection,
// Sets the inert bit on an out-of-process iframe.
IPC_MESSAGE_ROUTED1(ViewMsg_SetIsInert, bool /* inert */)
+// Sets the inherited effective touch action on an out-of-process iframe.
+IPC_MESSAGE_ROUTED1(ViewMsg_SetInheritedEffectiveTouchAction, cc::TouchAction)
+
// Toggles render throttling for an out-of-process iframe.
IPC_MESSAGE_ROUTED2(ViewMsg_UpdateRenderThrottlingStatus,
bool /* is_throttled */,
@@ -579,12 +551,6 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateTargetURL,
IPC_MESSAGE_ROUTED1(ViewHostMsg_DocumentAvailableInMainFrame,
bool /* uses_temporary_zoom_level */)
-// Sent as an acknowledgement to a previous resize request. This indicates that
-// the compositor has received a frame from the renderer corresponding to the
-// previous reszie request.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_ResizeOrRepaint_ACK,
- ViewHostMsg_ResizeOrRepaint_ACK_Params)
-
IPC_MESSAGE_ROUTED0(ViewHostMsg_Focus)
IPC_MESSAGE_ROUTED1(ViewHostMsg_SetCursor, content::WebCursor)
diff --git a/chromium/content/common/visual_properties.cc b/chromium/content/common/visual_properties.cc
new file mode 100644
index 00000000000..34c16c3fba5
--- /dev/null
+++ b/chromium/content/common/visual_properties.cc
@@ -0,0 +1,18 @@
+// 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.
+
+#include "content/common/visual_properties.h"
+
+namespace content {
+
+VisualProperties::VisualProperties() = default;
+
+VisualProperties::VisualProperties(const VisualProperties& other) = default;
+
+VisualProperties::~VisualProperties() = default;
+
+VisualProperties& VisualProperties::operator=(const VisualProperties& other) =
+ default;
+
+} // namespace content
diff --git a/chromium/content/common/resize_params.h b/chromium/content/common/visual_properties.h
index 51c472dd522..dd29af0cb31 100644
--- a/chromium/content/common/resize_params.h
+++ b/chromium/content/common/visual_properties.h
@@ -2,28 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_RESIZE_PARAMS_H_
-#define CONTENT_COMMON_RESIZE_PARAMS_H_
+#ifndef CONTENT_COMMON_VISUAL_PROPERTIES_H_
+#define CONTENT_COMMON_VISUAL_PROPERTIES_H_
#include "base/optional.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "content/common/content_export.h"
#include "content/public/common/screen_info.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
+#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "ui/gfx/geometry/size.h"
namespace content {
-struct CONTENT_EXPORT ResizeParams {
- ResizeParams();
- ResizeParams(const ResizeParams& other);
- ~ResizeParams();
+struct CONTENT_EXPORT VisualProperties {
+ VisualProperties();
+ VisualProperties(const VisualProperties& other);
+ ~VisualProperties();
+
+ VisualProperties& operator=(const VisualProperties& other);
// Information about the screen (dpi, depth, etc..).
ScreenInfo screen_info;
// Whether or not blink should be in auto-resize mode.
- bool auto_resize_enabled;
+ bool auto_resize_enabled = false;
// The minimum size for Blink if auto-resize is enabled.
gfx::Size min_size_for_auto_resize;
@@ -31,11 +33,6 @@ struct CONTENT_EXPORT ResizeParams {
// The maximum size for Blink if auto-resize is enabled.
gfx::Size max_size_for_auto_resize;
- // This variable is increased after each auto-resize. If the
- // renderer receives a ResizeParams with stale auto_resize_seqence_number,
- // then the resize request is dropped.
- uint64_t auto_resize_sequence_number;
-
// The size for the widget in DIPs.
gfx::Size new_size;
@@ -46,18 +43,18 @@ struct CONTENT_EXPORT ResizeParams {
// Whether or not Blink's viewport size should be shrunk by the height of the
// URL-bar (always false on platforms where URL-bar hiding isn't supported).
- bool browser_controls_shrink_blink_size;
+ bool browser_controls_shrink_blink_size = false;
// Whether or not the focused node should be scrolled into view after the
// resize.
- bool scroll_focused_node_into_view;
+ bool scroll_focused_node_into_view = false;
// The height of the top controls (always 0 on platforms where URL-bar hiding
// isn't supported).
- float top_controls_height;
+ float top_controls_height = 0.f;
// The height of the bottom controls.
- float bottom_controls_height;
+ float bottom_controls_height = 0.f;
// The local surface ID to use (if valid).
base::Optional<viz::LocalSurfaceId> local_surface_id;
@@ -68,22 +65,17 @@ struct CONTENT_EXPORT ResizeParams {
gfx::Size visible_viewport_size;
// Indicates whether tab-initiated fullscreen was granted.
- bool is_fullscreen_granted;
+ bool is_fullscreen_granted = false;
// The display mode.
- blink::WebDisplayMode display_mode;
-
- // If set, requests the renderer to reply with a
- // ViewHostMsg_ResizeOrRepaint_ACK with the
- // ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK bit set in flags.
- bool needs_resize_ack;
+ blink::WebDisplayMode display_mode = blink::kWebDisplayModeUndefined;
- // This variable is increased after each cross-document navigation. If the
- // renderer receives a ResizeParams with stale content_source_id, it still
- // performs the resize but doesn't use the given LocalSurfaceId.
- uint32_t content_source_id;
+ // This represents the latest capture sequence number requested. When this is
+ // incremented, that means the caller wants to synchronize surfaces which
+ // should cause a new LocalSurfaceId to be generated.
+ uint32_t capture_sequence_number = 0u;
};
} // namespace content
-#endif // CONTENT_COMMON_RESIZE_PARAMS_H_
+#endif // CONTENT_COMMON_VISUAL_PROPERTIES_H_
diff --git a/chromium/content/common/wrapper_shared_url_loader_factory.cc b/chromium/content/common/wrapper_shared_url_loader_factory.cc
deleted file mode 100644
index 370d3ab507e..00000000000
--- a/chromium/content/common/wrapper_shared_url_loader_factory.cc
+++ /dev/null
@@ -1,26 +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/common/wrapper_shared_url_loader_factory.h"
-
-
-namespace content {
-
-WrapperSharedURLLoaderFactoryInfo::WrapperSharedURLLoaderFactoryInfo() =
- default;
-
-WrapperSharedURLLoaderFactoryInfo::WrapperSharedURLLoaderFactoryInfo(
- network::mojom::URLLoaderFactoryPtrInfo factory_ptr_info)
- : factory_ptr_info_(std::move(factory_ptr_info)) {}
-
-WrapperSharedURLLoaderFactoryInfo::~WrapperSharedURLLoaderFactoryInfo() =
- default;
-
-scoped_refptr<network::SharedURLLoaderFactory>
-WrapperSharedURLLoaderFactoryInfo::CreateFactory() {
- return base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
- std::move(factory_ptr_info_));
-}
-
-} // namespace content
diff --git a/chromium/content/common/wrapper_shared_url_loader_factory.h b/chromium/content/common/wrapper_shared_url_loader_factory.h
deleted file mode 100644
index fd1bc0871b8..00000000000
--- a/chromium/content/common/wrapper_shared_url_loader_factory.h
+++ /dev/null
@@ -1,88 +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_COMMON_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
-#define CONTENT_COMMON_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
-
-#include "content/common/content_export.h"
-#include "content/common/possibly_associated_interface_ptr.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-
-namespace content {
-
-// A SharedURLLoaderFactoryInfo implementation that wraps a
-// network::mojom::URLLoaderFactoryPtrInfo.
-class CONTENT_EXPORT WrapperSharedURLLoaderFactoryInfo
- : public network::SharedURLLoaderFactoryInfo {
- public:
- WrapperSharedURLLoaderFactoryInfo();
- explicit WrapperSharedURLLoaderFactoryInfo(
- network::mojom::URLLoaderFactoryPtrInfo factory_ptr_info);
-
- ~WrapperSharedURLLoaderFactoryInfo() override;
-
- private:
- // SharedURLLoaderFactoryInfo implementation.
- scoped_refptr<network::SharedURLLoaderFactory> CreateFactory() override;
-
- network::mojom::URLLoaderFactoryPtrInfo factory_ptr_info_;
-};
-
-// A SharedURLLoaderFactory implementation that wraps a
-// PtrTemplateType<network::mojom::URLLoaderFactory>.
-template <template <typename> class PtrTemplateType>
-class WrapperSharedURLLoaderFactoryBase
- : public network::SharedURLLoaderFactory {
- public:
- using PtrType = PtrTemplateType<network::mojom::URLLoaderFactory>;
- using PtrInfoType = typename PtrType::PtrInfoType;
-
- explicit WrapperSharedURLLoaderFactoryBase(PtrType factory_ptr)
- : factory_ptr_(std::move(factory_ptr)) {}
-
- explicit WrapperSharedURLLoaderFactoryBase(PtrInfoType factory_ptr_info)
- : factory_ptr_(std::move(factory_ptr_info)) {}
-
- // SharedURLLoaderFactory implementation.
- void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag&
- traffic_annotation) override {
- if (!factory_ptr_)
- return;
- factory_ptr_->CreateLoaderAndStart(std::move(loader), routing_id,
- request_id, options, request,
- std::move(client), traffic_annotation);
- }
-
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
- network::mojom::URLLoaderFactoryPtrInfo factory_ptr_info;
- if (factory_ptr_)
- factory_ptr_->Clone(mojo::MakeRequest(&factory_ptr_info));
- return std::make_unique<WrapperSharedURLLoaderFactoryInfo>(
- std::move(factory_ptr_info));
- }
-
- private:
- ~WrapperSharedURLLoaderFactoryBase() override = default;
-
- PtrType factory_ptr_;
-};
-
-using WrapperSharedURLLoaderFactory =
- WrapperSharedURLLoaderFactoryBase<mojo::InterfacePtr>;
-using AssociatedWrapperSharedURLLoaderFactory =
- WrapperSharedURLLoaderFactoryBase<mojo::AssociatedInterfacePtr>;
-using PossiblyAssociatedWrapperSharedURLLoaderFactory =
- WrapperSharedURLLoaderFactoryBase<PossiblyAssociatedInterfacePtr>;
-
-} // namespace content
-
-#endif // CONTENT_COMMON_WRAPPER_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/common/zygote_commands_linux.h b/chromium/content/common/zygote_commands_linux.h
deleted file mode 100644
index 24f3bf6517e..00000000000
--- a/chromium/content/common/zygote_commands_linux.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ZYGOTE_COMMANDS_LINUX_H_
-#define CONTENT_COMMON_ZYGOTE_COMMANDS_LINUX_H_
-
-#include <stddef.h>
-
-#include "base/posix/global_descriptors.h"
-
-namespace content {
-
-// Contents of the initial message sent from the zygote to the browser right
-// after it starts.
-static const char kZygoteBootMessage[] = "ZYGOTE_BOOT";
-
-// Contents of the initial message sent from the zygote to the browser when it
-// is ready to go.
-static const char kZygoteHelloMessage[] = "ZYGOTE_OK";
-
-// Message sent by zygote children to the browser so the browser can discover
-// the sending child's process ID.
-static const char kZygoteChildPingMessage[] = "CHILD_PING";
-
-// Maximum allowable length for messages sent to the zygote.
-const size_t kZygoteMaxMessageLength = 8192;
-
-// File descriptors initialized by the Zygote Host
-const int kZygoteSocketPairFd = base::GlobalDescriptors::kBaseDescriptor;
-
-// These are the command codes used on the wire between the browser and the
-// zygote.
-enum {
- // Fork off a new renderer.
- kZygoteCommandFork = 0,
-
- // Reap a renderer child.
- kZygoteCommandReap = 1,
-
- // Check what happened to a child process.
- kZygoteCommandGetTerminationStatus = 2,
-
- // Read a bitmask of kSandboxLinux*
- kZygoteCommandGetSandboxStatus = 3,
-
- // Not a real zygote command, but a subcommand used during the zygote fork
- // protocol. Sends the child's PID as seen from the browser process.
- kZygoteCommandForkRealPID = 4
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_ZYGOTE_COMMANDS_LINUX_H_
diff --git a/chromium/content/content_resources.grd b/chromium/content/content_resources.grd
index 2c9642c82ad..5c3268a05c3 100644
--- a/chromium/content/content_resources.grd
+++ b/chromium/content/content_resources.grd
@@ -22,6 +22,8 @@
<include name="IDR_DEVTOOLS_TOUCH_CURSOR_ICON_2X" file="browser/resources/devtools/devtools_touch_cursor_2x.png" type="BINDATA" />
<include name="IDR_GPU_INTERNALS_HTML" file="browser/resources/gpu/gpu_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_GPU_INTERNALS_JS" file="browser/resources/gpu/gpu_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_HISTOGRAMS_INTERNALS_HTML" file="browser/resources/histograms/histograms_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_HISTOGRAMS_INTERNALS_JS" file="browser/resources/histograms/histograms_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_INDEXED_DB_INTERNALS_HTML" file="browser/resources/indexed_db/indexeddb_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_INDEXED_DB_INTERNALS_JS" file="browser/resources/indexed_db/indexeddb_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_INDEXED_DB_INTERNALS_CSS" file="browser/resources/indexed_db/indexeddb_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
@@ -37,6 +39,9 @@
<include name="IDR_NETWORK_ERROR_LISTING_HTML" file="browser/resources/net/network_errors_listing.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_JS" file="browser/resources/net/network_errors_listing.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_CSS" file="browser/resources/net/network_errors_listing.css" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_PROCESS_INTERNALS_HTML" file="browser/resources/process/process_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_PROCESS_INTERNALS_MOJO_JS" file="${root_gen_dir}/content/browser/process_internals/process_internals.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_PROCESS_INTERNALS_JS" file="browser/resources/process/process_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_SERVICE_WORKER_INTERNALS_HTML" file="browser/resources/service_worker/serviceworker_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_SERVICE_WORKER_INTERNALS_JS" file="browser/resources/service_worker/serviceworker_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_SERVICE_WORKER_INTERNALS_CSS" file="browser/resources/service_worker/serviceworker_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
diff --git a/chromium/content/gpu/BUILD.gn b/chromium/content/gpu/BUILD.gn
index 3e858724af3..9a8b1ca6b4f 100644
--- a/chromium/content/gpu/BUILD.gn
+++ b/chromium/content/gpu/BUILD.gn
@@ -93,6 +93,10 @@ target(link_target_type, "gpu_sources") {
deps += [ "//media" ]
}
+ if (is_linux) {
+ deps += [ "//services/service_manager/zygote" ]
+ }
+
if (mojo_media_host == "gpu") {
deps += [ "//media/mojo/services" ]
}
diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc
index 861c2f856c3..97ca63c7942 100644
--- a/chromium/content/gpu/gpu_child_thread.cc
+++ b/chromium/content/gpu/gpu_child_thread.cc
@@ -11,7 +11,6 @@
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
@@ -26,6 +25,7 @@
#include "content/public/common/service_names.mojom.h"
#include "content/public/gpu/content_gpu_client.h"
#include "gpu/command_buffer/common/activity_flags.h"
+#include "gpu/ipc/service/gpu_channel_manager.h"
#include "gpu/ipc/service/gpu_init.h"
#include "gpu/ipc/service/gpu_watchdog_thread.h"
#include "ipc/ipc_sync_message_filter.h"
@@ -274,6 +274,7 @@ void GpuChildThread::OnGpuServiceConnection(viz::GpuServiceImpl* gpu_service) {
// Only set once per process instance.
service_factory_.reset(new GpuServiceFactory(
gpu_service->gpu_preferences(),
+ gpu_service->gpu_channel_manager()->gpu_driver_bug_workarounds(),
gpu_service->media_gpu_channel_manager()->AsWeakPtr(),
std::move(overlay_factory_cb)));
diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc
index d9c8b6d8c61..e6a589fb90e 100644
--- a/chromium/content/gpu/gpu_main.cc
+++ b/chromium/content/gpu/gpu_main.cc
@@ -80,9 +80,9 @@
#if defined(OS_LINUX)
#include "content/common/font_config_ipc_linux.h"
#include "content/gpu/gpu_sandbox_hook_linux.h"
-#include "content/public/common/common_sandbox_support_linux.h"
#include "content/public/common/sandbox_init.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#endif
@@ -339,12 +339,12 @@ int GpuMain(const MainFunctionParams& parameters) {
nullptr);
#endif
- if (command_line.HasSwitch(switches::kEnableOOPRasterization)) {
+ if (gpu_preferences.enable_oop_rasterization) {
SkGraphics::Init();
#if defined(OS_LINUX)
// Set up the font IPC so that the GPU process can create typefaces.
- SkFontConfigInterface::SetGlobal(new FontConfigIPC(GetSandboxFD()))
- ->unref();
+ SkFontConfigInterface::SetGlobal(
+ sk_make_sp<FontConfigIPC>(service_manager::GetSandboxFD()));
#endif
}
diff --git a/chromium/content/gpu/gpu_service_factory.cc b/chromium/content/gpu/gpu_service_factory.cc
index 15a97fc0693..fc73e43a5c8 100644
--- a/chromium/content/gpu/gpu_service_factory.cc
+++ b/chromium/content/gpu/gpu_service_factory.cc
@@ -23,10 +23,12 @@ namespace content {
GpuServiceFactory::GpuServiceFactory(
const gpu::GpuPreferences& gpu_preferences,
+ const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager,
media::AndroidOverlayMojoFactoryCB android_overlay_factory_cb) {
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
gpu_preferences_ = gpu_preferences;
+ gpu_workarounds_ = gpu_workarounds;
task_runner_ = base::ThreadTaskRunnerHandle::Get();
media_gpu_channel_manager_ = std::move(media_gpu_channel_manager);
android_overlay_factory_cb_ = std::move(android_overlay_factory_cb);
@@ -46,8 +48,8 @@ void GpuServiceFactory::RegisterServices(ServiceMap* services) {
service_manager::EmbeddedServiceInfo info;
info.factory = base::BindRepeating(
- &media::CreateGpuMediaService, gpu_preferences_, task_runner_,
- media_gpu_channel_manager_, android_overlay_factory_cb_,
+ &media::CreateGpuMediaService, gpu_preferences_, gpu_workarounds_,
+ task_runner_, media_gpu_channel_manager_, android_overlay_factory_cb_,
std::move(cdm_proxy_factory_cb));
// This service will host audio/video decoders, and if these decoding
// operations are blocked, user may hear audio glitch or see video freezing,
diff --git a/chromium/content/gpu/gpu_service_factory.h b/chromium/content/gpu/gpu_service_factory.h
index ec30ff722e2..6644f0d0079 100644
--- a/chromium/content/gpu/gpu_service_factory.h
+++ b/chromium/content/gpu/gpu_service_factory.h
@@ -11,6 +11,7 @@
#include "base/single_thread_task_runner.h"
#include "content/child/service_factory.h"
#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "media/base/android_overlay_mojo_factory.h"
#include "media/mojo/buildflags.h"
@@ -25,6 +26,7 @@ class GpuServiceFactory : public ServiceFactory {
public:
GpuServiceFactory(
const gpu::GpuPreferences& gpu_preferences,
+ const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager,
media::AndroidOverlayMojoFactoryCB android_overlay_factory_cb);
~GpuServiceFactory() override;
@@ -42,6 +44,7 @@ class GpuServiceFactory : public ServiceFactory {
base::WeakPtr<media::MediaGpuChannelManager> media_gpu_channel_manager_;
media::AndroidOverlayMojoFactoryCB android_overlay_factory_cb_;
gpu::GpuPreferences gpu_preferences_;
+ gpu::GpuDriverBugWorkarounds gpu_workarounds_;
#endif
DISALLOW_COPY_AND_ASSIGN(GpuServiceFactory);
diff --git a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
index a6e5823a51d..cdfffa0cab1 100644
--- a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
+++ b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
@@ -141,16 +141,6 @@ blink::WebThread* PpapiBlinkPlatformImpl::CurrentThread() {
return BlinkPlatformImpl::CurrentThread();
}
-blink::WebClipboard* PpapiBlinkPlatformImpl::Clipboard() {
- NOTREACHED();
- return nullptr;
-}
-
-blink::WebFileUtilities* PpapiBlinkPlatformImpl::GetFileUtilities() {
- NOTREACHED();
- return nullptr;
-}
-
blink::WebSandboxSupport* PpapiBlinkPlatformImpl::GetSandboxSupport() {
#if !defined(OS_ANDROID) && !defined(OS_WIN)
return sandbox_support_.get();
diff --git a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
index 8a58a2ae1e2..5f245c7d85d 100644
--- a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
+++ b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
@@ -25,8 +25,6 @@ class PpapiBlinkPlatformImpl : public BlinkPlatformImpl {
// BlinkPlatformImpl methods:
blink::WebThread* CurrentThread() override;
- blink::WebClipboard* Clipboard() override;
- blink::WebFileUtilities* GetFileUtilities() override;
blink::WebSandboxSupport* GetSandboxSupport() override;
virtual bool sandboxEnabled();
unsigned long long VisitedLinkHash(const char* canonicalURL,
diff --git a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
index 3f59e25585d..c2cf95a216a 100644
--- a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
+++ b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
@@ -106,7 +106,7 @@ int PpapiPluginMain(const MainFunctionParams& parameters) {
// Specifies $HOME explicitly because some plugins rely on $HOME but
// no other part of Chrome OS uses that. See crbug.com/335290.
base::FilePath homedir;
- PathService::Get(base::DIR_HOME, &homedir);
+ base::PathService::Get(base::DIR_HOME, &homedir);
setenv("HOME", homedir.value().c_str(), 1);
#endif
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.cc b/chromium/content/ppapi_plugin/ppapi_thread.cc
index fb51dcfac2d..bb0abafb6ea 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.cc
+++ b/chromium/content/ppapi_plugin/ppapi_thread.cc
@@ -115,7 +115,7 @@ PpapiThread::PpapiThread(const base::CommandLine& command_line, bool is_broker)
// allocator.
if (!command_line.HasSwitch(switches::kSingleProcess)) {
discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
- if (features::IsMusEnabled()) {
+ if (features::IsMashEnabled()) {
#if defined(USE_AURA)
GetServiceManagerConnection()->GetConnector()->BindInterface(
ui::mojom::kServiceName, &manager_ptr);
@@ -148,7 +148,7 @@ void PpapiThread::Shutdown() {
bool PpapiThread::Send(IPC::Message* msg) {
// Allow access from multiple threads.
- if (message_loop()->task_runner()->BelongsToCurrentThread())
+ if (main_thread_runner()->BelongsToCurrentThread())
return ChildThreadImpl::Send(msg);
return sync_message_filter()->Send(msg);
diff --git a/chromium/content/public/android/BUILD.gn b/chromium/content/public/android/BUILD.gn
index cae8e5cb0a8..dedbd8707e9 100644
--- a/chromium/content/public/android/BUILD.gn
+++ b/chromium/content/public/android/BUILD.gn
@@ -45,7 +45,6 @@ android_library("content_java") {
"//media/midi:midi_java",
"//media/mojo/interfaces:interfaces_java",
"//mojo/android:system_java",
- "//mojo/common:common_custom_types_java",
"//mojo/public/java:base_java",
"//mojo/public/java:bindings_java",
"//mojo/public/java:system_java",
@@ -110,46 +109,44 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/AudioFocusDelegate.java",
"java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java",
"java/src/org/chromium/content/browser/BindingManager.java",
- "java/src/org/chromium/content/browser/BindingManagerImpl.java",
"java/src/org/chromium/content/browser/BrowserStartupController.java",
"java/src/org/chromium/content/browser/ChildProcessCreationParams.java",
"java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java",
+ "java/src/org/chromium/content/browser/ChildProcessRanking.java",
"java/src/org/chromium/content/browser/ContentChildProcessConstants.java",
"java/src/org/chromium/content/browser/ContentClassFactory.java",
"java/src/org/chromium/content/browser/ContentFeatureList.java",
"java/src/org/chromium/content/browser/ContentNfcDelegate.java",
- "java/src/org/chromium/content/browser/ContentVideoView.java",
- "java/src/org/chromium/content/browser/ContentVideoViewEmbedder.java",
+ "java/src/org/chromium/content/browser/ContentUiEventHandler.java",
+ "java/src/org/chromium/content/browser/ContentVideoViewImpl.java",
"java/src/org/chromium/content/browser/ContentViewCoreImpl.java",
"java/src/org/chromium/content/browser/ContentViewRenderView.java",
- "java/src/org/chromium/content/browser/ContentViewStatics.java",
- "java/src/org/chromium/content/browser/DeviceUtils.java",
+ "java/src/org/chromium/content/browser/ContentViewStaticsImpl.java",
+ "java/src/org/chromium/content/browser/DeviceUtilsImpl.java",
+ "java/src/org/chromium/content/browser/Gamepad.java",
"java/src/org/chromium/content/browser/GestureListenerManagerImpl.java",
"java/src/org/chromium/content/browser/GpuProcessCallback.java",
"java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java",
- "java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java",
"java/src/org/chromium/content/browser/JavascriptInjectorImpl.java",
"java/src/org/chromium/content/browser/JavascriptInterface.java",
"java/src/org/chromium/content/browser/JoystickHandler.java",
"java/src/org/chromium/content/browser/LauncherThread.java",
"java/src/org/chromium/content/browser/MediaSessionImpl.java",
"java/src/org/chromium/content/browser/MemoryMonitorAndroid.java",
- "java/src/org/chromium/content/browser/MotionEventSynthesizer.java",
+ "java/src/org/chromium/content/browser/MotionEventSynthesizerImpl.java",
"java/src/org/chromium/content/browser/NfcHost.java",
"java/src/org/chromium/content/browser/PepperPluginManager.java",
"java/src/org/chromium/content/browser/PopupController.java",
"java/src/org/chromium/content/browser/PopupZoomer.java",
- "java/src/org/chromium/content/browser/PositionObserver.java",
- "java/src/org/chromium/content/browser/RenderCoordinates.java",
+ "java/src/org/chromium/content/browser/RenderCoordinatesImpl.java",
"java/src/org/chromium/content/browser/ScreenOrientationProvider.java",
"java/src/org/chromium/content/browser/SpareChildConnection.java",
- "java/src/org/chromium/content/browser/SpeechRecognition.java",
+ "java/src/org/chromium/content/browser/SpeechRecognitionImpl.java",
"java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
"java/src/org/chromium/content/browser/TapDisambiguator.java",
"java/src/org/chromium/content/browser/TracingControllerAndroid.java",
- "java/src/org/chromium/content/browser/ViewPositionObserver.java",
- "java/src/org/chromium/content/browser/WindowAndroidChangedObserver.java",
"java/src/org/chromium/content/browser/WindowEventObserver.java",
+ "java/src/org/chromium/content/browser/WindowEventObserverManager.java",
"java/src/org/chromium/content/browser/accessibility/KitKatWebContentsAccessibility.java",
"java/src/org/chromium/content/browser/accessibility/LollipopWebContentsAccessibility.java",
"java/src/org/chromium/content/browser/accessibility/OWebContentsAccessibility.java",
@@ -166,8 +163,6 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/androidoverlay/DialogOverlayCore.java",
"java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java",
"java/src/org/chromium/content/browser/androidoverlay/ThreadHoppingHost.java",
- "java/src/org/chromium/content/browser/crypto/ByteArrayGenerator.java",
- "java/src/org/chromium/content/browser/crypto/CipherFactory.java",
"java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java",
"java/src/org/chromium/content/browser/framehost/RenderFrameHostDelegate.java",
"java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java",
@@ -212,7 +207,7 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/selection/FloatingActionModeCallback.java",
"java/src/org/chromium/content/browser/selection/FloatingPastePopupMenu.java",
"java/src/org/chromium/content/browser/selection/HandleViewResources.java",
- "java/src/org/chromium/content/browser/selection/LGEmailActionModeWorkaround.java",
+ "java/src/org/chromium/content/browser/selection/LGEmailActionModeWorkaroundImpl.java",
"java/src/org/chromium/content/browser/selection/LegacyPastePopupMenu.java",
"java/src/org/chromium/content/browser/selection/PastePopupMenu.java",
"java/src/org/chromium/content/browser/selection/SelectionEventProxyImpl.java",
@@ -225,13 +220,18 @@ android_library("content_java") {
"java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java",
"java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java",
"java/src/org/chromium/content/browser/webcontents/WebContentsUserData.java",
- "java/src/org/chromium/content/common/ContentSwitches.java",
+ "java/src/org/chromium/content/common/ContentSwitchUtils.java",
+ "java/src/org/chromium/content/common/ServiceManagerConnectionImpl.java",
"java/src/org/chromium/content/common/SurfaceWrapper.java",
"java/src/org/chromium/content_public/browser/AccessibilitySnapshotCallback.java",
"java/src/org/chromium/content_public/browser/AccessibilitySnapshotNode.java",
"java/src/org/chromium/content_public/browser/ActionModeCallbackHelper.java",
"java/src/org/chromium/content_public/browser/ChildProcessUtils.java",
+ "java/src/org/chromium/content_public/browser/ContentViewStatics.java",
+ "java/src/org/chromium/content_public/browser/DeviceUtils.java",
"java/src/org/chromium/content_public/browser/InputMethodManagerWrapper.java",
+ "java/src/org/chromium/content_public/browser/ContentVideoView.java",
+ "java/src/org/chromium/content_public/browser/ContentVideoViewEmbedder.java",
"java/src/org/chromium/content_public/browser/ContentViewCore.java",
"java/src/org/chromium/content_public/browser/GestureListenerManager.java",
"java/src/org/chromium/content_public/browser/GestureStateListener.java",
@@ -241,10 +241,12 @@ android_library("content_java") {
"java/src/org/chromium/content_public/browser/InterfaceRegistrar.java",
"java/src/org/chromium/content_public/browser/JavaScriptCallback.java",
"java/src/org/chromium/content_public/browser/JavascriptInjector.java",
+ "java/src/org/chromium/content_public/browser/LGEmailActionModeWorkaround.java",
"java/src/org/chromium/content_public/browser/LoadUrlParams.java",
"java/src/org/chromium/content_public/browser/MediaSession.java",
"java/src/org/chromium/content_public/browser/MediaSessionObserver.java",
"java/src/org/chromium/content_public/browser/MessagePort.java",
+ "java/src/org/chromium/content_public/browser/MotionEventSynthesizer.java",
"java/src/org/chromium/content_public/browser/NavigationController.java",
"java/src/org/chromium/content_public/browser/NavigationEntry.java",
"java/src/org/chromium/content_public/browser/NavigationHistory.java",
@@ -255,17 +257,21 @@ android_library("content_java") {
"java/src/org/chromium/content_public/browser/SelectionMetricsLogger.java",
"java/src/org/chromium/content_public/browser/SelectionPopupController.java",
"java/src/org/chromium/content_public/browser/SmartClipProvider.java",
+ "java/src/org/chromium/content_public/browser/SpeechRecognition.java",
+ "java/src/org/chromium/content_public/browser/RenderCoordinates.java",
"java/src/org/chromium/content_public/browser/WebContents.java",
"java/src/org/chromium/content_public/browser/WebContentsAccessibility.java",
"java/src/org/chromium/content_public/browser/WebContentsInternals.java",
"java/src/org/chromium/content_public/browser/WebContentsObserver.java",
"java/src/org/chromium/content_public/browser/WebContentsStatics.java",
"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",
+ "java/src/org/chromium/content_public/common/ServiceManagerConnection.java",
"java/src/org/chromium/content_public/common/UseZoomForDSFPolicy.java",
]
}
@@ -329,7 +335,6 @@ java_cpp_enum("content_public_android_java_enums_srcjar") {
"//content/public/browser/navigation_controller.h",
"//content/public/common/browser_controls_state.h",
"//content/public/common/console_message_level.h",
- "//content/public/common/result_codes.h",
"//content/public/common/screen_orientation_values.h",
"//content/public/common/speech_recognition_error.h",
]
@@ -355,21 +360,21 @@ generate_jni("content_jni_headers") {
"java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java",
"java/src/org/chromium/content/browser/ContentFeatureList.java",
"java/src/org/chromium/content/browser/ContentNfcDelegate.java",
- "java/src/org/chromium/content/browser/ContentVideoView.java",
+ "java/src/org/chromium/content/browser/ContentUiEventHandler.java",
+ "java/src/org/chromium/content/browser/ContentVideoViewImpl.java",
"java/src/org/chromium/content/browser/ContentViewCoreImpl.java",
"java/src/org/chromium/content/browser/ContentViewRenderView.java",
- "java/src/org/chromium/content/browser/ContentViewStatics.java",
+ "java/src/org/chromium/content/browser/ContentViewStaticsImpl.java",
"java/src/org/chromium/content/browser/GestureListenerManagerImpl.java",
"java/src/org/chromium/content/browser/GpuProcessCallback.java",
"java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java",
- "java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java",
"java/src/org/chromium/content/browser/JavascriptInjectorImpl.java",
"java/src/org/chromium/content/browser/LauncherThread.java",
"java/src/org/chromium/content/browser/MediaSessionImpl.java",
"java/src/org/chromium/content/browser/MemoryMonitorAndroid.java",
"java/src/org/chromium/content/browser/NfcHost.java",
"java/src/org/chromium/content/browser/ScreenOrientationProvider.java",
- "java/src/org/chromium/content/browser/SpeechRecognition.java",
+ "java/src/org/chromium/content/browser/SpeechRecognitionImpl.java",
"java/src/org/chromium/content/browser/SyntheticGestureTarget.java",
"java/src/org/chromium/content/browser/TapDisambiguator.java",
"java/src/org/chromium/content/browser/TracingControllerAndroid.java",
@@ -389,6 +394,7 @@ generate_jni("content_jni_headers") {
"java/src/org/chromium/content/browser/selection/SmartSelectionClient.java",
"java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java",
"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",
@@ -433,6 +439,8 @@ android_library("content_javatests") {
"//mojo/public/mojom/base:base_java",
"//net/android:net_java",
"//net/android:net_java_test_support",
+ "//services/service_manager/public/java:service_manager_java",
+ "//services/test/echo/public/mojom:mojom_java",
"//third_party/android_support_test_runner:rules_java",
"//third_party/android_support_test_runner:runner_java",
"//third_party/android_tools:android_support_annotations_java",
@@ -484,7 +492,6 @@ android_library("content_javatests") {
"javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplPixelTest.java",
"javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTest.java",
"javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestRule.java",
- "javatests/src/org/chromium/content/browser/crypto/CipherFactoryTest.java",
"javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java",
"javatests/src/org/chromium/content/browser/input/ImeActivityTestRule.java",
"javatests/src/org/chromium/content/browser/input/ImeAutocapitalizeTest.java",
@@ -499,6 +506,7 @@ android_library("content_javatests") {
"javatests/src/org/chromium/content/browser/picker/DateTimePickerDialogTest.java",
"javatests/src/org/chromium/content/browser/webcontents/AccessibilitySnapshotTest.java",
"javatests/src/org/chromium/content/browser/webcontents/WebContentsTest.java",
+ "javatests/src/org/chromium/content/common/ServiceManagerConnectionImplTest.java",
]
data = [
@@ -512,7 +520,8 @@ android_library("content_javatests") {
junit_binary("content_junit_tests") {
java_files = [
- "junit/src/org/chromium/content/browser/BindingManagerImplTest.java",
+ "junit/src/org/chromium/content/browser/BindingManagerTest.java",
+ "junit/src/org/chromium/content/browser/ChildProcessRankingTest.java",
"junit/src/org/chromium/content/browser/SpareChildConnectionTest.java",
"junit/src/org/chromium/content/browser/androidoverlay/DialogOverlayCoreTest.java",
"junit/src/org/chromium/content/browser/input/RangeTest.java",
diff --git a/chromium/content/public/android/OWNERS b/chromium/content/public/android/OWNERS
index d6c853c953b..8716dc9986c 100644
--- a/chromium/content/public/android/OWNERS
+++ b/chromium/content/public/android/OWNERS
@@ -1,5 +1,6 @@
boliu@chromium.org
dtrainor@chromium.org
+jinsukkim@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/public/app/content_main_delegate.cc b/chromium/content/public/app/content_main_delegate.cc
index 5f2631cd6a7..c4bdfd36ad0 100644
--- a/chromium/content/public/app/content_main_delegate.cc
+++ b/chromium/content/public/app/content_main_delegate.cc
@@ -26,6 +26,10 @@ int ContentMainDelegate::RunProcess(
return -1;
}
+ui::DataPack* ContentMainDelegate::LoadServiceManifestDataPack() {
+ return nullptr;
+}
+
#if defined(OS_MACOSX)
bool ContentMainDelegate::ProcessRegistersWithSystemProcess(
@@ -45,7 +49,8 @@ bool ContentMainDelegate::DelaySandboxInitialization(
#elif defined(OS_LINUX)
void ContentMainDelegate::ZygoteStarting(
- std::vector<std::unique_ptr<ZygoteForkDelegate>>* delegates) {}
+ std::vector<std::unique_ptr<service_manager::ZygoteForkDelegate>>*
+ delegates) {}
#endif // defined(OS_LINUX)
diff --git a/chromium/content/public/app/content_main_delegate.h b/chromium/content/public/app/content_main_delegate.h
index a53d40b4efd..b5d8b1889d6 100644
--- a/chromium/content/public/app/content_main_delegate.h
+++ b/chromium/content/public/app/content_main_delegate.h
@@ -21,15 +21,19 @@ class CommandLine;
namespace service_manager {
class BackgroundServiceManager;
class Identity;
+class ZygoteForkDelegate;
} // namespace service_manager
+namespace ui {
+class DataPack;
+}
+
namespace content {
class ContentBrowserClient;
class ContentGpuClient;
class ContentRendererClient;
class ContentUtilityClient;
-class ZygoteForkDelegate;
struct MainFunctionParams;
class CONTENT_EXPORT ContentMainDelegate {
@@ -59,6 +63,10 @@ class CONTENT_EXPORT ContentMainDelegate {
// Called right before the process exits.
virtual void ProcessExiting(const std::string& process_type) {}
+ // This loads the service manifest datapack, takes its ownership and returns
+ // the pointer to it.
+ virtual ui::DataPack* LoadServiceManifestDataPack();
+
#if defined(OS_MACOSX)
// Returns true if the process registers with the system monitor, so that we
// can allocate an IO port for it before the sandbox is initialized. Embedders
@@ -81,7 +89,8 @@ class CONTENT_EXPORT ContentMainDelegate {
// specify one or more zygote delegates if it wishes by storing them in
// |*delegates|.
virtual void ZygoteStarting(
- std::vector<std::unique_ptr<ZygoteForkDelegate>>* delegates);
+ std::vector<std::unique_ptr<service_manager::ZygoteForkDelegate>>*
+ delegates);
// Called every time the zygote process forks.
virtual void ZygoteForked() {}
diff --git a/chromium/content/public/app/mojo/content_browser_manifest.json b/chromium/content/public/app/mojo/content_browser_manifest.json
index 7e3b765742a..a515b68616a 100644
--- a/chromium/content/public/app/mojo/content_browser_manifest.json
+++ b/chromium/content/public/app/mojo/content_browser_manifest.json
@@ -6,76 +6,80 @@
"provides": {
// Interfaces needed by a generic client of content browser.
"app": [
- "discardable_memory::mojom::DiscardableSharedMemoryManager",
- "memory_instrumentation::mojom::Coordinator"
+ "discardable_memory.mojom.DiscardableSharedMemoryManager",
+ "memory_instrumentation.mojom.Coordinator"
],
"dwrite_font_proxy": [
- "content::mojom::DWriteFontProxy"
+ "content.mojom.DWriteFontProxy"
],
"field_trials": [
- "content::mojom::FieldTrialRecorder"
+ "content.mojom.FieldTrialRecorder"
],
"font_cache": [
- "content::mojom::FontCacheWin"
+ "content.mojom.FontCacheWin"
],
"font_loader": [
- "content::mojom::FontLoaderMac"
+ "content.mojom.FontLoaderMac"
],
"gpu": [
- "discardable_memory::mojom::DiscardableSharedMemoryManager",
- "media::mojom::AndroidOverlayProvider"
+ "discardable_memory.mojom.DiscardableSharedMemoryManager",
+ "media.mojom.AndroidOverlayProvider"
],
"plugin": [
- "discardable_memory::mojom::DiscardableSharedMemoryManager",
- "ui::mojom::Gpu"
+ "discardable_memory.mojom.DiscardableSharedMemoryManager",
+ "ui.mojom.Gpu"
],
"renderer": [
- "blink::mojom::BackgroundSyncService",
- "blink::mojom::BlobRegistry",
- "blink::mojom::BroadcastChannelProvider",
- "blink::mojom::ClipboardHost",
- "blink::mojom::LockManager",
- "blink::mojom::Hyphenation",
- "blink::mojom::MimeRegistry",
- "blink::mojom::OffscreenCanvasProvider",
- "blink::mojom::ReportingServiceProxy",
- "blink::mojom::WebDatabaseHost",
- "content::mojom::AppCacheBackend",
- "content::mojom::ClipboardHost",
- "content::mojom::FieldTrialRecorder",
- "content::mojom::FileUtilitiesHost",
- "content::mojom::FrameSinkProvider",
- "content::mojom::MediaStreamTrackMetricsHost",
- "content::mojom::MemoryCoordinatorHandle",
- "content::mojom::PeerConnectionTrackerHost",
- "content::mojom::PushMessaging",
- "content::mojom::RendererHost",
- "content::mojom::ReportingServiceProxy",
- "content::mojom::ServiceWorkerDispatcherHost",
- "content::mojom::StoragePartitionService",
- "content::mojom::WorkerURLLoaderFactoryProvider",
- "device::mojom::BatteryMonitor",
- "device::mojom::GamepadHapticsManager",
- "device::mojom::GamepadMonitor",
- "discardable_memory::mojom::DiscardableSharedMemoryManager",
- "media::mojom::KeySystemSupport",
- "media::mojom::VideoCaptureHost",
- "media::mojom::VideoDecodePerfHistory",
- "memory_coordinator::mojom::MemoryCoordinatorHandle",
- "metrics::mojom::SingleSampleMetricsProvider",
- "network::mojom::URLLoaderFactory",
- "resource_coordinator::mojom::ProcessCoordinationUnit",
- "ui::mojom::Gpu",
- "viz::mojom::SharedBitmapAllocationNotifier",
- "viz::mojom::CompositingModeReporter"
+ "blink.mojom.BackgroundSyncService",
+ "blink.mojom.BlobRegistry",
+ "blink.mojom.BroadcastChannelProvider",
+ "blink.mojom.ClipboardHost",
+ "blink.mojom.EmbeddedFrameSinkProvider",
+ "blink.mojom.FileUtilitiesHost",
+ "blink.mojom.LockManager",
+ "blink.mojom.Hyphenation",
+ "blink.mojom.MimeRegistry",
+ "blink.mojom.ReportingServiceProxy",
+ "blink.mojom.WebDatabaseHost",
+ "content.mojom.AppCacheBackend",
+ "content.mojom.ClipboardHost",
+ "content.mojom.FieldTrialRecorder",
+ "content.mojom.FrameSinkProvider",
+ "content.mojom.MediaStreamTrackMetricsHost",
+ "content.mojom.MemoryCoordinatorHandle",
+ "content.mojom.PeerConnectionTrackerHost",
+ "content.mojom.PushMessaging",
+ "content.mojom.RendererHost",
+ "content.mojom.ReportingServiceProxy",
+ "content.mojom.ServiceWorkerDispatcherHost",
+ "content.mojom.StoragePartitionService",
+ "content.mojom.WorkerURLLoaderFactoryProvider",
+ "device.mojom.BatteryMonitor",
+ "device.mojom.GamepadHapticsManager",
+ "device.mojom.GamepadMonitor",
+ "discardable_memory.mojom.DiscardableSharedMemoryManager",
+ "media.mojom.KeySystemSupport",
+ "media.mojom.VideoCaptureHost",
+ "media.mojom.VideoDecodePerfHistory",
+ "memory_coordinator.mojom.MemoryCoordinatorHandle",
+ "metrics.mojom.SingleSampleMetricsProvider",
+ "network.mojom.URLLoaderFactory",
+ "resource_coordinator.mojom.ProcessCoordinationUnit",
+ "ui.mojom.Gpu",
+ "viz.mojom.CompositingModeReporter"
],
"service_manager:service_factory": [
- "service_manager::mojom::ServiceFactory"
+ "service_manager.mojom.ServiceFactory"
]
},
"requires": {
"*": [ "app" ],
- "audio": [ "info", "debug_recording"],
+ "audio": [
+ "info",
+ "debug_recording",
+ "device_notifier",
+ "stream_factory"
+ ],
"cdm": [ "media:cdm" ],
"content_gpu": [ "browser" ],
"content_plugin": [ "browser" ],
@@ -88,6 +92,7 @@
"device:geolocation",
"device:hid",
"device:input_service",
+ "device:mtp",
"device:nfc",
"device:serial",
"device:vibration",
@@ -133,66 +138,68 @@
// TODO(beng): these belong in //chrome's overlay, but there are some
// issues with mash browser_tests's manifest config that make this
// impossible this week. Remove once sky/ken fix this.
- "autofill::mojom::AutofillDriver",
- "autofill::mojom::PasswordManagerDriver",
- "blink::mojom::BackgroundFetchService",
- "blink::mojom::BudgetService",
- "blink::mojom::CacheStorage",
- "blink::mojom::ColorChooserFactory",
- "blink::mojom::DedicatedWorkerFactory",
- "blink::mojom::LockManager",
- "blink::mojom::GeolocationService",
- "blink::mojom::InsecureInputService",
- "blink::mojom::KeyboardLockService",
- "blink::mojom::MediaDevicesDispatcherHost",
- "blink::mojom::MediaSessionService",
- "blink::mojom::NotificationService",
- "blink::mojom::PermissionService",
- "blink::mojom::PrefetchURLLoaderService",
- "blink::mojom::PresentationService",
- "blink::mojom::QuotaDispatcherHost",
- "blink::mojom::TextSuggestionHost",
- "blink::mojom::UnhandledTapNotifier",
- "blink::mojom::WebBluetoothService",
+ "autofill.mojom.AutofillDriver",
+ "autofill.mojom.PasswordManagerDriver",
+ "blink.mojom.BackgroundFetchService",
+ "blink.mojom.BudgetService",
+ "blink.mojom.CacheStorage",
+ "blink.mojom.ColorChooserFactory",
+ "blink.mojom.DedicatedWorkerFactory",
+ "blink.mojom.LockManager",
+ "blink.mojom.GeolocationService",
+ "blink.mojom.InsecureInputService",
+ "blink.mojom.KeyboardLockService",
+ "blink.mojom.MediaDevicesDispatcherHost",
+ "blink.mojom.MediaSessionService",
+ "blink.mojom.NotificationService",
+ "blink.mojom.PermissionService",
+ "blink.mojom.PrefetchURLLoaderService",
+ "blink.mojom.PresentationService",
+ "blink.mojom.QuotaDispatcherHost",
+ "blink.mojom.TextSuggestionHost",
+ "blink.mojom.UnhandledTapNotifier",
+ "blink.mojom.WebBluetoothService",
// TODO(beng): figure out how to overlay test interfaces like this.
- "content::mojom::BrowserTarget",
+ "content.mojom.BrowserTarget",
// InputInjector is only exposed when gpu benchmarking is enabled.
- "content::mojom::InputInjector",
+ "content.mojom.InputInjector",
- "content::mojom::MediaStreamDispatcherHost",
- "content::mojom::RendererAudioInputStreamFactory",
- "content::mojom::RendererAudioOutputStreamFactory",
- "content::mojom::SharedWorkerConnector",
- "device::mojom::Geolocation",
- "device::mojom::NFC",
- "device::mojom::SensorProvider",
- "device::mojom::UsbChooserService",
- "device::mojom::UsbDeviceManager",
- "device::mojom::VibrationManager",
- "device::mojom::UsbDeviceManager",
- "device::mojom::VRService",
- "device::mojom::VRService",
- "device::mojom::WakeLock",
- "discardable_memory::mojom::DiscardableSharedMemoryManager",
- "media::mojom::ImageCapture",
- "media::mojom::InterfaceFactory",
- "media::mojom::MediaMetricsProvider",
- "media::mojom::RemoterFactory",
- "media::mojom::Renderer",
- "network::mojom::RestrictedCookieManager",
- "network::mojom::WebSocket",
- "password_manager::mojom::CredentialManager",
- "payments::mojom::PaymentManager",
- "payments::mojom::PaymentRequest",
- "resource_coordinator::mojom::FrameCoordinationUnit",
- "shape_detection::mojom::BarcodeDetection",
- "shape_detection::mojom::FaceDetectionProvider",
- "shape_detection::mojom::TextDetection",
- "ui::mojom::Gpu",
- "webauth::mojom::Authenticator",
- "webauth::test::mojom::VirtualAuthenticatorManager"
+ "content.mojom.MediaStreamDispatcherHost",
+ "content.mojom.RendererAudioInputStreamFactory",
+ "content.mojom.RendererAudioOutputStreamFactory",
+ "content.mojom.SharedWorkerConnector",
+ "content.mojom.SpeechRecognizer",
+ "device.mojom.Geolocation",
+ "device.mojom.NFC",
+ "device.mojom.SensorProvider",
+ "device.mojom.UsbChooserService",
+ "device.mojom.UsbDeviceManager",
+ "device.mojom.VibrationManager",
+ "device.mojom.UsbDeviceManager",
+ "device.mojom.VRService",
+ "device.mojom.VRService",
+ "device.mojom.WakeLock",
+ "discardable_memory.mojom.DiscardableSharedMemoryManager",
+ "media.mojom.ImageCapture",
+ "media.mojom.InterfaceFactory",
+ "media.mojom.MediaMetricsProvider",
+ "media.mojom.RemoterFactory",
+ "media.mojom.Renderer",
+ "mojom.ProcessInternalsHandler",
+ "network.mojom.RestrictedCookieManager",
+ "network.mojom.WebSocket",
+ "password_manager.mojom.CredentialManager",
+ "payments.mojom.PaymentManager",
+ "payments.mojom.PaymentRequest",
+ "resource_coordinator.mojom.FrameCoordinationUnit",
+ "shape_detection.mojom.BarcodeDetection",
+ "shape_detection.mojom.FaceDetectionProvider",
+ "shape_detection.mojom.TextDetection",
+ "ui.mojom.Gpu",
+ "webauth.mojom.Authenticator",
+ "webauth.test.mojom.VirtualAuthenticatorManager"
]
},
"requires": {
@@ -202,53 +209,55 @@
"navigation:dedicated_worker": {
"provides": {
"renderer": [
- "blink::mojom::BudgetService",
- "blink::mojom::CacheStorage",
- "blink::mojom::LockManager",
- "blink::mojom::NotificationService",
- "blink::mojom::PermissionService",
- "blink::mojom::QuotaDispatcherHost",
- "network::mojom::WebSocket",
- "payments::mojom::PaymentManager",
- "shape_detection::mojom::BarcodeDetection",
- "shape_detection::mojom::FaceDetectionProvider",
- "shape_detection::mojom::TextDetection"
+ "blink.mojom.BudgetService",
+ "blink.mojom.CacheStorage",
+ "blink.mojom.LockManager",
+ "blink.mojom.NotificationService",
+ "blink.mojom.PermissionService",
+ "blink.mojom.QuotaDispatcherHost",
+ "device.mojom.UsbDeviceManager",
+ "network.mojom.WebSocket",
+ "payments.mojom.PaymentManager",
+ "shape_detection.mojom.BarcodeDetection",
+ "shape_detection.mojom.FaceDetectionProvider",
+ "shape_detection.mojom.TextDetection"
]
}
},
"navigation:service_worker": {
"provides": {
"renderer": [
- "blink::mojom::BackgroundFetchService",
- "blink::mojom::BudgetService",
- "blink::mojom::CacheStorage",
- "blink::mojom::LockManager",
- "blink::mojom::NotificationService",
- "blink::mojom::PermissionService",
- "blink::mojom::QuotaDispatcherHost",
- "network::mojom::RestrictedCookieManager",
- "network::mojom::WebSocket",
- "payments::mojom::PaymentManager",
- "shape_detection::mojom::BarcodeDetection",
- "shape_detection::mojom::FaceDetectionProvider",
- "shape_detection::mojom::TextDetection"
+ "blink.mojom.BackgroundFetchService",
+ "blink.mojom.BudgetService",
+ "blink.mojom.CacheStorage",
+ "blink.mojom.CookieStore",
+ "blink.mojom.LockManager",
+ "blink.mojom.NotificationService",
+ "blink.mojom.PermissionService",
+ "blink.mojom.QuotaDispatcherHost",
+ "network.mojom.RestrictedCookieManager",
+ "network.mojom.WebSocket",
+ "payments.mojom.PaymentManager",
+ "shape_detection.mojom.BarcodeDetection",
+ "shape_detection.mojom.FaceDetectionProvider",
+ "shape_detection.mojom.TextDetection"
]
}
},
"navigation:shared_worker": {
"provides": {
"renderer": [
- "blink::mojom::BudgetService",
- "blink::mojom::CacheStorage",
- "blink::mojom::LockManager",
- "blink::mojom::NotificationService",
- "blink::mojom::PermissionService",
- "blink::mojom::QuotaDispatcherHost",
- "network::mojom::WebSocket",
- "payments::mojom::PaymentManager",
- "shape_detection::mojom::BarcodeDetection",
- "shape_detection::mojom::FaceDetectionProvider",
- "shape_detection::mojom::TextDetection"
+ "blink.mojom.BudgetService",
+ "blink.mojom.CacheStorage",
+ "blink.mojom.LockManager",
+ "blink.mojom.NotificationService",
+ "blink.mojom.PermissionService",
+ "blink.mojom.QuotaDispatcherHost",
+ "network.mojom.WebSocket",
+ "payments.mojom.PaymentManager",
+ "shape_detection.mojom.BarcodeDetection",
+ "shape_detection.mojom.FaceDetectionProvider",
+ "shape_detection.mojom.TextDetection"
]
}
}
diff --git a/chromium/content/public/app/mojo/content_gpu_manifest.json b/chromium/content/public/app/mojo/content_gpu_manifest.json
index b55e6021dc5..1335cff15ee 100644
--- a/chromium/content/public/app/mojo/content_gpu_manifest.json
+++ b/chromium/content/public/app/mojo/content_gpu_manifest.json
@@ -5,20 +5,20 @@
"service_manager:connector": {
"provides": {
"browser": [
- "content::mojom::Child",
- "content::mojom::ChildControl",
- "content::mojom::ChildHistogramFetcher",
- "content::mojom::ChildHistogramFetcherFactory",
- "content::mojom::ResourceUsageReporter",
- "IPC::mojom::ChannelBootstrap",
- "service_manager::mojom::ServiceFactory",
- "ui::ozone::mojom::DeviceCursor",
- "ui::ozone::mojom::DrmDevice",
- "viz::mojom::CompositingModeReporter",
- "viz::mojom::VizMain"
+ "content.mojom.Child",
+ "content.mojom.ChildControl",
+ "content.mojom.ChildHistogramFetcher",
+ "content.mojom.ChildHistogramFetcherFactory",
+ "content.mojom.ResourceUsageReporter",
+ "IPC.mojom.ChannelBootstrap",
+ "service_manager.mojom.ServiceFactory",
+ "ui.ozone.mojom.DeviceCursor",
+ "ui.ozone.mojom.DrmDevice",
+ "viz.mojom.CompositingModeReporter",
+ "viz.mojom.VizMain"
],
"service_manager:service_factory": [
- "service_manager::mojom::ServiceFactory"
+ "service_manager.mojom.ServiceFactory"
]
},
"requires": {
diff --git a/chromium/content/public/app/mojo/content_packaged_services_manifest.json b/chromium/content/public/app/mojo/content_packaged_services_manifest.json
index 358bd19fbd4..7bee3760674 100644
--- a/chromium/content/public/app/mojo/content_packaged_services_manifest.json
+++ b/chromium/content/public/app/mojo/content_packaged_services_manifest.json
@@ -12,7 +12,7 @@
"service_manager:connector": {
"provides": {
"service_manager:service_factory": [
- "service_manager::mojom::ServiceFactory"
+ "service_manager.mojom.ServiceFactory"
]
},
"requires": {
diff --git a/chromium/content/public/app/mojo/content_plugin_manifest.json b/chromium/content/public/app/mojo/content_plugin_manifest.json
index 91cb6ec4f20..44c6d2bafa5 100644
--- a/chromium/content/public/app/mojo/content_plugin_manifest.json
+++ b/chromium/content/public/app/mojo/content_plugin_manifest.json
@@ -5,15 +5,15 @@
"service_manager:connector": {
"provides": {
"browser": [
- "content::mojom::Child",
- "content::mojom::ChildControl",
- "content::mojom::ChildHistogramFetcher",
- "content::mojom::ChildHistogramFetcherFactory",
- "content::mojom::ResourceUsageReporter",
- "IPC::mojom::ChannelBootstrap"
+ "content.mojom.Child",
+ "content.mojom.ChildControl",
+ "content.mojom.ChildHistogramFetcher",
+ "content.mojom.ChildHistogramFetcherFactory",
+ "content.mojom.ResourceUsageReporter",
+ "IPC.mojom.ChannelBootstrap"
],
"service_manager:service_factory": [
- "service_manager::mojom::ServiceFactory"
+ "service_manager.mojom.ServiceFactory"
]
},
"requires": {
diff --git a/chromium/content/public/app/mojo/content_renderer_manifest.json b/chromium/content/public/app/mojo/content_renderer_manifest.json
index 9c5f03aad42..71bc81d6183 100644
--- a/chromium/content/public/app/mojo/content_renderer_manifest.json
+++ b/chromium/content/public/app/mojo/content_renderer_manifest.json
@@ -5,25 +5,24 @@
"service_manager:connector": {
"provides": {
"browser": [
- "blink::mojom::OomIntervention",
- "blink::mojom::WebDatabase",
- "content::mojom::AppCacheFrontend",
- "content::mojom::Child",
- "content::mojom::ChildControl",
- "content::mojom::ChildHistogramFetcher",
- "content::mojom::ChildHistogramFetcherFactory",
- "content::mojom::EmbeddedWorkerInstanceClient",
- "content::mojom::EmbeddedWorkerSetup",
- "content::mojom::FrameFactory",
- "content::mojom::RenderWidgetWindowTreeClientFactory",
- "content::mojom::ResourceUsageReporter",
- "content::mojom::SharedWorkerFactory",
- "IPC::mojom::ChannelBootstrap",
- "visitedlink::mojom::VisitedLinkNotificationSink",
- "web_cache::mojom::WebCache"
+ "blink.mojom.LeakDetector",
+ "blink.mojom.OomIntervention",
+ "blink.mojom.WebDatabase",
+ "content.mojom.AppCacheFrontend",
+ "content.mojom.Child",
+ "content.mojom.ChildControl",
+ "content.mojom.ChildHistogramFetcher",
+ "content.mojom.ChildHistogramFetcherFactory",
+ "content.mojom.FrameFactory",
+ "content.mojom.RenderWidgetWindowTreeClientFactory",
+ "content.mojom.ResourceUsageReporter",
+ "content.mojom.SharedWorkerFactory",
+ "IPC.mojom.ChannelBootstrap",
+ "visitedlink.mojom.VisitedLinkNotificationSink",
+ "web_cache.mojom.WebCache"
],
"service_manager:service_factory": [
- "service_manager::mojom::ServiceFactory"
+ "service_manager.mojom.ServiceFactory"
]
},
"requires": {
@@ -49,18 +48,18 @@
"navigation:frame": {
"provides": {
"browser": [
- "blink::mojom::AppBannerController",
- "blink::mojom::EngagementClient",
- "blink::mojom::InstallationService",
- "blink::mojom::ManifestManager",
- "blink::mojom::MediaDevicesListener",
- "blink::mojom::TextSuggestionBackend",
- "content::mojom::ImageDownloader",
- "content::mojom::FrameInputHandler",
- "content::mojom::FullscreenVideoElementHandler",
- "content::mojom::MediaStreamDeviceObserver",
- "content::mojom::Widget",
- "viz::mojom::InputTargetClient"
+ "blink.mojom.AppBannerController",
+ "blink.mojom.EngagementClient",
+ "blink.mojom.InstallationService",
+ "blink.mojom.ManifestManager",
+ "blink.mojom.MediaDevicesListener",
+ "blink.mojom.TextSuggestionBackend",
+ "content.mojom.ImageDownloader",
+ "content.mojom.FrameInputHandler",
+ "content.mojom.FullscreenVideoElementHandler",
+ "content.mojom.MediaStreamDeviceObserver",
+ "content.mojom.Widget",
+ "viz.mojom.InputTargetClient"
]
},
"requires": {
diff --git a/chromium/content/public/app/mojo/content_utility_manifest.json b/chromium/content/public/app/mojo/content_utility_manifest.json
index e5cc53c978e..563c88580bd 100644
--- a/chromium/content/public/app/mojo/content_utility_manifest.json
+++ b/chromium/content/public/app/mojo/content_utility_manifest.json
@@ -5,18 +5,18 @@
"service_manager:connector": {
"provides": {
"browser": [
- "content::mojom::Child",
- "content::mojom::ChildControl",
- "content::mojom::ChildHistogramFetcher",
- "content::mojom::ChildHistogramFetcherFactory",
- "content::mojom::ResourceUsageReporter",
- "IPC::mojom::ChannelBootstrap",
- "printing::mojom::PdfToEmfConverterFactory",
- "printing::mojom::PdfToPwgRasterConverter",
- "service_manager::mojom::ServiceFactory"
+ "content.mojom.Child",
+ "content.mojom.ChildControl",
+ "content.mojom.ChildHistogramFetcher",
+ "content.mojom.ChildHistogramFetcherFactory",
+ "content.mojom.ResourceUsageReporter",
+ "IPC.mojom.ChannelBootstrap",
+ "printing.mojom.PdfToEmfConverterFactory",
+ "printing.mojom.PdfToPwgRasterConverter",
+ "service_manager.mojom.ServiceFactory"
],
"service_manager:service_factory": [
- "service_manager::mojom::ServiceFactory"
+ "service_manager.mojom.ServiceFactory"
]
},
"requires": {
diff --git a/chromium/content/public/browser/BUILD.gn b/chromium/content/public/browser/BUILD.gn
index 9646d6b0555..93b61314c26 100644
--- a/chromium/content/public/browser/BUILD.gn
+++ b/chromium/content/public/browser/BUILD.gn
@@ -4,7 +4,6 @@
import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
-import("//media/media_options.gni")
# See //content/BUILD.gn for how this works.
group("browser") {
@@ -38,10 +37,14 @@ jumbo_source_set("browser_sources") {
"android/synchronous_compositor.h",
"android/synchronous_compositor_client.h",
"appcache_service.h",
+ "audio_service_info.cc",
+ "audio_service_info.h",
"ax_event_notification_details.cc",
"ax_event_notification_details.h",
"background_fetch_delegate.cc",
"background_fetch_delegate.h",
+ "background_fetch_description.cc",
+ "background_fetch_description.h",
"background_fetch_response.cc",
"background_fetch_response.h",
"background_sync_controller.h",
@@ -86,12 +89,15 @@ jumbo_source_set("browser_sources") {
"child_process_data.h",
"child_process_launcher_utils.h",
"child_process_security_policy.h",
+ "child_process_termination_info.h",
"client_certificate_delegate.h",
"color_chooser.h",
"content_browser_client.cc",
"content_browser_client.h",
"context_factory.h",
"cookie_store_factory.h",
+ "desktop_capture.cc",
+ "desktop_capture.h",
"desktop_media_id.cc",
"desktop_media_id.h",
"devtools_agent_host.h",
@@ -120,6 +126,7 @@ jumbo_source_set("browser_sources") {
"font_list_async.h",
"frame_service_base.h",
"global_request_id.h",
+ "gpu_client.h",
"gpu_data_manager.h",
"gpu_data_manager_observer.h",
"gpu_feature_checker.cc",
@@ -271,6 +278,7 @@ jumbo_source_set("browser_sources") {
"tracing_delegate.h",
"url_data_source.cc",
"url_data_source.h",
+ "url_loader_request_interceptor.h",
"video_capture_device_launcher.h",
"visibility.h",
"vpn_service_proxy.h",
@@ -298,10 +306,11 @@ jumbo_source_set("browser_sources") {
"web_ui_url_loader_factory.h",
"webrtc_event_logger.cc",
"webrtc_event_logger.h",
+ "webrtc_log.cc",
+ "webrtc_log.h",
"websocket_handshake_request_info.h",
"webvr_service_provider.cc",
"webvr_service_provider.h",
- "zygote_host_linux.h",
]
configs += [
"//build/config:precompiled_headers",
@@ -320,6 +329,8 @@ jumbo_source_set("browser_sources") {
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/service_manager/public/cpp",
"//services/tracing/public/cpp",
+ "//services/ui/public/interfaces",
+ "//third_party/webrtc/modules/desktop_capture",
# We expose skia headers in the public API.
"//skia",
@@ -338,6 +349,7 @@ jumbo_source_set("browser_sources") {
"//media/capture",
"//net",
"//ppapi/c",
+ "//services/service_manager/embedder:embedder_result_codes",
"//ui/accessibility",
"//ui/base",
"//ui/events",
@@ -372,14 +384,4 @@ jumbo_source_set("browser_sources") {
"zoom_level_delegate.h",
]
}
-
- if (enable_webrtc) {
- sources += [
- "desktop_capture.cc",
- "desktop_capture.h",
- "webrtc_log.cc",
- "webrtc_log.h",
- ]
- public_deps += [ "//third_party/webrtc/modules/desktop_capture" ]
- }
}
diff --git a/chromium/content/public/browser/DEPS b/chromium/content/public/browser/DEPS
index 38169801ef2..782fb0e3ad4 100644
--- a/chromium/content/public/browser/DEPS
+++ b/chromium/content/public/browser/DEPS
@@ -9,6 +9,7 @@ include_rules = [
"+services/network/public/cpp",
"+services/service_manager/sandbox",
"+services/resource_coordinator/public",
+ "+services/ui/public/interfaces",
]
specific_include_rules = {
diff --git a/chromium/content/public/browser/android/compositor_client.h b/chromium/content/public/browser/android/compositor_client.h
index bb03a251627..382575219e3 100644
--- a/chromium/content/public/browser/android/compositor_client.h
+++ b/chromium/content/public/browser/android/compositor_client.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "content/common/content_export.h"
+#include "ui/gfx/geometry/size.h"
namespace content {
@@ -21,7 +22,7 @@ class CONTENT_EXPORT CompositorClient {
virtual void DidSwapFrame(int pending_frames) {}
// This is called on all swap buffers, regardless of cause.
- virtual void DidSwapBuffers() {}
+ virtual void DidSwapBuffers(const gfx::Size& swap_size) {}
protected:
CompositorClient() {}
diff --git a/chromium/content/public/browser/android/content_view_layer_renderer.h b/chromium/content/public/browser/android/content_view_layer_renderer.h
index 2911bb4f948..09bf2f6f32d 100644
--- a/chromium/content/public/browser/android/content_view_layer_renderer.h
+++ b/chromium/content/public/browser/android/content_view_layer_renderer.h
@@ -5,19 +5,18 @@
#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_CONTENT_VIEW_LAYER_RENDERER_H_
#define CONTENT_PUBLIC_BROWSER_ANDROID_CONTENT_VIEW_LAYER_RENDERER_H_
-// This interface is used by consumers of the ContentViewRenderView to
-// attach/detach layers.
-
-namespace blink {
-class WebLayer;
+namespace cc {
+class Layer;
}
namespace content {
+// This interface is used by consumers of the ContentViewRenderView to
+// attach/detach layers.
class ContentViewLayerRenderer {
public:
- virtual void AttachLayer(blink::WebLayer* layer) = 0;
- virtual void DetachLayer(blink::WebLayer* layer) = 0;
+ virtual void AttachLayer(cc::Layer* layer) = 0;
+ virtual void DetachLayer(cc::Layer* layer) = 0;
protected:
virtual ~ContentViewLayerRenderer() {}
diff --git a/chromium/content/public/browser/audio_service_info.cc b/chromium/content/public/browser/audio_service_info.cc
new file mode 100644
index 00000000000..e8638324648
--- /dev/null
+++ b/chromium/content/public/browser/audio_service_info.cc
@@ -0,0 +1,26 @@
+// 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/public/browser/audio_service_info.h"
+
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/renderer_host/media/audio_service_listener.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+base::ProcessId GetProcessIdForAudioService() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // May be null in unittests.
+ if (!BrowserMainLoop::GetInstance())
+ return base::kNullProcessId;
+
+ MediaStreamManager* manager =
+ BrowserMainLoop::GetInstance()->media_stream_manager();
+ return manager->audio_service_listener()->GetProcessId();
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/audio_service_info.h b/chromium/content/public/browser/audio_service_info.h
new file mode 100644
index 00000000000..4483043f44b
--- /dev/null
+++ b/chromium/content/public/browser/audio_service_info.h
@@ -0,0 +1,20 @@
+// 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_PUBLIC_BROWSER_AUDIO_SERVICE_INFO_H_
+#define CONTENT_PUBLIC_BROWSER_AUDIO_SERVICE_INFO_H_
+
+#include "base/process/process_handle.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Returns the process id of the audio service utility process or
+// base::kNullProcessId if audio service is not running in an utility process.
+// Must be called on UI thread.
+CONTENT_EXPORT base::ProcessId GetProcessIdForAudioService();
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_AUDIO_SERVICE_INFO_H_
diff --git a/chromium/content/public/browser/background_fetch_delegate.h b/chromium/content/public/browser/background_fetch_delegate.h
index 6830505d4f0..275814357b6 100644
--- a/chromium/content/public/browser/background_fetch_delegate.h
+++ b/chromium/content/public/browser/background_fetch_delegate.h
@@ -16,7 +16,6 @@
#include "content/common/content_export.h"
class GURL;
-class SkBitmap;
namespace gfx {
class Size;
@@ -27,13 +26,18 @@ class HttpRequestHeaders;
struct NetworkTrafficAnnotationTag;
} // namespace net
-namespace url {
-class Origin;
-} // namespace url
-
namespace content {
struct BackgroundFetchResponse;
struct BackgroundFetchResult;
+struct BackgroundFetchDescription;
+
+// Various reasons a Background Fetch can get aborted.
+enum class BackgroundFetchReasonToAbort {
+ NONE,
+ CANCELLED_FROM_UI,
+ ABORTED_BY_DEVELOPER,
+ TOTAL_DOWNLOAD_SIZE_EXCEEDED,
+};
// Interface for launching background fetches. Implementing classes would
// generally interface with the DownloadService or DownloadManager.
@@ -51,7 +55,9 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
// Called when the entire download job has been cancelled by the delegate,
// e.g. because the user clicked cancel on a notification.
- virtual void OnJobCancelled(const std::string& job_unique_id) = 0;
+ virtual void OnJobCancelled(
+ const std::string& job_unique_id,
+ BackgroundFetchReasonToAbort reason_to_abort) = 0;
// Called after the download has started with the initial response
// (including headers and URL chain). Always called on the UI thread.
@@ -92,13 +98,7 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
// contain the GUIDs of in progress downloads, while completed downloads are
// recorded in |completed_parts|.
virtual void CreateDownloadJob(
- const std::string& job_unique_id,
- const std::string& title,
- const url::Origin& origin,
- const SkBitmap& icon,
- int completed_parts,
- int total_parts,
- const std::vector<std::string>& current_guids) = 0;
+ std::unique_ptr<BackgroundFetchDescription> fetch_description) = 0;
// Creates a new download identified by |download_guid| in the download job
// identified by |job_unique_id|.
diff --git a/chromium/content/public/browser/background_fetch_description.cc b/chromium/content/public/browser/background_fetch_description.cc
new file mode 100644
index 00000000000..7857bfd244a
--- /dev/null
+++ b/chromium/content/public/browser/background_fetch_description.cc
@@ -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.
+
+#include "content/public/browser/background_fetch_description.h"
+
+namespace content {
+
+BackgroundFetchDescription::BackgroundFetchDescription(
+ std::string job_unique_id,
+ std::string title,
+ url::Origin origin,
+ SkBitmap icon,
+ int completed_parts,
+ int total_parts,
+ int completed_parts_size,
+ int total_parts_size,
+ std::vector<std::string> current_guids)
+ : job_unique_id(job_unique_id),
+ title(title),
+ origin(origin),
+ icon(icon),
+ completed_parts(completed_parts),
+ total_parts(total_parts),
+ completed_parts_size(completed_parts_size),
+ total_parts_size(total_parts_size),
+ current_guids(std::move(current_guids)) {}
+
+BackgroundFetchDescription::~BackgroundFetchDescription() = default;
+
+} // namespace content
diff --git a/chromium/content/public/browser/background_fetch_description.h b/chromium/content/public/browser/background_fetch_description.h
new file mode 100644
index 00000000000..40d56f07ba3
--- /dev/null
+++ b/chromium/content/public/browser/background_fetch_description.h
@@ -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.
+//
+#ifndef CONTENT_PUBLIC_BROWSER_BACKGROUND_FETCH_DESCRIPTION_H_
+#define CONTENT_PUBLIC_BROWSER_BACKGROUND_FETCH_DESCRIPTION_H_
+
+#include <vector>
+#include "content/common/content_export.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "url/origin.h"
+
+namespace content {
+
+// Contains all information necessary to create
+// a BackgroundFetch download (and in the future, upload) job.
+struct CONTENT_EXPORT BackgroundFetchDescription {
+ BackgroundFetchDescription(std::string job_unique_id,
+ std::string title,
+ url::Origin origin,
+ SkBitmap icon,
+ int completed_parts,
+ int total_parts,
+ int completed_parts_size,
+ int total_parts_size,
+ std::vector<std::string> current_guids);
+ ~BackgroundFetchDescription();
+
+ const std::string job_unique_id;
+ std::string title;
+ const url::Origin origin;
+ SkBitmap icon;
+ int completed_parts;
+ int total_parts;
+ int completed_parts_size;
+ int total_parts_size;
+ std::vector<std::string> current_guids;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDescription);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_BACKGROUND_FETCH_DESCRIPTION_H
diff --git a/chromium/content/public/browser/background_tracing_manager.h b/chromium/content/public/browser/background_tracing_manager.h
index c681d655cb9..dca9d8a3e46 100644
--- a/chromium/content/public/browser/background_tracing_manager.h
+++ b/chromium/content/public/browser/background_tracing_manager.h
@@ -26,21 +26,24 @@ class BackgroundTracingManager {
// BackgroundTracingManager finalizes a trace. The first parameter of this
// callback is the trace data. The second is metadata that was generated and
// embedded into the trace. The third is a callback to notify the
- // BackgroundTracingManager that you've finished processing the trace data.
+ // BackgroundTracingManager that you've finished processing the trace data
+ // and whether we were successful or not.
//
// Example:
//
// void Upload(const scoped_refptr<base::RefCountedString>& data,
- // base::Closure done_callback) {
+ // FinishedProcessingCallback done_callback) {
// base::PostTaskWithTraitsAndReply(
// FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
- // base::Bind(&DoUploadInBackground, data), done_callback);
+ // base::BindOnce(&DoUploadInBackground, data),
+ // std::move(done_callback));
// }
//
+ using FinishedProcessingCallback = base::OnceCallback<void(bool success)>;
using ReceiveCallback =
- base::Callback<void(const scoped_refptr<base::RefCountedString>&,
- std::unique_ptr<const base::DictionaryValue>,
- base::Closure)>;
+ base::OnceCallback<void(const scoped_refptr<base::RefCountedString>&,
+ std::unique_ptr<const base::DictionaryValue>,
+ FinishedProcessingCallback)>;
// Set the triggering rules for when to start recording.
//
@@ -63,7 +66,7 @@ class BackgroundTracingManager {
};
virtual bool SetActiveScenario(
std::unique_ptr<BackgroundTracingConfig> config,
- const ReceiveCallback& receive_callback,
+ ReceiveCallback receive_callback,
DataFiltering data_filtering) = 0;
// Notifies the caller when the manager is idle (not recording or uploading),
diff --git a/chromium/content/public/browser/browser_child_process_host.h b/chromium/content/public/browser/browser_child_process_host.h
index 16c7089a2d0..3d9a91c4e88 100644
--- a/chromium/content/public/browser/browser_child_process_host.h
+++ b/chromium/content/public/browser/browser_child_process_host.h
@@ -12,6 +12,7 @@
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
+#include "content/public/browser/child_process_termination_info.h"
#include "content/public/common/process_type.h"
#include "ipc/ipc_sender.h"
#include "services/service_manager/public/mojom/service.mojom.h"
@@ -69,15 +70,11 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
// Returns the ChildProcessHost object used by this object.
virtual ChildProcessHost* GetHost() const = 0;
- // Returns the termination status of a child. |exit_code| is the
- // status returned when the process exited (for posix, as returned
- // from waitpid(), for Windows, as returned from
- // GetExitCodeProcess()). |exit_code| may be nullptr.
+ // Returns the termination info of a child.
// |known_dead| indicates that the child is already dead. On Linux, this
// information is necessary to retrieve accurate information. See
- // ChildProcessLauncher::GetChildTerminationStatus() for more details.
- virtual base::TerminationStatus GetTerminationStatus(
- bool known_dead, int* exit_code) = 0;
+ // ChildProcessLauncher::GetChildTerminationInfo() for more details.
+ virtual ChildProcessTerminationInfo GetTerminationInfo(bool known_dead) = 0;
// Take ownership of a "shared" metrics allocator (if one exists).
virtual std::unique_ptr<base::SharedPersistentMemoryAllocator>
diff --git a/chromium/content/public/browser/browser_child_process_observer.h b/chromium/content/public/browser/browser_child_process_observer.h
index faaa175a53a..ddf9cd2b623 100644
--- a/chromium/content/public/browser/browser_child_process_observer.h
+++ b/chromium/content/public/browser/browser_child_process_observer.h
@@ -10,6 +10,7 @@
namespace content {
struct ChildProcessData;
+struct ChildProcessTerminationInfo;
// An observer API implemented by classes which are interested in browser child
// process events. Note that render processes cannot be observed through this
@@ -31,15 +32,20 @@ class CONTENT_EXPORT BrowserChildProcessObserver {
const ChildProcessData& data) {}
// Called when a child process disappears unexpectedly as a result of a crash.
- // |exit_code| contains the exit code from the process.
- virtual void BrowserChildProcessCrashed(const ChildProcessData& data,
- int exit_code) {}
+ virtual void BrowserChildProcessCrashed(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) {}
// Called when a child process disappears unexpectedly as a result of being
// killed.
- // |exit_code| contains the exit code from the process.
- virtual void BrowserChildProcessKilled(const ChildProcessData& data,
- int exit_code) {}
+ virtual void BrowserChildProcessKilled(
+ const ChildProcessData& data,
+ const ChildProcessTerminationInfo& info) {}
+
+ // Note for Android. There is no way to reliably distinguish between Crash
+ // and Kill. Arbitrarily choose all abnormal terminations on Android to call
+ // BrowserChildProcessKilled, which means BrowserChildProcessCrashed will
+ // never be called on Android.
protected:
// The observer can be destroyed on any thread.
diff --git a/chromium/content/public/browser/browser_context.h b/chromium/content/public/browser/browser_context.h
index ddb42286696..b5cad2b7364 100644
--- a/chromium/content/public/browser/browser_context.h
+++ b/chromium/content/public/browser/browser_context.h
@@ -29,7 +29,6 @@ class GURL;
namespace base {
class FilePath;
-class Time;
}
namespace service_manager {
@@ -135,21 +134,15 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
using BlobContextGetter =
base::RepeatingCallback<base::WeakPtr<storage::BlobStorageContext>()>;
- // |callback| returns a nullptr scoped_ptr on failure.
+ // This method should be called on UI thread and calls back on UI thread
+ // as well. Note that retrieving a blob ptr out of BlobHandle can only be
+ // done on IO. |callback| returns a nullptr on failure.
static void CreateMemoryBackedBlob(BrowserContext* browser_context,
const char* data,
size_t length,
const std::string& content_type,
BlobCallback callback);
- // |callback| returns a nullptr scoped_ptr on failure.
- static void CreateFileBackedBlob(BrowserContext* browser_context,
- const base::FilePath& path,
- int64_t offset,
- int64_t size,
- const base::Time& expected_modification_time,
- BlobCallback callback);
-
// Get a BlobStorageContext getter that needs to run on IO thread.
static BlobContextGetter GetBlobStorageContext(
BrowserContext* browser_context);
@@ -301,6 +294,9 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
// by the Service Manager.
virtual void RegisterInProcessServices(StaticServiceMap* services) {}
+ // Returns a unique string associated with this browser context.
+ virtual const std::string& UniqueId() const;
+
// Returns a random salt string that is used for creating media device IDs.
// Returns a random string by default.
virtual std::string GetMediaDeviceIDSalt();
@@ -317,7 +313,7 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
virtual media::VideoDecodePerfHistory* GetVideoDecodePerfHistory();
private:
- const std::string media_device_id_salt_;
+ const std::string unique_id_;
bool was_notify_will_be_destroyed_called_ = false;
};
diff --git a/chromium/content/public/browser/browser_main_parts.cc b/chromium/content/public/browser/browser_main_parts.cc
index 108bf6b4235..130ad375fea 100644
--- a/chromium/content/public/browser/browser_main_parts.cc
+++ b/chromium/content/public/browser/browser_main_parts.cc
@@ -4,7 +4,7 @@
#include "content/public/browser/browser_main_parts.h"
-#include "content/public/common/result_codes.h"
+#include "services/service_manager/embedder/result_codes.h"
namespace content {
@@ -13,7 +13,7 @@ bool BrowserMainParts::ShouldContentCreateFeatureList() {
}
int BrowserMainParts::PreEarlyInitialization() {
- return RESULT_CODE_NORMAL_EXIT;
+ return service_manager::RESULT_CODE_NORMAL_EXIT;
}
int BrowserMainParts::PreCreateThreads() {
diff --git a/chromium/content/public/browser/browser_main_parts.h b/chromium/content/public/browser/browser_main_parts.h
index 630d0251875..4b8b672fd40 100644
--- a/chromium/content/public/browser/browser_main_parts.h
+++ b/chromium/content/public/browser/browser_main_parts.h
@@ -30,7 +30,7 @@ class ServiceManagerConnection;
// things which should be done immediately before the start of the main
// message loop should go in |PreMainMessageLoopStart()|.
// - RunMainMessageLoopParts: things to be done before and after invoking the
-// main message loop run method (e.g. MessageLoopForUI::current()->Run()).
+// main message loop run method (e.g. MessageLoopCurrentForUI::Get()->Run()).
//
// How to add stuff (to existing parts):
// - Figure out when your new code should be executed. What must happen
diff --git a/chromium/content/public/browser/browsing_data_filter_builder.h b/chromium/content/public/browser/browsing_data_filter_builder.h
index 1d75cd40e94..e99ffc878e7 100644
--- a/chromium/content/public/browser/browsing_data_filter_builder.h
+++ b/chromium/content/public/browser/browsing_data_filter_builder.h
@@ -17,10 +17,6 @@
class GURL;
-namespace net {
-class CanonicalCookie;
-}
-
namespace url {
class Origin;
}
@@ -70,20 +66,17 @@ class CONTENT_EXPORT BrowsingDataFilterBuilder {
virtual base::RepeatingCallback<bool(const GURL&)>
BuildGeneralFilter() const = 0;
- // Builds a filter that can be used with the network service, more precisely
- // with NetworkContext.ClearHttpCache().
- virtual network::mojom::ClearCacheUrlFilterPtr BuildClearCacheUrlFilter()
+ // Builds a filter that can be used with the network service. This uses a Mojo
+ // struct rather than a predicate function (as used by the rest of the filters
+ // built by this class) because we need to be able to pass the filter to the
+ // network service via IPC.
+ virtual network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter()
const = 0;
- // Builds a filter that matches cookies whose sources are in the whitelist,
- // or aren't in the blacklist.
- virtual base::RepeatingCallback<bool(const net::CanonicalCookie& pattern)>
- BuildCookieFilter() const = 0;
-
- // Builds a filter that matches channel IDs whose server identifiers are in
- // the whitelist, or aren't in the blacklist.
- virtual base::RepeatingCallback<bool(const std::string& server_id)>
- BuildChannelIDFilter() const = 0;
+ // Builds a CookieDeletionInfo object that matches cookies whose sources are
+ // in the whitelist, or aren't in the blacklist.
+ virtual network::mojom::CookieDeletionFilterPtr BuildCookieDeletionFilter()
+ const = 0;
// Builds a filter that matches the |site| of a plugin.
virtual base::RepeatingCallback<bool(const std::string& site)>
diff --git a/chromium/content/public/browser/browsing_data_remover.h b/chromium/content/public/browser/browsing_data_remover.h
index f672bcc1a22..ba4694da241 100644
--- a/chromium/content/public/browser/browsing_data_remover.h
+++ b/chromium/content/public/browser/browsing_data_remover.h
@@ -70,6 +70,8 @@ class BrowsingDataRemover {
DATA_TYPE_WEB_SQL = 1 << 4,
DATA_TYPE_SERVICE_WORKERS = 1 << 5,
DATA_TYPE_CACHE_STORAGE = 1 << 6,
+ // This is also persisted, keep with storage datatypes.
+ DATA_TYPE_BACKGROUND_FETCH = 1 << 14,
// Used to request the deletion of embedder-specific storage datatypes.
DATA_TYPE_EMBEDDER_DOM_STORAGE = 1 << 7,
@@ -77,13 +79,11 @@ class BrowsingDataRemover {
// DOM-accessible storage (https://www.w3.org/TR/clear-site-data/#storage).
// Has the same effect as selecting all storage datatypes listed above
// and ones defined by the embedder.
- DATA_TYPE_DOM_STORAGE = DATA_TYPE_APP_CACHE | DATA_TYPE_FILE_SYSTEMS |
- DATA_TYPE_INDEXED_DB |
- DATA_TYPE_LOCAL_STORAGE |
- DATA_TYPE_WEB_SQL |
- DATA_TYPE_SERVICE_WORKERS |
- DATA_TYPE_CACHE_STORAGE |
- DATA_TYPE_EMBEDDER_DOM_STORAGE,
+ DATA_TYPE_DOM_STORAGE =
+ DATA_TYPE_APP_CACHE | DATA_TYPE_FILE_SYSTEMS | DATA_TYPE_INDEXED_DB |
+ DATA_TYPE_LOCAL_STORAGE | DATA_TYPE_WEB_SQL |
+ DATA_TYPE_SERVICE_WORKERS | DATA_TYPE_CACHE_STORAGE |
+ DATA_TYPE_EMBEDDER_DOM_STORAGE | DATA_TYPE_BACKGROUND_FETCH,
// Other datatypes.
DATA_TYPE_COOKIES = 1 << 8,
@@ -100,7 +100,7 @@ class BrowsingDataRemover {
// deleting COOKIES and CHANNEL IDs, BrowsingDataRemover should skip
// storage backends whose deletion would cause closing network connections.
// TODO(crbug.com/798760): Remove when fixed.
- DATA_TYPE_AVOID_CLOSING_CONNECTIONS = 1 << 14,
+ DATA_TYPE_AVOID_CLOSING_CONNECTIONS = 1 << 15,
// Embedders can add more datatypes beyond this point.
DATA_TYPE_CONTENT_END = DATA_TYPE_AVOID_CLOSING_CONNECTIONS,
diff --git a/chromium/content/public/browser/child_process_termination_info.h b/chromium/content/public/browser/child_process_termination_info.h
new file mode 100644
index 00000000000..37a325679b1
--- /dev/null
+++ b/chromium/content/public/browser/child_process_termination_info.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 CONTENT_PUBLIC_BROWSER_CHILD_PROCESS_TERMINATION_INFO_H_
+#define CONTENT_PUBLIC_BROWSER_CHILD_PROCESS_TERMINATION_INFO_H_
+
+#include "base/process/kill.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "content/public/common/result_codes.h"
+
+namespace content {
+
+struct ChildProcessTerminationInfo {
+ base::TerminationStatus status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
+
+ // If |status| is TERMINATION_STATUS_LAUNCH_FAILED then |exit_code| will
+ // contain a platform specific launch failure error code. Otherwise, it will
+ // contain the exit code for the process (e.g. status from waitpid if on
+ // posix, from GetExitCodeProcess on Windows).
+ int exit_code = service_manager::RESULT_CODE_NORMAL_EXIT;
+
+ // Time delta between 1) the process start and 2) the time when
+ // ChildProcessTerminationInfo is computed.
+ base::TimeDelta uptime = base::TimeDelta::Max();
+
+#if defined(OS_ANDROID)
+ // True if child service has strong or moderate binding at time of death.
+ bool has_oom_protection_bindings = false;
+
+ // True if child service was explicitly killed by browser.
+ bool was_killed_intentionally_by_browser = false;
+#endif
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_CHILD_PROCESS_TERMINATION_INFO_H_
diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc
index f6ae6d1d445..a8927d0ba8d 100644
--- a/chromium/content/public/browser/content_browser_client.cc
+++ b/chromium/content/public/browser/content_browser_client.cc
@@ -17,6 +17,7 @@
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/page_navigator.h"
+#include "content/public/browser/url_loader_request_interceptor.h"
#include "content/public/browser/vpn_service_proxy.h"
#include "content/public/common/url_loader_throttle.h"
#include "device/geolocation/public/cpp/location_provider.h"
@@ -166,11 +167,19 @@ bool ContentBrowserClient::ShouldSwapBrowsingInstancesForNavigation(
return false;
}
+bool ContentBrowserClient::ShouldIsolateErrorPage(bool in_main_frame) {
+ return false;
+}
+
std::unique_ptr<media::AudioManager> ContentBrowserClient::CreateAudioManager(
media::AudioLogFactory* audio_log_factory) {
return nullptr;
}
+bool ContentBrowserClient::OverridesAudioManager() {
+ return false;
+}
+
std::unique_ptr<media::CdmFactory> ContentBrowserClient::CreateCdmFactory() {
return nullptr;
}
@@ -591,12 +600,12 @@ ContentBrowserClient::CreateURLLoaderThrottles(
}
void ContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
- RenderFrameHost* frame_host,
+ int frame_tree_node_id,
NonNetworkURLLoaderFactoryMap* factories) {}
void ContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
- RenderFrameHost* frame_host,
- const GURL& frame_url,
+ int render_process_id,
+ int render_frame_id,
NonNetworkURLLoaderFactoryMap* factories) {}
bool ContentBrowserClient::WillCreateURLLoaderFactory(
@@ -617,6 +626,7 @@ network::mojom::NetworkContextPtr ContentBrowserClient::CreateNetworkContext(
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->user_agent = GetContentClient()->GetUserAgent();
+ context_params->accept_language = "en-us,en";
context_params->enable_data_url_support = true;
context_params->enable_file_url_support = true;
GetNetworkService()->CreateNetworkContext(MakeRequest(&network_context),
@@ -695,11 +705,10 @@ ContentBrowserClient::CreateClientCertStore(ResourceContext* resource_context) {
scoped_refptr<LoginDelegate> ContentBrowserClient::CreateLoginDelegate(
net::AuthChallengeInfo* auth_info,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
- bool is_main_frame,
+ bool is_request_for_main_frame,
const GURL& url,
bool first_auth_attempt,
- const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
- auth_required_callback) {
+ LoginAuthRequiredCallback auth_required_callback) {
return nullptr;
}
@@ -720,4 +729,11 @@ ContentBrowserClient::CreateWindowForPictureInPicture(
return nullptr;
}
+std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
+ContentBrowserClient::WillCreateURLLoaderRequestInterceptors(
+ NavigationUIData* navigation_ui_data,
+ int frame_tree_node_id) {
+ return std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>();
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h
index 63cb3851db0..e9c6b810e05 100644
--- a/chromium/content/public/browser/content_browser_client.h
+++ b/chromium/content/public/browser/content_browser_client.h
@@ -46,15 +46,17 @@
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || defined(OS_FUCHSIA)
#include "base/posix/global_descriptors.h"
#endif
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
#include "content/public/browser/posix_file_descriptor_info.h"
#endif
class GURL;
+using LoginAuthRequiredCallback =
+ base::OnceCallback<void(const base::Optional<net::AuthCredentials>&)>;
namespace base {
class CommandLine;
@@ -151,10 +153,12 @@ class RenderFrameHost;
class RenderProcessHost;
class RenderViewHost;
class ResourceContext;
+class ServiceManagerConnection;
class SiteInstance;
class SpeechRecognitionManagerDelegate;
class StoragePartition;
class TracingDelegate;
+class URLLoaderRequestInterceptor;
class URLLoaderThrottle;
class VpnServiceProxy;
class WebContents;
@@ -366,6 +370,9 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& current_url,
const GURL& new_url);
+ // Returns true if error page should be isolated in its own process.
+ virtual bool ShouldIsolateErrorPage(bool in_main_frame);
+
// Returns true if the passed in URL should be assigned as the site of the
// current SiteInstance, if it does not yet have a site.
virtual bool ShouldAssignSiteForURL(const GURL& url);
@@ -816,8 +823,11 @@ class CONTENT_EXPORT ContentBrowserClient {
std::map<std::string, service_manager::EmbeddedServiceInfo>;
// Registers services to be loaded in the browser process by the Service
- // Manager.
- virtual void RegisterInProcessServices(StaticServiceMap* services) {}
+ // Manager. |connection| is the ServiceManagerConnection service are
+ // registered with.
+ virtual void RegisterInProcessServices(StaticServiceMap* services,
+ ServiceManagerConnection* connection) {
+ }
virtual void OverrideOnBindInterface(
const service_manager::BindSourceInfo& remote_info,
@@ -924,18 +934,23 @@ class CONTENT_EXPORT ContentBrowserClient {
// will be used.
virtual std::unique_ptr<media::AudioManager> CreateAudioManager(
media::AudioLogFactory* audio_log_factory);
+
+ // Returns true if (and only if) CreateAudioManager() is implemented and
+ // returns a non-null value.
+ virtual bool OverridesAudioManager();
+
// Creates and returns a factory used for creating CDM instances for playing
// protected content.
virtual std::unique_ptr<media::CdmFactory> CreateCdmFactory();
// Populates |mappings| with all files that need to be mapped before launching
// a child process.
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
+#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || defined(OS_FUCHSIA)
virtual void GetAdditionalMappedFilesForChildProcess(
const base::CommandLine& command_line,
int child_process_id,
content::PosixFileDescriptorInfo* mappings) {}
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
+#endif // defined(OS_POSIX) && !defined(OS_MACOSX) || defined(OS_FUCHSIA)
#if defined(OS_WIN)
// This is called on the PROCESS_LAUNCHER thread before the renderer process
@@ -984,20 +999,23 @@ class CONTENT_EXPORT ContentBrowserClient {
// Allows the embedder to register per-scheme URLLoaderFactory implementations
// to handle navigation URL requests for schemes not handled by the Network
// Service. Only called when the Network Service is enabled.
+ // Note that a RenderFrameHost or RenderProcessHost aren't passed in because
+ // these can change during a navigation (e.g. depending on redirects).
using NonNetworkURLLoaderFactoryMap =
std::map<std::string, std::unique_ptr<network::mojom::URLLoaderFactory>>;
virtual void RegisterNonNetworkNavigationURLLoaderFactories(
- RenderFrameHost* frame_host,
+ int frame_tree_node_id,
NonNetworkURLLoaderFactoryMap* factories);
// Allows the embedder to register per-scheme URLLoaderFactory implementations
// to handle subresource URL requests for schemes not handled by the Network
- // Service. The factories added to this map will only be used to service
- // subresource requests from |frame_host| as long as it's navigated to
- // |frame_url|. Only called when the Network Service is enabled.
+ // Service. This function can also be used to make a factory for other
+ // non-subresource requests, such as for the service worker script when
+ // starting a service worker. In that case, the frame id will be
+ // MSG_ROUTING_NONE.
virtual void RegisterNonNetworkSubresourceURLLoaderFactories(
- RenderFrameHost* frame_host,
- const GURL& frame_url,
+ int render_process_id,
+ int render_frame_id,
NonNetworkURLLoaderFactoryMap* factories);
// Allows the embedder to intercept URLLoaderFactory interfaces used for
@@ -1015,6 +1033,15 @@ class CONTENT_EXPORT ContentBrowserClient {
bool is_navigation,
network::mojom::URLLoaderFactoryRequest* factory_request);
+ // Allows the embedder to returns a list of request interceptors that can
+ // intercept a navigation request.
+ //
+ // Always called on the IO thread and only when the Network Service is
+ // enabled.
+ virtual std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
+ WillCreateURLLoaderRequestInterceptors(NavigationUIData* navigation_ui_data,
+ int frame_tree_node_id);
+
// Creates a NetworkContext for a BrowserContext's StoragePartition. If the
// network service is enabled, it must return a NetworkContext using the
// network service. If the network service is disabled, the embedder may
@@ -1144,11 +1171,10 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual scoped_refptr<LoginDelegate> CreateLoginDelegate(
net::AuthChallengeInfo* auth_info,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
- bool is_main_frame,
+ bool is_request_for_main_frame,
const GURL& url,
bool first_auth_attempt,
- const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
- auth_required_callback);
+ LoginAuthRequiredCallback auth_required_callback);
// Launches the url for the given tab. Returns true if an attempt to handle
// the url was made, e.g. by launching an app. Note that this does not
diff --git a/chromium/content/public/browser/desktop_capture.cc b/chromium/content/public/browser/desktop_capture.cc
index 016a774820e..2d41880a3bb 100644
--- a/chromium/content/public/browser/desktop_capture.cc
+++ b/chromium/content/public/browser/desktop_capture.cc
@@ -6,6 +6,7 @@
#include "base/feature_list.h"
#include "build/build_config.h"
+#include "content/public/common/content_features.h"
namespace content {
namespace desktop_capture {
@@ -24,7 +25,11 @@ webrtc::DesktopCaptureOptions CreateDesktopCaptureOptions() {
} else {
options.set_allow_use_magnification_api(true);
}
-#endif // defined(OS_WIN)
+#elif defined(OS_MACOSX)
+ if (base::FeatureList::IsEnabled(features::kIOSurfaceCapturer)) {
+ options.set_allow_iosurface(true);
+ }
+#endif
return options;
}
diff --git a/chromium/content/public/browser/devtools_agent_host.h b/chromium/content/public/browser/devtools_agent_host.h
index a6e78f907cd..0be97b39183 100644
--- a/chromium/content/public/browser/devtools_agent_host.h
+++ b/chromium/content/public/browser/devtools_agent_host.h
@@ -121,10 +121,6 @@ class CONTENT_EXPORT DevToolsAgentHost
// Returns |true| on success.
virtual bool AttachRestrictedClient(DevToolsAgentHostClient* client) = 0;
- // Attaches |client| to this agent host to start debugging. Disconnects
- // any existing clients.
- virtual void ForceAttachClient(DevToolsAgentHostClient* client) = 0;
-
// Already attached client detaches from this agent host to stop debugging it.
// Returns true iff detach succeeded.
virtual bool DetachClient(DevToolsAgentHostClient* client) = 0;
diff --git a/chromium/content/public/browser/download_manager.h b/chromium/content/public/browser/download_manager.h
index e9480a681d8..0708c4157d0 100644
--- a/chromium/content/public/browser/download_manager.h
+++ b/chromium/content/public/browser/download_manager.h
@@ -43,18 +43,16 @@
#include "components/download/public/common/input_stream.h"
#include "content/common/content_export.h"
#include "net/base/net_errors.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "storage/browser/blob/blob_data_handle.h"
class GURL;
namespace download {
struct DownloadCreateInfo;
+class DownloadURLLoaderFactoryGetter;
} // namespace download
-namespace network {
-class SharedURLLoaderFactory;
-} // namespace network
-
namespace content {
class BrowserContext;
@@ -121,12 +119,13 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
// Called by a download source (Currently DownloadResourceHandler)
// to initiate the non-source portions of a download.
// If the DownloadCreateInfo specifies an id, that id will be used.
- // If |shared_url_loader_factory| is provided, it can be used to issue
+ // If |url_loader_factory_getter| is provided, it can be used to issue
// parallel download requests.
virtual void StartDownload(
std::unique_ptr<download::DownloadCreateInfo> info,
std::unique_ptr<download::InputStream> stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const download::DownloadUrlParameters::OnStartedCallback& on_started) = 0;
// Remove downloads whose URLs match the |url_filter| and are within
@@ -151,7 +150,9 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
// fail.
virtual void DownloadUrl(
std::unique_ptr<download::DownloadUrlParameters> parameters,
- std::unique_ptr<storage::BlobDataHandle> blob_data_handle) = 0;
+ std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+ scoped_refptr<network::SharedURLLoaderFactory>
+ blob_url_loader_factory) = 0;
// Allow objects to observe the download creation process.
virtual void AddObserver(Observer* observer) = 0;
diff --git a/chromium/content/public/browser/download_manager_delegate.cc b/chromium/content/public/browser/download_manager_delegate.cc
index 8eac05f2552..b5963aa8b77 100644
--- a/chromium/content/public/browser/download_manager_delegate.cc
+++ b/chromium/content/public/browser/download_manager_delegate.cc
@@ -53,10 +53,6 @@ bool DownloadManagerDelegate::GenerateFileHash() {
return false;
}
-download::InProgressCache* DownloadManagerDelegate::GetInProgressCache() {
- return nullptr;
-}
-
std::string
DownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
return std::string();
diff --git a/chromium/content/public/browser/download_manager_delegate.h b/chromium/content/public/browser/download_manager_delegate.h
index 579ea358435..ac3055c280e 100644
--- a/chromium/content/public/browser/download_manager_delegate.h
+++ b/chromium/content/public/browser/download_manager_delegate.h
@@ -17,9 +17,6 @@
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/save_page_type.h"
-namespace download {
-class InProgressCache;
-} // namespace download
namespace content {
@@ -138,9 +135,6 @@ class CONTENT_EXPORT DownloadManagerDelegate {
base::FilePath* download_save_dir,
bool* skip_dir_check) {}
- // Returns the metadata cache for in-progress downloads.
- virtual download::InProgressCache* GetInProgressCache();
-
// Asks the user for the path to save a page. The delegate calls the callback
// to give the answer.
virtual void ChooseSavePath(
diff --git a/chromium/content/public/browser/file_url_loader.h b/chromium/content/public/browser/file_url_loader.h
index c8a7ed86a51..b6f0f24ec72 100644
--- a/chromium/content/public/browser/file_url_loader.h
+++ b/chromium/content/public/browser/file_url_loader.h
@@ -22,7 +22,6 @@ class CONTENT_EXPORT FileURLLoaderObserver
~FileURLLoaderObserver() override {}
virtual void OnStart() {}
- virtual void OnOpenComplete(int result) {}
virtual void OnSeekComplete(int64_t result) {}
private:
diff --git a/chromium/content/public/browser/gpu_client.h b/chromium/content/public/browser/gpu_client.h
new file mode 100644
index 00000000000..77a7e386c5d
--- /dev/null
+++ b/chromium/content/public/browser/gpu_client.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 CONTENT_PUBLIC_BROWSER_GPU_CLIENT_H_
+#define CONTENT_PUBLIC_BROWSER_GPU_CLIENT_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
+#include "services/ui/public/interfaces/gpu.mojom.h"
+
+namespace content {
+
+// GpuClient provides an implementation of ui::mojom::Gpu.
+class CONTENT_EXPORT GpuClient {
+ public:
+ virtual ~GpuClient() {}
+
+ using ConnectionErrorHandlerClosure =
+ base::OnceCallback<void(GpuClient* client)>;
+ static std::unique_ptr<GpuClient, BrowserThread::DeleteOnIOThread> Create(
+ ui::mojom::GpuRequest request,
+ ConnectionErrorHandlerClosure connection_error_handler);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_GPU_CLIENT_H_
diff --git a/chromium/content/public/browser/gpu_data_manager.h b/chromium/content/public/browser/gpu_data_manager.h
index ebe6ba517c6..481bf03ef3d 100644
--- a/chromium/content/public/browser/gpu_data_manager.h
+++ b/chromium/content/public/browser/gpu_data_manager.h
@@ -61,10 +61,6 @@ class GpuDataManager {
// Whether a GPU is in use (as opposed to a software renderer).
virtual bool HardwareAccelerationEnabled() const = 0;
- // Extensions that are currently disabled.
- virtual void GetDisabledExtensions(
- std::string* disabled_extensions) const = 0;
-
protected:
virtual ~GpuDataManager() {}
};
diff --git a/chromium/content/public/browser/gpu_utils.cc b/chromium/content/public/browser/gpu_utils.cc
index b2fd38514cb..52db4930d03 100644
--- a/chromium/content/public/browser/gpu_utils.cc
+++ b/chromium/content/public/browser/gpu_utils.cc
@@ -4,20 +4,21 @@
#include "content/public/browser/gpu_utils.h"
+#include <string>
+
#include "base/command_line.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/service_utils.h"
-#include "gpu/config/gpu_switches.h"
#include "media/media_buildflags.h"
-#include "ui/gl/gl_switches.h"
namespace {
+#if defined(OS_WIN)
bool GetUintFromSwitch(const base::CommandLine* command_line,
const base::StringPiece& switch_string,
uint32_t* value) {
@@ -26,6 +27,7 @@ bool GetUintFromSwitch(const base::CommandLine* command_line,
std::string switch_value(command_line->GetSwitchValueASCII(switch_string));
return base::StringToUint(switch_value, value);
}
+#endif // defined(OS_WIN)
void RunTaskOnTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
@@ -49,7 +51,8 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
DCHECK(base::CommandLine::InitializedForCurrentProcess());
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
- gpu::GpuPreferences gpu_preferences;
+ gpu::GpuPreferences gpu_preferences =
+ gpu::gles2::ParseGpuPreferences(command_line);
gpu_preferences.single_process =
command_line->HasSwitch(switches::kSingleProcess);
gpu_preferences.in_process_gpu =
@@ -78,50 +81,6 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
command_line->HasSwitch(switches::kDisableSoftwareRasterizer);
gpu_preferences.log_gpu_control_list_decisions =
command_line->HasSwitch(switches::kLogGpuControlListDecisions);
- gpu_preferences.compile_shader_always_succeeds =
- command_line->HasSwitch(switches::kCompileShaderAlwaysSucceeds);
- gpu_preferences.disable_gl_error_limit =
- command_line->HasSwitch(switches::kDisableGLErrorLimit);
- gpu_preferences.disable_glsl_translator =
- command_line->HasSwitch(switches::kDisableGLSLTranslator);
- gpu_preferences.disable_shader_name_hashing =
- command_line->HasSwitch(switches::kDisableShaderNameHashing);
- gpu_preferences.enable_gpu_command_logging =
- command_line->HasSwitch(switches::kEnableGPUCommandLogging);
- gpu_preferences.enable_gpu_debugging =
- command_line->HasSwitch(switches::kEnableGPUDebugging);
- gpu_preferences.enable_gpu_service_logging_gpu =
- command_line->HasSwitch(switches::kEnableGPUServiceLoggingGPU);
- gpu_preferences.enable_gpu_driver_debug_logging =
- command_line->HasSwitch(switches::kEnableGPUDriverDebugLogging);
- gpu_preferences.disable_gpu_program_cache =
- command_line->HasSwitch(switches::kDisableGpuProgramCache);
- gpu_preferences.enforce_gl_minimums =
- command_line->HasSwitch(switches::kEnforceGLMinimums);
- if (GetUintFromSwitch(command_line, switches::kForceGpuMemAvailableMb,
- &gpu_preferences.force_gpu_mem_available)) {
- gpu_preferences.force_gpu_mem_available *= 1024 * 1024;
- }
- if (GetUintFromSwitch(command_line, switches::kGpuProgramCacheSizeKb,
- &gpu_preferences.gpu_program_cache_size)) {
- gpu_preferences.gpu_program_cache_size *= 1024;
- }
- gpu_preferences.disable_gpu_shader_disk_cache =
- command_line->HasSwitch(switches::kDisableGpuShaderDiskCache);
- gpu_preferences.enable_threaded_texture_mailboxes =
- command_line->HasSwitch(switches::kEnableThreadedTextureMailboxes);
- gpu_preferences.gl_shader_interm_output =
- command_line->HasSwitch(switches::kGLShaderIntermOutput);
- gpu_preferences.emulate_shader_precision =
- command_line->HasSwitch(switches::kEmulateShaderPrecision);
- gpu_preferences.enable_raster_decoder =
- command_line->HasSwitch(switches::kEnableRasterDecoder);
- gpu_preferences.enable_gpu_service_logging =
- command_line->HasSwitch(switches::kEnableGPUServiceLogging);
- gpu_preferences.enable_gpu_service_tracing =
- command_line->HasSwitch(switches::kEnableGPUServiceTracing);
- gpu_preferences.use_passthrough_cmd_decoder =
- gpu::gles2::UsePassthroughCommandDecoder(command_line);
gpu_preferences.gpu_startup_dialog =
command_line->HasSwitch(switches::kGpuStartupDialog);
gpu_preferences.disable_gpu_watchdog =
@@ -129,10 +88,6 @@ const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
(gpu_preferences.single_process || gpu_preferences.in_process_gpu);
gpu_preferences.gpu_sandbox_start_early =
command_line->HasSwitch(switches::kGpuSandboxStartEarly);
- gpu_preferences.disable_gpu_driver_bug_workarounds =
- command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds);
- gpu_preferences.ignore_gpu_blacklist =
- command_line->HasSwitch(switches::kIgnoreGpuBlacklist);
// Some of these preferences are set or adjusted in
// GpuDataManagerImplPrivate::AppendGpuCommandLine.
return gpu_preferences;
diff --git a/chromium/content/public/browser/keyboard_event_processing_result.h b/chromium/content/public/browser/keyboard_event_processing_result.h
index 4030a527e7c..ba43542c7ab 100644
--- a/chromium/content/public/browser/keyboard_event_processing_result.h
+++ b/chromium/content/public/browser/keyboard_event_processing_result.h
@@ -11,6 +11,9 @@ enum class KeyboardEventProcessingResult {
// The event was handled.
HANDLED,
+ // The event was handled, and we want to be notified of the keyup event too.
+ HANDLED_WANTS_KEY_UP,
+
#if defined(USE_AURA)
// The event was handled, but don't update the underlying event. A value
// HANDLED results in calling ui::Event::SetHandled(), where as this does not.
diff --git a/chromium/content/public/browser/manifest_icon_selector.h b/chromium/content/public/browser/manifest_icon_selector.h
index f95ea6aa678..e535ec07f18 100644
--- a/chromium/content/public/browser/manifest_icon_selector.h
+++ b/chromium/content/public/browser/manifest_icon_selector.h
@@ -6,7 +6,8 @@
#define CONTENT_PUBLIC_BROWSER_MANIFEST_ICON_SELECTOR_H_
#include "base/macros.h"
-#include "content/public/common/manifest.h"
+#include "content/common/content_export.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
#include "url/gurl.h"
namespace content {
@@ -26,10 +27,10 @@ class CONTENT_EXPORT ManifestIconSelector {
//
// Returns the icon url if a suitable icon is found. An empty URL otherwise.
static GURL FindBestMatchingIcon(
- const std::vector<content::Manifest::Icon>& icons,
+ const std::vector<blink::Manifest::Icon>& icons,
int ideal_icon_size_in_px,
int minimum_icon_size_in_px,
- content::Manifest::Icon::IconPurpose purpose);
+ blink::Manifest::Icon::IconPurpose purpose);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ManifestIconSelector);
diff --git a/chromium/content/public/browser/native_web_keyboard_event.h b/chromium/content/public/browser/native_web_keyboard_event.h
index 32b4a0d3e69..60fccfbc6cb 100644
--- a/chromium/content/public/browser/native_web_keyboard_event.h
+++ b/chromium/content/public/browser/native_web_keyboard_event.h
@@ -29,9 +29,6 @@ struct CONTENT_EXPORT NativeWebKeyboardEvent : public blink::WebKeyboardEvent {
NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
int modifiers,
base::TimeTicks timestamp);
- NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
- int modifiers,
- double timestampSeconds);
// Creates a native web keyboard event from a WebKeyboardEvent. The |os_event|
// member may be a synthetic event, and possibly incomplete.
@@ -46,7 +43,7 @@ struct CONTENT_EXPORT NativeWebKeyboardEvent : public blink::WebKeyboardEvent {
const base::android::JavaRef<jobject>& android_key_event,
blink::WebInputEvent::Type type,
int modifiers,
- double time_secs,
+ base::TimeTicks timestamp,
int keycode,
int scancode,
int unicode_character,
diff --git a/chromium/content/public/browser/navigation_controller.h b/chromium/content/public/browser/navigation_controller.h
index 3bd12f4efc2..3e4fe938dd9 100644
--- a/chromium/content/public/browser/navigation_controller.h
+++ b/chromium/content/public/browser/navigation_controller.h
@@ -24,6 +24,7 @@
#include "content/public/browser/site_instance.h"
#include "content/public/common/referrer.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
@@ -101,7 +102,8 @@ class NavigationController {
ui::PageTransition transition,
bool is_renderer_initiated,
const std::string& extra_headers,
- BrowserContext* browser_context);
+ BrowserContext* browser_context,
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory);
// Extra optional parameters for LoadURLWithParams.
struct CONTENT_EXPORT LoadURLParams {
@@ -199,10 +201,8 @@ class NavigationController {
// Indicates whether or not this navigation was initiated via context menu.
bool started_from_context_menu;
- // If this event was triggered by an anchor element with a download
- // attribute, |suggested_filename| will contain the (possibly empty) value
- // of that attribute.
- base::Optional<std::string> suggested_filename;
+ // Optional URLLoaderFactory to facilitate navigation to a blob URL.
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
// This value should only be set for main frame navigations. Subframe
// navigations will always get their NavigationUIData from
diff --git a/chromium/content/public/browser/navigation_handle.cc b/chromium/content/public/browser/navigation_handle.cc
index a109ce3e70f..f0770fddd3f 100644
--- a/chromium/content/public/browser/navigation_handle.cc
+++ b/chromium/content/public/browser/navigation_handle.cc
@@ -50,7 +50,6 @@ NavigationHandle::CreateNavigationHandleForTesting(
false, // started_from_context_menu
CSPDisposition::CHECK, // should_check_main_world_csp
is_form_submission, // is_form_submission
- base::nullopt, // suggested_filename
nullptr, // navigation_ui_data
method, net::HttpRequestHeaders(), resource_request_body, Referrer(),
false, // has_user_gesture
diff --git a/chromium/content/public/browser/navigation_handle.h b/chromium/content/public/browser/navigation_handle.h
index 28e3bf684ee..0ee6b89e56a 100644
--- a/chromium/content/public/browser/navigation_handle.h
+++ b/chromium/content/public/browser/navigation_handle.h
@@ -161,13 +161,10 @@ class CONTENT_EXPORT NavigationHandle {
// be net::OK.
virtual net::Error GetNetErrorCode() = 0;
- // Returns the RenderFrameHost this navigation is taking place in. This can
- // only be accessed after a response has been delivered for processing.
- //
- // If PlzNavigate is active, the RenderFrameHost returned will be the final
- // host for the navigation. If PlzNavigate is inactive, the navigation may
- // transfer to a new host up until the point that DidFinishNavigation is
- // called.
+ // Returns the RenderFrameHost this navigation is committing in. The
+ // RenderFrameHost returned will be the final host for the navigation. This
+ // can only be accessed after a response has been delivered for processing,
+ // or after the navigation fails with an error page.
virtual RenderFrameHost* GetRenderFrameHost() = 0;
// Whether the navigation happened without changing document. Examples of
@@ -262,10 +259,6 @@ class CONTENT_EXPORT NavigationHandle {
// Returns true if this navigation was initiated by a form submission.
virtual bool IsFormSubmission() = 0;
- // If this navigation was triggered by an anchor with a download attribute,
- // this returns the (possibly empty) value of that attribute.
- virtual const base::Optional<std::string>& GetSuggestedFilename() = 0;
-
// Testing methods ----------------------------------------------------------
//
// The following methods should be used exclusively for writing unit tests.
@@ -303,6 +296,7 @@ class CONTENT_EXPORT NavigationHandle {
// Simulates the network request failing.
virtual NavigationThrottle::ThrottleCheckResult CallWillFailRequestForTesting(
+ RenderFrameHost* render_frame_host,
base::Optional<net::SSLInfo> ssl_info) = 0;
// Simulates the reception of the network response.
diff --git a/chromium/content/public/browser/network_service_instance.h b/chromium/content/public/browser/network_service_instance.h
index 947fe3f570a..47e20afb942 100644
--- a/chromium/content/public/browser/network_service_instance.h
+++ b/chromium/content/public/browser/network_service_instance.h
@@ -31,8 +31,7 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkService();
CONTENT_EXPORT network::NetworkService* GetNetworkServiceImpl();
// Call |FlushForTesting()| on cached |NetworkServicePtr|. For testing only.
-// Must only be called on the UI thread. Must not be called if the network
-// service is disabled.
+// Must only be called on the UI thread.
CONTENT_EXPORT void FlushNetworkServiceInstanceForTesting();
} // namespace content
diff --git a/chromium/content/public/browser/notification_database_data.h b/chromium/content/public/browser/notification_database_data.h
index f91abcec530..8d1298f0eb1 100644
--- a/chromium/content/public/browser/notification_database_data.h
+++ b/chromium/content/public/browser/notification_database_data.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <string>
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/common/platform_notification_data.h"
#include "url/gurl.h"
@@ -17,6 +18,8 @@ namespace content {
// Stores information about a Web Notification as available in the notification
// database. Beyond the notification's own data, its id and attribution need
// to be available for users of the database as well.
+// Note: There are extra properties being stored for UKM logging purposes.
+// TODO(https://crbug.com/842622): Add the UKM that will use these properties.
struct CONTENT_EXPORT NotificationDatabaseData {
NotificationDatabaseData();
NotificationDatabaseData(const NotificationDatabaseData& other);
@@ -24,6 +27,19 @@ struct CONTENT_EXPORT NotificationDatabaseData {
NotificationDatabaseData& operator=(const NotificationDatabaseData& other);
+ // Corresponds to why a notification was closed.
+ enum class ClosedReason {
+ // The user explicitly closed the notification.
+ USER,
+
+ // The notification was closed by the developer.
+ DEVELOPER,
+
+ // The notification was found to be closed in the notification database,
+ // but why it was closed was not found.
+ UNKNOWN
+ };
+
// Id of the notification as assigned by the NotificationIdGenerator.
std::string notification_id;
@@ -35,6 +51,35 @@ struct CONTENT_EXPORT NotificationDatabaseData {
// Platform data of the notification that's being stored.
PlatformNotificationData notification_data;
+
+ // Boolean for if this current notification is replacing an existing
+ // notification.
+ bool replaced_existing_notification = false;
+
+ // Number of clicks on the notification itself, i.e. clicks on the
+ // notification that take the user to the website. This excludes action
+ // button clicks.
+ int num_clicks = 0;
+
+ // Number of action button clicks.
+ int num_action_button_clicks = 0;
+
+ // Time the notification was first requested to be shown.
+ base::Time creation_time_millis;
+
+ // Amount of time, in ms, between when the notification is shown and the
+ // first click.
+ base::TimeDelta time_until_first_click_millis;
+
+ // Amount of time, in ms, between when the notification is shown and the
+ // last click.
+ base::TimeDelta time_until_last_click_millis;
+
+ // Amount of time, in ms, between when the notification is shown and closed.
+ base::TimeDelta time_until_close_millis;
+
+ // Why the notification was closed.
+ ClosedReason closed_reason = ClosedReason::UNKNOWN;
};
} // namespace content
diff --git a/chromium/content/public/browser/notification_event_dispatcher.h b/chromium/content/public/browser/notification_event_dispatcher.h
index 66b91718bfb..2d0b88d1902 100644
--- a/chromium/content/public/browser/notification_event_dispatcher.h
+++ b/chromium/content/public/browser/notification_event_dispatcher.h
@@ -61,7 +61,8 @@ class CONTENT_EXPORT NotificationEventDispatcher {
virtual void DispatchNonPersistentClickEvent(
const std::string& notification_id) = 0;
virtual void DispatchNonPersistentCloseEvent(
- const std::string& notification_id) = 0;
+ const std::string& notification_id,
+ base::OnceClosure completed_closure) = 0;
protected:
virtual ~NotificationEventDispatcher() {}
diff --git a/chromium/content/public/browser/notification_types.h b/chromium/content/public/browser/notification_types.h
index 75826c37889..c79b6c34123 100644
--- a/chromium/content/public/browser/notification_types.h
+++ b/chromium/content/public/browser/notification_types.h
@@ -107,8 +107,8 @@ enum NotificationType {
// Indicates that a render process was closed (meaning it exited, but the
// RenderProcessHost might be reused). The source will be the corresponding
- // RenderProcessHost. The details will be a RendererClosedDetails struct.
- // This may get sent along with RENDERER_PROCESS_TERMINATED.
+ // RenderProcessHost. The details will be a ChildProcessTerminationInfo
+ // struct. This may get sent along with RENDERER_PROCESS_TERMINATED.
// DEPRECATED: Use RenderProcessHostObserver::RenderProcessExited()
NOTIFICATION_RENDERER_PROCESS_CLOSED,
@@ -119,15 +119,20 @@ enum NotificationType {
// This is sent when a RenderWidgetHost is being destroyed. The source is
// the RenderWidgetHost, the details are not used.
+ // DEPRECATED: Use RenderWidgetHostObserver::RenderWidgetHostDestroyed()
NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
- // Sent after the backing store has been updated but before the widget has
- // painted. The source is the RenderWidgetHost, the details are not used.
- NOTIFICATION_RENDER_WIDGET_HOST_DID_COMPLETE_RESIZE_OR_REPAINT,
+ // Sent after the renderer has updated visual properties on the main thread
+ // and committed the change on the compositor thread. The source is the
+ // RenderWidgetHost, the details are not used.
+ NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_VISUAL_PROPERTIES,
// Indicates a RenderWidgetHost has been hidden or restored. The source is
// the RWH whose visibility changed, the details is a bool set to true if
// the new state is "visible."
+ //
+ // DEPRECATED:
+ // Use RenderWidgetHostObserver::RenderWidgetHostVisibilityChanged()
NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
// The focused element inside a page has changed. The source is the
diff --git a/chromium/content/public/browser/overlay_window.h b/chromium/content/public/browser/overlay_window.h
index d8cf4cfec00..553fc063922 100644
--- a/chromium/content/public/browser/overlay_window.h
+++ b/chromium/content/public/browser/overlay_window.h
@@ -36,8 +36,9 @@ class OverlayWindow {
PictureInPictureWindowController* controller);
virtual bool IsActive() const = 0;
- virtual void Show() = 0;
virtual void Close() = 0;
+ virtual void Show() = 0;
+ virtual void Hide() = 0;
virtual bool IsVisible() const = 0;
virtual bool IsAlwaysOnTop() const = 0;
virtual ui::Layer* GetLayer() = 0;
@@ -45,6 +46,16 @@ class OverlayWindow {
virtual gfx::Rect GetBounds() const = 0;
virtual void UpdateVideoSize(const gfx::Size& natural_size) = 0;
+ // Retrieve the ui::Layers corresponding to the video and controls.
+ virtual ui::Layer* GetVideoLayer() = 0;
+ virtual ui::Layer* GetControlsBackgroundLayer() = 0;
+ virtual ui::Layer* GetCloseControlsLayer() = 0;
+ virtual ui::Layer* GetPlayPauseControlsLayer() = 0;
+
+ // Retrieves the bounds of the media controls.
+ virtual gfx::Rect GetCloseControlsBounds() = 0;
+ virtual gfx::Rect GetPlayPauseControlsBounds() = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(OverlayWindow);
};
diff --git a/chromium/content/public/browser/overscroll_configuration.h b/chromium/content/public/browser/overscroll_configuration.h
index 1cfca76392c..9df88576bf2 100644
--- a/chromium/content/public/browser/overscroll_configuration.h
+++ b/chromium/content/public/browser/overscroll_configuration.h
@@ -6,6 +6,7 @@
#define CONTENT_PUBLIC_BROWSER_OVERSCROLL_CONFIGURATION_H_
#include "base/macros.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
namespace content {
@@ -62,6 +63,8 @@ class CONTENT_EXPORT OverscrollConfig {
static bool TouchpadOverscrollHistoryNavigationEnabled();
+ static base::TimeDelta MaxInertialEventsBeforeOverscrollCancellation();
+
private:
friend class ScopedHistoryNavigationMode;
friend class ScopedPullToRefreshMode;
diff --git a/chromium/content/public/browser/page_navigator.h b/chromium/content/public/browser/page_navigator.h
index a7572a8b7b8..801566bf79f 100644
--- a/chromium/content/public/browser/page_navigator.h
+++ b/chromium/content/public/browser/page_navigator.h
@@ -21,6 +21,7 @@
#include "content/public/common/referrer.h"
#include "ipc/ipc_message.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
@@ -108,10 +109,8 @@ struct CONTENT_EXPORT OpenURLParams {
// Indicates whether this navigation was started via context menu.
bool started_from_context_menu;
- // If this event was triggered by an anchor element with a download
- // attribute, |suggested_filename| will contain the (possibly empty) value of
- // that attribute.
- base::Optional<std::string> suggested_filename;
+ // Optional URLLoaderFactory to facilitate navigation to a blob URL.
+ scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
// Indicates that the navigation should happen in an app window if
// possible, i.e. if an app for the URL is installed.
diff --git a/chromium/content/public/browser/payment_app_provider.h b/chromium/content/public/browser/payment_app_provider.h
index 8e13ae5638e..bde13864ff4 100644
--- a/chromium/content/public/browser/payment_app_provider.h
+++ b/chromium/content/public/browser/payment_app_provider.h
@@ -75,6 +75,17 @@ class CONTENT_EXPORT PaymentAppProvider {
virtual void SetOpenedWindow(WebContents* web_contents) = 0;
virtual void CloseOpenedWindow(BrowserContext* browser_context) = 0;
+ // Notify the opened payment handler window is closing or closed by user so as
+ // to abort payment request.
+ virtual void OnClosingOpenedWindow(BrowserContext* browser_context) = 0;
+
+ // Check whether given |sw_js_url| from |manifest_url| is allowed to register
+ // with |sw_scope|.
+ virtual bool IsValidInstallablePaymentApp(const GURL& manifest_url,
+ const GURL& sw_js_url,
+ const GURL& sw_scope,
+ std::string* error_message) = 0;
+
protected:
virtual ~PaymentAppProvider() {}
};
diff --git a/chromium/content/public/browser/picture_in_picture_window_controller.h b/chromium/content/public/browser/picture_in_picture_window_controller.h
index e5c6b2a8447..a6292fa8e29 100644
--- a/chromium/content/public/browser/picture_in_picture_window_controller.h
+++ b/chromium/content/public/browser/picture_in_picture_window_controller.h
@@ -33,14 +33,22 @@ class PictureInPictureWindowController {
virtual ~PictureInPictureWindowController() = default;
- virtual void Show() = 0;
+ // Shows the Picture-in-Picture window.
+ // Returns the size of the window in pixels.
+ virtual gfx::Size Show() = 0;
+
virtual void Close() = 0;
virtual void EmbedSurface(const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) = 0;
virtual OverlayWindow* GetWindowForTesting() = 0;
+ virtual void UpdateLayerBounds() = 0;
+ virtual bool IsPlayerActive() = 0;
+ virtual WebContents* GetInitiatorWebContents() = 0;
// Commands.
- virtual void TogglePlayPause() = 0;
+ // Returns true if the player is active (i.e. currently playing) after this
+ // call.
+ virtual bool TogglePlayPause() = 0;
protected:
// Use PictureInPictureWindowController::GetOrCreateForWebContents() to
diff --git a/chromium/content/public/browser/presentation_service_delegate.h b/chromium/content/public/browser/presentation_service_delegate.h
index 63ff87336bf..4c1b22497e1 100644
--- a/chromium/content/public/browser/presentation_service_delegate.h
+++ b/chromium/content/public/browser/presentation_service_delegate.h
@@ -14,7 +14,6 @@
#include "content/common/content_export.h"
#include "content/public/browser/media_controller.h"
#include "content/public/common/presentation_connection_message.h"
-#include "content/public/common/presentation_info.h"
#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
namespace content {
@@ -23,23 +22,25 @@ struct PresentationRequest;
class PresentationScreenAvailabilityListener;
using PresentationConnectionCallback =
- base::OnceCallback<void(const PresentationInfo&)>;
+ base::OnceCallback<void(const blink::mojom::PresentationInfo&)>;
using PresentationConnectionErrorCallback =
- base::OnceCallback<void(const PresentationError&)>;
+ base::OnceCallback<void(const blink::mojom::PresentationError&)>;
using DefaultPresentationConnectionCallback =
- base::RepeatingCallback<void(const PresentationInfo&)>;
+ base::RepeatingCallback<void(const blink::mojom::PresentationInfo&)>;
struct PresentationConnectionStateChangeInfo {
explicit PresentationConnectionStateChangeInfo(
- PresentationConnectionState state)
+ blink::mojom::PresentationConnectionState state)
: state(state),
- close_reason(PRESENTATION_CONNECTION_CLOSE_REASON_CONNECTION_ERROR) {}
+ close_reason(
+ blink::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR) {
+ }
~PresentationConnectionStateChangeInfo() = default;
- PresentationConnectionState state;
+ blink::mojom::PresentationConnectionState state;
// |close_reason| and |messsage| are only used for state change to CLOSED.
- PresentationConnectionCloseReason close_reason;
+ blink::mojom::PresentationConnectionCloseReason close_reason;
std::string message;
};
@@ -51,7 +52,7 @@ using PresentationConnectionRequest =
blink::mojom::PresentationConnectionRequest;
using ReceiverConnectionAvailableCallback =
- base::RepeatingCallback<void(const content::PresentationInfo&,
+ base::RepeatingCallback<void(blink::mojom::PresentationInfoPtr,
PresentationConnectionPtr,
PresentationConnectionRequest)>;
@@ -121,7 +122,7 @@ class CONTENT_EXPORT ControllerPresentationServiceDelegate
// Sets the default presentation URLs represented by |request|. When the
// default presentation is started on this frame, |callback| will be invoked
- // with the corresponding PresentationInfo object.
+ // with the corresponding blink::mojom::PresentationInfo object.
// If |request.presentation_urls| is empty, the default presentation URLs will
// be cleared and the previously registered callback (if any) will be removed.
virtual void SetDefaultPresentationUrls(
@@ -187,7 +188,7 @@ class CONTENT_EXPORT ControllerPresentationServiceDelegate
virtual void ListenForConnectionStateChange(
int render_process_id,
int render_frame_id,
- const PresentationInfo& connection,
+ const blink::mojom::PresentationInfo& connection,
const PresentationConnectionStateChangedCallback& state_changed_cb) = 0;
// Connect |controller_connection| owned by the controlling frame to the
@@ -200,7 +201,7 @@ class CONTENT_EXPORT ControllerPresentationServiceDelegate
virtual void ConnectToPresentation(
int render_process_id,
int render_frame_id,
- const PresentationInfo& presentation_info,
+ const blink::mojom::PresentationInfo& presentation_info,
PresentationConnectionPtr controller_connection_ptr,
PresentationConnectionRequest receiver_connection_request) = 0;
};
diff --git a/chromium/content/public/browser/provision_fetcher_factory.h b/chromium/content/public/browser/provision_fetcher_factory.h
index cd9eca15668..32313e4c222 100644
--- a/chromium/content/public/browser/provision_fetcher_factory.h
+++ b/chromium/content/public/browser/provision_fetcher_factory.h
@@ -13,8 +13,8 @@ namespace media {
class ProvisionFetcher;
}
-namespace net {
-class URLRequestContextGetter;
+namespace network {
+class SharedURLLoaderFactory;
}
namespace content {
@@ -23,7 +23,7 @@ namespace content {
CONTENT_EXPORT
std::unique_ptr<media::ProvisionFetcher> CreateProvisionFetcher(
- net::URLRequestContextGetter* context_getter);
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
} // namespace content
diff --git a/chromium/content/public/browser/provision_fetcher_impl.cc b/chromium/content/public/browser/provision_fetcher_impl.cc
index 77dab1fa220..0f5775edb2a 100644
--- a/chromium/content/public/browser/provision_fetcher_impl.cc
+++ b/chromium/content/public/browser/provision_fetcher_impl.cc
@@ -6,18 +6,19 @@
#include "content/public/browser/provision_fetcher_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace content {
// static
void ProvisionFetcherImpl::Create(
- net::URLRequestContextGetter* context_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
media::mojom::ProvisionFetcherRequest request) {
- DCHECK(context_getter);
- mojo::MakeStrongBinding(std::make_unique<ProvisionFetcherImpl>(
- CreateProvisionFetcher(context_getter)),
- std::move(request));
+ DCHECK(url_loader_factory);
+ mojo::MakeStrongBinding(
+ std::make_unique<ProvisionFetcherImpl>(
+ CreateProvisionFetcher(std::move(url_loader_factory))),
+ std::move(request));
}
ProvisionFetcherImpl::ProvisionFetcherImpl(
diff --git a/chromium/content/public/browser/provision_fetcher_impl.h b/chromium/content/public/browser/provision_fetcher_impl.h
index 5e58a293052..6b3106f901c 100644
--- a/chromium/content/public/browser/provision_fetcher_impl.h
+++ b/chromium/content/public/browser/provision_fetcher_impl.h
@@ -14,9 +14,9 @@
#include "media/base/provision_fetcher.h"
#include "media/mojo/interfaces/provision_fetcher.mojom.h"
-namespace net {
-class URLRequestContextGetter;
-}
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
namespace content {
@@ -25,8 +25,9 @@ namespace content {
class CONTENT_EXPORT ProvisionFetcherImpl
: public media::mojom::ProvisionFetcher {
public:
- static void Create(net::URLRequestContextGetter* context_getter,
- media::mojom::ProvisionFetcherRequest request);
+ static void Create(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ media::mojom::ProvisionFetcherRequest request);
explicit ProvisionFetcherImpl(
std::unique_ptr<media::ProvisionFetcher> provision_fetcher);
diff --git a/chromium/content/public/browser/render_frame_host.h b/chromium/content/public/browser/render_frame_host.h
index 4a3ea81bca5..f5dced5b834 100644
--- a/chromium/content/public/browser/render_frame_host.h
+++ b/chromium/content/public/browser/render_frame_host.h
@@ -273,15 +273,6 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// RenderFrame. See BindingsPolicy for details.
virtual int GetEnabledBindings() const = 0;
- // Causes all new requests for the root RenderFrameHost and its children to
- // be blocked (not being started) until ResumeBlockedRequestsForFrame is
- // called.
- virtual void BlockRequestsForFrame() = 0;
-
- // Resumes any blocked request for the specified root RenderFrameHost and
- // child frame hosts.
- virtual void ResumeBlockedRequestsForFrame() = 0;
-
#if defined(OS_ANDROID)
// Returns an InterfaceProvider for Java-implemented interfaces that are
// scoped to this RenderFrameHost. This provides access to interfaces
diff --git a/chromium/content/public/browser/render_frame_metadata_provider.h b/chromium/content/public/browser/render_frame_metadata_provider.h
index b64eeddbdc1..6ee7068fcdd 100644
--- a/chromium/content/public/browser/render_frame_metadata_provider.h
+++ b/chromium/content/public/browser/render_frame_metadata_provider.h
@@ -31,6 +31,13 @@ class CONTENT_EXPORT RenderFrameMetadataProvider {
virtual void OnRenderFrameMetadataChanged() = 0;
virtual void OnRenderFrameSubmission() = 0;
+
+ // Called to indicate that the viz::LocalSurfaceId within the
+ // RenderFrameMetadata has changed. Note that this is called as
+ // soon as |metadata| arrives and does not wait for the frame token
+ // to pass in Viz.
+ virtual void OnLocalSurfaceIdChanged(
+ const cc::RenderFrameMetadata& metadata) = 0;
};
RenderFrameMetadataProvider() = default;
diff --git a/chromium/content/public/browser/render_process_host.h b/chromium/content/public/browser/render_process_host.h
index 30213bbbf09..df65dddfb96 100644
--- a/chromium/content/public/browser/render_process_host.h
+++ b/chromium/content/public/browser/render_process_host.h
@@ -9,10 +9,12 @@
#include <stdint.h>
#include <list>
+#include <memory>
+#include <string>
#include "base/containers/id_map.h"
#include "base/process/kill.h"
-#include "base/process/process_handle.h"
+#include "base/process/process.h"
#include "base/supports_user_data.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
@@ -20,6 +22,7 @@
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_sender.h"
#include "media/media_buildflags.h"
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
#include "ui/gfx/native_widget_types.h"
#if defined(OS_ANDROID)
@@ -41,10 +44,6 @@ namespace resource_coordinator {
class ProcessResourceCoordinator;
}
-namespace viz {
-class SharedBitmapAllocationNotifierImpl;
-}
-
namespace content {
class BrowserContext;
class BrowserMessageFilter;
@@ -52,7 +51,6 @@ class RenderProcessHostObserver;
class RenderWidgetHost;
class RendererAudioOutputStreamFactoryContext;
class StoragePartition;
-struct GlobalRequestID;
#if defined(OS_ANDROID)
enum class ChildProcessImportance;
@@ -93,17 +91,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual ~PriorityClient() {}
};
- // Details for RENDERER_PROCESS_CLOSED notifications.
- struct RendererClosedDetails {
- RendererClosedDetails(base::TerminationStatus status,
- int exit_code) {
- this->status = status;
- this->exit_code = exit_code;
- }
- base::TerminationStatus status;
- int exit_code;
- };
-
// Crash reporting mode for ShutdownForBadMessage.
enum class CrashReportMode {
NO_CRASH_DUMP,
@@ -159,7 +146,7 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual int VisibleClientCount() const = 0;
// Get computed frame depth from PriorityClients.
- virtual unsigned int GetFrameDepthForTesting() const = 0;
+ virtual unsigned int GetFrameDepth() const = 0;
virtual RendererAudioOutputStreamFactoryContext*
GetRendererAudioOutputStreamFactoryContext() = 0;
@@ -206,7 +193,7 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// Init starts the process asynchronously. It's guaranteed to be valid after
// the first IPC arrives or RenderProcessReady was called on a
// RenderProcessHostObserver for this. At that point, IsReady() returns true.
- virtual base::ProcessHandle GetHandle() const = 0;
+ virtual const base::Process& GetProcess() const = 0;
// Returns whether the process is ready. The process is ready once both
// conditions (which can happen in arbitrary order) are true:
@@ -234,8 +221,14 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// This will never return ChildProcessHost::kInvalidUniqueID.
virtual int GetID() const = 0;
- // Returns true iff channel_ has been set to non-nullptr. Use this for
- // checking if there is connection or not. Virtual for mocking out for tests.
+ // Returns true iff the Init() was called and the process hasn't died yet.
+ //
+ // Note that even if HasConnection() returns true, then (for a short duration
+ // after calling Init()) the process might not be fully spawned *yet* - e.g.
+ // IsReady() might return false and GetProcess() might still return an invalid
+ // process with a null handle.
+ //
+ // TODO(lukasza): Rename to IsInitializedAndNotDead().
virtual bool HasConnection() const = 0;
// Returns the renderer channel.
@@ -282,7 +275,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// |empty_allowed| must be set to false for navigations for security reasons.
virtual void FilterURL(bool empty_allowed, GURL* url) = 0;
-#if BUILDFLAG(ENABLE_WEBRTC)
virtual void EnableAudioDebugRecordings(const base::FilePath& file) = 0;
virtual void DisableAudioDebugRecordings() = 0;
@@ -317,11 +309,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// Start/stop event log output from WebRTC on this RPH for the peer connection
// identified locally within the RPH using the ID |lid|.
virtual void SetWebRtcEventLogOutput(int lid, bool enabled) = 0;
-#endif
-
- // Tells the ResourceDispatcherHost to resume a deferred navigation without
- // transferring it to a new renderer process.
- virtual void ResumeDeferredNavigation(const GlobalRequestID& request_id) = 0;
// Binds interfaces exposed to the browser process from the renderer.
virtual void BindInterface(const std::string& interface_name,
@@ -351,6 +338,7 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
kServiceWorker = 0,
kSharedWorker = 1,
kFetch = 2,
+ kUnload = 3,
};
// "Keep alive ref count" represents the number of the customers of this
// render process who wish the renderer process to be alive. While the ref
@@ -373,6 +361,10 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// When a fetch request with keepalive flag
// (https://fetch.spec.whatwg.org/#request-keepalive-flag) specified is
// pending, it wishes the renderer process to be kept alive.
+ // - Unload handlers:
+ // Keeps the process alive briefly to give subframe unload handlers a
+ // chance to execute after their parent frame navigates or is detached.
+ // See https://crbug.com/852204.
virtual void IncrementKeepAliveRefCount(KeepAliveClientType) = 0;
virtual void DecrementKeepAliveRefCount(KeepAliveClientType) = 0;
@@ -428,6 +420,12 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// crbug.com/738634.
virtual bool HostHasNotBeenUsed() = 0;
+ // Binds |request| to the CacheStorageDispatcherHost instance. The binding is
+ // sent to the IO thread. This is for internal use only, and is only exposed
+ // here to support MockRenderProcessHost usage in tests.
+ virtual void BindCacheStorage(blink::mojom::CacheStorageRequest request,
+ const url::Origin& origin) = 0;
+
// Returns the current number of active views in this process. Excludes
// any RenderViewHosts that are swapped out.
size_t GetActiveViewCount();
@@ -439,12 +437,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// be posted back on the UI thread).
void PostTaskWhenProcessIsReady(base::OnceClosure task);
- // Returns the SharedBitmapAllocationNotifier associated with this process.
- // SharedBitmapAllocationNotifier manages viz::SharedBitmaps created by this
- // process and can notify observers when a new SharedBitmap is allocated.
- virtual viz::SharedBitmapAllocationNotifierImpl*
- GetSharedBitmapAllocationNotifier() = 0;
-
// Static management functions -----------------------------------------------
// Possibly start an unbound, spare RenderProcessHost. A subsequent creation
diff --git a/chromium/content/public/browser/render_process_host_observer.h b/chromium/content/public/browser/render_process_host_observer.h
index 3aeec100526..2cfd0cc25bd 100644
--- a/chromium/content/public/browser/render_process_host_observer.h
+++ b/chromium/content/public/browser/render_process_host_observer.h
@@ -12,6 +12,7 @@
namespace content {
class RenderProcessHost;
+struct ChildProcessTerminationInfo;
// An observer API implemented by classes which are interested
// in RenderProcessHost lifecycle events.
@@ -46,13 +47,8 @@ class CONTENT_EXPORT RenderProcessHostObserver {
// active renderer process for the top-level frame; for code that needs to be
// a WebContentsObserver anyway, consider whether that API might be a better
// choice.
- //
- // If |status| is TERMINATION_STATUS_LAUNCH_FAILED then |exit_code| will
- // contain a platform specific launch failure error code. Otherwise, it will
- // contain the exit code for the process.
virtual void RenderProcessExited(RenderProcessHost* host,
- base::TerminationStatus status,
- int exit_code) {}
+ const ChildProcessTerminationInfo& info) {}
// This method is invoked when the observed RenderProcessHost itself is
// destroyed. This is guaranteed to be the last call made to the observer, so
diff --git a/chromium/content/public/browser/render_widget_host.h b/chromium/content/public/browser/render_widget_host.h
index d0ea640fac2..f547b65c75b 100644
--- a/chromium/content/public/browser/render_widget_host.h
+++ b/chromium/content/public/browser/render_widget_host.h
@@ -39,6 +39,7 @@ namespace content {
struct CursorInfo;
class RenderProcessHost;
class RenderWidgetHostIterator;
+class RenderWidgetHostObserver;
class RenderWidgetHostView;
struct ScreenInfo;
@@ -76,8 +77,8 @@ struct ScreenInfo;
// the render process dies, the RenderWidgetHostView goes away and all
// references to it must become nullptr.
//
-// RenderViewHost (a RenderWidgetHost subclass) is the conduit used to
-// communicate with the RenderView and is owned by the WebContents. If the
+// RenderViewHost (an owner delegate for RenderWidgetHost) is the conduit used
+// to communicate with the RenderView and is owned by the WebContents. If the
// render process crashes, the RenderViewHost remains and restarts the render
// process if needed to continue navigation.
//
@@ -92,9 +93,9 @@ struct ScreenInfo;
// For select popups, the situation is a little different. The RenderWidgetHost
// associated with the select popup owns the view and itself (is responsible
// for destroying itself when the view is closed). The WebContents's only
-// responsibility is to select popups is to create them when it is told to. When
-// the View is destroyed via an IPC message (for when WebCore destroys the
-// popup, e.g. if the user selects one of the options), or because
+// responsibility with select popups is to create them when it is told to. When
+// the View is destroyed via an IPC message (triggered when WebCore destroys
+// the popup, e.g. if the user selects one of the options), or because
// WM_CANCELMODE is received by the view, the View schedules the destruction of
// the render process. However in this case since there's no WebContents
// container, when the render process is destroyed, the RenderWidgetHost just
@@ -207,8 +208,9 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
virtual void SetIgnoreInputEvents(bool ignore_input_events) = 0;
- // Called to notify the RenderWidget that it has been resized.
- virtual void WasResized() = 0;
+ // Called to propagate updated visual properties to the renderer. Returns
+ // whether the renderer has been informed of updated properties.
+ virtual bool SynchronizeVisualProperties() = 0;
// Access to the implementation's IPC::Listener::OnMessageReceived. Intended
// only for test code.
@@ -241,6 +243,12 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
virtual void AddInputEventObserver(InputEventObserver* observer) = 0;
virtual void RemoveInputEventObserver(InputEventObserver* observer) = 0;
+ // Add and remove observers for widget host events. The order in which
+ // notifications are sent to observers is undefined. Observers must be sure to
+ // remove the observer before they go away.
+ virtual void AddObserver(RenderWidgetHostObserver* observer) = 0;
+ virtual void RemoveObserver(RenderWidgetHostObserver* observer) = 0;
+
// Get the screen info corresponding to this render widget.
virtual void GetScreenInfo(ScreenInfo* result) = 0;
diff --git a/chromium/content/public/browser/render_widget_host_observer.h b/chromium/content/public/browser/render_widget_host_observer.h
new file mode 100644
index 00000000000..88778577aa9
--- /dev/null
+++ b/chromium/content/public/browser/render_widget_host_observer.h
@@ -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.
+
+#ifndef CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_OBSERVER_H_
+#define CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_OBSERVER_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+class RenderWidgetHost;
+
+// An observer API implemented by classes which are interested
+// in RenderWidgetHost events.
+class CONTENT_EXPORT RenderWidgetHostObserver {
+ public:
+ // This method is invoked when the visibility of the RenderWidgetHost changes.
+ virtual void RenderWidgetHostVisibilityChanged(RenderWidgetHost* widget_host,
+ bool became_visible) {}
+
+ // This method is invoked when the observed RenderWidgetHost is destroyed.
+ // This is guaranteed to be the last call made to the observer, so if the
+ // observer is tied to the observed RenderWidgetHost, it is safe to delete it.
+ virtual void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) {}
+
+ protected:
+ virtual ~RenderWidgetHostObserver() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_RENDER_PROCESS_HOST_OBSERVER_H_
diff --git a/chromium/content/public/browser/render_widget_host_view.h b/chromium/content/public/browser/render_widget_host_view.h
index 1ced1c489b4..0f2bbdcf4b2 100644
--- a/chromium/content/public/browser/render_widget_host_view.h
+++ b/chromium/content/public/browser/render_widget_host_view.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_VIEW_H_
#define CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_VIEW_H_
+#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/optional.h"
#include "base/strings/string16.h"
@@ -22,20 +23,13 @@ class Rect;
class Size;
}
-namespace mojo {
-template <class T>
-class InterfacePtr;
-}
-
namespace ui {
+enum class DomCode;
class TextInputClient;
}
namespace viz {
-namespace mojom {
-class FrameSinkVideoCapturer;
-using FrameSinkVideoCapturerPtr = mojo::InterfacePtr<FrameSinkVideoCapturer>;
-} // namespace mojom
+class ClientFrameSinkVideoCapturer;
} // namespace viz
namespace content {
@@ -157,11 +151,11 @@ class CONTENT_EXPORT RenderWidgetHostView {
// has to be either SK_ColorTRANSPARENT or opaque. If set to
// SK_ColorTRANSPARENT, the renderer's background color will be overridden to
// be fully transparent.
+ // SetBackgroundColor is called to set the default color of the view,
+ // which is shown if the background color of the renderer is not available.
virtual void SetBackgroundColor(SkColor color) = 0;
- virtual SkColor background_color() const = 0;
- // Convenience method to fill the background layer with the default color by
- // calling |SetBackgroundColor|.
- virtual void SetBackgroundColorToDefault() = 0;
+ // GetBackgroundColor returns the current background color of the view.
+ virtual base::Optional<SkColor> GetBackgroundColor() const = 0;
// Return value indicates whether the mouse is locked successfully or not.
virtual bool LockMouse() = 0;
@@ -170,11 +164,17 @@ class CONTENT_EXPORT RenderWidgetHostView {
virtual bool IsMouseLocked() = 0;
// Start/Stop intercepting future system keyboard events.
- virtual bool LockKeyboard(base::Optional<base::flat_set<int>> keys) = 0;
+ virtual bool LockKeyboard(
+ base::Optional<base::flat_set<ui::DomCode>> dom_codes) = 0;
virtual void UnlockKeyboard() = 0;
// Returns true if keyboard lock is active.
virtual bool IsKeyboardLocked() = 0;
+ // Return a mapping dictionary from keyboard code to key values for the
+ // highest-priority ASCII-capable layout in the list of currently installed
+ // keyboard layouts.
+ virtual base::flat_map<std::string, std::string> GetKeyboardLayoutMap() = 0;
+
// Retrives the size of the viewport for the visible region. May be smaller
// than the view size if a portion of the view is obstructed (e.g. by a
// virtual keyboard).
@@ -184,8 +184,7 @@ class CONTENT_EXPORT RenderWidgetHostView {
// visible viewport.
virtual void SetInsets(const gfx::Insets& insets) = 0;
- // Returns true if the current display surface is available, a prerequisite
- // for CopyFromSurface() to succeed.
+ // Returns true if the current display surface is available.
virtual bool IsSurfaceAvailableForCopy() const = 0;
// Copies the given subset of the view's surface, optionally scales it, and
@@ -214,11 +213,16 @@ class CONTENT_EXPORT RenderWidgetHostView {
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) = 0;
+ // Ensures that all surfaces are synchronized for the next call to
+ // CopyFromSurface. This is used by LayoutTests.
+ virtual void EnsureSurfaceSynchronizedForLayoutTest() = 0;
+
// Creates a video capturer, which will allow the caller to receive a stream
// of media::VideoFrames captured from this view. The capturer is configured
// to target this view, so there is no need to call ChangeTarget() before
// Start(). See viz.mojom.FrameSinkVideoCapturer for documentation.
- virtual viz::mojom::FrameSinkVideoCapturerPtr CreateVideoCapturer() = 0;
+ virtual std::unique_ptr<viz::ClientFrameSinkVideoCapturer>
+ CreateVideoCapturer() = 0;
// Notification that a node was touched.
// The |editable| parameter indicates if the node is editable, for e.g.
diff --git a/chromium/content/public/browser/resource_dispatcher_host_delegate.cc b/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
index 838ec2e1295..ac7f3cb63d2 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -12,14 +12,6 @@ namespace content {
ResourceDispatcherHostDelegate::~ResourceDispatcherHostDelegate() {}
-bool ResourceDispatcherHostDelegate::ShouldBeginRequest(
- const std::string& method,
- const GURL& url,
- ResourceType resource_type,
- ResourceContext* resource_context) {
- return true;
-}
-
void ResourceDispatcherHostDelegate::RequestBeginning(
net::URLRequest* request,
ResourceContext* resource_context,
diff --git a/chromium/content/public/browser/resource_dispatcher_host_delegate.h b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
index 8a11639fba0..f0f9b73a62c 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.h
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
@@ -37,12 +37,6 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
public:
virtual ~ResourceDispatcherHostDelegate();
- // Called when a request begins. Return false to abort the request.
- virtual bool ShouldBeginRequest(const std::string& method,
- const GURL& url,
- ResourceType resource_type,
- ResourceContext* resource_context);
-
// Called after ShouldBeginRequest to allow the embedder to add resource
// throttles.
virtual void RequestBeginning(
diff --git a/chromium/content/public/browser/resource_hints.h b/chromium/content/public/browser/resource_hints.h
index 0364cf0e627..e5b293eaa3a 100644
--- a/chromium/content/public/browser/resource_hints.h
+++ b/chromium/content/public/browser/resource_hints.h
@@ -27,13 +27,11 @@ namespace content {
// coalesce. |allow_credentials| corresponds to the fetch spec.
// Note: This should only be called on the IO thread, with a valid
// URLRequestContextGetter.
-CONTENT_EXPORT void PreconnectUrl(
- net::URLRequestContextGetter* getter,
- const GURL& url,
- const GURL& site_for_cookies,
- int count,
- bool allow_credentials,
- net::HttpRequestInfo::RequestMotivation motivation);
+CONTENT_EXPORT void PreconnectUrl(net::URLRequestContextGetter* getter,
+ const GURL& url,
+ const GURL& site_for_cookies,
+ int count,
+ bool allow_credentials);
// Issues a DNS request to |url|. Note that these requests are sent to the host
// resolver with priority net::IDLE.
diff --git a/chromium/content/public/browser/resource_request_info.h b/chromium/content/public/browser/resource_request_info.h
index 6e05dd71c37..dee1f061b99 100644
--- a/chromium/content/public/browser/resource_request_info.h
+++ b/chromium/content/public/browser/resource_request_info.h
@@ -12,6 +12,7 @@
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/resource_type.h"
+#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_referrer_policy.h"
#include "ui/base/page_transition_types.h"
@@ -183,9 +184,14 @@ class ResourceRequestInfo {
kNotCanceled,
};
- // If and why this request was canceled by DevTools.
+ // If and why this request was canceled by DevTools. TODO(johannes): Remove.
virtual DevToolsStatus GetDevToolsStatus() const = 0;
+ // For net::ERR_BLOCKED_BY_CLIENT and net::ERR_BLOCKED_BY_RESPONSE
+ // errors, this will return the reason, otherwise base::nullopt.
+ virtual base::Optional<blink::ResourceRequestBlockedReason>
+ GetResourceRequestBlockedReason() const = 0;
+
// When the client of a request decides to cancel it, it may optionally
// provide an application-defined description of the canncellation reason.
// This method returns the custom reason. If no such reason has been provided,
diff --git a/chromium/content/public/browser/screen_orientation_delegate.h b/chromium/content/public/browser/screen_orientation_delegate.h
index 6862cc4145e..aed3680b1fa 100644
--- a/chromium/content/public/browser/screen_orientation_delegate.h
+++ b/chromium/content/public/browser/screen_orientation_delegate.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
namespace content {
diff --git a/chromium/content/public/browser/service_worker_context_observer.h b/chromium/content/public/browser/service_worker_context_observer.h
index 2fc757d673e..1f1b3b8315a 100644
--- a/chromium/content/public/browser/service_worker_context_observer.h
+++ b/chromium/content/public/browser/service_worker_context_observer.h
@@ -12,7 +12,11 @@ namespace content {
class ServiceWorkerContextObserver {
public:
// Called when a service worker has been registered with scope |pattern|.
- virtual void OnRegistrationStored(const GURL& pattern) {}
+ //
+ // This is called when the ServiceWorkerContainer.register() promise is
+ // resolved, which happens before the service worker registration is persisted
+ // to disk.
+ virtual void OnRegistrationCompleted(const GURL& pattern) {}
protected:
virtual ~ServiceWorkerContextObserver() {}
diff --git a/chromium/content/public/browser/site_isolation_policy.cc b/chromium/content/public/browser/site_isolation_policy.cc
index aa1599deaae..f6736b39a3b 100644
--- a/chromium/content/public/browser/site_isolation_policy.cc
+++ b/chromium/content/public/browser/site_isolation_policy.cc
@@ -72,11 +72,6 @@ bool SiteIsolationPolicy::IsTopDocumentIsolationEnabled() {
if (UseDedicatedProcessesForAllSites())
return false;
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableSiteIsolationTrials)) {
- return false;
- }
-
// The feature needs to be checked last, because checking the feature
// activates the field trial and assigns the client either to a control or an
// experiment group - such assignment should be final.
@@ -105,7 +100,11 @@ bool SiteIsolationPolicy::AreIsolatedOriginsEnabled() {
}
// static
+bool SiteIsolationPolicy::IsErrorPageIsolationEnabled(bool in_main_frame) {
+ return GetContentClient()->browser()->ShouldIsolateErrorPage(in_main_frame);
+}
+// static
bool SiteIsolationPolicy::ShouldPdfCompositorBeEnabledForOopifs() {
// TODO(weili): We only create pdf compositor client and use pdf compositor
// service when site-per-process or isolate-origins flag/feature is enabled,
diff --git a/chromium/content/public/browser/site_isolation_policy.h b/chromium/content/public/browser/site_isolation_policy.h
index 06e13c0d98a..e0edfc6e8ee 100644
--- a/chromium/content/public/browser/site_isolation_policy.h
+++ b/chromium/content/public/browser/site_isolation_policy.h
@@ -43,6 +43,9 @@ class CONTENT_EXPORT SiteIsolationPolicy {
// Returns true if isolated origins feature is enabled.
static bool AreIsolatedOriginsEnabled();
+ // Returns true if error page isolation is enabled.
+ static bool IsErrorPageIsolationEnabled(bool in_main_frame);
+
// Returns true if the PDF compositor should be enabled to allow out-of-
// process iframes (OOPIF's) to print properly.
static bool ShouldPdfCompositorBeEnabledForOopifs();
diff --git a/chromium/content/public/browser/speech_recognition_manager.h b/chromium/content/public/browser/speech_recognition_manager.h
index 8c6040ef98c..10f82b91beb 100644
--- a/chromium/content/public/browser/speech_recognition_manager.h
+++ b/chromium/content/public/browser/speech_recognition_manager.h
@@ -65,12 +65,6 @@ class SpeechRecognitionManager {
virtual SpeechRecognitionSessionContext GetSessionContext(
int session_id) const = 0;
- // Looks up an existing session from the context tuple
- // {render_process_id, render_frame_id, request_id}.
- virtual int GetSession(int render_process_id,
- int render_frame_id,
- int request_id) const = 0;
-
protected:
virtual ~SpeechRecognitionManager() {}
diff --git a/chromium/content/public/browser/speech_recognition_session_config.h b/chromium/content/public/browser/speech_recognition_session_config.h
index d3bea186e1d..9b57ba02b31 100644
--- a/chromium/content/public/browser/speech_recognition_session_config.h
+++ b/chromium/content/public/browser/speech_recognition_session_config.h
@@ -14,8 +14,9 @@
#include "content/common/content_export.h"
#include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/browser/speech_recognition_session_preamble.h"
-#include "content/public/common/speech_recognition_grammar.h"
+#include "content/public/common/speech_recognition_grammar.mojom.h"
#include "net/url_request/url_request_context_getter.h"
+#include "url/origin.h"
namespace content {
@@ -28,8 +29,8 @@ struct CONTENT_EXPORT SpeechRecognitionSessionConfig {
~SpeechRecognitionSessionConfig();
std::string language;
- SpeechRecognitionGrammarArray grammars;
- std::string origin_url;
+ std::vector<mojom::SpeechRecognitionGrammar> grammars;
+ url::Origin origin;
bool filter_profanities;
bool continuous;
bool interim_results;
diff --git a/chromium/content/public/browser/speech_recognition_session_context.cc b/chromium/content/public/browser/speech_recognition_session_context.cc
index ebcb190fb81..fa196e3573e 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.cc
+++ b/chromium/content/public/browser/speech_recognition_session_context.cc
@@ -12,8 +12,7 @@ SpeechRecognitionSessionContext::SpeechRecognitionSessionContext()
: render_process_id(0),
render_frame_id(MSG_ROUTING_NONE),
embedder_render_process_id(0),
- embedder_render_frame_id(MSG_ROUTING_NONE),
- request_id(0) {}
+ embedder_render_frame_id(MSG_ROUTING_NONE) {}
SpeechRecognitionSessionContext::SpeechRecognitionSessionContext(
const SpeechRecognitionSessionContext& other) = default;
diff --git a/chromium/content/public/browser/speech_recognition_session_context.h b/chromium/content/public/browser/speech_recognition_session_context.h
index b0cfb8e6b3d..1575e5a8f85 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.h
+++ b/chromium/content/public/browser/speech_recognition_session_context.h
@@ -10,6 +10,7 @@
#include "content/common/content_export.h"
#include "content/public/common/media_stream_request.h"
#include "ui/gfx/geometry/rect.h"
+#include "url/origin.h"
namespace content {
@@ -34,12 +35,9 @@ struct CONTENT_EXPORT SpeechRecognitionSessionContext {
int embedder_render_process_id;
int embedder_render_frame_id;
- // The request id provided by the originating SpeechRecognitionDispatcher.
- int request_id;
-
- // A textual description of the context (website, extension name) that is
- // requesting recognition, for prompting security notifications to the user.
- std::string context_name;
+ // Origin that is requesting recognition, for prompting security notifications
+ // to the user.
+ url::Origin security_origin;
// The label for the permission request, it is used for request abortion.
std::string label;
diff --git a/chromium/content/public/browser/storage_partition.h b/chromium/content/public/browser/storage_partition.h
index ec12926fcbb..28e2c251a11 100644
--- a/chromium/content/public/browser/storage_partition.h
+++ b/chromium/content/public/browser/storage_partition.h
@@ -7,14 +7,15 @@
#include <stdint.h>
+#include <set>
#include <string>
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "net/cookies/cookie_store.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
class GURL;
@@ -75,7 +76,12 @@ class CONTENT_EXPORT StoragePartition {
virtual base::FilePath GetPath() = 0;
virtual net::URLRequestContextGetter* GetURLRequestContext() = 0;
virtual net::URLRequestContextGetter* GetMediaURLRequestContext() = 0;
+
+ // Returns a raw mojom::NetworkContext pointer. When network service crashes
+ // or restarts, the raw pointer will not be valid or safe to use. Therefore,
+ // caller should not hold onto this pointer beyond the same message loop task.
virtual network::mojom::NetworkContext* GetNetworkContext() = 0;
+
// Returns a pointer/info to a URLLoaderFactory/CookieManager owned by
// the storage partition. Prefer to use this instead of creating a new
// URLLoaderFactory when issuing requests from the Browser process, to
@@ -119,6 +125,7 @@ class CONTENT_EXPORT StoragePartition {
REMOVE_DATA_MASK_SERVICE_WORKERS = 1 << 7,
REMOVE_DATA_MASK_CACHE_STORAGE = 1 << 8,
REMOVE_DATA_MASK_PLUGIN_PRIVATE_DATA = 1 << 9,
+ REMOVE_DATA_MASK_BACKGROUND_FETCH = 1 << 10,
REMOVE_DATA_MASK_ALL = 0xFFFFFFFF,
// Corresponds to storage::kStorageTypeTemporary.
@@ -152,9 +159,6 @@ class CONTENT_EXPORT StoragePartition {
typedef base::Callback<bool(const GURL&, storage::SpecialStoragePolicy*)>
OriginMatcherFunction;
- // A callback type to check if a given cookie should be cleared.
- using CookieMatcherFunction = net::CookieStore::CookiePredicate;
-
// Similar to ClearDataForOrigin().
// Deletes all data out for the StoragePartition if |storage_origin| is empty.
// |origin_matcher| is present if special storage policy is to be handled,
@@ -176,20 +180,24 @@ class CONTENT_EXPORT StoragePartition {
// * |origin_matcher| is present if special storage policy is to be handled,
// otherwise the callback should be null (base::Callback::is_null()==true).
// The origin matcher does not apply to cookies, instead use:
- // * |cookies_matcher| is present if special cookie clearing is to be handled.
- // If the callback is null all cookies withing the time range will be
- // cleared.
+ // * |cookie_deletion_filter| identifies the cookies to delete and will be
+ // used if |remove_mask| has the REMOVE_DATA_MASK_COOKIES bit set. Note:
+ // CookieDeletionFilterPtr also contains a time interval
+ // (created_after_time/created_before_time), so when deleting cookies
+ // |begin| and |end| will be used ignoring the interval in
+ // |cookie_deletion_filter|.
// * |callback| is called when data deletion is done or at least the deletion
// is scheduled.
// Note: Make sure you know what you are doing before clearing cookies
// selectively. You don't want to break the web.
- virtual void ClearData(uint32_t remove_mask,
- uint32_t quota_storage_remove_mask,
- const OriginMatcherFunction& origin_matcher,
- const CookieMatcherFunction& cookie_matcher,
- const base::Time begin,
- const base::Time end,
- base::OnceClosure callback) = 0;
+ virtual void ClearData(
+ uint32_t remove_mask,
+ uint32_t quota_storage_remove_mask,
+ const OriginMatcherFunction& origin_matcher,
+ network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,
+ const base::Time begin,
+ const base::Time end,
+ base::OnceClosure callback) = 0;
// Clears the HTTP and media caches associated with this StoragePartition's
// request contexts. If |begin| and |end| are not null, only entries with
diff --git a/chromium/content/public/browser/trace_uploader.h b/chromium/content/public/browser/trace_uploader.h
index 9f293d4647f..cd0c7e662a9 100644
--- a/chromium/content/public/browser/trace_uploader.h
+++ b/chromium/content/public/browser/trace_uploader.h
@@ -21,10 +21,11 @@ class TraceUploader {
// This should be called when the tracing is complete.
// The bool denotes success or failure, the string is feedback
// to show in the Tracing UI.
- typedef base::Callback<void(bool, const std::string&)> UploadDoneCallback;
+ typedef base::OnceCallback<void(bool, const std::string&)> UploadDoneCallback;
// Call this to update the progress UI with the current bytes uploaded,
// as well as the total.
- typedef base::Callback<void(int64_t, int64_t)> UploadProgressCallback;
+ typedef base::RepeatingCallback<void(int64_t, int64_t)>
+ UploadProgressCallback;
virtual ~TraceUploader() {}
@@ -35,7 +36,7 @@ class TraceUploader {
UploadMode upload_mode,
std::unique_ptr<const base::DictionaryValue> metadata,
const UploadProgressCallback& progress_callback,
- const UploadDoneCallback& done_callback) = 0;
+ UploadDoneCallback done_callback) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/url_loader_request_interceptor.h b/chromium/content/public/browser/url_loader_request_interceptor.h
new file mode 100644
index 00000000000..473902d6f07
--- /dev/null
+++ b/chromium/content/public/browser/url_loader_request_interceptor.h
@@ -0,0 +1,48 @@
+// 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_PUBLIC_BROWSER_URL_LOADER_REQUEST_INTERCEPTOR_H_
+#define CONTENT_PUBLIC_BROWSER_URL_LOADER_REQUEST_INTERCEPTOR_H_
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+
+namespace network {
+struct ResourceRequest;
+}
+
+namespace content {
+
+class ResourceContext;
+
+// URLLoaderRequestInterceptor is given a chance to create a URLLoader and
+// intercept a navigation request before the request is handed off to the
+// default URLLoader, e.g. the one from the network service.
+// URLLoaderRequestInterceptor is a per-request object and kept around during
+// the lifetime of a navigation request (including multiple redirect legs).
+class URLLoaderRequestInterceptor {
+ public:
+ URLLoaderRequestInterceptor() = default;
+ virtual ~URLLoaderRequestInterceptor() = default;
+
+ using RequestHandler =
+ base::OnceCallback<void(network::mojom::URLLoaderRequest,
+ network::mojom::URLLoaderClientPtr)>;
+ using LoaderCallback = base::OnceCallback<void(RequestHandler)>;
+
+ // Asks this handler to handle this resource load request.
+ // The handler must invoke |callback| eventually with either a non-null
+ // RequestHandler indicating its willingness to handle the request, or a null
+ // RequestHandler to indicate that someone else should handle the request.
+ virtual void MaybeCreateLoader(
+ const network::ResourceRequest& resource_request,
+ ResourceContext* resource_context,
+ LoaderCallback callback) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_URL_LOADER_REQUEST_INTERCEPTOR_H_
diff --git a/chromium/content/public/browser/web_contents.cc b/chromium/content/public/browser/web_contents.cc
index 53d56abb35a..df508da0aef 100644
--- a/chromium/content/public/browser/web_contents.cc
+++ b/chromium/content/public/browser/web_contents.cc
@@ -29,7 +29,7 @@ WebContents::CreateParams::CreateParams(BrowserContext* context,
guest_delegate(nullptr),
context(nullptr),
renderer_initiated_creation(false),
- initialize_renderer(false),
+ desired_renderer_state(kOkayToHaveRendererProcess),
starting_sandbox_flags(blink::WebSandboxFlags::kNone) {}
WebContents::CreateParams::CreateParams(const CreateParams& other) = default;
diff --git a/chromium/content/public/browser/web_contents.h b/chromium/content/public/browser/web_contents.h
index 423362cb245..dee5814a247 100644
--- a/chromium/content/public/browser/web_contents.h
+++ b/chromium/content/public/browser/web_contents.h
@@ -41,6 +41,10 @@
#include "base/android/scoped_java_ref.h"
#endif
+namespace blink {
+struct Manifest;
+}
+
namespace base {
class TimeTicks;
}
@@ -75,7 +79,6 @@ class RenderWidgetHostView;
class WebContentsDelegate;
struct CustomContextMenuContext;
struct DropData;
-struct Manifest;
struct MHTMLGenerationParams;
struct PageImportanceSignals;
struct RendererPreferences;
@@ -165,20 +168,58 @@ class WebContents : public PageNavigator,
// WebContents construction should take this into account.
bool renderer_initiated_creation;
- // True if the WebContents should create its renderer process and main
- // RenderFrame before the first navigation. This is useful to reduce
- // the latency of the first navigation in cases where it might
- // not happen right away.
+ // Used to specify how far WebContents::Create can initialize a renderer
+ // process.
+ //
+ // This is useful in two scenarios:
+ // - Conserving resources - e.g. tab discarding and session restore do not
+ // want to use an actual renderer process before the WebContents are
+ // loaded or reloaded. This can be accomplished via kNoRendererProcess.
+ // - Avoiding the latency of the first navigation
+ // - kInitializeAndWarmupRendererProcess is most aggressive in avoiding
+ // the latency, but may be incompatible with scenarios that require
+ // manipulating the freshly created WebContents prior to initializing
+ // renderer-side objects (e.g. in scenarios like
+ // WebContentsImpl::CreateNewWindow which needs to copy the
+ // SessionStorageNamespace)
+ // - kOkayToHaveRendererProcess is the default latency-conserving mode.
+ // In this mode a spare, pre-spawned RenderProcessHost may be claimed
+ // by the newly created WebContents, but no renderer-side objects will
+ // be initialized from within WebContents::Create method.
+ //
// Note that the pre-created renderer process may not be used if the first
// navigation requires a dedicated or privileged process, such as a WebUI.
- bool initialize_renderer;
+ // This can be avoided by ensuring that |site_instance| matches the first
+ // navigation's destination.
+ enum RendererInitializationState {
+ // Creation of WebContents should not spawn a new OS process and should
+ // not reuse a RenderProcessHost that might be associated with an existing
+ // OS process (as in the case of SpareRenderProcessHostManager).
+ kNoRendererProcess,
+
+ // Created WebContents may or may not be associated with an actual OS
+ // process.
+ kOkayToHaveRendererProcess,
+
+ // Ensures that the created WebContents are backed by an OS process which
+ // has an initialized RenderView.
+ //
+ // TODO(lukasza): https://crbug.com/848366: Remove
+ // kInitializeAndWarmupRendererProcess value - warming up the renderer by
+ // initializing the RenderView is redundant with the warm-up that can be
+ // achieved by either 1) warming up the spare renderer before creating
+ // WebContents and/or 2) speculative RenderFrameHost used internally
+ // during a navigation.
+ kInitializeAndWarmupRendererProcess,
+ } desired_renderer_state;
// Sandboxing flags set on the new WebContents.
blink::WebSandboxFlags starting_sandbox_flags;
};
// Creates a new WebContents.
- CONTENT_EXPORT static WebContents* Create(const CreateParams& params);
+ CONTENT_EXPORT static std::unique_ptr<WebContents> Create(
+ const CreateParams& params);
// Similar to Create() above but should be used when you need to prepopulate
// the SessionStorageNamespaceMap of the WebContents. This can happen if
@@ -190,7 +231,7 @@ class WebContents : public PageNavigator,
// understand when SessionStorageNamespace objects should be cloned, why
// they should not be shared by multiple WebContents, and what bad things
// can happen if you share the object.
- CONTENT_EXPORT static WebContents* CreateWithSessionStorage(
+ CONTENT_EXPORT static std::unique_ptr<WebContents> CreateWithSessionStorage(
const CreateParams& params,
const SessionStorageNamespaceMap& session_storage_namespace_map);
@@ -418,6 +459,9 @@ class WebContents : public PageNavigator,
// Device.
virtual bool IsConnectedToBluetoothDevice() const = 0;
+ // Indicates whether a video is in Picture-in-Picture for |this|.
+ virtual bool HasPictureInPictureVideo() const = 0;
+
// Indicates whether this tab should be considered crashed. The setter will
// also notify the delegate when the flag is changed.
virtual bool IsCrashed() const = 0;
@@ -460,11 +504,8 @@ class WebContents : public PageNavigator,
// returns false.
virtual bool NeedToFireBeforeUnload() = 0;
- // Runs the beforeunload handler for the main frame. See also ClosePage and
- // SwapOut in RenderViewHost, which run the unload handler.
- //
- // TODO(creis): We should run the beforeunload handler for every frame that
- // has one.
+ // Runs the beforeunload handler for the main frame and all its subframes.
+ // See also ClosePage in RenderViewHostImpl, which runs the unload handler.
virtual void DispatchBeforeUnload() = 0;
// Attaches this inner WebContents to its container frame
@@ -494,7 +535,7 @@ class WebContents : public PageNavigator,
// Creates a new WebContents with the same state as this one. The returned
// heap-allocated pointer is owned by the caller.
- virtual WebContents* Clone() = 0;
+ virtual std::unique_ptr<WebContents> Clone() = 0;
// Reloads the focused frame.
virtual void ReloadFocusedFrame(bool bypass_cache) = 0;
@@ -770,7 +811,7 @@ class WebContents : public PageNavigator,
// frame document's manifest. The url will be empty if the document specifies
// no manifest, and the manifest will be empty if any other failures occurred.
using GetManifestCallback =
- base::OnceCallback<void(const GURL&, const Manifest&)>;
+ base::OnceCallback<void(const GURL&, const blink::Manifest&)>;
// Requests the manifest URL and the Manifest of the main frame's document.
virtual void GetManifest(GetManifestCallback callback) = 0;
@@ -863,6 +904,13 @@ class WebContents : public PageNavigator,
virtual bool CompletedFirstVisuallyNonEmptyPaint() const = 0;
#endif // OS_ANDROID
+ // TODO(https://crbug.com/826293): This is a simple mitigation to validate
+ // that an action that requires a user gesture actually has one in the
+ // trustworthy browser process, rather than relying on the untrustworthy
+ // renderer. This should be eventually merged into and accounted for in the
+ // user activation work.
+ virtual bool HasRecentInteractiveInputEvent() const = 0;
+
private:
// This interface should only be implemented inside content.
friend class WebContentsImpl;
diff --git a/chromium/content/public/browser/web_contents_delegate.cc b/chromium/content/public/browser/web_contents_delegate.cc
index a30f195a3a0..b6c6478c858 100644
--- a/chromium/content/public/browser/web_contents_delegate.cc
+++ b/chromium/content/public/browser/web_contents_delegate.cc
@@ -269,9 +269,10 @@ bool WebContentsDelegate::DoBrowserControlsShrinkBlinkSize() const {
return false;
}
-void WebContentsDelegate::UpdatePictureInPictureSurfaceId(
- const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size) {}
+gfx::Size WebContentsDelegate::EnterPictureInPicture(const viz::SurfaceId&,
+ const gfx::Size&) {
+ return gfx::Size();
+}
void WebContentsDelegate::ExitPictureInPicture() {}
diff --git a/chromium/content/public/browser/web_contents_delegate.h b/chromium/content/public/browser/web_contents_delegate.h
index 28cf408db3b..4fc457c9e41 100644
--- a/chromium/content/public/browser/web_contents_delegate.h
+++ b/chromium/content/public/browser/web_contents_delegate.h
@@ -18,13 +18,15 @@
#include "content/common/content_export.h"
#include "content/public/browser/bluetooth_chooser.h"
#include "content/public/browser/invalidate_type.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/common/media_stream_request.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/window_container_type.mojom.h"
+#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "third_party/blink/public/mojom/color_chooser/color_chooser.mojom.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "third_party/blink/public/platform/web_security_style.h"
+#include "third_party/blink/public/web/web_fullscreen_options.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -48,7 +50,6 @@ class RenderProcessHost;
class RenderWidgetHost;
class SessionStorageNamespace;
class SiteInstance;
-class WebContents;
class WebContentsImpl;
struct ContextMenuParams;
struct DropData;
@@ -121,7 +122,7 @@ class CONTENT_EXPORT WebContentsDelegate {
// |*was_blocked| will be set to true if the popup gets blocked, and left
// unchanged otherwise.
virtual void AddNewContents(WebContents* source,
- WebContents* new_contents,
+ std::unique_ptr<WebContents> new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture,
@@ -384,8 +385,10 @@ class CONTENT_EXPORT WebContentsDelegate {
// |origin| is the origin of the initiating frame inside the |web_contents|.
// |origin| can be empty in which case the |web_contents| last committed
// URL's origin should be used.
- virtual void EnterFullscreenModeForTab(WebContents* web_contents,
- const GURL& origin) {}
+ virtual void EnterFullscreenModeForTab(
+ WebContents* web_contents,
+ const GURL& origin,
+ const blink::WebFullscreenOptions& options) {}
// Called when the renderer puts a tab out of fullscreen mode.
virtual void ExitFullscreenModeForTab(WebContents*) {}
@@ -534,9 +537,6 @@ class CONTENT_EXPORT WebContentsDelegate {
// Requests the app banner. This method is called from the DevTools.
virtual void RequestAppBannerFromDevTools(content::WebContents* web_contents);
- // Called when an audio change occurs.
- virtual void OnAudioStateChanged(WebContents* web_contents, bool audible) {}
-
// Called when a suspicious navigation of the main frame has been blocked.
// Allows the delegate to provide some UI to let the user know about the
// blocked navigation and give them the option to recover from it. The given
@@ -580,10 +580,11 @@ class CONTENT_EXPORT WebContentsDelegate {
RenderFrameHost* subframe_host) const {
}
- // Updates the Picture-in-Picture controller with the relevant viz::SurfaceId
- // and natural size of the video to be in Picture-in-Picture mode.
- virtual void UpdatePictureInPictureSurfaceId(const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size);
+ // Notifies the Picture-in-Picture controller that there is a new player
+ // entering Picture-in-Picture.
+ // Returns the size of the Picture-in-Picture window.
+ virtual gfx::Size EnterPictureInPicture(const viz::SurfaceId&,
+ const gfx::Size& natural_size);
// Updates the Picture-in-Picture controller with a signal that
// Picture-in-Picture mode has ended.
diff --git a/chromium/content/public/browser/web_contents_observer.h b/chromium/content/public/browser/web_contents_observer.h
index a0acf0a102d..9a875c6bb40 100644
--- a/chromium/content/public/browser/web_contents_observer.h
+++ b/chromium/content/public/browser/web_contents_observer.h
@@ -256,9 +256,10 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
const std::string& mime_type,
ResourceType resource_type) {}
- // This method is invoked when a resource has been loaded, successfully or
- // not.
+ // This method is invoked when a resource associate with the frame
+ // |render_frame_host| has been loaded, successfully or not.
virtual void ResourceLoadComplete(
+ RenderFrameHost* render_frame_host,
const mojom::ResourceLoadInfo& resource_load_info) {}
// This method is invoked when a new non-pending navigation entry is created.
@@ -387,6 +388,9 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener {
// process.
virtual void DidUpdateFaviconURL(const std::vector<FaviconURL>& candidates) {}
+ // Called when an audio change occurs.
+ virtual void OnAudioStateChanged(bool audible) {}
+
// Invoked when the WebContents is muted/unmuted.
virtual void DidUpdateAudioMutingState(bool muted) {}
diff --git a/chromium/content/public/browser/web_ui_message_handler.h b/chromium/content/public/browser/web_ui_message_handler.h
index 966992cb648..0ce6334e74b 100644
--- a/chromium/content/public/browser/web_ui_message_handler.h
+++ b/chromium/content/public/browser/web_ui_message_handler.h
@@ -15,6 +15,7 @@
#include "content/public/browser/web_ui.h"
class WebUIBrowserTest;
+class MojoWebUIBrowserTest;
namespace base {
class ListValue;
@@ -137,6 +138,7 @@ class CONTENT_EXPORT WebUIMessageHandler {
// RenderViewReused.
friend class WebUIImpl;
friend class ::WebUIBrowserTest;
+ friend class ::MojoWebUIBrowserTest;
// TODO(dbeam): disallow JavaScript when a renderer process crashes.
// http://crbug.com/610450
diff --git a/chromium/content/public/browser/webrtc_log.h b/chromium/content/public/browser/webrtc_log.h
index 0cc7ab8cc05..449cacbe504 100644
--- a/chromium/content/public/browser/webrtc_log.h
+++ b/chromium/content/public/browser/webrtc_log.h
@@ -12,10 +12,6 @@
#include "content/common/content_export.h"
#include "media/media_buildflags.h"
-#if !BUILDFLAG(ENABLE_WEBRTC)
-#error "WebRTC not enabled."
-#endif
-
namespace content {
class CONTENT_EXPORT WebRtcLog {
diff --git a/chromium/content/public/browser/zygote_host_linux.h b/chromium/content/public/browser/zygote_host_linux.h
deleted file mode 100644
index 537d6d3f763..00000000000
--- a/chromium/content/public/browser/zygote_host_linux.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_BROWSER_ZYGOTE_HOST_LINUX_H_
-#define CONTENT_PUBLIC_BROWSER_ZYGOTE_HOST_LINUX_H_
-
-#include <unistd.h>
-
-#include "base/process/process.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
-
-// The zygote host is an interface, in the browser process, to the zygote
-// process.
-class ZygoteHost {
- public:
- // Returns the singleton instance.
- CONTENT_EXPORT static ZygoteHost* GetInstance();
-
- virtual ~ZygoteHost() {}
-
- // Returns the pid of the Zygote process.
- virtual bool IsZygotePid(pid_t pid) = 0;
-
- // Returns an int which is a bitmask of kSandboxLinux* values. Only valid
- // after the first render has been forked.
- virtual int GetRendererSandboxStatus() const = 0;
-
- // Adjust the OOM score of the given renderer's PID. The allowed
- // range for the score is [0, 1000], where higher values are more
- // likely to be killed by the OOM killer.
- virtual void AdjustRendererOOMScore(base::ProcessHandle process_handle,
- int score) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_ZYGOTE_HOST_LINUX_H_
diff --git a/chromium/content/public/common/BUILD.gn b/chromium/content/public/common/BUILD.gn
index 67588799001..f134458dd61 100644
--- a/chromium/content/public/common/BUILD.gn
+++ b/chromium/content/public/common/BUILD.gn
@@ -7,7 +7,6 @@ import("//build/config/chromecast_build.gni")
import("//build/config/features.gni")
import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
-import("//content/public/common/zygote_features.gni")
import("//media/media_options.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//ppapi/buildflags/buildflags.gni")
@@ -32,6 +31,10 @@ source_set("result_codes") {
sources = [
"result_codes.h",
]
+
+ deps = [
+ "//services/service_manager/embedder:embedder_result_codes",
+ ]
}
# This target allows other targets to depend on content_descriptors.h which is
@@ -70,12 +73,10 @@ config("static_switches_defines") {
source_set("static_switches") {
public = [
"content_switches.h",
- "mojo_channel_switches.h",
]
sources = [
"//content/common/content_export.h",
"content_switches.cc",
- "mojo_channel_switches.cc",
]
public_configs = [ ":static_switches_defines" ]
@@ -156,10 +157,6 @@ jumbo_source_set("common_sources") {
"isolated_world_ids.h",
"javascript_dialog_type.h",
"main_function_params.h",
- "manifest.cc",
- "manifest.h",
- "manifest_share_target_util.cc",
- "manifest_share_target_util.h",
"manifest_util.cc",
"manifest_util.h",
"media_metadata.cc",
@@ -170,14 +167,10 @@ jumbo_source_set("common_sources") {
"menu_item.h",
"mhtml_generation_params.cc",
"mhtml_generation_params.h",
- "mojo_channel_switches.cc",
- "mojo_channel_switches.h",
"network_connection_tracker.cc",
"network_connection_tracker.h",
"notification_resources.cc",
"notification_resources.h",
- "origin_trial_policy.cc",
- "origin_trial_policy.h",
"origin_util.h",
"page_importance_signals.h",
"page_state.cc",
@@ -191,8 +184,6 @@ jumbo_source_set("common_sources") {
"platform_notification_data.h",
"presentation_connection_message.cc",
"presentation_connection_message.h",
- "presentation_info.cc",
- "presentation_info.h",
"previews_state.h",
"process_type.h",
"push_event_payload.h",
@@ -215,13 +206,11 @@ jumbo_source_set("common_sources") {
"screen_info.cc",
"screen_info.h",
"screen_orientation_values.h",
- "send_zygote_child_ping_linux.h",
"service_manager_connection.h",
"simple_connection_filter.cc",
"simple_connection_filter.h",
"socket_permission_request.h",
"speech_recognition_error.h",
- "speech_recognition_grammar.h",
"speech_recognition_result.cc",
"speech_recognition_result.h",
"stop_find_action.h",
@@ -237,14 +226,13 @@ jumbo_source_set("common_sources") {
"use_zoom_for_dsf_policy.cc",
"use_zoom_for_dsf_policy.h",
"user_agent.h",
- "weak_wrapper_shared_url_loader_factory.cc",
- "weak_wrapper_shared_url_loader_factory.h",
"web_preferences.cc",
"web_preferences.h",
"webplugininfo.cc",
"webplugininfo.h",
"webplugininfo_param_traits.h",
- "zygote_fork_delegate_linux.h",
+ "webrtc_ip_handling_policy.cc",
+ "webrtc_ip_handling_policy.h",
]
configs += [
@@ -257,7 +245,6 @@ jumbo_source_set("common_sources") {
public_deps = [
":interfaces",
":service_names",
- ":zygote_buildflags",
"//content/common",
"//ipc",
"//media/capture:capture_base",
@@ -282,11 +269,12 @@ jumbo_source_set("common_sources") {
# needed because of allow_circular_includes_from.
"//content/common:mojo_bindings",
"//media",
- "//mojo/common",
"//ppapi/buildflags",
"//ppapi/c",
"//services/network/public/cpp",
+ "//services/service_manager/embedder:embedder_result_codes",
"//services/service_manager/public/cpp",
+ "//services/service_manager/zygote:zygote_buildflags",
"//skia",
"//storage/common",
"//third_party/blink/public/common",
@@ -308,6 +296,10 @@ jumbo_source_set("common_sources") {
deps += [ "//content/public/android:jni" ]
}
+ if (is_linux) {
+ deps += [ "//services/service_manager/zygote" ]
+ }
+
# //content/common needs to include public headers.
allow_circular_includes_from = [
":interfaces",
@@ -321,17 +313,6 @@ jumbo_source_set("common_sources") {
"pepper_plugin_info.h",
]
}
-
- if (enable_webrtc) {
- sources += [
- "webrtc_ip_handling_policy.cc",
- "webrtc_ip_handling_policy.h",
- ]
- }
-
- if (use_zygote_handle) {
- sources += [ "zygote_handle.h" ]
- }
}
buildflag_header("buildflags") {
@@ -351,11 +332,6 @@ source_set("feature_h264_with_openh264_ffmpeg") {
]
}
-buildflag_header("zygote_buildflags") {
- header = "zygote_buildflags.h"
- flags = [ "USE_ZYGOTE_HANDLE=$use_zygote_handle" ]
-}
-
mojom("interfaces") {
# Must depend on //content/public/common/ instead, for component build.
visibility = [
@@ -375,9 +351,13 @@ mojom("interfaces") {
sources = [
"appcache_info.mojom",
"fullscreen_video_element.mojom",
+ "load_timing_info.mojom",
"push_messaging_status.mojom",
"resource_load_info.mojom",
"resource_usage_reporter.mojom",
+ "speech_recognition_error.mojom",
+ "speech_recognition_grammar.mojom",
+ "speech_recognition_result.mojom",
"transferrable_url_loader.mojom",
"webplugininfo.mojom",
"window_container_type.mojom",
@@ -389,7 +369,6 @@ mojom("interfaces") {
public_deps = [
":resource_type_bindings",
- "//mojo/common:common_custom_types",
"//services/network/public/mojom",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
diff --git a/chromium/content/public/common/browser_side_navigation_policy.cc b/chromium/content/public/common/browser_side_navigation_policy.cc
index c71206145eb..726289ea83e 100644
--- a/chromium/content/public/common/browser_side_navigation_policy.cc
+++ b/chromium/content/public/common/browser_side_navigation_policy.cc
@@ -15,19 +15,8 @@ bool IsBrowserSideNavigationEnabled() {
return true;
}
-// Browser side navigation (aka PlzNavigate) is using blob URLs to deliver
-// the body of the main resource to the renderer process. When enabled, the
-// NavigationMojoResponse feature replaces this mechanism by a Mojo DataPipe.
-// Design doc: https://goo.gl/Rrrc7n.
-bool IsNavigationMojoResponseEnabled() {
- if (!IsBrowserSideNavigationEnabled())
- return false;
-
- return base::FeatureList::IsEnabled(features::kNavigationMojoResponse) ||
- base::FeatureList::IsEnabled(
- features::kServiceWorkerServicification) ||
- base::FeatureList::IsEnabled(features::kSignedHTTPExchange) ||
- base::FeatureList::IsEnabled(network::features::kNetworkService);
+bool IsPerNavigationMojoInterfaceEnabled() {
+ return base::FeatureList::IsEnabled(features::kPerNavigationMojoInterface);
}
} // namespace content
diff --git a/chromium/content/public/common/browser_side_navigation_policy.h b/chromium/content/public/common/browser_side_navigation_policy.h
index 8a2524a284e..d5887a160cd 100644
--- a/chromium/content/public/common/browser_side_navigation_policy.h
+++ b/chromium/content/public/common/browser_side_navigation_policy.h
@@ -13,7 +13,7 @@
namespace content {
CONTENT_EXPORT bool IsBrowserSideNavigationEnabled();
-CONTENT_EXPORT bool IsNavigationMojoResponseEnabled();
+CONTENT_EXPORT bool IsPerNavigationMojoInterfaceEnabled();
} // namespace content
diff --git a/chromium/content/public/common/cdm_info.h b/chromium/content/public/common/cdm_info.h
index e6305bfd8a9..c3c2898a714 100644
--- a/chromium/content/public/common/cdm_info.h
+++ b/chromium/content/public/common/cdm_info.h
@@ -8,24 +8,30 @@
#include <string>
#include <vector>
+#include "base/containers/flat_set.h"
#include "base/files/file_path.h"
#include "base/version.h"
#include "content/common/content_export.h"
+// TODO(crbug.com/825041): Move EncryptionMode out of decrypt_config and
+// rename it to EncryptionScheme.
+#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h"
namespace content {
// Represents a Content Decryption Module implementation and its capabilities.
struct CONTENT_EXPORT CdmInfo {
- CdmInfo(const std::string& name,
- const std::string& guid,
- const base::Version& version,
- const base::FilePath& path,
- const std::string& file_system_id,
- const std::vector<media::VideoCodec>& supported_video_codecs,
- bool supports_persistent_license,
- const std::string& supported_key_system,
- bool supports_sub_key_systems);
+ CdmInfo(
+ const std::string& name,
+ const std::string& guid,
+ const base::Version& version,
+ const base::FilePath& path,
+ const std::string& file_system_id,
+ const std::vector<media::VideoCodec>& supported_video_codecs,
+ bool supports_persistent_license,
+ const base::flat_set<media::EncryptionMode>& supported_encryption_schemes,
+ const std::string& supported_key_system,
+ bool supports_sub_key_systems);
CdmInfo(const CdmInfo& other);
~CdmInfo();
@@ -57,6 +63,10 @@ struct CONTENT_EXPORT CdmInfo {
// Whether this CDM supports persistent licenses.
bool supports_persistent_license;
+ // List of encryption schemes supported by the CDM (e.g. cenc). This is the
+ // set of encryption schemes that the CDM supports.
+ base::flat_set<media::EncryptionMode> supported_encryption_schemes;
+
// The key system supported by this CDM.
std::string supported_key_system;
@@ -64,7 +74,7 @@ struct CONTENT_EXPORT CdmInfo {
// A sub key system to a key system is like a sub domain to a domain.
// For example, com.example.somekeysystem.a and com.example.somekeysystem.b
// are both sub key systems of com.example.somekeysystem.
- bool supports_sub_key_systems = false;
+ bool supports_sub_key_systems;
};
} // namespace content
diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h
index 3b72878d946..e3c46fdf48c 100644
--- a/chromium/content/public/common/common_param_traits_macros.h
+++ b/chromium/content/public/common/common_param_traits_macros.h
@@ -9,13 +9,14 @@
#define CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
#include "build/build_config.h"
+#include "cc/input/touch_action.h"
#include "content/public/common/console_message_level.h"
#include "content/public/common/referrer.h"
#include "content/public/common/web_preferences.h"
#include "content/public/common/webplugininfo_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/network_change_notifier.h"
-#include "services/network/public/cpp/network_param_ipc_traits.h"
+#include "services/network/public/cpp/network_ipc_param_traits.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "third_party/blink/public/platform/web_history_scroll_restoration_type.h"
#include "third_party/blink/public/platform/web_point.h"
@@ -55,6 +56,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebHistoryScrollRestorationType,
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebSecurityStyle, blink::kWebSecurityStyleLast)
IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::PermissionStatus,
blink::mojom::PermissionStatus::LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(cc::TouchAction, cc::kTouchActionMax)
IPC_ENUM_TRAITS_MAX_VALUE(content::EditingBehavior,
content::EDITING_BEHAVIOR_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(WindowOpenDisposition,
@@ -125,6 +127,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(xss_auditor_enabled)
IPC_STRUCT_TRAITS_MEMBER(dns_prefetching_enabled)
IPC_STRUCT_TRAITS_MEMBER(data_saver_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(data_saver_holdback_web_api_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(data_saver_holdback_media_api_enabled)
IPC_STRUCT_TRAITS_MEMBER(local_storage_enabled)
IPC_STRUCT_TRAITS_MEMBER(databases_enabled)
IPC_STRUCT_TRAITS_MEMBER(application_cache_enabled)
diff --git a/chromium/content/public/common/common_sandbox_support_linux.h b/chromium/content/public/common/common_sandbox_support_linux.h
index dc63dd29deb..e9e8b5e1df5 100644
--- a/chromium/content/public/common/common_sandbox_support_linux.h
+++ b/chromium/content/public/common/common_sandbox_support_linux.h
@@ -29,20 +29,6 @@ CONTENT_EXPORT bool GetFontTable(int fd,
uint8_t* output,
size_t* output_length);
-// Returns a file descriptor for a shared memory segment. The
-// executable flag indicates that the caller intends to use mprotect
-// with PROT_EXEC after making a mapping, but not that it intends to
-// mmap with PROT_EXEC in the first place. (Some systems, such as
-// ChromeOS, disallow PROT_EXEC in mmap on /dev/shm files but do allow
-// PROT_EXEC in mprotect on mappings from such files. This function
-// can yield an object that has that constraint.)
-CONTENT_EXPORT int MakeSharedMemorySegmentViaIPC(size_t length,
- bool executable);
-
-// Gets the well-known file descriptor on which we expect to find the
-// sandbox IPC channel.
-CONTENT_EXPORT int GetSandboxFD();
-
-}; // namespace content
+} // namespace content
#endif // CONTENT_PUBLIC_COMMON_COMMON_SANDBOX_SUPPORT_LINUX_H_
diff --git a/chromium/content/public/common/content_client.cc b/chromium/content/public/common/content_client.cc
index a2a5a3318c7..24932438c9f 100644
--- a/chromium/content/public/common/content_client.cc
+++ b/chromium/content/public/common/content_client.cc
@@ -102,7 +102,7 @@ std::string ContentClient::GetProcessTypeNameInEnglish(int type) {
return std::string();
}
-OriginTrialPolicy* ContentClient::GetOriginTrialPolicy() {
+blink::OriginTrialPolicy* ContentClient::GetOriginTrialPolicy() {
return nullptr;
}
diff --git a/chromium/content/public/common/content_client.h b/chromium/content/public/common/content_client.h
index ea3c1ef6bb6..528fd6abf6a 100644
--- a/chromium/content/public/common/content_client.h
+++ b/chromium/content/public/common/content_client.h
@@ -22,6 +22,10 @@ namespace base {
class RefCountedMemory;
}
+namespace blink {
+class OriginTrialPolicy;
+}
+
namespace IPC {
class Message;
}
@@ -46,7 +50,6 @@ class ContentClient;
class ContentGpuClient;
class ContentRendererClient;
class ContentUtilityClient;
-class OriginTrialPolicy;
class ServiceManagerConnection;
struct CdmInfo;
struct PepperPluginInfo;
@@ -129,7 +132,9 @@ class CONTENT_EXPORT ContentClient {
std::vector<std::string> csp_bypassing_schemes;
// See https://www.w3.org/TR/powerful-features/#is-origin-trustworthy.
std::vector<std::string> secure_schemes;
- std::vector<url::Origin> secure_origins;
+ // Registers a serialized origin or a hostname pattern that should be
+ // considered trustworthy.
+ std::vector<std::string> secure_origins;
// Registers a URL scheme as strictly empty documents, allowing them to
// commit synchronously.
std::vector<std::string> empty_document_schemes;
@@ -146,6 +151,7 @@ class CONTENT_EXPORT ContentClient {
virtual std::string GetProduct() const;
// Returns the user agent. Content may cache this value.
+ // TODO(yhirano): Move this to ContentBrowserClient.
virtual std::string GetUserAgent() const;
// Returns a string resource given its id.
@@ -173,7 +179,7 @@ class CONTENT_EXPORT ContentClient {
// Returns the origin trial policy, or nullptr if origin trials are not
// supported by the embedder.
- virtual OriginTrialPolicy* GetOriginTrialPolicy();
+ virtual blink::OriginTrialPolicy* GetOriginTrialPolicy();
#if defined(OS_ANDROID)
// Returns true for clients like Android WebView that uses synchronous
diff --git a/chromium/content/public/common/content_descriptors.h b/chromium/content/public/common/content_descriptors.h
index 35bf7abd24a..bccbe890411 100644
--- a/chromium/content/public/common/content_descriptors.h
+++ b/chromium/content/public/common/content_descriptors.h
@@ -7,16 +7,13 @@
#include "build/build_config.h"
+#include "services/service_manager/embedder/descriptors.h"
+
// This is a list of global descriptor keys to be used with the
// base::GlobalDescriptors object (see base/posix/global_descriptors.h)
enum {
- kCrashDumpSignal = 0,
- kSandboxIPCChannel, // https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
- kMojoIPCChannel,
- kFieldTrialDescriptor,
-
#if defined(OS_ANDROID)
- kAndroidPropertyDescriptor,
+ kAndroidPropertyDescriptor = service_manager::kFirstEmbedderDescriptor,
kAndroidICUDataDescriptor,
#endif
diff --git a/chromium/content/public/common/content_features.cc b/chromium/content/public/common/content_features.cc
index 50c3617648a..10d9366af33 100644
--- a/chromium/content/public/common/content_features.cc
+++ b/chromium/content/public/common/content_features.cc
@@ -21,10 +21,6 @@ const base::Feature kAllowContentInitiatedDataUrlNavigations{
"AllowContentInitiatedDataUrlNavigations",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables Array.prototype.values method
-const base::Feature kArrayPrototypeValues{"ArrayPrototypeValues",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables asm.js to WebAssembly V8 backend.
// http://asmjs.org/spec/latest/
const base::Feature kAsmJsToWebAssembly{"AsmJsToWebAssembly",
@@ -36,6 +32,18 @@ const base::Feature kAsmJsToWebAssembly{"AsmJsToWebAssembly",
const base::Feature kAsyncWheelEvents{"AsyncWheelEvents",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Creates audio output and input streams using the audio service.
+const base::Feature kAudioServiceAudioStreams{
+ "AudioServiceAudioStreams", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Launches the audio service on the browser startup.
+const base::Feature kAudioServiceLaunchOnStartup{
+ "AudioServiceLaunchOnStartup", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Runs the audio service in a separate process.
+const base::Feature kAudioServiceOutOfProcess{
+ "AudioServiceOutOfProcess", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Allows swipe left/right from touchpad change browser navigation. Currently
// only enabled by default on CrOS.
const base::Feature kTouchpadOverscrollHistoryNavigation {
@@ -72,15 +80,6 @@ const base::Feature kCanvas2DImageChromium {
#endif
};
-// Enabled decoding images asynchronously from raster in the renderer
-// compositor.
-const base::Feature kCheckerImaging{"CheckerImaging",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Enables code caching after executing the script.
-const base::Feature kCodeCacheAfterExecute{"CodeCacheAfterExecute",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables the compositing of fixed position content that is opaque and can
// preserve LCD text.
const base::Feature kCompositeOpaqueFixedPosition{
@@ -99,7 +98,7 @@ const base::Feature kCompositorTouchAction{"CompositorTouchAction",
// Enables blocking cross-site document responses (not paying attention to
// whether a site isolation mode is also enabled).
const base::Feature kCrossSiteDocumentBlockingAlways{
- "CrossSiteDocumentBlockingAlways", base::FEATURE_DISABLED_BY_DEFAULT};
+ "CrossSiteDocumentBlockingAlways", base::FEATURE_ENABLED_BY_DEFAULT};
// Enables blocking cross-site document responses if one of site isolation modes
// is (e.g. site-per-process or isolate-origins) is enabled.
@@ -130,11 +129,16 @@ const base::Feature kFontCacheScaling{"FontCacheScaling",
// same-origin to the top frame, or if a user gesture is being processed.
const base::Feature kFramebustingNeedsSameOriginOrUserGesture{
"FramebustingNeedsSameOriginOrUserGesture",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Enables extended Gamepad API features like motion tracking and haptics.
const base::Feature kGamepadExtensions{"GamepadExtensions",
base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables haptic vibration effects on supported gamepads.
+const base::Feature kGamepadVibration{"GamepadVibration",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// When WebXR Device API is enabled, exposes VR controllers as Gamepads and
// enables additional Gamepad attributes for use with WebXR Device API. Each
// XRInputSource will have a corresponding Gamepad instance.
@@ -154,6 +158,10 @@ const base::Feature kHeapCompaction{"HeapCompaction",
const base::Feature kImageCaptureAPI{"ImageCaptureAPI",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Whether to use GeometryMapper to optimize IntersectionObserver.
+const base::Feature kIntersectionObserverGeometryMapper{
+ "IntersectionObserverGeometryMapper", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Alternative to switches::kIsolateOrigins, for turning on origin isolation.
// List of origins to isolate has to be specified via
// kIsolateOriginsFieldTrialParamName.
@@ -164,7 +172,10 @@ const char kIsolateOriginsFieldTrialParamName[] = "OriginsList";
// Enables an API which allows websites to capture reserved keys in fullscreen.
// Defined by w3c here: https://w3c.github.io/keyboard-lock/
const base::Feature kKeyboardLockAPI{"KeyboardLockAPI",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kLayeredAPI{"LayeredAPI",
+ base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kLazyFrameLoading{"LazyFrameLoading",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -181,11 +192,6 @@ const base::Feature kLazyParseCSS{"LazyParseCSS",
const base::Feature kLowPriorityIframes{"LowPriorityIframes",
base::FEATURE_DISABLED_BY_DEFAULT};
-// An experiment forcing events to be non-blocking when the main thread is
-// deemed unresponsive. See https://crbug.com/599609.
-const base::Feature kMainThreadBusyScrollIntervention{
- "MainThreadBusyScrollIntervention", base::FEATURE_DISABLED_BY_DEFAULT};
-
// If this feature is enabled, media-device enumerations use a cache that is
// invalidated upon notifications sent by base::SystemMonitor. If disabled, the
// cache is considered invalid on every enumeration request.
@@ -213,10 +219,6 @@ const base::Feature kModuleScriptsDynamicImport{
const base::Feature kModuleScriptsImportMetaUrl{
"ModuleScriptsImportMetaUrl", base::FEATURE_ENABLED_BY_DEFAULT};
-// Mojo-based Input Event routing.
-const base::Feature kMojoInputMessages{"MojoInputMessages",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Mojo-based Session Storage.
const base::Feature kMojoSessionStorage{"MojoSessionStorage",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -231,13 +233,6 @@ const base::Feature kMojoVideoCapture {
#endif
};
-// Browser side navigation (aka PlzNavigate) is using blob URLs to deliver
-// the body of the main resource to the renderer process. When enabled, the
-// NavigationMojoResponse feature replaces this mechanism by a Mojo DataPipe.
-// Design doc: https://goo.gl/Rrrc7n.
-const base::Feature kNavigationMojoResponse{"NavigationMojoResponse",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// If the network service is enabled, runs it in process.
const base::Feature kNetworkServiceInProcess{"NetworkServiceInProcess",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -246,13 +241,9 @@ const base::Feature kNetworkServiceInProcess{"NetworkServiceInProcess",
const base::Feature kNotificationContentImage{"NotificationContentImage",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Use Mojo IPC for notifications.
-const base::Feature kNotificationsWithMojo{"NotificationsWithMojo",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Off-main-thread WebSocket. See https://crbug.com/825740
const base::Feature kOffMainThreadWebSocket{"OffMainThreadWebSocket",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Origin Manifest. See crbug.com/751996
const base::Feature kOriginManifest{"OriginManifest",
@@ -275,6 +266,10 @@ const base::Feature kPassiveEventListenersDueToFling{
const base::Feature kPdfIsolation = {"PdfIsolation",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Whether we should use the navigation_client mojo interface for navigations.
+const base::Feature kPerNavigationMojoInterface = {
+ "PerNavigationMojoInterface", base::FEATURE_DISABLED_BY_DEFAULT};
+
// If Pepper 3D Image Chromium is allowed, this feature controls whether it is
// enabled.
const base::Feature kPepper3DImageChromium {
@@ -316,24 +311,20 @@ const base::Feature kRenderingPipelineThrottling{
const base::Feature kRequireCSSExtensionForFile{
"RequireCSSExtensionForFile", base::FEATURE_ENABLED_BY_DEFAULT};
+// Enables resampling input events on main thread.
+const base::Feature kResamplingInputEvents{"ResamplingInputEvents",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Loading Dispatcher v0 support with ResourceLoadScheduler (crbug.com/729954).
const base::Feature kResourceLoadScheduler{"ResourceLoadScheduler",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Use common overflow scroll mechanism for frames. See http://crbug.com/417782.
-const base::Feature kRootLayerScrolling{"RootLayerScrolling",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Run video capture service in the Browser process as opposed to a dedicated
// utility process
const base::Feature kRunVideoCaptureServiceInBrowserProcess{
"RunVideoCaptureServiceInBrowserProcess",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Scrolls to compensate for layout movements (bit.ly/scroll-anchoring).
-const base::Feature kScrollAnchoring{"ScrollAnchoring",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Save the scroll anchor and use it to restore scroll position.
const base::Feature kScrollAnchorSerialization{
"ScrollAnchorSerialization", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -343,6 +334,9 @@ const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{
"SendBeaconThrowForBlobWithNonSimpleType",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kSecMetadata{"SecMetadata",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Service worker based payment apps as defined by w3c here:
// https://w3c.github.io/webpayments-payment-apps-api/
const base::Feature kServiceWorkerPaymentApps{
@@ -365,6 +359,10 @@ const base::Feature kSharedArrayBuffer{"SharedArrayBuffer",
const base::Feature kSignedHTTPExchange{"SignedHTTPExchange",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Origin Trial of Origin-Signed HTTP Exchanges (for WebPackage Loading)
+const base::Feature kSignedHTTPExchangeOriginTrial{
+ "SignedHTTPExchangeOriginTrial", base::FEATURE_DISABLED_BY_DEFAULT};
+
// An experiment to require process isolation for the sign-in origin,
// https://accounts.google.com. Launch bug: https://crbug.com/739418.
const base::Feature kSignInProcessIsolation{"sign-in-process-isolation",
@@ -414,31 +412,11 @@ const base::Feature kTopDocumentIsolation{"top-document-isolation",
const base::Feature kTouchpadAndWheelScrollLatching{
"TouchpadAndWheelScrollLatching", base::FEATURE_ENABLED_BY_DEFAULT};
-// An experiment to turn off compositing for 2D transform & opacity animations.
-const base::Feature kTurnOff2DAndOpacityCompositorAnimations{
- "TurnOff2DAndOpacityCompositorAnimations",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Enables unified touch adjustment which adjusts touch events target to a best
-// nearby node.
-const base::Feature kUnifiedTouchAdjustment{"UnifiedTouchAdjustment",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Use Feature Policy to gate the use of permission features like midi,
// geolocation, camera, microphone, etc.
const base::Feature kUseFeaturePolicyForPermissions{
"UseFeaturePolicyForPermissions", base::FEATURE_ENABLED_BY_DEFAULT};
-// Use MojoAudioInputIPC and RenderFrameAudioInputStreamFactory rather than
-// AudioInputMessageFilter and AudioInputRendererHost.
-const base::Feature kUseMojoAudioInputStreamFactory{
- "UseMojoAudioInputStreamFactory", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Use MojoAudioOutputIPC and RenderFrameAudioOutputStreamFactory rather than
-// AudioMessageFilter and AudioRendererHost.
-const base::Feature kUseMojoAudioOutputStreamFactory{
- "UseMojoAudioOutputStreamFactory", base::FEATURE_ENABLED_BY_DEFAULT};
-
// An experimental simple user-activation model where the user gesture state is
// tracked through a frame-based state instead of the gesture tokens we use
// today.
@@ -450,8 +428,7 @@ const base::Feature kUserActivationV2{"UserActivationV2",
// captured from the renderer for DevTools performance timeline and eyedropper
// tool.
const base::Feature kUseVideoCaptureApiForDevToolsSnapshots{
- "UseVideoCaptureApiForDevToolsSnapshots",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ "UseVideoCaptureApiForDevToolsSnapshots", base::FEATURE_ENABLED_BY_DEFAULT};
// Enables to use a snapshot file in creating V8 contexts.
const base::Feature kV8ContextSnapshot{"V8ContextSnapshot",
@@ -474,7 +451,11 @@ const base::Feature kWebAssembly{"WebAssembly",
const base::Feature kWebAssemblyStreaming{"WebAssemblyStreaming",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Enable WebAssembly streamed compilation.
+// Enable WebAssembly baseline compilation and tier up.
+const base::Feature kWebAssemblyBaseline{"WebAssemblyBaseline",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enable WebAssembly trap handler.
const base::Feature kWebAssemblyTrapHandler{"WebAssemblyTrapHandler",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -510,11 +491,21 @@ const base::Feature kWebAuthBle{"WebAuthenticationBle",
const base::Feature kWebAuthCtap2{"WebAuthenticationCtap2",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether CTAP2 devices can communicate via the WebAuthentication API
+// using pairingless BLE protocol.
+// https://w3c.github.io/webauthn
+const base::Feature kWebAuthCable{"WebAuthenticationCable",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// If WebGL Image Chromium is allowed, this feature controls whether it is
// enabled.
const base::Feature kWebGLImageChromium{"WebGLImageChromium",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Enable experimental policy-controlled features and LAPIs
+const base::Feature kExperimentalProductivityFeatures{
+ "ExperimentalProductivityFeatures", base::FEATURE_DISABLED_BY_DEFAULT};
+
// The JavaScript API for payments on the web.
const base::Feature kWebPayments{"WebPayments",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -529,6 +520,11 @@ const base::Feature kWebRtcAecBoundedErlSetup{
const base::Feature kWebRtcAecClockDriftSetup{
"WebRtcAecClockDriftSetup", base::FEATURE_DISABLED_BY_DEFAULT};
+// Informs the WebRTC Acoustic Echo Canceler (AEC) that the feature providing
+// echo canceller transparency to render noise should be used.
+const base::Feature kWebRtcAecNoiseTransparency{
+ "WebRtcAecNoiseTransparency", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Makes WebRTC use ECDSA certs by default (i.e., when no cert type was
// specified in JS).
const base::Feature kWebRtcEcdsaDefault{"WebRTC-EnableWebRtcEcdsa",
@@ -548,6 +544,11 @@ const base::Feature kWebRtcHWVP8Encoding {
#endif
};
+// Enables HW VP8 encoding using Intel Vaapi, if available.
+// TODO(crbug.com/794608): Enable by default when we trust quality.
+const base::Feature kWebRtcVaapiHWVP8Encoding{
+ "WebRtcVaapiHWVP8Encoding", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables negotiation of experimental multiplex codec in SDP.
const base::Feature kWebRtcMultiplexCodec{"WebRTC-MultiplexCodec",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -586,6 +587,10 @@ const base::Feature kWebXrHitTest{"WebXRHitTest",
const base::Feature kWebXrOrientationSensorDevice{
"WebXROrientationSensorDevice", base::FEATURE_DISABLED_BY_DEFAULT};
+// Wipe corrupt v2 IndexedDB databases.
+const base::Feature kWipeCorruptV2IDBDatabases{
+ "WipeCorruptV2IDBDatabases", base::FEATURE_ENABLED_BY_DEFAULT};
+
// Enabled "work stealing" in the script runner.
const base::Feature kWorkStealingInScriptRunner{
"WorkStealingInScriptRunner", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -596,6 +601,11 @@ const base::Feature kWorkStealingInScriptRunner{
const base::Feature kAndroidAutofillAccessibility{
"AndroidAutofillAccessibility", base::FEATURE_ENABLED_BY_DEFAULT};
+// Enables developers to use the CSS safe-area-* and viewport-fit APIs which
+// allow them to support devices with a display cutout.
+const base::Feature kDisplayCutoutAPI{"DisplayCutoutAPI",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables hiding incorrectly-sized frames while in fullscreen.
const base::Feature kHideIncorrectlySizedFullscreenFrames{
"HideIncorrectlySizedFullscreenFrames", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -621,10 +631,19 @@ const char kWebXrRenderPathParamValueSharedBuffer[] = "SharedBuffer";
const base::Feature kDeviceMonitorMac{"DeviceMonitorMac",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Enable IOSurface based screen capturer.
+const base::Feature kIOSurfaceCapturer{"IOSurfaceCapturer",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// The V2 sandbox on MacOS removes the unsandboed warmup phase and sandboxes the
// entire life of the process.
const base::Feature kMacV2Sandbox{"MacV2Sandbox",
base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Controls whether the CTAP2 implementation should use a built-in platform
+// authenticator, where available.
+const base::Feature kWebAuthTouchId{"WebAuthenticationTouchId",
+ base::FEATURE_DISABLED_BY_DEFAULT};
#endif // defined(OS_MACOSX)
bool IsVideoCaptureServiceEnabledForOutOfProcess() {
diff --git a/chromium/content/public/common/content_features.h b/chromium/content/public/common/content_features.h
index e3eed28171b..d972131225d 100644
--- a/chromium/content/public/common/content_features.h
+++ b/chromium/content/public/common/content_features.h
@@ -19,74 +19,76 @@ namespace features {
CONTENT_EXPORT extern const base::Feature kAllowActivationDelegationAttr;
CONTENT_EXPORT extern const base::Feature
kAllowContentInitiatedDataUrlNavigations;
-CONTENT_EXPORT extern const base::Feature kArrayPrototypeValues;
CONTENT_EXPORT extern const base::Feature kAsmJsToWebAssembly;
CONTENT_EXPORT extern const base::Feature kAsyncWheelEvents;
+CONTENT_EXPORT extern const base::Feature kAudioServiceAudioStreams;
+CONTENT_EXPORT extern const base::Feature kAudioServiceLaunchOnStartup;
+CONTENT_EXPORT extern const base::Feature kAudioServiceOutOfProcess;
CONTENT_EXPORT extern const base::Feature kBlockCredentialedSubresources;
CONTENT_EXPORT extern const base::Feature kBrotliEncoding;
CONTENT_EXPORT extern const base::Feature kCacheInlineScriptCode;
CONTENT_EXPORT extern const base::Feature kCanvas2DImageChromium;
-CONTENT_EXPORT extern const base::Feature kCheckerImaging;
-CONTENT_EXPORT extern const base::Feature kCodeCacheAfterExecute;
CONTENT_EXPORT extern const base::Feature kCompositeOpaqueFixedPosition;
CONTENT_EXPORT extern const base::Feature kCompositeOpaqueScrollers;
CONTENT_EXPORT extern const base::Feature kCompositorTouchAction;
CONTENT_EXPORT extern const base::Feature kCrossSiteDocumentBlockingAlways;
CONTENT_EXPORT extern const base::Feature kCrossSiteDocumentBlockingIfIsolating;
CONTENT_EXPORT extern const base::Feature kDataSaverHoldback;
+CONTENT_EXPORT extern const base::Feature kExperimentalProductivityFeatures;
CONTENT_EXPORT extern const base::Feature kExpensiveBackgroundTimerThrottling;
CONTENT_EXPORT extern const base::Feature kExtendedMouseButtons;
CONTENT_EXPORT extern const base::Feature kFontCacheScaling;
CONTENT_EXPORT extern const base::Feature
kFramebustingNeedsSameOriginOrUserGesture;
CONTENT_EXPORT extern const base::Feature kGamepadExtensions;
+CONTENT_EXPORT extern const base::Feature kGamepadVibration;
CONTENT_EXPORT extern const base::Feature kGuestViewCrossProcessFrames;
CONTENT_EXPORT extern const base::Feature kHeapCompaction;
CONTENT_EXPORT extern const base::Feature kImageCaptureAPI;
+CONTENT_EXPORT extern const base::Feature kIntersectionObserverGeometryMapper;
CONTENT_EXPORT extern const base::Feature kIsolateOrigins;
CONTENT_EXPORT extern const char kIsolateOriginsFieldTrialParamName[];
CONTENT_EXPORT extern const base::Feature kKeyboardLockAPI;
+CONTENT_EXPORT extern const base::Feature kLayeredAPI;
CONTENT_EXPORT extern const base::Feature kLazyFrameLoading;
CONTENT_EXPORT extern const base::Feature kLazyInitializeMediaControls;
CONTENT_EXPORT extern const base::Feature kLazyParseCSS;
CONTENT_EXPORT extern const base::Feature kLowPriorityIframes;
-CONTENT_EXPORT extern const base::Feature kMainThreadBusyScrollIntervention;
CONTENT_EXPORT extern const base::Feature kMediaDevicesSystemMonitorCache;
CONTENT_EXPORT extern const base::Feature kMemoryCoordinator;
CONTENT_EXPORT extern const base::Feature kModuleScriptsDynamicImport;
CONTENT_EXPORT extern const base::Feature kModuleScriptsImportMetaUrl;
-CONTENT_EXPORT extern const base::Feature kMojoInputMessages;
CONTENT_EXPORT extern const base::Feature kMojoSessionStorage;
CONTENT_EXPORT extern const base::Feature kMojoVideoCapture;
-CONTENT_EXPORT extern const base::Feature kNavigationMojoResponse;
CONTENT_EXPORT extern const base::Feature kNetworkServiceInProcess;
CONTENT_EXPORT extern const base::Feature kNotificationContentImage;
-CONTENT_EXPORT extern const base::Feature kNotificationsWithMojo;
CONTENT_EXPORT extern const base::Feature kOffMainThreadWebSocket;
CONTENT_EXPORT extern const base::Feature kOriginManifest;
CONTENT_EXPORT extern const base::Feature kOriginTrials;
CONTENT_EXPORT extern const base::Feature kPassiveDocumentEventListeners;
CONTENT_EXPORT extern const base::Feature kPassiveEventListenersDueToFling;
CONTENT_EXPORT extern const base::Feature kPdfIsolation;
+CONTENT_EXPORT extern const base::Feature kPerNavigationMojoInterface;
CONTENT_EXPORT extern const base::Feature kPepper3DImageChromium;
CONTENT_EXPORT extern const base::Feature kPurgeAndSuspend;
CONTENT_EXPORT extern const base::Feature kPWAFullCodeCache;
CONTENT_EXPORT extern const base::Feature kRasterInducingScroll;
CONTENT_EXPORT extern const base::Feature kRenderingPipelineThrottling;
CONTENT_EXPORT extern const base::Feature kRequireCSSExtensionForFile;
+CONTENT_EXPORT extern const base::Feature kResamplingInputEvents;
CONTENT_EXPORT extern const base::Feature kResourceLoadScheduler;
-CONTENT_EXPORT extern const base::Feature kRootLayerScrolling;
CONTENT_EXPORT extern const base::Feature
kRunVideoCaptureServiceInBrowserProcess;
-CONTENT_EXPORT extern const base::Feature kScrollAnchoring;
CONTENT_EXPORT extern const base::Feature kScrollAnchorSerialization;
CONTENT_EXPORT extern const base::Feature
kSendBeaconThrowForBlobWithNonSimpleType;
+CONTENT_EXPORT extern const base::Feature kSecMetadata;
CONTENT_EXPORT extern const base::Feature kServiceWorkerPaymentApps;
CONTENT_EXPORT extern const base::Feature kServiceWorkerScriptFullCodeCache;
CONTENT_EXPORT extern const base::Feature kServiceWorkerServicification;
CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer;
CONTENT_EXPORT extern const base::Feature kSignedHTTPExchange;
+CONTENT_EXPORT extern const base::Feature kSignedHTTPExchangeOriginTrial;
CONTENT_EXPORT extern const base::Feature kSignInProcessIsolation;
CONTENT_EXPORT extern const base::Feature kSlimmingPaintV175;
CONTENT_EXPORT extern const base::Feature kSpareRendererForSitePerProcess;
@@ -97,12 +99,7 @@ CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames;
CONTENT_EXPORT extern const base::Feature kTopDocumentIsolation;
CONTENT_EXPORT extern const base::Feature kTouchpadAndWheelScrollLatching;
CONTENT_EXPORT extern const base::Feature kTouchpadOverscrollHistoryNavigation;
-CONTENT_EXPORT extern const base::Feature
- kTurnOff2DAndOpacityCompositorAnimations;
-CONTENT_EXPORT extern const base::Feature kUnifiedTouchAdjustment;
CONTENT_EXPORT extern const base::Feature kUseFeaturePolicyForPermissions;
-CONTENT_EXPORT extern const base::Feature kUseMojoAudioInputStreamFactory;
-CONTENT_EXPORT extern const base::Feature kUseMojoAudioOutputStreamFactory;
CONTENT_EXPORT extern const base::Feature kUserActivationV2;
CONTENT_EXPORT extern const base::Feature
kUseVideoCaptureApiForDevToolsSnapshots;
@@ -111,18 +108,22 @@ CONTENT_EXPORT extern const base::Feature kV8VmFuture;
CONTENT_EXPORT extern const base::Feature kVrWebInputEditing;
CONTENT_EXPORT extern const base::Feature kWebAssembly;
CONTENT_EXPORT extern const base::Feature kWebAssemblyStreaming;
+CONTENT_EXPORT extern const base::Feature kWebAssemblyBaseline;
CONTENT_EXPORT extern const base::Feature kWebAssemblyTrapHandler;
CONTENT_EXPORT extern const base::Feature kWebAuth;
CONTENT_EXPORT extern const base::Feature kWebAuthBle;
-CONTENT_EXPORT extern const base::Feature kWebContentsOcclusion;
CONTENT_EXPORT extern const base::Feature kWebAuthCtap2;
+CONTENT_EXPORT extern const base::Feature kWebAuthCable;
+CONTENT_EXPORT extern const base::Feature kWebContentsOcclusion;
CONTENT_EXPORT extern const base::Feature kWebGLImageChromium;
CONTENT_EXPORT extern const base::Feature kWebPayments;
CONTENT_EXPORT extern const base::Feature kWebRtcAecBoundedErlSetup;
CONTENT_EXPORT extern const base::Feature kWebRtcAecClockDriftSetup;
+CONTENT_EXPORT extern const base::Feature kWebRtcAecNoiseTransparency;
CONTENT_EXPORT extern const base::Feature kWebRtcEcdsaDefault;
CONTENT_EXPORT extern const base::Feature kWebRtcHWH264Encoding;
CONTENT_EXPORT extern const base::Feature kWebRtcHWVP8Encoding;
+CONTENT_EXPORT extern const base::Feature kWebRtcVaapiHWVP8Encoding;
CONTENT_EXPORT extern const base::Feature kWebRtcMultiplexCodec;
CONTENT_EXPORT extern const base::Feature kWebRtcScreenshareSwEncoding;
CONTENT_EXPORT extern const base::Feature kWebRtcUseEchoCanceller3;
@@ -133,10 +134,12 @@ CONTENT_EXPORT extern const base::Feature kWebXr;
CONTENT_EXPORT extern const base::Feature kWebXrGamepadSupport;
CONTENT_EXPORT extern const base::Feature kWebXrHitTest;
CONTENT_EXPORT extern const base::Feature kWebXrOrientationSensorDevice;
+CONTENT_EXPORT extern const base::Feature kWipeCorruptV2IDBDatabases;
CONTENT_EXPORT extern const base::Feature kWorkStealingInScriptRunner;
#if defined(OS_ANDROID)
CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility;
+CONTENT_EXPORT extern const base::Feature kDisplayCutoutAPI;
CONTENT_EXPORT extern const base::Feature kHideIncorrectlySizedFullscreenFrames;
CONTENT_EXPORT extern const base::Feature kWebNfc;
CONTENT_EXPORT extern const base::Feature kWebXrRenderPath;
@@ -148,7 +151,9 @@ CONTENT_EXPORT extern const char kWebXrRenderPathParamValueSharedBuffer[];
#if defined(OS_MACOSX)
CONTENT_EXPORT extern const base::Feature kDeviceMonitorMac;
+CONTENT_EXPORT extern const base::Feature kIOSurfaceCapturer;
CONTENT_EXPORT extern const base::Feature kMacV2Sandbox;
+CONTENT_EXPORT extern const base::Feature kWebAuthTouchId;
#endif // defined(OS_MACOSX)
// DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
diff --git a/chromium/content/public/common/content_switches.cc b/chromium/content/public/common/content_switches.cc
index 97e443b8fd7..aac63339ab2 100644
--- a/chromium/content/public/common/content_switches.cc
+++ b/chromium/content/public/common/content_switches.cc
@@ -169,9 +169,6 @@ const char kDisableGpuProcessCrashLimit[] = "disable-gpu-process-crash-limit";
// during fast scrolling especially on slower devices.
const char kDisableLowResTiling[] = "disable-low-res-tiling";
-// Disable the GPU process sandbox.
-const char kDisableGpuSandbox[] = "disable-gpu-sandbox";
-
// Disable the thread that crashes the GPU process if it stops responding to
// messages.
const char kDisableGpuWatchdog[] = "disable-gpu-watchdog";
@@ -206,9 +203,6 @@ const char kDisableLogging[] = "disable-logging";
// Disables using CODECAPI_AVLowLatencyMode when creating DXVA decoders.
const char kDisableLowLatencyDxva[] = "disable-low-latency-dxva";
-// Disables usage of the namespace sandbox.
-const char kDisableNamespaceSandbox[] = "disable-namespace-sandbox";
-
// Disables clearing the rendering output of a renderer when it didn't commit
// new output for a while after a top-frame navigation.
const char kDisableNewContentRenderingTimeout[] =
@@ -349,6 +343,10 @@ const char kEnableBackgroundFetchPersistence[] =
// features.
const char kEnableBlinkFeatures[] = "enable-blink-features";
+// A shorthand for adding both "--enable-blink-features=BlinkGenPropertyTrees"
+// and "--enable-layer-lists".
+const char kEnableBlinkGenPropertyTrees[] = "enable-blink-gen-property-trees";
+
// Enables Web Platform features that are in development.
const char kEnableExperimentalWebPlatformFeatures[] =
"enable-experimental-web-platform-features";
@@ -404,9 +402,10 @@ const char kEnableRGBA4444Textures[] = "enable-rgba-4444-textures";
// Set options to cache V8 data. (off, preparse data, or code)
const char kV8CacheOptions[] = "v8-cache-options";
-// Cause the OS X sandbox write to syslog every time an access to a resource
-// is denied by the sandbox.
-const char kEnableSandboxLogging[] = "enable-sandbox-logging";
+// If true the ServiceProcessLauncher is used to launch services. This allows
+// for service binaries to be loaded rather than using the utility process. This
+// is only useful for tests.
+const char kEnableServiceBinaryLauncher[] = "enable-service-binary-launcher";
// Enables the Skia benchmarking extension
const char kEnableSkiaBenchmarking[] = "enable-skia-benchmarking";
@@ -607,9 +606,6 @@ const char kMHTMLSkipNostoreAll[] = "skip-nostore-all";
// Use a Mojo-based LocalStorage implementation.
const char kMojoLocalStorage[] = "mojo-local-storage";
-// Disables the sandbox for all process types that are normally sandboxed.
-const char kNoSandbox[] = "no-sandbox";
-
// Disables the use of a zygote process for forking child processes. Instead,
// child processes will be forked and exec'd directly. Note that --no-sandbox
// should also be used together with this flag because the sandbox needs the
@@ -736,8 +732,8 @@ const char kRendererProcess[] = "renderer";
const char kRendererProcessLimit[] = "renderer-process-limit";
// Causes the renderer process to display a dialog on launch. Passing this flag
-// also adds kNoSandbox on Windows non-official builds, since that's needed to
-// show a dialog.
+// also adds service_manager::kNoSandbox on Windows non-official builds, since
+// that's needed to show a dialog.
const char kRendererStartupDialog[] = "renderer-startup-dialog";
// Reduce the default `referer` header's granularity.
@@ -856,13 +852,6 @@ const char kValidateInputEventStream[] = "validate-input-event-stream";
// kWaitForDebugger flag passed on or not.
const char kWaitForDebuggerChildren[] = "wait-for-debugger-children";
-// The prefix used when starting the zygote process. (i.e. 'gdb --args')
-const char kZygoteCmdPrefix[] = "zygote-cmd-prefix";
-
-// Causes the process to run as a renderer zygote.
-const char kZygoteProcess[] = "zygote";
-
-#if BUILDFLAG(ENABLE_WEBRTC)
// Disables encryption of RTP Media for WebRTC. When Chrome embeds Content, it
// ignores this switch on its stable and beta channels.
const char kDisableWebRtcEncryption[] = "disable-webrtc-encryption";
@@ -909,7 +898,6 @@ const char kWebRtcMaxCpuConsumptionPercentage[] =
// interval. Please see SetupStunProbeTrial in
// chrome_browser_field_trials_desktop.cc for more detail.
const char kWebRtcStunProbeTrialParameter[] = "webrtc-stun-probe-trial";
-#endif
// Enable capture and local storage of WebRTC event logs without visiting
// chrome://webrtc-internals. This is useful for automated testing. It accepts
diff --git a/chromium/content/public/common/content_switches.h b/chromium/content/public/common/content_switches.h
index a1ccec7e81f..990f172ac8c 100644
--- a/chromium/content/public/common/content_switches.h
+++ b/chromium/content/public/common/content_switches.h
@@ -58,7 +58,6 @@ CONTENT_EXPORT extern const char kDisableGpuEarlyInit[];
CONTENT_EXPORT extern const char kDisableGpuMemoryBufferCompositorResources[];
CONTENT_EXPORT extern const char kDisableGpuMemoryBufferVideoFrames[];
extern const char kDisableGpuProcessCrashLimit[];
-CONTENT_EXPORT extern const char kDisableGpuSandbox[];
CONTENT_EXPORT extern const char kDisableGpuWatchdog[];
CONTENT_EXPORT extern const char kDisableImageAnimationResync[];
CONTENT_EXPORT extern const char kDisableJavaScriptHarmonyShipping[];
@@ -71,7 +70,6 @@ CONTENT_EXPORT extern const char kDisablePreferCompositingToLCDText[];
CONTENT_EXPORT extern const char kDisableKillAfterBadIPC[];
CONTENT_EXPORT extern const char kDisableLocalStorage[];
CONTENT_EXPORT extern const char kDisableLogging[];
-CONTENT_EXPORT extern const char kDisableNamespaceSandbox[];
CONTENT_EXPORT extern const char kDisableNewContentRenderingTimeout[];
CONTENT_EXPORT extern const char kDisableNotifications[];
CONTENT_EXPORT extern const char kDisableOriginTrialControlledBlinkFeatures[];
@@ -111,6 +109,7 @@ CONTENT_EXPORT extern const char kEnableAggressiveDOMStorageFlushing[];
CONTENT_EXPORT extern const char kEnableAutomation[];
CONTENT_EXPORT extern const char kEnablePreferCompositingToLCDText[];
CONTENT_EXPORT extern const char kEnableBlinkFeatures[];
+CONTENT_EXPORT extern const char kEnableBlinkGenPropertyTrees[];
CONTENT_EXPORT extern const char kEnableBackgroundFetchPersistence[];
CONTENT_EXPORT extern const char kEnableDisplayList2dCanvas[];
CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
@@ -127,7 +126,7 @@ CONTENT_EXPORT extern const char kEnablePluginPlaceholderTesting[];
CONTENT_EXPORT extern const char kEnablePreciseMemoryInfo[];
CONTENT_EXPORT extern const char kEnablePrintBrowser[];
CONTENT_EXPORT extern const char kEnableRGBA4444Textures[];
-CONTENT_EXPORT extern const char kEnableSandboxLogging[];
+CONTENT_EXPORT extern const char kEnableServiceBinaryLauncher[];
extern const char kEnableSkiaBenchmarking[];
CONTENT_EXPORT extern const char kEnableSlimmingPaintV175[];
CONTENT_EXPORT extern const char kEnableSlimmingPaintV2[];
@@ -182,7 +181,6 @@ CONTENT_EXPORT extern const char kMHTMLGeneratorOption[];
CONTENT_EXPORT extern const char kMHTMLSkipNostoreMain[];
CONTENT_EXPORT extern const char kMHTMLSkipNostoreAll[];
CONTENT_EXPORT extern const char kMojoLocalStorage[];
-CONTENT_EXPORT extern const char kNoSandbox[];
CONTENT_EXPORT extern const char kNoZygote[];
CONTENT_EXPORT extern const char kEnableAppContainer[];
CONTENT_EXPORT extern const char kDisableAppContainer[];
@@ -237,10 +235,7 @@ CONTENT_EXPORT extern const char kUtilityStartupDialog[];
CONTENT_EXPORT extern const char kV8CacheOptions[];
CONTENT_EXPORT extern const char kValidateInputEventStream[];
CONTENT_EXPORT extern const char kWaitForDebuggerChildren[];
-CONTENT_EXPORT extern const char kZygoteCmdPrefix[];
-CONTENT_EXPORT extern const char kZygoteProcess[];
-#if BUILDFLAG(ENABLE_WEBRTC)
CONTENT_EXPORT extern const char kDisableWebRtcEncryption[];
CONTENT_EXPORT extern const char kDisableWebRtcHWDecoding[];
CONTENT_EXPORT extern const char kDisableWebRtcHWEncoding[];
@@ -252,11 +247,6 @@ CONTENT_EXPORT extern const char kForceWebRtcIPHandlingPolicy[];
extern const char kWebRtcMaxCaptureFramerate[];
extern const char kWebRtcMaxCpuConsumptionPercentage[];
CONTENT_EXPORT extern const char kWebRtcStunProbeTrialParameter[];
-#endif
-
-// TODO(eladalon): Move into "#if BUILDFLAG(ENABLE_WEBRTC)" section when
-// WebRTCInternals is excluded from the build for non-WebRTC builds.
-// https://crbug.com/817446
CONTENT_EXPORT extern const char kWebRtcLocalEventLogging[];
#if defined(OS_ANDROID)
diff --git a/chromium/content/public/common/load_timing_info.mojom b/chromium/content/public/common/load_timing_info.mojom
new file mode 100644
index 00000000000..605e65bd29d
--- /dev/null
+++ b/chromium/content/public/common/load_timing_info.mojom
@@ -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.
+
+module content.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+
+// Mirror of net::LoadTimingInfo::ConnectTiming.
+struct LoadTimingInfoConnectTiming {
+ mojo_base.mojom.TimeTicks dns_start;
+ mojo_base.mojom.TimeTicks dns_end;
+ mojo_base.mojom.TimeTicks connect_start;
+ mojo_base.mojom.TimeTicks connect_end;
+ mojo_base.mojom.TimeTicks ssl_start;
+ mojo_base.mojom.TimeTicks ssl_end;
+};
+
+// Mirror of net::LoadTimingInfo.
+struct LoadTimingInfo {
+ bool socket_reused;
+ uint32 socket_log_id;
+ mojo_base.mojom.Time request_start_time;
+ mojo_base.mojom.TimeTicks request_start;
+ mojo_base.mojom.TimeTicks proxy_resolve_start;
+ mojo_base.mojom.TimeTicks proxy_resolve_end;
+ LoadTimingInfoConnectTiming connect_timing;
+ mojo_base.mojom.TimeTicks send_start;
+ mojo_base.mojom.TimeTicks send_end;
+ mojo_base.mojom.TimeTicks receive_headers_end;
+ mojo_base.mojom.TimeTicks push_start;
+ mojo_base.mojom.TimeTicks push_end;
+};
diff --git a/chromium/content/public/common/load_timing_info.typemap b/chromium/content/public/common/load_timing_info.typemap
new file mode 100644
index 00000000000..b86d3647324
--- /dev/null
+++ b/chromium/content/public/common/load_timing_info.typemap
@@ -0,0 +1,14 @@
+# 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 = "//content/public/common/load_timing_info.mojom"
+public_headers = [ "//net/base/load_timing_info.h" ]
+traits_headers = [ "//content/public/common/load_timing_info_struct_traits.h" ]
+sources = [
+ "//content/public/common/load_timing_info_struct_traits.cc",
+]
+type_mappings = [
+ "content.mojom.LoadTimingInfo=net::LoadTimingInfo",
+ "content.mojom.LoadTimingInfoConnectTiming=net::LoadTimingInfo::ConnectTiming",
+]
diff --git a/chromium/content/public/common/load_timing_info_struct_traits.cc b/chromium/content/public/common/load_timing_info_struct_traits.cc
new file mode 100644
index 00000000000..5894946d0a9
--- /dev/null
+++ b/chromium/content/public/common/load_timing_info_struct_traits.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 "content/public/common/load_timing_info_struct_traits.h"
+
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<content::mojom::LoadTimingInfoConnectTimingDataView,
+ net::LoadTimingInfo::ConnectTiming>::
+ Read(content::mojom::LoadTimingInfoConnectTimingDataView data,
+ net::LoadTimingInfo::ConnectTiming* out) {
+ return data.ReadDnsStart(&out->dns_start) && data.ReadDnsEnd(&out->dns_end) &&
+ data.ReadConnectStart(&out->connect_start) &&
+ data.ReadConnectEnd(&out->connect_end) &&
+ data.ReadSslStart(&out->ssl_start) && data.ReadSslEnd(&out->ssl_end);
+}
+
+// static
+bool StructTraits<content::mojom::LoadTimingInfoDataView, net::LoadTimingInfo>::
+ Read(content::mojom::LoadTimingInfoDataView data,
+ net::LoadTimingInfo* out) {
+ out->socket_reused = data.socket_reused();
+ out->socket_log_id = data.socket_log_id();
+ return data.ReadRequestStartTime(&out->request_start_time) &&
+ data.ReadRequestStart(&out->request_start) &&
+ data.ReadProxyResolveStart(&out->proxy_resolve_start) &&
+ data.ReadProxyResolveEnd(&out->proxy_resolve_end) &&
+ data.ReadConnectTiming(&out->connect_timing) &&
+ data.ReadSendStart(&out->send_start) &&
+ data.ReadSendEnd(&out->send_end) &&
+ data.ReadReceiveHeadersEnd(&out->receive_headers_end) &&
+ data.ReadPushStart(&out->push_start) &&
+ data.ReadPushEnd(&out->push_end);
+}
+
+} // namespace mojo
diff --git a/chromium/content/public/common/load_timing_info_struct_traits.h b/chromium/content/public/common/load_timing_info_struct_traits.h
new file mode 100644
index 00000000000..523da814216
--- /dev/null
+++ b/chromium/content/public/common/load_timing_info_struct_traits.h
@@ -0,0 +1,109 @@
+// 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_PUBLIC_COMMON_LOAD_TIMING_INFO_STRUCT_TRAITS_H_
+#define CONTENT_PUBLIC_COMMON_LOAD_TIMING_INFO_STRUCT_TRAITS_H_
+
+#include "content/public/common/load_timing_info.mojom.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "net/base/load_timing_info.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<content::mojom::LoadTimingInfoConnectTimingDataView,
+ net::LoadTimingInfo::ConnectTiming> {
+ static base::TimeTicks dns_start(
+ const net::LoadTimingInfo::ConnectTiming& obj) {
+ return obj.dns_start;
+ }
+
+ static base::TimeTicks dns_end(
+ const net::LoadTimingInfo::ConnectTiming& obj) {
+ return obj.dns_end;
+ }
+
+ static base::TimeTicks connect_start(
+ const net::LoadTimingInfo::ConnectTiming& obj) {
+ return obj.connect_start;
+ }
+
+ static base::TimeTicks connect_end(
+ const net::LoadTimingInfo::ConnectTiming& obj) {
+ return obj.connect_end;
+ }
+
+ static base::TimeTicks ssl_start(
+ const net::LoadTimingInfo::ConnectTiming& obj) {
+ return obj.ssl_start;
+ }
+
+ static base::TimeTicks ssl_end(
+ const net::LoadTimingInfo::ConnectTiming& obj) {
+ return obj.ssl_end;
+ }
+
+ static bool Read(content::mojom::LoadTimingInfoConnectTimingDataView obj,
+ net::LoadTimingInfo::ConnectTiming* output);
+};
+
+template <>
+struct StructTraits<content::mojom::LoadTimingInfoDataView,
+ net::LoadTimingInfo> {
+ static bool socket_reused(const net::LoadTimingInfo& obj) {
+ return obj.socket_reused;
+ }
+
+ static uint32_t socket_log_id(const net::LoadTimingInfo& obj) {
+ return obj.socket_log_id;
+ }
+
+ static base::Time request_start_time(const net::LoadTimingInfo& obj) {
+ return obj.request_start_time;
+ }
+
+ static base::TimeTicks request_start(const net::LoadTimingInfo& obj) {
+ return obj.request_start;
+ }
+
+ static base::TimeTicks proxy_resolve_start(const net::LoadTimingInfo& obj) {
+ return obj.proxy_resolve_start;
+ }
+
+ static base::TimeTicks proxy_resolve_end(const net::LoadTimingInfo& obj) {
+ return obj.proxy_resolve_end;
+ }
+
+ static net::LoadTimingInfo::ConnectTiming connect_timing(
+ const net::LoadTimingInfo& obj) {
+ return obj.connect_timing;
+ }
+
+ static base::TimeTicks send_start(const net::LoadTimingInfo& obj) {
+ return obj.send_start;
+ }
+
+ static base::TimeTicks send_end(const net::LoadTimingInfo& obj) {
+ return obj.send_end;
+ }
+
+ static base::TimeTicks receive_headers_end(const net::LoadTimingInfo& obj) {
+ return obj.receive_headers_end;
+ }
+
+ static base::TimeTicks push_start(const net::LoadTimingInfo& obj) {
+ return obj.push_start;
+ }
+
+ static base::TimeTicks push_end(const net::LoadTimingInfo& obj) {
+ return obj.push_end;
+ }
+
+ static bool Read(content::mojom::LoadTimingInfoDataView obj,
+ net::LoadTimingInfo* output);
+};
+
+} // namespace mojo
+
+#endif // CONTENT_PUBLIC_COMMON_LOAD_TIMING_INFO_STRUCT_TRAITS_H_
diff --git a/chromium/content/public/common/manifest.cc b/chromium/content/public/common/manifest.cc
deleted file mode 100644
index ad5211065be..00000000000
--- a/chromium/content/public/common/manifest.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 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/public/common/manifest.h"
-
-namespace content {
-
-// We need to provide a value here which is out of the range of a 32-bit integer
-// since otherwise we would not be able to check whether a theme color was valid
-// or not. The simplest way to do this is to simply add one to the maximum
-// possible 32-bit integer.
-const int64_t Manifest::kInvalidOrMissingColor =
- static_cast<int64_t>(std::numeric_limits<int32_t>::max()) + 1;
-const size_t Manifest::kMaxIPCStringLength = 4 * 1024;
-
-Manifest::Icon::Icon() = default;
-
-Manifest::Icon::Icon(const Icon& other) = default;
-
-Manifest::Icon::~Icon() = default;
-
-bool Manifest::Icon::operator==(const Manifest::Icon& other) const {
- return src == other.src && type == other.type && sizes == other.sizes;
-}
-
-Manifest::ShareTarget::ShareTarget() = default;
-
-Manifest::ShareTarget::~ShareTarget() = default;
-
-Manifest::RelatedApplication::RelatedApplication() = default;
-
-Manifest::RelatedApplication::~RelatedApplication() = default;
-
-Manifest::Manifest()
- : display(blink::kWebDisplayModeUndefined),
- orientation(blink::kWebScreenOrientationLockDefault),
- prefer_related_applications(false),
- theme_color(Manifest::kInvalidOrMissingColor),
- background_color(Manifest::kInvalidOrMissingColor) {
- share_target = base::nullopt;
-}
-
-Manifest::Manifest(const Manifest& other) = default;
-
-Manifest::~Manifest() = default;
-
-bool Manifest::IsEmpty() const {
- return name.is_null() && short_name.is_null() && start_url.is_empty() &&
- display == blink::kWebDisplayModeUndefined &&
- orientation == blink::kWebScreenOrientationLockDefault &&
- icons.empty() && !share_target.has_value() &&
- related_applications.empty() && !prefer_related_applications &&
- theme_color == Manifest::kInvalidOrMissingColor &&
- background_color == Manifest::kInvalidOrMissingColor &&
- splash_screen_url.is_empty() && gcm_sender_id.is_null() &&
- scope.is_empty();
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/manifest.h b/chromium/content/public/common/manifest.h
deleted file mode 100644
index e00110ff2e0..00000000000
--- a/chromium/content/public/common/manifest.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2014 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_PUBLIC_COMMON_MANIFEST_H_
-#define CONTENT_PUBLIC_COMMON_MANIFEST_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/optional.h"
-#include "base/strings/nullable_string16.h"
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
-#include "ui/gfx/geometry/size.h"
-#include "url/gurl.h"
-
-namespace content {
-
-// The Manifest structure is an internal representation of the Manifest file
-// described in the "Manifest for Web Application" document:
-// http://w3c.github.io/manifest/
-struct CONTENT_EXPORT Manifest {
- // Structure representing an icon as per the Manifest specification, see:
- // http://w3c.github.io/manifest/#dfn-icon-object
- struct CONTENT_EXPORT Icon {
- enum IconPurpose {
- ANY = 0,
- BADGE,
- ICON_PURPOSE_LAST = BADGE,
- };
-
- Icon();
- Icon(const Icon& other);
- ~Icon();
-
- bool operator==(const Icon& 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;
-
- // Empty if the field was not present or not of type "string". Defaults to
- // a vector with a single value, IconPurpose::ANY, for all other parsing
- // exceptions.
- std::vector<IconPurpose> purpose;
- };
-
- // Structure representing how a Web Share target handles an incoming share.
- struct CONTENT_EXPORT ShareTarget {
- ShareTarget();
- ~ShareTarget();
-
- // The URL template that contains placeholders to be replaced with shared
- // data. Empty if the parsing failed.
- GURL url_template;
- };
-
- // Structure representing a related application.
- struct CONTENT_EXPORT RelatedApplication {
- RelatedApplication();
- ~RelatedApplication();
-
- // The platform on which the application can be found. This can be any
- // string, and is interpreted by the consumer of the object. Empty if the
- // parsing failed.
- base::NullableString16 platform;
-
- // URL at which the application can be found. One of |url| and |id| must be
- // present. Empty if the parsing failed or the field was not present.
- GURL url;
-
- // An id which is used to represent the application on the platform. One of
- // |url| and |id| must be present. Empty if the parsing failed or the field
- // was not present.
- base::NullableString16 id;
- };
-
- Manifest();
- Manifest(const Manifest& other);
- ~Manifest();
-
- // Returns whether this Manifest had no attribute set. A newly created
- // Manifest is always empty.
- bool IsEmpty() const;
-
- // Null if the parsing failed or the field was not present.
- base::NullableString16 name;
-
- // Null if the parsing failed or the field was not present.
- base::NullableString16 short_name;
-
- // Empty if the parsing failed or the field was not present.
- GURL start_url;
-
- // Set to WebDisplayModeUndefined if the parsing failed or the field was not
- // present.
- blink::WebDisplayMode display;
-
- // Set to blink::WebScreenOrientationLockDefault if the parsing failed or the
- // field was not present.
- blink::WebScreenOrientationLockType orientation;
-
- // Empty if the parsing failed, the field was not present, empty or all the
- // icons inside the JSON array were invalid.
- std::vector<Icon> icons;
-
- // Null if parsing failed or the field was not present.
- // TODO(constantina): This field is non-standard and part of a Chrome
- // experiment. See:
- // https://github.com/WICG/web-share-target/blob/master/docs/interface.md
- // As such, this field should not be exposed to web contents.
- base::Optional<ShareTarget> share_target;
-
- // Empty if the parsing failed, the field was not present, empty or all the
- // applications inside the array were invalid. The order of the array
- // indicates the priority of the application to use.
- std::vector<RelatedApplication> related_applications;
-
- // A boolean that is used as a hint for the user agent to say that related
- // applications should be preferred over the web application. False if missing
- // or there is a parsing failure.
- bool prefer_related_applications;
-
- // This is a 64 bit integer because we need to represent an error state. The
- // color itself should only be 32 bits long if the value is not
- // kInvalidOrMissingColor and can be safely cast to SkColor if is valid.
- // Set to kInvalidOrMissingColor if parsing failed or field is not
- // present.
- int64_t theme_color;
-
- // This is a 64 bit integer because we need to represent an error state. The
- // color itself should only be 32 bits long if the value is not
- // kInvalidOrMissingColor and can be safely cast to SkColor if is valid.
- // Set to kInvalidOrMissingColor if parsing failed or field is not
- // present.
- int64_t background_color;
-
- // A URL of the HTML splash screen.
- // Empty if the parsing failed or the field was not present.
- GURL splash_screen_url;
-
- // This is a proprietary extension of the web Manifest, double-check that it
- // is okay to use this entry.
- // Null if parsing failed or the field was not present.
- base::NullableString16 gcm_sender_id;
-
- // Empty if the parsing failed or the field was not present.
- GURL scope;
-
- // Maximum length for all the strings inside the Manifest when it is sent over
- // IPC. The renderer process should truncate the strings before sending the
- // Manifest and the browser process must do the same when receiving it.
- static const size_t kMaxIPCStringLength;
-
- // Constant representing an invalid color. Set to a value outside the
- // range of a 32-bit integer.
- static const int64_t kInvalidOrMissingColor;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_MANIFEST_H_
diff --git a/chromium/content/public/common/manifest.typemap b/chromium/content/public/common/manifest.typemap
deleted file mode 100644
index 4b27a5b76b7..00000000000
--- a/chromium/content/public/common/manifest.typemap
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2017 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 = "//third_party/blink/public/platform/modules/manifest/manifest.mojom"
-public_headers = [ "//content/public/common/manifest.h" ]
-traits_headers = [ "//content/public/common/manifest_struct_traits.h" ]
-sources = [
- # Because this mojom is effectively linked as part of content/public/common,
- # and it cannot express a dependency on that target; yet manifest.h belongs to
- # that target, so gn check will complain about its inclusion by the traits
- # given the lack of explicit dependency. We work around this awkward situation
- # by claiming that manifest.h is part of the mojom sources. As long as
- # everything is still effectively part of content/public/common, this is fine.
- "//content/public/common/manifest.h",
- "//content/public/common/manifest_struct_traits.cc",
- "//content/public/common/manifest_struct_traits.h",
-]
-deps = [
- "//ui/gfx/geometry/mojo:struct_traits",
-]
-type_mappings = [
- "blink.mojom.Manifest=content::Manifest[nullable_is_same_type]",
- "blink.mojom.ManifestIcon=content::Manifest::Icon",
- "blink.mojom.ManifestRelatedApplication=content::Manifest::RelatedApplication",
- "blink.mojom.ManifestShareTarget=content::Manifest::ShareTarget",
-]
diff --git a/chromium/content/public/common/manifest_share_target_util.cc b/chromium/content/public/common/manifest_share_target_util.cc
deleted file mode 100644
index ada0a39b654..00000000000
--- a/chromium/content/public/common/manifest_share_target_util.cc
+++ /dev/null
@@ -1,127 +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/public/common/manifest_share_target_util.h"
-
-#include <map>
-
-#include "base/strings/strcat.h"
-#include "base/strings/string_util.h"
-#include "net/base/escape.h"
-#include "url/gurl.h"
-
-namespace content {
-namespace {
-
-// Determines whether a character is allowed in a URL template placeholder.
-bool IsIdentifier(char c) {
- return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || c == '-' || c == '_';
-}
-
-// Returns to |out| the result of running the "replace placeholders"
-// algorithm on |url_template|. The algorithm is specified at
-// https://wicg.github.io/web-share-target/#dfn-replace-placeholders
-// Does not copy any string data. The resulting vector can be concatenated
-// together with base::StrCat to produce the final string.
-bool ReplacePlaceholders(base::StringPiece template_string,
- const std::map<base::StringPiece, std::string>& data,
- std::vector<base::StringPiece>* out) {
- DCHECK(out);
-
- bool last_saw_open = false;
- size_t start_index_to_copy = 0;
- for (size_t i = 0; i < template_string.size(); ++i) {
- if (last_saw_open) {
- if (template_string[i] == '}') {
- base::StringPiece placeholder = template_string.substr(
- start_index_to_copy + 1, i - 1 - start_index_to_copy);
- auto it = data.find(placeholder);
- if (it != data.end()) {
- // Replace the placeholder text with the parameter value.
- out->push_back(it->second);
- }
-
- last_saw_open = false;
- start_index_to_copy = i + 1;
- } else if (!IsIdentifier(template_string[i])) {
- // Error: Non-identifier character seen after open.
- return false;
- }
- } else {
- if (template_string[i] == '}') {
- // Error: Saw close, with no corresponding open.
- return false;
- } else if (template_string[i] == '{') {
- out->push_back(template_string.substr(start_index_to_copy,
- i - start_index_to_copy));
-
- last_saw_open = true;
- start_index_to_copy = i;
- }
- }
- }
- if (last_saw_open) {
- // Error: Saw open that was never closed.
- return false;
- }
- out->push_back(template_string.substr(
- start_index_to_copy, template_string.size() - start_index_to_copy));
- return true;
-}
-
-} // namespace
-
-bool ValidateWebShareUrlTemplate(const GURL& url_template) {
- return ReplaceWebShareUrlPlaceholders(url_template, /*title=*/"", /*text=*/"",
- /*share_url=*/GURL(),
- /*url_template_filled=*/nullptr);
-}
-
-bool ReplaceWebShareUrlPlaceholders(const GURL& url_template,
- base::StringPiece title,
- base::StringPiece text,
- const GURL& share_url,
- GURL* url_template_filled) {
- constexpr char kTitlePlaceholder[] = "title";
- constexpr char kTextPlaceholder[] = "text";
- constexpr char kUrlPlaceholder[] = "url";
- std::map<base::StringPiece, std::string> replacements;
- replacements[kTitlePlaceholder] = net::EscapeQueryParamValue(title, false);
- replacements[kTextPlaceholder] = net::EscapeQueryParamValue(text, false);
- replacements[kUrlPlaceholder] =
- net::EscapeQueryParamValue(share_url.spec(), false);
-
- std::vector<base::StringPiece> new_query_split;
- std::vector<base::StringPiece> new_ref_split;
- if (!ReplacePlaceholders(url_template.query_piece(), replacements,
- &new_query_split) ||
- !ReplacePlaceholders(url_template.ref_piece(), replacements,
- &new_ref_split)) {
- return false;
- }
-
- // Early-return optimization, since ReplaceWebShareUrlPlaceholders() is called
- // at manifest parse time just to get the success boolean, ignoring the
- // result.
- if (!url_template_filled)
- return true;
-
- // Ensure that the replacements are not deleted prior to
- // GURL::ReplaceComponents() being called. GURL::Replacements::SetQueryStr()
- // does not make a copy.
- std::string new_query = base::StrCat(new_query_split);
- std::string new_ref = base::StrCat(new_ref_split);
-
- // Check whether |url_template| has a query in order to preserve the '?' in
- // a URL with an empty query. e.g. http://www.google.com/?
- GURL::Replacements url_replacements;
- if (url_template.has_query())
- url_replacements.SetQueryStr(new_query);
- if (url_template.has_ref())
- url_replacements.SetRefStr(new_ref);
- *url_template_filled = url_template.ReplaceComponents(url_replacements);
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/manifest_share_target_util.h b/chromium/content/public/common/manifest_share_target_util.h
deleted file mode 100644
index ee46b28b363..00000000000
--- a/chromium/content/public/common/manifest_share_target_util.h
+++ /dev/null
@@ -1,37 +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_PUBLIC_COMMON_MANIFEST_SHARE_TARGET_UTIL_H_
-#define CONTENT_PUBLIC_COMMON_MANIFEST_SHARE_TARGET_UTIL_H_
-
-#include <string>
-
-#include "base/strings/string_piece.h"
-#include "content/common/content_export.h"
-
-class GURL;
-
-namespace content {
-
-// Determines whether |url_template| is valid; that is, whether
-// ReplaceWebShareUrlPlaceholders() would succeed for the given template.
-CONTENT_EXPORT bool ValidateWebShareUrlTemplate(const GURL& url_template);
-
-// Writes to |url_template_filled|, a copy of |url_template| with all
-// instances of "{title}", "{text}", and "{url}" in the query and fragment
-// parts of the URL replaced with |title|, |text|, and |url| respectively.
-// Replaces instances of "{X}" where "X" is any string besides "title",
-// "text", and "url", with an empty string, for forwards compatibility.
-// Returns false, if there are badly nested placeholders.
-// This includes any case in which two "{" occur before a "}", or a "}"
-// occurs with no preceding "{".
-CONTENT_EXPORT bool ReplaceWebShareUrlPlaceholders(const GURL& url_template,
- base::StringPiece title,
- base::StringPiece text,
- const GURL& share_url,
- GURL* url_template_filled);
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_MANIFEST_SHARE_TARGET_UTIL_H_
diff --git a/chromium/content/public/common/manifest_struct_traits.cc b/chromium/content/public/common/manifest_struct_traits.cc
deleted file mode 100644
index 2dfe11bc1df..00000000000
--- a/chromium/content/public/common/manifest_struct_traits.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2017 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/public/common/manifest_struct_traits.h"
-
-#include "mojo/public/cpp/base/string16_mojom_traits.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_enum_traits.h"
-#include "third_party/blink/public/platform/web_display_mode_struct_traits.h"
-#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
-#include "url/mojom/url_gurl_mojom_traits.h"
-
-namespace mojo {
-namespace {
-
-bool ValidateColor(int64_t color) {
- return color >= std::numeric_limits<int32_t>::min() ||
- color <= std::numeric_limits<int32_t>::max() ||
- color == content::Manifest::kInvalidOrMissingColor;
-}
-
-// A wrapper around base::Optional<base::string16> so a custom StructTraits
-// specialization can enforce maximum string length.
-struct TruncatedString16 {
- base::Optional<base::string16> string;
-};
-
-} // namespace
-
-template <>
-struct StructTraits<mojo_base::mojom::String16DataView, TruncatedString16> {
- static void SetToNull(TruncatedString16* output) { output->string.reset(); }
-
- static bool Read(mojo_base::mojom::String16DataView input,
- TruncatedString16* output) {
- if (input.is_null()) {
- output->string.reset();
- return true;
- }
- mojo::ArrayDataView<uint16_t> buffer_view;
- input.GetDataDataView(&buffer_view);
- if (buffer_view.size() > content::Manifest::kMaxIPCStringLength)
- return false;
-
- output->string.emplace();
- return StructTraits<mojo_base::mojom::String16DataView,
- base::string16>::Read(input, &output->string.value());
- }
-};
-
-bool StructTraits<blink::mojom::ManifestDataView, content::Manifest>::Read(
- blink::mojom::ManifestDataView data,
- content::Manifest* out) {
- TruncatedString16 string;
- if (!data.ReadName(&string))
- return false;
- out->name = base::NullableString16(std::move(string.string));
-
- if (!data.ReadShortName(&string))
- return false;
- out->short_name = base::NullableString16(std::move(string.string));
-
- if (!data.ReadGcmSenderId(&string))
- return false;
- out->gcm_sender_id = base::NullableString16(std::move(string.string));
-
- if (!data.ReadStartUrl(&out->start_url))
- return false;
-
- if (!data.ReadIcons(&out->icons))
- return false;
-
- if (!data.ReadShareTarget(&out->share_target))
- return false;
-
- if (!data.ReadRelatedApplications(&out->related_applications))
- return false;
-
- out->prefer_related_applications = data.prefer_related_applications();
- out->theme_color = data.theme_color();
- if (!ValidateColor(out->theme_color))
- return false;
-
- out->background_color = data.background_color();
- if (!ValidateColor(out->background_color))
- return false;
-
- if (!data.ReadSplashScreenUrl(&out->splash_screen_url))
- return false;
-
- if (!data.ReadDisplay(&out->display))
- return false;
-
- if (!data.ReadOrientation(&out->orientation))
- return false;
-
- if (!data.ReadScope(&out->scope))
- return false;
-
- return true;
-}
-
-bool StructTraits<blink::mojom::ManifestIconDataView, content::Manifest::Icon>::
- Read(blink::mojom::ManifestIconDataView data,
- content::Manifest::Icon* out) {
- if (!data.ReadSrc(&out->src))
- return false;
-
- TruncatedString16 string;
- if (!data.ReadType(&string))
- return false;
-
- if (!string.string)
- return false;
-
- out->type = *std::move(string.string);
-
- if (!data.ReadSizes(&out->sizes))
- return false;
-
- if (!data.ReadPurpose(&out->purpose))
- return false;
-
- return true;
-}
-
-bool StructTraits<blink::mojom::ManifestRelatedApplicationDataView,
- content::Manifest::RelatedApplication>::
- Read(blink::mojom::ManifestRelatedApplicationDataView data,
- content::Manifest::RelatedApplication* out) {
- TruncatedString16 string;
- if (!data.ReadPlatform(&string))
- return false;
- out->platform = base::NullableString16(std::move(string.string));
-
- if (!data.ReadUrl(&out->url))
- return false;
-
- if (!data.ReadId(&string))
- return false;
- out->id = base::NullableString16(std::move(string.string));
-
- return !(out->url.is_empty() && out->id.is_null());
-}
-
-bool StructTraits<blink::mojom::ManifestShareTargetDataView,
- content::Manifest::ShareTarget>::
- Read(blink::mojom::ManifestShareTargetDataView data,
- content::Manifest::ShareTarget* out) {
- return data.ReadUrlTemplate(&out->url_template);
-}
-
-} // namespace mojo
diff --git a/chromium/content/public/common/manifest_struct_traits.h b/chromium/content/public/common/manifest_struct_traits.h
index f816251fb1d..ee92dc4e34c 100644
--- a/chromium/content/public/common/manifest_struct_traits.h
+++ b/chromium/content/public/common/manifest_struct_traits.h
@@ -63,12 +63,20 @@ struct StructTraits<blink::mojom::ManifestDataView, content::Manifest> {
return m.orientation;
}
- static int64_t theme_color(const content::Manifest& m) {
- return m.theme_color;
+ static bool has_theme_color(const content::Manifest& m) {
+ return m.theme_color.has_value();
}
- static int64_t background_color(const content::Manifest& m) {
- return m.background_color;
+ static uint32_t theme_color(const content::Manifest& m) {
+ return m.theme_color.value_or(0);
+ }
+
+ static bool has_background_color(const content::Manifest& m) {
+ return m.background_color.has_value();
+ }
+
+ static uint32_t background_color(const content::Manifest& m) {
+ return m.background_color.value_or(0);
}
static const GURL& splash_screen_url(const content::Manifest& m) {
diff --git a/chromium/content/public/common/manifest_util.h b/chromium/content/public/common/manifest_util.h
index 1ebe834a3e5..f6c70ba32b0 100644
--- a/chromium/content/public/common/manifest_util.h
+++ b/chromium/content/public/common/manifest_util.h
@@ -8,8 +8,8 @@
#include <string>
#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_lock_type.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
+#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
namespace content {
diff --git a/chromium/content/public/common/media_stream_request.cc b/chromium/content/public/common/media_stream_request.cc
index 47a1085fd65..d2e688e67d3 100644
--- a/chromium/content/public/common/media_stream_request.cc
+++ b/chromium/content/public/common/media_stream_request.cc
@@ -22,8 +22,7 @@ bool IsVideoMediaType(MediaStreamType type) {
}
bool IsScreenCaptureMediaType(MediaStreamType type) {
- return (type == MEDIA_TAB_AUDIO_CAPTURE ||
- type == MEDIA_TAB_VIDEO_CAPTURE ||
+ return (type == MEDIA_TAB_AUDIO_CAPTURE || type == MEDIA_TAB_VIDEO_CAPTURE ||
type == MEDIA_DESKTOP_AUDIO_CAPTURE ||
type == MEDIA_DESKTOP_VIDEO_CAPTURE);
}
@@ -40,21 +39,19 @@ MediaStreamDevice::MediaStreamDevice(MediaStreamType type,
: type(type),
id(id),
video_facing(media::MEDIA_VIDEO_FACING_NONE),
- name(name) {
-#if defined(OS_ANDROID)
- if (name.find("front") != std::string::npos) {
- video_facing = media::MEDIA_VIDEO_FACING_USER;
- } else if (name.find("back") != std::string::npos) {
- video_facing = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
- }
-#endif
-}
-
-MediaStreamDevice::MediaStreamDevice(MediaStreamType type,
- const std::string& id,
- const std::string& name,
- media::VideoFacingMode facing)
- : type(type), id(id), video_facing(facing), name(name) {}
+ name(name) {}
+
+MediaStreamDevice::MediaStreamDevice(
+ MediaStreamType type,
+ const std::string& id,
+ const std::string& name,
+ media::VideoFacingMode facing,
+ const base::Optional<std::string>& group_id)
+ : type(type),
+ id(id),
+ video_facing(facing),
+ group_id(group_id),
+ name(name) {}
MediaStreamDevice::MediaStreamDevice(MediaStreamType type,
const std::string& id,
@@ -69,7 +66,6 @@ MediaStreamDevice::MediaStreamDevice(MediaStreamType type,
input(media::AudioParameters::AUDIO_FAKE,
static_cast<media::ChannelLayout>(channel_layout),
sample_rate,
- 16,
frames_per_buffer) {
DCHECK(input.IsValid());
}
diff --git a/chromium/content/public/common/media_stream_request.h b/chromium/content/public/common/media_stream_request.h
index fedfe072de9..9ea6103ed5c 100644
--- a/chromium/content/public/common/media_stream_request.h
+++ b/chromium/content/public/common/media_stream_request.h
@@ -91,10 +91,12 @@ struct CONTENT_EXPORT MediaStreamDevice {
const std::string& id,
const std::string& name);
- MediaStreamDevice(MediaStreamType type,
- const std::string& id,
- const std::string& name,
- media::VideoFacingMode facing);
+ MediaStreamDevice(
+ MediaStreamType type,
+ const std::string& id,
+ const std::string& name,
+ media::VideoFacingMode facing,
+ const base::Optional<std::string>& group_id = base::nullopt);
MediaStreamDevice(MediaStreamType type,
const std::string& id,
@@ -118,6 +120,9 @@ struct CONTENT_EXPORT MediaStreamDevice {
// The facing mode for video capture device.
media::VideoFacingMode video_facing;
+ // The device's group ID.
+ base::Optional<std::string> group_id;
+
// The device id of a matched output device if any (otherwise empty).
// Only applicable to audio devices.
base::Optional<std::string> matched_output_device_id;
diff --git a/chromium/content/public/common/mojo_channel_switches.cc b/chromium/content/public/common/mojo_channel_switches.cc
deleted file mode 100644
index 9cd2c3c1bb5..00000000000
--- a/chromium/content/public/common/mojo_channel_switches.cc
+++ /dev/null
@@ -1,13 +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.
-
-#include "content/public/common/mojo_channel_switches.h"
-
-namespace switches {
-
-// The token to use to construct the message pipe for a service in a child
-// process.
-const char kServiceRequestChannelToken[] = "service-request-channel-token";
-
-} // namespace switches
diff --git a/chromium/content/public/common/mojo_channel_switches.h b/chromium/content/public/common/mojo_channel_switches.h
deleted file mode 100644
index 954a86f691c..00000000000
--- a/chromium/content/public/common/mojo_channel_switches.h
+++ /dev/null
@@ -1,16 +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 CONTENT_PUBLIC_COMMON_MOJO_CHANNEL_SWITCHES_H_
-#define CONTENT_PUBLIC_COMMON_MOJO_CHANNEL_SWITCHES_H_
-
-#include "content/common/content_export.h"
-
-namespace switches {
-
-CONTENT_EXPORT extern const char kServiceRequestChannelToken[];
-
-} // namespace switches
-
-#endif // CONTENT_PUBLIC_COMMON_MOJO_CHANNEL_SWITCHES_H_
diff --git a/chromium/content/public/common/origin_trial_policy.cc b/chromium/content/public/common/origin_trial_policy.cc
deleted file mode 100644
index 76472c94b29..00000000000
--- a/chromium/content/public/common/origin_trial_policy.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 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/public/common/origin_trial_policy.h"
-
-namespace content {
-
-base::StringPiece OriginTrialPolicy::GetPublicKey() const {
- return base::StringPiece();
-}
-
-bool OriginTrialPolicy::IsFeatureDisabled(base::StringPiece feature) const {
- return false;
-}
-
-bool OriginTrialPolicy::IsTokenDisabled(
- base::StringPiece token_signature) const {
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/origin_trial_policy.h b/chromium/content/public/common/origin_trial_policy.h
deleted file mode 100644
index 5368e6dea9b..00000000000
--- a/chromium/content/public/common/origin_trial_policy.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 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_PUBLIC_COMMON_ORIGIN_TRIAL_POLICY_H_
-#define CONTENT_PUBLIC_COMMON_ORIGIN_TRIAL_POLICY_H_
-
-#include "base/strings/string_piece.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class CONTENT_EXPORT OriginTrialPolicy {
- public:
- virtual ~OriginTrialPolicy() = default;
-
- virtual void Initialize() {}
- virtual base::StringPiece GetPublicKey() const;
- virtual bool IsFeatureDisabled(base::StringPiece feature) const;
- virtual bool IsTokenDisabled(base::StringPiece token_signature) const;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_ORIGIN_TRIAL_POLICY_H_
diff --git a/chromium/content/public/common/page_state.h b/chromium/content/public/common/page_state.h
index 6cf6c09116e..c630e6bcf30 100644
--- a/chromium/content/public/common/page_state.h
+++ b/chromium/content/public/common/page_state.h
@@ -53,20 +53,18 @@ class CONTENT_EXPORT PageState {
PageState RemoveScrollOffset() const;
PageState RemoveReferrer() const;
+ // Support DCHECK_EQ(a, b), etc.
+ bool operator==(const PageState& other) const { return this->Equals(other); }
+ bool operator!=(const PageState& other) const {
+ return !(this->Equals(other));
+ }
+
private:
PageState(const std::string& data);
std::string data_;
};
-// Support DCHECK_EQ(a, b), etc.
-inline bool operator==(const PageState& a, const PageState& b) {
- return a.Equals(b);
-}
-inline bool operator!=(const PageState& a, const PageState& b) {
- return !(a == b);
-}
-
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_PAGE_STATE_H_
diff --git a/chromium/content/public/common/platform_notification_data.h b/chromium/content/public/common/platform_notification_data.h
index 74049011c9b..c6bd563401e 100644
--- a/chromium/content/public/common/platform_notification_data.h
+++ b/chromium/content/public/common/platform_notification_data.h
@@ -56,10 +56,6 @@ struct CONTENT_EXPORT PlatformNotificationData {
PlatformNotificationData(const PlatformNotificationData& other);
~PlatformNotificationData();
- // The maximum size of developer-provided data to be stored in the |data|
- // property of this structure.
- static const size_t kMaximumDeveloperDataSize = 1024 * 1024;
-
enum Direction {
DIRECTION_LEFT_TO_RIGHT,
DIRECTION_RIGHT_TO_LEFT,
diff --git a/chromium/content/public/common/presentation_info.cc b/chromium/content/public/common/presentation_info.cc
deleted file mode 100644
index 09cff09e76b..00000000000
--- a/chromium/content/public/common/presentation_info.cc
+++ /dev/null
@@ -1,24 +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.
-
-#include "content/public/common/presentation_info.h"
-
-namespace content {
-
-PresentationInfo::PresentationInfo(const GURL& presentation_url,
- const std::string& presentation_id)
- : presentation_url(presentation_url), presentation_id(presentation_id) {}
-
-PresentationInfo::~PresentationInfo() {}
-
-PresentationError::PresentationError()
- : error_type(PRESENTATION_ERROR_UNKNOWN) {}
-
-PresentationError::PresentationError(PresentationErrorType error_type,
- const std::string& message)
- : error_type(error_type), message(message) {}
-
-PresentationError::~PresentationError() {}
-
-} // namespace content
diff --git a/chromium/content/public/common/presentation_info.h b/chromium/content/public/common/presentation_info.h
deleted file mode 100644
index 5adb0f54f66..00000000000
--- a/chromium/content/public/common/presentation_info.h
+++ /dev/null
@@ -1,69 +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 CONTENT_PUBLIC_COMMON_PRESENTATION_INFO_H_
-#define CONTENT_PUBLIC_COMMON_PRESENTATION_INFO_H_
-
-#include <string>
-
-#include "content/common/content_export.h"
-#include "url/gurl.h"
-
-namespace content {
-
-enum PresentationConnectionState {
- PRESENTATION_CONNECTION_STATE_CONNECTING,
- PRESENTATION_CONNECTION_STATE_CONNECTED,
- PRESENTATION_CONNECTION_STATE_CLOSED,
- PRESENTATION_CONNECTION_STATE_TERMINATED
-};
-
-// TODO(imcheng): Use WENT_AWAY for 1-UA mode when it is implemented
-// (crbug.com/513859).
-enum PresentationConnectionCloseReason {
- PRESENTATION_CONNECTION_CLOSE_REASON_CONNECTION_ERROR,
- PRESENTATION_CONNECTION_CLOSE_REASON_CLOSED,
- PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY
-};
-
-// Represents a presentation that has been established via either
-// browser actions or Presentation API.
-struct CONTENT_EXPORT PresentationInfo {
- PresentationInfo() = default;
- PresentationInfo(const GURL& presentation_url,
- const std::string& presentation_id);
- ~PresentationInfo();
-
- static constexpr size_t kMaxIdLength = 256;
-
- GURL presentation_url;
- std::string presentation_id;
-};
-
-// Possible reasons why an attempt to create a presentation failed.
-enum PresentationErrorType {
- PRESENTATION_ERROR_NO_AVAILABLE_SCREENS,
- PRESENTATION_ERROR_PRESENTATION_REQUEST_CANCELLED,
- PRESENTATION_ERROR_NO_PRESENTATION_FOUND,
- PRESENTATION_ERROR_PREVIOUS_START_IN_PROGRESS,
- PRESENTATION_ERROR_UNKNOWN,
-};
-
-// Struct returned when an attempt to create a presentation fails.
-// Defaults to PRESENTATION_ERROR_UNKNOWN with an empty message.
-struct CONTENT_EXPORT PresentationError {
- PresentationError();
- PresentationError(PresentationErrorType error_type,
- const std::string& message);
- ~PresentationError();
-
- static constexpr size_t kMaxMessageLength = 256;
-
- PresentationErrorType error_type;
- std::string message;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_PRESENTATION_INFO_H_
diff --git a/chromium/content/public/common/resource_load_info.mojom b/chromium/content/public/common/resource_load_info.mojom
index c6926fdacaa..9305cbaf6e0 100644
--- a/chromium/content/public/common/resource_load_info.mojom
+++ b/chromium/content/public/common/resource_load_info.mojom
@@ -4,11 +4,34 @@
module content.mojom;
+import "content/public/common/load_timing_info.mojom";
import "content/public/common/resource_type.mojom";
-import "mojo/public/mojom/base/time.mojom";
import "net/interfaces/ip_address.mojom";
+import "services/network/public/mojom/network_param.mojom";
import "url/mojom/url.mojom";
+// Network related information reported for loads and redirects.
+struct CommonNetworkInfo {
+ // True if the request accessed the network in the process of retrieving data.
+ bool network_accessed;
+
+ // True if loading this resource always requires accessing the network, either
+ // because it should always be revalidated or because it should not be cached.
+ bool always_access_network;
+
+ // The host IP and port of the response.
+ network.mojom.HostPortPair? ip_port_pair;
+};
+
+// Information for a redirect.
+struct RedirectInfo {
+ // The URL after the redirect.
+ url.mojom.Url url;
+
+ // Various network related information.
+ CommonNetworkInfo network_info;
+};
+
// Information pertaining to resource loading.
// This will be passed to ResourceResponse callback methods.
struct ResourceLoadInfo {
@@ -34,18 +57,29 @@ struct ResourceLoadInfo {
// The mime type.
string mime_type;
- // The host IP.
- net.interfaces.IPAddress? ip;
-
// True if the response was fetched from the network cache.
bool was_cached;
- // True if the request accessed the network in the process of retrieving data.
- bool network_accessed;
+ // Various network related information.
+ CommonNetworkInfo network_info;
// The network error code, net::OK if no error happened.
int32 net_error;
- // The time at which the request was started.
- mojo_base.mojom.TimeTicks request_start;
+ // The timing info.
+ content.mojom.LoadTimingInfo load_timing_info;
+
+ // The size of the response body before removing any content encodings.
+ // Does not include redirects or sub-requests issued at lower levels (range
+ // requests or auth). Does include bytes from the cache.
+ int64 raw_body_bytes;
+
+ // The total amount of data received from network after SSL decoding and proxy
+ // handling. Pertains only to the last request, i.e. reset on redirects, but
+ // not reset when multiple roundtrips are used for range requests or auth.
+ int64 total_received_bytes;
+
+ // The list of redirects that led to this resource load. Empty if there were
+ // no redirects.
+ array<RedirectInfo> redirect_info_chain;
};
diff --git a/chromium/content/public/common/result_codes.h b/chromium/content/public/common/result_codes.h
index cd66a5bdc42..a0b0b7482e9 100644
--- a/chromium/content/public/common/result_codes.h
+++ b/chromium/content/public/common/result_codes.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_PUBLIC_COMMON_RESULT_CODES_H_
#define CONTENT_PUBLIC_COMMON_RESULT_CODES_H_
+#include "services/service_manager/embedder/result_codes.h"
+
namespace content {
// This file consolidates all the return codes for the browser and renderer
@@ -28,11 +30,10 @@ namespace content {
// TODO(wfh): Break the dependency so it is possible to add more values.
enum ResultCode {
- // Process terminated normally.
- RESULT_CODE_NORMAL_EXIT,
+ RESULT_CODE_CONTENT_START = service_manager::RESULT_CODE_LAST_CODE,
// Process was killed by user or system.
- RESULT_CODE_KILLED,
+ RESULT_CODE_KILLED = RESULT_CODE_CONTENT_START,
// Process hung.
RESULT_CODE_HUNG,
diff --git a/chromium/content/public/common/sandboxed_process_launcher_delegate.cc b/chromium/content/public/common/sandboxed_process_launcher_delegate.cc
index 2574f49e44b..1b3d27134ee 100644
--- a/chromium/content/public/common/sandboxed_process_launcher_delegate.cc
+++ b/chromium/content/public/common/sandboxed_process_launcher_delegate.cc
@@ -5,11 +5,7 @@
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "build/build_config.h"
-#include "content/public/common/zygote_buildflags.h"
-
-#if BUILDFLAG(USE_ZYGOTE_HANDLE)
-#include "content/public/common/zygote_handle.h"
-#endif
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
namespace content {
@@ -37,7 +33,7 @@ bool SandboxedProcessLauncherDelegate::ShouldLaunchElevated() {
#endif // defined(OS_WIN)
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
-ZygoteHandle SandboxedProcessLauncherDelegate::GetZygote() {
+service_manager::ZygoteHandle SandboxedProcessLauncherDelegate::GetZygote() {
return nullptr;
}
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
diff --git a/chromium/content/public/common/sandboxed_process_launcher_delegate.h b/chromium/content/public/common/sandboxed_process_launcher_delegate.h
index 80043c88767..644e461607c 100644
--- a/chromium/content/public/common/sandboxed_process_launcher_delegate.h
+++ b/chromium/content/public/common/sandboxed_process_launcher_delegate.h
@@ -10,12 +10,12 @@
#include "base/process/process.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
-#include "content/public/common/zygote_buildflags.h"
#include "services/service_manager/sandbox/sandbox_delegate.h"
#include "services/service_manager/sandbox/sandbox_type.h"
+#include "services/service_manager/zygote/common/zygote_buildflags.h"
#if BUILDFLAG(USE_ZYGOTE_HANDLE)
-#include "content/public/common/zygote_handle.h"
+#include "services/service_manager/zygote/common/zygote_handle.h" // nogncheck
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
namespace content {
@@ -45,7 +45,7 @@ class CONTENT_EXPORT SandboxedProcessLauncherDelegate
// Returns the zygote used to launch the process.
// NOTE: For now Chrome always uses the same zygote for performance reasons.
// http://crbug.com/569191
- virtual ZygoteHandle GetZygote();
+ virtual service_manager::ZygoteHandle GetZygote();
#endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
#if defined(OS_POSIX)
diff --git a/chromium/content/public/common/send_zygote_child_ping_linux.h b/chromium/content/public/common/send_zygote_child_ping_linux.h
deleted file mode 100644
index ae971a1b290..00000000000
--- a/chromium/content/public/common/send_zygote_child_ping_linux.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 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_PUBLIC_COMMON_SEND_ZYGOTE_CHILD_PING_LINUX_H_
-#define CONTENT_PUBLIC_COMMON_SEND_ZYGOTE_CHILD_PING_LINUX_H_
-
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Sends a zygote child "ping" message to browser process via socket |fd|.
-// Returns true on success.
-CONTENT_EXPORT bool SendZygoteChildPing(int fd);
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_SEND_ZYGOTE_CHILD_PING_LINUX_H_
diff --git a/chromium/content/public/common/speech_recognition_error.h b/chromium/content/public/common/speech_recognition_error.h
index 7456a43f204..34aa16de1c2 100644
--- a/chromium/content/public/common/speech_recognition_error.h
+++ b/chromium/content/public/common/speech_recognition_error.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_ERROR_H_
#define CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_ERROR_H_
+#include "content/common/content_export.h"
+
namespace content {
// A Java counterpart will be generated for this enum.
diff --git a/chromium/content/public/common/speech_recognition_error.mojom b/chromium/content/public/common/speech_recognition_error.mojom
new file mode 100644
index 00000000000..31f28a46d87
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_error.mojom
@@ -0,0 +1,34 @@
+// 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.
+
+module content.mojom;
+
+// TODO(adithyas): Update users of content::SpeechRecognitionErrorCode to use
+// this instead, then remove content::SpeechRecognitionErrorCode.
+enum SpeechRecognitionErrorCode {
+ kNone,
+ kNoSpeech,
+ kAborted,
+ kAudioCapture,
+ kNetwork,
+ kNotAllowed,
+ kServiceNotAllowed,
+ kBadGrammar,
+ kLanguageNotSupported,
+ kNoMatch
+};
+
+// TODO(adithyas): Update users of content::SpeechAudioErrorDetails to use
+// this instead, then remove content::SpeechAudioErrorDetails.
+enum SpeechAudioErrorDetails {
+ kNone,
+ kNoMic
+};
+
+// TODO(adithyas): Update users of content::SpeechRecognitionError to use
+// this instead, then remove content::SpeechRecognitionError.
+struct SpeechRecognitionError {
+ content.mojom.SpeechRecognitionErrorCode code;
+ content.mojom.SpeechAudioErrorDetails details;
+};
diff --git a/chromium/content/public/common/speech_recognition_error.typemap b/chromium/content/public/common/speech_recognition_error.typemap
new file mode 100644
index 00000000000..4b99fa73245
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_error.typemap
@@ -0,0 +1,14 @@
+# 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 = "//content/public/common/speech_recognition_error.mojom"
+public_headers = [ "//content/public/common/speech_recognition_error.h" ]
+traits_headers =
+ [ "//content/public/common/speech_recognition_error_struct_traits.h" ]
+sources = [
+ "//content/public/common/speech_recognition_error_struct_traits.cc",
+]
+deps = []
+type_mappings =
+ [ "content.mojom.SpeechRecognitionError=content::SpeechRecognitionError" ]
diff --git a/chromium/content/public/common/speech_recognition_error_struct_traits.cc b/chromium/content/public/common/speech_recognition_error_struct_traits.cc
new file mode 100644
index 00000000000..19720639dd1
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_error_struct_traits.cc
@@ -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.
+
+#include "content/public/common/speech_recognition_error_struct_traits.h"
+
+namespace mojo {
+
+bool StructTraits<content::mojom::SpeechRecognitionErrorDataView,
+ content::SpeechRecognitionError>::
+ Read(content::mojom::SpeechRecognitionErrorDataView data,
+ content::SpeechRecognitionError* out) {
+ if (!data.ReadCode(&out->code)) {
+ return false;
+ }
+ if (!data.ReadDetails(&out->details)) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/content/public/common/speech_recognition_error_struct_traits.h b/chromium/content/public/common/speech_recognition_error_struct_traits.h
new file mode 100644
index 00000000000..c863e5a698b
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_error_struct_traits.h
@@ -0,0 +1,152 @@
+// 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_PUBLIC_COMMON_SPEECH_RECOGNITION_ERROR_STRUCT_TRAITS_H_
+#define CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_ERROR_STRUCT_TRAITS_H_
+
+#include "content/public/common/speech_recognition_error.h"
+#include "content/public/common/speech_recognition_error.mojom.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<content::mojom::SpeechRecognitionErrorCode,
+ content::SpeechRecognitionErrorCode> {
+ static content::mojom::SpeechRecognitionErrorCode ToMojom(
+ content::SpeechRecognitionErrorCode input) {
+ switch (input) {
+ case content::SpeechRecognitionErrorCode::SPEECH_RECOGNITION_ERROR_NONE:
+ return content::mojom::SpeechRecognitionErrorCode::kNone;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NO_SPEECH:
+ return content::mojom::SpeechRecognitionErrorCode::kNoSpeech;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_ABORTED:
+ return content::mojom::SpeechRecognitionErrorCode::kAborted;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE:
+ return content::mojom::SpeechRecognitionErrorCode::kAudioCapture;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NETWORK:
+ return content::mojom::SpeechRecognitionErrorCode::kNetwork;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NOT_ALLOWED:
+ return content::mojom::SpeechRecognitionErrorCode::kNotAllowed;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_SERVICE_NOT_ALLOWED:
+ return content::mojom::SpeechRecognitionErrorCode::kServiceNotAllowed;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR:
+ return content::mojom::SpeechRecognitionErrorCode::kBadGrammar;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_LANGUAGE_NOT_SUPPORTED:
+ return content::mojom::SpeechRecognitionErrorCode::
+ kLanguageNotSupported;
+ case content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NO_MATCH:
+ return content::mojom::SpeechRecognitionErrorCode::kNoMatch;
+ }
+ NOTREACHED();
+ return content::mojom::SpeechRecognitionErrorCode::kNoMatch;
+ }
+
+ static bool FromMojom(content::mojom::SpeechRecognitionErrorCode input,
+ content::SpeechRecognitionErrorCode* output) {
+ switch (input) {
+ case content::mojom::SpeechRecognitionErrorCode::kNone:
+ *output =
+ content::SpeechRecognitionErrorCode::SPEECH_RECOGNITION_ERROR_NONE;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kNoSpeech:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NO_SPEECH;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kAborted:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_ABORTED;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kAudioCapture:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kNetwork:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NETWORK;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kNotAllowed:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NOT_ALLOWED;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kServiceNotAllowed:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_SERVICE_NOT_ALLOWED;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kBadGrammar:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kLanguageNotSupported:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_LANGUAGE_NOT_SUPPORTED;
+ return true;
+ case content::mojom::SpeechRecognitionErrorCode::kNoMatch:
+ *output = content::SpeechRecognitionErrorCode::
+ SPEECH_RECOGNITION_ERROR_NO_MATCH;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+};
+
+template <>
+struct EnumTraits<content::mojom::SpeechAudioErrorDetails,
+ content::SpeechAudioErrorDetails> {
+ static content::mojom::SpeechAudioErrorDetails ToMojom(
+ content::SpeechAudioErrorDetails input) {
+ switch (input) {
+ case content::SpeechAudioErrorDetails::SPEECH_AUDIO_ERROR_DETAILS_NONE:
+ return content::mojom::SpeechAudioErrorDetails::kNone;
+ case content::SpeechAudioErrorDetails::SPEECH_AUDIO_ERROR_DETAILS_NO_MIC:
+ return content::mojom::SpeechAudioErrorDetails::kNoMic;
+ }
+ NOTREACHED();
+ return content::mojom::SpeechAudioErrorDetails::kNoMic;
+ }
+
+ static bool FromMojom(content::mojom::SpeechAudioErrorDetails input,
+ content::SpeechAudioErrorDetails* output) {
+ switch (input) {
+ case content::mojom::SpeechAudioErrorDetails::kNone:
+ *output =
+ content::SpeechAudioErrorDetails::SPEECH_AUDIO_ERROR_DETAILS_NONE;
+ return true;
+ case content::mojom::SpeechAudioErrorDetails::kNoMic:
+ *output =
+ content::SpeechAudioErrorDetails::SPEECH_AUDIO_ERROR_DETAILS_NO_MIC;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+};
+
+template <>
+struct StructTraits<content::mojom::SpeechRecognitionErrorDataView,
+ content::SpeechRecognitionError> {
+ static content::SpeechRecognitionErrorCode code(
+ const content::SpeechRecognitionError& r) {
+ return r.code;
+ }
+ static content::SpeechAudioErrorDetails details(
+ const content::SpeechRecognitionError& r) {
+ return r.details;
+ }
+ static bool Read(content::mojom::SpeechRecognitionErrorDataView data,
+ content::SpeechRecognitionError* out);
+};
+
+} // namespace mojo
+
+#endif // CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_ERROR_STRUCT_TRAITS_H_
diff --git a/chromium/content/public/common/speech_recognition_grammar.h b/chromium/content/public/common/speech_recognition_grammar.h
deleted file mode 100644
index 0621a56259c..00000000000
--- a/chromium/content/public/common/speech_recognition_grammar.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_GRAMMAR_H_
-#define CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_GRAMMAR_H_
-
-#include <vector>
-
-#include "content/common/content_export.h"
-
-namespace content {
-
-struct CONTENT_EXPORT SpeechRecognitionGrammar {
- SpeechRecognitionGrammar()
- : weight(0.0f) {
- }
- explicit SpeechRecognitionGrammar(const std::string& url_value)
- : url(url_value),
- weight(0.0f) {
- }
- SpeechRecognitionGrammar(const std::string& url_value, double weight_value)
- : url(url_value),
- weight(weight_value) {
- }
-
- std::string url;
- double weight;
-};
-
-typedef std::vector<SpeechRecognitionGrammar> SpeechRecognitionGrammarArray;
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_GRAMMAR_H_
diff --git a/chromium/content/public/common/speech_recognition_grammar.mojom b/chromium/content/public/common/speech_recognition_grammar.mojom
new file mode 100644
index 00000000000..fbb0bb2cbfe
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_grammar.mojom
@@ -0,0 +1,12 @@
+// 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.
+
+module content.mojom;
+
+import "url/mojom/url.mojom";
+
+struct SpeechRecognitionGrammar {
+ url.mojom.Url url;
+ double weight;
+};
diff --git a/chromium/content/public/common/speech_recognition_result.mojom b/chromium/content/public/common/speech_recognition_result.mojom
new file mode 100644
index 00000000000..8bc5b6c55c1
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_result.mojom
@@ -0,0 +1,29 @@
+// 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.
+
+module content.mojom;
+
+import "mojo/public/mojom/base/string16.mojom";
+
+// A single hypothesis indicating what the recognition service thinks a
+// particular speech segment means.
+struct SpeechRecognitionHypothesis {
+ // Transcript of spoken text.
+ mojo_base.mojom.String16 utterance;
+
+ // A numeric estimate between 0 and 1 that represents how confident the
+ // recognition system is that the recognition is correct.
+ double confidence;
+};
+
+// Group of recognition hypotheses for a particular speech segment.
+struct SpeechRecognitionResult {
+ // An N-best list of hypotheses.
+ array<content.mojom.SpeechRecognitionHypothesis> hypotheses;
+
+ // False if this is the final time the speech service will return this
+ // particular result. If true, then this represents an interim result that
+ // could still be changed.
+ bool is_provisional;
+};
diff --git a/chromium/content/public/common/speech_recognition_result.typemap b/chromium/content/public/common/speech_recognition_result.typemap
new file mode 100644
index 00000000000..ac03718a8d6
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_result.typemap
@@ -0,0 +1,16 @@
+# 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 = "//content/public/common/speech_recognition_result.mojom"
+public_headers = [ "//content/public/common/speech_recognition_result.h" ]
+traits_headers =
+ [ "//content/public/common/speech_recognition_result_struct_traits.h" ]
+sources = [
+ "//content/public/common/speech_recognition_result_struct_traits.cc",
+]
+deps = []
+type_mappings = [
+ "content.mojom.SpeechRecognitionHypothesis=content::SpeechRecognitionHypothesis",
+ "content.mojom.SpeechRecognitionResult=content::SpeechRecognitionResult",
+]
diff --git a/chromium/content/public/common/speech_recognition_result_struct_traits.cc b/chromium/content/public/common/speech_recognition_result_struct_traits.cc
new file mode 100644
index 00000000000..1c1e06d1f08
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_result_struct_traits.cc
@@ -0,0 +1,29 @@
+// 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/public/common/speech_recognition_result_struct_traits.h"
+
+namespace mojo {
+
+bool StructTraits<content::mojom::SpeechRecognitionHypothesisDataView,
+ content::SpeechRecognitionHypothesis>::
+ Read(content::mojom::SpeechRecognitionHypothesisDataView data,
+ content::SpeechRecognitionHypothesis* out) {
+ if (!data.ReadUtterance(&out->utterance))
+ return false;
+ out->confidence = data.confidence();
+ return true;
+}
+
+bool StructTraits<content::mojom::SpeechRecognitionResultDataView,
+ content::SpeechRecognitionResult>::
+ Read(content::mojom::SpeechRecognitionResultDataView data,
+ content::SpeechRecognitionResult* out) {
+ if (!data.ReadHypotheses(&out->hypotheses))
+ return false;
+ out->is_provisional = data.is_provisional();
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/content/public/common/speech_recognition_result_struct_traits.h b/chromium/content/public/common/speech_recognition_result_struct_traits.h
new file mode 100644
index 00000000000..53b84eb0da0
--- /dev/null
+++ b/chromium/content/public/common/speech_recognition_result_struct_traits.h
@@ -0,0 +1,47 @@
+// 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_PUBLIC_COMMON_SPEECH_RECOGNITION_RESULT_STRUCT_TRAITS_H_
+#define CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_RESULT_STRUCT_TRAITS_H_
+
+#include "content/public/common/speech_recognition_result.h"
+#include "content/public/common/speech_recognition_result.mojom.h"
+#include "mojo/public/cpp/base/string16_mojom_traits.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<content::mojom::SpeechRecognitionHypothesisDataView,
+ content::SpeechRecognitionHypothesis> {
+ static const base::string16& utterance(
+ const content::SpeechRecognitionHypothesis& r) {
+ return r.utterance;
+ }
+ static double confidence(const content::SpeechRecognitionHypothesis& r) {
+ return r.confidence;
+ }
+ static bool Read(content::mojom::SpeechRecognitionHypothesisDataView data,
+ content::SpeechRecognitionHypothesis* out);
+};
+
+template <>
+struct StructTraits<content::mojom::SpeechRecognitionResultDataView,
+ content::SpeechRecognitionResult> {
+ static const std::vector<content::SpeechRecognitionHypothesis>& hypotheses(
+ const content::SpeechRecognitionResult& r) {
+ return r.hypotheses;
+ }
+
+ static bool is_provisional(const content::SpeechRecognitionResult& r) {
+ return r.is_provisional;
+ }
+
+ static bool Read(content::mojom::SpeechRecognitionResultDataView data,
+ content::SpeechRecognitionResult* out);
+};
+
+} // namespace mojo
+
+#endif // CONTENT_PUBLIC_COMMON_SPEECH_RECOGNITION_RESULT_STRUCT_TRAITS_H_
diff --git a/chromium/content/public/common/stop_find_action.h b/chromium/content/public/common/stop_find_action.h
index 0088eec3ea6..399c4be6e30 100644
--- a/chromium/content/public/common/stop_find_action.h
+++ b/chromium/content/public/common/stop_find_action.h
@@ -5,15 +5,22 @@
#ifndef CONTENT_PUBLIC_COMMON_STOP_FIND_ACTION_H_
#define CONTENT_PUBLIC_COMMON_STOP_FIND_ACTION_H_
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+
namespace content {
+// DEPRECATED - For future usage, use blink::mojom::StopFindAction directly.
// The user has completed a find-in-page; this type defines what actions the
// renderer should take next.
enum StopFindAction {
- STOP_FIND_ACTION_CLEAR_SELECTION,
- STOP_FIND_ACTION_KEEP_SELECTION,
- STOP_FIND_ACTION_ACTIVATE_SELECTION,
- STOP_FIND_ACTION_LAST = STOP_FIND_ACTION_ACTIVATE_SELECTION
+ STOP_FIND_ACTION_CLEAR_SELECTION = static_cast<int>(
+ blink::mojom::StopFindAction::kStopFindActionClearSelection),
+ STOP_FIND_ACTION_KEEP_SELECTION = static_cast<int>(
+ blink::mojom::StopFindAction::kStopFindActionKeepSelection),
+ STOP_FIND_ACTION_ACTIVATE_SELECTION = static_cast<int>(
+ blink::mojom::StopFindAction::kStopFindActionActivateSelection),
+ STOP_FIND_ACTION_LAST =
+ static_cast<int>(blink::mojom::StopFindAction::kMaxValue)
};
} // namespace content
diff --git a/chromium/content/public/common/typemaps.gni b/chromium/content/public/common/typemaps.gni
index 5d4fc4d71a9..ae8d8a0e219 100644
--- a/chromium/content/public/common/typemaps.gni
+++ b/chromium/content/public/common/typemaps.gni
@@ -3,8 +3,10 @@
# found in the LICENSE file.
typemaps = [
- "//content/public/common/manifest.typemap",
+ "//content/public/common/load_timing_info.typemap",
"//content/public/common/referrer.typemap",
"//content/public/common/resource_type.typemap",
+ "//content/public/common/speech_recognition_result.typemap",
+ "//content/public/common/speech_recognition_error.typemap",
"//content/public/common/webplugininfo.typemap",
]
diff --git a/chromium/content/public/common/url_constants.cc b/chromium/content/public/common/url_constants.cc
index ece77d53898..e85d54e2990 100644
--- a/chromium/content/public/common/url_constants.cc
+++ b/chromium/content/public/common/url_constants.cc
@@ -32,6 +32,7 @@ const char kChromeUIMediaInternalsHost[] = "media-internals";
const char kChromeUIMemoryExhaustHost[] = "memory-exhaust";
const char kChromeUINetworkErrorHost[] = "network-error";
const char kChromeUINetworkErrorsListingHost[] = "network-errors";
+const char kChromeUIProcessInternalsHost[] = "process-internals";
const char kChromeUIResourcesHost[] = "resources";
const char kChromeUIServiceWorkerInternalsHost[] = "serviceworker-internals";
const char kChromeUITracingHost[] = "tracing";
@@ -54,6 +55,7 @@ const char kChromeUINetworkErrorURL[] = "chrome://network-error/";
const char kChromeUINetworkErrorsListingURL[] = "chrome://network-errors/";
const char kChromeUIPpapiFlashCrashURL[] = "chrome://ppapiflashcrash/";
const char kChromeUIPpapiFlashHangURL[] = "chrome://ppapiflashhang/";
+const char kChromeUIProcessInternalsURL[] = "chrome://process-internals";
#if defined(OS_ANDROID)
const char kChromeUIGpuJavaCrashURL[] = "chrome://gpu-java-crash/";
#endif
diff --git a/chromium/content/public/common/url_constants.h b/chromium/content/public/common/url_constants.h
index 67009beda0d..0da500fb484 100644
--- a/chromium/content/public/common/url_constants.h
+++ b/chromium/content/public/common/url_constants.h
@@ -41,6 +41,7 @@ CONTENT_EXPORT extern const char kChromeUIMediaInternalsHost[];
CONTENT_EXPORT extern const char kChromeUIMemoryExhaustHost[];
CONTENT_EXPORT extern const char kChromeUINetworkErrorHost[];
CONTENT_EXPORT extern const char kChromeUINetworkErrorsListingHost[];
+CONTENT_EXPORT extern const char kChromeUIProcessInternalsHost[];
CONTENT_EXPORT extern const char kChromeUIResourcesHost[];
CONTENT_EXPORT extern const char kChromeUIServiceWorkerInternalsHost[];
CONTENT_EXPORT extern const char kChromeUITracingHost[];
@@ -64,6 +65,7 @@ CONTENT_EXPORT extern const char kChromeUINetworkErrorsListingURL[];
CONTENT_EXPORT extern const char kChromeUINetworkErrorURL[];
CONTENT_EXPORT extern const char kChromeUIPpapiFlashCrashURL[];
CONTENT_EXPORT extern const char kChromeUIPpapiFlashHangURL[];
+CONTENT_EXPORT extern const char kChromeUIProcessInternalsURL[];
#if defined(OS_ANDROID)
CONTENT_EXPORT extern const char kChromeUIGpuJavaCrashURL[];
#endif
diff --git a/chromium/content/public/common/weak_wrapper_shared_url_loader_factory.cc b/chromium/content/public/common/weak_wrapper_shared_url_loader_factory.cc
deleted file mode 100644
index bd99c1e1914..00000000000
--- a/chromium/content/public/common/weak_wrapper_shared_url_loader_factory.cc
+++ /dev/null
@@ -1,47 +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/public/common/weak_wrapper_shared_url_loader_factory.h"
-
-#include "content/common/wrapper_shared_url_loader_factory.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-
-namespace content {
-
-WeakWrapperSharedURLLoaderFactory::WeakWrapperSharedURLLoaderFactory(
- network::mojom::URLLoaderFactory* factory_ptr)
- : factory_ptr_(factory_ptr) {}
-
-void WeakWrapperSharedURLLoaderFactory::Detach() {
- factory_ptr_ = nullptr;
-}
-
-void WeakWrapperSharedURLLoaderFactory::CreateLoaderAndStart(
- network::mojom::URLLoaderRequest loader,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
- if (!factory_ptr_)
- return;
- factory_ptr_->CreateLoaderAndStart(std::move(loader), routing_id, request_id,
- options, request, std::move(client),
- traffic_annotation);
-}
-
-std::unique_ptr<network::SharedURLLoaderFactoryInfo>
-WeakWrapperSharedURLLoaderFactory::Clone() {
- network::mojom::URLLoaderFactoryPtrInfo factory_ptr_info;
- if (factory_ptr_)
- factory_ptr_->Clone(mojo::MakeRequest(&factory_ptr_info));
- return std::make_unique<WrapperSharedURLLoaderFactoryInfo>(
- std::move(factory_ptr_info));
-}
-
-WeakWrapperSharedURLLoaderFactory::~WeakWrapperSharedURLLoaderFactory() =
- default;
-
-} // namespace content
diff --git a/chromium/content/public/common/weak_wrapper_shared_url_loader_factory.h b/chromium/content/public/common/weak_wrapper_shared_url_loader_factory.h
deleted file mode 100644
index 0bbf213f914..00000000000
--- a/chromium/content/public/common/weak_wrapper_shared_url_loader_factory.h
+++ /dev/null
@@ -1,47 +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_PUBLIC_COMMON_WEAK_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
-#define CONTENT_PUBLIC_COMMON_WEAK_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
-
-#include "content/common/content_export.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-
-namespace content {
-
-// A SharedURLLoaderFactory implementation that wraps a raw
-// mojom::URLLoaderFactory pointer.
-class CONTENT_EXPORT WeakWrapperSharedURLLoaderFactory
- : public network::SharedURLLoaderFactory {
- public:
- explicit WeakWrapperSharedURLLoaderFactory(
- network::mojom::URLLoaderFactory* factory_ptr);
-
- // Detaches from the raw mojom::URLLoaderFactory pointer. All subsequent calls
- // to CreateLoaderAndStart() will fail silently.
- void Detach();
-
- // SharedURLLoaderFactory implementation.
- void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader,
- int32_t routing_id,
- int32_t request_id,
- uint32_t options,
- const network::ResourceRequest& request,
- network::mojom::URLLoaderClientPtr client,
- const net::MutableNetworkTrafficAnnotationTag&
- traffic_annotation) override;
-
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
-
- private:
- ~WeakWrapperSharedURLLoaderFactory() override;
-
- // Not owned.
- network::mojom::URLLoaderFactory* factory_ptr_ = nullptr;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_WEAK_WRAPPER_SHARED_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/public/common/web_preferences.cc b/chromium/content/public/common/web_preferences.cc
index dcff5cef776..c5f6d0b03ba 100644
--- a/chromium/content/public/common/web_preferences.cc
+++ b/chromium/content/public/common/web_preferences.cc
@@ -90,6 +90,8 @@ WebPreferences::WebPreferences()
xss_auditor_enabled(true),
dns_prefetching_enabled(true),
data_saver_enabled(false),
+ data_saver_holdback_web_api_enabled(false),
+ data_saver_holdback_media_api_enabled(false),
local_storage_enabled(false),
databases_enabled(false),
application_cache_enabled(false),
diff --git a/chromium/content/public/common/web_preferences.h b/chromium/content/public/common/web_preferences.h
index e4fc39c60fd..a1e9fba06a6 100644
--- a/chromium/content/public/common/web_preferences.h
+++ b/chromium/content/public/common/web_preferences.h
@@ -118,6 +118,14 @@ struct CONTENT_EXPORT WebPreferences {
// Preference to save data. When enabled, requests will contain the header
// 'Save-Data: on'.
bool data_saver_enabled;
+ // Whether data saver holdback for Web APIs is enabled. If enabled, data saver
+ // appears as disabled to the web consumers even if it has been actually
+ // enabled by the user.
+ bool data_saver_holdback_web_api_enabled;
+ // Whether data saver holdback is enabled when queried by the media APIs
+ // within Blink. If enabled, data saver appears as disabled to the media APIs
+ // even if it has been actually enabled by the user.
+ bool data_saver_holdback_media_api_enabled;
bool local_storage_enabled;
bool databases_enabled;
bool application_cache_enabled;
diff --git a/chromium/content/public/common/zygote_fork_delegate_linux.h b/chromium/content/public/common/zygote_fork_delegate_linux.h
deleted file mode 100644
index 8a15434ecc2..00000000000
--- a/chromium/content/public/common/zygote_fork_delegate_linux.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_ZYGOTE_FORK_DELEGATE_LINUX_H_
-#define CONTENT_PUBLIC_COMMON_ZYGOTE_FORK_DELEGATE_LINUX_H_
-
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-// TODO(jln) base::TerminationStatus should be forward declared when switching
-// to C++11.
-#include "base/process/kill.h"
-
-namespace content {
-
-// The ZygoteForkDelegate allows the Chrome Linux zygote to delegate
-// fork operations to another class that knows how to do some
-// specialized version of fork.
-class ZygoteForkDelegate {
- public:
- // A ZygoteForkDelegate is created during Chrome linux zygote
- // initialization, and provides "fork()" functionality as an
- // alternative to forking the zygote. A new delegate is passed in
- // as an argument to ZygoteMain().
- virtual ~ZygoteForkDelegate() {}
-
- // Initialization happens in the zygote after it has been
- // started by ZygoteMain.
- // If |enable_layer1_sandbox| is true, the delegate must enable a
- // layer-1 sandbox such as the setuid sandbox.
- virtual void Init(int sandboxdesc, bool enable_layer1_sandbox) = 0;
-
- // After Init, supply a UMA_HISTOGRAM_ENUMERATION the delegate would like
- // reported to the browser process. (Note: Because these reports are
- // piggy-backed onto fork responses that don't otherwise contain UMA reports,
- // this method may not be called until much later.)
- virtual void InitialUMA(std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value) = 0;
-
- // Returns 'true' if the delegate would like to handle a given fork
- // request. Otherwise returns false. Optionally, fills in uma_name et al
- // with a report the helper wants to make via UMA_HISTOGRAM_ENUMERATION.
- virtual bool CanHelp(const std::string& process_type, std::string* uma_name,
- int* uma_sample, int* uma_boundary_value) = 0;
-
- // Indexes of FDs in the vector passed to Fork().
- enum {
- // Used to pass in the descriptor for talking to the Browser.
- // Because the children use ChannelMojo, this is actually the Mojo fd.
- kBrowserFDIndex,
- // The PID oracle is used in the protocol for discovering the
- // child process's real PID from within the SUID sandbox.
- // The child process is required to write to the socket after
- // successfully forking.
- kPIDOracleFDIndex,
- kNumPassedFDs // Number of FDs in the vector passed to Fork().
- };
-
- // Delegate forks, returning a -1 on failure. Outside the
- // suid sandbox, Fork() returns the Linux process ID.
- // This method is not aware of any potential pid namespaces, so it'll
- // return a raw pid just like fork() would.
- // Delegate is responsible for communicating the channel ID to the
- // newly created child process.
- virtual pid_t Fork(const std::string& process_type,
- const std::vector<int>& fds,
- const std::string& channel_id) = 0;
-
- // The fork delegate must also assume the role of waiting for its children
- // since the caller will not be their parents and cannot do it. |pid| here
- // should be a pid that has been returned by the Fork() method. i.e. This
- // method is completely unaware of eventual PID namespaces due to sandboxing.
- // |known_dead| indicates that the process is already dead and that a
- // blocking wait() should be performed. In this case, GetTerminationStatus()
- // will send a SIGKILL to the target process first.
- virtual bool GetTerminationStatus(pid_t pid, bool known_dead,
- base::TerminationStatus* status,
- int* exit_code) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_ZYGOTE_FORK_DELEGATE_LINUX_H_
diff --git a/chromium/content/public/common/zygote_handle.h b/chromium/content/public/common/zygote_handle.h
deleted file mode 100644
index 5c21c883072..00000000000
--- a/chromium/content/public/common/zygote_handle.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2016 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_PUBLIC_COMMON_ZYGOTE_HANDLE_H_
-#define CONTENT_PUBLIC_COMMON_ZYGOTE_HANDLE_H_
-
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/files/scoped_file.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "content/public/common/zygote_buildflags.h"
-
-#if !BUILDFLAG(USE_ZYGOTE_HANDLE)
-#error "Can not use zygote handles without USE_ZYGOTE_HANDLE"
-#endif
-
-namespace content {
-
-#if defined(OS_POSIX)
-class ZygoteCommunication;
-using ZygoteHandle = ZygoteCommunication*;
-#else
-// Perhaps other ports may USE_ZYGOTE_HANDLE here somdeday.
-#error "Can not use zygote handles on this platform"
-#endif // defined(OS_POSIX)
-
-// Allocates and initializes the global generic zygote process, and returns the
-// ZygoteHandle used to communicate with it. |launcher| is a callback that
-// should actually launch the process, after adding additional command line
-// switches to the ones composed by this function. It returns the pid created,
-// and provides a control fd for it.
-CONTENT_EXPORT ZygoteHandle CreateGenericZygote(
- base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)> launcher);
-
-// Returns a handle to a global generic zygote object. This function allows the
-// browser to launch and use a single zygote process until the performance
-// issues around launching multiple zygotes are resolved.
-// http://crbug.com/569191
-CONTENT_EXPORT ZygoteHandle GetGenericZygote();
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_ZYGOTE_HANDLE_H_
diff --git a/chromium/content/public/renderer/BUILD.gn b/chromium/content/public/renderer/BUILD.gn
index 004fc2e6fa3..ea773ce6f24 100644
--- a/chromium/content/public/renderer/BUILD.gn
+++ b/chromium/content/public/renderer/BUILD.gn
@@ -42,6 +42,16 @@ target(link_target_type, "renderer_sources") {
"document_state.h",
"fixed_received_data.cc",
"fixed_received_data.h",
+ "media_stream_audio_renderer.h",
+ "media_stream_audio_sink.cc",
+ "media_stream_audio_sink.h",
+ "media_stream_renderer_factory.h",
+ "media_stream_sink.h",
+ "media_stream_utils.cc",
+ "media_stream_utils.h",
+ "media_stream_video_renderer.h",
+ "media_stream_video_sink.cc",
+ "media_stream_video_sink.h",
"navigation_state.cc",
"navigation_state.h",
"pepper_plugin_instance.h",
@@ -72,6 +82,8 @@ target(link_target_type, "renderer_sources") {
"v8_value_converter.h",
"video_encode_accelerator.cc",
"video_encode_accelerator.h",
+ "webrtc_log_message_delegate.h",
+ "websocket_handshake_throttle_provider.h",
"window_features_converter.cc",
"window_features_converter.h",
"worker_thread.h",
@@ -85,7 +97,9 @@ target(link_target_type, "renderer_sources") {
deps = [
"//content/public/child:child_sources",
+ "//content/public/common:buildflags",
"//content/public/common:common_sources",
+ "//content/public/common:feature_h264_with_openh264_ffmpeg",
"//content/renderer",
"//gin",
"//media/capture",
@@ -95,6 +109,7 @@ target(link_target_type, "renderer_sources") {
"//ppapi/c",
"//skia",
"//third_party/blink/public:blink_headers",
+ "//third_party/webrtc_overrides",
"//third_party/widevine/cdm:headers",
"//ui/base",
"//ui/base/ime",
@@ -113,27 +128,6 @@ target(link_target_type, "renderer_sources") {
deps += [ "//sandbox" ]
}
- if (enable_webrtc) {
- sources += [
- "media_stream_audio_renderer.h",
- "media_stream_audio_sink.cc",
- "media_stream_audio_sink.h",
- "media_stream_renderer_factory.h",
- "media_stream_sink.h",
- "media_stream_utils.cc",
- "media_stream_utils.h",
- "media_stream_video_renderer.h",
- "media_stream_video_sink.cc",
- "media_stream_video_sink.h",
- "webrtc_log_message_delegate.h",
- ]
- deps += [
- "//content/public/common:buildflags",
- "//content/public/common:feature_h264_with_openh264_ffmpeg",
- "//third_party/webrtc_overrides",
- ]
- }
-
if (enable_plugins) {
sources += [ "plugin_instance_throttler.h" ]
}
diff --git a/chromium/content/public/renderer/content_renderer_client.cc b/chromium/content/public/renderer/content_renderer_client.cc
index 5bfd2922492..5134616afa5 100644
--- a/chromium/content/public/renderer/content_renderer_client.cc
+++ b/chromium/content/public/renderer/content_renderer_client.cc
@@ -10,8 +10,8 @@
#include "third_party/blink/public/platform/web_audio_device.h"
#include "third_party/blink/public/platform/web_media_stream_center.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
-#include "third_party/blink/public/platform/web_socket_handshake_throttle.h"
#include "third_party/blink/public/platform/web_speech_synthesizer.h"
+#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "ui/gfx/icc_profile.h"
#include "url/gurl.h"
@@ -64,16 +64,6 @@ ContentRendererClient::OverrideCreateMIDIAccessor(
return nullptr;
}
-std::unique_ptr<blink::WebAudioDevice>
-ContentRendererClient::OverrideCreateAudioDevice(
- const blink::WebAudioLatencyHint& latency_hint) {
- return nullptr;
-}
-
-blink::WebClipboard* ContentRendererClient::OverrideWebClipboard() {
- return nullptr;
-}
-
blink::WebThemeEngine* ContentRendererClient::OverrideThemeEngine() {
return nullptr;
}
@@ -83,6 +73,11 @@ ContentRendererClient::CreateWebSocketHandshakeThrottle() {
return nullptr;
}
+std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ContentRendererClient::CreateWebSocketHandshakeThrottleProvider() {
+ return nullptr;
+}
+
std::unique_ptr<blink::WebSpeechSynthesizer>
ContentRendererClient::OverrideSpeechSynthesizer(
blink::WebSpeechSynthesizerClient* client) {
@@ -99,7 +94,7 @@ bool ContentRendererClient::RunIdleHandlerWhenWidgetsHidden() {
return true;
}
-bool ContentRendererClient::AllowStoppingWhenProcessBackgrounded() {
+bool ContentRendererClient::AllowFreezingWhenProcessBackgrounded() {
return false;
}
diff --git a/chromium/content/public/renderer/content_renderer_client.h b/chromium/content/public/renderer/content_renderer_client.h
index a68f00aec37..6dd2589d653 100644
--- a/chromium/content/public/renderer/content_renderer_client.h
+++ b/chromium/content/public/renderer/content_renderer_client.h
@@ -20,6 +20,7 @@
#include "build/build_config.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
+#include "content/public/renderer/websocket_handshake_throttle_provider.h"
#include "media/base/decode_capabilities.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
@@ -38,16 +39,12 @@ class SingleThreadTaskRunner;
}
namespace blink {
-class WebAudioDevice;
-class WebAudioLatencyHint;
-class WebClipboard;
class WebFrame;
class WebLocalFrame;
class WebMIDIAccessor;
class WebMIDIAccessorClient;
class WebPlugin;
class WebPrescientNetworking;
-class WebSocketHandshakeThrottle;
class WebSpeechSynthesizer;
class WebSpeechSynthesizerClient;
class WebThemeEngine;
@@ -167,24 +164,22 @@ class CONTENT_EXPORT ContentRendererClient {
virtual std::unique_ptr<blink::WebMIDIAccessor> OverrideCreateMIDIAccessor(
blink::WebMIDIAccessorClient* client);
- // Allows the embedder to override creating a WebAudioDevice. If it
- // returns NULL the content layer will create the audio device.
- virtual std::unique_ptr<blink::WebAudioDevice> OverrideCreateAudioDevice(
- const blink::WebAudioLatencyHint& latency_hint);
-
- // Allows the embedder to override the blink::WebClipboard used. If it
- // returns NULL the content layer will handle clipboard interactions.
- virtual blink::WebClipboard* OverrideWebClipboard();
-
// Allows the embedder to override the WebThemeEngine used. If it returns NULL
// the content layer will provide an engine.
virtual blink::WebThemeEngine* OverrideThemeEngine();
// Allows the embedder to provide a WebSocketHandshakeThrottle. If it returns
// NULL then none will be used.
+ // TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
+ // default (https://crbug.com/825740).
virtual std::unique_ptr<blink::WebSocketHandshakeThrottle>
CreateWebSocketHandshakeThrottle();
+ // Allows the embedder to provide a WebSocketHandshakeThrottleProvider. If it
+ // returns NULL then none will be used.
+ virtual std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ CreateWebSocketHandshakeThrottleProvider();
+
// Allows the embedder to override the WebSpeechSynthesizer used.
// If it returns NULL the content layer will provide an engine.
virtual std::unique_ptr<blink::WebSpeechSynthesizer>
@@ -206,7 +201,7 @@ class CONTENT_EXPORT ContentRendererClient {
// Returns true if the renderer process should allow task suspension
// after the process has been backgrounded. Defaults to false.
- virtual bool AllowStoppingWhenProcessBackgrounded();
+ virtual bool AllowFreezingWhenProcessBackgrounded();
// Returns true if a popup window should be allowed.
virtual bool AllowPopup();
diff --git a/chromium/content/public/renderer/key_system_support.cc b/chromium/content/public/renderer/key_system_support.cc
index 6d07eb8f5ce..9b5ae43b983 100644
--- a/chromium/content/public/renderer/key_system_support.cc
+++ b/chromium/content/public/renderer/key_system_support.cc
@@ -15,7 +15,8 @@ namespace content {
bool IsKeySystemSupported(
const std::string& key_system,
std::vector<media::VideoCodec>* supported_video_codecs,
- bool* supports_persistent_license) {
+ bool* supports_persistent_license,
+ std::vector<media::EncryptionMode>* supported_encryption_schemes) {
DVLOG(3) << __func__ << " key_system: " << key_system;
bool is_supported = false;
@@ -23,9 +24,9 @@ bool IsKeySystemSupported(
content::RenderThread::Get()->GetConnector()->BindInterface(
mojom::kBrowserServiceName, mojo::MakeRequest(&key_system_support));
- key_system_support->IsKeySystemSupported(key_system, &is_supported,
- supported_video_codecs,
- supports_persistent_license);
+ key_system_support->IsKeySystemSupported(
+ key_system, &is_supported, supported_video_codecs,
+ supports_persistent_license, supported_encryption_schemes);
return is_supported;
}
diff --git a/chromium/content/public/renderer/key_system_support.h b/chromium/content/public/renderer/key_system_support.h
index dd8d04a81d3..8491ecc1a41 100644
--- a/chromium/content/public/renderer/key_system_support.h
+++ b/chromium/content/public/renderer/key_system_support.h
@@ -9,18 +9,20 @@
#include <vector>
#include "content/common/content_export.h"
+#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h"
namespace content {
// Determines if |key_system| is supported by calling into the browser.
-// If it is supported, return true and |supported_video_codecs| and
-// |supports_persistent_license| are updated to match what |key_system|
-// supports. If not supported, false is returned.
+// If it is supported, return true and |supported_video_codecs|,
+// |supports_persistent_license| and |supported_encryption_schemes| are updated
+// to match what |key_system| supports. If not supported, false is returned.
CONTENT_EXPORT bool IsKeySystemSupported(
const std::string& key_system,
std::vector<media::VideoCodec>* supported_video_codecs,
- bool* supports_persistent_license);
+ bool* supports_persistent_license,
+ std::vector<media::EncryptionMode>* supported_encryption_schemes);
} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_audio_renderer.h b/chromium/content/public/renderer/media_stream_audio_renderer.h
index 3061d6427f5..54bd151eef0 100644
--- a/chromium/content/public/renderer/media_stream_audio_renderer.h
+++ b/chromium/content/public/renderer/media_stream_audio_renderer.h
@@ -11,7 +11,6 @@
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "media/base/output_device_info.h"
-#include "url/origin.h"
namespace content {
@@ -50,7 +49,6 @@ class MediaStreamAudioRenderer
// update clients accordingly and fix the comment.
virtual void SwitchOutputDevice(
const std::string& device_id,
- const url::Origin& security_origin,
const media::OutputDeviceStatusCB& callback) = 0;
// Time stamp that reflects the current render time. Should not be updated
diff --git a/chromium/content/public/renderer/media_stream_renderer_factory.h b/chromium/content/public/renderer/media_stream_renderer_factory.h
index aec3098a642..6dd479a77e0 100644
--- a/chromium/content/public/renderer/media_stream_renderer_factory.h
+++ b/chromium/content/public/renderer/media_stream_renderer_factory.h
@@ -11,7 +11,6 @@
#include "base/memory/ref_counted.h"
#include "content/public/renderer/media_stream_audio_renderer.h"
#include "content/public/renderer/media_stream_video_renderer.h"
-#include "url/origin.h"
namespace base {
class SingleThreadTaskRunner;
@@ -42,8 +41,7 @@ class MediaStreamRendererFactory {
virtual scoped_refptr<MediaStreamAudioRenderer> GetAudioRenderer(
const blink::WebMediaStream& web_stream,
int render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) = 0;
+ const std::string& device_id) = 0;
};
} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_utils.cc b/chromium/content/public/renderer/media_stream_utils.cc
index 1aeea995d84..15d6f12ca2d 100644
--- a/chromium/content/public/renderer/media_stream_utils.cc
+++ b/chromium/content/public/renderer/media_stream_utils.cc
@@ -71,7 +71,7 @@ bool AddAudioTrackToMediaStream(
const media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
- sample_rate, sizeof(int16_t) * 8, frames_per_buffer);
+ sample_rate, frames_per_buffer);
if (!params.IsValid()) {
DLOG(ERROR) << "Invalid audio parameters.";
return false;
diff --git a/chromium/content/public/renderer/pepper_plugin_instance.h b/chromium/content/public/renderer/pepper_plugin_instance.h
index dbad584d2f3..99a7a8a0319 100644
--- a/chromium/content/public/renderer/pepper_plugin_instance.h
+++ b/chromium/content/public/renderer/pepper_plugin_instance.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <string>
+
#include "base/process/process_handle.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
@@ -138,9 +140,24 @@ class PepperPluginInstance {
// Returns true if the plugin text can be edited.
virtual bool CanEditText() = 0;
+ // Returns true if the plugin has editable text. i.e. The editable text field
+ // is non-empty. Assumes CanEditText() returns true.
+ virtual bool HasEditableText() = 0;
+
// Replaces the plugin's selected text, if any, with |text|. Assumes
// CanEditText() returns true.
virtual void ReplaceSelection(const std::string& text) = 0;
+
+ // Issues a select all command.
+ virtual void SelectAll() = 0;
+
+ // Returns true if the plugin can undo/redo.
+ virtual bool CanUndo() = 0;
+ virtual bool CanRedo() = 0;
+
+ // Issues undo and redo commands.
+ virtual void Undo() = 0;
+ virtual void Redo() = 0;
};
} // namespace content
diff --git a/chromium/content/public/renderer/render_thread.h b/chromium/content/public/renderer/render_thread.h
index 01b5ef6737e..13f0d61c008 100644
--- a/chromium/content/public/renderer/render_thread.h
+++ b/chromium/content/public/renderer/render_thread.h
@@ -15,6 +15,7 @@
#include "content/common/content_export.h"
#include "content/public/child/child_thread.h"
#include "ipc/ipc_channel_proxy.h"
+#include "third_party/blink/public/platform/web_string.h"
class GURL;
@@ -38,10 +39,6 @@ namespace v8 {
class Extension;
}
-namespace viz {
-class SharedBitmapManager;
-}
-
namespace content {
class RenderThreadObserver;
@@ -83,8 +80,6 @@ class CONTENT_EXPORT RenderThread : virtual public ChildThread {
virtual std::unique_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
size_t buffer_size) = 0;
- virtual viz::SharedBitmapManager* GetSharedBitmapManager() = 0;
-
// Registers the given V8 extension with WebKit.
virtual void RegisterExtension(v8::Extension* extension) = 0;
@@ -116,6 +111,9 @@ class CONTENT_EXPORT RenderThread : virtual public ChildThread {
// Set the renderer process type.
virtual void SetRendererProcessType(
blink::scheduler::RendererProcessType type) = 0;
+
+ // Returns the user-agent string.
+ virtual blink::WebString GetUserAgent() const = 0;
};
} // namespace content
diff --git a/chromium/content/public/renderer/render_view.h b/chromium/content/public/renderer/render_view.h
index 5cd1c34fb6d..ee8c5779144 100644
--- a/chromium/content/public/renderer/render_view.h
+++ b/chromium/content/public/renderer/render_view.h
@@ -95,10 +95,6 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// false, but set to true by some tests.
virtual bool GetContentStateImmediately() const = 0;
- // Notifies the renderer that a paint is to be generated for the size
- // passed in.
- virtual void Repaint(const gfx::Size& size) = 0;
-
// Inject edit commands to be used for the next keyboard event.
// TODO(alexmos): Currently, these are used only by BlinkTestRunner. They
// should be removed from RenderView and instead be plumbed through the
@@ -126,8 +122,6 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
virtual gfx::RectF ElementBoundsInWindow(const blink::WebElement& element)
= 0;
- virtual bool HasAddedInputHandler() const = 0;
-
protected:
~RenderView() override {}
diff --git a/chromium/content/public/renderer/request_peer.h b/chromium/content/public/renderer/request_peer.h
index 3b8d3fa2983..dfd650e57c3 100644
--- a/chromium/content/public/renderer/request_peer.h
+++ b/chromium/content/public/renderer/request_peer.h
@@ -24,7 +24,6 @@ struct URLLoaderCompletionStatus;
namespace content {
-
// This is implemented by our custom resource loader within content. The Peer
// and it's bridge should have identical lifetimes as they represent each end of
// a communication channel.
diff --git a/chromium/content/public/renderer/url_loader_throttle_provider.h b/chromium/content/public/renderer/url_loader_throttle_provider.h
index 07cdaa412d3..2d1aca8d6e4 100644
--- a/chromium/content/public/renderer/url_loader_throttle_provider.h
+++ b/chromium/content/public/renderer/url_loader_throttle_provider.h
@@ -28,6 +28,9 @@ class CONTENT_EXPORT URLLoaderThrottleProvider {
public:
virtual ~URLLoaderThrottleProvider() {}
+ // Used to copy a URLLoaderThrottleProvider between worker threads.
+ virtual std::unique_ptr<URLLoaderThrottleProvider> Clone() = 0;
+
// For requests from frames and dedicated workers, |render_frame_id| should be
// set to the corresponding frame. For requests from shared or
// service workers, |render_frame_id| should be set to MSG_ROUTING_NONE.
diff --git a/chromium/content/public/renderer/websocket_handshake_throttle_provider.h b/chromium/content/public/renderer/websocket_handshake_throttle_provider.h
new file mode 100644
index 00000000000..565aa818996
--- /dev/null
+++ b/chromium/content/public/renderer/websocket_handshake_throttle_provider.h
@@ -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.
+
+#ifndef CONTENT_PUBLIC_RENDERER_WEBSOCKET_HANDSHAKE_THROTTLE_PROVIDER_H_
+#define CONTENT_PUBLIC_RENDERER_WEBSOCKET_HANDSHAKE_THROTTLE_PROVIDER_H_
+
+#include <memory>
+
+#include "content/common/content_export.h"
+
+namespace blink {
+class WebSocketHandshakeThrottle;
+}
+
+namespace content {
+
+// This interface allows the embedder to provide a WebSocketHandshakeThrottle
+// implementation. An instance of this class must be constructed on the render
+// thread, and then used and destructed on a single thread, which can be
+// different from the render thread.
+class CONTENT_EXPORT WebSocketHandshakeThrottleProvider {
+ public:
+ virtual ~WebSocketHandshakeThrottleProvider() {}
+
+ // Used to copy a WebSocketHandshakeThrottleProvider between worker threads.
+ virtual std::unique_ptr<WebSocketHandshakeThrottleProvider> Clone() = 0;
+
+ // For requests from frames and dedicated workers, |render_frame_id| should be
+ // set to the corresponding frame. For requests from shared or service
+ // workers, |render_frame_id| should be set to MSG_ROUTING_NONE.
+ virtual std::unique_ptr<blink::WebSocketHandshakeThrottle> CreateThrottle(
+ int render_frame_id) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_WEBSOCKET_HANDSHAKE_THROTTLE_PROVIDER_H_
diff --git a/chromium/content/public/test/android/BUILD.gn b/chromium/content/public/test/android/BUILD.gn
index beebfd72c69..08de4404b1c 100644
--- a/chromium/content/public/test/android/BUILD.gn
+++ b/chromium/content/public/test/android/BUILD.gn
@@ -33,6 +33,7 @@ android_library("content_java_test_support") {
"javatests/src/org/chromium/content/browser/test/ChildProcessAllocatorSettings.java",
"javatests/src/org/chromium/content/browser/test/ChildProcessAllocatorSettingsHook.java",
"javatests/src/org/chromium/content/browser/test/ContentJUnit4ClassRunner.java",
+ "javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java",
"javatests/src/org/chromium/content/browser/test/NativeLibraryTestRule.java",
"javatests/src/org/chromium/content/browser/test/mock/MockRenderFrameHost.java",
"javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java",
@@ -56,3 +57,26 @@ android_library("content_java_test_support") {
"javatests/src/org/chromium/content/browser/test/util/UiUtils.java",
]
}
+
+generate_jni("content_test_jni") {
+ testonly = true
+ jni_package = "content/public/test"
+ sources = [
+ "javatests/src/org/chromium/content/browser/test/InterstitialPageDelegateAndroid.java",
+ ]
+}
+
+static_library("content_native_test_support") {
+ testonly = true
+ sources = [
+ "interstitial_page_delegate_android.cc",
+ "interstitial_page_delegate_android.h",
+ ]
+ deps = [
+ ":content_test_jni",
+ "//base",
+ "//content/public/browser",
+ "//device/gamepad",
+ "//media/midi",
+ ]
+}
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn
index e90c9c2a023..4f9c35e697b 100644
--- a/chromium/content/renderer/BUILD.gn
+++ b/chromium/content/renderer/BUILD.gn
@@ -43,12 +43,8 @@ target(link_target_type, "renderer") {
"android/disambiguation_popup_helper.h",
"android/renderer_date_time_picker.cc",
"android/renderer_date_time_picker.h",
- "android/synchronous_compositor_filter.cc",
- "android/synchronous_compositor_filter.h",
"android/synchronous_compositor_proxy.cc",
"android/synchronous_compositor_proxy.h",
- "android/synchronous_compositor_proxy_chrome_ipc.cc",
- "android/synchronous_compositor_proxy_chrome_ipc.h",
"android/synchronous_compositor_proxy_mojo.cc",
"android/synchronous_compositor_proxy_mojo.h",
"android/synchronous_compositor_registry.h",
@@ -68,8 +64,6 @@ target(link_target_type, "renderer") {
"browser_plugin/browser_plugin.h",
"browser_plugin/browser_plugin_manager.cc",
"browser_plugin/browser_plugin_manager.h",
- "cache_storage/webserviceworkercachestorage_impl.cc",
- "cache_storage/webserviceworkercachestorage_impl.h",
"categorized_worker_pool.cc",
"categorized_worker_pool.h",
"child_frame_compositing_helper.cc",
@@ -164,6 +158,8 @@ target(link_target_type, "renderer") {
"history_serialization.h",
"idle_user_detector.cc",
"idle_user_detector.h",
+ "image_capture/image_capture_frame_grabber.cc",
+ "image_capture/image_capture_frame_grabber.h",
"image_downloader/image_downloader_base.cc",
"image_downloader/image_downloader_base.h",
"image_downloader/image_downloader_impl.cc",
@@ -190,14 +186,8 @@ target(link_target_type, "renderer") {
"indexed_db/webidbfactory_impl.h",
"input/frame_input_handler_impl.cc",
"input/frame_input_handler_impl.h",
- "input/input_event_filter.cc",
- "input/input_event_filter.h",
- "input/input_event_filter_ipc_names.cc",
- "input/input_handler_manager.cc",
- "input/input_handler_manager.h",
- "input/input_handler_manager_client.h",
- "input/input_handler_wrapper.cc",
- "input/input_handler_wrapper.h",
+ "input/input_event_prediction.cc",
+ "input/input_event_prediction.h",
"input/input_target_client_impl.cc",
"input/input_target_client_impl.h",
"input/main_thread_event_queue.cc",
@@ -205,8 +195,6 @@ target(link_target_type, "renderer") {
"input/main_thread_event_queue_task.h",
"input/main_thread_event_queue_task_list.cc",
"input/main_thread_event_queue_task_list.h",
- "input/main_thread_input_event_filter.cc",
- "input/main_thread_input_event_filter.h",
"input/render_widget_input_handler.cc",
"input/render_widget_input_handler.h",
"input/render_widget_input_handler_delegate.h",
@@ -234,6 +222,8 @@ target(link_target_type, "renderer") {
"loader/child_url_loader_factory_bundle.h",
"loader/ftp_directory_listing_response_delegate.cc",
"loader/ftp_directory_listing_response_delegate.h",
+ "loader/navigation_response_override_parameters.cc",
+ "loader/navigation_response_override_parameters.h",
"loader/request_extra_data.cc",
"loader/request_extra_data.h",
"loader/resource_dispatcher.cc",
@@ -284,10 +274,6 @@ target(link_target_type, "renderer") {
"media/audio_device_factory.h",
"media/audio_input_ipc_factory.cc",
"media/audio_input_ipc_factory.h",
- "media/audio_input_message_filter.cc",
- "media/audio_input_message_filter.h",
- "media/audio_message_filter.cc",
- "media/audio_message_filter.h",
"media/audio_output_ipc_factory.cc",
"media/audio_output_ipc_factory.h",
"media/audio_renderer_mixer_manager.cc",
@@ -317,12 +303,178 @@ target(link_target_type, "renderer") {
"media/renderer_webaudiodevice_impl.h",
"media/renderer_webmediaplayer_delegate.cc",
"media/renderer_webmediaplayer_delegate.h",
+ "media/stream/aec_dump_message_filter.cc",
+ "media/stream/aec_dump_message_filter.h",
+ "media/stream/apply_constraints_processor.cc",
+ "media/stream/apply_constraints_processor.h",
+ "media/stream/external_media_stream_audio_source.cc",
+ "media/stream/external_media_stream_audio_source.h",
+ "media/stream/local_media_stream_audio_source.cc",
+ "media/stream/local_media_stream_audio_source.h",
+ "media/stream/media_stream_audio_deliverer.h",
+ "media/stream/media_stream_audio_level_calculator.cc",
+ "media/stream/media_stream_audio_level_calculator.h",
+ "media/stream/media_stream_audio_processor.cc",
+ "media/stream/media_stream_audio_processor.h",
+ "media/stream/media_stream_audio_processor_options.cc",
+ "media/stream/media_stream_audio_processor_options.h",
+ "media/stream/media_stream_audio_source.cc",
+ "media/stream/media_stream_audio_source.h",
+ "media/stream/media_stream_audio_track.cc",
+ "media/stream/media_stream_audio_track.h",
+ "media/stream/media_stream_center.cc",
+ "media/stream/media_stream_center.h",
+ "media/stream/media_stream_constraints_util.cc",
+ "media/stream/media_stream_constraints_util.h",
+ "media/stream/media_stream_constraints_util_audio.cc",
+ "media/stream/media_stream_constraints_util_audio.h",
+ "media/stream/media_stream_constraints_util_sets.cc",
+ "media/stream/media_stream_constraints_util_sets.h",
+ "media/stream/media_stream_constraints_util_video_content.cc",
+ "media/stream/media_stream_constraints_util_video_content.h",
+ "media/stream/media_stream_constraints_util_video_device.cc",
+ "media/stream/media_stream_constraints_util_video_device.h",
+ "media/stream/media_stream_device_observer.cc",
+ "media/stream/media_stream_device_observer.h",
+ "media/stream/media_stream_dispatcher_eventhandler.h",
+ "media/stream/media_stream_registry_interface.h",
+ "media/stream/media_stream_renderer_factory_impl.cc",
+ "media/stream/media_stream_renderer_factory_impl.h",
+ "media/stream/media_stream_source.cc",
+ "media/stream/media_stream_source.h",
+ "media/stream/media_stream_track.cc",
+ "media/stream/media_stream_track.h",
+ "media/stream/media_stream_video_capturer_source.cc",
+ "media/stream/media_stream_video_capturer_source.h",
+ "media/stream/media_stream_video_renderer_sink.cc",
+ "media/stream/media_stream_video_renderer_sink.h",
+ "media/stream/media_stream_video_source.cc",
+ "media/stream/media_stream_video_source.h",
+ "media/stream/media_stream_video_track.cc",
+ "media/stream/media_stream_video_track.h",
+ "media/stream/processed_local_audio_source.cc",
+ "media/stream/processed_local_audio_source.h",
+ "media/stream/remote_media_stream_track_adapter.cc",
+ "media/stream/remote_media_stream_track_adapter.h",
+ "media/stream/secure_display_link_tracker.h",
+ "media/stream/track_audio_renderer.cc",
+ "media/stream/track_audio_renderer.h",
+ "media/stream/user_media_client_impl.cc",
+ "media/stream/user_media_client_impl.h",
+ "media/stream/user_media_processor.cc",
+ "media/stream/user_media_processor.h",
+ "media/stream/video_track_adapter.cc",
+ "media/stream/video_track_adapter.h",
+ "media/stream/webaudio_media_stream_source.cc",
+ "media/stream/webaudio_media_stream_source.h",
+ "media/stream/webmediaplayer_ms.cc",
+ "media/stream/webmediaplayer_ms.h",
+ "media/stream/webmediaplayer_ms_compositor.cc",
+ "media/stream/webmediaplayer_ms_compositor.h",
"media/video_capture_impl.cc",
"media/video_capture_impl.h",
"media/video_capture_impl_manager.cc",
"media/video_capture_impl_manager.h",
"media/web_media_element_source_utils.cc",
"media/web_media_element_source_utils.h",
+ "media/webrtc/audio_codec_factory.cc",
+ "media/webrtc/audio_codec_factory.h",
+ "media/webrtc/media_stream_remote_video_source.cc",
+ "media/webrtc/media_stream_remote_video_source.h",
+ "media/webrtc/media_stream_track_metrics.cc",
+ "media/webrtc/media_stream_track_metrics.h",
+ "media/webrtc/media_stream_video_webrtc_sink.cc",
+ "media/webrtc/media_stream_video_webrtc_sink.h",
+ "media/webrtc/peer_connection_dependency_factory.cc",
+ "media/webrtc/peer_connection_dependency_factory.h",
+ "media/webrtc/peer_connection_remote_audio_source.cc",
+ "media/webrtc/peer_connection_remote_audio_source.h",
+ "media/webrtc/peer_connection_tracker.cc",
+ "media/webrtc/peer_connection_tracker.h",
+ "media/webrtc/rtc_certificate.cc",
+ "media/webrtc/rtc_certificate.h",
+ "media/webrtc/rtc_certificate_generator.cc",
+ "media/webrtc/rtc_certificate_generator.h",
+ "media/webrtc/rtc_data_channel_handler.cc",
+ "media/webrtc/rtc_data_channel_handler.h",
+ "media/webrtc/rtc_dtmf_sender_handler.cc",
+ "media/webrtc/rtc_dtmf_sender_handler.h",
+ "media/webrtc/rtc_event_log_output_sink.h",
+ "media/webrtc/rtc_event_log_output_sink_proxy.cc",
+ "media/webrtc/rtc_event_log_output_sink_proxy.h",
+ "media/webrtc/rtc_peer_connection_handler.cc",
+ "media/webrtc/rtc_peer_connection_handler.h",
+ "media/webrtc/rtc_rtp_contributing_source.cc",
+ "media/webrtc/rtc_rtp_contributing_source.h",
+ "media/webrtc/rtc_rtp_receiver.cc",
+ "media/webrtc/rtc_rtp_receiver.h",
+ "media/webrtc/rtc_rtp_sender.cc",
+ "media/webrtc/rtc_rtp_sender.h",
+ "media/webrtc/rtc_stats.cc",
+ "media/webrtc/rtc_stats.h",
+ "media/webrtc/rtc_video_decoder.cc",
+ "media/webrtc/rtc_video_decoder.h",
+ "media/webrtc/rtc_video_decoder_factory.cc",
+ "media/webrtc/rtc_video_decoder_factory.h",
+ "media/webrtc/rtc_video_encoder.cc",
+ "media/webrtc/rtc_video_encoder.h",
+ "media/webrtc/rtc_video_encoder_factory.cc",
+ "media/webrtc/rtc_video_encoder_factory.h",
+ "media/webrtc/stun_field_trial.cc",
+ "media/webrtc/stun_field_trial.h",
+ "media/webrtc/track_observer.cc",
+ "media/webrtc/track_observer.h",
+ "media/webrtc/two_keys_adapter_map.h",
+ "media/webrtc/webrtc_audio_device_impl.cc",
+ "media/webrtc/webrtc_audio_device_impl.h",
+ "media/webrtc/webrtc_audio_device_not_impl.cc",
+ "media/webrtc/webrtc_audio_device_not_impl.h",
+ "media/webrtc/webrtc_audio_renderer.cc",
+ "media/webrtc/webrtc_audio_renderer.h",
+ "media/webrtc/webrtc_audio_sink.cc",
+ "media/webrtc/webrtc_audio_sink.h",
+ "media/webrtc/webrtc_media_stream_adapter.cc",
+ "media/webrtc/webrtc_media_stream_adapter.h",
+ "media/webrtc/webrtc_media_stream_adapter_map.cc",
+ "media/webrtc/webrtc_media_stream_adapter_map.h",
+ "media/webrtc/webrtc_media_stream_track_adapter.cc",
+ "media/webrtc/webrtc_media_stream_track_adapter.h",
+ "media/webrtc/webrtc_media_stream_track_adapter_map.cc",
+ "media/webrtc/webrtc_media_stream_track_adapter_map.h",
+ "media/webrtc/webrtc_set_remote_description_observer.cc",
+ "media/webrtc/webrtc_set_remote_description_observer.h",
+ "media/webrtc/webrtc_uma_histograms.cc",
+ "media/webrtc/webrtc_uma_histograms.h",
+ "media/webrtc/webrtc_video_capturer_adapter.cc",
+ "media/webrtc/webrtc_video_capturer_adapter.h",
+ "media/webrtc/webrtc_video_frame_adapter.cc",
+ "media/webrtc/webrtc_video_frame_adapter.h",
+ "media/webrtc_local_audio_source_provider.cc",
+ "media/webrtc_local_audio_source_provider.h",
+ "media/webrtc_logging.cc",
+ "media/webrtc_logging.h",
+ "media_capture_from_element/canvas_capture_handler.cc",
+ "media_capture_from_element/canvas_capture_handler.h",
+ "media_capture_from_element/html_audio_element_capturer_source.cc",
+ "media_capture_from_element/html_audio_element_capturer_source.h",
+ "media_capture_from_element/html_video_element_capturer_source.cc",
+ "media_capture_from_element/html_video_element_capturer_source.h",
+ "media_recorder/audio_track_encoder.cc",
+ "media_recorder/audio_track_encoder.h",
+ "media_recorder/audio_track_opus_encoder.cc",
+ "media_recorder/audio_track_opus_encoder.h",
+ "media_recorder/audio_track_pcm_encoder.cc",
+ "media_recorder/audio_track_pcm_encoder.h",
+ "media_recorder/audio_track_recorder.cc",
+ "media_recorder/audio_track_recorder.h",
+ "media_recorder/media_recorder_handler.cc",
+ "media_recorder/media_recorder_handler.h",
+ "media_recorder/vea_encoder.cc",
+ "media_recorder/vea_encoder.h",
+ "media_recorder/video_track_recorder.cc",
+ "media_recorder/video_track_recorder.h",
+ "media_recorder/vpx_encoder.cc",
+ "media_recorder/vpx_encoder.h",
"menu_item_builder.cc",
"menu_item_builder.h",
"message_delivery_policy.h",
@@ -338,18 +490,31 @@ target(link_target_type, "renderer") {
"net_info_helper.h",
"notifications/notification_data_conversions.cc",
"notifications/notification_data_conversions.h",
- "notifications/notification_dispatcher.cc",
- "notifications/notification_dispatcher.h",
- "notifications/notification_manager.cc",
- "notifications/notification_manager.h",
- "origin_trials/web_trial_token_validator_impl.cc",
- "origin_trials/web_trial_token_validator_impl.h",
+ "p2p/empty_network_manager.cc",
+ "p2p/empty_network_manager.h",
+ "p2p/filtering_network_manager.cc",
+ "p2p/filtering_network_manager.h",
+ "p2p/host_address_request.cc",
+ "p2p/host_address_request.h",
+ "p2p/ipc_network_manager.cc",
+ "p2p/ipc_network_manager.h",
+ "p2p/ipc_socket_factory.cc",
+ "p2p/ipc_socket_factory.h",
"p2p/network_list_manager.h",
+ "p2p/network_list_observer.h",
+ "p2p/network_manager_uma.cc",
+ "p2p/network_manager_uma.h",
+ "p2p/port_allocator.cc",
+ "p2p/port_allocator.h",
+ "p2p/socket_client.h",
+ "p2p/socket_client_delegate.h",
+ "p2p/socket_client_impl.cc",
+ "p2p/socket_client_impl.h",
+ "p2p/socket_dispatcher.cc",
+ "p2p/socket_dispatcher.h",
"pepper/fullscreen_container.h",
"peripheral_content_heuristic.cc",
"peripheral_content_heuristic.h",
- "presentation/presentation_dispatcher.cc",
- "presentation/presentation_dispatcher.h",
"push_messaging/push_messaging_client.cc",
"push_messaging/push_messaging_client.h",
"push_messaging/push_provider.cc",
@@ -406,8 +571,6 @@ target(link_target_type, "renderer") {
"service_worker/embedded_worker_instance_client_impl.h",
"service_worker/service_worker_context_client.cc",
"service_worker/service_worker_context_client.h",
- "service_worker/service_worker_dispatcher.cc",
- "service_worker/service_worker_dispatcher.h",
"service_worker/service_worker_fetch_context_impl.cc",
"service_worker/service_worker_fetch_context_impl.h",
"service_worker/service_worker_message_filter.cc",
@@ -436,8 +599,6 @@ target(link_target_type, "renderer") {
"service_worker/web_service_worker_registration_impl.h",
"service_worker/worker_fetch_context_impl.cc",
"service_worker/worker_fetch_context_impl.h",
- "shared_memory_seqlock_reader.cc",
- "shared_memory_seqlock_reader.h",
"shared_worker/embedded_shared_worker_stub.cc",
"shared_worker/embedded_shared_worker_stub.h",
"shared_worker/shared_worker_client_impl.cc",
@@ -472,8 +633,6 @@ target(link_target_type, "renderer") {
"web_ui_extension.h",
"web_ui_extension_data.cc",
"web_ui_extension_data.h",
- "webfileutilities_impl.cc",
- "webfileutilities_impl.h",
"webgraphicscontext3d_provider_impl.cc",
"webgraphicscontext3d_provider_impl.h",
"webpublicsuffixlist_impl.cc",
@@ -488,16 +647,6 @@ target(link_target_type, "renderer") {
"worker_thread_registry.h",
]
- jumbo_excluded_sources = [
- # IPC code is built with macros that redefine the default meaning
- # of the IPC macros. When that happens in a translation unit there
- # is no way to get the default meaning of the macros
- # back. Therefore any code that redefines the default IPC macros
- # need to be excluded from jumbo
- # compilations. https://crbug.com/794176
- "input/input_event_filter_ipc_names.cc",
- ]
-
if (!is_component_build) {
if (is_win && is_official_build) {
split_count = 2 # In certain configurations a full renderer.lib can
@@ -522,12 +671,11 @@ target(link_target_type, "renderer") {
"//base:i18n",
"//cc",
"//cc/animation",
- "//cc/blink",
- "//cc/ipc",
"//cc/paint",
"//components/discardable_memory/client",
"//components/metrics",
"//components/metrics:single_sample_metrics",
+ "//components/services/leveldb/public/cpp",
"//components/url_formatter",
"//components/viz/client",
"//components/viz/common",
@@ -541,6 +689,7 @@ target(link_target_type, "renderer") {
"//content/public/common:buildflags",
"//content/public/common:feature_h264_with_openh264_ffmpeg",
"//content/public/common:service_names",
+ "//crypto",
"//crypto:platform",
"//device/base/synchronization",
"//device/gamepad/public/cpp:shared_with_blink",
@@ -550,6 +699,7 @@ target(link_target_type, "renderer") {
"//gpu",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/client:raster_interface",
+ "//jingle:jingle_glue",
"//media",
"//media:media_buildflags",
"//media/blink",
@@ -563,7 +713,6 @@ target(link_target_type, "renderer") {
"//media/mojo/clients",
"//media/mojo/interfaces",
"//media/mojo/interfaces:remoting",
- "//mojo/common",
"//mojo/public/cpp/bindings",
"//net",
"//ppapi/buildflags",
@@ -586,7 +735,50 @@ target(link_target_type, "renderer") {
"//third_party/blink/public/common",
"//third_party/boringssl",
"//third_party/icu",
+ "//third_party/libvpx",
"//third_party/libyuv",
+ "//third_party/opus",
+ "//third_party/webrtc/api:libjingle_logging_api",
+ "//third_party/webrtc/api:libjingle_peerconnection_api",
+ "//third_party/webrtc/api:optional",
+ "//third_party/webrtc/api:rtc_stats_api",
+ "//third_party/webrtc/api/audio:aec3_factory",
+ "//third_party/webrtc/api/audio_codecs:audio_codecs_api",
+ "//third_party/webrtc/api/audio_codecs/L16:audio_decoder_L16",
+ "//third_party/webrtc/api/audio_codecs/L16:audio_encoder_L16",
+ "//third_party/webrtc/api/audio_codecs/g711:audio_decoder_g711",
+ "//third_party/webrtc/api/audio_codecs/g711:audio_encoder_g711",
+ "//third_party/webrtc/api/audio_codecs/g722:audio_decoder_g722",
+ "//third_party/webrtc/api/audio_codecs/g722:audio_encoder_g722",
+ "//third_party/webrtc/api/audio_codecs/isac:audio_decoder_isac",
+ "//third_party/webrtc/api/audio_codecs/isac:audio_encoder_isac",
+ "//third_party/webrtc/api/audio_codecs/opus:audio_decoder_opus",
+ "//third_party/webrtc/api/audio_codecs/opus:audio_encoder_opus",
+ "//third_party/webrtc/api/video:video_bitrate_allocation",
+ "//third_party/webrtc/api/video:video_frame",
+ "//third_party/webrtc/api/video:video_frame_i420",
+ "//third_party/webrtc/api/video_codecs:video_codecs_api",
+ "//third_party/webrtc/common_video:common_video",
+ "//third_party/webrtc/media:rtc_internal_video_codecs",
+ "//third_party/webrtc/media:rtc_media",
+ "//third_party/webrtc/media:rtc_media_base",
+ "//third_party/webrtc/modules/audio_device",
+ "//third_party/webrtc/modules/audio_processing",
+ "//third_party/webrtc/modules/audio_processing:audio_processing_statistics",
+ "//third_party/webrtc/modules/audio_processing/aec_dump",
+ "//third_party/webrtc/modules/video_coding:video_codec_interface",
+ "//third_party/webrtc/modules/video_coding:webrtc_h264",
+ "//third_party/webrtc/p2p:libstunprober",
+ "//third_party/webrtc/p2p:rtc_p2p",
+ "//third_party/webrtc/pc:libjingle_peerconnection",
+ "//third_party/webrtc/pc:peerconnection",
+ "//third_party/webrtc/pc:rtc_pc",
+ "//third_party/webrtc/pc:rtc_pc_base",
+ "//third_party/webrtc/rtc_base:rtc_base",
+ "//third_party/webrtc/rtc_base:rtc_task_queue",
+ "//third_party/webrtc/stats",
+ "//third_party/webrtc/system_wrappers",
+ "//third_party/webrtc_overrides:init_webrtc",
"//third_party/widevine/cdm:headers",
"//ui/accessibility",
"//ui/base",
@@ -646,6 +838,10 @@ target(link_target_type, "renderer") {
]
}
+ if (is_linux) {
+ deps += [ "//services/service_manager/zygote" ]
+ }
+
if (is_fuchsia) {
sources += [
"render_view_fuchsia.cc",
@@ -657,281 +853,31 @@ target(link_target_type, "renderer") {
deps += [ "//media/remoting" ]
}
- if (enable_webrtc) {
- # WebRTC plugin-related stuff goes in a different section below.
+ if (enable_plugins) {
sources += [
- "image_capture/image_capture_frame_grabber.cc",
- "image_capture/image_capture_frame_grabber.h",
- "media/stream/aec_dump_message_filter.cc",
- "media/stream/aec_dump_message_filter.h",
- "media/stream/apply_constraints_processor.cc",
- "media/stream/apply_constraints_processor.h",
- "media/stream/external_media_stream_audio_source.cc",
- "media/stream/external_media_stream_audio_source.h",
- "media/stream/local_media_stream_audio_source.cc",
- "media/stream/local_media_stream_audio_source.h",
- "media/stream/media_stream_audio_deliverer.h",
- "media/stream/media_stream_audio_level_calculator.cc",
- "media/stream/media_stream_audio_level_calculator.h",
- "media/stream/media_stream_audio_processor.cc",
- "media/stream/media_stream_audio_processor.h",
- "media/stream/media_stream_audio_processor_options.cc",
- "media/stream/media_stream_audio_processor_options.h",
- "media/stream/media_stream_audio_source.cc",
- "media/stream/media_stream_audio_source.h",
- "media/stream/media_stream_audio_track.cc",
- "media/stream/media_stream_audio_track.h",
- "media/stream/media_stream_center.cc",
- "media/stream/media_stream_center.h",
- "media/stream/media_stream_constraints_util.cc",
- "media/stream/media_stream_constraints_util.h",
- "media/stream/media_stream_constraints_util_audio.cc",
- "media/stream/media_stream_constraints_util_audio.h",
- "media/stream/media_stream_constraints_util_sets.cc",
- "media/stream/media_stream_constraints_util_sets.h",
- "media/stream/media_stream_constraints_util_video_content.cc",
- "media/stream/media_stream_constraints_util_video_content.h",
- "media/stream/media_stream_constraints_util_video_device.cc",
- "media/stream/media_stream_constraints_util_video_device.h",
- "media/stream/media_stream_device_observer.cc",
- "media/stream/media_stream_device_observer.h",
- "media/stream/media_stream_dispatcher_eventhandler.h",
- "media/stream/media_stream_registry_interface.h",
- "media/stream/media_stream_renderer_factory_impl.cc",
- "media/stream/media_stream_renderer_factory_impl.h",
- "media/stream/media_stream_source.cc",
- "media/stream/media_stream_source.h",
- "media/stream/media_stream_track.cc",
- "media/stream/media_stream_track.h",
- "media/stream/media_stream_video_capturer_source.cc",
- "media/stream/media_stream_video_capturer_source.h",
- "media/stream/media_stream_video_renderer_sink.cc",
- "media/stream/media_stream_video_renderer_sink.h",
- "media/stream/media_stream_video_source.cc",
- "media/stream/media_stream_video_source.h",
- "media/stream/media_stream_video_track.cc",
- "media/stream/media_stream_video_track.h",
- "media/stream/processed_local_audio_source.cc",
- "media/stream/processed_local_audio_source.h",
- "media/stream/remote_media_stream_track_adapter.cc",
- "media/stream/remote_media_stream_track_adapter.h",
- "media/stream/secure_display_link_tracker.h",
- "media/stream/track_audio_renderer.cc",
- "media/stream/track_audio_renderer.h",
- "media/stream/user_media_client_impl.cc",
- "media/stream/user_media_client_impl.h",
- "media/stream/user_media_processor.cc",
- "media/stream/user_media_processor.h",
- "media/stream/video_track_adapter.cc",
- "media/stream/video_track_adapter.h",
- "media/stream/webaudio_media_stream_source.cc",
- "media/stream/webaudio_media_stream_source.h",
- "media/stream/webmediaplayer_ms.cc",
- "media/stream/webmediaplayer_ms.h",
- "media/stream/webmediaplayer_ms_compositor.cc",
- "media/stream/webmediaplayer_ms_compositor.h",
- "media/webrtc/audio_codec_factory.cc",
- "media/webrtc/audio_codec_factory.h",
- "media/webrtc/media_stream_remote_video_source.cc",
- "media/webrtc/media_stream_remote_video_source.h",
- "media/webrtc/media_stream_track_metrics.cc",
- "media/webrtc/media_stream_track_metrics.h",
- "media/webrtc/media_stream_video_webrtc_sink.cc",
- "media/webrtc/media_stream_video_webrtc_sink.h",
- "media/webrtc/peer_connection_dependency_factory.cc",
- "media/webrtc/peer_connection_dependency_factory.h",
- "media/webrtc/peer_connection_remote_audio_source.cc",
- "media/webrtc/peer_connection_remote_audio_source.h",
- "media/webrtc/peer_connection_tracker.cc",
- "media/webrtc/peer_connection_tracker.h",
- "media/webrtc/rtc_certificate.cc",
- "media/webrtc/rtc_certificate.h",
- "media/webrtc/rtc_certificate_generator.cc",
- "media/webrtc/rtc_certificate_generator.h",
- "media/webrtc/rtc_data_channel_handler.cc",
- "media/webrtc/rtc_data_channel_handler.h",
- "media/webrtc/rtc_dtmf_sender_handler.cc",
- "media/webrtc/rtc_dtmf_sender_handler.h",
- "media/webrtc/rtc_error.cc",
- "media/webrtc/rtc_error.h",
- "media/webrtc/rtc_event_log_output_sink.h",
- "media/webrtc/rtc_event_log_output_sink_proxy.cc",
- "media/webrtc/rtc_event_log_output_sink_proxy.h",
- "media/webrtc/rtc_peer_connection_handler.cc",
- "media/webrtc/rtc_peer_connection_handler.h",
- "media/webrtc/rtc_rtp_contributing_source.cc",
- "media/webrtc/rtc_rtp_contributing_source.h",
- "media/webrtc/rtc_rtp_parameters.cc",
- "media/webrtc/rtc_rtp_parameters.h",
- "media/webrtc/rtc_rtp_receiver.cc",
- "media/webrtc/rtc_rtp_receiver.h",
- "media/webrtc/rtc_rtp_sender.cc",
- "media/webrtc/rtc_rtp_sender.h",
- "media/webrtc/rtc_stats.cc",
- "media/webrtc/rtc_stats.h",
- "media/webrtc/rtc_video_decoder.cc",
- "media/webrtc/rtc_video_decoder.h",
- "media/webrtc/rtc_video_decoder_factory.cc",
- "media/webrtc/rtc_video_decoder_factory.h",
- "media/webrtc/rtc_video_encoder.cc",
- "media/webrtc/rtc_video_encoder.h",
- "media/webrtc/rtc_video_encoder_factory.cc",
- "media/webrtc/rtc_video_encoder_factory.h",
- "media/webrtc/stun_field_trial.cc",
- "media/webrtc/stun_field_trial.h",
- "media/webrtc/track_observer.cc",
- "media/webrtc/track_observer.h",
- "media/webrtc/two_keys_adapter_map.h",
- "media/webrtc/webrtc_audio_device_impl.cc",
- "media/webrtc/webrtc_audio_device_impl.h",
- "media/webrtc/webrtc_audio_device_not_impl.cc",
- "media/webrtc/webrtc_audio_device_not_impl.h",
- "media/webrtc/webrtc_audio_renderer.cc",
- "media/webrtc/webrtc_audio_renderer.h",
- "media/webrtc/webrtc_audio_sink.cc",
- "media/webrtc/webrtc_audio_sink.h",
- "media/webrtc/webrtc_media_stream_adapter.cc",
- "media/webrtc/webrtc_media_stream_adapter.h",
- "media/webrtc/webrtc_media_stream_adapter_map.cc",
- "media/webrtc/webrtc_media_stream_adapter_map.h",
- "media/webrtc/webrtc_media_stream_track_adapter.cc",
- "media/webrtc/webrtc_media_stream_track_adapter.h",
- "media/webrtc/webrtc_media_stream_track_adapter_map.cc",
- "media/webrtc/webrtc_media_stream_track_adapter_map.h",
- "media/webrtc/webrtc_set_remote_description_observer.cc",
- "media/webrtc/webrtc_set_remote_description_observer.h",
- "media/webrtc/webrtc_uma_histograms.cc",
- "media/webrtc/webrtc_uma_histograms.h",
- "media/webrtc/webrtc_video_capturer_adapter.cc",
- "media/webrtc/webrtc_video_capturer_adapter.h",
- "media/webrtc/webrtc_video_frame_adapter.cc",
- "media/webrtc/webrtc_video_frame_adapter.h",
- "media/webrtc_local_audio_source_provider.cc",
- "media/webrtc_local_audio_source_provider.h",
- "media/webrtc_logging.cc",
- "media/webrtc_logging.h",
- "media_capture_from_element/canvas_capture_handler.cc",
- "media_capture_from_element/canvas_capture_handler.h",
- "media_capture_from_element/html_audio_element_capturer_source.cc",
- "media_capture_from_element/html_audio_element_capturer_source.h",
- "media_capture_from_element/html_video_element_capturer_source.cc",
- "media_capture_from_element/html_video_element_capturer_source.h",
- "media_recorder/audio_track_encoder.cc",
- "media_recorder/audio_track_encoder.h",
- "media_recorder/audio_track_opus_encoder.cc",
- "media_recorder/audio_track_opus_encoder.h",
- "media_recorder/audio_track_pcm_encoder.cc",
- "media_recorder/audio_track_pcm_encoder.h",
- "media_recorder/audio_track_recorder.cc",
- "media_recorder/audio_track_recorder.h",
- "media_recorder/media_recorder_handler.cc",
- "media_recorder/media_recorder_handler.h",
- "media_recorder/vea_encoder.cc",
- "media_recorder/vea_encoder.h",
- "media_recorder/video_track_recorder.cc",
- "media_recorder/video_track_recorder.h",
- "media_recorder/vpx_encoder.cc",
- "media_recorder/vpx_encoder.h",
- "p2p/empty_network_manager.cc",
- "p2p/empty_network_manager.h",
- "p2p/filtering_network_manager.cc",
- "p2p/filtering_network_manager.h",
- "p2p/host_address_request.cc",
- "p2p/host_address_request.h",
- "p2p/ipc_network_manager.cc",
- "p2p/ipc_network_manager.h",
- "p2p/ipc_socket_factory.cc",
- "p2p/ipc_socket_factory.h",
- "p2p/network_list_observer.h",
- "p2p/network_manager_uma.cc",
- "p2p/network_manager_uma.h",
- "p2p/port_allocator.cc",
- "p2p/port_allocator.h",
- "p2p/socket_client.h",
- "p2p/socket_client_delegate.h",
- "p2p/socket_client_impl.cc",
- "p2p/socket_client_impl.h",
- "p2p/socket_dispatcher.cc",
- "p2p/socket_dispatcher.h",
+ "media/pepper/pepper_to_video_track_adapter.cc",
+ "media/pepper/pepper_to_video_track_adapter.h",
+ "media/pepper/video_track_to_pepper_adapter.cc",
+ "media/pepper/video_track_to_pepper_adapter.h",
+ "pepper/pepper_media_stream_audio_track_host.cc",
+ "pepper/pepper_media_stream_audio_track_host.h",
+ "pepper/pepper_media_stream_track_host_base.cc",
+ "pepper/pepper_media_stream_track_host_base.h",
+ "pepper/pepper_media_stream_video_track_host.cc",
+ "pepper/pepper_media_stream_video_track_host.h",
+ "pepper/pepper_video_destination_host.cc",
+ "pepper/pepper_video_destination_host.h",
+ "pepper/pepper_video_source_host.cc",
+ "pepper/pepper_video_source_host.h",
]
+ }
- if (enable_plugins) {
- sources += [
- "media/pepper/pepper_to_video_track_adapter.cc",
- "media/pepper/pepper_to_video_track_adapter.h",
- "media/pepper/video_track_to_pepper_adapter.cc",
- "media/pepper/video_track_to_pepper_adapter.h",
- "pepper/pepper_media_stream_audio_track_host.cc",
- "pepper/pepper_media_stream_audio_track_host.h",
- "pepper/pepper_media_stream_track_host_base.cc",
- "pepper/pepper_media_stream_track_host_base.h",
- "pepper/pepper_media_stream_video_track_host.cc",
- "pepper/pepper_media_stream_video_track_host.h",
- "pepper/pepper_video_destination_host.cc",
- "pepper/pepper_video_destination_host.h",
- "pepper/pepper_video_source_host.cc",
- "pepper/pepper_video_source_host.h",
- ]
- }
-
- deps += [
- "//crypto",
- "//jingle:jingle_glue",
- "//third_party/libvpx",
- "//third_party/opus",
- "//third_party/webrtc/api:libjingle_logging_api",
- "//third_party/webrtc/api:libjingle_peerconnection_api",
- "//third_party/webrtc/api:optional",
- "//third_party/webrtc/api:rtc_stats_api",
- "//third_party/webrtc/api:video_frame_api",
- "//third_party/webrtc/api:video_frame_api_i420",
- "//third_party/webrtc/api/audio:aec3_factory",
- "//third_party/webrtc/api/audio_codecs:audio_codecs_api",
- "//third_party/webrtc/api/audio_codecs/L16:audio_decoder_L16",
- "//third_party/webrtc/api/audio_codecs/L16:audio_encoder_L16",
- "//third_party/webrtc/api/audio_codecs/g711:audio_decoder_g711",
- "//third_party/webrtc/api/audio_codecs/g711:audio_encoder_g711",
- "//third_party/webrtc/api/audio_codecs/g722:audio_decoder_g722",
- "//third_party/webrtc/api/audio_codecs/g722:audio_encoder_g722",
- "//third_party/webrtc/api/audio_codecs/isac:audio_decoder_isac",
- "//third_party/webrtc/api/audio_codecs/isac:audio_encoder_isac",
- "//third_party/webrtc/api/audio_codecs/opus:audio_decoder_opus",
- "//third_party/webrtc/api/audio_codecs/opus:audio_encoder_opus",
- "//third_party/webrtc/api/video_codecs:video_codecs_api",
- "//third_party/webrtc/common_video:common_video",
- "//third_party/webrtc/media:rtc_internal_video_codecs",
- "//third_party/webrtc/media:rtc_media",
- "//third_party/webrtc/media:rtc_media_base",
- "//third_party/webrtc/modules/audio_device",
- "//third_party/webrtc/modules/audio_processing",
- "//third_party/webrtc/modules/audio_processing:audio_processing_statistics",
- "//third_party/webrtc/modules/audio_processing/aec_dump",
- "//third_party/webrtc/modules/video_coding:video_codec_interface",
- "//third_party/webrtc/modules/video_coding:webrtc_h264",
- "//third_party/webrtc/p2p:libstunprober",
- "//third_party/webrtc/p2p:rtc_p2p",
- "//third_party/webrtc/pc:libjingle_peerconnection",
- "//third_party/webrtc/pc:peerconnection",
- "//third_party/webrtc/pc:rtc_pc",
- "//third_party/webrtc/pc:rtc_pc_base",
- "//third_party/webrtc/rtc_base:rtc_base",
- "//third_party/webrtc/rtc_base:rtc_task_queue",
- "//third_party/webrtc/stats",
- "//third_party/webrtc/system_wrappers",
- "//third_party/webrtc_overrides:init_webrtc",
- ]
- if (rtc_use_h264) {
- sources += [
- "media_recorder/h264_encoder.cc",
- "media_recorder/h264_encoder.h",
- ]
- deps += [ "//third_party/openh264:encoder" ]
- }
- } else {
+ if (rtc_use_h264) {
sources += [
- "media/webrtc_logging.h",
- "media/webrtc_logging_noop.cc",
+ "media_recorder/h264_encoder.cc",
+ "media_recorder/h264_encoder.h",
]
+ deps += [ "//third_party/openh264:encoder" ]
}
if (enable_plugins) {
@@ -1083,7 +1029,7 @@ target(link_target_type, "renderer") {
]
}
- if (enable_basic_printing || enable_print_preview) {
+ if (enable_basic_printing) {
deps += [ "//printing" ]
}
diff --git a/chromium/content/renderer/DEPS b/chromium/content/renderer/DEPS
index 340b6b17d9b..65119d8fb62 100644
--- a/chromium/content/renderer/DEPS
+++ b/chromium/content/renderer/DEPS
@@ -8,7 +8,6 @@ include_rules = [
"+components/url_formatter",
"+components/viz/client",
"+components/viz/common",
- "+cc/blink",
"+content/public/child",
"+content/public/renderer",
"+content/child",
diff --git a/chromium/content/renderer/OWNERS b/chromium/content/renderer/OWNERS
index c367d11096b..9b1fac28656 100644
--- a/chromium/content/renderer/OWNERS
+++ b/chromium/content/renderer/OWNERS
@@ -9,4 +9,8 @@ per-file renderer_font_platform_win.*=scottmg@chromium.org
per-file renderer_font_platform_win.*=cpu@chromium.org
# For surface ID propagation and synchronization
+per-file render_frame_proxy.*=fsamuel@chromium.org
+per-file render_view_impl.*=fsamuel@chromium.org
+per-file render_widget.*=fsamuel@chromium.org
+per-file child_frame_compositor.*=fsamuel@chromium.org
per-file child_frame_compositing_helper.*=fsamuel@chromium.org
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
index 86439122101..1e9b5afec74 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -20,8 +20,10 @@ void AXStateFromBlink(const blink::WebAXObject& o, ui::AXNodeData* dst) {
if (o.CanSetFocusAttribute())
dst->AddState(ax::mojom::State::kFocusable);
- if (o.Role() == blink::kWebAXRolePopUpButton || o.AriaHasPopup())
- dst->AddState(ax::mojom::State::kHaspopup);
+ if (o.HasPopup())
+ dst->SetHasPopup(AXHasPopupFromBlink(o.HasPopup()));
+ else if (o.Role() == blink::kWebAXRolePopUpButton)
+ dst->SetHasPopup(ax::mojom::HasPopup::kMenu);
if (o.IsHovered())
dst->AddState(ax::mojom::State::kHovered);
@@ -133,6 +135,84 @@ ax::mojom::Role AXRoleFromBlink(blink::WebAXRole role) {
return ax::mojom::Role::kDirectory;
case blink::kWebAXRoleDisclosureTriangle:
return ax::mojom::Role::kDisclosureTriangle;
+ case blink::kWebAXRoleDocAbstract:
+ return ax::mojom::Role::kDocAbstract;
+ case blink::kWebAXRoleDocAcknowledgments:
+ return ax::mojom::Role::kDocAcknowledgments;
+ case blink::kWebAXRoleDocAfterword:
+ return ax::mojom::Role::kDocAfterword;
+ case blink::kWebAXRoleDocAppendix:
+ return ax::mojom::Role::kDocAppendix;
+ case blink::kWebAXRoleDocBackLink:
+ return ax::mojom::Role::kDocBackLink;
+ case blink::kWebAXRoleDocBiblioEntry:
+ return ax::mojom::Role::kDocBiblioEntry;
+ case blink::kWebAXRoleDocBibliography:
+ return ax::mojom::Role::kDocBibliography;
+ case blink::kWebAXRoleDocBiblioRef:
+ return ax::mojom::Role::kDocBiblioRef;
+ case blink::kWebAXRoleDocChapter:
+ return ax::mojom::Role::kDocChapter;
+ case blink::kWebAXRoleDocColophon:
+ return ax::mojom::Role::kDocColophon;
+ case blink::kWebAXRoleDocConclusion:
+ return ax::mojom::Role::kDocConclusion;
+ case blink::kWebAXRoleDocCover:
+ return ax::mojom::Role::kDocCover;
+ case blink::kWebAXRoleDocCredit:
+ return ax::mojom::Role::kDocCredit;
+ case blink::kWebAXRoleDocCredits:
+ return ax::mojom::Role::kDocCredits;
+ case blink::kWebAXRoleDocDedication:
+ return ax::mojom::Role::kDocDedication;
+ case blink::kWebAXRoleDocEndnote:
+ return ax::mojom::Role::kDocEndnote;
+ case blink::kWebAXRoleDocEndnotes:
+ return ax::mojom::Role::kDocEndnotes;
+ case blink::kWebAXRoleDocEpigraph:
+ return ax::mojom::Role::kDocEpigraph;
+ case blink::kWebAXRoleDocEpilogue:
+ return ax::mojom::Role::kDocEpilogue;
+ case blink::kWebAXRoleDocErrata:
+ return ax::mojom::Role::kDocErrata;
+ case blink::kWebAXRoleDocExample:
+ return ax::mojom::Role::kDocExample;
+ case blink::kWebAXRoleDocFootnote:
+ return ax::mojom::Role::kDocFootnote;
+ case blink::kWebAXRoleDocForeword:
+ return ax::mojom::Role::kDocForeword;
+ case blink::kWebAXRoleDocGlossary:
+ return ax::mojom::Role::kDocGlossary;
+ case blink::kWebAXRoleDocGlossRef:
+ return ax::mojom::Role::kDocGlossRef;
+ case blink::kWebAXRoleDocIndex:
+ return ax::mojom::Role::kDocIndex;
+ case blink::kWebAXRoleDocIntroduction:
+ return ax::mojom::Role::kDocIntroduction;
+ case blink::kWebAXRoleDocNoteRef:
+ return ax::mojom::Role::kDocNoteRef;
+ case blink::kWebAXRoleDocNotice:
+ return ax::mojom::Role::kDocNotice;
+ case blink::kWebAXRoleDocPageBreak:
+ return ax::mojom::Role::kDocPageBreak;
+ case blink::kWebAXRoleDocPageList:
+ return ax::mojom::Role::kDocPageList;
+ case blink::kWebAXRoleDocPart:
+ return ax::mojom::Role::kDocPart;
+ case blink::kWebAXRoleDocPreface:
+ return ax::mojom::Role::kDocPreface;
+ case blink::kWebAXRoleDocPrologue:
+ return ax::mojom::Role::kDocPrologue;
+ case blink::kWebAXRoleDocPullquote:
+ return ax::mojom::Role::kDocPullquote;
+ case blink::kWebAXRoleDocQna:
+ return ax::mojom::Role::kDocQna;
+ case blink::kWebAXRoleDocSubtitle:
+ return ax::mojom::Role::kDocSubtitle;
+ case blink::kWebAXRoleDocTip:
+ return ax::mojom::Role::kDocTip;
+ case blink::kWebAXRoleDocToc:
+ return ax::mojom::Role::kDocToc;
case blink::kWebAXRoleDocument:
return ax::mojom::Role::kDocument;
case blink::kWebAXRoleEmbeddedObject:
@@ -149,6 +229,12 @@ ax::mojom::Role AXRoleFromBlink(blink::WebAXRole role) {
return ax::mojom::Role::kForm;
case blink::kWebAXRoleGenericContainer:
return ax::mojom::Role::kGenericContainer;
+ case blink::kWebAXRoleGraphicsDocument:
+ return ax::mojom::Role::kGraphicsDocument;
+ case blink::kWebAXRoleGraphicsObject:
+ return ax::mojom::Role::kGraphicsObject;
+ case blink::kWebAXRoleGraphicsSymbol:
+ return ax::mojom::Role::kGraphicsSymbol;
case blink::kWebAXRoleGrid:
return ax::mojom::Role::kGrid;
case blink::kWebAXRoleGroup:
@@ -263,8 +349,6 @@ ax::mojom::Role AXRoleFromBlink(blink::WebAXRole role) {
return ax::mojom::Role::kSliderThumb;
case blink::kWebAXRoleSpinButton:
return ax::mojom::Role::kSpinButton;
- case blink::kWebAXRoleSpinButtonPart:
- return ax::mojom::Role::kSpinButtonPart;
case blink::kWebAXRoleSplitter:
return ax::mojom::Role::kSplitter;
case blink::kWebAXRoleStaticText:
@@ -445,6 +529,20 @@ ax::mojom::TextDirection AXTextDirectionFromBlink(
return ax::mojom::TextDirection::kNone;
}
+ax::mojom::TextPosition AXTextPositionFromBlink(
+ blink::WebAXTextPosition text_position) {
+ switch (text_position) {
+ case blink::kWebAXTextPositionNone:
+ return ax::mojom::TextPosition::kNone;
+ case blink::kWebAXTextPositionSubscript:
+ return ax::mojom::TextPosition::kSubscript;
+ case blink::kWebAXTextPositionSuperscript:
+ return ax::mojom::TextPosition::kSuperscript;
+ }
+ NOTREACHED();
+ return ax::mojom::TextPosition::kNone;
+}
+
ax::mojom::TextStyle AXTextStyleFromBlink(blink::WebAXTextStyle text_style) {
uint32_t browser_text_style =
static_cast<uint32_t>(ax::mojom::TextStyle::kNone);
@@ -488,6 +586,28 @@ ax::mojom::AriaCurrentState AXAriaCurrentStateFromBlink(
return ax::mojom::AriaCurrentState::kNone;
}
+ax::mojom::HasPopup AXHasPopupFromBlink(blink::WebAXHasPopup has_popup) {
+ switch (has_popup) {
+ case blink::kWebAXHasPopupFalse:
+ return ax::mojom::HasPopup::kFalse;
+ case blink::kWebAXHasPopupTrue:
+ return ax::mojom::HasPopup::kTrue;
+ case blink::kWebAXHasPopupMenu:
+ return ax::mojom::HasPopup::kMenu;
+ case blink::kWebAXHasPopupListbox:
+ return ax::mojom::HasPopup::kListbox;
+ case blink::kWebAXHasPopupTree:
+ return ax::mojom::HasPopup::kTree;
+ case blink::kWebAXHasPopupGrid:
+ return ax::mojom::HasPopup::kGrid;
+ case blink::kWebAXHasPopupDialog:
+ return ax::mojom::HasPopup::kDialog;
+ }
+
+ NOTREACHED();
+ return ax::mojom::HasPopup::kFalse;
+}
+
ax::mojom::InvalidState AXInvalidStateFromBlink(
blink::WebAXInvalidState invalid_state) {
switch (invalid_state) {
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h
index 18b471b02ab..0c543f2789e 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.h
@@ -34,11 +34,16 @@ ax::mojom::MarkerType AXMarkerTypeFromBlink(blink::WebAXMarkerType marker_type);
ax::mojom::TextDirection AXTextDirectionFromBlink(
blink::WebAXTextDirection text_direction);
+ax::mojom::TextPosition AXTextPositionFromBlink(
+ blink::WebAXTextPosition text_position);
+
ax::mojom::TextStyle AXTextStyleFromBlink(blink::WebAXTextStyle text_style);
ax::mojom::AriaCurrentState AXAriaCurrentStateFromBlink(
blink::WebAXAriaCurrentState aria_current_state);
+ax::mojom::HasPopup AXHasPopupFromBlink(blink::WebAXHasPopup has_popup);
+
ax::mojom::InvalidState AXInvalidStateFromBlink(
blink::WebAXInvalidState invalid_state);
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
index 173d360e2b6..2e67e084f9c 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_view.h"
#include "ui/accessibility/ax_enum_util.h"
+#include "ui/accessibility/ax_role_properties.h"
using base::ASCIIToUTF16;
using base::UTF16ToUTF8;
@@ -549,6 +550,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
dst->AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize,
src.FontSize());
+ if (src.HasPopup())
+ dst->SetHasPopup(AXHasPopupFromBlink(src.HasPopup()));
+ else if (src.Role() == blink::kWebAXRolePopUpButton)
+ dst->SetHasPopup(ax::mojom::HasPopup::kMenu);
+
if (src.AriaCurrentState()) {
dst->AddIntAttribute(ax::mojom::IntAttribute::kAriaCurrentState,
static_cast<int32_t>(AXAriaCurrentStateFromBlink(
@@ -572,6 +578,12 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
dst->SetTextDirection(AXTextDirectionFromBlink(src.GetTextDirection()));
}
+ if (src.GetTextPosition()) {
+ dst->AddIntAttribute(
+ ax::mojom::IntAttribute::kTextPosition,
+ static_cast<int32_t>(AXTextPositionFromBlink(src.GetTextPosition())));
+ }
+
if (src.TextStyle()) {
dst->AddIntAttribute(
ax::mojom::IntAttribute::kTextStyle,
@@ -651,7 +663,7 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
src.AriaActiveDescendant().AxID());
}
- if (dst->role == ax::mojom::Role::kHeading && src.HeadingLevel()) {
+ if (ui::IsHeading(dst->role) && src.HeadingLevel()) {
dst->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel,
src.HeadingLevel());
} else if ((dst->role == ax::mojom::Role::kTreeItem ||
@@ -772,9 +784,6 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
int column_count = src.ColumnCount();
int row_count = src.RowCount();
if (column_count > 0 && row_count > 0) {
- std::set<int32_t> unique_cell_id_set;
- std::vector<int32_t> cell_ids;
- std::vector<int32_t> unique_cell_ids;
dst->AddIntAttribute(ax::mojom::IntAttribute::kTableColumnCount,
column_count);
dst->AddIntAttribute(ax::mojom::IntAttribute::kTableRowCount,
@@ -783,23 +792,6 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
if (!header.IsDetached())
dst->AddIntAttribute(ax::mojom::IntAttribute::kTableHeaderId,
header.AxID());
- for (int i = 0; i < column_count * row_count; ++i) {
- WebAXObject cell =
- src.CellForColumnAndRow(i % column_count, i / column_count);
- int cell_id = -1;
- if (!cell.IsDetached()) {
- cell_id = cell.AxID();
- if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) {
- unique_cell_id_set.insert(cell_id);
- unique_cell_ids.push_back(cell_id);
- }
- }
- cell_ids.push_back(cell_id);
- }
- dst->AddIntListAttribute(ax::mojom::IntListAttribute::kCellIds,
- cell_ids);
- dst->AddIntListAttribute(ax::mojom::IntListAttribute::kUniqueCellIds,
- unique_cell_ids);
}
int aria_colcount = src.AriaColumnCount();
@@ -957,21 +949,21 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
}
if (src.IsScrollableContainer()) {
- const gfx::Point& scrollOffset = src.GetScrollOffset();
- dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollX, scrollOffset.x());
- dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollY, scrollOffset.y());
+ const gfx::Point& scroll_offset = src.GetScrollOffset();
+ dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollX, scroll_offset.x());
+ dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollY, scroll_offset.y());
- const gfx::Point& minScrollOffset = src.MinimumScrollOffset();
+ const gfx::Point& min_scroll_offset = src.MinimumScrollOffset();
dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin,
- minScrollOffset.x());
+ min_scroll_offset.x());
dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin,
- minScrollOffset.y());
+ min_scroll_offset.y());
- const gfx::Point& maxScrollOffset = src.MaximumScrollOffset();
+ const gfx::Point& max_scroll_offset = src.MaximumScrollOffset();
dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax,
- maxScrollOffset.x());
+ max_scroll_offset.x());
dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax,
- maxScrollOffset.y());
+ max_scroll_offset.y());
}
if (dst->id == image_data_node_id_) {
diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.cc b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
index 28fd14d2b5c..79fd36cffc5 100644
--- a/chromium/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/chromium/content/renderer/accessibility/render_accessibility_impl.cc
@@ -334,7 +334,7 @@ void RenderAccessibilityImpl::HandleAXEvent(const blink::WebAXObject& obj,
// When no accessibility events are in-flight post a task to send
// the events to the browser. We use PostTask so that we can queue
// up additional events.
- render_frame_->GetTaskRunner(blink::TaskType::kUnspecedTimer)
+ render_frame_->GetTaskRunner(blink::TaskType::kInternalDefault)
->PostTask(FROM_HERE,
base::BindOnce(
&RenderAccessibilityImpl::SendPendingAccessibilityEvents,
@@ -566,6 +566,9 @@ void RenderAccessibilityImpl::OnPerformAction(
case ax::mojom::Action::kBlur:
root.Focus();
break;
+ case ax::mojom::Action::kClearAccessibilityFocus:
+ target.ClearAccessibilityFocus();
+ break;
case ax::mojom::Action::kDecrement:
target.Decrement();
break;
@@ -598,6 +601,9 @@ void RenderAccessibilityImpl::OnPerformAction(
case ax::mojom::Action::kFocus:
target.Focus();
break;
+ case ax::mojom::Action::kSetAccessibilityFocus:
+ target.SetAccessibilityFocus();
+ break;
case ax::mojom::Action::kSetScrollOffset:
target.SetScrollOffset(
WebPoint(data.target_point.x(), data.target_point.y()));
diff --git a/chromium/content/renderer/android/synchronous_compositor_filter.cc b/chromium/content/renderer/android/synchronous_compositor_filter.cc
deleted file mode 100644
index d7db19946e8..00000000000
--- a/chromium/content/renderer/android/synchronous_compositor_filter.cc
+++ /dev/null
@@ -1,208 +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.
-
-#include "content/renderer/android/synchronous_compositor_filter.h"
-
-#include <utility>
-
-#include "base/callback.h"
-#include "base/stl_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/common/input/sync_compositor_messages.h"
-#include "content/common/input_messages.h"
-#include "content/renderer/android/synchronous_compositor_proxy_chrome_ipc.h"
-#include "ipc/ipc_message_macros.h"
-#include "ui/events/blink/synchronous_input_handler_proxy.h"
-
-namespace content {
-
-SynchronousCompositorFilter::SynchronousCompositorFilter(
- const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner)
- : compositor_task_runner_(compositor_task_runner), filter_ready_(false) {
- DCHECK(compositor_task_runner_);
-}
-
-SynchronousCompositorFilter::~SynchronousCompositorFilter() {}
-
-void SynchronousCompositorFilter::OnFilterAdded(IPC::Channel* channel) {
- io_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- sender_ = channel;
- compositor_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&SynchronousCompositorFilter::FilterReadyOnCompositorThread,
- this));
-}
-
-void SynchronousCompositorFilter::OnFilterRemoved() {
- sender_ = nullptr;
-}
-
-void SynchronousCompositorFilter::OnChannelClosing() {
- sender_ = nullptr;
-}
-
-bool SynchronousCompositorFilter::OnMessageReceived(
- const IPC::Message& message) {
- DCHECK_EQ(SyncCompositorMsgStart, IPC_MESSAGE_ID_CLASS(message.type()));
- bool result = compositor_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &SynchronousCompositorFilter::OnMessageReceivedOnCompositorThread,
- this, message));
- if (!result && message.is_sync()) {
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
- reply->set_reply_error();
- SendOnIOThread(reply);
- }
- return result;
-}
-
-SynchronousCompositorProxyChromeIPC* SynchronousCompositorFilter::FindProxy(
- int routing_id) {
- auto itr = sync_compositor_map_.find(routing_id);
- if (itr == sync_compositor_map_.end()) {
- return nullptr;
- }
- return itr->second.get();
-}
-
-bool SynchronousCompositorFilter::GetSupportedMessageClasses(
- std::vector<uint32_t>* supported_message_classes) const {
- supported_message_classes->push_back(SyncCompositorMsgStart);
- return true;
-}
-
-void SynchronousCompositorFilter::OnMessageReceivedOnCompositorThread(
- const IPC::Message& message) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
-
- SynchronousCompositorProxyChromeIPC* proxy = FindProxy(message.routing_id());
- if (proxy) {
- proxy->OnMessageReceived(message);
- return;
- }
-
- if (!message.is_sync())
- return;
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
- reply->set_reply_error();
- Send(reply);
-}
-
-bool SynchronousCompositorFilter::Send(IPC::Message* message) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- DCHECK(filter_ready_);
- if (!io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&SynchronousCompositorFilter::SendOnIOThread,
- this, message))) {
- delete message;
- DLOG(WARNING) << "IO PostTask failed";
- return false;
- }
- return true;
-}
-
-void SynchronousCompositorFilter::SendOnIOThread(IPC::Message* message) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- DCHECK(sender_);
- if (!sender_) {
- delete message;
- return;
- }
- bool result = sender_->Send(message);
- if (!result)
- DLOG(WARNING) << "Failed to send message";
-}
-
-void SynchronousCompositorFilter::FilterReadyOnCompositorThread() {
- DCHECK(!filter_ready_);
- filter_ready_ = true;
- for (const auto& entry_pair : synchronous_input_handler_proxy_map_) {
- DCHECK(entry_pair.second);
- int routing_id = entry_pair.first;
- CreateSynchronousCompositorProxy(routing_id, entry_pair.second);
- auto layer_tree_frame_sink_entry =
- layer_tree_frame_sink_map_.find(routing_id);
- if (layer_tree_frame_sink_entry != layer_tree_frame_sink_map_.end()) {
- SetProxyLayerTreeFrameSink(routing_id,
- layer_tree_frame_sink_entry->second);
- }
- }
-}
-
-void SynchronousCompositorFilter::RegisterLayerTreeFrameSink(
- int routing_id,
- SynchronousLayerTreeFrameSink* layer_tree_frame_sink) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- DCHECK(layer_tree_frame_sink);
- SynchronousCompositorProxy* proxy = FindProxy(routing_id);
- if (proxy) {
- proxy->SetLayerTreeFrameSink(layer_tree_frame_sink);
- } else {
- DCHECK(layer_tree_frame_sink_map_.find(routing_id) ==
- layer_tree_frame_sink_map_.end());
- layer_tree_frame_sink_map_[routing_id] = layer_tree_frame_sink;
- }
-}
-
-void SynchronousCompositorFilter::UnregisterLayerTreeFrameSink(
- int routing_id,
- SynchronousLayerTreeFrameSink* layer_tree_frame_sink) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- DCHECK(layer_tree_frame_sink);
- auto entry = layer_tree_frame_sink_map_.find(routing_id);
- if (entry != layer_tree_frame_sink_map_.end())
- layer_tree_frame_sink_map_.erase(entry);
-}
-
-void SynchronousCompositorFilter::CreateSynchronousCompositorProxy(
- int routing_id,
- ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
- DCHECK(sync_compositor_map_.find(routing_id) == sync_compositor_map_.end());
- auto proxy = std::make_unique<SynchronousCompositorProxyChromeIPC>(
- routing_id, this, synchronous_input_handler_proxy);
- proxy->Init();
- sync_compositor_map_[routing_id] = std::move(proxy);
-}
-
-void SynchronousCompositorFilter::SetProxyLayerTreeFrameSink(
- int routing_id,
- SynchronousLayerTreeFrameSink* layer_tree_frame_sink) {
- DCHECK(layer_tree_frame_sink);
- SynchronousCompositorProxy* proxy = FindProxy(routing_id);
- DCHECK(proxy);
- proxy->SetLayerTreeFrameSink(layer_tree_frame_sink);
-}
-
-void SynchronousCompositorFilter::DidAddSynchronousHandlerProxy(
- int routing_id,
- ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- DCHECK(synchronous_input_handler_proxy);
- if (filter_ready_) {
- CreateSynchronousCompositorProxy(routing_id,
- synchronous_input_handler_proxy);
- auto entry = layer_tree_frame_sink_map_.find(routing_id);
- if (entry != layer_tree_frame_sink_map_.end())
- SetProxyLayerTreeFrameSink(routing_id, entry->second);
- } else {
- auto*& mapped_synchronous_input_handler_proxy =
- synchronous_input_handler_proxy_map_[routing_id];
- DCHECK(!mapped_synchronous_input_handler_proxy);
- mapped_synchronous_input_handler_proxy = synchronous_input_handler_proxy;
- }
-}
-
-void SynchronousCompositorFilter::DidRemoveSynchronousHandlerProxy(
- int routing_id) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- if (base::ContainsKey(sync_compositor_map_, routing_id)) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- sync_compositor_map_.erase(routing_id);
- }
- if (base::ContainsKey(synchronous_input_handler_proxy_map_, routing_id))
- synchronous_input_handler_proxy_map_.erase(routing_id);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/android/synchronous_compositor_filter.h b/chromium/content/renderer/android/synchronous_compositor_filter.h
deleted file mode 100644
index 4e1637fb1cc..00000000000
--- a/chromium/content/renderer/android/synchronous_compositor_filter.h
+++ /dev/null
@@ -1,112 +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 CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_FILTER_H_
-#define CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_FILTER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "content/renderer/android/synchronous_compositor_registry.h"
-#include "content/renderer/input/input_handler_manager_client.h"
-#include "ipc/ipc_sender.h"
-#include "ipc/message_filter.h"
-
-namespace ui {
-class SynchronousInputHandlerProxy;
-}
-
-namespace content {
-
-class SynchronousCompositorProxyChromeIPC;
-
-class SynchronousCompositorFilter
- : public IPC::MessageFilter,
- public IPC::Sender,
- public SynchronousCompositorRegistry,
- public SynchronousInputHandlerProxyClient {
- public:
- SynchronousCompositorFilter(const scoped_refptr<base::SingleThreadTaskRunner>&
- compositor_task_runner);
-
- // IPC::MessageFilter overrides.
- void OnFilterAdded(IPC::Channel* channel) override;
- void OnFilterRemoved() override;
- void OnChannelClosing() override;
- bool OnMessageReceived(const IPC::Message& message) override;
- bool GetSupportedMessageClasses(
- std::vector<uint32_t>* supported_message_classes) const override;
-
- // IPC::Sender overrides.
- bool Send(IPC::Message* message) override;
-
- // SynchronousCompositorRegistry overrides.
- void RegisterLayerTreeFrameSink(
- int routing_id,
- SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override;
- void UnregisterLayerTreeFrameSink(
- int routing_id,
- SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override;
-
- // SynchronousInputHandlerProxyClient overrides.
- void DidAddSynchronousHandlerProxy(
- int routing_id,
- ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy)
- override;
- void DidRemoveSynchronousHandlerProxy(int routing_id) override;
-
- private:
- ~SynchronousCompositorFilter() override;
-
- // IO thread methods.
- void SendOnIOThread(IPC::Message* message);
-
- // Compositor thread methods.
- void FilterReadyOnCompositorThread();
- void OnMessageReceivedOnCompositorThread(const IPC::Message& message);
- void CreateSynchronousCompositorProxy(
- int routing_id,
- ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy);
- void SetProxyLayerTreeFrameSink(
- int routing_id,
- SynchronousLayerTreeFrameSink* layer_tree_frame_sink);
- void UnregisterObjects(int routing_id);
- void RemoveEntryIfNeeded(int routing_id);
- SynchronousCompositorProxyChromeIPC* FindProxy(int routing_id);
-
- const scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
-
- // The sender_ only gets invoked on the thread corresponding to io_loop_.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- IPC::Sender* sender_;
-
- // Compositor thread-only fields.
- using SyncCompositorMap =
- std::unordered_map<int /* routing_id */,
- std::unique_ptr<SynchronousCompositorProxyChromeIPC>>;
- SyncCompositorMap sync_compositor_map_;
-
- bool filter_ready_;
- using SynchronousInputHandlerProxyMap =
- base::hash_map<int, ui::SynchronousInputHandlerProxy*>;
- using LayerTreeFrameSinkMap =
- base::hash_map<int, SynchronousLayerTreeFrameSink*>;
-
- // This is only used before FilterReadyOnCompositorThread.
- SynchronousInputHandlerProxyMap synchronous_input_handler_proxy_map_;
-
- // This is only used if input_handler_proxy has not been registered.
- LayerTreeFrameSinkMap layer_tree_frame_sink_map_;
-
- DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_FILTER_H_
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.cc b/chromium/content/renderer/android/synchronous_compositor_proxy.cc
index f5424a95681..441d8e860b7 100644
--- a/chromium/content/renderer/android/synchronous_compositor_proxy.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_proxy.cc
@@ -7,7 +7,6 @@
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/memory/shared_memory.h"
-#include "cc/ipc/cc_param_traits.h"
#include "content/common/android/sync_compositor_statics.h"
#include "content/common/input/sync_compositor_messages.h"
#include "content/public/common/content_switches.h"
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.cc b/chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.cc
deleted file mode 100644
index 4809e8592df..00000000000
--- a/chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2017 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/renderer/android/synchronous_compositor_proxy_chrome_ipc.h"
-
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#include "base/memory/shared_memory.h"
-#include "cc/ipc/cc_param_traits.h"
-#include "content/common/android/sync_compositor_statics.h"
-#include "content/common/input/sync_compositor_messages.h"
-#include "content/public/common/content_switches.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_sender.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkImageInfo.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/gfx/skia_util.h"
-
-namespace content {
-
-SynchronousCompositorProxyChromeIPC::SynchronousCompositorProxyChromeIPC(
- int routing_id,
- IPC::Sender* sender,
- ui::SynchronousInputHandlerProxy* input_handler_proxy)
- : SynchronousCompositorProxy(input_handler_proxy),
- routing_id_(routing_id),
- sender_(sender) {}
-
-SynchronousCompositorProxyChromeIPC::~SynchronousCompositorProxyChromeIPC() {}
-
-void SynchronousCompositorProxyChromeIPC::Send(IPC::Message* message) {
- sender_->Send(message);
-}
-
-void SynchronousCompositorProxyChromeIPC::OnMessageReceived(
- const IPC::Message& message) {
- IPC_BEGIN_MESSAGE_MAP(SynchronousCompositorProxyChromeIPC, message)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_ComputeScroll, ComputeScroll)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncCompositorMsg_DemandDrawHw,
- OnDemandDrawHw)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_DemandDrawHwAsync, DemandDrawHwAsync)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetSharedMemory, OnSetSharedMemory)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_ZeroSharedMemory, ZeroSharedMemory)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncCompositorMsg_DemandDrawSw,
- OnDemandDrawSw)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_ZoomBy, OnZoomBy)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetScroll, SetScroll)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetMemoryPolicy, SetMemoryPolicy)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_ReclaimResources, ReclaimResources)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetBeginFramePaused,
- SetBeginFrameSourcePaused)
- IPC_MESSAGE_HANDLER(SyncCompositorMsg_BeginFrame, BeginFrame)
- IPC_END_MESSAGE_MAP()
-}
-
-void SynchronousCompositorProxyChromeIPC::OnDemandDrawHw(
- const SyncCompositorDemandDrawHwParams& params,
- IPC::Message* reply_message) {
- DCHECK(reply_message);
- DemandDrawHw(params,
- base::BindOnce(
- &SynchronousCompositorProxyChromeIPC::SendDemandDrawHwReply,
- base::Unretained(this), reply_message));
-}
-
-void SynchronousCompositorProxyChromeIPC::OnDemandDrawSw(
- const SyncCompositorDemandDrawSwParams& params,
- IPC::Message* reply_message) {
- DemandDrawSw(params,
- base::BindOnce(
- &SynchronousCompositorProxyChromeIPC::SendDemandDrawSwReply,
- base::Unretained(this), reply_message));
-}
-
-void SynchronousCompositorProxyChromeIPC::SendDemandDrawHwAsyncReply(
- const SyncCompositorCommonRendererParams& common_renderer_params,
- uint32_t layer_tree_frame_sink_id,
- uint32_t metadata_version,
- base::Optional<viz::CompositorFrame> frame) {
- Send(new SyncCompositorHostMsg_ReturnFrame(
- routing_id_, layer_tree_frame_sink_id, metadata_version, frame));
-}
-
-void SynchronousCompositorProxyChromeIPC::SendDemandDrawHwReply(
- IPC::Message* reply_message,
- const SyncCompositorCommonRendererParams& common_renderer_params,
- uint32_t layer_tree_frame_sink_id,
- uint32_t metadata_version,
- base::Optional<viz::CompositorFrame> frame) {
- SyncCompositorMsg_DemandDrawHw::WriteReplyParams(
- reply_message, common_renderer_params, layer_tree_frame_sink_id,
- metadata_version, frame);
- Send(reply_message);
-}
-
-void SynchronousCompositorProxyChromeIPC::SendDemandDrawSwReply(
- IPC::Message* reply_message,
- const SyncCompositorCommonRendererParams& common_renderer_params,
- uint32_t metadata_version,
- base::Optional<viz::CompositorFrameMetadata> metadata) {
- SyncCompositorMsg_DemandDrawSw::WriteReplyParams(
- reply_message, common_renderer_params, metadata_version, metadata);
- Send(reply_message);
-}
-
-void SynchronousCompositorProxyChromeIPC::SendAsyncRendererStateIfNeeded() {
- // If any of the sync IPCs are in flight avoid pushing an asynch update
- // state message as that is pointless as we will send the updated state
- // with the response when the compositor frame is submitted.
- if (hardware_draw_reply_ || software_draw_reply_ || zoom_by_reply_)
- return;
- SyncCompositorCommonRendererParams params;
- PopulateCommonParams(&params);
-
- Send(new SyncCompositorHostMsg_UpdateState(routing_id_, params));
-}
-
-void SynchronousCompositorProxyChromeIPC::OnSetSharedMemory(
- const SyncCompositorSetSharedMemoryParams& params,
- bool* success,
- SyncCompositorCommonRendererParams* common_renderer_params) {
- *success = false;
- SetSharedMemory(
- params,
- base::BindOnce(&SynchronousCompositorProxyChromeIPC::SetSharedMemoryReply,
- base::Unretained(this), success, common_renderer_params));
-}
-
-void SynchronousCompositorProxyChromeIPC::SetSharedMemoryReply(
- bool* out_success,
- SyncCompositorCommonRendererParams* out_common_renderer_params,
- bool success,
- const SyncCompositorCommonRendererParams& common_renderer_params) {
- *out_success = success;
- *out_common_renderer_params = common_renderer_params;
-}
-
-void SynchronousCompositorProxyChromeIPC::OnZoomBy(
- float zoom_delta,
- const gfx::Point& anchor,
- SyncCompositorCommonRendererParams* common_renderer_params) {
- ZoomBy(zoom_delta, anchor,
- base::BindOnce(&SynchronousCompositorProxyChromeIPC::ZoomByReply,
- base::Unretained(this), common_renderer_params));
-}
-
-void SynchronousCompositorProxyChromeIPC::ZoomByReply(
- SyncCompositorCommonRendererParams* output_params,
- const SyncCompositorCommonRendererParams& params) {
- *output_params = params;
-}
-
-void SynchronousCompositorProxyChromeIPC::LayerTreeFrameSinkCreated() {
- Send(new SyncCompositorHostMsg_LayerTreeFrameSinkCreated(routing_id_));
-}
-
-void SynchronousCompositorProxyChromeIPC::SendBeginFrameResponse(
- const content::SyncCompositorCommonRendererParams& param) {
- Send(new SyncCompositorHostMsg_BeginFrameResponse(routing_id_, param));
-}
-
-void SynchronousCompositorProxyChromeIPC::SendSetNeedsBeginFrames(
- bool needs_begin_frames) {
- Send(new SyncCompositorHostMsg_SetNeedsBeginFrames(routing_id_,
- needs_begin_frames));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.h b/chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.h
deleted file mode 100644
index ac87956db2b..00000000000
--- a/chromium/content/renderer/android/synchronous_compositor_proxy_chrome_ipc.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 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_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_PROXY_CHROME_IPC_H_
-#define CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_PROXY_CHROME_IPC_H_
-
-#include "content/renderer/android/synchronous_compositor_proxy.h"
-
-namespace IPC {
-class Message;
-class Sender;
-} // namespace IPC
-
-namespace content {
-
-// This class implements the SynchronousCompositorProxy with
-// IPC messaging backed by Chrome IPC.
-class SynchronousCompositorProxyChromeIPC : public SynchronousCompositorProxy {
- public:
- SynchronousCompositorProxyChromeIPC(
- int routing_id,
- IPC::Sender* sender,
- ui::SynchronousInputHandlerProxy* input_handler_proxy);
- ~SynchronousCompositorProxyChromeIPC() override;
-
- void Send(IPC::Message* message);
- void OnMessageReceived(const IPC::Message& message);
-
- protected:
- void SendSetNeedsBeginFrames(bool needs_begin_frames) final;
- void SendAsyncRendererStateIfNeeded() final;
- void LayerTreeFrameSinkCreated() final;
- void SendBeginFrameResponse(
- const content::SyncCompositorCommonRendererParams&) final;
- void SendDemandDrawHwAsyncReply(
- const content::SyncCompositorCommonRendererParams&,
- uint32_t layer_tree_frame_sink_id,
- uint32_t metadata_version,
- base::Optional<viz::CompositorFrame>) final;
-
- private:
- // IPC handlers.
- void OnSetSharedMemory(
- const SyncCompositorSetSharedMemoryParams& params,
- bool* success,
- SyncCompositorCommonRendererParams* common_renderer_params);
- void OnDemandDrawHw(const SyncCompositorDemandDrawHwParams& params,
- IPC::Message* reply_message);
- void OnDemandDrawSw(const SyncCompositorDemandDrawSwParams& params,
- IPC::Message* reply_message);
-
- void OnZoomBy(float zoom_delta,
- const gfx::Point& anchor,
- SyncCompositorCommonRendererParams* common_renderer_params);
-
- void SendDemandDrawHwReply(
- IPC::Message* reply_message,
- const SyncCompositorCommonRendererParams& common_renderer_params,
- uint32_t layer_tree_frame_sink_id,
- uint32_t metadata_version,
- base::Optional<viz::CompositorFrame> frame);
- void SendDemandDrawSwReply(
- IPC::Message* reply_message,
- const SyncCompositorCommonRendererParams& common_renderer_params,
- uint32_t metadata_version,
- base::Optional<viz::CompositorFrameMetadata> metadata);
- void ZoomByReply(SyncCompositorCommonRendererParams* output_params,
- const SyncCompositorCommonRendererParams& params);
- void SetSharedMemoryReply(
- bool* out_success,
- SyncCompositorCommonRendererParams* out_common_renderer_params,
- bool success,
- const SyncCompositorCommonRendererParams& common_renderer_params);
-
- const int routing_id_;
- IPC::Sender* const sender_;
-
- DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorProxyChromeIPC);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_PROXY_CHROME_IPC_H_
diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
index f942bf9dd1d..2b66ba1ad54 100644
--- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
+++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -27,7 +27,6 @@
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "content/common/view_messages.h"
-#include "content/renderer/android/synchronous_compositor_filter.h"
#include "content/renderer/android/synchronous_compositor_registry.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "content/renderer/render_thread_impl.h"
@@ -102,9 +101,9 @@ class SynchronousLayerTreeFrameSink::SoftwareOutputSurface
gfx::BufferFormat GetOverlayBufferFormat() const override {
return gfx::BufferFormat::RGBX_8888;
}
- bool SurfaceIsSuspendForRecycle() const override { return false; }
bool HasExternalStencilTest() const override { return false; }
void ApplyExternalStencil() override {}
+ unsigned UpdateGpuFence() override { return 0; }
};
SynchronousLayerTreeFrameSink::SynchronousLayerTreeFrameSink(
@@ -121,8 +120,7 @@ SynchronousLayerTreeFrameSink::SynchronousLayerTreeFrameSink(
: cc::LayerTreeFrameSink(std::move(context_provider),
std::move(worker_context_provider),
std::move(compositor_task_runner),
- gpu_memory_buffer_manager,
- nullptr),
+ gpu_memory_buffer_manager),
routing_id_(routing_id),
layer_tree_frame_sink_id_(layer_tree_frame_sink_id),
registry_(registry),
diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h
index fe175cacf57..380c3109a16 100644
--- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h
+++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -14,6 +14,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/managed_memory_policy.h"
@@ -171,6 +172,8 @@ class SynchronousLayerTreeFrameSink
void DisplayDidDrawAndSwap() override {}
void DisplayDidReceiveCALayerParams(
const gfx::CALayerParams& ca_layer_params) override {}
+ void DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) override {}
};
// TODO(danakj): These don't to be stored in unique_ptrs when OutputSurface
diff --git a/chromium/content/renderer/appcache/OWNERS b/chromium/content/renderer/appcache/OWNERS
index 21ddbb8551d..db1043cbffe 100644
--- a/chromium/content/renderer/appcache/OWNERS
+++ b/chromium/content/renderer/appcache/OWNERS
@@ -1,8 +1,5 @@
pwnall@chromium.org
jsbell@chromium.org
-# OOO until this comment is removed.
-michaeln@chromium.org
-
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>AppCache
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc
index c5fe59a5237..d64895137a7 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc
@@ -95,7 +95,8 @@ BrowserPlugin::BrowserPlugin(
ready_(false),
browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
delegate_(delegate),
- task_runner_(render_frame->GetTaskRunner(blink::TaskType::kUnthrottled)),
+ task_runner_(
+ render_frame->GetTaskRunner(blink::TaskType::kInternalDefault)),
weak_ptr_factory_(this) {
browser_plugin_instance_id_ =
BrowserPluginManager::Get()->GetNextInstanceID();
@@ -126,8 +127,8 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestReady, OnGuestReady)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_EnableAutoResize, OnEnableAutoResize)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_DisableAutoResize, OnDisableAutoResize)
- IPC_MESSAGE_HANDLER(BrowserPluginMsg_ResizeDueToAutoResize,
- OnResizeDueToAutoResize)
+ IPC_MESSAGE_HANDLER(BrowserPluginMsg_DidUpdateVisualProperties,
+ OnDidUpdateVisualProperties)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
#if defined(USE_AURA)
@@ -209,7 +210,7 @@ void BrowserPlugin::Attach() {
}
}
- sent_resize_params_ = base::nullopt;
+ sent_visual_properties_ = base::nullopt;
}
void BrowserPlugin::Detach() {
@@ -218,7 +219,7 @@ void BrowserPlugin::Detach() {
attached_ = false;
guest_crashed_ = false;
- web_layer_ = nullptr;
+ embedded_layer_ = nullptr;
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_Detach(browser_plugin_instance_id_));
@@ -250,57 +251,72 @@ void BrowserPlugin::CreateMusWindowAndEmbed(
}
#endif
-void BrowserPlugin::WasResized() {
- bool size_changed = !sent_resize_params_ ||
- sent_resize_params_->auto_resize_enabled !=
- pending_resize_params_.auto_resize_enabled ||
- sent_resize_params_->min_size_for_auto_resize !=
- pending_resize_params_.min_size_for_auto_resize ||
- sent_resize_params_->max_size_for_auto_resize !=
- pending_resize_params_.max_size_for_auto_resize ||
- sent_resize_params_->local_frame_size !=
- pending_resize_params_.local_frame_size ||
- sent_resize_params_->screen_space_rect.size() !=
- pending_resize_params_.screen_space_rect.size() ||
- sent_resize_params_->auto_resize_sequence_number !=
- pending_resize_params_.auto_resize_sequence_number;
-
- bool synchronized_params_changed =
- !sent_resize_params_ || size_changed ||
- sent_resize_params_->screen_info != pending_resize_params_.screen_info;
-
- if (synchronized_params_changed)
+void BrowserPlugin::SynchronizeVisualProperties() {
+ bool size_changed = !sent_visual_properties_ ||
+ sent_visual_properties_->auto_resize_enabled !=
+ pending_visual_properties_.auto_resize_enabled ||
+ sent_visual_properties_->min_size_for_auto_resize !=
+ pending_visual_properties_.min_size_for_auto_resize ||
+ sent_visual_properties_->max_size_for_auto_resize !=
+ pending_visual_properties_.max_size_for_auto_resize ||
+ sent_visual_properties_->local_frame_size !=
+ pending_visual_properties_.local_frame_size ||
+ sent_visual_properties_->screen_space_rect.size() !=
+ pending_visual_properties_.screen_space_rect.size();
+
+ // Note that the following flag is true if the capture sequence number
+ // actually changed. That is, it is false if we did not have
+ // |sent_visual_properties_|, which is different from the other local flags
+ // here.
+ bool capture_sequence_number_changed =
+ sent_visual_properties_ &&
+ sent_visual_properties_->capture_sequence_number !=
+ pending_visual_properties_.capture_sequence_number;
+
+ bool synchronized_props_changed =
+ !sent_visual_properties_ || size_changed ||
+ sent_visual_properties_->screen_info !=
+ pending_visual_properties_.screen_info ||
+ capture_sequence_number_changed;
+
+ if (synchronized_props_changed)
parent_local_surface_id_allocator_.GenerateId();
if (enable_surface_synchronization_ && frame_sink_id_.is_valid()) {
- // TODO(vmpstr): When capture_sequence_number is available, the deadline
- // should be infinite if the sequence number has changed.
+ // If we're synchronizing surfaces, then use an infinite deadline to ensure
+ // everything is synchronized.
+ cc::DeadlinePolicy deadline =
+ capture_sequence_number_changed
+ ? cc::DeadlinePolicy::UseInfiniteDeadline()
+ : cc::DeadlinePolicy::UseDefaultDeadline();
compositing_helper_->SetPrimarySurfaceId(
viz::SurfaceId(frame_sink_id_, GetLocalSurfaceId()),
- screen_space_rect().size(), cc::DeadlinePolicy::UseDefaultDeadline());
+ screen_space_rect().size(), deadline);
}
- bool position_changed = !sent_resize_params_ ||
- sent_resize_params_->screen_space_rect.origin() !=
- pending_resize_params_.screen_space_rect.origin();
- bool resize_params_changed = synchronized_params_changed || position_changed;
+ bool position_changed =
+ !sent_visual_properties_ ||
+ sent_visual_properties_->screen_space_rect.origin() !=
+ pending_visual_properties_.screen_space_rect.origin();
+ bool visual_properties_changed =
+ synchronized_props_changed || position_changed;
- if (resize_params_changed && attached()) {
+ if (visual_properties_changed && attached()) {
// Let the browser know about the updated view rect.
BrowserPluginManager::Get()->Send(
- new BrowserPluginHostMsg_UpdateResizeParams(browser_plugin_instance_id_,
- GetLocalSurfaceId(),
- pending_resize_params_));
+ new BrowserPluginHostMsg_SynchronizeVisualProperties(
+ browser_plugin_instance_id_, GetLocalSurfaceId(),
+ pending_visual_properties_));
}
if (delegate_ && size_changed)
delegate_->DidResizeElement(screen_space_rect().size());
- if (resize_params_changed && attached())
- sent_resize_params_ = pending_resize_params_;
+ if (visual_properties_changed && attached())
+ sent_visual_properties_ = pending_visual_properties_;
#if defined(USE_AURA)
- if (features::IsMusEnabled() && mus_embedded_frame_) {
+ if (features::IsMashEnabled() && mus_embedded_frame_) {
mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(),
FrameRectInPixels());
}
@@ -323,7 +339,7 @@ void BrowserPlugin::OnAttachACK(
attached_ = true;
if (child_local_surface_id)
parent_local_surface_id_allocator_.Reset(*child_local_surface_id);
- WasResized();
+ SynchronizeVisualProperties();
}
void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
@@ -336,28 +352,35 @@ void BrowserPlugin::OnGuestReady(int browser_plugin_instance_id,
const viz::FrameSinkId& frame_sink_id) {
guest_crashed_ = false;
frame_sink_id_ = frame_sink_id;
- sent_resize_params_ = base::nullopt;
- WasResized();
+ sent_visual_properties_ = base::nullopt;
+ SynchronizeVisualProperties();
}
-void BrowserPlugin::OnResizeDueToAutoResize(int browser_plugin_instance_id,
- uint64_t sequence_number) {
- pending_resize_params_.auto_resize_sequence_number = sequence_number;
- WasResized();
+void BrowserPlugin::OnDidUpdateVisualProperties(
+ int browser_plugin_instance_id,
+ const cc::RenderFrameMetadata& metadata) {
+ if (!parent_local_surface_id_allocator_.UpdateFromChild(
+ metadata.local_surface_id.value_or(viz::LocalSurfaceId()))) {
+ return;
+ }
+
+ // The viz::LocalSurfaceId has changed so we call SynchronizeVisualProperties
+ // here to embed it.
+ SynchronizeVisualProperties();
}
void BrowserPlugin::OnEnableAutoResize(int browser_plugin_instance_id,
const gfx::Size& min_size,
const gfx::Size& max_size) {
- pending_resize_params_.auto_resize_enabled = true;
- pending_resize_params_.min_size_for_auto_resize = min_size;
- pending_resize_params_.max_size_for_auto_resize = max_size;
- WasResized();
+ pending_visual_properties_.auto_resize_enabled = true;
+ pending_visual_properties_.min_size_for_auto_resize = min_size;
+ pending_visual_properties_.max_size_for_auto_resize = max_size;
+ SynchronizeVisualProperties();
}
void BrowserPlugin::OnDisableAutoResize(int browser_plugin_instance_id) {
- pending_resize_params_.auto_resize_enabled = false;
- WasResized();
+ pending_visual_properties_.auto_resize_enabled = false;
+ SynchronizeVisualProperties();
}
void BrowserPlugin::OnSetCursor(int browser_plugin_instance_id,
@@ -418,7 +441,7 @@ gfx::Rect BrowserPlugin::FrameRectInPixels() const {
}
float BrowserPlugin::GetDeviceScaleFactor() const {
- return pending_resize_params_.screen_info.device_scale_factor;
+ return pending_visual_properties_.screen_info.device_scale_factor;
}
void BrowserPlugin::UpdateInternalInstanceId() {
@@ -442,14 +465,20 @@ void BrowserPlugin::UpdateGuestFocusState(blink::WebFocusType focus_type) {
}
void BrowserPlugin::ScreenInfoChanged(const ScreenInfo& screen_info) {
- pending_resize_params_.screen_info = screen_info;
+ pending_visual_properties_.screen_info = screen_info;
if (guest_crashed_) {
// Update the sad page to match the current ScreenInfo.
compositing_helper_->ChildFrameGone(screen_space_rect().size(),
screen_info.device_scale_factor);
return;
}
- WasResized();
+ SynchronizeVisualProperties();
+}
+
+void BrowserPlugin::UpdateCaptureSequenceNumber(
+ uint32_t capture_sequence_number) {
+ pending_visual_properties_.capture_sequence_number = capture_sequence_number;
+ SynchronizeVisualProperties();
}
bool BrowserPlugin::ShouldGuestBeFocused() const {
@@ -574,14 +603,14 @@ void BrowserPlugin::UpdateGeometry(const WebRect& plugin_rect_in_viewport,
ready_ = true;
}
- pending_resize_params_.screen_space_rect = screen_space_rect;
+ pending_visual_properties_.screen_space_rect = screen_space_rect;
if (guest_crashed_) {
// Update the sad page to match the current ScreenInfo.
compositing_helper_->ChildFrameGone(screen_space_rect.size(),
screen_info().device_scale_factor);
return;
}
- WasResized();
+ SynchronizeVisualProperties();
}
void BrowserPlugin::UpdateFocus(bool focused, blink::WebFocusType focus_type) {
@@ -823,14 +852,15 @@ void BrowserPlugin::OnMusEmbeddedFrameSinkIdAllocated(
}
#endif
-blink::WebLayer* BrowserPlugin::GetLayer() {
- return web_layer_.get();
+cc::Layer* BrowserPlugin::GetLayer() {
+ return embedded_layer_.get();
}
-void BrowserPlugin::SetLayer(std::unique_ptr<blink::WebLayer> web_layer) {
+void BrowserPlugin::SetLayer(scoped_refptr<cc::Layer> layer,
+ bool prevent_contents_opaque_changes) {
if (container_)
- container_->SetWebLayer(web_layer.get());
- web_layer_ = std::move(web_layer);
+ container_->SetCcLayer(layer.get(), prevent_contents_opaque_changes);
+ embedded_layer_ = std::move(layer);
}
SkBitmap* BrowserPlugin::GetSadPageBitmap() {
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h
index a123a1bf87f..8ab2c1b82ba 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.h
@@ -16,7 +16,7 @@
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
#include "content/public/common/screen_info.h"
#include "content/renderer/child_frame_compositor.h"
#include "content/renderer/mouse_lock_dispatcher.h"
@@ -34,6 +34,11 @@ namespace base {
class UnguessableToken;
}
+namespace cc {
+class Layer;
+class RenderFrameMetadata;
+}
+
namespace viz {
class SurfaceInfo;
}
@@ -76,6 +81,8 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
void ScreenInfoChanged(const ScreenInfo& screen_info);
+ void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
+
// Indicates whether the guest should be focused.
bool ShouldGuestBeFocused() const;
@@ -90,7 +97,7 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
// Returns the last allocated LocalSurfaceId.
const viz::LocalSurfaceId& GetLocalSurfaceId() const;
- void WasResized();
+ void SynchronizeVisualProperties();
// Returns whether a message should be forwarded to BrowserPlugin.
static bool ShouldForwardToBrowserPlugin(const IPC::Message& message);
@@ -165,17 +172,13 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
~BrowserPlugin() override;
const gfx::Rect& screen_space_rect() const {
- return pending_resize_params_.screen_space_rect;
+ return pending_visual_properties_.screen_space_rect;
}
gfx::Rect FrameRectInPixels() const;
float GetDeviceScaleFactor() const;
const ScreenInfo& screen_info() const {
- return pending_resize_params_.screen_info;
- }
-
- uint64_t auto_size_sequence_number() const {
- return pending_resize_params_.auto_resize_sequence_number;
+ return pending_visual_properties_.screen_info;
}
void UpdateInternalInstanceId();
@@ -192,8 +195,8 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
const base::Optional<viz::LocalSurfaceId>& child_local_surface_id);
void OnGuestGone(int instance_id);
void OnGuestReady(int instance_id, const viz::FrameSinkId& frame_sink_id);
- void OnResizeDueToAutoResize(int browser_plugin_instance_id,
- uint64_t sequence_number);
+ void OnDidUpdateVisualProperties(int browser_plugin_instance_id,
+ const cc::RenderFrameMetadata& metadata);
void OnEnableAutoResize(int browser_plugin_instance_id,
const gfx::Size& min_size,
const gfx::Size& max_size);
@@ -218,8 +221,9 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
#endif
// ChildFrameCompositor:
- blink::WebLayer* GetLayer() override;
- void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) override;
+ cc::Layer* GetLayer() override;
+ void SetLayer(scoped_refptr<cc::Layer> layer,
+ bool prevent_contents_opaque_changes) override;
SkBitmap* GetSadPageBitmap() override;
// This indicates whether this BrowserPlugin has been attached to a
@@ -258,11 +262,11 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
bool enable_surface_synchronization_ = false;
// The last ResizeParams sent to the browser process, if any.
- base::Optional<FrameResizeParams> sent_resize_params_;
+ base::Optional<FrameVisualProperties> sent_visual_properties_;
// The current set of ResizeParams. This may or may not match
- // |sent_resize_params_|.
- FrameResizeParams pending_resize_params_;
+ // |sent_visual_properties_|.
+ FrameVisualProperties pending_visual_properties_;
// We call lifetime managing methods on |delegate_|, but we do not directly
// own this. The delegate destroys itself.
@@ -281,7 +285,7 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin,
base::WeakPtr<RenderWidget> embedding_render_widget_;
// The layer used to embed the out-of-process content.
- std::unique_ptr<blink::WebLayer> web_layer_;
+ scoped_refptr<cc::Layer> embedded_layer_;
// Weak factory used in v8 |MakeWeak| callback, since the v8 callback might
// get called after BrowserPlugin has been destroyed.
diff --git a/chromium/content/renderer/browser_render_view_browsertest.cc b/chromium/content/renderer/browser_render_view_browsertest.cc
index 88a0573dac3..6d6bd0de218 100644
--- a/chromium/content/renderer/browser_render_view_browsertest.cc
+++ b/chromium/content/renderer/browser_render_view_browsertest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
@@ -36,6 +37,7 @@
#include "net/http/http_cache.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -78,61 +80,6 @@ class TestShellContentRendererClient : public ShellContentRendererClient {
bool latest_error_stale_copy_in_cache_;
};
-// Must be called on IO thread.
-void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
- net::Error error) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::HttpCache* cache(
- getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
- DCHECK(cache);
- std::unique_ptr<net::FailingHttpTransactionFactory> factory(
- new net::FailingHttpTransactionFactory(cache->GetSession(), error));
- // Throw away old version; since this is a browser test, there is no
- // need to restore the old state.
- cache->SetHttpNetworkTransactionFactoryForTesting(std::move(factory));
-}
-
-void CallOnUIThreadValidatingReturn(const base::Closure& callback,
- int rv) {
- DCHECK_EQ(net::OK, rv);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, callback);
-}
-
-// Must be called on IO thread. The callback will be called on
-// completion of cache clearing on the UI thread.
-void BackendClearCache(std::unique_ptr<disk_cache::Backend*> backend,
- const base::Closure& callback,
- int rv) {
- DCHECK(*backend);
- DCHECK_EQ(net::OK, rv);
- (*backend)->DoomAllEntries(
- base::Bind(&CallOnUIThreadValidatingReturn, callback));
-}
-
-// Must be called on IO thread. The callback will be called on
-// completion of cache clearing on the UI thread.
-void ClearCache(net::URLRequestContextGetter* getter,
- const base::Closure& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::HttpCache* cache(
- getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
- DCHECK(cache);
- std::unique_ptr<disk_cache::Backend*> backend(new disk_cache::Backend*);
- *backend = NULL;
- disk_cache::Backend** backend_ptr = backend.get();
-
- net::CompletionCallback backend_callback(base::Bind(
- &BackendClearCache, base::Passed(std::move(backend)), callback));
-
- // backend_ptr is valid until all copies of backend_callback go out
- // of scope.
- if (net::OK == cache->GetBackend(backend_ptr, backend_callback)) {
- // The call completed synchronously, so GetBackend didn't run the callback.
- std::move(backend_callback).Run(net::OK);
- }
-}
-
} // namespace
class RenderViewBrowserTest : public ContentBrowserTest {
@@ -213,18 +160,16 @@ IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest,
// Reload same URL after forcing an error from the the network layer;
// confirm that the error page is told the cached copy exists.
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
- shell()
- ->web_contents()
- ->GetMainFrame()
- ->GetProcess()
- ->GetStoragePartition()
- ->GetURLRequestContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&InterceptNetworkTransactions,
- base::RetainedRef(url_request_context_getter),
- net::ERR_FAILED));
+ {
+ mojo::ScopedAllowSyncCallForTesting allow_sync_call;
+ content::StoragePartition* partition = shell()
+ ->web_contents()
+ ->GetMainFrame()
+ ->GetProcess()
+ ->GetStoragePartition();
+ partition->GetNetworkContext()->SetFailingHttpTransactionForTesting(
+ net::ERR_FAILED);
+ }
// An error results in one completed navigation.
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
@@ -236,12 +181,18 @@ IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest,
EXPECT_TRUE(stale_cache_entry_present);
// Clear the cache and repeat; confirm lack of entry in cache reported.
- scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ClearCache, base::RetainedRef(url_request_context_getter),
- runner->QuitClosure()));
- runner->Run();
+ {
+ base::RunLoop run_loop;
+ content::StoragePartition* partition = shell()
+ ->web_contents()
+ ->GetMainFrame()
+ ->GetProcess()
+ ->GetStoragePartition();
+ partition->GetNetworkContext()->ClearHttpCache(
+ base::Time(), base::Time(), nullptr /* filter */,
+ base::BindOnce(run_loop.QuitClosure()));
+ run_loop.Run();
+ }
content::NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
diff --git a/chromium/content/renderer/cache_storage/OWNERS b/chromium/content/renderer/cache_storage/OWNERS
deleted file mode 100644
index b78333e3092..00000000000
--- a/chromium/content/renderer/cache_storage/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-michaeln@chromium.org
-nhiroki@chromium.org
-jkarlin@chromium.org
-jsbell@chromium.org
-
-# TEAM: storage-dev@chromium.org
-# COMPONENT: Blink>Storage>CacheStorage
diff --git a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc b/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
deleted file mode 100644
index d6d31794194..00000000000
--- a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
+++ /dev/null
@@ -1,481 +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.
-
-#include "content/renderer/cache_storage/webserviceworkercachestorage_impl.h"
-
-#include <algorithm>
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_local.h"
-#include "content/child/child_thread_impl.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/referrer.h"
-#include "content/public/common/service_names.mojom.h"
-#include "content/public/renderer/render_thread.h"
-#include "content/renderer/service_worker/service_worker_type_util.h"
-#include "mojo/public/cpp/bindings/callback_helpers.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "storage/common/blob_storage/blob_handle.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_cache.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace content {
-
-using base::TimeTicks;
-using blink::mojom::CacheStorageError;
-using blink::WebServiceWorkerRequest;
-using blink::WebString;
-
-namespace {
-
-ServiceWorkerFetchRequest FetchRequestFromWebRequest(
- const WebServiceWorkerRequest& web_request) {
- ServiceWorkerHeaderMap headers;
- GetServiceWorkerHeaderMapFromWebRequest(web_request, &headers);
-
- return ServiceWorkerFetchRequest(
- web_request.Url(), web_request.Method().Ascii(), headers,
- Referrer(web_request.ReferrerUrl(), web_request.GetReferrerPolicy()),
- web_request.IsReload());
-}
-
-void PopulateWebRequestFromFetchRequest(
- const ServiceWorkerFetchRequest& request,
- WebServiceWorkerRequest* web_request) {
- web_request->SetURL(request.url);
- web_request->SetMethod(WebString::FromASCII(request.method));
- for (const auto& header : request.headers) {
- web_request->SetHeader(WebString::FromASCII(header.first),
- WebString::FromASCII(header.second));
- }
- web_request->SetReferrer(WebString::FromASCII(request.referrer.url.spec()),
- request.referrer.policy);
- web_request->SetIsReload(request.is_reload);
-}
-
-blink::WebVector<WebServiceWorkerRequest> WebRequestsFromRequests(
- const std::vector<ServiceWorkerFetchRequest>& requests) {
- blink::WebVector<WebServiceWorkerRequest> web_requests(requests.size());
- for (size_t i = 0; i < requests.size(); ++i)
- PopulateWebRequestFromFetchRequest(requests[i], &(web_requests[i]));
- return web_requests;
-}
-
-CacheStorageCacheQueryParams QueryParamsFromWebQueryParams(
- const blink::WebServiceWorkerCache::QueryParams& web_query_params) {
- CacheStorageCacheQueryParams query_params;
- query_params.ignore_search = web_query_params.ignore_search;
- query_params.ignore_method = web_query_params.ignore_method;
- query_params.ignore_vary = web_query_params.ignore_vary;
- query_params.cache_name =
- WebString::ToNullableString16(web_query_params.cache_name);
- return query_params;
-}
-
-CacheStorageCacheOperationType CacheOperationTypeFromWebCacheOperationType(
- blink::WebServiceWorkerCache::OperationType operation_type) {
- switch (operation_type) {
- case blink::WebServiceWorkerCache::kOperationTypePut:
- return CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
- case blink::WebServiceWorkerCache::kOperationTypeDelete:
- return CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
- default:
- return CACHE_STORAGE_CACHE_OPERATION_TYPE_UNDEFINED;
- }
-}
-
-CacheStorageBatchOperation BatchOperationFromWebBatchOperation(
- const blink::WebServiceWorkerCache::BatchOperation& web_operation) {
- CacheStorageBatchOperation operation;
- operation.operation_type =
- CacheOperationTypeFromWebCacheOperationType(web_operation.operation_type);
- operation.request = FetchRequestFromWebRequest(web_operation.request);
- operation.response =
- GetServiceWorkerResponseFromWebResponse(web_operation.response);
- operation.match_params =
- QueryParamsFromWebQueryParams(web_operation.match_params);
- return operation;
-}
-
-} // namespace
-
-// Class to outlive WebCache, we need to keep the ref (and callbacks) around
-// even after WebCache is dropped as some consumers like
-// InspectorCacheStorageAgent expects to be called back without holding a
-// reference to it. CacheRef is ref-counted and the callback holds a reference
-// to it to keep it alive until the callback is called.
-class WebServiceWorkerCacheStorageImpl::CacheRef
- : public base::RefCounted<CacheRef> {
- public:
- using CacheBatchCallbacks = blink::WebServiceWorkerCache::CacheBatchCallbacks;
- using CacheMatchCallbacks = blink::WebServiceWorkerCache::CacheMatchCallbacks;
- using CacheWithResponsesCallbacks =
- blink::WebServiceWorkerCache::CacheWithResponsesCallbacks;
- using CacheWithRequestsCallbacks =
- blink::WebServiceWorkerCache::CacheWithRequestsCallbacks;
-
- CacheRef(base::WeakPtr<WebServiceWorkerCacheStorageImpl> dispatcher,
- blink::mojom::CacheStorageCacheAssociatedPtrInfo cache_ptr_info)
- : dispatcher_(std::move(dispatcher)) {
- cache_ptr_.Bind(std::move(cache_ptr_info));
- }
-
- void DispatchMatch(
- std::unique_ptr<CacheMatchCallbacks> callbacks,
- const WebServiceWorkerRequest& request,
- const blink::WebServiceWorkerCache::QueryParams& query_params) {
- cache_ptr_->Match(FetchRequestFromWebRequest(request),
- QueryParamsFromWebQueryParams(query_params),
- base::BindOnce(&CacheRef::CacheMatchCallback, this,
- std::move(callbacks), TimeTicks::Now()));
- }
-
- void DispatchMatchAll(
- std::unique_ptr<CacheWithResponsesCallbacks> callbacks,
- const WebServiceWorkerRequest& request,
- const blink::WebServiceWorkerCache::QueryParams& query_params) {
- cache_ptr_->MatchAll(
- FetchRequestFromWebRequest(request),
- QueryParamsFromWebQueryParams(query_params),
- base::BindOnce(&CacheRef::CacheMatchAllCallback, this,
- std::move(callbacks), TimeTicks::Now()));
- }
-
- void DispatchKeys(
- std::unique_ptr<CacheWithRequestsCallbacks> callbacks,
- const WebServiceWorkerRequest& request,
- const blink::WebServiceWorkerCache::QueryParams& query_params) {
- cache_ptr_->Keys(FetchRequestFromWebRequest(request),
- QueryParamsFromWebQueryParams(query_params),
- base::BindOnce(&CacheRef::CacheKeysCallback, this,
- std::move(callbacks)));
- }
-
- void DispatchBatch(
- std::unique_ptr<CacheBatchCallbacks> callbacks,
- const blink::WebVector<blink::WebServiceWorkerCache::BatchOperation>&
- batch_operations) {
- std::vector<CacheStorageBatchOperation> operations;
- operations.reserve(batch_operations.size());
- for (size_t i = 0; i < batch_operations.size(); ++i) {
- operations.push_back(
- BatchOperationFromWebBatchOperation(batch_operations[i]));
- }
- cache_ptr_->Batch(operations,
- base::BindOnce(&CacheRef::BatchCallback, this,
- std::move(callbacks), TimeTicks::Now()));
- }
-
- private:
- friend class base::RefCounted<CacheRef>;
-
- ~CacheRef() = default;
-
- void CacheMatchCallback(std::unique_ptr<CacheMatchCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::MatchResultPtr result) {
- if (result->is_status() &&
- result->get_status() != CacheStorageError::kSuccess) {
- callbacks->OnError(result->get_status());
- } else if (!dispatcher_) {
- callbacks->OnError(CacheStorageError::kErrorNotFound);
- } else {
- blink::WebServiceWorkerResponse web_response;
- dispatcher_->PopulateWebResponseFromResponse(result->get_response(),
- &web_response);
-
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.Cache.Match",
- TimeTicks::Now() - start_time);
- callbacks->OnSuccess(web_response);
- }
- }
-
- void CacheMatchAllCallback(
- std::unique_ptr<CacheWithResponsesCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::MatchAllResultPtr result) {
- if (result->is_status() &&
- result->get_status() != CacheStorageError::kSuccess) {
- callbacks->OnError(result->get_status());
- } else if (!dispatcher_) {
- callbacks->OnError(CacheStorageError::kErrorNotFound);
- } else {
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.Cache.MatchAll",
- TimeTicks::Now() - start_time);
- callbacks->OnSuccess(
- dispatcher_->WebResponsesFromResponses(result->get_responses()));
- }
- }
-
- void CacheKeysCallback(std::unique_ptr<CacheWithRequestsCallbacks> callbacks,
- blink::mojom::CacheKeysResultPtr result) {
- if (result->is_status() &&
- result->get_status() != CacheStorageError::kSuccess) {
- callbacks->OnError(result->get_status());
- } else {
- callbacks->OnSuccess(WebRequestsFromRequests(result->get_keys()));
- }
- }
-
- void BatchCallback(std::unique_ptr<CacheBatchCallbacks> callbacks,
- base::TimeTicks start_time,
- CacheStorageError error) {
- if (error == CacheStorageError::kSuccess) {
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.Cache.Batch",
- TimeTicks::Now() - start_time);
- callbacks->OnSuccess();
- } else {
- callbacks->OnError(error);
- }
- }
-
- blink::mojom::CacheStorageCacheAssociatedPtr cache_ptr_;
- base::WeakPtr<WebServiceWorkerCacheStorageImpl> dispatcher_;
-};
-
-// The WebCache object is the Chromium side implementation of the Blink
-// WebServiceWorkerCache API. It only delegates the client calls to CacheRef
-// object, which have a lifetime longer than the WebCache. WebCache is owned by
-// the script-facing caller. CacheRef outlives WebCache to guarantee callback
-// responses are invoked, regardless of script-facing keeping WebCache instance
-// alive.
-class WebServiceWorkerCacheStorageImpl::WebCache
- : public blink::WebServiceWorkerCache {
- public:
- WebCache(scoped_refptr<CacheRef> cache_ref)
- : cache_ref_(std::move(cache_ref)) {}
-
- ~WebCache() override = default;
-
- // From blink::WebServiceWorkerCache:
- void DispatchMatch(std::unique_ptr<CacheMatchCallbacks> callbacks,
- const WebServiceWorkerRequest& request,
- const QueryParams& query_params) override {
- cache_ref_->DispatchMatch(std::move(callbacks), std::move(request),
- std::move(query_params));
- }
-
- void DispatchMatchAll(std::unique_ptr<CacheWithResponsesCallbacks> callbacks,
- const WebServiceWorkerRequest& request,
- const QueryParams& query_params) override {
- cache_ref_->DispatchMatchAll(std::move(callbacks), std::move(request),
- std::move(query_params));
- }
-
- void DispatchKeys(std::unique_ptr<CacheWithRequestsCallbacks> callbacks,
- const WebServiceWorkerRequest& request,
- const QueryParams& query_params) override {
- cache_ref_->DispatchKeys(std::move(callbacks), std::move(request),
- std::move(query_params));
- }
-
- void DispatchBatch(
- std::unique_ptr<CacheBatchCallbacks> callbacks,
- const blink::WebVector<blink::WebServiceWorkerCache::BatchOperation>&
- batch_operations) override {
- cache_ref_->DispatchBatch(std::move(callbacks),
- std::move(batch_operations));
- }
-
- private:
- scoped_refptr<CacheRef> cache_ref_;
-
- DISALLOW_COPY_AND_ASSIGN(WebCache);
-};
-
-WebServiceWorkerCacheStorageImpl::WebServiceWorkerCacheStorageImpl(
- service_manager::InterfaceProvider* provider)
- : weak_factory_(this) {
- // Sets up the Mojo InterfacePtr to send IPCs to browser process.
- provider->GetInterface(mojo::MakeRequest(&cache_storage_ptr_));
-}
-
-WebServiceWorkerCacheStorageImpl::~WebServiceWorkerCacheStorageImpl() = default;
-
-void WebServiceWorkerCacheStorageImpl::DispatchHas(
- std::unique_ptr<CacheStorageCallbacks> callbacks,
- const WebString& cacheName) {
- GetCacheStorage().Has(
- cacheName.Utf16(),
- base::BindOnce(
- &WebServiceWorkerCacheStorageImpl::OnCacheStorageHasCallback,
- weak_factory_.GetWeakPtr(), std::move(callbacks),
- base::TimeTicks::Now()));
-}
-
-void WebServiceWorkerCacheStorageImpl::OnCacheStorageHasCallback(
- std::unique_ptr<CacheStorageCallbacks> callbacks,
- base::TimeTicks start_time,
- CacheStorageError result) {
- if (result == CacheStorageError::kSuccess) {
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.CacheStorage.Has",
- TimeTicks::Now() - start_time);
- callbacks->OnSuccess();
- } else {
- callbacks->OnError(result);
- }
-}
-
-void WebServiceWorkerCacheStorageImpl::DispatchOpen(
- std::unique_ptr<CacheStorageWithCacheCallbacks> callbacks,
- const WebString& cacheName) {
- GetCacheStorage().Open(
- cacheName.Utf16(),
- base::BindOnce(
- &WebServiceWorkerCacheStorageImpl::OnCacheStorageOpenCallback,
- weak_factory_.GetWeakPtr(), std::move(callbacks),
- base::TimeTicks::Now()));
-}
-
-void WebServiceWorkerCacheStorageImpl::OnCacheStorageOpenCallback(
- std::unique_ptr<CacheStorageWithCacheCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::OpenResultPtr result) {
- if (result->is_status() &&
- result->get_status() != CacheStorageError::kSuccess) {
- callbacks->OnError(result->get_status());
- } else {
- std::unique_ptr<WebCache> web_cache =
- std::make_unique<WebCache>(base::MakeRefCounted<CacheRef>(
- weak_factory_.GetWeakPtr(), std::move(result->get_cache())));
-
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.CacheStorage.Open",
- TimeTicks::Now() - start_time);
- callbacks->OnSuccess(std::move(web_cache));
- }
-}
-
-void WebServiceWorkerCacheStorageImpl::DispatchDelete(
- std::unique_ptr<CacheStorageCallbacks> callbacks,
- const WebString& cacheName) {
- GetCacheStorage().Delete(
- cacheName.Utf16(),
- base::BindOnce(
- &WebServiceWorkerCacheStorageImpl::CacheStorageDeleteCallback,
- weak_factory_.GetWeakPtr(), std::move(callbacks),
- base::TimeTicks::Now()));
-}
-
-void WebServiceWorkerCacheStorageImpl::CacheStorageDeleteCallback(
- std::unique_ptr<CacheStorageCallbacks> callbacks,
- base::TimeTicks start_time,
- CacheStorageError result) {
- if (result == CacheStorageError::kSuccess) {
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.CacheStorage.Delete",
- TimeTicks::Now() - start_time);
- callbacks->OnSuccess();
- } else {
- callbacks->OnError(result);
- }
-}
-
-void WebServiceWorkerCacheStorageImpl::DispatchKeys(
- std::unique_ptr<CacheStorageKeysCallbacks> callbacks) {
- GetCacheStorage().Keys(
- base::BindOnce(&WebServiceWorkerCacheStorageImpl::KeysCallback,
- weak_factory_.GetWeakPtr(), std::move(callbacks),
- base::TimeTicks::Now()));
-}
-
-void WebServiceWorkerCacheStorageImpl::KeysCallback(
- std::unique_ptr<CacheStorageKeysCallbacks> callbacks,
- base::TimeTicks start_time,
- const std::vector<base::string16>& keys) {
- blink::WebVector<WebString> web_keys(keys.size());
- std::transform(
- keys.begin(), keys.end(), web_keys.begin(),
- [](const base::string16& s) { return WebString::FromUTF16(s); });
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.CacheStorage.Keys",
- TimeTicks::Now() - start_time);
- callbacks->OnSuccess(web_keys);
-}
-
-void WebServiceWorkerCacheStorageImpl::DispatchMatch(
- std::unique_ptr<CacheStorageMatchCallbacks> callbacks,
- const WebServiceWorkerRequest& request,
- const blink::WebServiceWorkerCache::QueryParams& query_params) {
- GetCacheStorage().Match(
- FetchRequestFromWebRequest(request),
- QueryParamsFromWebQueryParams(query_params),
- base::BindOnce(
- &WebServiceWorkerCacheStorageImpl::OnCacheStorageMatchCallback,
- weak_factory_.GetWeakPtr(), std::move(callbacks),
- base::TimeTicks::Now()));
-}
-
-void WebServiceWorkerCacheStorageImpl::OnCacheStorageMatchCallback(
- std::unique_ptr<CacheStorageMatchCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::MatchResultPtr result) {
- if (result->is_status() &&
- result->get_status() != CacheStorageError::kSuccess) {
- callbacks->OnError(result->get_status());
- } else {
- UMA_HISTOGRAM_TIMES("ServiceWorkerCache.CacheStorage.Match",
- TimeTicks::Now() - start_time);
- blink::WebServiceWorkerResponse web_response;
- PopulateWebResponseFromResponse(result->get_response(), &web_response);
-
- callbacks->OnSuccess(web_response);
- }
-}
-
-blink::mojom::CacheStorage&
-WebServiceWorkerCacheStorageImpl::GetCacheStorage() {
- return *cache_storage_ptr_;
-}
-
-void WebServiceWorkerCacheStorageImpl::PopulateWebResponseFromResponse(
- const ServiceWorkerResponse& response,
- blink::WebServiceWorkerResponse* web_response) {
- web_response->SetURLList(response.url_list);
- web_response->SetStatus(response.status_code);
- web_response->SetStatusText(WebString::FromASCII(response.status_text));
- web_response->SetResponseType(response.response_type);
- web_response->SetResponseTime(response.response_time);
- web_response->SetCacheStorageCacheName(
- response.is_in_cache_storage
- ? WebString::FromUTF8(response.cache_storage_cache_name)
- : WebString());
- blink::WebVector<WebString> headers(
- response.cors_exposed_header_names.size());
- std::transform(response.cors_exposed_header_names.begin(),
- response.cors_exposed_header_names.end(), headers.begin(),
- [](const std::string& s) { return WebString::FromLatin1(s); });
- web_response->SetCorsExposedHeaderNames(headers);
-
- for (const auto& i : response.headers) {
- web_response->SetHeader(WebString::FromASCII(i.first),
- WebString::FromASCII(i.second));
- }
-
- if (!response.blob_uuid.empty()) {
- DCHECK(response.blob);
- web_response->SetBlob(WebString::FromUTF8(response.blob_uuid),
- response.blob_size,
- response.blob->Clone().PassInterface().PassHandle());
- }
-}
-
-blink::WebVector<blink::WebServiceWorkerResponse>
-WebServiceWorkerCacheStorageImpl::WebResponsesFromResponses(
- const std::vector<ServiceWorkerResponse>& responses) {
- blink::WebVector<blink::WebServiceWorkerResponse> web_responses(
- responses.size());
- for (size_t i = 0; i < responses.size(); ++i)
- PopulateWebResponseFromResponse(responses[i], &(web_responses[i]));
- return web_responses;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h b/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h
deleted file mode 100644
index de4bc018e58..00000000000
--- a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h
+++ /dev/null
@@ -1,103 +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 CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_CACHE_STORAGE_IMPL_H_
-#define CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_CACHE_STORAGE_IMPL_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/containers/id_map.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string16.h"
-#include "base/time/time.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_cache.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_cache_storage.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace content {
-struct ServiceWorkerResponse;
-
-// This corresponds to an instance of the script-facing CacheStorage object.
-// One exists per script execution context (window, worker) and has an origin
-// which provides a namespace for the caches. Script calls to the CacheStorage
-// object are routed through here via Mojo interface then on to the browser,
-// with the origin managed at binding time on browser side. Cache instances
-// returned by open() calls return a WebCache to script-facing caller which can
-// dispatch calls to browser via CacheRef. WebCache is owned by script-facing
-// caller and CacheRef is owned by WebServiceWorkerCacheStorageImpl. CacheRef is
-// destroyed once WebCache has been destroyed and there are no pending
-// callbacks.
-class WebServiceWorkerCacheStorageImpl
- : public blink::WebServiceWorkerCacheStorage {
- public:
- explicit WebServiceWorkerCacheStorageImpl(
- service_manager::InterfaceProvider* provider);
-
- ~WebServiceWorkerCacheStorageImpl() override;
-
- // From WebServiceWorkerCacheStorage interface to script-facing:
- void DispatchHas(std::unique_ptr<CacheStorageCallbacks> callbacks,
- const blink::WebString& cacheName) override;
- void DispatchOpen(std::unique_ptr<CacheStorageWithCacheCallbacks> callbacks,
- const blink::WebString& cacheName) override;
- void DispatchDelete(std::unique_ptr<CacheStorageCallbacks> callbacks,
- const blink::WebString& cacheName) override;
- void DispatchKeys(
- std::unique_ptr<CacheStorageKeysCallbacks> callbacks) override;
- void DispatchMatch(
- std::unique_ptr<CacheStorageMatchCallbacks> callbacks,
- const blink::WebServiceWorkerRequest& request,
- const blink::WebServiceWorkerCache::QueryParams& query_params) override;
-
- // Message handlers for CacheStorage messages from the browser process.
- // And callbacks called by Mojo implementation on browser process.
- void OnCacheStorageHasCallback(
- std::unique_ptr<CacheStorageCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::CacheStorageError result);
- void OnCacheStorageOpenCallback(
- std::unique_ptr<CacheStorageWithCacheCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::OpenResultPtr result);
- void CacheStorageDeleteCallback(
- std::unique_ptr<CacheStorageCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::CacheStorageError result);
- void KeysCallback(std::unique_ptr<CacheStorageKeysCallbacks> callbacks,
- base::TimeTicks start_time,
- const std::vector<base::string16>& keys);
- void OnCacheStorageMatchCallback(
- std::unique_ptr<CacheStorageMatchCallbacks> callbacks,
- base::TimeTicks start_time,
- blink::mojom::MatchResultPtr result);
-
- private:
- class WebCache;
- class CacheRef;
-
- void PopulateWebResponseFromResponse(
- const ServiceWorkerResponse& response,
- blink::WebServiceWorkerResponse* web_response);
-
- blink::WebVector<blink::WebServiceWorkerResponse> WebResponsesFromResponses(
- const std::vector<ServiceWorkerResponse>& responses);
-
- blink::mojom::CacheStorage& GetCacheStorage();
-
- blink::mojom::CacheStoragePtr cache_storage_ptr_;
-
- base::WeakPtrFactory<WebServiceWorkerCacheStorageImpl> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerCacheStorageImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_CACHE_STORAGE_IMPL_H_
diff --git a/chromium/content/renderer/categorized_worker_pool.cc b/chromium/content/renderer/categorized_worker_pool.cc
index 5a1cfa976af..0235547e93b 100644
--- a/chromium/content/renderer/categorized_worker_pool.cc
+++ b/chromium/content/renderer/categorized_worker_pool.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
@@ -32,12 +33,32 @@ class CategorizedWorkerPoolThread : public base::SimpleThread {
categories_(categories),
has_ready_to_run_tasks_cv_(has_ready_to_run_tasks_cv) {}
+ void SetBackgroundingCallback(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ base::OnceCallback<void(base::PlatformThreadId)> callback) {
+ DCHECK(!HasStartBeenAttempted());
+ background_task_runner_ = std::move(task_runner);
+ backgrounding_callback_ = std::move(callback);
+ }
+
+ // base::SimpleThread:
+ void BeforeRun() override {
+ if (backgrounding_callback_) {
+ DCHECK(background_task_runner_);
+ background_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(std::move(backgrounding_callback_), tid()));
+ }
+ }
+
void Run() override { pool_->Run(categories_, has_ready_to_run_tasks_cv_); }
private:
CategorizedWorkerPool* const pool_;
const std::vector<cc::TaskCategory> categories_;
base::ConditionVariable* const has_ready_to_run_tasks_cv_;
+
+ base::OnceCallback<void(base::PlatformThreadId)> backgrounding_callback_;
+ scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_;
};
} // namespace
@@ -142,7 +163,7 @@ void CategorizedWorkerPool::Start(int num_threads) {
base::StringPrintf("CompositorTileWorker%d", i + 1).c_str(),
base::SimpleThread::Options(), this, foreground_categories,
&has_ready_to_run_foreground_tasks_cv_));
- thread->Start();
+ thread->StartAsync();
threads_.push_back(std::move(thread));
}
@@ -156,10 +177,14 @@ void CategorizedWorkerPool::Start(int num_threads) {
thread_options.priority = base::ThreadPriority::BACKGROUND;
#endif
- std::unique_ptr<base::SimpleThread> thread(new CategorizedWorkerPoolThread(
+ auto thread = std::make_unique<CategorizedWorkerPoolThread>(
"CompositorTileWorkerBackground", thread_options, this,
- background_categories, &has_ready_to_run_background_tasks_cv_));
- thread->Start();
+ background_categories, &has_ready_to_run_background_tasks_cv_);
+ if (backgrounding_callback_) {
+ thread->SetBackgroundingCallback(std::move(background_task_runner_),
+ std::move(backgrounding_callback_));
+ }
+ thread->StartAsync();
threads_.push_back(std::move(thread));
}
@@ -258,6 +283,15 @@ CategorizedWorkerPool::CreateSequencedTaskRunner() {
return new CategorizedWorkerPoolSequencedTaskRunner(this);
}
+void CategorizedWorkerPool::SetBackgroundingCallback(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ base::OnceCallback<void(base::PlatformThreadId)> callback) {
+ // The callback must be set before the threads have been created.
+ DCHECK(threads_.empty());
+ backgrounding_callback_ = std::move(callback);
+ background_task_runner_ = std::move(task_runner);
+}
+
CategorizedWorkerPool::~CategorizedWorkerPool() {}
cc::NamespaceToken CategorizedWorkerPool::GenerateNamespaceToken() {
diff --git a/chromium/content/renderer/categorized_worker_pool.h b/chromium/content/renderer/categorized_worker_pool.h
index 1e8194db5e2..54403e07e72 100644
--- a/chromium/content/renderer/categorized_worker_pool.h
+++ b/chromium/content/renderer/categorized_worker_pool.h
@@ -19,6 +19,10 @@
#include "cc/raster/task_graph_work_queue.h"
#include "content/common/content_export.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace content {
// A pool of threads used to run categorized work. The work can be scheduled on
@@ -69,9 +73,11 @@ class CONTENT_EXPORT CategorizedWorkerPool : public base::TaskRunner,
// Create a new sequenced task graph runner.
scoped_refptr<base::SequencedTaskRunner> CreateSequencedTaskRunner();
- base::PlatformThreadId background_worker_thread_id() const {
- return threads_.back()->tid();
- }
+ // Runs the callback on the specified task-runner once the background worker
+ // thread is initialized.
+ void SetBackgroundingCallback(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ base::OnceCallback<void(base::PlatformThreadId)> callback);
protected:
~CategorizedWorkerPool() override;
@@ -145,6 +151,9 @@ class CONTENT_EXPORT CategorizedWorkerPool : public base::TaskRunner,
base::ConditionVariable has_namespaces_with_finished_running_tasks_cv_;
// Set during shutdown. Tells Run() to return when no more tasks are pending.
bool shutdown_;
+
+ base::OnceCallback<void(base::PlatformThreadId)> backgrounding_callback_;
+ scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_;
};
} // namespace content
diff --git a/chromium/content/renderer/child_frame_compositing_helper.cc b/chromium/content/renderer/child_frame_compositing_helper.cc
index 620cab062a4..8ef6f5b20b7 100644
--- a/chromium/content/renderer/child_frame_compositing_helper.cc
+++ b/chromium/content/renderer/child_frame_compositing_helper.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "build/build_config.h"
-#include "cc/blink/web_layer_impl.h"
#include "cc/layers/picture_image_layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/surface_layer.h"
@@ -66,8 +65,9 @@ void ChildFrameCompositingHelper::ChildFrameGone(
}
}
- child_frame_compositor_->SetLayer(
- std::make_unique<cc_blink::WebLayerImpl>(crashed_layer));
+ bool prevent_contents_opaque_changes = false;
+ child_frame_compositor_->SetLayer(std::move(crashed_layer),
+ prevent_contents_opaque_changes);
}
void ChildFrameCompositingHelper::SetPrimarySurfaceId(
@@ -81,25 +81,21 @@ void ChildFrameCompositingHelper::SetPrimarySurfaceId(
surface_layer_ = cc::SurfaceLayer::Create();
surface_layer_->SetMasksToBounds(true);
- surface_layer_->SetHitTestable(true);
+ surface_layer_->SetSurfaceHitTestable(true);
surface_layer_->SetBackgroundColor(SK_ColorTRANSPARENT);
surface_layer_->SetPrimarySurfaceId(surface_id, deadline);
surface_layer_->SetFallbackSurfaceId(fallback_surface_id_);
- std::unique_ptr<cc_blink::WebLayerImpl> layer(
- new cc_blink::WebLayerImpl(surface_layer_));
- // TODO(lfg): Investigate if it's possible to propagate the information about
- // the child surface's opacity. https://crbug.com/629851.
- layer->SetOpaque(false);
- layer->SetContentsOpaqueIsFixed(true);
- child_frame_compositor_->SetLayer(std::move(layer));
+ // TODO(lfg): Investigate if it's possible to propagate the information
+ // about the child surface's opacity. https://crbug.com/629851.
+ bool prevent_contents_opaque_changes = true;
+ child_frame_compositor_->SetLayer(surface_layer_,
+ prevent_contents_opaque_changes);
UpdateVisibility(true);
- static_cast<cc_blink::WebLayerImpl*>(child_frame_compositor_->GetLayer())
- ->layer()
- ->SetBounds(frame_size_in_dip);
+ surface_layer_->SetBounds(frame_size_in_dip);
}
void ChildFrameCompositingHelper::SetFallbackSurfaceId(
@@ -120,9 +116,9 @@ void ChildFrameCompositingHelper::SetFallbackSurfaceId(
}
void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
- blink::WebLayer* web_layer = child_frame_compositor_->GetLayer();
- if (web_layer)
- web_layer->SetDrawsContent(visible);
+ cc::Layer* layer = child_frame_compositor_->GetLayer();
+ if (layer)
+ layer->SetIsDrawable(visible);
}
} // namespace content
diff --git a/chromium/content/renderer/child_frame_compositing_helper_unittest.cc b/chromium/content/renderer/child_frame_compositing_helper_unittest.cc
index b84e214c5ff..d2c3e498636 100644
--- a/chromium/content/renderer/child_frame_compositing_helper_unittest.cc
+++ b/chromium/content/renderer/child_frame_compositing_helper_unittest.cc
@@ -4,7 +4,7 @@
#include "content/renderer/child_frame_compositing_helper.h"
-#include "cc/blink/web_layer_impl.h"
+#include "cc/layers/layer.h"
#include "content/renderer/child_frame_compositor.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,16 +20,17 @@ class MockChildFrameCompositor : public ChildFrameCompositor {
sad_page_bitmap_.allocN32Pixels(width, height);
}
- blink::WebLayer* GetLayer() override { return web_layer_.get(); }
+ cc::Layer* GetLayer() override { return layer_.get(); }
- void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) override {
- web_layer_ = std::move(web_layer);
+ void SetLayer(scoped_refptr<cc::Layer> layer,
+ bool prevent_contents_opaque_changes) override {
+ layer_ = std::move(layer);
}
SkBitmap* GetSadPageBitmap() override { return &sad_page_bitmap_; }
private:
- std::unique_ptr<blink::WebLayer> web_layer_;
+ scoped_refptr<cc::Layer> layer_;
SkBitmap sad_page_bitmap_;
DISALLOW_COPY_AND_ASSIGN(MockChildFrameCompositor);
diff --git a/chromium/content/renderer/child_frame_compositor.h b/chromium/content/renderer/child_frame_compositor.h
index cee6610f03d..f93b026813a 100644
--- a/chromium/content/renderer/child_frame_compositor.h
+++ b/chromium/content/renderer/child_frame_compositor.h
@@ -5,21 +5,22 @@
#ifndef CONTENT_RENDERER_CHILD_FRAME_COMPOSITOR_H_
#define CONTENT_RENDERER_CHILD_FRAME_COMPOSITOR_H_
-namespace blink {
-class WebLayer;
-} // namespace blink
+namespace cc {
+class Layer;
+}
namespace content {
-// A ChildFrameCompositor is an owner of a blink::WebLayer that embeds a child
+// A ChildFrameCompositor is an owner of a cc::Layer that embeds a child
// frame.
class ChildFrameCompositor {
public:
- // Get the child frame's blink::WebLayer.
- virtual blink::WebLayer* GetLayer() = 0;
+ // Get the child frame's cc::Layer.
+ virtual cc::Layer* GetLayer() = 0;
- // Passes ownership of a blink::WebLayer to the ChildFrameCompositor.
- virtual void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) = 0;
+ // Passes ownership of a cc::Layer to the ChildFrameCompositor.
+ virtual void SetLayer(scoped_refptr<cc::Layer> layer,
+ bool prevent_contents_opaque_changes) = 0;
// Returns a sad page bitmap used when the child frame has crashed.
virtual SkBitmap* GetSadPageBitmap() = 0;
diff --git a/chromium/content/renderer/content_security_policy_util.cc b/chromium/content/renderer/content_security_policy_util.cc
index 825ecbe7d1f..dd234502e50 100644
--- a/chromium/content/renderer/content_security_policy_util.cc
+++ b/chromium/content/renderer/content_security_policy_util.cc
@@ -24,9 +24,10 @@ CSPSourceList BuildCSPSourceList(
sources.push_back(BuildCSPSource(source));
}
- return CSPSourceList(source_list.allow_self, // allow_self
- source_list.allow_star, // allow_star
- sources); // source_list
+ return CSPSourceList(source_list.allow_self, // allow_self
+ source_list.allow_star, // allow_star
+ source_list.allow_redirects, // allow_redirects
+ sources); // source_list
}
CSPDirective BuildCSPDirective(
@@ -52,6 +53,16 @@ ContentSecurityPolicy BuildContentSecurityPolicy(
directives, report_endpoints, policy.use_reporting_api);
}
+std::vector<ContentSecurityPolicy> BuildContentSecurityPolicyList(
+ const blink::WebContentSecurityPolicyList& policies) {
+ std::vector<ContentSecurityPolicy> list;
+
+ for (const auto& policy : policies.policies)
+ list.push_back(BuildContentSecurityPolicy(policy));
+
+ return list;
+}
+
blink::WebContentSecurityPolicyViolation BuildWebContentSecurityPolicyViolation(
const content::CSPViolationParams& violation_params) {
blink::WebContentSecurityPolicyViolation violation;
diff --git a/chromium/content/renderer/content_security_policy_util.h b/chromium/content/renderer/content_security_policy_util.h
index 6ef7ab183f9..9480bea4c86 100644
--- a/chromium/content/renderer/content_security_policy_util.h
+++ b/chromium/content/renderer/content_security_policy_util.h
@@ -17,6 +17,13 @@ namespace content {
ContentSecurityPolicy BuildContentSecurityPolicy(
const blink::WebContentSecurityPolicy&);
+// Convert a WebContentSecurityPolicyList into a list of ContentSecurityPolicy.
+std::vector<ContentSecurityPolicy> BuildContentSecurityPolicyList(
+ const blink::WebContentSecurityPolicyList&);
+
+CSPSource BuildCSPSource(
+ const blink::WebContentSecurityPolicySourceExpression&);
+
// Convert a CSPViolationParams into a WebContentSecurityPolicyViolation. These
// two classes represent the exact same thing, but one is in content, the other
// is in blink.
diff --git a/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc b/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
index 6cf54ed49fa..2d35111465a 100644
--- a/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
+++ b/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
@@ -417,7 +417,7 @@ TEST_F(DeviceMotionEventPumpTest, PumpThrottlesEventRate) {
sensor_provider()->UpdateGyroscopeData(7, 8, 9);
blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostDelayedTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
base::TimeDelta::FromMilliseconds(100));
base::RunLoop().Run();
motion_pump()->Stop();
diff --git a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
index 52ac6da18f1..dcab57919fd 100644
--- a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
+++ b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
@@ -4,7 +4,7 @@
#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h"
-#include "content/common/resize_params.h"
+#include "content/common/visual_properties.h"
#include "content/public/common/context_menu_params.h"
#include "content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h"
@@ -13,22 +13,18 @@ namespace content {
RenderWidgetScreenMetricsEmulator::RenderWidgetScreenMetricsEmulator(
RenderWidgetScreenMetricsEmulatorDelegate* delegate,
const blink::WebDeviceEmulationParams& params,
- const ResizeParams& resize_params,
+ const VisualProperties& visual_properties,
const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect)
: delegate_(delegate),
emulation_params_(params),
scale_(1.f),
- original_resize_params_(resize_params),
+ original_visual_properties_(visual_properties),
original_view_screen_rect_(view_screen_rect),
- original_window_screen_rect_(window_screen_rect) {
-}
+ original_window_screen_rect_(window_screen_rect) {}
RenderWidgetScreenMetricsEmulator::~RenderWidgetScreenMetricsEmulator() {
- // needs_resize_ack was handled during OnResize() and may cause a DCHECK to
- // fail in RenderWidget if not cleared (crbug.com/635560).
- original_resize_params_.needs_resize_ack = false;
- delegate_->Resize(original_resize_params_);
+ delegate_->SynchronizeVisualProperties(original_visual_properties_);
delegate_->SetScreenMetricsEmulationParameters(false, emulation_params_);
delegate_->SetScreenRects(original_view_screen_rect_,
original_window_screen_rect_);
@@ -41,7 +37,7 @@ void RenderWidgetScreenMetricsEmulator::ChangeEmulationParams(
}
void RenderWidgetScreenMetricsEmulator::Apply() {
- ResizeParams modified_resize_params = original_resize_params_;
+ VisualProperties modified_visual_properties = original_visual_properties_;
applied_widget_rect_.set_size(gfx::Size(emulation_params_.view_size));
if (!applied_widget_rect_.width())
@@ -60,8 +56,8 @@ void RenderWidgetScreenMetricsEmulator::Apply() {
gfx::Rect window_screen_rect;
if (emulation_params_.screen_position ==
blink::WebDeviceEmulationParams::kDesktop) {
- modified_resize_params.screen_info.rect = original_screen_info().rect;
- modified_resize_params.screen_info.available_rect =
+ modified_visual_properties.screen_info.rect = original_screen_info().rect;
+ modified_visual_properties.screen_info.available_rect =
original_screen_info().available_rect;
window_screen_rect = original_window_screen_rect_;
if (emulation_params_.view_position) {
@@ -73,19 +69,20 @@ void RenderWidgetScreenMetricsEmulator::Apply() {
} else {
applied_widget_rect_.set_origin(
emulation_params_.view_position.value_or(blink::WebPoint()));
- modified_resize_params.screen_info.rect = applied_widget_rect_;
- modified_resize_params.screen_info.available_rect = applied_widget_rect_;
+ modified_visual_properties.screen_info.rect = applied_widget_rect_;
+ modified_visual_properties.screen_info.available_rect =
+ applied_widget_rect_;
window_screen_rect = applied_widget_rect_;
}
if (!emulation_params_.screen_size.IsEmpty()) {
gfx::Rect screen_rect = gfx::Rect(0, 0, emulation_params_.screen_size.width,
emulation_params_.screen_size.height);
- modified_resize_params.screen_info.rect = screen_rect;
- modified_resize_params.screen_info.available_rect = screen_rect;
+ modified_visual_properties.screen_info.rect = screen_rect;
+ modified_visual_properties.screen_info.available_rect = screen_rect;
}
- modified_resize_params.screen_info.device_scale_factor =
+ modified_visual_properties.screen_info.device_scale_factor =
emulation_params_.device_scale_factor
? emulation_params_.device_scale_factor
: original_screen_info().device_scale_factor;
@@ -94,27 +91,27 @@ void RenderWidgetScreenMetricsEmulator::Apply() {
blink::kWebScreenOrientationUndefined) {
switch (emulation_params_.screen_orientation_type) {
case blink::kWebScreenOrientationPortraitPrimary:
- modified_resize_params.screen_info.orientation_type =
+ modified_visual_properties.screen_info.orientation_type =
SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY;
break;
case blink::kWebScreenOrientationPortraitSecondary:
- modified_resize_params.screen_info.orientation_type =
+ modified_visual_properties.screen_info.orientation_type =
SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY;
break;
case blink::kWebScreenOrientationLandscapePrimary:
- modified_resize_params.screen_info.orientation_type =
+ modified_visual_properties.screen_info.orientation_type =
SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY;
break;
case blink::kWebScreenOrientationLandscapeSecondary:
- modified_resize_params.screen_info.orientation_type =
+ modified_visual_properties.screen_info.orientation_type =
SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY;
break;
default:
- modified_resize_params.screen_info.orientation_type =
+ modified_visual_properties.screen_info.orientation_type =
SCREEN_ORIENTATION_VALUES_DEFAULT;
break;
}
- modified_resize_params.screen_info.orientation_angle =
+ modified_visual_properties.screen_info.orientation_angle =
emulation_params_.screen_orientation_angle;
}
@@ -132,18 +129,18 @@ void RenderWidgetScreenMetricsEmulator::Apply() {
delegate_->SetScreenRects(applied_widget_rect_, window_screen_rect);
- modified_resize_params.new_size = applied_widget_rect_.size();
- modified_resize_params.visible_viewport_size = applied_widget_rect_.size();
- modified_resize_params.needs_resize_ack = false;
- delegate_->Resize(modified_resize_params);
+ modified_visual_properties.new_size = applied_widget_rect_.size();
+ modified_visual_properties.visible_viewport_size =
+ applied_widget_rect_.size();
+ delegate_->SynchronizeVisualProperties(modified_visual_properties);
}
-void RenderWidgetScreenMetricsEmulator::OnResize(const ResizeParams& params) {
- original_resize_params_ = params;
+void RenderWidgetScreenMetricsEmulator::OnSynchronizeVisualProperties(
+ const VisualProperties& params) {
+ original_visual_properties_ = params;
Apply();
- if (params.needs_resize_ack)
- delegate_->Redraw();
+ delegate_->Redraw();
}
void RenderWidgetScreenMetricsEmulator::OnUpdateWindowScreenRect(
diff --git a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h
index 3497fe04752..54040dde1ea 100644
--- a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h
+++ b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "content/common/resize_params.h"
+#include "content/common/visual_properties.h"
#include "third_party/blink/public/web/web_device_emulation_params.h"
namespace gfx {
@@ -28,7 +28,7 @@ class CONTENT_EXPORT RenderWidgetScreenMetricsEmulator {
RenderWidgetScreenMetricsEmulator(
RenderWidgetScreenMetricsEmulatorDelegate* delegate,
const blink::WebDeviceEmulationParams& params,
- const ResizeParams& resize_params,
+ const VisualProperties& visual_properties,
const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
virtual ~RenderWidgetScreenMetricsEmulator();
@@ -36,13 +36,13 @@ class CONTENT_EXPORT RenderWidgetScreenMetricsEmulator {
// Scale and offset used to convert between host coordinates
// and webwidget coordinates.
const gfx::Size& original_size() const {
- return original_resize_params_.new_size;
+ return original_visual_properties_.new_size;
}
float scale() const { return scale_; }
const gfx::Rect& applied_widget_rect() const { return applied_widget_rect_; }
const ScreenInfo& original_screen_info() const {
- return original_resize_params_.screen_info;
+ return original_visual_properties_.screen_info;
}
const gfx::Rect& original_screen_rect() const {
return original_view_screen_rect_;
@@ -52,7 +52,7 @@ class CONTENT_EXPORT RenderWidgetScreenMetricsEmulator {
// The following methods alter handlers' behavior for messages related to
// widget size and position.
- void OnResize(const ResizeParams& params);
+ void OnSynchronizeVisualProperties(const VisualProperties& params);
void OnUpdateWindowScreenRect(const gfx::Rect& window_screen_rect);
void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
@@ -75,7 +75,7 @@ class CONTENT_EXPORT RenderWidgetScreenMetricsEmulator {
gfx::Rect applied_widget_rect_;
// Original values to restore back after emulation ends.
- ResizeParams original_resize_params_;
+ VisualProperties original_visual_properties_;
gfx::Rect original_view_screen_rect_;
gfx::Rect original_window_screen_rect_;
diff --git a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h
index af79f1967b6..ac7c8e62bff 100644
--- a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h
+++ b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h
@@ -13,7 +13,7 @@ struct WebDeviceEmulationParams;
namespace content {
-struct ResizeParams;
+struct VisualProperties;
// Consumers of RenderWidgetScreenMetricsEmulatorDelegate implement this
// delegate in order to transport emulation information across processes.
@@ -22,8 +22,9 @@ class CONTENT_EXPORT RenderWidgetScreenMetricsEmulatorDelegate {
// Requests a full redraw of the contents of the renderer.
virtual void Redraw() = 0;
- // Resizes the Widget with the provided |resize_params|.
- virtual void Resize(const ResizeParams& resize_params) = 0;
+ // Synchronize visual properties with the widget.
+ virtual void SynchronizeVisualProperties(
+ const VisualProperties& visual_properties) = 0;
// Passes device emulation parameters to the delegate.
virtual void SetScreenMetricsEmulationParameters(
diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc
index c91dd9293d9..fc8ff6e4ebd 100644
--- a/chromium/content/renderer/dom_serializer_browsertest.cc
+++ b/chromium/content/renderer/dom_serializer_browsertest.cc
@@ -11,7 +11,7 @@
#include "base/containers/hash_tables.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
@@ -140,8 +140,7 @@ class MAYBE_DomSerializerTests : public ContentBrowserTest,
WebData data(contents.data(), contents.length());
GetMainFrame()->LoadData(data, "text/html", encoding_info, base_url);
}
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
+ base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
waiter.Wait();
}
diff --git a/chromium/content/renderer/dom_storage/DEPS b/chromium/content/renderer/dom_storage/DEPS
index 48915ca750d..32e0c4f75bc 100644
--- a/chromium/content/renderer/dom_storage/DEPS
+++ b/chromium/content/renderer/dom_storage/DEPS
@@ -1,6 +1,7 @@
specific_include_rules = {
'local_storage\.*': [
"-content/renderer",
+ "+components/services/leveldb/public/cpp/util.h",
"+components/services/leveldb/public/interfaces",
"+content/common/dom_storage/dom_storage_map.h",
"+content/renderer/dom_storage/local_storage_cached_area.h",
@@ -8,7 +9,7 @@ specific_include_rules = {
"+content/renderer/dom_storage/local_storage_area.h",
"+content/renderer/dom_storage/local_storage_namespace.h",
"+content/renderer/dom_storage/mock_leveldb_wrapper.h",
- "+content/renderer/dom_storage/webstoragenamespace_impl.h",
+ "+content/renderer/dom_storage/session_web_storage_namespace_impl.h",
"+content/renderer/render_thread_impl.h",
],
}
diff --git a/chromium/content/renderer/dom_storage/OWNERS b/chromium/content/renderer/dom_storage/OWNERS
index f3d5983b2f8..c41905dac40 100644
--- a/chromium/content/renderer/dom_storage/OWNERS
+++ b/chromium/content/renderer/dom_storage/OWNERS
@@ -1,8 +1,5 @@
-michaeln@chromium.org
mek@chromium.org
-jsbell@chromium.org
-
-# Please include michaeln@ or mek@ if you make any functional/runtime changes.
+dmurph@chromium.org
# TEAM: storage-dev@chromium.org
# COMPONENT: Blink>Storage>DOMStorage
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area.cc b/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
index def0d2b96a2..a56c6def416 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
@@ -11,12 +11,14 @@
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "components/services/leveldb/public/cpp/util.h"
#include "content/common/dom_storage/dom_storage_map.h"
#include "content/common/storage_partition_service.mojom.h"
#include "content/renderer/dom_storage/local_storage_area.h"
#include "content/renderer/dom_storage/local_storage_cached_areas.h"
-#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
+#include "content/renderer/dom_storage/session_web_storage_namespace_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "third_party/blink/public/platform/web_url.h"
@@ -90,7 +92,6 @@ LocalStorageCachedArea::LocalStorageCachedArea(
mojom::LevelDBObserverAssociatedPtrInfo ptr_info;
binding_.Bind(mojo::MakeRequest(&ptr_info),
main_thread_scheduler->IPCTaskRunner());
- leveldb_->AddObserver(std::move(ptr_info));
}
LocalStorageCachedArea::LocalStorageCachedArea(
@@ -153,24 +154,44 @@ bool LocalStorageCachedArea::SetItem(const base::string16& key,
if (!result)
return false;
+ // Determine data formats.
+ bool is_session_storage = IsSessionStorage();
+ FormatOption key_format = is_session_storage
+ ? FormatOption::kSessionStorageForceUTF8
+ : FormatOption::kLocalStorageDetectFormat;
+ FormatOption value_format = is_session_storage
+ ? FormatOption::kSessionStorageForceUTF16
+ : FormatOption::kLocalStorageDetectFormat;
+
// Ignore mutations to |key| until OnSetItemComplete.
ignore_key_mutations_[key]++;
base::Optional<std::vector<uint8_t>> optional_old_value;
- bool is_session_storage = IsSessionStorage();
if (!old_nullable_value.is_null())
optional_old_value =
- String16ToUint8Vector(old_nullable_value.string(), is_session_storage);
+ String16ToUint8Vector(old_nullable_value.string(), value_format);
blink::WebScopedVirtualTimePauser virtual_time_pauser =
main_thread_scheduler_->CreateWebScopedVirtualTimePauser(
"LocalStorageCachedArea");
virtual_time_pauser.PauseVirtualTime();
- leveldb_->Put(String16ToUint8Vector(key, is_session_storage),
- String16ToUint8Vector(value, is_session_storage),
- optional_old_value, PackSource(page_url, storage_area_id),
+ leveldb_->Put(String16ToUint8Vector(key, key_format),
+ String16ToUint8Vector(value, value_format), optional_old_value,
+ PackSource(page_url, storage_area_id),
base::BindOnce(&LocalStorageCachedArea::OnSetItemComplete,
weak_factory_.GetWeakPtr(), key,
std::move(virtual_time_pauser)));
+ if (IsSessionStorage() &&
+ (old_nullable_value.is_null() || old_nullable_value.string() != value)) {
+ blink::WebStorageArea* originating_area = areas_[storage_area_id];
+ DCHECK_NE(nullptr, originating_area);
+ SessionWebStorageNamespaceImpl session_namespace_for_event_dispatch(
+ namespace_id_, nullptr);
+ blink::WebStorageEventDispatcher::DispatchSessionStorageEvent(
+ blink::WebString::FromUTF16(key),
+ blink::WebString::FromUTF16(old_nullable_value),
+ blink::WebString::FromUTF16(value), origin_.GetURL(), page_url,
+ session_namespace_for_event_dispatch, originating_area);
+ }
return true;
}
@@ -187,26 +208,50 @@ void LocalStorageCachedArea::RemoveItem(const base::string16& key,
if (!result)
return;
+ // Determine data formats.
+ bool is_session_storage = IsSessionStorage();
+ FormatOption key_format = is_session_storage
+ ? FormatOption::kSessionStorageForceUTF8
+ : FormatOption::kLocalStorageDetectFormat;
+ FormatOption value_format = is_session_storage
+ ? FormatOption::kSessionStorageForceUTF16
+ : FormatOption::kLocalStorageDetectFormat;
+
// Ignore mutations to |key| until OnRemoveItemComplete.
ignore_key_mutations_[key]++;
base::Optional<std::vector<uint8_t>> optional_old_value;
- bool is_session_storage = IsSessionStorage();
if (should_send_old_value_on_mutations_)
- optional_old_value = String16ToUint8Vector(old_value, is_session_storage);
+ optional_old_value = String16ToUint8Vector(old_value, value_format);
blink::WebScopedVirtualTimePauser virtual_time_pauser =
main_thread_scheduler_->CreateWebScopedVirtualTimePauser(
"LocalStorageCachedArea");
virtual_time_pauser.PauseVirtualTime();
- leveldb_->Delete(String16ToUint8Vector(key, is_session_storage),
- optional_old_value, PackSource(page_url, storage_area_id),
+ leveldb_->Delete(String16ToUint8Vector(key, key_format), optional_old_value,
+ PackSource(page_url, storage_area_id),
base::BindOnce(&LocalStorageCachedArea::OnRemoveItemComplete,
weak_factory_.GetWeakPtr(), key,
std::move(virtual_time_pauser)));
+ if (IsSessionStorage() && old_value != base::string16()) {
+ blink::WebStorageArea* originating_area = areas_[storage_area_id];
+ DCHECK_NE(nullptr, originating_area);
+ SessionWebStorageNamespaceImpl session_namespace_for_event_dispatch(
+ namespace_id_, nullptr);
+ blink::WebStorageEventDispatcher::DispatchSessionStorageEvent(
+ blink::WebString::FromUTF16(key),
+ blink::WebString::FromUTF16(old_value), blink::WebString(),
+ origin_.GetURL(), page_url, session_namespace_for_event_dispatch,
+ originating_area);
+ }
}
void LocalStorageCachedArea::Clear(const GURL& page_url,
const std::string& storage_area_id) {
+ bool already_empty = false;
+ if (IsSessionStorage()) {
+ EnsureLoaded();
+ already_empty = map_->Length() == 0u;
+ }
// No need to prime the cache in this case.
Reset();
map_ = new DOMStorageMap(kPerStorageAreaQuota);
@@ -220,6 +265,16 @@ void LocalStorageCachedArea::Clear(const GURL& page_url,
base::BindOnce(&LocalStorageCachedArea::OnClearComplete,
weak_factory_.GetWeakPtr(),
std::move(virtual_time_pauser)));
+ if (IsSessionStorage() && !already_empty) {
+ blink::WebStorageArea* originating_area = areas_[storage_area_id];
+ DCHECK_NE(nullptr, originating_area);
+ SessionWebStorageNamespaceImpl session_namespace_for_event_dispatch(
+ namespace_id_, nullptr);
+ blink::WebStorageEventDispatcher::DispatchSessionStorageEvent(
+ blink::WebString(), blink::WebString(), blink::WebString(),
+ origin_.GetURL(), page_url, session_namespace_for_event_dispatch,
+ originating_area);
+ }
}
void LocalStorageCachedArea::AreaCreated(LocalStorageArea* area) {
@@ -233,22 +288,28 @@ void LocalStorageCachedArea::AreaDestroyed(LocalStorageArea* area) {
// static
base::string16 LocalStorageCachedArea::Uint8VectorToString16(
const std::vector<uint8_t>& input,
- bool force_plain_utf16) {
+ FormatOption format_option) {
if (input.empty())
return base::string16();
size_t input_size = input.size();
base::string16 result;
- if (force_plain_utf16) {
- if (input_size % sizeof(base::char16) != 0) {
- // TODO(mek): Better error recovery when corrupt (or otherwise invalid)
- // data is detected.
- LOCAL_HISTOGRAM_BOOLEAN("LocalStorageCachedArea.CorruptData", true);
- LOG(ERROR) << "Corrupt data in domstorage";
- return base::string16();
- }
- result.resize(input_size / sizeof(base::char16));
- std::memcpy(&result[0], input.data(), input_size);
- return result;
+ switch (format_option) {
+ case FormatOption::kSessionStorageForceUTF16:
+ if (input_size % sizeof(base::char16) != 0) {
+ // TODO(mek): Better error recovery when corrupt (or otherwise invalid)
+ // data is detected.
+ LOCAL_HISTOGRAM_BOOLEAN("LocalStorageCachedArea.CorruptData", true);
+ LOG(ERROR) << "Corrupt data in domstorage";
+ return base::string16();
+ }
+ result.resize(input_size / sizeof(base::char16));
+ std::memcpy(&result[0], input.data(), input_size);
+ return result;
+ case FormatOption::kSessionStorageForceUTF8:
+ // Encoding / codepoint errors are ignored on purpose.
+ return base::UTF8ToUTF16(leveldb::Uint8VectorToStringPiece(input));
+ case FormatOption::kLocalStorageDetectFormat:
+ break;
}
StorageFormat format = static_cast<StorageFormat>(input[0]);
const size_t payload_size = input_size - 1;
@@ -282,14 +343,23 @@ base::string16 LocalStorageCachedArea::Uint8VectorToString16(
// static
std::vector<uint8_t> LocalStorageCachedArea::String16ToUint8Vector(
const base::string16& input,
- bool force_plain_utf16) {
- if (force_plain_utf16) {
- std::vector<uint8_t> result;
- result.reserve(input.size() * sizeof(base::char16));
- const uint8_t* data = reinterpret_cast<const uint8_t*>(input.data());
- result.insert(result.begin(), data,
- data + input.size() * sizeof(base::char16));
- return result;
+ FormatOption format_option) {
+ switch (format_option) {
+ case FormatOption::kSessionStorageForceUTF16: {
+ std::vector<uint8_t> result;
+ result.reserve(input.size() * sizeof(base::char16));
+ const uint8_t* data = reinterpret_cast<const uint8_t*>(input.data());
+ result.insert(result.begin(), data,
+ data + input.size() * sizeof(base::char16));
+ return result;
+ }
+ case FormatOption::kSessionStorageForceUTF8: {
+ // Encoding / codepoint errors are ignored on purpose.
+ std::string utf8 = base::UTF16ToUTF8(base::StringPiece16(input));
+ return leveldb::StdStringToUint8Vector(utf8);
+ }
+ case FormatOption::kLocalStorageDetectFormat:
+ break;
}
bool is_8bit = true;
for (const auto& c : input) {
@@ -315,6 +385,7 @@ std::vector<uint8_t> LocalStorageCachedArea::String16ToUint8Vector(
void LocalStorageCachedArea::KeyAdded(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
const std::string& source) {
+ DCHECK(!IsSessionStorage());
base::NullableString16 null_value;
KeyAddedOrChanged(key, value, null_value, source);
}
@@ -323,19 +394,23 @@ void LocalStorageCachedArea::KeyChanged(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& new_value,
const std::vector<uint8_t>& old_value,
const std::string& source) {
+ DCHECK(!IsSessionStorage());
base::NullableString16 old_value_str(
- Uint8VectorToString16(old_value, IsSessionStorage()), false);
+ Uint8VectorToString16(old_value, FormatOption::kLocalStorageDetectFormat),
+ false);
KeyAddedOrChanged(key, new_value, old_value_str, source);
}
void LocalStorageCachedArea::KeyDeleted(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& old_value,
const std::string& source) {
+ DCHECK(!IsSessionStorage());
GURL page_url;
std::string storage_area_id;
UnpackSource(source, &page_url, &storage_area_id);
- base::string16 key_string = Uint8VectorToString16(key, IsSessionStorage());
+ base::string16 key_string =
+ Uint8VectorToString16(key, FormatOption::kLocalStorageDetectFormat);
blink::WebStorageArea* originating_area = nullptr;
if (areas_.find(storage_area_id) != areas_.end()) {
@@ -350,24 +425,15 @@ void LocalStorageCachedArea::KeyDeleted(const std::vector<uint8_t>& key,
map_->RemoveItem(key_string, nullptr);
}
- if (IsSessionStorage()) {
- WebStorageNamespaceImpl session_namespace_for_event_dispatch(namespace_id_);
- blink::WebStorageEventDispatcher::DispatchSessionStorageEvent(
- blink::WebString::FromUTF16(key_string),
- blink::WebString::FromUTF16(
- Uint8VectorToString16(old_value, IsSessionStorage())),
- blink::WebString(), origin_.GetURL(), page_url,
- session_namespace_for_event_dispatch, originating_area);
- } else {
- blink::WebStorageEventDispatcher::DispatchLocalStorageEvent(
- blink::WebString::FromUTF16(key_string),
- blink::WebString::FromUTF16(
- Uint8VectorToString16(old_value, IsSessionStorage())),
- blink::WebString(), origin_.GetURL(), page_url, originating_area);
- }
+ blink::WebStorageEventDispatcher::DispatchLocalStorageEvent(
+ blink::WebString::FromUTF16(key_string),
+ blink::WebString::FromUTF16(Uint8VectorToString16(
+ old_value, FormatOption::kLocalStorageDetectFormat)),
+ blink::WebString(), origin_.GetURL(), page_url, originating_area);
}
void LocalStorageCachedArea::AllDeleted(const std::string& source) {
+ DCHECK(!IsSessionStorage());
GURL page_url;
std::string storage_area_id;
UnpackSource(source, &page_url, &storage_area_id);
@@ -391,21 +457,13 @@ void LocalStorageCachedArea::AllDeleted(const std::string& source) {
}
}
- if (IsSessionStorage()) {
- WebStorageNamespaceImpl session_namespace_for_event_dispatch(namespace_id_);
- blink::WebStorageEventDispatcher::DispatchSessionStorageEvent(
- blink::WebString(), blink::WebString(), blink::WebString(),
- origin_.GetURL(), page_url, session_namespace_for_event_dispatch,
- originating_area);
-
- } else {
- blink::WebStorageEventDispatcher::DispatchLocalStorageEvent(
- blink::WebString(), blink::WebString(), blink::WebString(),
- origin_.GetURL(), page_url, originating_area);
- }
+ blink::WebStorageEventDispatcher::DispatchLocalStorageEvent(
+ blink::WebString(), blink::WebString(), blink::WebString(),
+ origin_.GetURL(), page_url, originating_area);
}
void LocalStorageCachedArea::ShouldSendOldValueOnMutations(bool value) {
+ DCHECK(!IsSessionStorage());
should_send_old_value_on_mutations_ = value;
}
@@ -414,13 +472,15 @@ void LocalStorageCachedArea::KeyAddedOrChanged(
const std::vector<uint8_t>& new_value,
const base::NullableString16& old_value,
const std::string& source) {
+ DCHECK(!IsSessionStorage());
GURL page_url;
std::string storage_area_id;
UnpackSource(source, &page_url, &storage_area_id);
- base::string16 key_string = Uint8VectorToString16(key, IsSessionStorage());
+ base::string16 key_string =
+ Uint8VectorToString16(key, FormatOption::kLocalStorageDetectFormat);
base::string16 new_value_string =
- Uint8VectorToString16(new_value, IsSessionStorage());
+ Uint8VectorToString16(new_value, FormatOption::kLocalStorageDetectFormat);
blink::WebStorageArea* originating_area = nullptr;
if (areas_.find(storage_area_id) != areas_.end()) {
@@ -440,21 +500,11 @@ void LocalStorageCachedArea::KeyAddedOrChanged(
}
}
- if (IsSessionStorage()) {
- WebStorageNamespaceImpl session_namespace_for_event_dispatch(namespace_id_);
- blink::WebStorageEventDispatcher::DispatchSessionStorageEvent(
- blink::WebString::FromUTF16(key_string),
- blink::WebString::FromUTF16(old_value),
- blink::WebString::FromUTF16(new_value_string), origin_.GetURL(),
- page_url, session_namespace_for_event_dispatch, originating_area);
-
- } else {
- blink::WebStorageEventDispatcher::DispatchLocalStorageEvent(
- blink::WebString::FromUTF16(key_string),
- blink::WebString::FromUTF16(old_value),
- blink::WebString::FromUTF16(new_value_string), origin_.GetURL(),
- page_url, originating_area);
- }
+ blink::WebStorageEventDispatcher::DispatchLocalStorageEvent(
+ blink::WebString::FromUTF16(key_string),
+ blink::WebString::FromUTF16(old_value),
+ blink::WebString::FromUTF16(new_value_string), origin_.GetURL(), page_url,
+ originating_area);
}
void LocalStorageCachedArea::EnsureLoaded() {
@@ -472,10 +522,16 @@ void LocalStorageCachedArea::EnsureLoaded() {
DOMStorageValuesMap values;
bool is_session_storage = IsSessionStorage();
+ FormatOption key_format = is_session_storage
+ ? FormatOption::kSessionStorageForceUTF8
+ : FormatOption::kLocalStorageDetectFormat;
+ FormatOption value_format = is_session_storage
+ ? FormatOption::kSessionStorageForceUTF16
+ : FormatOption::kLocalStorageDetectFormat;
for (size_t i = 0; i < data.size(); ++i) {
- values[Uint8VectorToString16(data[i]->key, is_session_storage)] =
+ values[Uint8VectorToString16(data[i]->key, key_format)] =
base::NullableString16(
- Uint8VectorToString16(data[i]->value, is_session_storage), false);
+ Uint8VectorToString16(data[i]->value, value_format), false);
}
map_ = new DOMStorageMap(kPerStorageAreaQuota);
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area.h b/chromium/content/renderer/dom_storage/local_storage_cached_area.h
index 315f8972b46..a4b8b03b4a8 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_area.h
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.h
@@ -90,10 +90,16 @@ class CONTENT_EXPORT LocalStorageCachedArea
friend class LocalStorageCachedAreaTest;
+ enum class FormatOption {
+ kLocalStorageDetectFormat,
+ kSessionStorageForceUTF16,
+ kSessionStorageForceUTF8
+ };
+
static base::string16 Uint8VectorToString16(const std::vector<uint8_t>& input,
- bool force_plain_utf16);
+ FormatOption format_option);
static std::vector<uint8_t> String16ToUint8Vector(const base::string16& input,
- bool force_plain_utf16);
+ FormatOption format_option);
// LevelDBObserver:
void KeyAdded(const std::vector<uint8_t>& key,
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc b/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc
index 98ca9ec2d85..341cbc23f33 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc
@@ -64,12 +64,14 @@ class LocalStorageCachedAreaTest : public testing::Test {
static std::vector<uint8_t> String16ToUint8Vector(
const base::string16& input) {
- return LocalStorageCachedArea::String16ToUint8Vector(input, false);
+ return LocalStorageCachedArea::String16ToUint8Vector(
+ input, LocalStorageCachedArea::FormatOption::kLocalStorageDetectFormat);
}
static base::string16 Uint8VectorToString16(
const std::vector<uint8_t>& input) {
- return LocalStorageCachedArea::Uint8VectorToString16(input, false);
+ return LocalStorageCachedArea::Uint8VectorToString16(
+ input, LocalStorageCachedArea::FormatOption::kLocalStorageDetectFormat);
}
protected:
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc b/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
index b8aeaab96b8..1f2133c87d6 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
@@ -6,6 +6,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/sys_info.h"
+#include "content/common/dom_storage/dom_storage_namespace_ids.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/common/content_features.h"
#include "content/renderer/dom_storage/local_storage_cached_area.h"
@@ -40,7 +41,7 @@ scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea(
scoped_refptr<LocalStorageCachedArea>
LocalStorageCachedAreas::GetSessionStorageArea(const std::string& namespace_id,
const url::Origin& origin) {
- DCHECK_NE(namespace_id, kLocalStorageNamespaceId);
+ DCHECK_NE(kLocalStorageNamespaceId, namespace_id);
return GetCachedArea(namespace_id, origin, main_thread_scheduler_);
}
@@ -48,19 +49,21 @@ void LocalStorageCachedAreas::CloneNamespace(
const std::string& source_namespace,
const std::string& destination_namespace) {
DCHECK(base::FeatureList::IsEnabled(features::kMojoSessionStorage));
+ DCHECK_EQ(kSessionStorageNamespaceIdLength, source_namespace.size());
+ DCHECK_EQ(kSessionStorageNamespaceIdLength, destination_namespace.size());
+
auto namespace_it = cached_namespaces_.find(source_namespace);
- if (namespace_it != cached_namespaces_.end()) {
- namespace_it->second.session_storage_namespace->Clone(
- destination_namespace);
- return;
+ if (namespace_it == cached_namespaces_.end()) {
+ namespace_it =
+ cached_namespaces_
+ .emplace(std::make_pair(source_namespace, DOMStorageNamespace()))
+ .first;
+ storage_partition_service_->OpenSessionStorage(
+ source_namespace,
+ mojo::MakeRequest(&namespace_it->second.session_storage_namespace));
}
- // The clone call still has to be sent, as we can have a case where the
- // storage is never opened but there is still data there (from a restore or
- // an earlier clone).
- mojom::SessionStorageNamespacePtr session_storage_namespace;
- storage_partition_service_->OpenSessionStorage(
- source_namespace, mojo::MakeRequest(&session_storage_namespace));
- session_storage_namespace->Clone(destination_namespace);
+ DCHECK(namespace_it->second.session_storage_namespace);
+ namespace_it->second.session_storage_namespace->Clone(destination_namespace);
}
size_t LocalStorageCachedAreas::TotalCacheSize() const {
@@ -126,9 +129,11 @@ scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea(
origin, storage_partition_service_, this, scheduler);
} else {
DCHECK(base::FeatureList::IsEnabled(features::kMojoSessionStorage));
- storage_partition_service_->OpenSessionStorage(
- namespace_id,
- mojo::MakeRequest(&dom_namespace->session_storage_namespace));
+ if (!dom_namespace->session_storage_namespace) {
+ storage_partition_service_->OpenSessionStorage(
+ namespace_id,
+ mojo::MakeRequest(&dom_namespace->session_storage_namespace));
+ }
result = base::MakeRefCounted<LocalStorageCachedArea>(
namespace_id, origin, dom_namespace->session_storage_namespace.get(),
this, scheduler);
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc b/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc
index b07311bb138..15704b82293 100644
--- a/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc
@@ -4,8 +4,11 @@
#include "content/renderer/dom_storage/local_storage_cached_areas.h"
+#include "base/guid.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
+#include "content/public/common/content_features.h"
#include "content/renderer/dom_storage/local_storage_cached_area.h"
#include "content/renderer/dom_storage/mock_leveldb_wrapper.h"
#include "third_party/blink/public/platform/scheduler/test/fake_renderer_scheduler.h"
@@ -56,4 +59,26 @@ TEST(LocalStorageCachedAreasTest, CacheLimit) {
EXPECT_EQ(cached_area2->memory_used(), cached_areas.TotalCacheSize());
}
+TEST(LocalStorageCachedAreasTest, CloneBeforeGetArea) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kMojoSessionStorage);
+ const std::string kNamespace1 = base::GenerateGUID();
+ const std::string kNamespace2 = base::GenerateGUID();
+ const url::Origin kOrigin = url::Origin::Create(GURL("http://dom_storage1/"));
+
+ blink::scheduler::FakeRendererScheduler renderer_scheduler;
+
+ MockLevelDBWrapper mock_leveldb_wrapper;
+ LocalStorageCachedAreas cached_areas(&mock_leveldb_wrapper,
+ &renderer_scheduler);
+
+ cached_areas.CloneNamespace(kNamespace1, kNamespace2);
+
+ scoped_refptr<LocalStorageCachedArea> cached_area1 =
+ cached_areas.GetSessionStorageArea(kNamespace1, kOrigin);
+ EXPECT_TRUE(cached_area1);
+ EXPECT_EQ(1ul, mock_leveldb_wrapper.NumNamespaceBindings());
+}
+
} // namespace content
diff --git a/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h b/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h
index 28ec3613345..8c96fda2e03 100644
--- a/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h
+++ b/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h
@@ -56,6 +56,8 @@ class MockLevelDBWrapper : public mojom::StoragePartitionService,
// Methods and members for use by test fixtures.
bool HasBindings() { return !bindings_.empty(); }
+ size_t NumNamespaceBindings() { return namespace_bindings_.size(); }
+
void ResetObservations() {
observed_get_all_ = false;
observed_put_ = false;
diff --git a/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc
index 6e43922b7ac..942003c6d00 100644
--- a/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc
+++ b/chromium/content/renderer/fetchers/associated_resource_fetcher_impl.cc
@@ -86,7 +86,7 @@ class AssociatedResourceFetcherImpl::ClientImpl
data_.append(data, data_length);
}
- void DidFinishLoading(double finishTime) override {
+ void DidFinishLoading() override {
// The WebAssociatedURLLoader will continue after a load failure.
// For example, for an Access Control error.
if (completed_)
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc b/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc
index 33f4cb394e2..f6cf6b2b3a5 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_browsertest.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
index 41046213d13..56aca6e806d 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
#include "content/public/common/referrer.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/loader/resource_dispatcher.h"
@@ -186,7 +187,7 @@ class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient {
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) override {
DCHECK_EQ(Status::kStarted, status_);
- loader_->FollowRedirect();
+ loader_->FollowRedirect(base::nullopt);
response_.SetURL(redirect_info.new_url);
}
void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override {}
diff --git a/chromium/content/renderer/fileapi/OWNERS b/chromium/content/renderer/fileapi/OWNERS
index c72d620620e..df298d5781b 100644
--- a/chromium/content/renderer/fileapi/OWNERS
+++ b/chromium/content/renderer/fileapi/OWNERS
@@ -1,5 +1,4 @@
jsbell@chromium.org
-michaeln@chromium.org
pwnall@chromium.org
jianli@chromium.org
tzik@chromium.org
diff --git a/chromium/content/renderer/fileapi/webfilewriter_base_unittest.cc b/chromium/content/renderer/fileapi/webfilewriter_base_unittest.cc
index baff9ae88d1..58bd5aaa08f 100644
--- a/chromium/content/renderer/fileapi/webfilewriter_base_unittest.cc
+++ b/chromium/content/renderer/fileapi/webfilewriter_base_unittest.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_file_error.h"
diff --git a/chromium/content/renderer/gpu/actions_parser.cc b/chromium/content/renderer/gpu/actions_parser.cc
index 5cb285a0974..fe0b34ab0c2 100644
--- a/chromium/content/renderer/gpu/actions_parser.cc
+++ b/chromium/content/renderer/gpu/actions_parser.cc
@@ -117,14 +117,6 @@ bool ActionsParser::ParsePointerActions(const base::DictionaryValue& pointer) {
if (source_type_.empty()) {
source_type_ = source_type;
-
-#if defined(OS_MACOSX)
- if (source_type == "touch") {
- error_message_ =
- base::StringPrintf("Mac OS does not support touch events");
- return false;
- }
-#endif // defined(OS_MACOSX)
}
if (source_type_ != source_type) {
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
index ddf4a1e1f00..cedd8d4ca36 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -13,6 +13,7 @@
#include "base/base64.h"
#include "base/command_line.h"
+#include "base/debug/profiler.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
@@ -295,16 +296,13 @@ bool BeginSmoothScroll(GpuBenchmarkingContext* context,
}
if (gesture_source_type == SyntheticGestureParams::MOUSE_INPUT) {
- // Ensure the mouse is centered and visible, in case it will
+ // Ensure the mouse is visible and move to start position, in case it will
// trigger any hover or mousemove effects.
context->web_view()->SetIsActive(true);
- blink::WebRect content_rect =
- context->render_view_impl()->GetWidget()->ViewRect();
- blink::WebMouseEvent mouseMove(
- blink::WebInputEvent::kMouseMove, blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
- mouseMove.SetPositionInWidget((content_rect.x + content_rect.width / 2.0),
- (content_rect.y + content_rect.height / 2.0));
+ blink::WebMouseEvent mouseMove(blink::WebInputEvent::kMouseMove,
+ blink::WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
+ mouseMove.SetPositionInWidget(start_x, start_y);
context->web_view()->HandleInputEvent(
blink::WebCoalescedInputEvent(mouseMove));
context->web_view()->SetCursorVisibilityState(true);
@@ -550,7 +548,9 @@ gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
.SetMethod("hasGpuChannel", &GpuBenchmarking::HasGpuChannel)
.SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess)
.SetMethod("getGpuDriverBugWorkarounds",
- &GpuBenchmarking::GetGpuDriverBugWorkarounds);
+ &GpuBenchmarking::GetGpuDriverBugWorkarounds)
+ .SetMethod("startProfiling", &GpuBenchmarking::StartProfiling)
+ .SetMethod("stopProfiling", &GpuBenchmarking::StopProfiling);
}
void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
@@ -800,12 +800,12 @@ bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
float anchor_y;
v8::Local<v8::Function> callback;
float relative_pointer_speed_in_pixels_s = 800;
+ int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
- if (!GetArg(args, &scale_factor) ||
- !GetArg(args, &anchor_x) ||
- !GetArg(args, &anchor_y) ||
- !GetOptionalArg(args, &callback) ||
- !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
+ if (!GetArg(args, &scale_factor) || !GetArg(args, &anchor_x) ||
+ !GetArg(args, &anchor_y) || !GetOptionalArg(args, &callback) ||
+ !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s) ||
+ !GetOptionalArg(args, &gesture_source_type)) {
return false;
}
@@ -823,6 +823,27 @@ bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
gesture_params.relative_pointer_speed_in_pixels_s =
relative_pointer_speed_in_pixels_s;
+ if (gesture_source_type < 0 ||
+ gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+ args->ThrowTypeError("Unknown gesture source type");
+ return false;
+ }
+
+ gesture_params.gesture_source_type =
+ static_cast<SyntheticGestureParams::GestureSourceType>(
+ gesture_source_type);
+
+ switch (gesture_params.gesture_source_type) {
+ case SyntheticGestureParams::DEFAULT_INPUT:
+ case SyntheticGestureParams::TOUCH_INPUT:
+ case SyntheticGestureParams::MOUSE_INPUT:
+ break;
+ case SyntheticGestureParams::PEN_INPUT:
+ args->ThrowTypeError(
+ "Gesture is not implemented for the given source type");
+ return false;
+ }
+
scoped_refptr<CallbackAndContext> callback_and_context =
new CallbackAndContext(args->isolate(), callback,
context.web_frame()->MainWorldScriptContext());
@@ -1075,4 +1096,21 @@ void GpuBenchmarking::GetGpuDriverBugWorkarounds(gin::Arguments* args) {
args->Return(result);
}
+void GpuBenchmarking::StartProfiling(gin::Arguments* args) {
+ if (base::debug::BeingProfiled())
+ return;
+ std::string file_name;
+ if (!GetOptionalArg(args, &file_name))
+ return;
+ if (!file_name.length())
+ file_name = "profile.pb";
+ base::debug::StartProfiling(file_name);
+ base::debug::RestartProfilingAfterFork();
+}
+
+void GpuBenchmarking::StopProfiling() {
+ if (base::debug::BeingProfiled())
+ base::debug::StopProfiling();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
index 477f5ed1291..15b285cf7de 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
@@ -82,6 +82,15 @@ class GpuBenchmarking : public gin::Wrappable<GpuBenchmarking> {
bool HasGpuProcess();
void GetGpuDriverBugWorkarounds(gin::Arguments* args);
+ // Starts/stops the sampling profiler. StartProfiling takes one optional
+ // argument, which is a file name for saving the data (relative to `pwd`
+ // or %USERDIR%); if omitted, it defaults to "profile.pb".
+ //
+ // DO NOT USE THIS IN CHROMIUM TESTS -- we don't want to fill up the bots'
+ // hard drives with profile data.
+ void StartProfiling(gin::Arguments* args);
+ void StopProfiling();
+
RenderFrameImpl* render_frame_;
mojom::InputInjectorPtr input_injector_;
DISALLOW_COPY_AND_ASSIGN(GpuBenchmarking);
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.cc b/chromium/content/renderer/gpu/render_widget_compositor.cc
index 9d0ebcbcdc8..e4faef4229e 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor.cc
@@ -34,7 +34,6 @@
#include "cc/base/region.h"
#include "cc/base/switches.h"
#include "cc/benchmarks/micro_benchmark.h"
-#include "cc/blink/web_layer_impl.h"
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/input/layer_selection_bound.h"
#include "cc/layers/layer.h"
@@ -61,15 +60,12 @@
#include "content/public/common/use_zoom_for_dsf_policy.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/gpu/render_widget_compositor_delegate.h"
-#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/render_frame_metadata_observer_impl.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "media/base/media_switches.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
-#include "third_party/blink/public/platform/web_composite_and_readback_async_callback.h"
-#include "third_party/blink/public/platform/web_layout_and_paint_async_callback.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/web/blink.h"
@@ -89,33 +85,19 @@ namespace cc {
class Layer;
}
-using blink::WebFloatPoint;
-using blink::WebRect;
-using blink::WebSelection;
-using blink::WebSize;
-using blink::WebBrowserControlsState;
-using blink::WebLayerTreeView;
-using blink::WebOverscrollBehavior;
-
namespace content {
namespace {
const base::Feature kUnpremultiplyAndDitherLowBitDepthTiles = {
"UnpremultiplyAndDitherLowBitDepthTiles", base::FEATURE_ENABLED_BY_DEFAULT};
-using ReportTimeCallback =
- base::Callback<void(WebLayerTreeView::SwapResult, double)>;
-
-double MonotonicallyIncreasingTime() {
- return static_cast<double>(base::TimeTicks::Now().ToInternalValue()) /
- base::Time::kMicrosecondsPerSecond;
-}
+using ReportTimeCallback = blink::WebLayerTreeView::ReportTimeCallback;
class ReportTimeSwapPromise : public cc::SwapPromise {
public:
ReportTimeSwapPromise(
ReportTimeCallback callback,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~ReportTimeSwapPromise() override;
void DidActivate() override {}
@@ -135,38 +117,37 @@ class ReportTimeSwapPromise : public cc::SwapPromise {
ReportTimeSwapPromise::ReportTimeSwapPromise(
ReportTimeCallback callback,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
- : callback_(callback), task_runner_(task_runner) {}
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : callback_(std::move(callback)), task_runner_(std::move(task_runner)) {}
ReportTimeSwapPromise::~ReportTimeSwapPromise() {}
void ReportTimeSwapPromise::DidSwap() {
task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(callback_, WebLayerTreeView::SwapResult::kDidSwap,
- MonotonicallyIncreasingTime()));
+ FROM_HERE, base::BindOnce(std::move(callback_),
+ blink::WebLayerTreeView::SwapResult::kDidSwap,
+ base::TimeTicks::Now()));
}
cc::SwapPromise::DidNotSwapAction ReportTimeSwapPromise::DidNotSwap(
cc::SwapPromise::DidNotSwapReason reason) {
- WebLayerTreeView::SwapResult result;
+ blink::WebLayerTreeView::SwapResult result;
switch (reason) {
case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS:
- result = WebLayerTreeView::SwapResult::kDidNotSwapSwapFails;
+ result = blink::WebLayerTreeView::SwapResult::kDidNotSwapSwapFails;
break;
case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS:
- result = WebLayerTreeView::SwapResult::kDidNotSwapCommitFails;
+ result = blink::WebLayerTreeView::SwapResult::kDidNotSwapCommitFails;
break;
case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE:
- result = WebLayerTreeView::SwapResult::kDidNotSwapCommitNoUpdate;
+ result = blink::WebLayerTreeView::SwapResult::kDidNotSwapCommitNoUpdate;
break;
case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS:
- result = WebLayerTreeView::SwapResult::kDidNotSwapActivationFails;
+ result = blink::WebLayerTreeView::SwapResult::kDidNotSwapActivationFails;
break;
}
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(callback_, result, MonotonicallyIncreasingTime()));
+ task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback_), result,
+ base::TimeTicks::Now()));
return cc::SwapPromise::DidNotSwapAction::BREAK_PROMISE;
}
@@ -217,7 +198,8 @@ cc::LayerSelectionBound ConvertFromWebSelectionBound(
return cc_bound;
}
-cc::LayerSelection ConvertFromWebSelection(const WebSelection& web_selection) {
+cc::LayerSelection ConvertFromWebSelection(
+ const blink::WebSelection& web_selection) {
if (web_selection.IsNone())
return cc::LayerSelection();
cc::LayerSelection cc_selection;
@@ -267,7 +249,7 @@ static_assert(int(blink::kWebBrowserControlsShown) == int(cc::SHOWN),
"mismatching enums: SHOWN");
static cc::BrowserControlsState ConvertBrowserControlsState(
- WebBrowserControlsState state) {
+ blink::WebBrowserControlsState state) {
return static_cast<cc::BrowserControlsState>(state);
}
@@ -290,7 +272,6 @@ RenderWidgetCompositor::RenderWidgetCompositor(
threaded_(!!compositor_deps_->GetCompositorImplThreadTaskRunner()),
never_visible_(false),
is_for_oopif_(false),
- layout_and_paint_async_callback_(nullptr),
weak_factory_(this) {}
void RenderWidgetCompositor::Initialize(
@@ -367,8 +348,11 @@ cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings(
settings.main_frame_before_activation_enabled =
cmd.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation);
+ // Checkerimaging is not supported for synchronous single-threaded mode, which
+ // is what the renderer uses if its not threaded.
settings.enable_checker_imaging =
- cmd.HasSwitch(cc::switches::kEnableCheckerImaging);
+ !cmd.HasSwitch(cc::switches::kDisableCheckerImaging) && is_threaded;
+
#if defined(OS_ANDROID)
// We can use a more aggressive limit on Android since decodes tend to take
// longer on these devices.
@@ -456,6 +440,7 @@ cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings(
cmd.HasSwitch(cc::switches::kEnableGpuBenchmarking));
settings.enable_surface_synchronization =
features::IsSurfaceSynchronizationEnabled();
+ settings.build_hit_test_data = features::IsVizHitTestingSurfaceLayerEnabled();
if (cmd.HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) {
const int kMinSlowDownScaleFactor = 0;
@@ -550,7 +535,7 @@ cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings(
if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures) &&
base::SysInfo::AmountOfPhysicalMemoryMB() <= 512 &&
!using_synchronous_compositor) {
- settings.preferred_tile_format = viz::RGBA_4444;
+ settings.use_rgba_4444 = viz::RGBA_4444;
// If we are going to unpremultiply and dither these tiles, we need to
// allocate an additional RGBA_8888 intermediate for each tile
@@ -572,11 +557,7 @@ cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings(
if (cmd.HasSwitch(switches::kEnableRGBA4444Textures) &&
!cmd.HasSwitch(switches::kDisableRGBA4444Textures)) {
- settings.preferred_tile_format = viz::RGBA_4444;
- }
-
- if (cmd.HasSwitch(cc::switches::kEnableTileCompression)) {
- settings.preferred_tile_format = viz::ETC1;
+ settings.use_rgba_4444 = true;
}
settings.max_staging_buffer_usage_in_bytes = 32 * 1024 * 1024; // 32MB
@@ -787,6 +768,14 @@ void RenderWidgetCompositor::SetViewportSizeAndScale(
device_viewport_size, device_scale_factor, local_surface_id);
}
+void RenderWidgetCompositor::RequestNewLocalSurfaceId() {
+ layer_tree_host_->RequestNewLocalSurfaceId();
+}
+
+bool RenderWidgetCompositor::HasNewLocalSurfaceIdRequest() const {
+ return layer_tree_host_->new_local_surface_id_request_for_testing();
+}
+
void RenderWidgetCompositor::SetViewportVisibleRect(
const gfx::Rect& visible_rect) {
layer_tree_host_->SetViewportVisibleRect(visible_rect);
@@ -796,29 +785,28 @@ viz::FrameSinkId RenderWidgetCompositor::GetFrameSinkId() {
return frame_sink_id_;
}
-void RenderWidgetCompositor::SetRootLayer(const blink::WebLayer& layer) {
- layer_tree_host_->SetRootLayer(
- static_cast<const cc_blink::WebLayerImpl*>(&layer)->layer());
+void RenderWidgetCompositor::SetRootLayer(scoped_refptr<cc::Layer> layer) {
+ layer_tree_host_->SetRootLayer(std::move(layer));
}
void RenderWidgetCompositor::ClearRootLayer() {
- layer_tree_host_->SetRootLayer(scoped_refptr<cc::Layer>());
+ layer_tree_host_->SetRootLayer(nullptr);
}
cc::AnimationHost* RenderWidgetCompositor::CompositorAnimationHost() {
return animation_host_.get();
}
-WebSize RenderWidgetCompositor::GetViewportSize() const {
+blink::WebSize RenderWidgetCompositor::GetViewportSize() const {
return layer_tree_host_->device_viewport_size();
}
-WebFloatPoint RenderWidgetCompositor::adjustEventPointForPinchZoom(
- const WebFloatPoint& point) const {
+blink::WebFloatPoint RenderWidgetCompositor::adjustEventPointForPinchZoom(
+ const blink::WebFloatPoint& point) const {
return point;
}
-void RenderWidgetCompositor::SetBackgroundColor(blink::WebColor color) {
+void RenderWidgetCompositor::SetBackgroundColor(SkColor color) {
layer_tree_host_->set_background_color(color);
}
@@ -876,34 +864,21 @@ void RenderWidgetCompositor::RegisterViewportLayers(
// like overscroll elasticity may still be nullptr until VisualViewport
// registers its layers.
if (layers.overscroll_elasticity) {
- viewport_layers.overscroll_elasticity =
- static_cast<const cc_blink::WebLayerImpl*>(layers.overscroll_elasticity)
- ->layer();
+ viewport_layers.overscroll_elasticity = layers.overscroll_elasticity;
}
- viewport_layers.page_scale =
- static_cast<const cc_blink::WebLayerImpl*>(layers.page_scale)->layer();
+ viewport_layers.page_scale = layers.page_scale;
if (layers.inner_viewport_container) {
- viewport_layers.inner_viewport_container =
- static_cast<const cc_blink::WebLayerImpl*>(
- layers.inner_viewport_container)
- ->layer();
+ viewport_layers.inner_viewport_container = layers.inner_viewport_container;
}
if (layers.outer_viewport_container) {
- viewport_layers.outer_viewport_container =
- static_cast<const cc_blink::WebLayerImpl*>(
- layers.outer_viewport_container)
- ->layer();
+ viewport_layers.outer_viewport_container = layers.outer_viewport_container;
}
- viewport_layers.inner_viewport_scroll =
- static_cast<const cc_blink::WebLayerImpl*>(layers.inner_viewport_scroll)
- ->layer();
+ viewport_layers.inner_viewport_scroll = layers.inner_viewport_scroll;
// TODO(bokan): This check can probably be removed now, but it looks
// like overscroll elasticity may still be nullptr until VisualViewport
// registers its layers.
if (layers.outer_viewport_scroll) {
- viewport_layers.outer_viewport_scroll =
- static_cast<const cc_blink::WebLayerImpl*>(layers.outer_viewport_scroll)
- ->layer();
+ viewport_layers.outer_viewport_scroll = layers.outer_viewport_scroll;
}
layer_tree_host_->RegisterViewportLayers(viewport_layers);
}
@@ -990,10 +965,9 @@ bool RenderWidgetCompositor::CompositeIsSynchronous() const {
return false;
}
-void RenderWidgetCompositor::LayoutAndPaintAsync(
- blink::WebLayoutAndPaintAsyncCallback* callback) {
- DCHECK(!layout_and_paint_async_callback_);
- layout_and_paint_async_callback_ = callback;
+void RenderWidgetCompositor::LayoutAndPaintAsync(base::OnceClosure callback) {
+ DCHECK(layout_and_paint_async_callback_.is_null());
+ layout_and_paint_async_callback_ = std::move(callback);
if (CompositeIsSynchronous()) {
// The LayoutAndPaintAsyncCallback is invoked in WillCommit, which is
@@ -1018,32 +992,27 @@ void RenderWidgetCompositor::SetLayerTreeFrameSink(
}
void RenderWidgetCompositor::InvokeLayoutAndPaintCallback() {
- if (!layout_and_paint_async_callback_)
- return;
- layout_and_paint_async_callback_->DidLayoutAndPaint();
- layout_and_paint_async_callback_ = nullptr;
+ if (!layout_and_paint_async_callback_.is_null())
+ std::move(layout_and_paint_async_callback_).Run();
}
void RenderWidgetCompositor::CompositeAndReadbackAsync(
- blink::WebCompositeAndReadbackAsyncCallback* callback) {
- DCHECK(!layout_and_paint_async_callback_);
+ base::OnceCallback<void(const SkBitmap&)> callback) {
+ DCHECK(layout_and_paint_async_callback_.is_null());
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner =
layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner();
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
base::BindOnce(
- [](blink::WebCompositeAndReadbackAsyncCallback* callback,
+ [](base::OnceCallback<void(const SkBitmap&)> callback,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<viz::CopyOutputResult> result) {
task_runner->PostTask(
FROM_HERE,
- base::BindOnce(
- &blink::WebCompositeAndReadbackAsyncCallback::
- DidCompositeAndReadback,
- base::Unretained(callback), result->AsSkBitmap()));
+ base::BindOnce(std::move(callback), result->AsSkBitmap()));
},
- callback, std::move(main_thread_task_runner)));
+ std::move(callback), std::move(main_thread_task_runner)));
auto swap_promise =
delegate_->RequestCopyOfOutputForLayoutTest(std::move(request));
@@ -1073,6 +1042,10 @@ void RenderWidgetCompositor::SynchronouslyCompositeNoRasterForTesting() {
SynchronouslyComposite(false /* raster */, nullptr /* swap_promise */);
}
+void RenderWidgetCompositor::CompositeWithRasterForTesting() {
+ SynchronouslyComposite(true /* raster */, nullptr /* swap_promise */);
+}
+
void RenderWidgetCompositor::SynchronouslyComposite(
bool raster,
std::unique_ptr<cc::SwapPromise> swap_promise) {
@@ -1084,8 +1057,7 @@ void RenderWidgetCompositor::SynchronouslyComposite(
// LayoutTests can use a nested message loop to pump frames while inside a
// frame, but the compositor does not support this. In this case, we only
// run blink's lifecycle updates.
- delegate_->BeginMainFrame(
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF());
+ delegate_->BeginMainFrame(base::TimeTicks::Now());
delegate_->UpdateVisualState(
cc::LayerTreeHostClient::VisualStateUpdate::kAll);
return;
@@ -1142,8 +1114,8 @@ void RenderWidgetCompositor::SetShowScrollBottleneckRects(bool show) {
}
void RenderWidgetCompositor::UpdateBrowserControlsState(
- WebBrowserControlsState constraints,
- WebBrowserControlsState current,
+ blink::WebBrowserControlsState constraints,
+ blink::WebBrowserControlsState current,
bool animate) {
layer_tree_host_->UpdateBrowserControlsState(
ConvertBrowserControlsState(constraints),
@@ -1161,7 +1133,7 @@ void RenderWidgetCompositor::SetBrowserControlsShownRatio(float ratio) {
}
void RenderWidgetCompositor::RequestDecode(
- const PaintImage& image,
+ const cc::PaintImage& image,
base::OnceCallback<void(bool)> callback) {
layer_tree_host_->QueueImageDecode(image, std::move(callback));
@@ -1180,7 +1152,7 @@ void RenderWidgetCompositor::RequestDecode(
}
void RenderWidgetCompositor::SetOverscrollBehavior(
- const WebOverscrollBehavior& behavior) {
+ const cc::OverscrollBehavior& behavior) {
layer_tree_host_->SetOverscrollBehavior(behavior);
}
@@ -1192,8 +1164,7 @@ void RenderWidgetCompositor::DidBeginMainFrame() {}
void RenderWidgetCompositor::BeginMainFrame(const viz::BeginFrameArgs& args) {
compositor_deps_->GetWebMainThreadScheduler()->WillBeginFrame(args);
- double frame_time_sec = (args.frame_time - base::TimeTicks()).InSecondsF();
- delegate_->BeginMainFrame(frame_time_sec);
+ delegate_->BeginMainFrame(args.frame_time);
}
void RenderWidgetCompositor::BeginMainFrameNotExpectedSoon() {
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.h b/chromium/content/renderer/gpu/render_widget_compositor.h
index 8b145362d61..933ed484cec 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.h
+++ b/chromium/content/renderer/gpu/render_widget_compositor.h
@@ -56,9 +56,6 @@ class CONTENT_EXPORT RenderWidgetCompositor
: public blink::WebLayerTreeView,
public cc::LayerTreeHostClient,
public cc::LayerTreeHostSingleThreadClient {
- using ReportTimeCallback =
- base::Callback<void(blink::WebLayerTreeView::SwapResult, double)>;
-
public:
// Attempt to construct and initialize a compositor instance for the widget
// with the given settings. Returns NULL if initialization fails.
@@ -124,18 +121,20 @@ class CONTENT_EXPORT RenderWidgetCompositor
void SetViewportSizeAndScale(const gfx::Size& device_viewport_size,
float device_scale_factor,
const viz::LocalSurfaceId& local_surface_id);
+ void RequestNewLocalSurfaceId();
+ bool HasNewLocalSurfaceIdRequest() const;
void SetViewportVisibleRect(const gfx::Rect& visible_rect);
void SetURLForUkm(const GURL& url);
// WebLayerTreeView implementation.
viz::FrameSinkId GetFrameSinkId() override;
- void SetRootLayer(const blink::WebLayer& layer) override;
+ void SetRootLayer(scoped_refptr<cc::Layer> layer) override;
void ClearRootLayer() override;
cc::AnimationHost* CompositorAnimationHost() override;
blink::WebSize GetViewportSize() const override;
virtual blink::WebFloatPoint adjustEventPointForPinchZoom(
const blink::WebFloatPoint& point) const;
- void SetBackgroundColor(blink::WebColor color) override;
+ void SetBackgroundColor(SkColor color) override;
void SetVisible(bool visible) override;
void SetPageScaleFactorAndLimits(float page_scale_factor,
float minimum,
@@ -148,11 +147,11 @@ class CONTENT_EXPORT RenderWidgetCompositor
void HeuristicsForGpuRasterizationUpdated(bool matches_heuristics) override;
void SetNeedsBeginFrame() override;
void DidStopFlinging() override;
- void LayoutAndPaintAsync(
- blink::WebLayoutAndPaintAsyncCallback* callback) override;
+ void LayoutAndPaintAsync(base::OnceClosure callback) override;
void CompositeAndReadbackAsync(
- blink::WebCompositeAndReadbackAsyncCallback* callback) override;
+ base::OnceCallback<void(const SkBitmap&)> callback) override;
void SynchronouslyCompositeNoRasterForTesting() override;
+ void CompositeWithRasterForTesting() override;
void SetDeferCommits(bool defer_commits) override;
void RegisterViewportLayers(
const blink::WebLayerTreeView::ViewportLayers& viewport_layers) override;
@@ -182,10 +181,10 @@ class CONTENT_EXPORT RenderWidgetCompositor
float bottom_height,
bool shrink) override;
void SetBrowserControlsShownRatio(float) override;
- void RequestDecode(const PaintImage& image,
+ void RequestDecode(const cc::PaintImage& image,
base::OnceCallback<void(bool)> callback) override;
- void SetOverscrollBehavior(const blink::WebOverscrollBehavior&) override;
+ void SetOverscrollBehavior(const cc::OverscrollBehavior&) override;
// cc::LayerTreeHostClient implementation.
void WillBeginMainFrame() override;
@@ -254,7 +253,7 @@ class CONTENT_EXPORT RenderWidgetCompositor
bool layer_tree_frame_sink_request_failed_while_invisible_ = false;
bool in_synchronous_compositor_update_ = false;
- blink::WebLayoutAndPaintAsyncCallback* layout_and_paint_async_callback_;
+ base::OnceClosure layout_and_paint_async_callback_;
viz::FrameSinkId frame_sink_id_;
diff --git a/chromium/content/renderer/gpu/render_widget_compositor_delegate.h b/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
index 6dc043bf4d0..24e9453d6dc 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
+++ b/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/time/time.h"
#include "cc/trees/layer_tree_host_client.h"
#include "content/common/content_export.h"
@@ -50,7 +51,7 @@ class CONTENT_EXPORT RenderWidgetCompositorDelegate {
bool has_scrolled_by_touch) = 0;
// Notifies that the compositor has issed a BeginMainFrame.
- virtual void BeginMainFrame(double frame_time_sec) = 0;
+ virtual void BeginMainFrame(base::TimeTicks frame_time) = 0;
// Requests a LayerTreeFrameSink to submit CompositorFrames to.
virtual void RequestNewLayerTreeFrameSink(
diff --git a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
index 1258707c011..b0cd76d9bb5 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -50,7 +50,7 @@ class StubRenderWidgetCompositorDelegate
float top_controls_delta) override {}
void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel,
bool has_scrolled_by_touch) override {}
- void BeginMainFrame(double frame_time_sec) override {}
+ void BeginMainFrame(base::TimeTicks frame_time) override {}
void RequestNewLayerTreeFrameSink(
const LayerTreeFrameSinkCallback& callback) override {
callback.Run(nullptr);
diff --git a/chromium/content/renderer/idle_user_detector.cc b/chromium/content/renderer/idle_user_detector.cc
index 74799834fff..a33ea38de41 100644
--- a/chromium/content/renderer/idle_user_detector.cc
+++ b/chromium/content/renderer/idle_user_detector.cc
@@ -11,17 +11,9 @@
namespace content {
-IdleUserDetector::IdleUserDetector(RenderView* render_view)
- : RenderViewObserver(render_view) {}
+IdleUserDetector::IdleUserDetector() = default;
-IdleUserDetector::~IdleUserDetector() {}
-
-bool IdleUserDetector::OnMessageReceived(const IPC::Message& message) {
- IPC_BEGIN_MESSAGE_MAP(IdleUserDetector, message)
- IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
- IPC_END_MESSAGE_MAP()
- return false;
-}
+IdleUserDetector::~IdleUserDetector() = default;
void IdleUserDetector::ActivityDetected() {
if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) {
@@ -32,14 +24,4 @@ void IdleUserDetector::ActivityDetected() {
}
}
-void IdleUserDetector::OnHandleInputEvent(
- const blink::WebInputEvent* event,
- const std::vector<const blink::WebInputEvent*>& coalesced_events,
- const ui::LatencyInfo& latency_info,
- InputEventDispatchType dispatch_type) {
- ActivityDetected();
-}
-
-void IdleUserDetector::OnDestruct() {}
-
} // namespace content
diff --git a/chromium/content/renderer/idle_user_detector.h b/chromium/content/renderer/idle_user_detector.h
index 1118cb68e31..ead8dcc49dc 100644
--- a/chromium/content/renderer/idle_user_detector.h
+++ b/chromium/content/renderer/idle_user_detector.h
@@ -6,40 +6,19 @@
#define CONTENT_RENDERER_IDLE_USER_DETECTOR_H_
#include "base/macros.h"
-#include "content/common/input/input_event_dispatch_type.h"
-#include "content/public/renderer/render_view_observer.h"
-
-#include <vector>
-
-namespace blink {
-class WebInputEvent;
-}
-
-namespace ui {
-class LatencyInfo;
-}
namespace content {
// Class which observes user input events and postpones
// idle notifications if the user is active.
-class IdleUserDetector : public RenderViewObserver {
+class IdleUserDetector {
public:
- IdleUserDetector(RenderView* render_view);
- ~IdleUserDetector() override;
+ IdleUserDetector();
+ ~IdleUserDetector();
void ActivityDetected();
private:
- // RenderViewObserver implementation:
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnDestruct() override;
-
- void OnHandleInputEvent(
- const blink::WebInputEvent* event,
- const std::vector<const blink::WebInputEvent*>& coalesced_events,
- const ui::LatencyInfo& latency_info,
- InputEventDispatchType dispatch_type);
DISALLOW_COPY_AND_ASSIGN(IdleUserDetector);
};
diff --git a/chromium/content/renderer/image_downloader/image_downloader_base.cc b/chromium/content/renderer/image_downloader/image_downloader_base.cc
index 19dda4fcef9..cd2b1388ddf 100644
--- a/chromium/content/renderer/image_downloader/image_downloader_base.cc
+++ b/chromium/content/renderer/image_downloader/image_downloader_base.cc
@@ -111,7 +111,7 @@ void ImageDownloaderBase::DidFetchImage(
iter->release();
image_fetchers_.erase(iter);
render_frame()
- ->GetTaskRunner(blink::TaskType::kUnthrottled)
+ ->GetTaskRunner(blink::TaskType::kInternalLoading)
->DeleteSoon(FROM_HERE, fetcher);
break;
}
diff --git a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
index 08f03791791..4ccf2af1b8e 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
+++ b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.cc
@@ -49,6 +49,10 @@ void BuildObservationsAndNotify(WebIDBDatabaseCallbacks* callbacks,
IndexedDBCallbacksImpl::ConvertValue(observation->value));
}
+ WebIDBDatabaseCallbacks::ObservationIndexMap observation_index_map(
+ changes->observation_index_map.begin(),
+ changes->observation_index_map.end());
+
std::unordered_map<int32_t, std::pair<int64_t, std::vector<int64_t>>>
observer_transactions;
for (const auto& transaction_pair : changes->transaction_map) {
@@ -60,8 +64,8 @@ void BuildObservationsAndNotify(WebIDBDatabaseCallbacks* callbacks,
std::move(transaction_pair.second->scope));
}
- callbacks->OnChanges(changes->observation_index_map,
- std::move(web_observations), observer_transactions);
+ callbacks->OnChanges(observation_index_map, std::move(web_observations),
+ observer_transactions);
}
} // namespace
diff --git a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
index f6986dd7226..13df0fa2260 100644
--- a/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
+++ b/chromium/content/renderer/indexed_db/indexed_db_database_callbacks_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
#define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_DATABASE_CALLBACKS_IMPL_H_
+#include "base/single_thread_task_runner.h"
#include "content/common/indexed_db/indexed_db.mojom.h"
namespace blink {
diff --git a/chromium/content/renderer/indexed_db/mock_webidbcallbacks.h b/chromium/content/renderer/indexed_db/mock_webidbcallbacks.h
index aa59e310a73..a52677cb4d1 100644
--- a/chromium/content/renderer/indexed_db/mock_webidbcallbacks.h
+++ b/chromium/content/renderer/indexed_db/mock_webidbcallbacks.h
@@ -19,7 +19,7 @@ namespace content {
class MockWebIDBCallbacks : public blink::WebIDBCallbacks {
public:
MockWebIDBCallbacks();
- ~MockWebIDBCallbacks();
+ ~MockWebIDBCallbacks() override;
MOCK_METHOD1(OnError, void(const blink::WebIDBDatabaseError&));
void OnSuccess(blink::WebIDBKey,
diff --git a/chromium/content/renderer/indexed_db/webidbcursor_impl.cc b/chromium/content/renderer/indexed_db/webidbcursor_impl.cc
index 62811b6fd76..797d4d8ed39 100644
--- a/chromium/content/renderer/indexed_db/webidbcursor_impl.cc
+++ b/chromium/content/renderer/indexed_db/webidbcursor_impl.cc
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/single_thread_task_runner.h"
#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
#include "content/renderer/indexed_db/indexed_db_key_builders.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
diff --git a/chromium/content/renderer/input/frame_input_handler_impl.cc b/chromium/content/renderer/input/frame_input_handler_impl.cc
index 9b82d364e8d..d4293d0a857 100644
--- a/chromium/content/renderer/input/frame_input_handler_impl.cc
+++ b/chromium/content/renderer/input/frame_input_handler_impl.cc
@@ -33,7 +33,8 @@ FrameInputHandlerImpl::FrameInputHandlerImpl(
weak_this_ = weak_ptr_factory_.GetWeakPtr();
// If we have created an input event queue move the mojo request over to the
// compositor thread.
- if (RenderThreadImpl::current()->compositor_task_runner() &&
+ if (RenderThreadImpl::current() &&
+ RenderThreadImpl::current()->compositor_task_runner() &&
input_event_queue_) {
// Mojo channel bound on compositor thread.
RenderThreadImpl::current()->compositor_task_runner()->PostTask(
diff --git a/chromium/content/renderer/input/frame_input_handler_impl.h b/chromium/content/renderer/input/frame_input_handler_impl.h
index be452f97f52..794229f0f1e 100644
--- a/chromium/content/renderer/input/frame_input_handler_impl.h
+++ b/chromium/content/renderer/input/frame_input_handler_impl.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_INPUT_FRAME_INPUT_HANDLER_IMPL_H_
#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
#include "content/common/input/input_handler.mojom.h"
#include "content/renderer/render_frame_impl.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -35,7 +36,7 @@ class MainThreadEventQueue;
//
// When a compositor thread isn't used the mojo channel is just bound
// on the main thread and messages are handled right away.
-class FrameInputHandlerImpl : public mojom::FrameInputHandler {
+class CONTENT_EXPORT FrameInputHandlerImpl : public mojom::FrameInputHandler {
public:
static void CreateMojoService(
base::WeakPtr<RenderFrameImpl> render_frame,
diff --git a/chromium/content/renderer/input/input_event_filter.cc b/chromium/content/renderer/input/input_event_filter.cc
deleted file mode 100644
index 60eeab1818d..00000000000
--- a/chromium/content/renderer/input/input_event_filter.cc
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright 2013 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/renderer/input/input_event_filter.h"
-
-#include <tuple>
-#include <utility>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/debug/crash_logging.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/renderer/input/input_handler_manager.h"
-#include "content/renderer/render_thread_impl.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "ui/events/base_event_utils.h"
-#include "ui/events/blink/did_overscroll_params.h"
-#include "ui/events/blink/web_input_event_traits.h"
-#include "ui/gfx/geometry/vector2d_f.h"
-
-using blink::WebInputEvent;
-using ui::DidOverscrollParams;
-
-const char* GetInputMessageTypeName(const IPC::Message& message);
-
-namespace content {
-
-InputEventFilter::InputEventFilter(
- const base::Callback<void(const IPC::Message&)>& main_listener,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
- const scoped_refptr<base::SingleThreadTaskRunner>& target_task_runner)
- : main_task_runner_(main_task_runner),
- main_listener_(main_listener),
- sender_(nullptr),
- target_task_runner_(target_task_runner),
- input_handler_manager_(nullptr) {
- DCHECK(target_task_runner_.get());
- DCHECK(main_task_runner_->BelongsToCurrentThread());
-}
-
-void InputEventFilter::SetInputHandlerManager(
- InputHandlerManager* input_handler_manager) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
- input_handler_manager_ = input_handler_manager;
-}
-
-void InputEventFilter::RegisterRoutingID(
- int routing_id,
- const scoped_refptr<MainThreadEventQueue>& input_event_queue) {
- base::AutoLock locked(routes_lock_);
- routes_.insert(routing_id);
- route_queues_[routing_id] = input_event_queue;
-}
-
-void InputEventFilter::RegisterAssociatedRenderFrameRoutingID(
- int render_frame_routing_id,
- int render_view_routing_id) {
- base::AutoLock locked(routes_lock_);
- DCHECK(routes_.find(render_view_routing_id) != routes_.end());
- associated_routes_[render_frame_routing_id] = render_view_routing_id;
-}
-
-void InputEventFilter::UnregisterRoutingID(int routing_id) {
- base::AutoLock locked(routes_lock_);
- routes_.erase(routing_id);
- route_queues_.erase(routing_id);
- associated_routes_.erase(routing_id);
-}
-
-void InputEventFilter::DidOverscroll(int routing_id,
- const DidOverscrollParams& params) {
- SendMessage(std::unique_ptr<IPC::Message>(
- new InputHostMsg_DidOverscroll(routing_id, params)));
-}
-
-void InputEventFilter::DidStopFlinging(int routing_id) {
- SendMessage(std::make_unique<InputHostMsg_DidStopFlinging>(routing_id));
-}
-
-void InputEventFilter::DidStartScrollingViewport(int routing_id) {
- SendMessage(
- std::make_unique<InputHostMsg_DidStartScrollingViewport>(routing_id));
-}
-
-void InputEventFilter::QueueClosureForMainThreadEventQueue(
- int routing_id,
- const base::Closure& closure) {
- DCHECK(target_task_runner_->BelongsToCurrentThread());
- RouteQueueMap::iterator iter = route_queues_.find(routing_id);
- if (iter != route_queues_.end()) {
- iter->second->QueueClosure(closure);
- return;
- }
-
- // For some reason we didn't find an event queue for the route.
- // Don't drop the task on the floor allow it to execute.
- main_task_runner_->PostTask(FROM_HERE, closure);
-}
-
-void InputEventFilter::DispatchNonBlockingEventToMainThread(
- int routing_id,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info) {
- DCHECK(target_task_runner_->BelongsToCurrentThread());
- RouteQueueMap::iterator iter = route_queues_.find(routing_id);
- if (iter != route_queues_.end()) {
- iter->second->HandleEvent(
- std::move(event), latency_info, DISPATCH_TYPE_NON_BLOCKING,
- INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING, HandledEventCallback());
- }
-}
-
-void InputEventFilter::SetWhiteListedTouchAction(int routing_id,
- cc::TouchAction touch_action,
- uint32_t unique_touch_event_id,
- InputEventAckState ack_state) {
- SendMessage(std::make_unique<InputHostMsg_SetWhiteListedTouchAction>(
- routing_id, touch_action, unique_touch_event_id, ack_state));
-}
-
-void InputEventFilter::OnFilterAdded(IPC::Channel* channel) {
- io_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- sender_ = channel;
-}
-
-void InputEventFilter::OnFilterRemoved() {
- sender_ = nullptr;
-}
-
-void InputEventFilter::OnChannelClosing() {
- sender_ = nullptr;
-}
-
-// This function returns true if the IPC message is one that the compositor
-// thread can handle *or* one that needs to preserve relative order with
-// messages that the compositor thread can handle. Returning true for a message
-// type means that the message will go through an extra copy and thread hop, so
-// use with care.
-static bool RequiresThreadBounce(const IPC::Message& message) {
- return IPC_MESSAGE_ID_CLASS(message.type()) == InputMsgStart;
-}
-
-bool InputEventFilter::OnMessageReceived(const IPC::Message& message) {
- if (!RequiresThreadBounce(message))
- return false;
-
- // If TimeTicks is not consistent across processes we cannot use the event's
- // platform timestamp in this process. Instead the time that the event is
- // received on the IO thread is used as the event's timestamp.
- base::TimeTicks received_time;
- if (!base::TimeTicks::IsConsistentAcrossProcesses())
- received_time = base::TimeTicks::Now();
-
- TRACE_EVENT0("input", "InputEventFilter::OnMessageReceived::InputMessage");
-
- int routing_id = message.routing_id();
- {
- base::AutoLock locked(routes_lock_);
- if (routes_.find(routing_id) == routes_.end()) {
- // |routes_| is based on the RenderView routing_id but the routing_id
- // may be from a RenderFrame. Messages from RenderFrames should be handled
- // synchronously with the associated RenderView as well.
- // Use the associated table to see if we have a mapping from
- // RenderFrame->RenderView if so use the queue for that routing id.
- // TODO(dtapuska): Input messages should NOT be sent to RenderFrames and
- // RenderViews; they should only goto one and this code will be
- // unnecessary as this would break for mojo which doesn't guarantee
- // ordering on different channels but Chrome IPC does.
- auto associated_routing_id = associated_routes_.find(routing_id);
- if (associated_routing_id == associated_routes_.end() ||
- routes_.find(associated_routing_id->second) == routes_.end()) {
- return false;
- }
- routing_id = associated_routing_id->second;
- }
- }
-
- bool postedTask = target_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&InputEventFilter::ForwardToHandler, this,
- routing_id, message, received_time));
- LOG_IF(WARNING, !postedTask) << "PostTask failed";
- return true;
-}
-
-InputEventFilter::~InputEventFilter() {}
-
-void InputEventFilter::ForwardToHandler(int associated_routing_id,
- const IPC::Message& message,
- base::TimeTicks received_time) {
- DCHECK(input_handler_manager_);
- DCHECK(target_task_runner_->BelongsToCurrentThread());
- TRACE_EVENT1("input", "InputEventFilter::ForwardToHandler",
- "message_type", GetInputMessageTypeName(message));
-
- if (message.type() != InputMsg_HandleInputEvent::ID) {
- TRACE_EVENT_INSTANT0(
- "input",
- "InputEventFilter::ForwardToHandler::ForwardToMainListener",
- TRACE_EVENT_SCOPE_THREAD);
- input_handler_manager_->QueueClosureForMainThreadEventQueue(
- associated_routing_id, base::Bind(main_listener_, message));
- return;
- }
-
- InputMsg_HandleInputEvent::Param params;
- if (!InputMsg_HandleInputEvent::Read(&message, &params))
- return;
- ui::WebScopedInputEvent event =
- ui::WebInputEventTraits::Clone(*std::get<0>(params));
- ui::LatencyInfo latency_info = std::get<2>(params);
- InputEventDispatchType dispatch_type = std::get<3>(params);
-
- // HandleInputEvent is always sent to the RenderView routing ID
- // so it should be the same as the message routing ID.
- DCHECK(associated_routing_id == message.routing_id());
- DCHECK(event);
- DCHECK(dispatch_type == DISPATCH_TYPE_BLOCKING ||
- dispatch_type == DISPATCH_TYPE_NON_BLOCKING);
-
- if (!received_time.is_null())
- event->SetTimeStampSeconds(ui::EventTimeStampToSeconds(received_time));
-
- input_handler_manager_->HandleInputEvent(
- associated_routing_id, std::move(event), latency_info,
- base::Bind(&InputEventFilter::DidForwardToHandlerAndOverscroll, this,
- associated_routing_id, dispatch_type));
-};
-
-void InputEventFilter::DidForwardToHandlerAndOverscroll(
- int routing_id,
- InputEventDispatchType dispatch_type,
- InputEventAckState ack_state,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<DidOverscrollParams> overscroll_params) {
- bool send_ack = dispatch_type == DISPATCH_TYPE_BLOCKING;
- uint32_t unique_touch_event_id =
- ui::WebInputEventTraits::GetUniqueTouchEventId(*event);
- WebInputEvent::Type type = event->GetType();
- HandledEventCallback callback;
- if (send_ack) {
- callback = base::Bind(&InputEventFilter::SendInputEventAck, this,
- routing_id, type, unique_touch_event_id);
- }
-
- if (ack_state == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING ||
- ack_state == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING ||
- ack_state == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) {
- DCHECK(!overscroll_params);
- RouteQueueMap::iterator iter = route_queues_.find(routing_id);
- if (iter != route_queues_.end()) {
- iter->second->HandleEvent(std::move(event), latency_info, dispatch_type,
- ack_state, std::move(callback));
- return;
- }
- }
- if (callback) {
- std::move(callback).Run(ack_state, latency_info,
- std::move(overscroll_params), base::nullopt);
- }
-}
-
-void InputEventFilter::SendInputEventAck(
- int routing_id,
- blink::WebInputEvent::Type event_type,
- int unique_touch_event_id,
- InputEventAckState ack_state,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<ui::DidOverscrollParams> overscroll_params,
- base::Optional<cc::TouchAction> touch_action) {
- bool main_thread = main_task_runner_->BelongsToCurrentThread();
-
- InputEventAck ack(main_thread ? InputEventAckSource::MAIN_THREAD
- : InputEventAckSource::COMPOSITOR_THREAD,
- event_type, ack_state, latency_info,
- std::move(overscroll_params), unique_touch_event_id,
- touch_action);
- SendMessage(std::unique_ptr<IPC::Message>(
- new InputHostMsg_HandleInputEvent_ACK(routing_id, ack)));
-}
-
-void InputEventFilter::SendMessage(std::unique_ptr<IPC::Message> message) {
- CHECK(io_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&InputEventFilter::SendMessageOnIOThread, this,
- std::move(message))))
- << "PostTask failed";
-}
-
-void InputEventFilter::SendMessageOnIOThread(
- std::unique_ptr<IPC::Message> message) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- if (!sender_)
- return; // Filter was removed.
-
- bool success = sender_->Send(message.release());
- if (success)
- return;
- static size_t s_send_failure_count_ = 0;
- s_send_failure_count_++;
-
- static auto* crash_key = base::debug::AllocateCrashKeyString(
- "input-event-filter-send-failure", base::debug::CrashKeySize::Size32);
- base::debug::SetCrashKeyString(crash_key,
- base::IntToString(s_send_failure_count_));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/input/input_event_filter.h b/chromium/content/renderer/input/input_event_filter.h
deleted file mode 100644
index d09f6a102c8..00000000000
--- a/chromium/content/renderer/input/input_event_filter.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2013 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_RENDERER_INPUT_INPUT_EVENT_FILTER_H_
-#define CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_
-
-#include <queue>
-#include <set>
-#include <unordered_map>
-
-#include "base/callback.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "content/public/common/input_event_ack_state.h"
-#include "content/renderer/input/input_handler_manager_client.h"
-#include "content/renderer/input/main_thread_event_queue.h"
-#include "ipc/message_filter.h"
-#include "third_party/blink/public/platform/web_input_event.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace ui {
-struct DidOverscrollParams;
-}
-
-namespace IPC {
-class Sender;
-}
-
-// This class can be used to intercept InputMsg_HandleInputEvent messages
-// and have them be delivered to a target thread. Input events are filtered
-// based on routing_id (see AddRoute and RemoveRoute).
-//
-// The user of this class provides an instance of InputHandlerManager via
-// |SetInputHandlerManager|. The InputHandlerManager's |HandleInputEvent|
-// will be called on the target thread to process the WebInputEvents.
-//
-
-namespace content {
-
-class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
- public IPC::MessageFilter {
- public:
- InputEventFilter(
- const base::Callback<void(const IPC::Message&)>& main_listener,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
- const scoped_refptr<base::SingleThreadTaskRunner>& target_task_runner);
-
- // The |handler| is invoked on the thread associated with |target_loop| to
- // handle input events matching the filtered routes.
- //
- // If INPUT_EVENT_ACK_STATE_NOT_CONSUMED is returned by the handler,
- // the original InputMsg_HandleInputEvent message will be delivered to
- // |main_listener| on the main thread. (The "main thread" in this context is
- // the thread where the InputEventFilter was constructed.) The responsibility
- // is left to the eventual handler to deliver the corresponding
- // InputHostMsg_HandleInputEvent_ACK.
- //
- void SetInputHandlerManager(InputHandlerManager*) override;
- void RegisterRoutingID(
- int routing_id,
- const scoped_refptr<MainThreadEventQueue>& input_event_queue) override;
- void UnregisterRoutingID(int routing_id) override;
- void RegisterAssociatedRenderFrameRoutingID(
- int render_frame_routing_id,
- int render_view_routing_id) override;
- void QueueClosureForMainThreadEventQueue(
- int routing_id,
- const base::Closure& closure) override;
- void DidOverscroll(int routing_id,
- const ui::DidOverscrollParams& params) override;
- void DidStopFlinging(int routing_id) override;
- void DidStartScrollingViewport(int routing_id) override;
- void DispatchNonBlockingEventToMainThread(
- int routing_id,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info) override;
- void SetWhiteListedTouchAction(int routing_id,
- cc::TouchAction touch_action,
- uint32_t unique_touch_event_id,
- InputEventAckState ack_state) override;
-
- // IPC::MessageFilter methods:
- void OnFilterAdded(IPC::Channel* channel) override;
- void OnFilterRemoved() override;
- void OnChannelClosing() override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- private:
- ~InputEventFilter() override;
-
- void ForwardToHandler(int routing_id,
- const IPC::Message& message,
- base::TimeTicks received_time);
- void DidForwardToHandlerAndOverscroll(
- int routing_id,
- InputEventDispatchType dispatch_type,
- InputEventAckState ack_state,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<ui::DidOverscrollParams> overscroll_params);
- void SendInputEventAck(
- int routing_id,
- blink::WebInputEvent::Type event_type,
- int unique_touch_event_id,
- InputEventAckState ack_state,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<ui::DidOverscrollParams> overscroll_params,
- base::Optional<cc::TouchAction> touch_action);
- void SendMessage(std::unique_ptr<IPC::Message> message);
- void SendMessageOnIOThread(std::unique_ptr<IPC::Message> message);
-
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
- base::Callback<void(const IPC::Message&)> main_listener_;
-
- // The sender_ only gets invoked on the thread corresponding to io_loop_.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- IPC::Sender* sender_;
-
- // The |input_handler_manager_| should outlive this class and
- // should only be called back on the |target_task_runner_|.
- scoped_refptr<base::SingleThreadTaskRunner> target_task_runner_;
- InputHandlerManager* input_handler_manager_;
-
- // Protects access to routes_.
- base::Lock routes_lock_;
-
- // Indicates the routing ids for RenderViews for which input events
- // should be filtered.
- std::set<int> routes_;
-
- using RouteQueueMap =
- std::unordered_map<int, scoped_refptr<MainThreadEventQueue>>;
- // Maps RenderView routing ids to a MainThreadEventQueue.
- RouteQueueMap route_queues_;
-
- using AssociatedRoutes = std::unordered_map<int, int>;
- // Maps RenderFrame routing ids to RenderView routing ids so that
- // events sent down the two routing pipes can be handled synchronously.
- AssociatedRoutes associated_routes_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_
diff --git a/chromium/content/renderer/input/input_event_filter_ipc_names.cc b/chromium/content/renderer/input/input_event_filter_ipc_names.cc
deleted file mode 100644
index 3d438ce6d2a..00000000000
--- a/chromium/content/renderer/input/input_event_filter_ipc_names.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2017 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/common/input_messages.h"
-
-#include "ipc/ipc_message_null_macros.h"
-#undef IPC_MESSAGE_DECL
-#define IPC_MESSAGE_DECL(name, ...) \
- case name::ID: \
- return #name;
-
-const char* GetInputMessageTypeName(const IPC::Message& message) {
- switch (message.type()) {
-#undef CONTENT_COMMON_INPUT_MESSAGES_H_
-#include "content/common/input_messages.h"
-#ifndef CONTENT_COMMON_INPUT_MESSAGES_H_
-#error "Failed to include content/common/input_messages.h"
-#endif
- default:
- NOTREACHED() << "Invalid message type: " << message.type();
- break;
- };
- return "NonInputMsgType";
-}
diff --git a/chromium/content/renderer/input/input_event_filter_unittest.cc b/chromium/content/renderer/input/input_event_filter_unittest.cc
deleted file mode 100644
index 05aa374836a..00000000000
--- a/chromium/content/renderer/input/input_event_filter_unittest.cc
+++ /dev/null
@@ -1,573 +0,0 @@
-// Copyright 2013 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 <stddef.h>
-
-#include <new>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "content/common/input/synthetic_web_input_event_builders.h"
-#include "content/common/input_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/common/content_features.h"
-#include "content/renderer/input/input_event_filter.h"
-#include "content/renderer/input/input_handler_manager.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_test_sink.h"
-#include "ipc/message_filter.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/mock_renderer_scheduler.h"
-#include "ui/events/blink/web_input_event_traits.h"
-
-using blink::WebInputEvent;
-using blink::WebMouseEvent;
-using blink::WebMouseWheelEvent;
-using blink::WebTouchEvent;
-
-namespace content {
-namespace {
-
-const int kTestRoutingID = 13;
-
-// Simulate a 16ms frame signal.
-const base::TimeDelta kFrameInterval = base::TimeDelta::FromMilliseconds(16);
-
-bool ShouldBlockEventStream(const blink::WebInputEvent& event) {
- return ui::WebInputEventTraits::ShouldBlockEventStream(
- event,
- base::FeatureList::IsEnabled(features::kTouchpadAndWheelScrollLatching));
-}
-
-class MainThreadEventQueueTest;
-
-class InputEventRecorder : public content::InputHandlerManager {
- public:
- InputEventRecorder(InputEventFilter* filter)
- : InputHandlerManager(nullptr, filter, nullptr, nullptr),
- handle_events_(false),
- send_to_widget_(false),
- passive_(false),
- needs_main_frame_(false) {}
-
- ~InputEventRecorder() override {}
-
- void set_handle_events(bool value) { handle_events_ = value; }
- void set_send_to_widget(bool value) { send_to_widget_ = value; }
- void set_passive(bool value) { passive_ = value; }
-
- size_t record_count() const { return records_.size(); }
-
- bool needs_main_frame() const { return needs_main_frame_; }
- void reset_needs_main_frame() { needs_main_frame_ = false; }
-
- const WebInputEvent* record_at(size_t i) const {
- const Record& record = records_[i];
- return reinterpret_cast<const WebInputEvent*>(&record.event_data[0]);
- }
-
- void Clear() {
- records_.clear();
- }
-
- void HandleInputEvent(int routing_id,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info,
- const InputHandlerManager::InputEventAckStateCallback&
- callback) override {
- DCHECK_EQ(kTestRoutingID, routing_id);
- records_.push_back(Record(event.get()));
- if (handle_events_) {
- callback.Run(INPUT_EVENT_ACK_STATE_CONSUMED, std::move(event),
- latency_info, nullptr);
- } else if (send_to_widget_) {
- if (passive_)
- callback.Run(INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING, std::move(event),
- latency_info, nullptr);
- else
- callback.Run(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, std::move(event),
- latency_info, nullptr);
- } else {
- callback.Run(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, std::move(event),
- latency_info, nullptr);
- }
- }
-
- void NeedsMainFrame() { needs_main_frame_ = true; }
-
- private:
- struct Record {
- Record(const WebInputEvent* event) {
- const char* ptr = reinterpret_cast<const char*>(event);
- event_data.assign(ptr, ptr + event->size());
- }
- std::vector<char> event_data;
- };
-
- bool handle_events_;
- bool send_to_widget_;
- bool passive_;
- bool needs_main_frame_;
- std::vector<Record> records_;
-};
-
-class ReceivedEvent;
-class ReceivedMessage;
-
-class ReceivedItem {
- public:
- ReceivedItem() {}
- virtual ~ReceivedItem() {}
-
- virtual const ReceivedMessage* ItemAsmessage() const {
- NOTREACHED();
- return nullptr;
- }
-
- virtual const ReceivedEvent* ItemAsEvent() const {
- NOTREACHED();
- return nullptr;
- }
-};
-
-class ReceivedMessage : public ReceivedItem {
- public:
- ReceivedMessage(const IPC::Message& message) : message_(message) {}
-
- ~ReceivedMessage() override {}
-
- const IPC::Message& message() const { return message_; }
-
- const ReceivedMessage* ItemAsmessage() const override { return this; }
-
- private:
- IPC::Message message_;
-};
-
-class ReceivedEvent : public ReceivedItem {
- public:
- ReceivedEvent(const blink::WebCoalescedInputEvent& event)
- : event_(event.Event(), event.GetCoalescedEventsPointers()) {}
-
- ~ReceivedEvent() override {}
-
- const ReceivedEvent* ItemAsEvent() const override { return this; }
-
- const blink::WebInputEvent& event() const { return event_.Event(); }
-
- private:
- blink::WebCoalescedInputEvent event_;
-};
-
-class IPCMessageRecorder : public IPC::Listener {
- public:
- bool OnMessageReceived(const IPC::Message& message) override {
- std::unique_ptr<ReceivedItem> item(new ReceivedMessage(message));
- messages_.push_back(std::move(item));
- return true;
- }
-
- size_t message_count() const { return messages_.size(); }
-
- const ReceivedMessage& message_at(size_t i) const {
- return *(messages_[i]->ItemAsmessage());
- }
-
- const ReceivedEvent& event_at(size_t i) const {
- return *(messages_[i]->ItemAsEvent());
- }
-
- void AppendEvent(const blink::WebCoalescedInputEvent& event) {
- std::unique_ptr<ReceivedItem> item(new ReceivedEvent(event));
- messages_.push_back(std::move(item));
- }
-
- void Clear() {
- messages_.clear();
- }
-
- private:
- std::vector<std::unique_ptr<ReceivedItem>> messages_;
-};
-
-} // namespace
-
-class InputEventFilterTest : public testing::Test,
- public MainThreadEventQueueClient {
- public:
- InputEventFilterTest()
- : main_task_runner_(new base::TestSimpleTaskRunner()) {}
-
- void SetUp() override {
- filter_ = new InputEventFilter(
- base::Bind(base::IgnoreResult(&IPCMessageRecorder::OnMessageReceived),
- base::Unretained(&message_recorder_)),
- main_task_runner_, main_task_runner_);
- event_recorder_ = std::make_unique<InputEventRecorder>(filter_.get());
- filter_->SetInputHandlerManager(event_recorder_.get());
- filter_->OnFilterAdded(&ipc_sink_);
- }
-
- void AddMessagesToFilter(const std::vector<IPC::Message>& events) {
- for (size_t i = 0; i < events.size(); ++i)
- filter_->OnMessageReceived(events[i]);
-
- // base::RunLoop is the "IO Thread".
- base::RunLoop().RunUntilIdle();
-
- while (event_recorder_->needs_main_frame() ||
- main_task_runner_->HasPendingTask()) {
- main_task_runner_->RunUntilIdle();
- frame_time_ += kFrameInterval;
- event_recorder_->reset_needs_main_frame();
- input_event_queue_->DispatchRafAlignedInput(frame_time_);
-
- // Run queued io thread tasks.
- base::RunLoop().RunUntilIdle();
- }
- }
-
- template <typename T>
- void AddEventsToFilter(const T events[], size_t count) {
- std::vector<IPC::Message> messages;
- for (size_t i = 0; i < count; ++i) {
- messages.push_back(InputMsg_HandleInputEvent(
- kTestRoutingID, &events[i], std::vector<const WebInputEvent*>(),
- ui::LatencyInfo(),
- ShouldBlockEventStream(events[i])
- ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
- : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING));
- }
-
- AddMessagesToFilter(messages);
- }
-
- void RegisterRoute() {
- input_event_queue_ = new MainThreadEventQueue(this, main_task_runner_,
- &renderer_scheduler_, true);
- filter_->RegisterRoutingID(kTestRoutingID, input_event_queue_);
- }
-
- void HandleInputEvent(const blink::WebCoalescedInputEvent& event,
- const ui::LatencyInfo& latency,
- HandledEventCallback callback) override {
- message_recorder_.AppendEvent(event);
- std::move(callback).Run(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, latency,
- nullptr, base::nullopt);
- }
-
- void SetNeedsMainFrame() override { event_recorder_->NeedsMainFrame(); }
-
- protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_;
-
- // Used to record IPCs sent by the filter to the RenderWidgetHost.
- IPC::TestSink ipc_sink_;
-
- // Used to record IPCs forwarded by the filter to the main thread.
- IPCMessageRecorder message_recorder_;
-
- scoped_refptr<InputEventFilter> filter_;
-
- blink::scheduler::MockRendererScheduler renderer_scheduler_;
- scoped_refptr<MainThreadEventQueue> input_event_queue_;
-
- // Used to record WebInputEvents delivered to the handler.
- std::unique_ptr<InputEventRecorder> event_recorder_;
-
- base::TimeTicks frame_time_;
-};
-
-TEST_F(InputEventFilterTest, Basic) {
- WebMouseEvent kEvents[3] = {SyntheticWebMouseEventBuilder::Build(
- WebMouseEvent::kMouseMove, 10, 10, 0),
- SyntheticWebMouseEventBuilder::Build(
- WebMouseEvent::kMouseMove, 20, 20, 0),
- SyntheticWebMouseEventBuilder::Build(
- WebMouseEvent::kMouseMove, 30, 30, 0)};
-
- AddEventsToFilter(kEvents, arraysize(kEvents));
- EXPECT_EQ(0U, ipc_sink_.message_count());
- EXPECT_EQ(0U, event_recorder_->record_count());
- EXPECT_EQ(0U, message_recorder_.message_count());
-
- RegisterRoute();
-
- AddEventsToFilter(kEvents, arraysize(kEvents));
- ASSERT_EQ(arraysize(kEvents), ipc_sink_.message_count());
- ASSERT_EQ(arraysize(kEvents), event_recorder_->record_count());
- EXPECT_EQ(0U, message_recorder_.message_count());
-
- for (size_t i = 0; i < arraysize(kEvents); ++i) {
- const IPC::Message* message = ipc_sink_.GetMessageAt(i);
- EXPECT_EQ(kTestRoutingID, message->routing_id());
- EXPECT_EQ(static_cast<uint32_t>(InputHostMsg_HandleInputEvent_ACK::ID),
- message->type());
-
- InputHostMsg_HandleInputEvent_ACK::Param params;
- EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, &params));
- WebInputEvent::Type event_type = std::get<0>(params).type;
- InputEventAckState ack_result = std::get<0>(params).state;
-
- EXPECT_EQ(kEvents[i].GetType(), event_type);
- EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
-
- const WebInputEvent* event = event_recorder_->record_at(i);
- ASSERT_TRUE(event);
-
- EXPECT_EQ(kEvents[i].size(), event->size());
- EXPECT_TRUE(memcmp(&kEvents[i], event, event->size()) == 0);
- }
-
- event_recorder_->set_send_to_widget(true);
-
- AddEventsToFilter(kEvents, arraysize(kEvents));
- EXPECT_EQ(2 * arraysize(kEvents), ipc_sink_.message_count());
- EXPECT_EQ(2 * arraysize(kEvents), event_recorder_->record_count());
- EXPECT_EQ(1u, message_recorder_.message_count());
-
- {
- const WebInputEvent& event = message_recorder_.event_at(0).event();
- EXPECT_EQ(kEvents[2].size(), event.size());
- EXPECT_TRUE(memcmp(&kEvents[2], &event, event.size()) == 0);
- }
-
- // Now reset everything, and test that DidHandleInputEvent is called.
-
- ipc_sink_.ClearMessages();
- event_recorder_->Clear();
- message_recorder_.Clear();
-
- event_recorder_->set_handle_events(true);
-
- AddEventsToFilter(kEvents, arraysize(kEvents));
- EXPECT_EQ(arraysize(kEvents), ipc_sink_.message_count());
- EXPECT_EQ(arraysize(kEvents), event_recorder_->record_count());
- EXPECT_EQ(0U, message_recorder_.message_count());
-
- for (size_t i = 0; i < arraysize(kEvents); ++i) {
- const IPC::Message* message = ipc_sink_.GetMessageAt(i);
- EXPECT_EQ(kTestRoutingID, message->routing_id());
- EXPECT_EQ(static_cast<uint32_t>(InputHostMsg_HandleInputEvent_ACK::ID),
- message->type());
-
- InputHostMsg_HandleInputEvent_ACK::Param params;
- EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, &params));
- WebInputEvent::Type event_type = std::get<0>(params).type;
- InputEventAckState ack_result = std::get<0>(params).state;
- EXPECT_EQ(kEvents[i].GetType(), event_type);
- EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_CONSUMED);
- }
-
- filter_->OnFilterRemoved();
-}
-
-TEST_F(InputEventFilterTest, PreserveRelativeOrder) {
- RegisterRoute();
- event_recorder_->set_send_to_widget(true);
-
- WebMouseEvent mouse_down =
- SyntheticWebMouseEventBuilder::Build(WebMouseEvent::kMouseDown);
- WebMouseEvent mouse_up =
- SyntheticWebMouseEventBuilder::Build(WebMouseEvent::kMouseUp);
-
- std::vector<IPC::Message> messages;
- messages.push_back(InputMsg_HandleInputEvent(
- kTestRoutingID, &mouse_down, std::vector<const WebInputEvent*>(),
- ui::LatencyInfo(),
- ShouldBlockEventStream(mouse_down)
- ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
- : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING));
- // Control where input events are delivered.
- messages.push_back(InputMsg_MouseCaptureLost(kTestRoutingID));
- messages.push_back(InputMsg_SetFocus(kTestRoutingID, true));
-
- // Editing operations
- messages.push_back(InputMsg_Undo(kTestRoutingID));
- messages.push_back(InputMsg_Redo(kTestRoutingID));
- messages.push_back(InputMsg_Cut(kTestRoutingID));
- messages.push_back(InputMsg_Copy(kTestRoutingID));
-#if defined(OS_MACOSX)
- messages.push_back(InputMsg_CopyToFindPboard(kTestRoutingID));
-#endif
- messages.push_back(InputMsg_Paste(kTestRoutingID));
- messages.push_back(InputMsg_PasteAndMatchStyle(kTestRoutingID));
- messages.push_back(InputMsg_Delete(kTestRoutingID));
- messages.push_back(InputMsg_Replace(kTestRoutingID, base::string16()));
- messages.push_back(InputMsg_ReplaceMisspelling(kTestRoutingID,
- base::string16()));
- messages.push_back(InputMsg_Delete(kTestRoutingID));
- messages.push_back(InputMsg_SelectAll(kTestRoutingID));
- messages.push_back(InputMsg_CollapseSelection(kTestRoutingID));
- messages.push_back(InputMsg_SelectRange(kTestRoutingID,
- gfx::Point(), gfx::Point()));
- messages.push_back(InputMsg_MoveCaret(kTestRoutingID, gfx::Point()));
-
- messages.push_back(InputMsg_HandleInputEvent(
- kTestRoutingID, &mouse_up, std::vector<const WebInputEvent*>(),
- ui::LatencyInfo(),
- ShouldBlockEventStream(mouse_up)
- ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
- : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING));
- AddMessagesToFilter(messages);
-
- // We should have sent all messages back to the main thread and preserved
- // their relative order.
- ASSERT_EQ(message_recorder_.message_count(), messages.size());
- EXPECT_EQ(WebMouseEvent::kMouseDown,
- message_recorder_.event_at(0).event().GetType());
- for (size_t i = 1; i < messages.size() - 1; ++i) {
- EXPECT_EQ(message_recorder_.message_at(i).message().type(),
- messages[i].type())
- << i;
- }
- EXPECT_EQ(WebMouseEvent::kMouseUp,
- message_recorder_.event_at(messages.size() - 1).event().GetType());
-}
-
-TEST_F(InputEventFilterTest, NonBlockingWheel) {
- WebMouseWheelEvent kEvents[4] = {
- SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, 53, 1, false),
- SyntheticWebMouseWheelEventBuilder::Build(20, 20, 0, 53, 0, false),
- SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
- SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
- };
-
- RegisterRoute();
- event_recorder_->set_send_to_widget(true);
- event_recorder_->set_passive(true);
-
- AddEventsToFilter(kEvents, arraysize(kEvents));
- EXPECT_EQ(arraysize(kEvents), event_recorder_->record_count());
- ASSERT_EQ(4u, ipc_sink_.message_count());
-
- // All events are handled, one is coalesced.
- EXPECT_EQ(3u, message_recorder_.message_count());
-
- // First two messages should be identical.
- for (size_t i = 0; i < 2; ++i) {
- const ReceivedEvent& message = message_recorder_.event_at(i);
- const WebInputEvent& event = message.event();
- EXPECT_EQ(kEvents[i].size(), event.size());
- kEvents[i].dispatch_type =
- WebInputEvent::DispatchType::kListenersNonBlockingPassive;
- EXPECT_TRUE(memcmp(&kEvents[i], &event, event.size()) == 0);
- }
-
- // Third message is coalesced.
- {
- const ReceivedEvent& message = message_recorder_.event_at(2);
- const WebMouseWheelEvent& event =
- static_cast<const WebMouseWheelEvent&>(message.event());
- kEvents[2].dispatch_type =
- WebInputEvent::DispatchType::kListenersNonBlockingPassive;
- EXPECT_EQ(kEvents[2].size(), event.size());
- EXPECT_EQ(kEvents[2].delta_x + kEvents[3].delta_x, event.delta_x);
- EXPECT_EQ(kEvents[2].delta_y + kEvents[3].delta_y, event.delta_y);
- }
-}
-
-TEST_F(InputEventFilterTest, NonBlockingTouch) {
- SyntheticWebTouchEvent kEvents[4];
- kEvents[0].PressPoint(10, 10);
- kEvents[1].PressPoint(10, 10);
- kEvents[1].SetModifiers(1);
- kEvents[1].MovePoint(0, 20, 20);
- kEvents[2].PressPoint(10, 10);
- kEvents[2].MovePoint(0, 30, 30);
- kEvents[3].PressPoint(10, 10);
- kEvents[3].MovePoint(0, 35, 35);
-
- RegisterRoute();
- event_recorder_->set_send_to_widget(true);
- event_recorder_->set_passive(true);
-
- AddEventsToFilter(kEvents, arraysize(kEvents));
- EXPECT_EQ(arraysize(kEvents), event_recorder_->record_count());
- ASSERT_EQ(4u, ipc_sink_.message_count());
-
- // All events are handled and one set was coalesced.
- EXPECT_EQ(3u, message_recorder_.message_count());
-
- // First two messages should be identical.
- for (size_t i = 0; i < 2; ++i) {
- const ReceivedEvent& message = message_recorder_.event_at(i);
- const WebInputEvent& event = message.event();
- EXPECT_EQ(kEvents[i].size(), event.size());
- kEvents[i].dispatch_type =
- WebInputEvent::DispatchType::kListenersNonBlockingPassive;
- EXPECT_TRUE(memcmp(&kEvents[i], &event, event.size()) == 0);
- }
-
- // Third message is coalesced.
- {
- const ReceivedEvent& message = message_recorder_.event_at(2);
- const WebTouchEvent& event =
- static_cast<const WebTouchEvent&>(message.event());
- EXPECT_EQ(kEvents[3].size(), event.size());
- EXPECT_EQ(1u, kEvents[3].touches_length);
- EXPECT_EQ(kEvents[3].touches[0].PositionInWidget().x,
- event.touches[0].PositionInWidget().x);
- EXPECT_EQ(kEvents[3].touches[0].PositionInWidget().y,
- event.touches[0].PositionInWidget().y);
- }
-}
-
-TEST_F(InputEventFilterTest, IntermingledNonBlockingTouch) {
- SyntheticWebTouchEvent kEvents[2];
- kEvents[0].PressPoint(10, 10);
- kEvents[1].PressPoint(10, 10);
- kEvents[1].ReleasePoint(0);
- SyntheticWebTouchEvent kBlockingEvents[1];
- kBlockingEvents[0].PressPoint(10, 10);
-
- RegisterRoute();
- event_recorder_->set_send_to_widget(true);
- event_recorder_->set_passive(true);
- AddEventsToFilter(kEvents, arraysize(kEvents));
- EXPECT_EQ(arraysize(kEvents), event_recorder_->record_count());
-
- event_recorder_->set_passive(false);
- AddEventsToFilter(kBlockingEvents, arraysize(kBlockingEvents));
- EXPECT_EQ(arraysize(kEvents) + arraysize(kBlockingEvents),
- event_recorder_->record_count());
- ASSERT_EQ(3u, event_recorder_->record_count());
- EXPECT_EQ(3u, message_recorder_.message_count());
-
- {
- const ReceivedEvent& message = message_recorder_.event_at(0);
- const WebInputEvent& event = message.event();
- EXPECT_EQ(kEvents[0].size(), event.size());
- kEvents[0].dispatch_type =
- WebInputEvent::DispatchType::kListenersNonBlockingPassive;
- EXPECT_TRUE(memcmp(&kEvents[0], &event, event.size()) == 0);
- }
-
- {
- const ReceivedEvent& message = message_recorder_.event_at(1);
- const WebInputEvent& event = message.event();
- EXPECT_EQ(kEvents[1].size(), event.size());
- kEvents[1].dispatch_type =
- WebInputEvent::DispatchType::kListenersNonBlockingPassive;
- EXPECT_TRUE(memcmp(&kEvents[1], &event, event.size()) == 0);
- }
-
- {
- const ReceivedEvent& message = message_recorder_.event_at(2);
- const WebInputEvent& event = message.event();
- EXPECT_EQ(kBlockingEvents[0].size(), event.size());
- EXPECT_TRUE(memcmp(&kBlockingEvents[0], &event, event.size()) == 0);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/input/input_event_prediction.cc b/chromium/content/renderer/input/input_event_prediction.cc
new file mode 100644
index 00000000000..89636c9736d
--- /dev/null
+++ b/chromium/content/renderer/input/input_event_prediction.cc
@@ -0,0 +1,160 @@
+// 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/renderer/input/input_event_prediction.h"
+
+#include "base/feature_list.h"
+#include "content/public/common/content_features.h"
+#include "ui/events/blink/prediction/empty_predictor.h"
+
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebPointerEvent;
+using blink::WebPointerProperties;
+using blink::WebTouchEvent;
+
+namespace content {
+
+namespace {
+
+std::unique_ptr<ui::InputPredictor> SetUpPredictor() {
+ return std::make_unique<ui::EmptyPredictor>();
+}
+
+} // namespace
+
+InputEventPrediction::InputEventPrediction() {
+ mouse_predictor_ = SetUpPredictor();
+}
+
+InputEventPrediction::~InputEventPrediction() {}
+
+void InputEventPrediction::HandleEvents(
+ const blink::WebCoalescedInputEvent& coalesced_event,
+ base::TimeTicks frame_time,
+ blink::WebInputEvent* event) {
+ switch (event->GetType()) {
+ case WebInputEvent::kMouseMove:
+ case WebInputEvent::kTouchMove:
+ case WebInputEvent::kPointerMove: {
+ size_t coalesced_size = coalesced_event.CoalescedEventSize();
+ for (size_t i = 0; i < coalesced_size; i++)
+ UpdatePrediction(coalesced_event.CoalescedEvent(i));
+
+ ApplyResampling(frame_time, event);
+ break;
+ }
+ case WebInputEvent::kTouchScrollStarted:
+ case WebInputEvent::kPointerCausedUaAction:
+ pointer_id_predictor_map_.clear();
+ break;
+ default:
+ ResetPredictor(*event);
+ }
+}
+
+void InputEventPrediction::UpdatePrediction(const WebInputEvent& event) {
+ if (WebInputEvent::IsTouchEventType(event.GetType())) {
+ DCHECK(event.GetType() == WebInputEvent::kTouchMove);
+ const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
+ for (unsigned i = 0; i < touch_event.touches_length; ++i) {
+ if (touch_event.touches[i].state == blink::WebTouchPoint::kStateMoved) {
+ UpdateSinglePointer(touch_event.touches[i], touch_event.TimeStamp());
+ }
+ }
+ } else if (WebInputEvent::IsMouseEventType(event.GetType())) {
+ DCHECK(event.GetType() == WebInputEvent::kMouseMove);
+ UpdateSinglePointer(static_cast<const WebMouseEvent&>(event),
+ event.TimeStamp());
+ } else if (WebInputEvent::IsPointerEventType(event.GetType())) {
+ DCHECK(event.GetType() == WebInputEvent::kPointerMove);
+ UpdateSinglePointer(static_cast<const WebPointerEvent&>(event),
+ event.TimeStamp());
+ }
+}
+
+void InputEventPrediction::ApplyResampling(base::TimeTicks frame_time,
+ WebInputEvent* event) {
+ if (event->GetType() == WebInputEvent::kTouchMove) {
+ WebTouchEvent* touch_event = static_cast<WebTouchEvent*>(event);
+ for (unsigned i = 0; i < touch_event->touches_length; ++i) {
+ if (ResampleSinglePointer(frame_time, &touch_event->touches[i]))
+ event->SetTimeStamp(frame_time);
+ }
+ } else if (event->GetType() == WebInputEvent::kMouseMove) {
+ if (ResampleSinglePointer(frame_time, static_cast<WebMouseEvent*>(event)))
+ event->SetTimeStamp(frame_time);
+ } else if (event->GetType() == WebInputEvent::kPointerMove) {
+ if (ResampleSinglePointer(frame_time, static_cast<WebPointerEvent*>(event)))
+ event->SetTimeStamp(frame_time);
+ }
+}
+
+void InputEventPrediction::ResetPredictor(const WebInputEvent& event) {
+ if (WebInputEvent::IsTouchEventType(event.GetType())) {
+ const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
+ for (unsigned i = 0; i < touch_event.touches_length; ++i) {
+ if (touch_event.touches[i].state != blink::WebTouchPoint::kStateMoved &&
+ touch_event.touches[i].state !=
+ blink::WebTouchPoint::kStateStationary)
+ pointer_id_predictor_map_.erase(touch_event.touches[i].id);
+ }
+ } else if (WebInputEvent::IsMouseEventType(event.GetType())) {
+ ResetSinglePredictor(static_cast<const WebMouseEvent&>(event));
+ } else if (WebInputEvent::IsPointerEventType(event.GetType())) {
+ ResetSinglePredictor(static_cast<const WebPointerEvent&>(event));
+ }
+}
+
+void InputEventPrediction::UpdateSinglePointer(
+ const WebPointerProperties& event,
+ base::TimeTicks event_time) {
+ ui::InputPredictor::InputData data = {event.PositionInWidget().x,
+ event.PositionInWidget().y, event_time};
+ if (event.pointer_type == WebPointerProperties::PointerType::kMouse)
+ mouse_predictor_->Update(data);
+ else {
+ auto predictor = pointer_id_predictor_map_.find(event.id);
+ if (predictor != pointer_id_predictor_map_.end()) {
+ predictor->second->Update(data);
+ } else {
+ pointer_id_predictor_map_.insert({event.id, SetUpPredictor()});
+ pointer_id_predictor_map_[event.id]->Update(data);
+ }
+ }
+}
+
+bool InputEventPrediction::ResampleSinglePointer(base::TimeTicks frame_time,
+ WebPointerProperties* event) {
+ ui::InputPredictor::InputData predict_result;
+ if (event->pointer_type == WebPointerProperties::PointerType::kMouse) {
+ if (mouse_predictor_->HasPrediction() &&
+ mouse_predictor_->GeneratePrediction(frame_time, &predict_result)) {
+ event->SetPositionInWidget(predict_result.pos_x, predict_result.pos_y);
+ return true;
+ }
+ } else {
+ // Reset mouse predictor if pointer type is touch or stylus
+ mouse_predictor_->Reset();
+
+ auto predictor = pointer_id_predictor_map_.find(event->id);
+ if (predictor != pointer_id_predictor_map_.end() &&
+ predictor->second->HasPrediction() &&
+ predictor->second->GeneratePrediction(frame_time, &predict_result)) {
+ event->SetPositionInWidget(predict_result.pos_x, predict_result.pos_y);
+ return true;
+ }
+ }
+ return false;
+}
+
+void InputEventPrediction::ResetSinglePredictor(
+ const WebPointerProperties& event) {
+ if (event.pointer_type == WebPointerProperties::PointerType::kMouse)
+ mouse_predictor_->Reset();
+ else
+ pointer_id_predictor_map_.erase(event.id);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/input/input_event_prediction.h b/chromium/content/renderer/input/input_event_prediction.h
new file mode 100644
index 00000000000..59a473e977d
--- /dev/null
+++ b/chromium/content/renderer/input/input_event_prediction.h
@@ -0,0 +1,66 @@
+// 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_RENDERER_INPUT_INPUT_EVENT_PREDICTION_H_
+#define CONTENT_RENDERER_INPUT_INPUT_EVENT_PREDICTION_H_
+
+#include <list>
+#include <unordered_map>
+
+#include "content/renderer/input/scoped_web_input_event_with_latency_info.h"
+#include "ui/events/blink/prediction/input_predictor.h"
+#include "ui/events/event.h"
+
+using blink::WebInputEvent;
+using blink::WebPointerProperties;
+
+namespace content {
+
+// Handle resampling of WebMouseEvent, WebTouchEvent and WebPointerEvent.
+// This class stores prediction of all active pointers.
+class CONTENT_EXPORT InputEventPrediction {
+ public:
+ InputEventPrediction();
+ ~InputEventPrediction();
+
+ void HandleEvents(const blink::WebCoalescedInputEvent& coalesced_event,
+ base::TimeTicks frame_time,
+ blink::WebInputEvent* event);
+
+ private:
+ // The following three function is for handling multiple TouchPoints in a
+ // WebTouchEvent. They should be more neat when WebTouchEvent is elimated.
+ // Cast events from WebInputEvent to WebPointerProperties. Call
+ // UpdateSinglePointer for each pointer.
+ void UpdatePrediction(const WebInputEvent& event);
+ // Cast events from WebInputEvent to WebPointerProperties. Call
+ // ResamplingSinglePointer for each poitner.
+ void ApplyResampling(base::TimeTicks frame_time, WebInputEvent* event);
+ // Cast events from WebInputEvent to WebPointerProperties. Call
+ // ResetSinglePredictor for each pointer.
+ void ResetPredictor(const WebInputEvent& event);
+
+ // Get single predictor based on event id and type, and update the predictor
+ // with new events coords.
+ void UpdateSinglePointer(const WebPointerProperties& event,
+ base::TimeTicks time);
+ // Get single predictor based on event id and type, apply resampling event
+ // coordinates.
+ bool ResampleSinglePointer(base::TimeTicks time, WebPointerProperties* event);
+ // Get single predictor based on event id and type. For mouse, reset the
+ // predictor, for other pointer type, remove it from mapping.
+ void ResetSinglePredictor(const WebPointerProperties& event);
+
+ friend class InputEventPredictionTest;
+
+ std::unordered_map<ui::PointerId, std::unique_ptr<ui::InputPredictor>>
+ pointer_id_predictor_map_;
+ std::unique_ptr<ui::InputPredictor> mouse_predictor_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputEventPrediction);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_INPUT_INPUT_EVENT_PREDICTION_H_
diff --git a/chromium/content/renderer/input/input_event_prediction_unittest.cc b/chromium/content/renderer/input/input_event_prediction_unittest.cc
new file mode 100644
index 00000000000..a0d5a498031
--- /dev/null
+++ b/chromium/content/renderer/input/input_event_prediction_unittest.cc
@@ -0,0 +1,213 @@
+// 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/renderer/input/input_event_prediction.h"
+
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/blink/prediction/empty_predictor.h"
+
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebPointerProperties;
+using blink::WebTouchEvent;
+
+namespace content {
+
+class InputEventPredictionTest : public testing::Test {
+ public:
+ InputEventPredictionTest() {
+ event_predictor_ = std::make_unique<InputEventPrediction>();
+ }
+
+ int GetPredictorMapSize() const {
+ return event_predictor_->pointer_id_predictor_map_.size();
+ }
+
+ bool GetPrediction(const WebPointerProperties& event,
+ ui::InputPredictor::InputData* result) const {
+ if (!event_predictor_)
+ return false;
+
+ if (event.pointer_type == WebPointerProperties::PointerType::kMouse) {
+ return event_predictor_->mouse_predictor_->GeneratePrediction(
+ WebInputEvent::GetStaticTimeStampForTests(), result);
+ } else {
+ auto predictor =
+ event_predictor_->pointer_id_predictor_map_.find(event.id);
+
+ if (predictor != event_predictor_->pointer_id_predictor_map_.end())
+ return predictor->second->GeneratePrediction(
+ WebInputEvent::GetStaticTimeStampForTests(), result);
+ else
+ return false;
+ }
+ }
+
+ void HandleEvents(const WebInputEvent& event) {
+ blink::WebCoalescedInputEvent coalesced_event(event);
+ event_predictor_->HandleEvents(coalesced_event,
+ WebInputEvent::GetStaticTimeStampForTests(),
+ coalesced_event.EventPointer());
+ }
+
+ protected:
+ std::unique_ptr<InputEventPrediction> event_predictor_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputEventPredictionTest);
+};
+
+TEST_F(InputEventPredictionTest, MouseEvent) {
+ WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseMove, 10, 10, 0);
+
+ ui::InputPredictor::InputData last_point;
+ EXPECT_FALSE(GetPrediction(mouse_move, &last_point));
+
+ HandleEvents(mouse_move);
+ EXPECT_EQ(GetPredictorMapSize(), 0);
+ EXPECT_TRUE(GetPrediction(mouse_move, &last_point));
+ EXPECT_EQ(last_point.pos_x, 10);
+ EXPECT_EQ(last_point.pos_y, 10);
+
+ WebMouseEvent mouse_down = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseDown, 10, 10, 0);
+ HandleEvents(mouse_down);
+ EXPECT_FALSE(GetPrediction(mouse_down, &last_point));
+}
+
+TEST_F(InputEventPredictionTest, SingleTouchPoint) {
+ SyntheticWebTouchEvent touch_event;
+
+ ui::InputPredictor::InputData last_point;
+
+ touch_event.PressPoint(10, 10);
+ touch_event.touches[0].pointer_type =
+ WebPointerProperties::PointerType::kTouch;
+ HandleEvents(touch_event);
+ EXPECT_FALSE(GetPrediction(touch_event.touches[0], &last_point));
+
+ touch_event.MovePoint(0, 11, 12);
+ HandleEvents(touch_event);
+ EXPECT_EQ(GetPredictorMapSize(), 1);
+ EXPECT_TRUE(GetPrediction(touch_event.touches[0], &last_point));
+ EXPECT_EQ(last_point.pos_x, 11);
+ EXPECT_EQ(last_point.pos_y, 12);
+
+ touch_event.ReleasePoint(0);
+ HandleEvents(touch_event);
+ EXPECT_FALSE(GetPrediction(touch_event.touches[0], &last_point));
+}
+
+TEST_F(InputEventPredictionTest, MouseEventTypePen) {
+ WebMouseEvent pen_move = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseMove, 10, 10, 0,
+ WebPointerProperties::PointerType::kPen);
+
+ ui::InputPredictor::InputData last_point;
+ EXPECT_FALSE(GetPrediction(pen_move, &last_point));
+ HandleEvents(pen_move);
+ EXPECT_EQ(GetPredictorMapSize(), 1);
+ EXPECT_TRUE(GetPrediction(pen_move, &last_point));
+ EXPECT_EQ(last_point.pos_x, 10);
+ EXPECT_EQ(last_point.pos_y, 10);
+
+ WebMouseEvent pen_leave = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseLeave, 10, 10, 0,
+ WebPointerProperties::PointerType::kPen);
+ HandleEvents(pen_leave);
+ EXPECT_EQ(GetPredictorMapSize(), 0);
+ EXPECT_FALSE(GetPrediction(pen_leave, &last_point));
+}
+
+TEST_F(InputEventPredictionTest, MultipleTouchPoint) {
+ SyntheticWebTouchEvent touch_event;
+
+ // Press and move 1st touch point
+ touch_event.PressPoint(10, 10);
+ touch_event.MovePoint(0, 11, 12);
+ touch_event.touches[0].pointer_type =
+ WebPointerProperties::PointerType::kTouch;
+ HandleEvents(touch_event);
+
+ // Press 2nd touch point
+ touch_event.PressPoint(20, 30);
+ touch_event.touches[1].pointer_type = WebPointerProperties::PointerType::kPen;
+ HandleEvents(touch_event);
+ EXPECT_EQ(GetPredictorMapSize(), 1);
+
+ // Move 2nd touch point
+ touch_event.MovePoint(1, 25, 25);
+ HandleEvents(touch_event);
+ EXPECT_EQ(GetPredictorMapSize(), 2);
+
+ ui::InputPredictor::InputData last_point;
+ EXPECT_TRUE(GetPrediction(touch_event.touches[0], &last_point));
+ EXPECT_EQ(last_point.pos_x, 11);
+ EXPECT_EQ(last_point.pos_y, 12);
+
+ EXPECT_TRUE(GetPrediction(touch_event.touches[1], &last_point));
+ EXPECT_EQ(last_point.pos_x, 25);
+ EXPECT_EQ(last_point.pos_y, 25);
+
+ touch_event.ReleasePoint(0);
+ HandleEvents(touch_event);
+ EXPECT_EQ(GetPredictorMapSize(), 1);
+}
+
+TEST_F(InputEventPredictionTest, TouchAndStylusResetMousePredictor) {
+ WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseMove, 10, 10, 0);
+ HandleEvents(mouse_move);
+ ui::InputPredictor::InputData last_point;
+ EXPECT_TRUE(GetPrediction(mouse_move, &last_point));
+
+ WebMouseEvent pen_move = SyntheticWebMouseEventBuilder::Build(
+ WebInputEvent::kMouseMove, 20, 20, 0,
+ WebPointerProperties::PointerType::kPen);
+ pen_move.id = 1;
+ HandleEvents(pen_move);
+ EXPECT_TRUE(GetPrediction(pen_move, &last_point));
+ EXPECT_FALSE(GetPrediction(mouse_move, &last_point));
+
+ HandleEvents(mouse_move);
+ EXPECT_TRUE(GetPrediction(mouse_move, &last_point));
+
+ SyntheticWebTouchEvent touch_event;
+ touch_event.PressPoint(10, 10);
+ touch_event.touches[0].pointer_type =
+ WebPointerProperties::PointerType::kTouch;
+ HandleEvents(touch_event);
+ touch_event.MovePoint(0, 10, 10);
+ HandleEvents(touch_event);
+ EXPECT_TRUE(GetPrediction(touch_event.touches[0], &last_point));
+ EXPECT_FALSE(GetPrediction(mouse_move, &last_point));
+}
+
+// TouchScrollStarted event removes all touch points.
+TEST_F(InputEventPredictionTest, TouchScrollStartedRemoveAllTouchPoints) {
+ SyntheticWebTouchEvent touch_event;
+
+ // Press 1st & 2nd touch point
+ touch_event.PressPoint(10, 10);
+ touch_event.touches[0].pointer_type =
+ WebPointerProperties::PointerType::kTouch;
+ touch_event.PressPoint(20, 20);
+ touch_event.touches[1].pointer_type =
+ WebPointerProperties::PointerType::kTouch;
+ HandleEvents(touch_event);
+
+ // Move 1st & 2nd touch point
+ touch_event.MovePoint(0, 15, 18);
+ touch_event.MovePoint(1, 25, 27);
+ HandleEvents(touch_event);
+ EXPECT_EQ(GetPredictorMapSize(), 2);
+
+ touch_event.SetType(WebInputEvent::kTouchScrollStarted);
+ HandleEvents(touch_event);
+ EXPECT_EQ(GetPredictorMapSize(), 0);
+}
+
+} // namespace content \ No newline at end of file
diff --git a/chromium/content/renderer/input/input_handler_manager.cc b/chromium/content/renderer/input/input_handler_manager.cc
deleted file mode 100644
index e164e177d0e..00000000000
--- a/chromium/content/renderer/input/input_handler_manager.cc
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2013 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/renderer/input/input_handler_manager.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/input/input_handler.h"
-#include "content/renderer/input/input_event_filter.h"
-#include "content/renderer/input/input_handler_manager_client.h"
-#include "content/renderer/input/input_handler_wrapper.h"
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
-#include "ui/events/blink/did_overscroll_params.h"
-#include "ui/events/blink/input_handler_proxy.h"
-#include "ui/events/blink/web_input_event_traits.h"
-
-using blink::WebInputEvent;
-using ui::InputHandlerProxy;
-using blink::scheduler::WebMainThreadScheduler;
-
-namespace content {
-
-InputEventAckState InputEventDispositionToAck(
- InputHandlerProxy::EventDisposition disposition) {
- switch (disposition) {
- case InputHandlerProxy::DID_HANDLE:
- return INPUT_EVENT_ACK_STATE_CONSUMED;
- case InputHandlerProxy::DID_NOT_HANDLE:
- return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
- case InputHandlerProxy::DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING:
- return INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING;
- case InputHandlerProxy::DROP_EVENT:
- return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
- case InputHandlerProxy::DID_HANDLE_NON_BLOCKING:
- return INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING;
- case InputHandlerProxy::DID_HANDLE_SHOULD_BUBBLE:
- return INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE;
- }
- NOTREACHED();
- return INPUT_EVENT_ACK_STATE_UNKNOWN;
-}
-
-InputHandlerManager::InputHandlerManager(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- InputHandlerManagerClient* client,
- SynchronousInputHandlerProxyClient* sync_handler_client,
- blink::scheduler::WebMainThreadScheduler* main_thread_scheduler)
- : task_runner_(task_runner),
- client_(client),
- synchronous_handler_proxy_client_(sync_handler_client),
- main_thread_scheduler_(main_thread_scheduler),
- weak_ptr_factory_(this) {
- DCHECK(client_);
- client_->SetInputHandlerManager(this);
-}
-
-InputHandlerManager::~InputHandlerManager() {
- client_->SetInputHandlerManager(nullptr);
-}
-
-void InputHandlerManager::AddInputHandler(
- int routing_id,
- const base::WeakPtr<cc::InputHandler>& input_handler,
- const scoped_refptr<MainThreadEventQueue>& input_event_queue,
- const base::WeakPtr<RenderWidget>& render_widget,
- bool enable_smooth_scrolling) {
- if (task_runner_->BelongsToCurrentThread()) {
- AddInputHandlerOnCompositorThread(
- routing_id, base::ThreadTaskRunnerHandle::Get(), input_handler,
- input_event_queue, render_widget, enable_smooth_scrolling);
- } else {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&InputHandlerManager::AddInputHandlerOnCompositorThread,
- base::Unretained(this), routing_id,
- base::ThreadTaskRunnerHandle::Get(), input_handler,
- input_event_queue, render_widget,
- enable_smooth_scrolling));
- }
-}
-
-void InputHandlerManager::AddInputHandlerOnCompositorThread(
- int routing_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
- const base::WeakPtr<cc::InputHandler>& input_handler,
- const scoped_refptr<MainThreadEventQueue>& input_event_queue,
- const base::WeakPtr<RenderWidget>& render_widget,
- bool enable_smooth_scrolling) {
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- // The handler could be gone by this point if the compositor has shut down.
- if (!input_handler)
- return;
-
- // The same handler may be registered for a route multiple times.
- if (input_handlers_.count(routing_id) != 0)
- return;
-
- TRACE_EVENT1("input",
- "InputHandlerManager::AddInputHandlerOnCompositorThread",
- "result", "AddingRoute");
- std::unique_ptr<InputHandlerWrapper> wrapper(
- new InputHandlerWrapper(this, routing_id, main_task_runner, input_handler,
- render_widget, enable_smooth_scrolling));
- client_->RegisterRoutingID(routing_id, input_event_queue);
- if (synchronous_handler_proxy_client_) {
- synchronous_handler_proxy_client_->DidAddSynchronousHandlerProxy(
- routing_id, wrapper->input_handler_proxy());
- }
- input_handlers_[routing_id] = std::move(wrapper);
-}
-
-void InputHandlerManager::RemoveInputHandler(int routing_id) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(input_handlers_.find(routing_id) != input_handlers_.end());
-
- TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler");
-
- client_->UnregisterRoutingID(routing_id);
- if (synchronous_handler_proxy_client_) {
- synchronous_handler_proxy_client_->DidRemoveSynchronousHandlerProxy(
- routing_id);
- }
- input_handlers_.erase(routing_id);
-}
-
-void InputHandlerManager::RegisterAssociatedRenderFrameRoutingID(
- int render_frame_routing_id,
- int render_view_routing_id) {
- if (task_runner_->BelongsToCurrentThread()) {
- RegisterAssociatedRenderFrameRoutingIDOnCompositorThread(
- render_frame_routing_id, render_view_routing_id);
- } else {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &InputHandlerManager::
- RegisterAssociatedRenderFrameRoutingIDOnCompositorThread,
- base::Unretained(this), render_frame_routing_id,
- render_view_routing_id));
- }
-}
-
-void InputHandlerManager::
- RegisterAssociatedRenderFrameRoutingIDOnCompositorThread(
- int render_frame_routing_id,
- int render_view_routing_id) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- client_->RegisterAssociatedRenderFrameRoutingID(render_frame_routing_id,
- render_view_routing_id);
-}
-
-void InputHandlerManager::UnregisterRoutingID(int routing_id) {
- if (task_runner_->BelongsToCurrentThread()) {
- UnregisterRoutingIDOnCompositorThread(routing_id);
- } else {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &InputHandlerManager::UnregisterRoutingIDOnCompositorThread,
- base::Unretained(this), routing_id));
- }
-}
-
-void InputHandlerManager::UnregisterRoutingIDOnCompositorThread(
- int routing_id) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- client_->UnregisterRoutingID(routing_id);
-}
-
-void InputHandlerManager::ObserveGestureEventAndResultOnMainThread(
- int routing_id,
- const blink::WebGestureEvent& gesture_event,
- const cc::InputHandlerScrollResult& scroll_result) {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &InputHandlerManager::ObserveGestureEventAndResultOnCompositorThread,
- base::Unretained(this), routing_id, gesture_event, scroll_result));
-}
-
-void InputHandlerManager::ObserveGestureEventAndResultOnCompositorThread(
- int routing_id,
- const blink::WebGestureEvent& gesture_event,
- const cc::InputHandlerScrollResult& scroll_result) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- auto it = input_handlers_.find(routing_id);
- if (it == input_handlers_.end())
- return;
-
- InputHandlerProxy* proxy = it->second->input_handler_proxy();
- DCHECK(proxy->scroll_elasticity_controller());
- proxy->scroll_elasticity_controller()->ObserveGestureEventAndResult(
- gesture_event, scroll_result);
-}
-
-void InputHandlerManager::HandleInputEvent(
- int routing_id,
- ui::WebScopedInputEvent input_event,
- const ui::LatencyInfo& latency_info,
- const InputEventAckStateCallback& callback) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- TRACE_EVENT1("input,benchmark,rail", "InputHandlerManager::HandleInputEvent",
- "type", WebInputEvent::GetName(input_event->GetType()));
-
- auto it = input_handlers_.find(routing_id);
- if (it == input_handlers_.end()) {
- TRACE_EVENT1("input,rail", "InputHandlerManager::HandleInputEvent",
- "result", "NoInputHandlerFound");
- // Oops, we no longer have an interested input handler..
- callback.Run(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, std::move(input_event),
- latency_info, nullptr);
- return;
- }
-
- TRACE_EVENT1("input,rail", "InputHandlerManager::HandleInputEvent",
- "result", "EventSentToInputHandlerProxy");
- InputHandlerProxy* proxy = it->second->input_handler_proxy();
- proxy->HandleInputEventWithLatencyInfo(
- std::move(input_event), latency_info,
- base::BindOnce(&InputHandlerManager::DidHandleInputEventAndOverscroll,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
-void InputHandlerManager::QueueClosureForMainThreadEventQueue(
- int routing_id,
- const base::Closure& closure) {
- client_->QueueClosureForMainThreadEventQueue(routing_id, closure);
-}
-
-void InputHandlerManager::DidHandleInputEventAndOverscroll(
- const InputEventAckStateCallback& callback,
- InputHandlerProxy::EventDisposition event_disposition,
- ui::WebScopedInputEvent input_event,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<ui::DidOverscrollParams> overscroll_params) {
- InputEventAckState input_event_ack_state =
- InputEventDispositionToAck(event_disposition);
- switch (input_event_ack_state) {
- case INPUT_EVENT_ACK_STATE_CONSUMED:
- main_thread_scheduler_->DidHandleInputEventOnCompositorThread(
- *input_event, WebMainThreadScheduler::InputEventState::
- EVENT_CONSUMED_BY_COMPOSITOR);
- break;
- case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
- case INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING:
- main_thread_scheduler_->DidHandleInputEventOnCompositorThread(
- *input_event, WebMainThreadScheduler::InputEventState::
- EVENT_FORWARDED_TO_MAIN_THREAD);
- break;
- default:
- break;
- }
- callback.Run(input_event_ack_state, std::move(input_event), latency_info,
- std::move(overscroll_params));
-}
-
-void InputHandlerManager::DidOverscroll(int routing_id,
- const ui::DidOverscrollParams& params) {
- client_->DidOverscroll(routing_id, params);
-}
-
-void InputHandlerManager::DidStopFlinging(int routing_id) {
- client_->DidStopFlinging(routing_id);
-}
-
-void InputHandlerManager::DidAnimateForInput() {
- main_thread_scheduler_->DidAnimateForInputOnCompositorThread();
-}
-
-void InputHandlerManager::DidStartScrollingViewport(int routing_id) {
- client_->DidStartScrollingViewport(routing_id);
-}
-
-void InputHandlerManager::DispatchNonBlockingEventToMainThread(
- int routing_id,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- client_->DispatchNonBlockingEventToMainThread(routing_id, std::move(event),
- latency_info);
-}
-
-void InputHandlerManager::SetWhiteListedTouchAction(
- int routing_id,
- cc::TouchAction touch_action,
- uint32_t unique_touch_event_id,
- InputHandlerProxy::EventDisposition event_disposition) {
- InputEventAckState input_event_ack_state =
- InputEventDispositionToAck(event_disposition);
- client_->SetWhiteListedTouchAction(
- routing_id, touch_action, unique_touch_event_id, input_event_ack_state);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/input/input_handler_manager.h b/chromium/content/renderer/input/input_handler_manager.h
deleted file mode 100644
index 0412791f3e7..00000000000
--- a/chromium/content/renderer/input/input_handler_manager.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2013 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_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_
-#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_
-
-#include <unordered_map>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "content/public/common/input_event_ack_state.h"
-#include "content/renderer/render_view_impl.h"
-#include "ui/events/blink/input_handler_proxy.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace cc {
-class InputHandler;
-struct InputHandlerScrollResult;
-}
-
-namespace blink {
-class WebMouseWheelEvent;
-}
-
-namespace blink {
-namespace scheduler {
-class WebMainThreadScheduler;
-}
-}
-
-namespace ui {
-struct DidOverscrollParams;
-}
-
-namespace content {
-
-class InputHandlerWrapper;
-class InputHandlerManagerClient;
-class MainThreadEventQueue;
-class SynchronousInputHandlerProxyClient;
-
-InputEventAckState InputEventDispositionToAck(
- ui::InputHandlerProxy::EventDisposition disposition);
-
-// InputHandlerManager class manages InputHandlerProxy instances for
-// the WebViews in this renderer.
-class CONTENT_EXPORT InputHandlerManager {
- public:
- // |task_runner| is the SingleThreadTaskRunner of the compositor thread. The
- // underlying MessageLoop and supplied |client| and the |renderer_scheduler|
- // must outlive this object. The RendererScheduler needs to know when input
- // events and fling animations occur, which is why it's passed in here.
- InputHandlerManager(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- InputHandlerManagerClient* client,
- SynchronousInputHandlerProxyClient* sync_handler_client,
- blink::scheduler::WebMainThreadScheduler* main_thread_scheduler);
- virtual ~InputHandlerManager();
-
- // Callable from the main thread only.
- void AddInputHandler(
- int routing_id,
- const base::WeakPtr<cc::InputHandler>& input_handler,
- const scoped_refptr<MainThreadEventQueue>& input_event_queue,
- const base::WeakPtr<RenderWidget>& render_widget,
- bool enable_smooth_scrolling);
-
- void UnregisterRoutingID(int routing_id);
-
- void RegisterAssociatedRenderFrameRoutingID(int render_frame_routing_id,
- int render_view_routing_id);
- void RegisterAssociatedRenderFrameRoutingIDOnCompositorThread(
- int render_frame_routing_id,
- int render_view_routing_id);
-
- void ObserveGestureEventAndResultOnMainThread(
- int routing_id,
- const blink::WebGestureEvent& gesture_event,
- const cc::InputHandlerScrollResult& scroll_result);
-
- // Callback only from the compositor's thread.
- void RemoveInputHandler(int routing_id);
-
- using InputEventAckStateCallback =
- base::Callback<void(InputEventAckState,
- ui::WebScopedInputEvent,
- const ui::LatencyInfo&,
- std::unique_ptr<ui::DidOverscrollParams>)>;
- // Called from the compositor's thread.
- virtual void HandleInputEvent(int routing_id,
- ui::WebScopedInputEvent input_event,
- const ui::LatencyInfo& latency_info,
- const InputEventAckStateCallback& callback);
-
- virtual void QueueClosureForMainThreadEventQueue(
- int routing_id,
- const base::Closure& closure);
- // Called from the compositor's thread.
- void DidOverscroll(int routing_id, const ui::DidOverscrollParams& params);
-
- // Called from the compositor's thread.
- void DidStopFlinging(int routing_id);
-
- // Called from the compositor's thread.
- void DidAnimateForInput();
-
- // Called from the compositor's thread.
- void DidStartScrollingViewport(int routing_id);
-
- // Called from the compositor's thread.
- void DispatchNonBlockingEventToMainThread(
- int routing_id,
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info);
-
- // Called from the compositor's thread.
- void SetWhiteListedTouchAction(
- int routing_id,
- cc::TouchAction touch_action,
- uint32_t unique_touch_event_id,
- ui::InputHandlerProxy::EventDisposition event_disposition);
-
- private:
- // Called from the compositor's thread.
- void AddInputHandlerOnCompositorThread(
- int routing_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
- const base::WeakPtr<cc::InputHandler>& input_handler,
- const scoped_refptr<MainThreadEventQueue>& input_event_queue,
- const base::WeakPtr<RenderWidget>& render_widget,
- bool enable_smooth_scrolling);
-
- void UnregisterRoutingIDOnCompositorThread(int routing_id);
-
- void ObserveWheelEventAndResultOnCompositorThread(
- int routing_id,
- const blink::WebMouseWheelEvent& wheel_event,
- const cc::InputHandlerScrollResult& scroll_result);
-
- void ObserveGestureEventAndResultOnCompositorThread(
- int routing_id,
- const blink::WebGestureEvent& gesture_event,
- const cc::InputHandlerScrollResult& scroll_result);
-
- void DidHandleInputEventAndOverscroll(
- const InputEventAckStateCallback& callback,
- ui::InputHandlerProxy::EventDisposition event_disposition,
- ui::WebScopedInputEvent input_event,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<ui::DidOverscrollParams> overscroll_params);
-
- using InputHandlerMap =
- std::unordered_map<int, // routing_id
- std::unique_ptr<InputHandlerWrapper>>;
- InputHandlerMap input_handlers_;
-
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- InputHandlerManagerClient* const client_;
- // May be null.
- SynchronousInputHandlerProxyClient* const synchronous_handler_proxy_client_;
-
- // Not owned.
- blink::scheduler::WebMainThreadScheduler* const main_thread_scheduler_;
-
- base::WeakPtrFactory<InputHandlerManager> weak_ptr_factory_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_
diff --git a/chromium/content/renderer/input/input_handler_wrapper.cc b/chromium/content/renderer/input/input_handler_wrapper.cc
deleted file mode 100644
index 55dd6040b5e..00000000000
--- a/chromium/content/renderer/input/input_handler_wrapper.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2013 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/renderer/input/input_handler_wrapper.h"
-
-#include "base/command_line.h"
-#include "base/location.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/renderer/input/input_event_filter.h"
-#include "content/renderer/input/input_handler_manager.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "ui/events/blink/did_overscroll_params.h"
-
-namespace content {
-
-InputHandlerWrapper::InputHandlerWrapper(
- InputHandlerManager* input_handler_manager,
- int routing_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
- const base::WeakPtr<cc::InputHandler>& input_handler,
- const base::WeakPtr<RenderWidget>& render_widget,
- bool enable_smooth_scrolling)
- : input_handler_manager_(input_handler_manager),
- routing_id_(routing_id),
- input_handler_proxy_(
- input_handler.get(),
- this,
- base::FeatureList::IsEnabled(
- features::kTouchpadAndWheelScrollLatching),
- base::FeatureList::IsEnabled(features::kAsyncWheelEvents)),
- main_task_runner_(main_task_runner),
- render_widget_(render_widget) {
- DCHECK(input_handler);
- input_handler_proxy_.set_smooth_scroll_enabled(enable_smooth_scrolling);
-}
-
-InputHandlerWrapper::~InputHandlerWrapper() {
-}
-
-void InputHandlerWrapper::NeedsMainFrame() {
- main_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&RenderWidget::SetNeedsMainFrame, render_widget_));
-}
-
-void InputHandlerWrapper::DispatchNonBlockingEventToMainThread(
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info) {
- input_handler_manager_->DispatchNonBlockingEventToMainThread(
- routing_id_, std::move(event), latency_info);
-}
-
-void InputHandlerWrapper::WillShutdown() {
- input_handler_manager_->RemoveInputHandler(routing_id_);
-}
-
-std::unique_ptr<blink::WebGestureCurve>
-InputHandlerWrapper::CreateFlingAnimationCurve(
- blink::WebGestureDevice deviceSource,
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulative_scroll) {
- return blink::Platform::Current()->CreateFlingAnimationCurve(
- deviceSource, velocity, cumulative_scroll);
-}
-
-void InputHandlerWrapper::DidOverscroll(
- const gfx::Vector2dF& accumulated_overscroll,
- const gfx::Vector2dF& latest_overscroll_delta,
- const gfx::Vector2dF& current_fling_velocity,
- const gfx::PointF& causal_event_viewport_point,
- const cc::OverscrollBehavior& overscroll_behavior) {
- ui::DidOverscrollParams params;
- params.accumulated_overscroll = accumulated_overscroll;
- params.latest_overscroll_delta = latest_overscroll_delta;
- params.current_fling_velocity = current_fling_velocity;
- params.causal_event_viewport_point = causal_event_viewport_point;
- params.overscroll_behavior = overscroll_behavior;
- input_handler_manager_->DidOverscroll(routing_id_, params);
-}
-
-void InputHandlerWrapper::DidStopFlinging() {
- input_handler_manager_->DidStopFlinging(routing_id_);
-}
-
-void InputHandlerWrapper::DidAnimateForInput() {
- input_handler_manager_->DidAnimateForInput();
-}
-
-void InputHandlerWrapper::DidStartScrollingViewport() {
- input_handler_manager_->DidStartScrollingViewport(routing_id_);
-}
-
-void InputHandlerWrapper::GenerateScrollBeginAndSendToMainThread(
- const blink::WebGestureEvent& update_event) {
- DCHECK_EQ(update_event.GetType(), blink::WebInputEvent::kGestureScrollUpdate);
- blink::WebGestureEvent scroll_begin(update_event);
- scroll_begin.SetType(blink::WebInputEvent::kGestureScrollBegin);
- scroll_begin.data.scroll_begin.inertial_phase =
- update_event.data.scroll_update.inertial_phase;
- scroll_begin.data.scroll_begin.delta_x_hint =
- update_event.data.scroll_update.delta_x;
- scroll_begin.data.scroll_begin.delta_y_hint =
- update_event.data.scroll_update.delta_y;
- scroll_begin.data.scroll_begin.delta_hint_units =
- update_event.data.scroll_update.delta_units;
-
- DispatchNonBlockingEventToMainThread(
- ui::WebInputEventTraits::Clone(scroll_begin), ui::LatencyInfo());
-}
-
-void InputHandlerWrapper::SetWhiteListedTouchAction(
- cc::TouchAction touch_action,
- uint32_t unique_touch_event_id,
- ui::InputHandlerProxy::EventDisposition event_disposition) {
- input_handler_manager_->SetWhiteListedTouchAction(
- routing_id_, touch_action, unique_touch_event_id, event_disposition);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/input/input_handler_wrapper.h b/chromium/content/renderer/input/input_handler_wrapper.h
deleted file mode 100644
index 3f6484f1ca8..00000000000
--- a/chromium/content/renderer/input/input_handler_wrapper.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2013 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_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_
-#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "content/renderer/input/input_handler_manager.h"
-#include "ui/events/blink/input_handler_proxy.h"
-#include "ui/events/blink/input_handler_proxy_client.h"
-
-namespace ui {
-class InputHandlerProxy;
-class InputHandlerProxyClient;
-}
-
-namespace content {
-
-// This class lives on the compositor thread.
-class InputHandlerWrapper : public ui::InputHandlerProxyClient {
- public:
- InputHandlerWrapper(
- InputHandlerManager* input_handler_manager,
- int routing_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
- const base::WeakPtr<cc::InputHandler>& input_handler,
- const base::WeakPtr<RenderWidget>& render_widget,
- bool enable_smooth_scrolling);
- ~InputHandlerWrapper() override;
-
- int routing_id() const { return routing_id_; }
- ui::InputHandlerProxy* input_handler_proxy() {
- return &input_handler_proxy_;
- }
-
- void NeedsMainFrame();
-
- // InputHandlerProxyClient implementation.
- void WillShutdown() override;
- void DispatchNonBlockingEventToMainThread(
- ui::WebScopedInputEvent event,
- const ui::LatencyInfo& latency_info) override;
- std::unique_ptr<blink::WebGestureCurve> CreateFlingAnimationCurve(
- blink::WebGestureDevice deviceSource,
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll) override;
- void DidOverscroll(
- const gfx::Vector2dF& accumulated_overscroll,
- const gfx::Vector2dF& latest_overscroll_delta,
- const gfx::Vector2dF& current_fling_velocity,
- const gfx::PointF& causal_event_viewport_point,
- const cc::OverscrollBehavior& overscroll_behavior) override;
- void DidStopFlinging() override;
- void DidAnimateForInput() override;
- void DidStartScrollingViewport() override;
- void GenerateScrollBeginAndSendToMainThread(
- const blink::WebGestureEvent& update_event) override;
- void SetWhiteListedTouchAction(
- cc::TouchAction touch_action,
- uint32_t unique_touch_event_id,
- ui::InputHandlerProxy::EventDisposition event_disposition) override;
-
- private:
- InputHandlerManager* input_handler_manager_;
- int routing_id_;
- ui::InputHandlerProxy input_handler_proxy_;
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
-
- // Can only be accessed on the main thread.
- base::WeakPtr<RenderWidget> render_widget_;
-
- DISALLOW_COPY_AND_ASSIGN(InputHandlerWrapper);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_
diff --git a/chromium/content/renderer/input/main_thread_event_queue.cc b/chromium/content/renderer/input/main_thread_event_queue.cc
index 9fcfca7d741..7db4e91d2e5 100644
--- a/chromium/content/renderer/input/main_thread_event_queue.cc
+++ b/chromium/content/renderer/input/main_thread_event_queue.cc
@@ -5,9 +5,7 @@
#include "content/renderer/input/main_thread_event_queue.h"
#include "base/containers/circular_deque.h"
-#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_number_conversions.h"
#include "content/common/input/event_with_latency_info.h"
#include "content/common/input_messages.h"
#include "content/renderer/render_widget.h"
@@ -51,13 +49,15 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
QueuedWebInputEvent(ui::WebScopedInputEvent event,
const ui::LatencyInfo& latency,
bool originally_cancelable,
- HandledEventCallback callback)
+ HandledEventCallback callback,
+ bool known_by_scheduler)
: ScopedWebInputEventWithLatencyInfo(std::move(event), latency),
non_blocking_coalesced_count_(0),
creation_timestamp_(base::TimeTicks::Now()),
last_coalesced_timestamp_(creation_timestamp_),
originally_cancelable_(originally_cancelable),
- callback_(std::move(callback)) {}
+ callback_(std::move(callback)),
+ known_by_scheduler_count_(known_by_scheduler ? 1 : 0) {}
~QueuedWebInputEvent() override {}
@@ -85,6 +85,7 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
} else {
non_blocking_coalesced_count_++;
}
+ known_by_scheduler_count_ += other_event->known_by_scheduler_count_;
ScopedWebInputEventWithLatencyInfo::CoalesceWith(*other_event);
last_coalesced_timestamp_ = base::TimeTicks::Now();
@@ -125,11 +126,10 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
}
}
- size_t num_events_handled = 1 + blocking_coalesced_callbacks_.size();
if (queue->main_thread_scheduler_) {
// TODO(dtapuska): Change the scheduler API to take into account number of
// events processed.
- for (size_t i = 0; i < num_events_handled; ++i) {
+ for (size_t i = 0; i < known_by_scheduler_count_; ++i) {
queue->main_thread_scheduler_->DidHandleInputEventOnMainThread(
event(), ack_result == INPUT_EVENT_ACK_STATE_CONSUMED
? blink::WebInputEventResult::kHandledApplication
@@ -197,6 +197,8 @@ class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
bool originally_cancelable_;
HandledEventCallback callback_;
+
+ size_t known_by_scheduler_count_;
};
MainThreadEventQueue::SharedState::SharedState()
@@ -213,33 +215,17 @@ MainThreadEventQueue::MainThreadEventQueue(
last_touch_start_forced_nonblocking_due_to_fling_(false),
enable_fling_passive_listener_flag_(base::FeatureList::IsEnabled(
features::kPassiveEventListenersDueToFling)),
- enable_non_blocking_due_to_main_thread_responsiveness_flag_(
- base::FeatureList::IsEnabled(
- features::kMainThreadBusyScrollIntervention)),
needs_low_latency_(false),
allow_raf_aligned_input_(allow_raf_aligned_input),
main_task_runner_(main_task_runner),
main_thread_scheduler_(main_thread_scheduler),
use_raf_fallback_timer_(true) {
- if (enable_non_blocking_due_to_main_thread_responsiveness_flag_) {
- std::string group = base::FieldTrialList::FindFullName(
- "MainThreadResponsivenessScrollIntervention");
-
- // The group name will be of the form Enabled$THRESHOLD_MS. Trim the prefix
- // "Enabled", and parse the threshold.
- int threshold_ms = 0;
- std::string prefix = "Enabled";
- group.erase(0, prefix.length());
- base::StringToInt(group, &threshold_ms);
-
- if (threshold_ms <= 0) {
- enable_non_blocking_due_to_main_thread_responsiveness_flag_ = false;
- } else {
- main_thread_responsiveness_threshold_ =
- base::TimeDelta::FromMilliseconds(threshold_ms);
- }
- }
raf_fallback_timer_.SetTaskRunner(main_task_runner);
+
+ event_predictor_ =
+ base::FeatureList::IsEnabled(features::kResamplingInputEvents)
+ ? std::make_unique<InputEventPrediction>()
+ : nullptr;
}
MainThreadEventQueue::~MainThreadEventQueue() {}
@@ -292,17 +278,6 @@ void MainThreadEventQueue::HandleEvent(
}
}
- if (enable_non_blocking_due_to_main_thread_responsiveness_flag_ &&
- touch_event->dispatch_type == blink::WebInputEvent::kBlocking) {
- bool passive_due_to_unresponsive_main =
- main_thread_scheduler_->MainThreadSeemsUnresponsive(
- main_thread_responsiveness_threshold_);
- if (passive_due_to_unresponsive_main) {
- touch_event->dispatch_type = blink::WebInputEvent::
- kListenersForcedNonBlockingDueToMainThreadResponsiveness;
- non_blocking = true;
- }
- }
// If the event is non-cancelable ACK it right away.
if (!non_blocking &&
touch_event->dispatch_type != blink::WebInputEvent::kBlocking)
@@ -327,9 +302,9 @@ void MainThreadEventQueue::HandleEvent(
event_callback = std::move(callback);
}
- std::unique_ptr<QueuedWebInputEvent> queued_event(
- new QueuedWebInputEvent(std::move(event), latency, originally_cancelable,
- std::move(event_callback)));
+ std::unique_ptr<QueuedWebInputEvent> queued_event(new QueuedWebInputEvent(
+ std::move(event), latency, originally_cancelable,
+ std::move(event_callback), IsForwardedAndSchedulerKnown(ack_result)));
QueueEvent(std::move(queued_event));
@@ -392,6 +367,7 @@ void MainThreadEventQueue::DispatchEvents() {
task = shared_state_.events_.Pop();
}
+ HandleEventResampling(task, base::TimeTicks::Now());
// Dispatching the event is outside of critical section.
task->Dispatch(this);
}
@@ -450,6 +426,7 @@ void MainThreadEventQueue::DispatchRafAlignedInput(base::TimeTicks frame_time) {
}
task = shared_state_.events_.Pop();
}
+ HandleEventResampling(task, frame_time);
// Dispatching the event is outside of critical section.
task->Dispatch(this);
}
@@ -507,6 +484,16 @@ bool MainThreadEventQueue::IsRafAlignedEvent(
}
}
+void MainThreadEventQueue::HandleEventResampling(
+ const std::unique_ptr<MainThreadEventQueueTask>& item,
+ base::TimeTicks frame_time) {
+ if (item->IsWebInputEvent() && allow_raf_aligned_input_ && event_predictor_) {
+ QueuedWebInputEvent* event = static_cast<QueuedWebInputEvent*>(item.get());
+ event_predictor_->HandleEvents(event->coalesced_event(), frame_time,
+ &event->event());
+ }
+}
+
void MainThreadEventQueue::HandleEventOnMainThread(
const blink::WebCoalescedInputEvent& event,
const ui::LatencyInfo& latency,
diff --git a/chromium/content/renderer/input/main_thread_event_queue.h b/chromium/content/renderer/input/main_thread_event_queue.h
index ba7c4100ab7..cf767c67a3d 100644
--- a/chromium/content/renderer/input/main_thread_event_queue.h
+++ b/chromium/content/renderer/input/main_thread_event_queue.h
@@ -13,6 +13,7 @@
#include "content/common/input/input_event_dispatch_type.h"
#include "content/public/common/content_features.h"
#include "content/public/common/input_event_ack_state.h"
+#include "content/renderer/input/input_event_prediction.h"
#include "content/renderer/input/main_thread_event_queue_task_list.h"
#include "content/renderer/input/scoped_web_input_event_with_latency_info.h"
#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
@@ -103,6 +104,16 @@ class CONTENT_EXPORT MainThreadEventQueue
// Request unbuffered input events until next pointerup.
void RequestUnbufferedInputEvents();
+ // Resampling event before dispatch it.
+ void HandleEventResampling(
+ const std::unique_ptr<MainThreadEventQueueTask>& item,
+ base::TimeTicks frame_time);
+
+ static bool IsForwardedAndSchedulerKnown(InputEventAckState ack_state) {
+ return ack_state == INPUT_EVENT_ACK_STATE_NOT_CONSUMED ||
+ ack_state == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING;
+ }
+
protected:
friend class base::RefCountedThreadSafe<MainThreadEventQueue>;
virtual ~MainThreadEventQueue();
@@ -129,8 +140,6 @@ class CONTENT_EXPORT MainThreadEventQueue
MainThreadEventQueueClient* client_;
bool last_touch_start_forced_nonblocking_due_to_fling_;
bool enable_fling_passive_listener_flag_;
- bool enable_non_blocking_due_to_main_thread_responsiveness_flag_;
- base::TimeDelta main_thread_responsiveness_threshold_;
bool needs_low_latency_;
bool allow_raf_aligned_input_;
bool needs_low_latency_until_pointer_up_ = false;
@@ -157,6 +166,8 @@ class CONTENT_EXPORT MainThreadEventQueue
base::OneShotTimer raf_fallback_timer_;
bool use_raf_fallback_timer_;
+ std::unique_ptr<InputEventPrediction> event_predictor_;
+
DISALLOW_COPY_AND_ASSIGN(MainThreadEventQueue);
};
diff --git a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
index d20c99eee70..66d57509894 100644
--- a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
+++ b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -10,7 +10,6 @@
#include "base/auto_reset.h"
#include "base/macros.h"
-#include "base/metrics/field_trial.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
@@ -233,7 +232,6 @@ class MainThreadEventQueueTest : public testing::Test,
}
protected:
- base::test::ScopedFeatureList feature_list_;
scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_;
blink::scheduler::MockRendererScheduler renderer_scheduler_;
scoped_refptr<MainThreadEventQueue> queue_;
@@ -259,7 +257,7 @@ TEST_F(MainThreadEventQueueTest, NonBlockingWheel) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(2);
+ .Times(0);
for (WebMouseWheelEvent& event : kEvents)
HandleEvent(event, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
@@ -345,7 +343,7 @@ TEST_F(MainThreadEventQueueTest, NonBlockingWheel) {
TEST_F(MainThreadEventQueueTest, NonBlockingTouch) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(3);
+ .Times(0);
SyntheticWebTouchEvent kEvents[4];
kEvents[0].PressPoint(10, 10);
@@ -450,7 +448,7 @@ TEST_F(MainThreadEventQueueTest, BlockingTouch) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(5);
+ .Times(3);
{
// Ensure that coalescing takes place.
HandleEvent(kEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
@@ -504,7 +502,7 @@ TEST_F(MainThreadEventQueueTest, InterleavedEvents) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(2);
+ .Times(0);
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
@@ -575,7 +573,7 @@ TEST_F(MainThreadEventQueueTest, RafAlignedMouseInput) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(11);
+ .Times(0);
// Simulate enqueing a discrete event, followed by continuous events and
// then a discrete event. The last discrete event should flush the
@@ -647,7 +645,7 @@ TEST_F(MainThreadEventQueueTest, RafAlignedTouchInput) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(10);
+ .Times(3);
// Simulate enqueing a discrete event, followed by continuous events and
// then a discrete event. The last discrete event should flush the
@@ -784,7 +782,7 @@ TEST_F(MainThreadEventQueueTest, RafAlignedTouchInputCoalescedMoves) {
TEST_F(MainThreadEventQueueTest, RafAlignedTouchInputThrottlingMoves) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(2);
+ .Times(3);
SyntheticWebTouchEvent kEvents[2];
kEvents[0].PressPoint(10, 10);
@@ -839,7 +837,7 @@ TEST_F(MainThreadEventQueueTest, LowLatency) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(8);
+ .Times(0);
for (SyntheticWebTouchEvent& event : kEvents)
HandleEvent(event, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
@@ -1077,16 +1075,7 @@ class MainThreadEventQueueInitializationTest
: public testing::Test,
public MainThreadEventQueueClient {
public:
- MainThreadEventQueueInitializationTest()
- : field_trial_list_(new base::FieldTrialList(nullptr)) {}
-
- base::TimeDelta main_thread_responsiveness_threshold() {
- return queue_->main_thread_responsiveness_threshold_;
- }
-
- bool enable_non_blocking_due_to_main_thread_responsiveness_flag() {
- return queue_->enable_non_blocking_due_to_main_thread_responsiveness_flag_;
- }
+ MainThreadEventQueueInitializationTest() {}
void HandleInputEvent(const blink::WebCoalescedInputEvent& event,
const ui::LatencyInfo& latency,
@@ -1099,37 +1088,10 @@ class MainThreadEventQueueInitializationTest
protected:
scoped_refptr<MainThreadEventQueue> queue_;
- base::test::ScopedFeatureList feature_list_;
blink::scheduler::MockRendererScheduler renderer_scheduler_;
scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_;
- std::unique_ptr<base::FieldTrialList> field_trial_list_;
};
-TEST_F(MainThreadEventQueueInitializationTest,
- MainThreadResponsivenessThresholdEnabled) {
- feature_list_.InitFromCommandLine(
- features::kMainThreadBusyScrollIntervention.name, "");
-
- base::FieldTrialList::CreateFieldTrial(
- "MainThreadResponsivenessScrollIntervention", "Enabled123");
- queue_ = new MainThreadEventQueue(this, main_task_runner_,
- &renderer_scheduler_, true);
- EXPECT_TRUE(enable_non_blocking_due_to_main_thread_responsiveness_flag());
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(123),
- main_thread_responsiveness_threshold());
-}
-
-TEST_F(MainThreadEventQueueInitializationTest,
- MainThreadResponsivenessThresholdDisabled) {
- base::FieldTrialList::CreateFieldTrial(
- "MainThreadResponsivenessScrollIntervention", "Control");
- queue_ = new MainThreadEventQueue(this, main_task_runner_,
- &renderer_scheduler_, true);
- EXPECT_FALSE(enable_non_blocking_due_to_main_thread_responsiveness_flag());
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(0),
- main_thread_responsiveness_threshold());
-}
-
TEST_F(MainThreadEventQueueTest, QueuingTwoClosures) {
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
@@ -1365,7 +1327,7 @@ TEST_F(MainThreadEventQueueTest, UnbufferedDispatchMouseEvent) {
EXPECT_CALL(renderer_scheduler_,
DidHandleInputEventOnMainThread(testing::_, testing::_))
- .Times(3);
+ .Times(0);
HandleEvent(mouse_down, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
queue_->RequestUnbufferedInputEvents();
diff --git a/chromium/content/renderer/input/main_thread_input_event_filter.cc b/chromium/content/renderer/input/main_thread_input_event_filter.cc
deleted file mode 100644
index abab750aa6e..00000000000
--- a/chromium/content/renderer/input/main_thread_input_event_filter.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 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/renderer/input/main_thread_input_event_filter.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "content/common/input_messages.h"
-#include "ipc/ipc_listener.h"
-
-namespace content {
-
-MainThreadInputEventFilter::MainThreadInputEventFilter(
- const base::Callback<void(const IPC::Message&)>& main_listener,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
- : main_listener_(main_listener), main_task_runner_(main_task_runner) {
- DCHECK(main_task_runner.get());
-}
-
-bool MainThreadInputEventFilter::OnMessageReceived(
- const IPC::Message& message) {
- DCHECK_EQ(static_cast<int>(IPC_MESSAGE_ID_CLASS(message.type())),
- InputMsgStart);
- bool handled = main_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(main_listener_, message));
- return handled;
-}
-
-bool MainThreadInputEventFilter::GetSupportedMessageClasses(
- std::vector<uint32_t>* supported_message_classes) const {
- supported_message_classes->push_back(InputMsgStart);
- return true;
-}
-
-MainThreadInputEventFilter::~MainThreadInputEventFilter() {
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/input/main_thread_input_event_filter.h b/chromium/content/renderer/input/main_thread_input_event_filter.h
deleted file mode 100644
index 70e3598626d..00000000000
--- a/chromium/content/renderer/input/main_thread_input_event_filter.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 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_RENDERER_INPUT_MAIN_THREAD_INPUT_EVENT_FILTER_H_
-#define CONTENT_RENDERER_INPUT_MAIN_THREAD_INPUT_EVENT_FILTER_H_
-
-#include <stdint.h>
-
-#include "base/callback.h"
-#include "ipc/message_filter.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-
-// Used to intercept InputMsg* messages and deliver them to the given listener
-// via the provided main thread task runner. Note that usage should be
-// restricted to cases where compositor-thread event filtering (via
-// |InputEventFilter|) is disabled or otherwise unavailable.
-class MainThreadInputEventFilter : public IPC::MessageFilter {
- public:
- MainThreadInputEventFilter(
- const base::Callback<void(const IPC::Message&)>& main_listener,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner);
-
- // IPC::MessageFilter implementation.
- bool OnMessageReceived(const IPC::Message& message) override;
- bool GetSupportedMessageClasses(
- std::vector<uint32_t>* supported_message_classes) const override;
-
- private:
- ~MainThreadInputEventFilter() override;
-
- base::Callback<void(const IPC::Message&)> main_listener_;
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_MAIN_THREAD_INPUT_EVENT_FILTER_H_
diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc
index fb0305ccf5e..ca425a44022 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.cc
+++ b/chromium/content/renderer/input/render_widget_input_handler.cc
@@ -54,7 +54,6 @@ using blink::WebInputEventResult;
using blink::WebKeyboardEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
-using blink::WebOverscrollBehavior;
using blink::WebPointerEvent;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
@@ -64,21 +63,22 @@ namespace content {
namespace {
-int64_t GetEventLatencyMicros(double event_timestamp, base::TimeTicks now) {
- return (now - base::TimeDelta::FromSecondsD(event_timestamp))
- .ToInternalValue();
+int64_t GetEventLatencyMicros(base::TimeTicks event_timestamp,
+ base::TimeTicks now) {
+ return (now - event_timestamp).InMicroseconds();
}
void LogInputEventLatencyUma(const WebInputEvent& event, base::TimeTicks now) {
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.AggregatedLatency.Renderer2",
- GetEventLatencyMicros(event.TimeStampSeconds(), now), 1, 10000000, 100);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Event.AggregatedLatency.Renderer2",
+ GetEventLatencyMicros(event.TimeStamp(), now), 1,
+ 10000000, 100);
}
void LogPassiveEventListenersUma(WebInputEventResult result,
WebInputEvent::DispatchType dispatch_type,
- double event_timestamp,
+ base::TimeTicks event_timestamp,
const ui::LatencyInfo& latency_info) {
+ // This enum is backing a histogram. Do not remove or reorder members.
enum ListenerEnum {
PASSIVE_LISTENER_UMA_ENUM_PASSIVE,
PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE,
@@ -86,7 +86,7 @@ void LogPassiveEventListenersUma(WebInputEventResult result,
PASSIVE_LISTENER_UMA_ENUM_CANCELABLE,
PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED,
PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING,
- PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS,
+ PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS_DEPRECATED,
PASSIVE_LISTENER_UMA_ENUM_COUNT
};
@@ -95,11 +95,6 @@ void LogPassiveEventListenersUma(WebInputEventResult result,
case WebInputEvent::kListenersForcedNonBlockingDueToFling:
enum_value = PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING;
break;
- case WebInputEvent::
- kListenersForcedNonBlockingDueToMainThreadResponsiveness:
- enum_value =
- PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS;
- break;
case WebInputEvent::kListenersNonBlockingPassive:
enum_value = PASSIVE_LISTENER_UMA_ENUM_PASSIVE;
break;
@@ -134,14 +129,6 @@ void LogPassiveEventListenersUma(WebInputEventResult result,
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Event.PassiveListeners.ForcedNonBlockingLatencyDueToFling",
GetEventLatencyMicros(event_timestamp, now), 1, 10000000, 100);
- } else if (
- enum_value ==
- PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS) {
- base::TimeTicks now = base::TimeTicks::Now();
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.PassiveListeners."
- "ForcedNonBlockingLatencyDueToUnresponsiveMainThread",
- GetEventLatencyMicros(event_timestamp, now), 1, 10000000, 50);
}
}
}
@@ -158,12 +145,12 @@ void LogAllPassiveEventListenersUma(const WebInputEvent& input_event,
const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event);
LogPassiveEventListenersUma(result, touch.dispatch_type,
- input_event.TimeStampSeconds(), latency_info);
+ input_event.TimeStamp(), latency_info);
} else if (input_event.GetType() == WebInputEvent::kMouseWheel) {
LogPassiveEventListenersUma(
result,
static_cast<const WebMouseWheelEvent&>(input_event).dispatch_type,
- input_event.TimeStampSeconds(), latency_info);
+ input_event.TimeStamp(), latency_info);
}
}
@@ -249,7 +236,7 @@ WebInputEventResult RenderWidgetInputHandler::HandleTouchEvent(
WebPointerEvent pointer_event =
WebPointerEvent::CreatePointerCausesUaActionEvent(
blink::WebPointerProperties::PointerType::kUnknown,
- input_event.TimeStampSeconds());
+ input_event.TimeStamp());
return widget_->GetWebWidget()->HandleInputEvent(
blink::WebCoalescedInputEvent(pointer_event));
}
@@ -317,16 +304,8 @@ void RenderWidgetInputHandler::HandleInputEvent(
std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor;
ui::LatencyInfo swap_latency_info(latency_info);
- if (RenderThreadImpl::current()) {
- swap_latency_info.set_expected_queueing_time_on_dispatch(
- RenderThreadImpl::current()
- ->GetWebMainThreadScheduler()
- ->MostRecentExpectedQueueingTime());
- }
-
swap_latency_info.AddLatencyNumber(
- ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0,
- 0);
+ ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0);
if (widget_->compositor()) {
latency_info_swap_promise_monitor =
widget_->compositor()->CreateLatencyInfoSwapPromiseMonitor(
@@ -465,7 +444,7 @@ void RenderWidgetInputHandler::DidOverscrollFromBlink(
const WebFloatSize& accumulatedOverscroll,
const WebFloatPoint& position,
const WebFloatSize& velocity,
- const WebOverscrollBehavior& behavior) {
+ const cc::OverscrollBehavior& behavior) {
std::unique_ptr<DidOverscrollParams> params(new DidOverscrollParams());
params->accumulated_overscroll = gfx::Vector2dF(
accumulatedOverscroll.width, accumulatedOverscroll.height);
diff --git a/chromium/content/renderer/input/render_widget_input_handler.h b/chromium/content/renderer/input/render_widget_input_handler.h
index ade4fffbffe..4ebdb4f9c91 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.h
+++ b/chromium/content/renderer/input/render_widget_input_handler.h
@@ -19,7 +19,10 @@
namespace blink {
struct WebFloatPoint;
struct WebFloatSize;
-struct WebOverscrollBehavior;
+} // namespace blink
+
+namespace cc {
+struct OverscrollBehavior;
}
namespace ui {
@@ -58,7 +61,7 @@ class CONTENT_EXPORT RenderWidgetInputHandler {
const blink::WebFloatSize& accumulatedOverscroll,
const blink::WebFloatPoint& position,
const blink::WebFloatSize& velocity,
- const blink::WebOverscrollBehavior& behavior);
+ const cc::OverscrollBehavior& behavior);
bool handling_input_event() const { return handling_input_event_; }
void set_handling_input_event(bool handling_input_event) {
diff --git a/chromium/content/renderer/input/scoped_web_input_event_with_latency_info.cc b/chromium/content/renderer/input/scoped_web_input_event_with_latency_info.cc
index ad5467bb38f..b829c1a94e4 100644
--- a/chromium/content/renderer/input/scoped_web_input_event_with_latency_info.cc
+++ b/chromium/content/renderer/input/scoped_web_input_event_with_latency_info.cc
@@ -29,9 +29,9 @@ void ScopedWebInputEventWithLatencyInfo::CoalesceWith(
// New events get coalesced into older events, and the newer timestamp
// should always be preserved.
- const double time_stamp_seconds = other.event().TimeStampSeconds();
+ const base::TimeTicks time_stamp = other.event().TimeStamp();
ui::Coalesce(other.event(), event_->EventPointer());
- event_->EventPointer()->SetTimeStampSeconds(time_stamp_seconds);
+ event_->EventPointer()->SetTimeStamp(time_stamp);
event_->AddCoalescedEvent(other.event());
// When coalescing two input events, we keep the oldest LatencyInfo
diff --git a/chromium/content/renderer/input/widget_input_handler_impl.h b/chromium/content/renderer/input/widget_input_handler_impl.h
index 8184618731a..51ffba24ae7 100644
--- a/chromium/content/renderer/input/widget_input_handler_impl.h
+++ b/chromium/content/renderer/input/widget_input_handler_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_INPUT_WIDGET_INPUT_HANDLER_IMPL_H_
#define CONTENT_RENDERER_INPUT_WIDGET_INPUT_HANDLER_IMPL_H_
+#include "base/single_thread_task_runner.h"
#include "content/common/input/input_handler.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding.h"
diff --git a/chromium/content/renderer/input/widget_input_handler_manager.cc b/chromium/content/renderer/input/widget_input_handler_manager.cc
index 7d07ba3de40..fa74edacbc2 100644
--- a/chromium/content/renderer/input/widget_input_handler_manager.cc
+++ b/chromium/content/renderer/input/widget_input_handler_manager.cc
@@ -11,7 +11,6 @@
#include "content/common/input_messages.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/ime_event_guard.h"
-#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/input/widget_input_handler_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_widget.h"
@@ -43,6 +42,26 @@ void CallCallback(mojom::WidgetInputHandler::DispatchEventCallback callback,
touch_action);
}
+InputEventAckState InputEventDispositionToAck(
+ ui::InputHandlerProxy::EventDisposition disposition) {
+ switch (disposition) {
+ case ui::InputHandlerProxy::DID_HANDLE:
+ return INPUT_EVENT_ACK_STATE_CONSUMED;
+ case ui::InputHandlerProxy::DID_NOT_HANDLE:
+ return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+ case ui::InputHandlerProxy::DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING:
+ return INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING;
+ case ui::InputHandlerProxy::DROP_EVENT:
+ return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ case ui::InputHandlerProxy::DID_HANDLE_NON_BLOCKING:
+ return INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING;
+ case ui::InputHandlerProxy::DID_HANDLE_SHOULD_BUBBLE:
+ return INPUT_EVENT_ACK_STATE_CONSUMED_SHOULD_BUBBLE;
+ }
+ NOTREACHED();
+ return INPUT_EVENT_ACK_STATE_UNKNOWN;
+}
+
} // namespace
#if defined(OS_ANDROID)
@@ -341,8 +360,7 @@ void WidgetInputHandlerManager::DispatchEvent(
// platform timestamp in this process. Instead use the time that the event is
// received as the event's timestamp.
if (!base::TimeTicks::IsConsistentAcrossProcesses()) {
- event->web_event->SetTimeStampSeconds(
- ui::EventTimeStampToSeconds(base::TimeTicks::Now()));
+ event->web_event->SetTimeStamp(base::TimeTicks::Now());
}
if (compositor_task_runner_) {
@@ -437,25 +455,21 @@ void WidgetInputHandlerManager::DidHandleInputEventAndOverscroll(
const ui::LatencyInfo& latency_info,
std::unique_ptr<ui::DidOverscrollParams> overscroll_params) {
InputEventAckState ack_state = InputEventDispositionToAck(event_disposition);
- switch (ack_state) {
- case INPUT_EVENT_ACK_STATE_CONSUMED:
- main_thread_scheduler_->DidHandleInputEventOnCompositorThread(
- *input_event, blink::scheduler::WebMainThreadScheduler::
- InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- break;
- case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
- case INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING:
- main_thread_scheduler_->DidHandleInputEventOnCompositorThread(
- *input_event, blink::scheduler::WebMainThreadScheduler::
- InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- break;
- default:
- break;
+ if (ack_state == INPUT_EVENT_ACK_STATE_CONSUMED) {
+ main_thread_scheduler_->DidHandleInputEventOnCompositorThread(
+ *input_event, blink::scheduler::WebMainThreadScheduler::
+ InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
+ } else if (MainThreadEventQueue::IsForwardedAndSchedulerKnown(ack_state)) {
+ main_thread_scheduler_->DidHandleInputEventOnCompositorThread(
+ *input_event, blink::scheduler::WebMainThreadScheduler::
+ InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
}
+
if (ack_state == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING ||
ack_state == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING ||
ack_state == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) {
DCHECK(!overscroll_params);
+ DCHECK(!latency_info.coalesced());
InputEventDispatchType dispatch_type = callback.is_null()
? DISPATCH_TYPE_NON_BLOCKING
: DISPATCH_TYPE_BLOCKING;
diff --git a/chromium/content/renderer/input/widget_input_handler_manager.h b/chromium/content/renderer/input/widget_input_handler_manager.h
index 2102159c579..abda6108d65 100644
--- a/chromium/content/renderer/input/widget_input_handler_manager.h
+++ b/chromium/content/renderer/input/widget_input_handler_manager.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_INPUT_WIDGET_INPUT_HANDLER_MANAGER_H_
#define CONTENT_RENDERER_INPUT_WIDGET_INPUT_HANDLER_MANAGER_H_
+#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/common/input/input_handler.mojom.h"
diff --git a/chromium/content/renderer/installedapp/related_apps_fetcher.cc b/chromium/content/renderer/installedapp/related_apps_fetcher.cc
index a7d3091f831..11d50f8b629 100644
--- a/chromium/content/renderer/installedapp/related_apps_fetcher.cc
+++ b/chromium/content/renderer/installedapp/related_apps_fetcher.cc
@@ -5,10 +5,10 @@
#include "content/renderer/installedapp/related_apps_fetcher.h"
#include "base/bind.h"
-#include "content/public/common/manifest.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
+#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
#include "third_party/blink/public/platform/modules/installedapp/web_related_application.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest.mojom.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h"
#include "third_party/blink/public/platform/web_string.h"
namespace content {
@@ -33,7 +33,7 @@ void RelatedAppsFetcher::OnGetManifestForRelatedApplications(
const blink::WebVector<blink::WebRelatedApplication>&,
void>> callbacks,
const GURL& /*url*/,
- const Manifest& manifest) {
+ const blink::Manifest& manifest) {
std::vector<blink::WebRelatedApplication> related_apps;
for (const auto& relatedApplication : manifest.related_applications) {
blink::WebRelatedApplication webRelatedApplication;
diff --git a/chromium/content/renderer/installedapp/related_apps_fetcher.h b/chromium/content/renderer/installedapp/related_apps_fetcher.h
index 73fbfc15f95..0f50aaad411 100644
--- a/chromium/content/renderer/installedapp/related_apps_fetcher.h
+++ b/chromium/content/renderer/installedapp/related_apps_fetcher.h
@@ -12,6 +12,7 @@
#include "third_party/blink/public/platform/modules/installedapp/web_related_apps_fetcher.h"
namespace blink {
+struct Manifest;
namespace mojom {
class ManifestManager;
}
@@ -19,7 +20,6 @@ class ManifestManager;
namespace content {
-struct Manifest;
class ManifestManager;
class CONTENT_EXPORT RelatedAppsFetcher : public blink::WebRelatedAppsFetcher {
@@ -41,7 +41,7 @@ class CONTENT_EXPORT RelatedAppsFetcher : public blink::WebRelatedAppsFetcher {
const blink::WebVector<blink::WebRelatedApplication>&,
void>> callbacks,
const GURL& url,
- const Manifest& manifest);
+ const blink::Manifest& manifest);
blink::mojom::ManifestManager* const manifest_manager_;
diff --git a/chromium/content/renderer/layout_test_dependencies.h b/chromium/content/renderer/layout_test_dependencies.h
index 167d9be12e5..4e556d872be 100644
--- a/chromium/content/renderer/layout_test_dependencies.h
+++ b/chromium/content/renderer/layout_test_dependencies.h
@@ -37,6 +37,10 @@ class CONTENT_EXPORT LayoutTestDependencies {
public:
virtual ~LayoutTestDependencies();
+ // Returns true if the layout tests should use the display compositor pixel
+ // dumps.
+ virtual bool UseDisplayCompositorPixelDump() const = 0;
+
virtual std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink(
int32_t routing_id,
scoped_refptr<gpu::GpuChannelHost> gpu_channel,
diff --git a/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc b/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
index feb92de61a6..32ddb9deabd 100644
--- a/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
+++ b/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc
@@ -24,7 +24,13 @@ class URLLoaderRelay : public network::mojom::URLLoaderClient,
client_sink_(std::move(client_sink)) {}
// network::mojom::URLLoader implementation:
- void FollowRedirect() override { loader_sink_->FollowRedirect(); }
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override {
+ DCHECK(!modified_request_headers.has_value())
+ << "Redirect with modified headers was not supported yet. "
+ "crbug.com/845683";
+ loader_sink_->FollowRedirect(base::nullopt);
+ }
void ProceedWithResponse() override { loader_sink_->ProceedWithResponse(); }
@@ -186,32 +192,12 @@ void ChildURLLoaderFactoryBundle::CreateLoaderAndStart(
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
ChildURLLoaderFactoryBundle::Clone() {
- InitDefaultBlobFactoryIfNecessary();
- InitDirectNetworkFactoryIfNecessary();
-
- network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
- if (default_factory_)
- default_factory_->Clone(mojo::MakeRequest(&default_factory_info));
-
- std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo> factories_info;
- for (auto& factory : factories_) {
- network::mojom::URLLoaderFactoryPtrInfo factory_info;
- factory.second->Clone(mojo::MakeRequest(&factory_info));
- factories_info.emplace(factory.first, std::move(factory_info));
- }
-
- network::mojom::URLLoaderFactoryPtrInfo direct_network_factory_info;
- if (direct_network_factory_) {
- direct_network_factory_->Clone(
- mojo::MakeRequest(&direct_network_factory_info));
- }
-
- // Currently there is no need to override subresources from workers,
- // therefore |subresource_overrides| are not shared with the clones.
+ return CloneInternal(true /* include_default */);
+}
- return std::make_unique<ChildURLLoaderFactoryBundleInfo>(
- std::move(default_factory_info), std::move(factories_info),
- std::move(direct_network_factory_info));
+std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ChildURLLoaderFactoryBundle::CloneWithoutDefaultFactory() {
+ return CloneInternal(false /* include_default */);
}
void ChildURLLoaderFactoryBundle::Update(
@@ -260,6 +246,36 @@ void ChildURLLoaderFactoryBundle::InitDirectNetworkFactoryIfNecessary() {
}
}
+std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ChildURLLoaderFactoryBundle::CloneInternal(bool include_default) {
+ InitDefaultBlobFactoryIfNecessary();
+ InitDirectNetworkFactoryIfNecessary();
+
+ network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
+ if (include_default && default_factory_)
+ default_factory_->Clone(mojo::MakeRequest(&default_factory_info));
+
+ std::map<std::string, network::mojom::URLLoaderFactoryPtrInfo> factories_info;
+ for (auto& factory : factories_) {
+ network::mojom::URLLoaderFactoryPtrInfo factory_info;
+ factory.second->Clone(mojo::MakeRequest(&factory_info));
+ factories_info.emplace(factory.first, std::move(factory_info));
+ }
+
+ network::mojom::URLLoaderFactoryPtrInfo direct_network_factory_info;
+ if (direct_network_factory_) {
+ direct_network_factory_->Clone(
+ mojo::MakeRequest(&direct_network_factory_info));
+ }
+
+ // Currently there is no need to override subresources from workers,
+ // therefore |subresource_overrides| are not shared with the clones.
+
+ return std::make_unique<ChildURLLoaderFactoryBundleInfo>(
+ std::move(default_factory_info), std::move(factories_info),
+ std::move(direct_network_factory_info));
+}
+
std::unique_ptr<ChildURLLoaderFactoryBundleInfo>
ChildURLLoaderFactoryBundle::PassInterface() {
InitDefaultBlobFactoryIfNecessary();
diff --git a/chromium/content/renderer/loader/child_url_loader_factory_bundle.h b/chromium/content/renderer/loader/child_url_loader_factory_bundle.h
index 922cca480bb..cb613cbc247 100644
--- a/chromium/content/renderer/loader/child_url_loader_factory_bundle.h
+++ b/chromium/content/renderer/loader/child_url_loader_factory_bundle.h
@@ -83,6 +83,11 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundle
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
+ // Returns an info that omits this bundle's default factory, if any. This is
+ // useful to make a clone that bypasses AppCache, for example.
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ CloneWithoutDefaultFactory();
+
std::unique_ptr<ChildURLLoaderFactoryBundleInfo> PassInterface();
void Update(std::unique_ptr<ChildURLLoaderFactoryBundleInfo> info,
@@ -97,6 +102,8 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundle
private:
void InitDefaultBlobFactoryIfNecessary();
void InitDirectNetworkFactoryIfNecessary();
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> CloneInternal(
+ bool include_default);
PossiblyAssociatedFactoryGetterCallback direct_network_factory_getter_;
PossiblyAssociatedURLLoaderFactoryPtr direct_network_factory_;
diff --git a/chromium/content/renderer/loader/navigation_response_override_parameters.cc b/chromium/content/renderer/loader/navigation_response_override_parameters.cc
new file mode 100644
index 00000000000..91be543f46c
--- /dev/null
+++ b/chromium/content/renderer/loader/navigation_response_override_parameters.cc
@@ -0,0 +1,17 @@
+// 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/renderer/loader/navigation_response_override_parameters.h"
+
+#include "base/callback.h"
+
+namespace content {
+
+NavigationResponseOverrideParameters::NavigationResponseOverrideParameters() =
+ default;
+
+NavigationResponseOverrideParameters::~NavigationResponseOverrideParameters() =
+ default;
+
+} // namespace content
diff --git a/chromium/content/renderer/loader/navigation_response_override_parameters.h b/chromium/content/renderer/loader/navigation_response_override_parameters.h
new file mode 100644
index 00000000000..e9a9b7b1d22
--- /dev/null
+++ b/chromium/content/renderer/loader/navigation_response_override_parameters.h
@@ -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.
+
+#ifndef CONTENT_RENDERER_LOADER_NAVIGATION_RESPONSE_OVERRIDE_PARAMETERS_H_
+#define CONTENT_RENDERER_LOADER_NAVIGATION_RESPONSE_OVERRIDE_PARAMETERS_H_
+
+#include <vector>
+
+#include "content/common/content_export.h"
+#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Used to override parameters of the navigation request.
+struct CONTENT_EXPORT NavigationResponseOverrideParameters {
+ public:
+ NavigationResponseOverrideParameters();
+ ~NavigationResponseOverrideParameters();
+
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
+ network::ResourceResponseHead response;
+ std::vector<GURL> redirects;
+ std::vector<network::ResourceResponseHead> redirect_responses;
+ std::vector<net::RedirectInfo> redirect_infos;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_LOADER_NAVIGATION_RESPONSE_OVERRIDE_PARAMETERS_H_
diff --git a/chromium/content/renderer/loader/request_extra_data.cc b/chromium/content/renderer/loader/request_extra_data.cc
index 3b523978f38..de594517dd3 100644
--- a/chromium/content/renderer/loader/request_extra_data.cc
+++ b/chromium/content/renderer/loader/request_extra_data.cc
@@ -17,7 +17,6 @@ RequestExtraData::RequestExtraData()
is_main_frame_(false),
allow_download_(true),
transition_type_(ui::PAGE_TRANSITION_LINK),
- should_replace_current_entry_(false),
service_worker_provider_id_(kInvalidServiceWorkerProviderId),
originated_from_service_worker_(false),
initiated_in_secure_context_(false),
@@ -39,7 +38,6 @@ void RequestExtraData::CopyToResourceRequest(
request->allow_download = allow_download_;
request->transition_type = transition_type_;
- request->should_replace_current_entry = should_replace_current_entry_;
request->service_worker_provider_id = service_worker_provider_id_;
request->originated_from_service_worker = originated_from_service_worker_;
diff --git a/chromium/content/renderer/loader/request_extra_data.h b/chromium/content/renderer/loader/request_extra_data.h
index 8d458507d5e..1c2f0bacdce 100644
--- a/chromium/content/renderer/loader/request_extra_data.h
+++ b/chromium/content/renderer/loader/request_extra_data.h
@@ -12,6 +12,7 @@
#include "content/common/content_export.h"
#include "content/common/navigation_params.h"
#include "content/public/common/url_loader_throttle.h"
+#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/web_url_loader_impl.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -49,10 +50,6 @@ class CONTENT_EXPORT RequestExtraData : public blink::WebURLRequest::ExtraData {
void set_transition_type(ui::PageTransition transition_type) {
transition_type_ = transition_type;
}
- void set_should_replace_current_entry(
- bool should_replace_current_entry) {
- should_replace_current_entry_ = should_replace_current_entry;
- }
int service_worker_provider_id() const {
return service_worker_provider_id_;
}
@@ -82,20 +79,20 @@ class CONTENT_EXPORT RequestExtraData : public blink::WebURLRequest::ExtraData {
requested_with_ = requested_with;
}
- // PlzNavigate: |stream_override| is used to override certain parameters of
- // navigation requests.
- std::unique_ptr<StreamOverrideParameters> TakeStreamOverrideOwnership() {
- return std::move(stream_override_);
+ // PlzNavigate: |navigation_response_override| is used to override certain
+ // parameters of navigation requests.
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ TakeNavigationResponseOverrideOwnership() {
+ return std::move(navigation_response_override_);
}
- void set_stream_override(
- std::unique_ptr<StreamOverrideParameters> stream_override) {
- stream_override_ = std::move(stream_override);
+ void set_navigation_response_override(
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override) {
+ navigation_response_override_ = std::move(response_override);
}
- // NavigationMojoResponse: |continue_navigation| is used to continue a
- // navigation on the renderer process that has already been started on the
- // browser process.
+ // |continue_navigation| is used to continue a navigation on the renderer
+ // process that has already been started on the browser process.
base::OnceClosure TakeContinueNavigationFunctionOwnerShip() {
return std::move(continue_navigation_function_);
}
@@ -163,14 +160,14 @@ class CONTENT_EXPORT RequestExtraData : public blink::WebURLRequest::ExtraData {
bool is_main_frame_;
bool allow_download_;
ui::PageTransition transition_type_;
- bool should_replace_current_entry_;
int service_worker_provider_id_;
bool originated_from_service_worker_;
blink::WebString custom_user_agent_;
blink::WebString requested_with_;
- std::unique_ptr<StreamOverrideParameters> stream_override_;
- // TODO(arthursonzogni): Once NavigationMojoResponse is launched, move most of
- // the |stream_override_| content as parameters of this function.
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ navigation_response_override_;
+ // TODO(arthursonzogni): Move most of the |navigation_response_override_|
+ // content as parameters of this function.
base::OnceClosure continue_navigation_function_;
bool initiated_in_secure_context_;
bool is_for_no_state_prefetch_;
diff --git a/chromium/content/renderer/loader/resource_dispatcher.cc b/chromium/content/renderer/loader/resource_dispatcher.cc
index 8764f8e026f..f3f906a3c5a 100644
--- a/chromium/content/renderer/loader/resource_dispatcher.cc
+++ b/chromium/content/renderer/loader/resource_dispatcher.cc
@@ -14,7 +14,6 @@
#include "base/debug/alias.h"
#include "base/debug/stack_trace.h"
#include "base/files/file_path.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
@@ -24,6 +23,7 @@
#include "content/common/inter_process_time_ticks_converter.h"
#include "content/common/navigation_params.h"
#include "content/common/throttling_url_loader.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/resource_load_info.mojom.h"
#include "content/public/common/resource_type.h"
#include "content/public/renderer/fixed_received_data.h"
@@ -119,6 +119,20 @@ void NotifyResourceLoadComplete(
std::move(resource_load_info));
}
+// Returns true if the headers indicate that this resource should always be
+// revalidated or not cached.
+bool AlwaysAccessNetwork(
+ const scoped_refptr<net::HttpResponseHeaders>& headers) {
+ if (!headers)
+ return false;
+
+ // RFC 2616, section 14.9.
+ return headers->HasHeaderValue("cache-control", "no-cache") ||
+ headers->HasHeaderValue("cache-control", "no-store") ||
+ headers->HasHeaderValue("pragma", "no-cache") ||
+ headers->HasHeaderValue("vary", "*");
+}
+
int GetInitialRequestID() {
// Starting with a random number speculatively avoids RDH_INVALID_REQUEST_ID
// which are assumed to have been caused by restarting RequestID at 0 when
@@ -172,13 +186,35 @@ void ResourceDispatcher::OnUploadProgress(int request_id,
void ResourceDispatcher::OnReceivedResponse(
int request_id,
- const network::ResourceResponseHead& response_head) {
+ const network::ResourceResponseHead& initial_response_head) {
TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedResponse");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
- request_info->response_start = base::TimeTicks::Now();
+ request_info->local_response_start = base::TimeTicks::Now();
+ request_info->remote_request_start =
+ initial_response_head.load_timing.request_start;
+ // Now that response_start has been set, we can properly set the TimeTicks in
+ // the ResourceResponseInfo.
+ network::ResourceResponseInfo renderer_response_info;
+ ToResourceResponseInfo(*request_info, initial_response_head,
+ &renderer_response_info);
+ request_info->load_timing_info = renderer_response_info.load_timing;
+
+ network::ResourceResponseHead response_head;
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override =
+ std::move(request_info->navigation_response_override);
+ if (response_override) {
+ CHECK(IsBrowserSideNavigationEnabled());
+ response_head = response_override->response;
+ } else {
+ response_head = initial_response_head;
+ }
+ request_info->mime_type = response_head.mime_type;
+ request_info->network_accessed = response_head.network_accessed;
+ request_info->always_access_network =
+ AlwaysAccessNetwork(response_head.headers);
if (delegate_) {
std::unique_ptr<RequestPeer> new_peer = delegate_->OnReceivedResponse(
std::move(request_info->peer), response_head.mime_type,
@@ -186,14 +222,7 @@ void ResourceDispatcher::OnReceivedResponse(
DCHECK(new_peer);
request_info->peer = std::move(new_peer);
}
-
- if (!response_head.socket_address.host().empty()) {
- ignore_result(request_info->parsed_ip.AssignFromIPLiteral(
- response_head.socket_address.host()));
- }
-
- request_info->mime_type = response_head.mime_type;
- request_info->network_accessed = response_head.network_accessed;
+ request_info->host_port_pair = renderer_response_info.socket_address;
if (!IsResourceTypeFrame(request_info->resource_type)) {
NotifySubresourceStarted(RenderThreadImpl::DeprecatedGetMainTaskRunner(),
request_info->render_frame_id,
@@ -201,8 +230,6 @@ void ResourceDispatcher::OnReceivedResponse(
response_head.cert_status);
}
- network::ResourceResponseInfo renderer_response_info;
- ToResourceResponseInfo(*request_info, response_head, &renderer_response_info);
request_info->peer->OnReceivedResponse(renderer_response_info);
}
@@ -248,7 +275,8 @@ void ResourceDispatcher::OnReceivedRedirect(
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
- request_info->response_start = base::TimeTicks::Now();
+ request_info->local_response_start = base::TimeTicks::Now();
+ request_info->remote_request_start = response_head.load_timing.request_start;
network::ResourceResponseInfo renderer_response_info;
ToResourceResponseInfo(*request_info, response_head, &renderer_response_info);
@@ -264,9 +292,19 @@ void ResourceDispatcher::OnReceivedRedirect(
request_info->response_method = redirect_info.new_method;
request_info->response_referrer = GURL(redirect_info.new_referrer);
request_info->has_pending_redirect = true;
- if (!request_info->is_deferred) {
+ mojom::RedirectInfoPtr net_redirect_info = mojom::RedirectInfo::New();
+ net_redirect_info->url = redirect_info.new_url;
+ net_redirect_info->network_info = mojom::CommonNetworkInfo::New();
+ net_redirect_info->network_info->network_accessed =
+ response_head.network_accessed;
+ net_redirect_info->network_info->always_access_network =
+ AlwaysAccessNetwork(response_head.headers);
+ net_redirect_info->network_info->ip_port_pair =
+ response_head.socket_address;
+ request_info->redirect_info_chain.push_back(std::move(net_redirect_info));
+
+ if (!request_info->is_deferred)
FollowPendingRedirect(request_info);
- }
} else {
Cancel(request_id, std::move(task_runner));
}
@@ -274,8 +312,11 @@ void ResourceDispatcher::OnReceivedRedirect(
void ResourceDispatcher::FollowPendingRedirect(
PendingRequestInfo* request_info) {
- if (request_info->has_pending_redirect) {
+ if (request_info->has_pending_redirect &&
+ request_info->should_follow_redirect) {
request_info->has_pending_redirect = false;
+ // net::URLRequest clears its request_start on redirect, so should we.
+ request_info->local_request_start = base::TimeTicks::Now();
request_info->url_loader->FollowRedirect();
}
}
@@ -288,7 +329,6 @@ void ResourceDispatcher::OnRequestComplete(
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
- request_info->completion_time = base::TimeTicks::Now();
request_info->buffer.reset();
request_info->buffer_size = 0;
@@ -299,13 +339,21 @@ void ResourceDispatcher::OnRequestComplete(
resource_load_info->method = request_info->response_method;
resource_load_info->resource_type = request_info->resource_type;
resource_load_info->request_id = request_id;
- if (request_info->parsed_ip.IsValid())
- resource_load_info->ip = request_info->parsed_ip;
resource_load_info->mime_type = request_info->mime_type;
- resource_load_info->network_accessed = request_info->network_accessed;
+ resource_load_info->network_info = mojom::CommonNetworkInfo::New();
+ resource_load_info->network_info->network_accessed =
+ request_info->network_accessed;
+ resource_load_info->network_info->always_access_network =
+ request_info->always_access_network;
+ resource_load_info->network_info->ip_port_pair = request_info->host_port_pair;
+ resource_load_info->load_timing_info = request_info->load_timing_info;
resource_load_info->was_cached = status.exists_in_cache;
resource_load_info->net_error = status.error_code;
- resource_load_info->request_start = request_info->request_start;
+ resource_load_info->redirect_info_chain =
+ std::move(request_info->redirect_info_chain);
+ resource_load_info->total_received_bytes = status.encoded_data_length;
+ resource_load_info->raw_body_bytes = status.encoded_body_length;
+
NotifyResourceLoadComplete(RenderThreadImpl::DeprecatedGetMainTaskRunner(),
request_info->render_frame_id,
std::move(resource_load_info));
@@ -320,15 +368,34 @@ void ResourceDispatcher::OnRequestComplete(
request_info->peer = std::move(new_peer);
}
+ network::URLLoaderCompletionStatus renderer_status(status);
+ if (status.completion_time.is_null()) {
+ // No completion timestamp is provided, leave it as is.
+ } else if (request_info->remote_request_start.is_null() ||
+ request_info->load_timing_info.request_start.is_null()) {
+ // We cannot convert the remote time to a local time, let's use the current
+ // timestamp. This happens when
+ // - We get an error before OnReceivedRedirect or OnReceivedResponse is
+ // called, or
+ // - Somehow such a timestamp was missing in the LoadTimingInfo.
+ renderer_status.completion_time = base::TimeTicks::Now();
+ } else {
+ // We have already converted the request start timestamp, let's use that
+ // conversion information.
+ // Note: We cannot create a InterProcessTimeTicksConverter with
+ // (local_request_start, now, remote_request_start, remote_completion_time)
+ // as that may result in inconsistent timestamps.
+ renderer_status.completion_time =
+ std::min(status.completion_time - request_info->remote_request_start +
+ request_info->load_timing_info.request_start,
+ base::TimeTicks::Now());
+ }
// The request ID will be removed from our pending list in the destructor.
// Normally, dispatching this message causes the reference-counted request to
// die immediately.
// TODO(kinuko): Revisit here. This probably needs to call request_info->peer
// but the past attempt to change it seems to have caused crashes.
// (crbug.com/547047)
- network::URLLoaderCompletionStatus renderer_status(status);
- renderer_status.completion_time =
- ToRendererCompletionTime(*request_info, status.completion_time);
peer->OnCompletedRequest(renderer_status);
}
@@ -427,7 +494,9 @@ ResourceDispatcher::PendingRequestInfo::PendingRequestInfo(
const GURL& request_url,
const std::string& method,
const GURL& referrer,
- bool download_to_file)
+ bool download_to_file,
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ navigation_response_override_params)
: peer(std::move(peer)),
resource_type(resource_type),
render_frame_id(render_frame_id),
@@ -436,7 +505,10 @@ ResourceDispatcher::PendingRequestInfo::PendingRequestInfo(
response_method(method),
response_referrer(referrer),
download_to_file(download_to_file),
- request_start(base::TimeTicks::Now()) {}
+ local_request_start(base::TimeTicks::Now()),
+ buffer_size(0),
+ navigation_response_override(
+ std::move(navigation_response_override_params)) {}
ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() {
}
@@ -449,12 +521,13 @@ void ResourceDispatcher::StartSync(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
double timeout,
- blink::mojom::BlobRegistryPtrInfo download_to_blob_registry) {
+ blink::mojom::BlobRegistryPtrInfo download_to_blob_registry,
+ std::unique_ptr<RequestPeer> peer) {
CheckSchemeForReferrerPolicy(*request);
std::unique_ptr<network::SharedURLLoaderFactoryInfo> factory_info =
url_loader_factory->Clone();
- base::WaitableEvent completed_event(
+ base::WaitableEvent redirect_or_response_event(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -474,10 +547,32 @@ void ResourceDispatcher::StartSync(
std::move(request), routing_id, task_runner,
traffic_annotation, std::move(factory_info),
std::move(throttles), base::Unretained(response),
- base::Unretained(&completed_event),
+ base::Unretained(&redirect_or_response_event),
base::Unretained(terminate_sync_load_event_), timeout,
std::move(download_to_blob_registry)));
- completed_event.Wait();
+
+ // redirect_or_response_event will signal when each redirect completes, and
+ // when the final response is complete.
+ redirect_or_response_event.Wait();
+
+ while (response->context_for_redirect) {
+ DCHECK(response->redirect_info);
+ bool follow_redirect =
+ peer->OnReceivedRedirect(*response->redirect_info, response->info);
+ redirect_or_response_event.Reset();
+ if (follow_redirect) {
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SyncLoadContext::FollowRedirect,
+ base::Unretained(response->context_for_redirect)));
+ } else {
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SyncLoadContext::CancelRedirect,
+ base::Unretained(response->context_for_redirect)));
+ }
+ redirect_or_response_event.Wait();
+ }
}
int ResourceDispatcher::StartAsync(
@@ -490,27 +585,32 @@ int ResourceDispatcher::StartAsync(
std::unique_ptr<RequestPeer> peer,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ response_override_params,
base::OnceClosure* continue_navigation_function) {
CheckSchemeForReferrerPolicy(*request);
+ bool override_url_loader =
+ !!response_override_params &&
+ !!response_override_params->url_loader_client_endpoints;
+
// Compute a unique request_id for this renderer process.
int request_id = MakeRequestID();
pending_requests_[request_id] = std::make_unique<PendingRequestInfo>(
std::move(peer), static_cast<ResourceType>(request->resource_type),
request->render_frame_id, request->url, request->method,
- request->referrer, request->download_to_file);
+ request->referrer, request->download_to_file,
+ std::move(response_override_params));
- if (url_loader_client_endpoints) {
+ if (override_url_loader) {
pending_requests_[request_id]->url_loader_client =
std::make_unique<URLLoaderClientImpl>(request_id, this,
loading_task_runner);
DCHECK(continue_navigation_function);
- *continue_navigation_function = base::BindOnce(
- &ResourceDispatcher::ContinueForNavigation, weak_factory_.GetWeakPtr(),
- request_id, std::move(url_loader_client_endpoints));
-
+ *continue_navigation_function =
+ base::BindOnce(&ResourceDispatcher::ContinueForNavigation,
+ weak_factory_.GetWeakPtr(), request_id);
return request_id;
}
@@ -550,16 +650,16 @@ void ResourceDispatcher::ToResourceResponseInfo(
network::ResourceResponseInfo* renderer_info) const {
*renderer_info = browser_info;
if (base::TimeTicks::IsConsistentAcrossProcesses() ||
- request_info.request_start.is_null() ||
- request_info.response_start.is_null() ||
+ request_info.local_request_start.is_null() ||
+ request_info.local_response_start.is_null() ||
browser_info.request_start.is_null() ||
browser_info.response_start.is_null() ||
browser_info.load_timing.request_start.is_null()) {
return;
}
InterProcessTimeTicksConverter converter(
- LocalTimeTicks::FromTimeTicks(request_info.request_start),
- LocalTimeTicks::FromTimeTicks(request_info.response_start),
+ LocalTimeTicks::FromTimeTicks(request_info.local_request_start),
+ LocalTimeTicks::FromTimeTicks(request_info.local_response_start),
RemoteTimeTicks::FromTimeTicks(browser_info.request_start),
RemoteTimeTicks::FromTimeTicks(browser_info.response_start));
@@ -582,46 +682,42 @@ void ResourceDispatcher::ToResourceResponseInfo(
RemoteToLocalTimeTicks(converter, &renderer_info->service_worker_ready_time);
}
-base::TimeTicks ResourceDispatcher::ToRendererCompletionTime(
- const PendingRequestInfo& request_info,
- const base::TimeTicks& browser_completion_time) const {
- if (request_info.completion_time.is_null()) {
- return browser_completion_time;
- }
-
- // TODO(simonjam): The optimal lower bound should be the most recent value of
- // TimeTicks::Now() returned to WebKit. Is it worth trying to cache that?
- // Until then, |response_start| is used as it is the most recent value
- // returned for this request.
- int64_t result = std::max(browser_completion_time.ToInternalValue(),
- request_info.response_start.ToInternalValue());
- result = std::min(result, request_info.completion_time.ToInternalValue());
- return base::TimeTicks::FromInternalValue(result);
-}
-
-void ResourceDispatcher::ContinueForNavigation(
- int request_id,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) {
- DCHECK(url_loader_client_endpoints);
+void ResourceDispatcher::ContinueForNavigation(int request_id) {
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
if (!request_info)
return;
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override =
+ std::move(request_info->navigation_response_override);
+ DCHECK(response_override);
+
+ // Mark the request so we do not attempt to follow the redirects, they already
+ // happened.
+ request_info->should_follow_redirect = false;
+
URLLoaderClientImpl* client_ptr = request_info->url_loader_client.get();
+ // PlzNavigate: during navigations, the ResourceResponse has already been
+ // received on the browser side, and has been passed down to the renderer.
+ // Replay the redirects that happened during navigation.
+ DCHECK_EQ(response_override->redirect_responses.size(),
+ response_override->redirect_infos.size());
+ for (size_t i = 0; i < response_override->redirect_responses.size(); ++i) {
+ client_ptr->OnReceiveRedirect(response_override->redirect_infos[i],
+ response_override->redirect_responses[i]);
+ // The request might have been cancelled while processing the redirect.
+ if (!GetPendingRequestInfo(request_id))
+ return;
+ }
- // Short circuiting call to OnReceivedResponse to immediately start
- // the request. ResourceResponseHead can be empty here because we
- // pull the StreamOverride's one in
- // WebURLLoaderImpl::Context::OnReceivedResponse.
- client_ptr->OnReceiveResponse(network::ResourceResponseHead(),
+ client_ptr->OnReceiveResponse(response_override->response,
network::mojom::DownloadedTempFilePtr());
- // TODO(clamy): Move the replaying of redirects from WebURLLoaderImpl here.
// Abort if the request is cancelled.
if (!GetPendingRequestInfo(request_id))
return;
- client_ptr->Bind(std::move(url_loader_client_endpoints));
+ DCHECK(response_override->url_loader_client_endpoints);
+ client_ptr->Bind(std::move(response_override->url_loader_client_endpoints));
}
} // namespace content
diff --git a/chromium/content/renderer/loader/resource_dispatcher.h b/chromium/content/renderer/loader/resource_dispatcher.h
index af1364a8799..609aaef3f2a 100644
--- a/chromium/content/renderer/loader/resource_dispatcher.h
+++ b/chromium/content/renderer/loader/resource_dispatcher.h
@@ -12,6 +12,7 @@
#include <map>
#include <memory>
#include <string>
+#include <vector>
#include "base/containers/circular_deque.h"
#include "base/containers/hash_tables.h"
@@ -22,9 +23,11 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "content/public/common/resource_load_info.mojom.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/url_loader_throttle.h"
#include "mojo/public/cpp/system/data_pipe.h"
+#include "net/base/host_port_pair.h"
#include "net/base/request_priority.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -52,6 +55,7 @@ class URLLoaderFactory;
}
namespace content {
+struct NavigationResponseOverrideParameters;
class RequestPeer;
class ResourceDispatcherDelegate;
struct SyncLoadResponse;
@@ -96,7 +100,8 @@ class CONTENT_EXPORT ResourceDispatcher {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
double timeout,
- blink::mojom::BlobRegistryPtrInfo download_to_blob_registry);
+ blink::mojom::BlobRegistryPtrInfo download_to_blob_registry,
+ std::unique_ptr<RequestPeer> peer);
// Call this method to initiate the request. If this method succeeds, then
// the peer's methods will be called asynchronously to report various events.
@@ -122,7 +127,8 @@ class CONTENT_EXPORT ResourceDispatcher {
std::unique_ptr<RequestPeer> peer,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ response_override_params,
base::OnceClosure* continue_navigation_function);
network::mojom::DownloadedTempFilePtr TakeDownloadedTempFile(int request_id);
@@ -179,7 +185,9 @@ class CONTENT_EXPORT ResourceDispatcher {
const GURL& request_url,
const std::string& method,
const GURL& referrer,
- bool download_to_file);
+ bool download_to_file,
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ response_override_params);
~PendingRequestInfo();
@@ -196,14 +204,21 @@ class CONTENT_EXPORT ResourceDispatcher {
GURL response_referrer;
bool download_to_file;
bool has_pending_redirect = false;
- base::TimeTicks request_start;
- base::TimeTicks response_start;
- base::TimeTicks completion_time;
+ base::TimeTicks local_request_start;
+ base::TimeTicks local_response_start;
+ base::TimeTicks remote_request_start;
+ net::LoadTimingInfo load_timing_info;
linked_ptr<base::SharedMemory> buffer;
int buffer_size;
- net::IPAddress parsed_ip;
+ net::HostPortPair host_port_pair;
bool network_accessed = false;
std::string mime_type;
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ navigation_response_override;
+ bool should_follow_redirect = true;
+ bool always_access_network = false;
+
+ std::vector<content::mojom::RedirectInfoPtr> redirect_info_chain;
// For mojo loading.
std::unique_ptr<ThrottlingURLLoader> url_loader;
@@ -239,13 +254,7 @@ class CONTENT_EXPORT ResourceDispatcher {
const network::ResourceResponseHead& browser_info,
network::ResourceResponseInfo* renderer_info) const;
- base::TimeTicks ToRendererCompletionTime(
- const PendingRequestInfo& request_info,
- const base::TimeTicks& browser_completion_time) const;
-
- void ContinueForNavigation(
- int request_id,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
+ void ContinueForNavigation(int request_id);
// All pending requests issued to the host
PendingRequestMap pending_requests_;
diff --git a/chromium/content/renderer/loader/resource_dispatcher_unittest.cc b/chromium/content/renderer/loader/resource_dispatcher_unittest.cc
index 32b18cfc520..9d89c8b0198 100644
--- a/chromium/content/renderer/loader/resource_dispatcher_unittest.cc
+++ b/chromium/content/renderer/loader/resource_dispatcher_unittest.cc
@@ -21,10 +21,10 @@
#include "base/test/scoped_feature_list.h"
#include "content/common/appcache_interfaces.h"
#include "content/public/common/content_features.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "content/public/renderer/fixed_received_data.h"
#include "content/public/renderer/request_peer.h"
#include "content/public/renderer/resource_dispatcher_delegate.h"
+#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/loader/test_request_peer.h"
#include "net/base/net_errors.h"
@@ -34,6 +34,7 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -117,9 +118,9 @@ class ResourceDispatcherTest : public testing::Test,
std::move(request), 0,
blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
TRAFFIC_ANNOTATION_FOR_TESTS, false, false, std::move(peer),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(this),
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this),
std::vector<std::unique_ptr<URLLoaderThrottle>>(),
- network::mojom::URLLoaderClientEndpointsPtr(),
+ nullptr /* navigation_response_override_params */,
nullptr /* continue_navigation_function */);
peer_context->request_id = request_id;
return request_id;
@@ -377,4 +378,85 @@ TEST_F(TimeConversionTest, NotInitialized) {
response_info().load_timing.connect_timing.dns_start);
}
+class CompletionTimeConversionTest : public ResourceDispatcherTest {
+ public:
+ void PerformTest(base::TimeTicks remote_request_start,
+ base::TimeTicks completion_time,
+ base::TimeDelta delay) {
+ std::unique_ptr<network::ResourceRequest> request(CreateResourceRequest());
+ StartAsync(std::move(request), nullptr, &peer_context_);
+
+ ASSERT_EQ(1u, loader_and_clients_.size());
+ auto client = std::move(loader_and_clients_[0].second);
+ network::ResourceResponseHead response_head;
+ response_head.request_start = remote_request_start;
+ response_head.load_timing.request_start = remote_request_start;
+ response_head.load_timing.receive_headers_end = remote_request_start;
+ // We need to put somthing non-null time, otherwise no values will be
+ // copied.
+ response_head.load_timing.request_start_time =
+ base::Time() + base::TimeDelta::FromSeconds(99);
+ client->OnReceiveResponse(response_head, {});
+
+ network::URLLoaderCompletionStatus status;
+ status.completion_time = completion_time;
+
+ client->OnComplete(status);
+
+ const base::TimeTicks until = base::TimeTicks::Now() + delay;
+ while (base::TimeTicks::Now() < until)
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
+ base::RunLoop().RunUntilIdle();
+ loader_and_clients_.clear();
+ }
+
+ base::TimeTicks request_start() const {
+ EXPECT_TRUE(peer_context_.received_response);
+ return peer_context_.last_load_timing.request_start;
+ }
+ base::TimeTicks completion_time() const {
+ EXPECT_TRUE(peer_context_.complete);
+ return peer_context_.completion_status.completion_time;
+ }
+
+ private:
+ TestRequestPeer::Context peer_context_;
+};
+
+TEST_F(CompletionTimeConversionTest, NullCompletionTimestamp) {
+ const auto remote_request_start =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(4);
+
+ PerformTest(remote_request_start, base::TimeTicks(), base::TimeDelta());
+
+ EXPECT_EQ(base::TimeTicks(), completion_time());
+}
+
+TEST_F(CompletionTimeConversionTest, RemoteRequestStartIsUnavailable) {
+ base::TimeTicks begin = base::TimeTicks::Now();
+
+ const auto remote_completion_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(8);
+
+ PerformTest(base::TimeTicks(), remote_completion_time, base::TimeDelta());
+
+ base::TimeTicks end = base::TimeTicks::Now();
+ EXPECT_LE(begin, completion_time());
+ EXPECT_LE(completion_time(), end);
+}
+
+TEST_F(CompletionTimeConversionTest, Convert) {
+ const auto remote_request_start =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(4);
+
+ const auto remote_completion_time =
+ remote_request_start + base::TimeDelta::FromMilliseconds(3);
+
+ PerformTest(remote_request_start, remote_completion_time,
+ base::TimeDelta::FromMilliseconds(15));
+
+ EXPECT_EQ(completion_time(),
+ request_start() + base::TimeDelta::FromMilliseconds(3));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/loader/shared_memory_data_consumer_handle.cc b/chromium/content/renderer/loader/shared_memory_data_consumer_handle.cc
index 2551ead92fa..f302985c610 100644
--- a/chromium/content/renderer/loader/shared_memory_data_consumer_handle.cc
+++ b/chromium/content/renderer/loader/shared_memory_data_consumer_handle.cc
@@ -11,7 +11,6 @@
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/content/renderer/loader/sync_load_context.cc b/chromium/content/renderer/loader/sync_load_context.cc
index fc94a225897..17da79d30b5 100644
--- a/chromium/content/renderer/loader/sync_load_context.cc
+++ b/chromium/content/renderer/loader/sync_load_context.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "content/public/common/url_loader_throttle.h"
+#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/sync_load_response.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_request.h"
@@ -16,6 +17,59 @@
namespace content {
+// An inner helper class to manage the SyncLoadContext's events and timeouts,
+// so that we can stop or resumse all of them at once.
+class SyncLoadContext::SignalHelper final {
+ public:
+ SignalHelper(SyncLoadContext* context,
+ base::WaitableEvent* redirect_or_response_event,
+ base::WaitableEvent* abort_event,
+ double timeout)
+ : context_(context),
+ redirect_or_response_event_(redirect_or_response_event),
+ abort_event_(abort_event) {
+ Start(base::TimeDelta::FromSecondsD(timeout));
+ }
+
+ void SignalRedirectOrResponseComplete() {
+ abort_watcher_.StopWatching();
+ timeout_timer_.AbandonAndStop();
+ redirect_or_response_event_->Signal();
+ }
+
+ bool RestartAfterRedirect() {
+ if (abort_event_ && abort_event_->IsSignaled())
+ return false;
+ base::TimeDelta timeout_remainder =
+ timeout_timer_.desired_run_time() - base::TimeTicks::Now();
+ if (timeout_remainder <= base::TimeDelta())
+ return false;
+ Start(timeout_remainder);
+ return true;
+ }
+
+ private:
+ void Start(const base::TimeDelta& timeout) {
+ DCHECK(!redirect_or_response_event_->IsSignaled());
+ if (abort_event_) {
+ abort_watcher_.StartWatching(
+ abort_event_,
+ base::BindOnce(&SyncLoadContext::OnAbort, base::Unretained(context_)),
+ context_->task_runner_);
+ }
+ if (timeout > base::TimeDelta()) {
+ timeout_timer_.Start(FROM_HERE, timeout, context_,
+ &SyncLoadContext::OnTimeout);
+ }
+ }
+
+ SyncLoadContext* context_;
+ base::WaitableEvent* redirect_or_response_event_;
+ base::WaitableEvent* abort_event_;
+ base::WaitableEventWatcher abort_watcher_;
+ base::OneShotTimer timeout_timer_;
+};
+
// static
void SyncLoadContext::StartAsyncWithWaitableEvent(
std::unique_ptr<network::ResourceRequest> request,
@@ -26,21 +80,21 @@ void SyncLoadContext::StartAsyncWithWaitableEvent(
url_loader_factory_info,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
SyncLoadResponse* response,
- base::WaitableEvent* completed_event,
+ base::WaitableEvent* redirect_or_response_event,
base::WaitableEvent* abort_event,
double timeout,
blink::mojom::BlobRegistryPtrInfo download_to_blob_registry) {
bool download_to_blob = download_to_blob_registry.is_valid();
auto* context = new SyncLoadContext(
request.get(), std::move(url_loader_factory_info), response,
- completed_event, abort_event, timeout,
+ redirect_or_response_event, abort_event, timeout,
std::move(download_to_blob_registry), loading_task_runner);
context->request_id_ = context->resource_dispatcher_->StartAsync(
std::move(request), routing_id, std::move(loading_task_runner),
traffic_annotation, true /* is_sync */,
download_to_blob /* pass_response_pipe_to_peer */,
base::WrapUnique(context), context->url_loader_factory_,
- std::move(throttles), network::mojom::URLLoaderClientEndpointsPtr(),
+ std::move(throttles), nullptr /* navigation_response_override_params */,
nullptr /* continue_for_navigation */);
}
@@ -48,27 +102,21 @@ SyncLoadContext::SyncLoadContext(
network::ResourceRequest* request,
std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory,
SyncLoadResponse* response,
- base::WaitableEvent* completed_event,
+ base::WaitableEvent* redirect_or_response_event,
base::WaitableEvent* abort_event,
double timeout,
blink::mojom::BlobRegistryPtrInfo download_to_blob_registry,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: response_(response),
- completed_event_(completed_event),
download_to_blob_registry_(std::move(download_to_blob_registry)),
- task_runner_(std::move(task_runner)) {
+ task_runner_(std::move(task_runner)),
+ signals_(std::make_unique<SignalHelper>(this,
+ redirect_or_response_event,
+ abort_event,
+ timeout)),
+ fetch_request_mode_(request->fetch_request_mode) {
url_loader_factory_ =
network::SharedURLLoaderFactory::Create(std::move(url_loader_factory));
- if (abort_event) {
- abort_watcher_.StartWatching(
- abort_event,
- base::BindOnce(&SyncLoadContext::OnAbort, base::Unretained(this)),
- task_runner_);
- }
- if (timeout) {
- timeout_timer_.Start(FROM_HERE, base::TimeDelta::FromSecondsD(timeout),
- this, &SyncLoadContext::OnTimeout);
- }
// Constructs a new ResourceDispatcher specifically for this request.
resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
@@ -86,7 +134,13 @@ bool SyncLoadContext::OnReceivedRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseInfo& info) {
DCHECK(!Completed());
- if (redirect_info.new_url.GetOrigin() != response_->url.GetOrigin()) {
+ // Synchronous loads in blink aren't associated with a ResourceClient, and
+ // CORS checks are performed by ResourceClient subclasses, so there's
+ // currently no way to perform CORS checks for redirects.
+ // Err on the side of extreme caution and block any cross origin redirect
+ // that might have CORS implications.
+ if (fetch_request_mode_ != network::mojom::FetchRequestMode::kNoCORS &&
+ redirect_info.new_url.GetOrigin() != response_->url.GetOrigin()) {
LOG(ERROR) << "Cross origin redirect denied";
response_->error_code = net::ERR_ABORTED;
@@ -98,9 +152,33 @@ bool SyncLoadContext::OnReceivedRedirect(
}
response_->url = redirect_info.new_url;
+ response_->info = info;
+ response_->redirect_info = redirect_info;
+ response_->context_for_redirect = this;
+ resource_dispatcher_->SetDefersLoading(request_id_, true);
+ signals_->SignalRedirectOrResponseComplete();
return true;
}
+void SyncLoadContext::FollowRedirect() {
+ if (!signals_->RestartAfterRedirect()) {
+ CancelRedirect();
+ return;
+ }
+
+ response_->redirect_info = net::RedirectInfo();
+ response_->context_for_redirect = nullptr;
+
+ resource_dispatcher_->SetDefersLoading(request_id_, false);
+}
+
+void SyncLoadContext::CancelRedirect() {
+ response_->redirect_info = net::RedirectInfo();
+ response_->context_for_redirect = nullptr;
+ response_->error_code = net::ERR_ABORTED;
+ CompleteRequest(true);
+}
+
void SyncLoadContext::OnReceivedResponse(
const network::ResourceResponseInfo& info) {
DCHECK(!Completed());
@@ -181,12 +259,8 @@ void SyncLoadContext::OnTimeout() {
}
void SyncLoadContext::CompleteRequest(bool remove_pending_request) {
- abort_watcher_.StopWatching();
- timeout_timer_.AbandonAndStop();
-
- completed_event_->Signal();
-
- completed_event_ = nullptr;
+ signals_->SignalRedirectOrResponseComplete();
+ signals_ = nullptr;
response_ = nullptr;
if (remove_pending_request) {
@@ -196,7 +270,7 @@ void SyncLoadContext::CompleteRequest(bool remove_pending_request) {
}
bool SyncLoadContext::Completed() const {
- DCHECK_EQ(!completed_event_, !response_);
+ DCHECK_EQ(!signals_, !response_);
return !response_;
}
diff --git a/chromium/content/renderer/loader/sync_load_context.h b/chromium/content/renderer/loader/sync_load_context.h
index b0b474405a3..23a7e7e8094 100644
--- a/chromium/content/renderer/loader/sync_load_context.h
+++ b/chromium/content/renderer/loader/sync_load_context.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event_watcher.h"
#include "base/timer/timer.h"
#include "content/public/renderer/request_peer.h"
@@ -54,6 +55,9 @@ class SyncLoadContext : public RequestPeer {
~SyncLoadContext() override;
+ void FollowRedirect();
+ void CancelRedirect();
+
private:
SyncLoadContext(
network::ResourceRequest* request,
@@ -90,10 +94,6 @@ class SyncLoadContext : public RequestPeer {
// Set to null after CompleteRequest() is called.
SyncLoadResponse* response_;
- // This event is signaled when the request is complete.
- // Set to null after CompleteRequest() is called.
- base::WaitableEvent* completed_event_;
-
// State necessary to run a request on an independent thread.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
@@ -110,8 +110,10 @@ class SyncLoadContext : public RequestPeer {
base::Optional<int64_t> downloaded_file_length_;
- base::WaitableEventWatcher abort_watcher_;
- base::OneShotTimer timeout_timer_;
+ class SignalHelper;
+ std::unique_ptr<SignalHelper> signals_;
+
+ const network::mojom::FetchRequestMode fetch_request_mode_;
DISALLOW_COPY_AND_ASSIGN(SyncLoadContext);
};
diff --git a/chromium/content/renderer/loader/sync_load_response.h b/chromium/content/renderer/loader/sync_load_response.h
index bd46a9b14a9..ea252ca5f31 100644
--- a/chromium/content/renderer/loader/sync_load_response.h
+++ b/chromium/content/renderer/loader/sync_load_response.h
@@ -17,6 +17,8 @@
namespace content {
+class SyncLoadContext;
+
// See the SyncLoad method. (The name of this struct is not
// suffixed with "Info" because it also contains the response data.)
struct CONTENT_EXPORT SyncLoadResponse {
@@ -26,6 +28,9 @@ struct CONTENT_EXPORT SyncLoadResponse {
SyncLoadResponse& operator=(SyncLoadResponse&& other);
+ base::Optional<net::RedirectInfo> redirect_info;
+ SyncLoadContext* context_for_redirect = nullptr;
+
network::ResourceResponseInfo info;
// The response error code.
diff --git a/chromium/content/renderer/loader/test_request_peer.cc b/chromium/content/renderer/loader/test_request_peer.cc
index 42b46e16e41..1d92c02c630 100644
--- a/chromium/content/renderer/loader/test_request_peer.cc
+++ b/chromium/content/renderer/loader/test_request_peer.cc
@@ -27,6 +27,7 @@ bool TestRequestPeer::OnReceivedRedirect(
EXPECT_FALSE(context_->cancelled);
EXPECT_FALSE(context_->complete);
++context_->seen_redirects;
+ context_->last_load_timing = info.load_timing;
if (context_->defer_on_redirect)
dispatcher_->SetDefersLoading(context_->request_id, true);
return context_->follow_redirects;
@@ -38,6 +39,7 @@ void TestRequestPeer::OnReceivedResponse(
EXPECT_FALSE(context_->received_response);
EXPECT_FALSE(context_->complete);
context_->received_response = true;
+ context_->last_load_timing = info.load_timing;
if (context_->cancel_on_receive_response) {
dispatcher_->Cancel(
context_->request_id,
@@ -101,6 +103,7 @@ void TestRequestPeer::OnCompletedRequest(
EXPECT_TRUE(context_->received_response);
EXPECT_FALSE(context_->complete);
context_->complete = true;
+ context_->completion_status = status;
}
TestRequestPeer::Context::Context() = default;
diff --git a/chromium/content/renderer/loader/test_request_peer.h b/chromium/content/renderer/loader/test_request_peer.h
index 06e3a24e7c0..3c40627b410 100644
--- a/chromium/content/renderer/loader/test_request_peer.h
+++ b/chromium/content/renderer/loader/test_request_peer.h
@@ -11,6 +11,8 @@
#include <vector>
#include "base/time/time.h"
#include "content/public/renderer/request_peer.h"
+#include "net/base/load_timing_info.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
namespace net {
struct RedirectInfo;
@@ -77,6 +79,9 @@ class TestRequestPeer : public RequestPeer {
bool complete = false;
bool cancelled = false;
int request_id = -1;
+
+ net::LoadTimingInfo last_load_timing;
+ network::URLLoaderCompletionStatus completion_status;
};
private:
diff --git a/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h b/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
index aaa4289f50c..d76f70f6355 100644
--- a/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
+++ b/chromium/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_LOADER_TRACKED_CHILD_URL_LOADER_FACTORY_BUNDLE_H_
#define CONTENT_RENDERER_LOADER_TRACKED_CHILD_URL_LOADER_FACTORY_BUNDLE_H_
+#include "base/sequenced_task_runner.h"
#include "content/common/content_export.h"
#include "content/renderer/loader/child_url_loader_factory_bundle.h"
diff --git a/chromium/content/renderer/loader/url_loader_client_impl.h b/chromium/content/renderer/loader/url_loader_client_impl.h
index 96712b00667..66c1a455214 100644
--- a/chromium/content/renderer/loader/url_loader_client_impl.h
+++ b/chromium/content/renderer/loader/url_loader_client_impl.h
@@ -60,10 +60,9 @@ class CONTENT_EXPORT URLLoaderClientImpl final
// Binds this instance to the given URLLoaderClient endpoints so that it can
// start getting the mojo calls from the given loader. This is used only for
- // the main resource loading when NavigationMojoResponse and/or NetworkService
- // is enabled. Otherwise (in regular subresource loading cases) |this| is not
- // bound to a client request, but used via ThrottlingURLLoader to get client
- // upcalls from the loader.
+ // the main resource loading. Otherwise (in regular subresource loading cases)
+ // |this| is not bound to a client request, but used via ThrottlingURLLoader
+ // to get client upcalls from the loader.
void Bind(
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
@@ -112,7 +111,6 @@ class CONTENT_EXPORT URLLoaderClientImpl final
ResourceDispatcher* const resource_dispatcher_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- // Used in NavigationMojoResponse and NetworkService.
network::mojom::URLLoaderPtr url_loader_;
mojo::Binding<network::mojom::URLLoaderClient> url_loader_client_binding_;
diff --git a/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc b/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc
index 9c00707535e..4278bd904a9 100644
--- a/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc
+++ b/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc
@@ -7,13 +7,14 @@
#include <vector>
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
+#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "content/renderer/loader/test_request_peer.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/redirect_info.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -30,9 +31,9 @@ class URLLoaderClientImplTest : public ::testing::Test,
TRAFFIC_ANNOTATION_FOR_TESTS, false, false,
std::make_unique<TestRequestPeer>(dispatcher_.get(),
&request_peer_context_),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(this),
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this),
std::vector<std::unique_ptr<URLLoaderThrottle>>(),
- network::mojom::URLLoaderClientEndpointsPtr(),
+ nullptr /* navigation_response_override_params */,
nullptr /* continue_navigation_function */);
request_peer_context_.request_id = request_id_;
@@ -62,7 +63,7 @@ class URLLoaderClientImplTest : public ::testing::Test,
static MojoCreateDataPipeOptions DataPipeOptions() {
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
- options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
options.element_num_bytes = 1;
options.capacity_num_bytes = 4096;
return options;
diff --git a/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc b/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc
index 49cb00b247c..3038533caa2 100644
--- a/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc
+++ b/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc
@@ -10,14 +10,15 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "content/public/renderer/request_peer.h"
+#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "net/base/request_priority.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -143,7 +144,7 @@ class URLResponseBodyConsumerTest : public ::testing::Test {
MojoCreateDataPipeOptions CreateDataPipeOptions() {
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
- options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
options.element_num_bytes = 1;
options.capacity_num_bytes = 1024;
return options;
@@ -158,9 +159,10 @@ class URLResponseBodyConsumerTest : public ::testing::Test {
TRAFFIC_ANNOTATION_FOR_TESTS, false,
false /* pass_response_pipe_to_peer */,
std::make_unique<TestRequestPeer>(context, message_loop_.task_runner()),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(&factory_),
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &factory_),
std::vector<std::unique_ptr<URLLoaderThrottle>>(),
- network::mojom::URLLoaderClientEndpointsPtr(),
+ nullptr /* navigation_response_override_params */,
nullptr /* continue_navigation_function */);
}
diff --git a/chromium/content/renderer/loader/web_data_consumer_handle_impl.cc b/chromium/content/renderer/loader/web_data_consumer_handle_impl.cc
index b97d43b62cc..c05041f207c 100644
--- a/chromium/content/renderer/loader/web_data_consumer_handle_impl.cc
+++ b/chromium/content/renderer/loader/web_data_consumer_handle_impl.cc
@@ -81,7 +81,7 @@ Result WebDataConsumerHandleImpl::ReaderImpl::Read(void* data,
context_->handle()->ReadData(data, &size_to_pass, flags_to_pass);
if (rv == MOJO_RESULT_OK)
*read_size = size_to_pass;
- if (rv == MOJO_RESULT_OK || rv == MOJO_RESULT_SHOULD_WAIT)
+ if (rv == MOJO_RESULT_SHOULD_WAIT)
handle_watcher_.ArmOrNotify();
return HandleReadResult(rv);
@@ -104,13 +104,13 @@ Result WebDataConsumerHandleImpl::ReaderImpl::BeginRead(const void** buffer,
context_->handle()->BeginReadData(buffer, &size_to_pass, flags_to_pass);
if (rv == MOJO_RESULT_OK)
*available = size_to_pass;
+ if (rv == MOJO_RESULT_SHOULD_WAIT)
+ handle_watcher_.ArmOrNotify();
return HandleReadResult(rv);
}
Result WebDataConsumerHandleImpl::ReaderImpl::EndRead(size_t read_size) {
MojoResult rv = context_->handle()->EndReadData(read_size);
- if (rv == MOJO_RESULT_OK)
- handle_watcher_.ArmOrNotify();
return rv == MOJO_RESULT_OK ? kOk : kUnexpectedError;
}
diff --git a/chromium/content/renderer/loader/web_data_consumer_handle_impl.h b/chromium/content/renderer/loader/web_data_consumer_handle_impl.h
index 83427b1149e..f79cb797b8e 100644
--- a/chromium/content/renderer/loader/web_data_consumer_handle_impl.h
+++ b/chromium/content/renderer/loader/web_data_consumer_handle_impl.h
@@ -9,6 +9,7 @@
#include <memory>
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
diff --git a/chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc b/chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc
index b01e4800a3d..8e4f0a216a5 100644
--- a/chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc
+++ b/chromium/content/renderer/loader/web_data_consumer_handle_impl_unittest.cc
@@ -196,7 +196,7 @@ class WebDataConsumerHandleImplTest : public ::testing::Test {
void SetUp() override {
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
- options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
options.element_num_bytes = 1;
options.capacity_num_bytes = kDataPipeCapacity;
@@ -326,7 +326,7 @@ class CountDidGetReadableClient : public blink::WebDataConsumerHandle::Client {
TEST_F(WebDataConsumerHandleImplTest, DidGetReadable) {
static constexpr size_t kBlockSize = kDataPipeCapacity / 3;
- static constexpr size_t kTotalSize = kBlockSize * 3;
+ static constexpr size_t kTotalSize = kBlockSize * 2;
std::unique_ptr<CountDidGetReadableClient> client =
std::make_unique<CountDidGetReadableClient>();
@@ -337,7 +337,7 @@ TEST_F(WebDataConsumerHandleImplTest, DidGetReadable) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, client->num_did_get_readable_called());
- // Push three blocks.
+ // Push two blocks.
{
std::string expected;
int index = 0;
@@ -365,10 +365,10 @@ TEST_F(WebDataConsumerHandleImplTest, DidGetReadable) {
EXPECT_EQ(sizeof(buffer), size);
}
base::RunLoop().RunUntilIdle();
- // |client| is notified the pipe is still ready.
- EXPECT_EQ(2, client->num_did_get_readable_called());
+ // |client| is NOT notified since the data is still available.
+ EXPECT_EQ(1, client->num_did_get_readable_called());
- // Read one more block.
+ // Read the other block.
{
const void* buffer = nullptr;
size_t size = sizeof(buffer);
@@ -378,28 +378,38 @@ TEST_F(WebDataConsumerHandleImplTest, DidGetReadable) {
EXPECT_TRUE(buffer);
EXPECT_EQ(kTotalSize - kBlockSize, size);
base::RunLoop().RunUntilIdle();
- // |client| is NOT notified until EndRead is called.
- EXPECT_EQ(2, client->num_did_get_readable_called());
rv = reader->EndRead(kBlockSize);
EXPECT_EQ(Result::kOk, rv);
}
base::RunLoop().RunUntilIdle();
- // |client| is notified the pipe is still ready.
- EXPECT_EQ(3, client->num_did_get_readable_called());
+ // |client| is NOT notified the pipe is still waiting for more data.
+ EXPECT_EQ(1, client->num_did_get_readable_called());
- // Read the final block.
+ // Read one more.
{
char buffer[kBlockSize];
size_t size = 0;
Result rv = reader->Read(&buffer, sizeof(buffer),
WebDataConsumerHandle::kFlagNone, &size);
- EXPECT_EQ(Result::kOk, rv);
- EXPECT_EQ(sizeof(buffer), size);
+ EXPECT_EQ(Result::kShouldWait, rv);
+ }
+ base::RunLoop().RunUntilIdle();
+ // |client| is NOT notified because the pipe is still waiting for more data.
+ EXPECT_EQ(1, client->num_did_get_readable_called());
+
+ // Push one more block.
+ {
+ std::string expected(kBlockSize, 'x');
+ uint32_t size = expected.size();
+ MojoResult rv =
+ producer_->WriteData(expected.data(), &size, MOJO_WRITE_DATA_FLAG_NONE);
+ EXPECT_EQ(MOJO_RESULT_OK, rv);
+ EXPECT_EQ(expected.size(), size);
}
base::RunLoop().RunUntilIdle();
- // |client| is NOT notified because the pipe doesn't have any data.
- EXPECT_EQ(3, client->num_did_get_readable_called());
+ // |client| is notified the pipe gets ready.
+ EXPECT_EQ(2, client->num_did_get_readable_called());
}
} // namespace
diff --git a/chromium/content/renderer/loader/web_url_loader_impl.cc b/chromium/content/renderer/loader/web_url_loader_impl.cc
index 0c2ed0fbdce..c1ece37554f 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl.cc
+++ b/chromium/content/renderer/loader/web_url_loader_impl.cc
@@ -142,32 +142,21 @@ void PopulateURLLoadTiming(const net::LoadTimingInfo& load_timing,
WebURLLoadTiming* url_timing) {
DCHECK(!load_timing.request_start.is_null());
- const TimeTicks kNullTicks;
url_timing->Initialize();
- url_timing->SetRequestTime(
- (load_timing.request_start - kNullTicks).InSecondsF());
- url_timing->SetProxyStart(
- (load_timing.proxy_resolve_start - kNullTicks).InSecondsF());
- url_timing->SetProxyEnd(
- (load_timing.proxy_resolve_end - kNullTicks).InSecondsF());
- url_timing->SetDNSStart(
- (load_timing.connect_timing.dns_start - kNullTicks).InSecondsF());
- url_timing->SetDNSEnd(
- (load_timing.connect_timing.dns_end - kNullTicks).InSecondsF());
- url_timing->SetConnectStart(
- (load_timing.connect_timing.connect_start - kNullTicks).InSecondsF());
- url_timing->SetConnectEnd(
- (load_timing.connect_timing.connect_end - kNullTicks).InSecondsF());
- url_timing->SetSSLStart(
- (load_timing.connect_timing.ssl_start - kNullTicks).InSecondsF());
- url_timing->SetSSLEnd(
- (load_timing.connect_timing.ssl_end - kNullTicks).InSecondsF());
- url_timing->SetSendStart((load_timing.send_start - kNullTicks).InSecondsF());
- url_timing->SetSendEnd((load_timing.send_end - kNullTicks).InSecondsF());
- url_timing->SetReceiveHeadersEnd(
- (load_timing.receive_headers_end - kNullTicks).InSecondsF());
- url_timing->SetPushStart((load_timing.push_start - kNullTicks).InSecondsF());
- url_timing->SetPushEnd((load_timing.push_end - kNullTicks).InSecondsF());
+ url_timing->SetRequestTime(load_timing.request_start);
+ url_timing->SetProxyStart(load_timing.proxy_resolve_start);
+ url_timing->SetProxyEnd(load_timing.proxy_resolve_end);
+ url_timing->SetDNSStart(load_timing.connect_timing.dns_start);
+ url_timing->SetDNSEnd(load_timing.connect_timing.dns_end);
+ url_timing->SetConnectStart(load_timing.connect_timing.connect_start);
+ url_timing->SetConnectEnd(load_timing.connect_timing.connect_end);
+ url_timing->SetSSLStart(load_timing.connect_timing.ssl_start);
+ url_timing->SetSSLEnd(load_timing.connect_timing.ssl_end);
+ url_timing->SetSendStart(load_timing.send_start);
+ url_timing->SetSendEnd(load_timing.send_end);
+ url_timing->SetReceiveHeadersEnd(load_timing.receive_headers_end);
+ url_timing->SetPushStart(load_timing.push_start);
+ url_timing->SetPushEnd(load_timing.push_end);
}
net::RequestPriority ConvertWebKitPriorityToNetPriority(
@@ -363,12 +352,6 @@ void SetSecurityStyleAndDetails(const GURL& url,
} // namespace
-StreamOverrideParameters::StreamOverrideParameters() {}
-StreamOverrideParameters::~StreamOverrideParameters() {
- if (on_delete)
- std::move(on_delete).Run(stream_url);
-}
-
WebURLLoaderFactoryImpl::WebURLLoaderFactoryImpl(
base::WeakPtr<ResourceDispatcher> resource_dispatcher,
scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
@@ -469,7 +452,6 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context> {
ResourceDispatcher* resource_dispatcher_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::unique_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
- std::unique_ptr<StreamOverrideParameters> stream_override_;
std::unique_ptr<SharedMemoryDataConsumerHandle::Writer> body_stream_writer_;
std::unique_ptr<KeepAliveHandleWithChildProcessReference> keep_alive_handle_;
enum DeferState {NOT_DEFERRING, SHOULD_DEFER, DEFERRED_DATA};
@@ -630,10 +612,11 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
return;
}
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override;
if (request.GetExtraData()) {
RequestExtraData* extra_data =
static_cast<RequestExtraData*>(request.GetExtraData());
- stream_override_ = extra_data->TakeStreamOverrideOwnership();
+ response_override = extra_data->TakeNavigationResponseOverrideOwnership();
}
@@ -641,7 +624,7 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
// the WebURLLoader are the ones created by CommitNavigation. Several browser
// tests load HTML directly through a data url which will be handled by the
// block above.
- DCHECK(!IsBrowserSideNavigationEnabled() || stream_override_ ||
+ DCHECK(response_override ||
request.GetFrameType() ==
network::mojom::RequestContextFrameType::kNone);
@@ -686,6 +669,11 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
network::kDefaultAcceptHeader);
}
+ if (resource_request->resource_type == RESOURCE_TYPE_PREFETCH ||
+ resource_request->resource_type == RESOURCE_TYPE_FAVICON) {
+ resource_request->do_not_prompt_for_login = true;
+ }
+
resource_request->load_flags = GetLoadFlagsForWebURLRequest(request);
// |plugin_child_id| only needs to be non-zero if the request originates
@@ -725,22 +713,13 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
resource_request->previews_state =
static_cast<int>(request.GetPreviewsState());
- // PlzNavigate: The network request has already been made by the browser.
- // The renderer should request a stream which contains the body of the
- // response. If the Network Service or NavigationMojoResponse is enabled, the
- // URLLoaderClientEndpoints is used instead to get the body.
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
- if (stream_override_) {
- CHECK(IsBrowserSideNavigationEnabled());
+ // The network request has already been made by the browser. The renderer
+ // should bind the URLLoaderClientEndpoints stored in |response_override| to
+ // an implementation of a URLLoaderClient to get the response body.
+ if (response_override) {
DCHECK(!sync_load_response);
DCHECK_NE(network::mojom::RequestContextFrameType::kNone,
request.GetFrameType());
- if (stream_override_->url_loader_client_endpoints) {
- url_loader_client_endpoints =
- std::move(stream_override_->url_loader_client_endpoints);
- } else {
- resource_request->resource_body_stream_url = stream_override_->stream_url;
- }
}
RequestExtraData empty_extra_data;
@@ -751,6 +730,16 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
extra_data = &empty_extra_data;
extra_data->CopyToResourceRequest(resource_request.get());
+ std::unique_ptr<RequestPeer> peer;
+ if (extra_data->download_to_network_cache_only()) {
+ peer = std::make_unique<SinkPeer>(this);
+ } else {
+ const bool discard_body =
+ (resource_request->resource_type == RESOURCE_TYPE_PREFETCH);
+ peer =
+ std::make_unique<WebURLLoaderImpl::RequestPeerImpl>(this, discard_body);
+ }
+
if (sync_load_response) {
DCHECK(defers_loading_ == NOT_DEFERRING);
@@ -763,20 +752,11 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
std::move(resource_request), request.RequestorID(),
GetTrafficAnnotationTag(request), sync_load_response,
url_loader_factory_, extra_data->TakeURLLoaderThrottles(),
- request.TimeoutInterval(), std::move(download_to_blob_registry));
+ request.TimeoutInterval(), std::move(download_to_blob_registry),
+ std::move(peer));
return;
}
- std::unique_ptr<RequestPeer> peer;
- if (extra_data->download_to_network_cache_only()) {
- peer = std::make_unique<SinkPeer>(this);
- } else {
- const bool discard_body =
- (resource_request->resource_type == RESOURCE_TYPE_PREFETCH);
- peer =
- std::make_unique<WebURLLoaderImpl::RequestPeerImpl>(this, discard_body);
- }
-
TRACE_EVENT_WITH_FLOW0("loading", "WebURLLoaderImpl::Context::Start", this,
TRACE_EVENT_FLAG_FLOW_OUT);
base::OnceClosure continue_navigation_function;
@@ -784,8 +764,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
std::move(resource_request), request.RequestorID(), task_runner_,
GetTrafficAnnotationTag(request), false /* is_sync */,
request.PassResponsePipeToClient(), std::move(peer), url_loader_factory_,
- extra_data->TakeURLLoaderThrottles(),
- std::move(url_loader_client_endpoints), &continue_navigation_function);
+ extra_data->TakeURLLoaderThrottles(), std::move(response_override),
+ &continue_navigation_function);
extra_data->set_continue_navigation_function(
std::move(continue_navigation_function));
@@ -823,7 +803,7 @@ bool WebURLLoaderImpl::Context::OnReceivedRedirect(
}
void WebURLLoaderImpl::Context::OnReceivedResponse(
- const network::ResourceResponseInfo& initial_info) {
+ const network::ResourceResponseInfo& info) {
if (!client_)
return;
@@ -831,25 +811,6 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
"loading", "WebURLLoaderImpl::Context::OnReceivedResponse",
this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- network::ResourceResponseInfo info = initial_info;
-
- // PlzNavigate: during navigations, the ResourceResponse has already been
- // received on the browser side, and has been passed down to the renderer.
- if (stream_override_) {
- CHECK(IsBrowserSideNavigationEnabled());
- info = stream_override_->response;
-
- // Replay the redirects that happened during navigation.
- DCHECK_EQ(stream_override_->redirect_responses.size(),
- stream_override_->redirect_infos.size());
- for (size_t i = 0; i < stream_override_->redirect_responses.size(); ++i) {
- bool result = OnReceivedRedirect(stream_override_->redirect_infos[i],
- stream_override_->redirect_responses[i]);
- if (!result)
- return;
- }
- }
-
WebURLResponse response;
PopulateURLResponse(url_, info, &response, report_raw_headers_);
@@ -1001,10 +962,9 @@ void WebURLLoaderImpl::Context::OnCompletedRequest(
WebURLError::IsWebSecurityViolation::kFalse, url_),
total_transfer_size, encoded_body_size, status.decoded_body_length);
} else {
- client_->DidFinishLoading(
- (status.completion_time - TimeTicks()).InSecondsF(),
- total_transfer_size, encoded_body_size, status.decoded_body_length,
- status.blocked_cross_site_document);
+ client_->DidFinishLoading(status.completion_time, total_transfer_size,
+ encoded_body_size, status.decoded_body_length,
+ status.blocked_cross_site_document);
}
}
}
@@ -1266,11 +1226,8 @@ void WebURLLoaderImpl::PopulateURLResponse(
if (!info.load_timing.receive_headers_end.is_null()) {
WebURLLoadTiming timing;
PopulateURLLoadTiming(info.load_timing, &timing);
- const TimeTicks kNullTicks;
- timing.SetWorkerStart(
- (info.service_worker_start_time - kNullTicks).InSecondsF());
- timing.SetWorkerReady(
- (info.service_worker_ready_time - kNullTicks).InSecondsF());
+ timing.SetWorkerStart(info.service_worker_start_time);
+ timing.SetWorkerReady(info.service_worker_ready_time);
response->SetLoadTiming(timing);
}
@@ -1334,6 +1291,7 @@ void WebURLLoaderImpl::PopulateURLResponse(
void WebURLLoaderImpl::LoadSynchronously(
const WebURLRequest& request,
+ WebURLLoaderClient* client,
WebURLResponse& response,
base::Optional<WebURLError>& error,
WebData& data,
@@ -1343,6 +1301,9 @@ void WebURLLoaderImpl::LoadSynchronously(
blink::WebBlobInfo& downloaded_blob) {
TRACE_EVENT0("loading", "WebURLLoaderImpl::loadSynchronously");
SyncLoadResponse sync_load_response;
+
+ DCHECK(!context_->client());
+ context_->set_client(client);
context_->Start(request, &sync_load_response);
const GURL& final_url = sync_load_response.url;
diff --git a/chromium/content/renderer/loader/web_url_loader_impl.h b/chromium/content/renderer/loader/web_url_loader_impl.h
index 147130d926e..ced62e5a71b 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl.h
+++ b/chromium/content/renderer/loader/web_url_loader_impl.h
@@ -5,22 +5,15 @@
#ifndef CONTENT_RENDERER_LOADER_WEB_URL_LOADER_IMPL_H_
#define CONTENT_RENDERER_LOADER_WEB_URL_LOADER_IMPL_H_
-#include <vector>
-
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/common/frame.mojom.h"
#include "mojo/public/cpp/system/data_pipe.h"
-#include "net/url_request/redirect_info.h"
-#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
-#include "url/gurl.h"
namespace base {
class SingleThreadTaskRunner;
@@ -34,24 +27,6 @@ namespace content {
class ResourceDispatcher;
-// PlzNavigate: Used to override parameters of the navigation request.
-struct CONTENT_EXPORT StreamOverrideParameters {
- public:
- StreamOverrideParameters();
- ~StreamOverrideParameters();
-
- GURL stream_url;
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
- network::ResourceResponseHead response;
- std::vector<GURL> redirects;
- std::vector<network::ResourceResponseInfo> redirect_responses;
- std::vector<net::RedirectInfo> redirect_infos;
-
- // Called when this struct is deleted. Used to notify the browser that it can
- // release its associated StreamHandle.
- base::OnceCallback<void(const GURL&)> on_delete;
-};
-
// Default implementation of WebURLLoaderFactory.
class CONTENT_EXPORT WebURLLoaderFactoryImpl
: public blink::WebURLLoaderFactory {
@@ -95,6 +70,7 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader {
bool report_security_info);
// WebURLLoader methods:
void LoadSynchronously(const blink::WebURLRequest& request,
+ blink::WebURLLoaderClient* client,
blink::WebURLResponse& response,
base::Optional<blink::WebURLError>& error,
blink::WebData& data,
diff --git a/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc b/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
index a573dee34d4..e3fd5112703 100644
--- a/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -19,9 +19,9 @@
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "content/public/renderer/fixed_received_data.h"
#include "content/public/renderer/request_peer.h"
+#include "content/renderer/loader/navigation_response_override_parameters.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "content/renderer/loader/sync_load_response.h"
@@ -35,6 +35,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_response_info.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -77,7 +78,8 @@ class TestResourceDispatcher : public ResourceDispatcher {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
double timeout,
- blink::mojom::BlobRegistryPtrInfo download_to_blob_registry) override {
+ blink::mojom::BlobRegistryPtrInfo download_to_blob_registry,
+ std::unique_ptr<RequestPeer> peer) override {
*response = std::move(sync_load_response_);
}
@@ -91,14 +93,16 @@ class TestResourceDispatcher : public ResourceDispatcher {
std::unique_ptr<RequestPeer> peer,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ navigation_response_override_params,
base::OnceClosure* continue_navigation_function) override {
EXPECT_FALSE(peer_);
if (sync_load_response_.info.encoded_body_length != -1)
EXPECT_TRUE(is_sync);
peer_ = std::move(peer);
url_ = request->url;
- stream_url_ = request->resource_body_stream_url;
+ navigation_response_override_params_ =
+ std::move(navigation_response_override_params);
return 1;
}
@@ -125,6 +129,11 @@ class TestResourceDispatcher : public ResourceDispatcher {
sync_load_response_ = std::move(sync_load_response);
}
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ TakeNavigationResponseOverrideParams() {
+ return std::move(navigation_response_override_params_);
+ }
+
private:
std::unique_ptr<RequestPeer> peer_;
bool canceled_;
@@ -132,6 +141,8 @@ class TestResourceDispatcher : public ResourceDispatcher {
GURL url_;
GURL stream_url_;
SyncLoadResponse sync_load_response_;
+ std::unique_ptr<NavigationResponseOverrideParameters>
+ navigation_response_override_params_;
DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcher);
};
@@ -165,7 +176,7 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
: loader_(new WebURLLoaderImpl(
dispatcher,
blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&fake_url_loader_factory_))),
delete_on_receive_redirect_(false),
delete_on_receive_response_(false),
@@ -230,7 +241,7 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
loader_.reset();
}
- void DidFinishLoading(double finishTime,
+ void DidFinishLoading(base::TimeTicks finishTime,
int64_t totalEncodedDataLength,
int64_t totalEncodedBodyLength,
int64_t totalDecodedBodyLength,
@@ -622,33 +633,32 @@ TEST_F(WebURLLoaderImplTest, FtpDeleteOnFail) {
DoFailRequest();
}
-// PlzNavigate: checks that the stream override parameters provided on
+// Checks that the navigation response override parameters provided on
// navigation commit are properly applied.
TEST_F(WebURLLoaderImplTest, BrowserSideNavigationCommit) {
// Initialize the request and the stream override.
const GURL kNavigationURL = GURL(kTestURL);
- const GURL kStreamURL = GURL("http://bar");
const std::string kMimeType = "text/html";
blink::WebURLRequest request(kNavigationURL);
request.SetFrameType(network::mojom::RequestContextFrameType::kTopLevel);
request.SetRequestContext(blink::WebURLRequest::kRequestContextFrame);
- std::unique_ptr<StreamOverrideParameters> stream_override(
- new StreamOverrideParameters());
- stream_override->stream_url = kStreamURL;
- stream_override->response.mime_type = kMimeType;
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override(
+ new NavigationResponseOverrideParameters());
+ response_override->response.mime_type = kMimeType;
auto extra_data = std::make_unique<RequestExtraData>();
- extra_data->set_stream_override(std::move(stream_override));
+ extra_data->set_navigation_response_override(std::move(response_override));
request.SetExtraData(std::move(extra_data));
client()->loader()->LoadAsynchronously(request, client());
- // The stream url should have been added to the ResourceRequest.
ASSERT_TRUE(peer());
EXPECT_EQ(kNavigationURL, dispatcher()->url());
- EXPECT_EQ(kStreamURL, dispatcher()->stream_url());
-
EXPECT_FALSE(client()->did_receive_response());
- peer()->OnReceivedResponse(network::ResourceResponseInfo());
+
+ response_override = dispatcher()->TakeNavigationResponseOverrideParams();
+ ASSERT_TRUE(response_override);
+ peer()->OnReceivedResponse(response_override->response);
+
EXPECT_TRUE(client()->did_receive_response());
// The response info should have been overriden.
@@ -789,8 +799,8 @@ TEST_F(WebURLLoaderImplTest, SyncLengths) {
base::Optional<int64_t> downloaded_file_length;
blink::WebBlobInfo downloaded_blob;
client()->loader()->LoadSynchronously(
- request, response, error, data, encoded_data_length, encoded_body_length,
- downloaded_file_length, downloaded_blob);
+ request, nullptr, response, error, data, encoded_data_length,
+ encoded_body_length, downloaded_file_length, downloaded_blob);
EXPECT_EQ(kEncodedBodyLength, encoded_body_length);
EXPECT_EQ(kEncodedDataLength, encoded_data_length);
diff --git a/chromium/content/renderer/loader/web_url_request_util.cc b/chromium/content/renderer/loader/web_url_request_util.cc
index 13ff3603eba..9dacb1aad64 100644
--- a/chromium/content/renderer/loader/web_url_request_util.cc
+++ b/chromium/content/renderer/loader/web_url_request_util.cc
@@ -24,8 +24,9 @@
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h"
@@ -296,10 +297,17 @@ int GetLoadFlagsForWebURLRequest(const WebURLRequest& request) {
WebHTTPBody GetWebHTTPBodyForRequestBody(
const network::ResourceRequestBody& input) {
+ return GetWebHTTPBodyForRequestBodyWithBlobPtrs(input, {});
+}
+
+WebHTTPBody GetWebHTTPBodyForRequestBodyWithBlobPtrs(
+ const network::ResourceRequestBody& input,
+ std::vector<blink::mojom::BlobPtrInfo> blob_ptrs) {
WebHTTPBody http_body;
http_body.Initialize();
http_body.SetIdentifier(input.identifier());
http_body.SetContainsPasswordData(input.contains_sensitive_info());
+ auto blob_ptr_iter = blob_ptrs.begin();
for (auto& element : *input.elements()) {
switch (element.type()) {
case network::DataElement::TYPE_BYTES:
@@ -314,12 +322,16 @@ WebHTTPBody GetWebHTTPBodyForRequestBody(
element.expected_modification_time().ToDoubleT());
break;
case network::DataElement::TYPE_BLOB:
- http_body.AppendBlob(WebString::FromASCII(element.blob_uuid()));
+ if (blob_ptrs.empty()) {
+ http_body.AppendBlob(WebString::FromASCII(element.blob_uuid()));
+ } else {
+ DCHECK(blob_ptr_iter != blob_ptrs.end());
+ blink::mojom::BlobPtrInfo& blob = *blob_ptr_iter++;
+ http_body.AppendBlob(WebString::FromASCII(element.blob_uuid()),
+ element.length(), blob.PassHandle());
+ }
break;
case network::DataElement::TYPE_DATA_PIPE: {
- // Append the cloned data pipe to the |http_body|. This might not be
- // needed for all callsites today but it respects the constness of
- // |input|, as opposed to moving the data pipe out of |input|.
http_body.AppendDataPipe(
element.CloneDataPipeGetter().PassInterface().PassHandle());
break;
@@ -334,6 +346,25 @@ WebHTTPBody GetWebHTTPBodyForRequestBody(
return http_body;
}
+std::vector<blink::mojom::BlobPtrInfo> GetBlobPtrsForRequestBody(
+ const network::ResourceRequestBody& input) {
+ std::vector<blink::mojom::BlobPtrInfo> blob_ptrs;
+ blink::mojom::BlobRegistryPtr blob_registry;
+ for (auto& element : *input.elements()) {
+ if (element.type() == network::DataElement::TYPE_BLOB) {
+ blink::mojom::BlobPtrInfo blob_ptr;
+ if (!blob_registry) {
+ blink::Platform::Current()->GetInterfaceProvider()->GetInterface(
+ mojo::MakeRequest(&blob_registry));
+ }
+ blob_registry->GetBlobFromUUID(mojo::MakeRequest(&blob_ptr),
+ element.blob_uuid());
+ blob_ptrs.push_back(std::move(blob_ptr));
+ }
+ }
+ return blob_ptrs;
+}
+
scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebURLRequest(
const WebURLRequest& request) {
scoped_refptr<network::ResourceRequestBody> request_body;
@@ -390,7 +421,8 @@ scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody(
request_body->AppendDataPipe(std::move(data_pipe_getter_ptr));
} else {
- request_body->AppendBlob(element.blob_uuid.Utf8());
+ request_body->AppendBlob(element.blob_uuid.Utf8(),
+ element.blob_length);
}
break;
}
diff --git a/chromium/content/renderer/loader/web_url_request_util.h b/chromium/content/renderer/loader/web_url_request_util.h
index dd42dcb240e..bc85bb64d15 100644
--- a/chromium/content/renderer/loader/web_url_request_util.h
+++ b/chromium/content/renderer/loader/web_url_request_util.h
@@ -13,6 +13,7 @@
#include "net/http/http_request_headers.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
+#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -40,6 +41,19 @@ int GetLoadFlagsForWebURLRequest(const blink::WebURLRequest& request);
blink::WebHTTPBody GetWebHTTPBodyForRequestBody(
const network::ResourceRequestBody& input);
+// Takes a ResourceRequestBody with additional |blob_ptrs| which corresponds to
+// each Blob entries, and converts into WebHTTPBody.
+// TODO(kinuko): Remove this once Network Service is shipped.
+blink::WebHTTPBody GetWebHTTPBodyForRequestBodyWithBlobPtrs(
+ const network::ResourceRequestBody& input,
+ std::vector<blink::mojom::BlobPtrInfo> blob_ptrs);
+
+// Takes a ResourceRequestBody and gets blob pointers for Blob entries.
+// Used only in non-NetworkService cases but with S13nServiceWorker.
+// TODO(kinuko): Remove this once Network Service is shipped.
+std::vector<blink::mojom::BlobPtrInfo> GetBlobPtrsForRequestBody(
+ const network::ResourceRequestBody& input);
+
// Takes a WebHTTPBody and converts into a ResourceRequestBody.
scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody(
const blink::WebHTTPBody& httpBody);
diff --git a/chromium/content/renderer/manifest/manifest_manager.cc b/chromium/content/renderer/manifest/manifest_manager.cc
index 32868f6bf99..9e83891ab48 100644
--- a/chromium/content/renderer/manifest/manifest_manager.cc
+++ b/chromium/content/renderer/manifest/manifest_manager.cc
@@ -47,7 +47,7 @@ ManifestManager::~ManifestManager() {
void ManifestManager::RequestManifest(RequestManifestCallback callback) {
RequestManifestImpl(base::BindOnce(
[](RequestManifestCallback callback, const GURL& manifest_url,
- const Manifest& manifest,
+ const blink::Manifest& manifest,
const blink::mojom::ManifestDebugInfo* debug_info) {
std::move(callback).Run(manifest_url, manifest);
},
@@ -58,7 +58,7 @@ void ManifestManager::RequestManifestDebugInfo(
RequestManifestDebugInfoCallback callback) {
RequestManifestImpl(base::BindOnce(
[](RequestManifestDebugInfoCallback callback, const GURL& manifest_url,
- const Manifest& manifest,
+ const blink::Manifest& manifest,
const blink::mojom::ManifestDebugInfo* debug_info) {
std::move(callback).Run(manifest_url,
debug_info ? debug_info->Clone() : nullptr);
@@ -69,7 +69,7 @@ void ManifestManager::RequestManifestDebugInfo(
void ManifestManager::RequestManifestImpl(
InternalRequestManifestCallback callback) {
if (!may_have_manifest_) {
- std::move(callback).Run(GURL(), Manifest(), nullptr);
+ std::move(callback).Run(GURL(), blink::Manifest(), nullptr);
return;
}
@@ -190,7 +190,7 @@ void ManifestManager::ResolveCallbacks(ResolveState state) {
// |manifest_url| will be reset on navigation or if we receive a didchange
// event.
if (state == ResolveStateFailure)
- manifest_ = Manifest();
+ manifest_ = blink::Manifest();
manifest_dirty_ = state != ResolveStateSuccess;
diff --git a/chromium/content/renderer/manifest/manifest_manager.h b/chromium/content/renderer/manifest/manifest_manager.h
index b6799d46643..67d2d374607 100644
--- a/chromium/content/renderer/manifest/manifest_manager.h
+++ b/chromium/content/renderer/manifest/manifest_manager.h
@@ -12,10 +12,10 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "content/public/common/manifest.h"
#include "content/public/renderer/render_frame_observer.h"
#include "mojo/public/cpp/bindings/binding_set.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
class GURL;
@@ -55,7 +55,7 @@ class ManifestManager : public RenderFrameObserver,
using InternalRequestManifestCallback =
base::OnceCallback<void(const GURL&,
- const Manifest&,
+ const blink::Manifest&,
const blink::mojom::ManifestDebugInfo*)>;
// RenderFrameObserver implementation.
@@ -86,7 +86,7 @@ class ManifestManager : public RenderFrameObserver,
bool manifest_dirty_;
// Current Manifest. Might be outdated if manifest_dirty_ is true.
- Manifest manifest_;
+ blink::Manifest manifest_;
// The URL of the current manifest.
GURL manifest_url_;
diff --git a/chromium/content/renderer/manifest/manifest_parser.cc b/chromium/content/renderer/manifest/manifest_parser.cc
index 3f4a29fb8b9..21f715cbf0d 100644
--- a/chromium/content/renderer/manifest/manifest_parser.cc
+++ b/chromium/content/renderer/manifest/manifest_parser.cc
@@ -13,15 +13,14 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
-#include "content/public/common/manifest.h"
-#include "content/public/common/manifest_share_target_util.h"
#include "content/public/common/manifest_util.h"
#include "content/renderer/manifest/manifest_uma_util.h"
-#include "third_party/blink/public/platform/web_color.h"
+#include "third_party/blink/public/common/manifest/manifest_share_target_util.h"
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_css_parser.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/size.h"
namespace content {
@@ -81,7 +80,7 @@ void ManifestParser::Parse() {
ManifestUmaUtil::ParseSucceeded(manifest_);
}
-const Manifest& ManifestParser::manifest() const {
+const blink::Manifest& ManifestParser::manifest() const {
return manifest_;
}
@@ -130,28 +129,23 @@ base::NullableString16 ManifestParser::ParseString(
return base::NullableString16(value, false);
}
-int64_t ManifestParser::ParseColor(
+base::Optional<SkColor> ManifestParser::ParseColor(
const base::DictionaryValue& dictionary,
const std::string& key) {
base::NullableString16 parsed_color = ParseString(dictionary, key, Trim);
if (parsed_color.is_null())
- return Manifest::kInvalidOrMissingColor;
+ return base::nullopt;
- blink::WebColor color;
+ SkColor color;
if (!blink::WebCSSParser::ParseColor(
&color, blink::WebString::FromUTF16(parsed_color.string()))) {
AddErrorInfo("property '" + key + "' ignored, '" +
base::UTF16ToUTF8(parsed_color.string()) + "' is not a " +
"valid color.");
- return Manifest::kInvalidOrMissingColor;
+ return base::nullopt;
}
- // We do this here because Java does not have an unsigned int32_t type so
- // colors with high alpha values will be negative. Instead of doing the
- // conversion after we pass over to Java, we do it here as it is easier and
- // clearer.
- int32_t signed_color = reinterpret_cast<int32_t&>(color);
- return static_cast<int64_t>(signed_color);
+ return color;
}
GURL ManifestParser::ParseURL(const base::DictionaryValue& dictionary,
@@ -283,13 +277,13 @@ std::vector<gfx::Size> ManifestParser::ParseIconSizes(
return sizes;
}
-std::vector<Manifest::Icon::IconPurpose> ManifestParser::ParseIconPurpose(
- const base::DictionaryValue& icon) {
+std::vector<blink::Manifest::Icon::IconPurpose>
+ManifestParser::ParseIconPurpose(const base::DictionaryValue& icon) {
base::NullableString16 purpose_str = ParseString(icon, "purpose", NoTrim);
- std::vector<Manifest::Icon::IconPurpose> purposes;
+ std::vector<blink::Manifest::Icon::IconPurpose> purposes;
if (purpose_str.is_null()) {
- purposes.push_back(Manifest::Icon::IconPurpose::ANY);
+ purposes.push_back(blink::Manifest::Icon::IconPurpose::ANY);
return purposes;
}
@@ -298,9 +292,9 @@ std::vector<Manifest::Icon::IconPurpose> ManifestParser::ParseIconPurpose(
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
for (const base::string16& keyword : keywords) {
if (base::LowerCaseEqualsASCII(keyword, "any")) {
- purposes.push_back(Manifest::Icon::IconPurpose::ANY);
+ purposes.push_back(blink::Manifest::Icon::IconPurpose::ANY);
} else if (base::LowerCaseEqualsASCII(keyword, "badge")) {
- purposes.push_back(Manifest::Icon::IconPurpose::BADGE);
+ purposes.push_back(blink::Manifest::Icon::IconPurpose::BADGE);
} else {
AddErrorInfo(
"found icon with invalid purpose. "
@@ -309,15 +303,15 @@ std::vector<Manifest::Icon::IconPurpose> ManifestParser::ParseIconPurpose(
}
if (purposes.empty()) {
- purposes.push_back(Manifest::Icon::IconPurpose::ANY);
+ purposes.push_back(blink::Manifest::Icon::IconPurpose::ANY);
}
return purposes;
}
-std::vector<Manifest::Icon> ManifestParser::ParseIcons(
+std::vector<blink::Manifest::Icon> ManifestParser::ParseIcons(
const base::DictionaryValue& dictionary) {
- std::vector<Manifest::Icon> icons;
+ std::vector<blink::Manifest::Icon> icons;
if (!dictionary.HasKey("icons"))
return icons;
@@ -332,7 +326,7 @@ std::vector<Manifest::Icon> ManifestParser::ParseIcons(
if (!icons_list->GetDictionary(i, &icon_dictionary))
continue;
- Manifest::Icon icon;
+ blink::Manifest::Icon icon;
icon.src = ParseIconSrc(*icon_dictionary);
// An icon MUST have a valid src. If it does not, it MUST be ignored.
if (!icon.src.is_valid())
@@ -351,7 +345,7 @@ GURL ManifestParser::ParseShareTargetURLTemplate(
const base::DictionaryValue& share_target) {
GURL url_template = ParseURL(share_target, "url_template", manifest_url_,
ParseURLOriginRestrictions::kSameOriginOnly);
- if (!ValidateWebShareUrlTemplate(url_template)) {
+ if (!blink::ValidateWebShareUrlTemplate(url_template)) {
AddErrorInfo(
"property 'url_template' ignored. Placeholders have incorrect "
"syntax.");
@@ -361,19 +355,19 @@ GURL ManifestParser::ParseShareTargetURLTemplate(
return url_template;
}
-base::Optional<Manifest::ShareTarget> ManifestParser::ParseShareTarget(
+base::Optional<blink::Manifest::ShareTarget> ManifestParser::ParseShareTarget(
const base::DictionaryValue& dictionary) {
if (!dictionary.HasKey("share_target"))
return base::nullopt;
- Manifest::ShareTarget share_target;
+ blink::Manifest::ShareTarget share_target;
const base::DictionaryValue* share_target_dict = nullptr;
dictionary.GetDictionary("share_target", &share_target_dict);
share_target.url_template = ParseShareTargetURLTemplate(*share_target_dict);
if (share_target.url_template.is_empty())
return base::nullopt;
- return base::Optional<Manifest::ShareTarget>(share_target);
+ return base::Optional<blink::Manifest::ShareTarget>(share_target);
}
base::NullableString16 ManifestParser::ParseRelatedApplicationPlatform(
@@ -392,10 +386,10 @@ base::NullableString16 ManifestParser::ParseRelatedApplicationId(
return ParseString(application, "id", Trim);
}
-std::vector<Manifest::RelatedApplication>
+std::vector<blink::Manifest::RelatedApplication>
ManifestParser::ParseRelatedApplications(
const base::DictionaryValue& dictionary) {
- std::vector<Manifest::RelatedApplication> applications;
+ std::vector<blink::Manifest::RelatedApplication> applications;
if (!dictionary.HasKey("related_applications"))
return applications;
@@ -411,7 +405,7 @@ ManifestParser::ParseRelatedApplications(
if (!applications_list->GetDictionary(i, &application_dictionary))
continue;
- Manifest::RelatedApplication application;
+ blink::Manifest::RelatedApplication application;
application.platform =
ParseRelatedApplicationPlatform(*application_dictionary);
// "If platform is undefined, move onto the next item if any are left."
@@ -442,12 +436,12 @@ bool ManifestParser::ParsePreferRelatedApplications(
return ParseBoolean(dictionary, "prefer_related_applications", false);
}
-int64_t ManifestParser::ParseThemeColor(
+base::Optional<SkColor> ManifestParser::ParseThemeColor(
const base::DictionaryValue& dictionary) {
return ParseColor(dictionary, "theme_color");
}
-int64_t ManifestParser::ParseBackgroundColor(
+base::Optional<SkColor> ManifestParser::ParseBackgroundColor(
const base::DictionaryValue& dictionary) {
return ParseColor(dictionary, "background_color");
}
diff --git a/chromium/content/renderer/manifest/manifest_parser.h b/chromium/content/renderer/manifest/manifest_parser.h
index 7e0cb7dfae2..a456754390f 100644
--- a/chromium/content/renderer/manifest/manifest_parser.h
+++ b/chromium/content/renderer/manifest/manifest_parser.h
@@ -14,8 +14,9 @@
#include "base/strings/nullable_string16.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
-#include "content/public/common/manifest.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest.mojom.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
+#include "third_party/skia/include/core/SkColor.h"
class GURL;
@@ -39,7 +40,7 @@ class CONTENT_EXPORT ManifestParser {
// http://w3c.github.io/manifest/#dfn-steps-for-processing-a-manifest
void Parse();
- const Manifest& manifest() const;
+ const blink::Manifest& manifest() const;
bool failed() const;
void TakeErrors(std::vector<blink::mojom::ManifestErrorPtr>* errors);
@@ -72,11 +73,10 @@ class CONTENT_EXPORT ManifestParser {
TrimType trim);
// Helper function to parse colors present on a given |dictionary| in a given
- // field identified by its |key|.
- // Returns the parsed color as an int64_t if any,
- // Manifest::kInvalidOrMissingColor if the parsing failed.
- int64_t ParseColor(const base::DictionaryValue& dictionary,
- const std::string& key);
+ // field identified by its |key|. Returns a null optional if the value is not
+ // present or is not a valid color.
+ base::Optional<SkColor> ParseColor(const base::DictionaryValue& dictionary,
+ const std::string& key);
// Helper function to parse URLs present on a given |dictionary| in a given
// field identified by its |key|. The URL is first parsed as a string then
@@ -146,14 +146,14 @@ class CONTENT_EXPORT ManifestParser {
// Returns a vector of Manifest::Icon::IconPurpose with the successfully
// parsed icon purposes, and a vector with Manifest::Icon::IconPurpose::Any if
// the parsing failed.
- std::vector<Manifest::Icon::IconPurpose> ParseIconPurpose(
+ std::vector<blink::Manifest::Icon::IconPurpose> ParseIconPurpose(
const base::DictionaryValue& icon);
// Parses the 'icons' field of a Manifest, as defined in:
// https://w3c.github.io/manifest/#dfn-steps-for-processing-an-array-of-images
// Returns a vector of Manifest::Icon with the successfully parsed icons, if
// any. An empty vector if the field was not present or empty.
- std::vector<Manifest::Icon> ParseIcons(
+ std::vector<blink::Manifest::Icon> ParseIcons(
const base::DictionaryValue& dictionary);
// Parses the 'url_template' field of a Share Target, as defined in:
@@ -165,7 +165,7 @@ class CONTENT_EXPORT ManifestParser {
// https://github.com/WICG/web-share-target/blob/master/docs/interface.md
// Returns the parsed Web Share target. The returned Share Target is null if
// the field didn't exist, parsing failed, or it was empty.
- base::Optional<Manifest::ShareTarget> ParseShareTarget(
+ base::Optional<blink::Manifest::ShareTarget> ParseShareTarget(
const base::DictionaryValue& dictionary);
// Parses the 'platform' field of a related application, as defined in:
@@ -190,7 +190,7 @@ class CONTENT_EXPORT ManifestParser {
// Returns a vector of Manifest::RelatedApplication with the successfully
// parsed applications, if any. An empty vector if the field was not present
// or empty.
- std::vector<Manifest::RelatedApplication> ParseRelatedApplications(
+ std::vector<blink::Manifest::RelatedApplication> ParseRelatedApplications(
const base::DictionaryValue& dictionary);
// Parses the 'prefer_related_applications' field on the manifest, as defined
@@ -201,15 +201,15 @@ class CONTENT_EXPORT ManifestParser {
// Parses the 'theme_color' field of the manifest, as defined in:
// https://w3c.github.io/manifest/#dfn-steps-for-processing-the-theme_color-member
- // Returns the parsed theme color if any,
- // Manifest::kInvalidOrMissingColor if the parsing failed.
- int64_t ParseThemeColor(const base::DictionaryValue& dictionary);
+ // Returns the parsed theme color if any, or a null optional otherwise.
+ base::Optional<SkColor> ParseThemeColor(
+ const base::DictionaryValue& dictionary);
// Parses the 'background_color' field of the manifest, as defined in:
// https://w3c.github.io/manifest/#dfn-steps-for-processing-the-background_color-member
- // Returns the parsed background color if any,
- // Manifest::kInvalidOrMissingColor if the parsing failed.
- int64_t ParseBackgroundColor(const base::DictionaryValue& dictionary);
+ // Returns the parsed background color if any, or a null optional otherwise.
+ base::Optional<SkColor> ParseBackgroundColor(
+ const base::DictionaryValue& dictionary);
// Parses the 'splash_screen_url' field of the manifest.
// Returns the parsed GURL if any, an empty GURL if the parsing failed.
@@ -231,7 +231,7 @@ class CONTENT_EXPORT ManifestParser {
GURL document_url_;
bool failed_;
- Manifest manifest_;
+ blink::Manifest manifest_;
std::vector<blink::mojom::ManifestErrorPtr> errors_;
DISALLOW_COPY_AND_ASSIGN(ManifestParser);
diff --git a/chromium/content/renderer/manifest/manifest_parser_unittest.cc b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
index db1768db351..016020e6f17 100644
--- a/chromium/content/renderer/manifest/manifest_parser_unittest.cc
+++ b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
@@ -11,27 +11,19 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string_util.h"
-#include "content/public/common/manifest.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
namespace content {
-namespace {
-
-uint32_t ExtractColor(int64_t color) {
- return reinterpret_cast<uint32_t&>(color);
-}
-
-} // anonymous namespace
-
class ManifestParserTest : public testing::Test {
protected:
ManifestParserTest() {}
~ManifestParserTest() override {}
- Manifest ParseManifestWithURLs(const base::StringPiece& data,
- const GURL& manifest_url,
- const GURL& document_url) {
+ blink::Manifest ParseManifestWithURLs(const base::StringPiece& data,
+ const GURL& manifest_url,
+ const GURL& document_url) {
ManifestParser parser(data, manifest_url, document_url);
parser.Parse();
std::vector<blink::mojom::ManifestErrorPtr> errors;
@@ -43,7 +35,7 @@ class ManifestParserTest : public testing::Test {
return parser.manifest();
}
- Manifest ParseManifest(const base::StringPiece& data) {
+ blink::Manifest ParseManifest(const base::StringPiece& data) {
return ParseManifestWithURLs(
data, default_manifest_url, default_document_url);
}
@@ -85,7 +77,7 @@ TEST_F(ManifestParserTest, CrashTest) {
}
TEST_F(ManifestParserTest, EmptyStringNull) {
- Manifest manifest = ParseManifest("");
+ blink::Manifest manifest = ParseManifest("");
// This Manifest is not a valid JSON object, it's a parsing error.
EXPECT_EQ(1u, GetErrorCount());
@@ -99,15 +91,15 @@ TEST_F(ManifestParserTest, EmptyStringNull) {
ASSERT_TRUE(manifest.start_url.is_empty());
ASSERT_EQ(manifest.display, blink::kWebDisplayModeUndefined);
ASSERT_EQ(manifest.orientation, blink::kWebScreenOrientationLockDefault);
- ASSERT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
- ASSERT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ ASSERT_FALSE(manifest.theme_color.has_value());
+ ASSERT_FALSE(manifest.background_color.has_value());
ASSERT_TRUE(manifest.splash_screen_url.is_empty());
ASSERT_TRUE(manifest.gcm_sender_id.is_null());
ASSERT_TRUE(manifest.scope.is_empty());
}
TEST_F(ManifestParserTest, ValidNoContentParses) {
- Manifest manifest = ParseManifest("{}");
+ blink::Manifest manifest = ParseManifest("{}");
// Empty Manifest is not a parsing error.
EXPECT_EQ(0u, GetErrorCount());
@@ -119,15 +111,16 @@ TEST_F(ManifestParserTest, ValidNoContentParses) {
ASSERT_TRUE(manifest.start_url.is_empty());
ASSERT_EQ(manifest.display, blink::kWebDisplayModeUndefined);
ASSERT_EQ(manifest.orientation, blink::kWebScreenOrientationLockDefault);
- ASSERT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
- ASSERT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ ASSERT_FALSE(manifest.theme_color.has_value());
+ ASSERT_FALSE(manifest.background_color.has_value());
ASSERT_TRUE(manifest.splash_screen_url.is_empty());
ASSERT_TRUE(manifest.gcm_sender_id.is_null());
ASSERT_TRUE(manifest.scope.is_empty());
}
TEST_F(ManifestParserTest, MultipleErrorsReporting) {
- Manifest manifest = ParseManifest("{ \"name\": 42, \"short_name\": 4,"
+ blink::Manifest manifest = ParseManifest(
+ "{ \"name\": 42, \"short_name\": 4,"
"\"orientation\": {}, \"display\": \"foo\","
"\"start_url\": null, \"icons\": {}, \"theme_color\": 42,"
"\"background_color\": 42 }");
@@ -155,7 +148,7 @@ TEST_F(ManifestParserTest, MultipleErrorsReporting) {
TEST_F(ManifestParserTest, NameParseRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"name\": \"foo\" }");
+ blink::Manifest manifest = ParseManifest("{ \"name\": \"foo\" }");
ASSERT_TRUE(base::EqualsASCII(manifest.name.string(), "foo"));
ASSERT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -163,14 +156,14 @@ TEST_F(ManifestParserTest, NameParseRules) {
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"name\": \" foo \" }");
+ blink::Manifest manifest = ParseManifest("{ \"name\": \" foo \" }");
ASSERT_TRUE(base::EqualsASCII(manifest.name.string(), "foo"));
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"name\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"name\": {} }");
ASSERT_TRUE(manifest.name.is_null());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' ignored, type string expected.",
@@ -179,7 +172,7 @@ TEST_F(ManifestParserTest, NameParseRules) {
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"name\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"name\": 42 }");
ASSERT_TRUE(manifest.name.is_null());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'name' ignored, type string expected.",
@@ -190,7 +183,7 @@ TEST_F(ManifestParserTest, NameParseRules) {
TEST_F(ManifestParserTest, ShortNameParseRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"short_name\": \"foo\" }");
+ blink::Manifest manifest = ParseManifest("{ \"short_name\": \"foo\" }");
ASSERT_TRUE(base::EqualsASCII(manifest.short_name.string(), "foo"));
ASSERT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -198,14 +191,14 @@ TEST_F(ManifestParserTest, ShortNameParseRules) {
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"short_name\": \" foo \" }");
+ blink::Manifest manifest = ParseManifest("{ \"short_name\": \" foo \" }");
ASSERT_TRUE(base::EqualsASCII(manifest.short_name.string(), "foo"));
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"short_name\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"short_name\": {} }");
ASSERT_TRUE(manifest.short_name.is_null());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'short_name' ignored, type string expected.",
@@ -214,7 +207,7 @@ TEST_F(ManifestParserTest, ShortNameParseRules) {
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"short_name\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"short_name\": 42 }");
ASSERT_TRUE(manifest.short_name.is_null());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'short_name' ignored, type string expected.",
@@ -225,7 +218,8 @@ TEST_F(ManifestParserTest, ShortNameParseRules) {
TEST_F(ManifestParserTest, StartURLParseRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"start_url\": \"land.html\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"start_url\": \"land.html\" }");
ASSERT_EQ(manifest.start_url.spec(),
default_document_url.Resolve("land.html").spec());
ASSERT_FALSE(manifest.IsEmpty());
@@ -234,7 +228,8 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Whitespaces.
{
- Manifest manifest = ParseManifest("{ \"start_url\": \" land.html \" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"start_url\": \" land.html \" }");
ASSERT_EQ(manifest.start_url.spec(),
default_document_url.Resolve("land.html").spec());
EXPECT_EQ(0u, GetErrorCount());
@@ -242,7 +237,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"start_url\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"start_url\": {} }");
ASSERT_TRUE(manifest.start_url.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'start_url' ignored, type string expected.",
@@ -251,7 +246,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"start_url\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"start_url\": 42 }");
ASSERT_TRUE(manifest.start_url.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'start_url' ignored, type string expected.",
@@ -260,7 +255,8 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Don't parse if property isn't a valid URL.
{
- Manifest manifest = ParseManifest("{ \"start_url\": \"http://www.google.ca:a\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"start_url\": \"http://www.google.ca:a\" }");
ASSERT_TRUE(manifest.start_url.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'start_url' ignored, URL is invalid.", errors()[0]);
@@ -268,7 +264,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Absolute start_url, same origin with document.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifestWithURLs("{ \"start_url\": \"http://foo.com/land.html\" }",
GURL("http://foo.com/manifest.json"),
GURL("http://foo.com/index.html"));
@@ -278,7 +274,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Absolute start_url, cross origin with document.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifestWithURLs("{ \"start_url\": \"http://bar.com/land.html\" }",
GURL("http://foo.com/manifest.json"),
GURL("http://foo.com/index.html"));
@@ -291,7 +287,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
// Resolving has to happen based on the manifest_url.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifestWithURLs("{ \"start_url\": \"land.html\" }",
GURL("http://foo.com/landing/manifest.json"),
GURL("http://foo.com/index.html"));
@@ -303,7 +299,7 @@ TEST_F(ManifestParserTest, StartURLParseRules) {
TEST_F(ManifestParserTest, ScopeParseRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"scope\": \"land\", \"start_url\": \"land/landing.html\" }");
ASSERT_EQ(manifest.scope.spec(),
default_document_url.Resolve("land").spec());
@@ -313,7 +309,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Whitespaces.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"scope\": \" land \", \"start_url\": \"land/landing.html\" }");
ASSERT_EQ(manifest.scope.spec(),
default_document_url.Resolve("land").spec());
@@ -322,7 +318,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"scope\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"scope\": {} }");
ASSERT_TRUE(manifest.scope.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
@@ -330,7 +326,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"scope\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"scope\": 42 }");
ASSERT_TRUE(manifest.scope.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
@@ -338,7 +334,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Absolute scope, start URL is in scope.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"scope\": \"http://foo.com/land\", "
"\"start_url\": \"http://foo.com/land/landing.html\" }",
GURL("http://foo.com/manifest.json"),
@@ -349,11 +345,11 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Absolute scope, start URL is not in scope.
{
- Manifest manifest =
- ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\", "
- "\"start_url\": \"http://foo.com/index.html\" }",
- GURL("http://foo.com/manifest.json"),
- GURL("http://foo.com/index.html"));
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"http://foo.com/land\", "
+ "\"start_url\": \"http://foo.com/index.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
ASSERT_TRUE(manifest.scope.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'scope' ignored. Start url should be within scope "
@@ -363,11 +359,11 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Absolute scope, start URL has different origin than scope URL.
{
- Manifest manifest =
- ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\", "
- "\"start_url\": \"http://bar.com/land/landing.html\" }",
- GURL("http://foo.com/manifest.json"),
- GURL("http://foo.com/index.html"));
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"http://foo.com/land\", "
+ "\"start_url\": \"http://bar.com/land/landing.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
ASSERT_TRUE(manifest.scope.is_empty());
ASSERT_EQ(2u, GetErrorCount());
EXPECT_EQ(
@@ -380,11 +376,11 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// scope and start URL have diferent origin than document URL.
{
- Manifest manifest =
- ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\", "
- "\"start_url\": \"http://foo.com/land/landing.html\" }",
- GURL("http://foo.com/manifest.json"),
- GURL("http://bar.com/index.html"));
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"http://foo.com/land\", "
+ "\"start_url\": \"http://foo.com/land/landing.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://bar.com/index.html"));
ASSERT_TRUE(manifest.scope.is_empty());
ASSERT_EQ(2u, GetErrorCount());
EXPECT_EQ(
@@ -396,18 +392,20 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// No start URL. Document URL is in scope.
{
- Manifest manifest = ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
- GURL("http://foo.com/manifest.json"),
- GURL("http://foo.com/land/index.html"));
+ blink::Manifest manifest =
+ ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/land/index.html"));
ASSERT_EQ(manifest.scope.spec(), "http://foo.com/land");
ASSERT_EQ(0u, GetErrorCount());
}
// No start URL. Document is out of scope.
{
- Manifest manifest = ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
- GURL("http://foo.com/manifest.json"),
- GURL("http://foo.com/index.html"));
+ blink::Manifest manifest =
+ ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'scope' ignored. Start url should be within scope "
"of scope URL.",
@@ -416,9 +414,8 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Resolving has to happen based on the manifest_url.
{
- Manifest manifest = ParseManifestWithURLs(
- "{ \"scope\": \"treasure\" }",
- GURL("http://foo.com/map/manifest.json"),
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"treasure\" }", GURL("http://foo.com/map/manifest.json"),
GURL("http://foo.com/map/treasure/island/index.html"));
ASSERT_EQ(manifest.scope.spec(), "http://foo.com/map/treasure");
EXPECT_EQ(0u, GetErrorCount());
@@ -426,20 +423,18 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
// Scope is parent directory.
{
- Manifest manifest =
- ParseManifestWithURLs("{ \"scope\": \"..\" }",
- GURL("http://foo.com/map/manifest.json"),
- GURL("http://foo.com/index.html"));
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"..\" }", GURL("http://foo.com/map/manifest.json"),
+ GURL("http://foo.com/index.html"));
ASSERT_EQ(manifest.scope.spec(), "http://foo.com/");
EXPECT_EQ(0u, GetErrorCount());
}
// Scope tries to go up past domain.
{
- Manifest manifest =
- ParseManifestWithURLs("{ \"scope\": \"../..\" }",
- GURL("http://foo.com/map/manifest.json"),
- GURL("http://foo.com/index.html"));
+ blink::Manifest manifest = ParseManifestWithURLs(
+ "{ \"scope\": \"../..\" }", GURL("http://foo.com/map/manifest.json"),
+ GURL("http://foo.com/index.html"));
ASSERT_EQ(manifest.scope.spec(), "http://foo.com/");
EXPECT_EQ(0u, GetErrorCount());
}
@@ -448,7 +443,7 @@ TEST_F(ManifestParserTest, ScopeParseRules) {
TEST_F(ManifestParserTest, DisplayParserRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeBrowser);
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -456,14 +451,15 @@ TEST_F(ManifestParserTest, DisplayParserRules) {
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"display\": \" browser \" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"display\": \" browser \" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"display\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": {} }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'display' ignored,"
@@ -473,7 +469,7 @@ TEST_F(ManifestParserTest, DisplayParserRules) {
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"display\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": 42 }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'display' ignored,"
@@ -483,7 +479,8 @@ TEST_F(ManifestParserTest, DisplayParserRules) {
// Parse fails if string isn't known.
{
- Manifest manifest = ParseManifest("{ \"display\": \"browser_something\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"display\": \"browser_something\" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("unknown 'display' value ignored.",
@@ -492,35 +489,35 @@ TEST_F(ManifestParserTest, DisplayParserRules) {
// Accept 'fullscreen'.
{
- Manifest manifest = ParseManifest("{ \"display\": \"fullscreen\" }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": \"fullscreen\" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeFullscreen);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'fullscreen'.
{
- Manifest manifest = ParseManifest("{ \"display\": \"standalone\" }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": \"standalone\" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeStandalone);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'minimal-ui'.
{
- Manifest manifest = ParseManifest("{ \"display\": \"minimal-ui\" }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": \"minimal-ui\" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeMinimalUi);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'browser'.
{
- Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
// Case insensitive.
{
- Manifest manifest = ParseManifest("{ \"display\": \"BROWSER\" }");
+ blink::Manifest manifest = ParseManifest("{ \"display\": \"BROWSER\" }");
EXPECT_EQ(manifest.display, blink::kWebDisplayModeBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
@@ -529,7 +526,8 @@ TEST_F(ManifestParserTest, DisplayParserRules) {
TEST_F(ManifestParserTest, OrientationParserRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"natural\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockNatural);
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -537,14 +535,15 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"natural\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockNatural);
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"orientation\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"orientation\": {} }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockDefault);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'orientation' ignored, type string expected.",
@@ -553,7 +552,7 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Don't parse if name isn't a string.
{
- Manifest manifest = ParseManifest("{ \"orientation\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"orientation\": 42 }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockDefault);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'orientation' ignored, type string expected.",
@@ -562,7 +561,8 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Parse fails if string isn't known.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"naturalish\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"naturalish\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockDefault);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("unknown 'orientation' value ignored.",
@@ -571,28 +571,30 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Accept 'any'.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"any\" }");
+ blink::Manifest manifest = ParseManifest("{ \"orientation\": \"any\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockAny);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'natural'.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"natural\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockNatural);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'landscape'.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"landscape\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"landscape\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockLandscape);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'landscape-primary'.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"orientation\": \"landscape-primary\" }");
EXPECT_EQ(manifest.orientation,
blink::kWebScreenOrientationLockLandscapePrimary);
@@ -601,7 +603,7 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Accept 'landscape-secondary'.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"orientation\": \"landscape-secondary\" }");
EXPECT_EQ(manifest.orientation,
blink::kWebScreenOrientationLockLandscapeSecondary);
@@ -610,15 +612,16 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Accept 'portrait'.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"portrait\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"portrait\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockPortrait);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'portrait-primary'.
{
- Manifest manifest =
- ParseManifest("{ \"orientation\": \"portrait-primary\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"portrait-primary\" }");
EXPECT_EQ(manifest.orientation,
blink::kWebScreenOrientationLockPortraitPrimary);
EXPECT_EQ(0u, GetErrorCount());
@@ -626,7 +629,7 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Accept 'portrait-secondary'.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"orientation\": \"portrait-secondary\" }");
EXPECT_EQ(manifest.orientation,
blink::kWebScreenOrientationLockPortraitSecondary);
@@ -635,7 +638,8 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
// Case insensitive.
{
- Manifest manifest = ParseManifest("{ \"orientation\": \"LANDSCAPE\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"orientation\": \"LANDSCAPE\" }");
EXPECT_EQ(manifest.orientation, blink::kWebScreenOrientationLockLandscape);
EXPECT_EQ(0u, GetErrorCount());
}
@@ -644,7 +648,7 @@ TEST_F(ManifestParserTest, OrientationParserRules) {
TEST_F(ManifestParserTest, IconsParseRules) {
// Smoke test: if no icon, empty list.
{
- Manifest manifest = ParseManifest("{ \"icons\": [] }");
+ blink::Manifest manifest = ParseManifest("{ \"icons\": [] }");
EXPECT_EQ(manifest.icons.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -652,7 +656,7 @@ TEST_F(ManifestParserTest, IconsParseRules) {
// Smoke test: if empty icon, empty list.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {} ] }");
+ blink::Manifest manifest = ParseManifest("{ \"icons\": [ {} ] }");
EXPECT_EQ(manifest.icons.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -660,7 +664,8 @@ TEST_F(ManifestParserTest, IconsParseRules) {
// Smoke test: icon with invalid src, empty list.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ { \"icons\": [] } ] }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"icons\": [ { \"icons\": [] } ] }");
EXPECT_EQ(manifest.icons.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -668,7 +673,8 @@ TEST_F(ManifestParserTest, IconsParseRules) {
// Smoke test: if icon with empty src, it will be present in the list.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ { \"src\": \"\" } ] }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"icons\": [ { \"src\": \"\" } ] }");
EXPECT_EQ(manifest.icons.size(), 1u);
EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/manifest.json");
EXPECT_FALSE(manifest.IsEmpty());
@@ -677,7 +683,7 @@ TEST_F(ManifestParserTest, IconsParseRules) {
// Smoke test: if one icons with valid src, it will be present in the list.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"icons\": [{ \"src\": \"foo.jpg\" }] }");
EXPECT_EQ(manifest.icons.size(), 1u);
EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/foo.jpg");
@@ -689,7 +695,7 @@ TEST_F(ManifestParserTest, IconsParseRules) {
TEST_F(ManifestParserTest, IconSrcParseRules) {
// Smoke test.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"icons\": [ {\"src\": \"foo.png\" } ] }");
EXPECT_EQ(manifest.icons[0].src.spec(),
default_document_url.Resolve("foo.png").spec());
@@ -698,7 +704,7 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Whitespaces.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"icons\": [ {\"src\": \" foo.png \" } ] }");
EXPECT_EQ(manifest.icons[0].src.spec(),
default_document_url.Resolve("foo.png").spec());
@@ -707,7 +713,8 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": {} } ] }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": {} } ] }");
EXPECT_TRUE(manifest.icons.empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'src' ignored, type string expected.",
@@ -716,7 +723,8 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": 42 } ] }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": 42 } ] }");
EXPECT_TRUE(manifest.icons.empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'src' ignored, type string expected.",
@@ -725,10 +733,9 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
// Resolving has to happen based on the document_url.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"icons\": [ {\"src\": \"icons/foo.png\" } ] }",
- GURL("http://foo.com/landing/index.html"),
- default_manifest_url);
+ GURL("http://foo.com/landing/index.html"), default_manifest_url);
EXPECT_EQ(manifest.icons[0].src.spec(),
"http://foo.com/landing/icons/foo.png");
EXPECT_EQ(0u, GetErrorCount());
@@ -738,7 +745,7 @@ TEST_F(ManifestParserTest, IconSrcParseRules) {
TEST_F(ManifestParserTest, IconTypeParseRules) {
// Smoke test.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": \"foo\" } ] }");
EXPECT_TRUE(base::EqualsASCII(manifest.icons[0].type, "foo"));
EXPECT_EQ(0u, GetErrorCount());
@@ -746,15 +753,16 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
- " \"type\": \" foo \" } ] }");
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
+ " \"type\": \" foo \" } ] }");
EXPECT_TRUE(base::EqualsASCII(manifest.icons[0].type, "foo"));
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if property isn't a string.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": {} } ] }");
EXPECT_TRUE(manifest.icons[0].type.empty());
EXPECT_EQ(1u, GetErrorCount());
@@ -764,7 +772,7 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": 42 } ] }");
EXPECT_TRUE(manifest.icons[0].type.empty());
EXPECT_EQ(1u, GetErrorCount());
@@ -776,7 +784,8 @@ TEST_F(ManifestParserTest, IconTypeParseRules) {
TEST_F(ManifestParserTest, IconSizesParseRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"42x42\" } ] }");
EXPECT_EQ(manifest.icons[0].sizes.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -784,7 +793,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \" 42x42 \" } ] }");
EXPECT_EQ(manifest.icons[0].sizes.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -792,7 +802,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Ignore sizes if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": {} } ] }");
EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -802,7 +813,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Ignore sizes if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": 42 } ] }");
EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -812,7 +824,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Smoke test: value correctly parsed.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"42x42 48x48\" } ] }");
EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(48, 48));
@@ -821,7 +834,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// <WIDTH>'x'<HEIGHT> and <WIDTH>'X'<HEIGHT> are equivalent.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"42X42 48X48\" } ] }");
EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(48, 48));
@@ -830,7 +844,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Twice the same value is parsed twice.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"42X42 42x42\" } ] }");
EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(42, 42));
@@ -839,7 +854,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Width or height can't start with 0.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"004X007 042x00\" } ] }");
EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -849,7 +865,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Width and height MUST contain digits.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"e4X1.0 55ax1e10\" } ] }");
EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -859,7 +876,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// 'any' is correctly parsed and transformed to gfx::Size(0,0).
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"any AnY ANY aNy\" } ] }");
gfx::Size any = gfx::Size(0, 0);
EXPECT_EQ(manifest.icons[0].sizes.size(), 4u);
@@ -872,7 +890,8 @@ TEST_F(ManifestParserTest, IconSizesParseRules) {
// Some invalid width/height combinations.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"sizes\": \"x 40xx 1x2x3 x42 42xx42\" } ] }");
EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
EXPECT_EQ(1u, GetErrorCount());
@@ -890,7 +909,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": \"any\" } ] }");
EXPECT_EQ(manifest.icons[0].purpose.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -898,7 +918,8 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// Trim leading and trailing whitespaces.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": \" any \" } ] }");
EXPECT_EQ(manifest.icons[0].purpose.size(), 1u);
EXPECT_EQ(0u, GetErrorCount());
@@ -906,19 +927,23 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// 'any' is added when property isn't present.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\" } ] }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\" } ] }");
EXPECT_EQ(manifest.icons[0].purpose.size(), 1u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::ANY);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::ANY);
EXPECT_EQ(0u, GetErrorCount());
}
// 'any' is added with error message when property isn't a string (is a
// number).
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": 42 } ] }");
EXPECT_EQ(manifest.icons[0].purpose.size(), 1u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::ANY);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::ANY);
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ(kPurposeParseStringError, errors()[0]);
}
@@ -926,60 +951,75 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
// 'any' is added with error message when property isn't a string (is a
// dictionary).
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": {} } ] }");
EXPECT_EQ(manifest.icons[0].purpose.size(), 1u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::ANY);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::ANY);
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ(kPurposeParseStringError, errors()[0]);
}
// Smoke test: values correctly parsed.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": \"Any Badge\" } ] }");
ASSERT_EQ(manifest.icons[0].purpose.size(), 2u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::ANY);
- EXPECT_EQ(manifest.icons[0].purpose[1], Manifest::Icon::IconPurpose::BADGE);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::ANY);
+ EXPECT_EQ(manifest.icons[0].purpose[1],
+ blink::Manifest::Icon::IconPurpose::BADGE);
EXPECT_EQ(0u, GetErrorCount());
}
// Trim whitespaces between values.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": \" Any Badge \" } ] }");
ASSERT_EQ(manifest.icons[0].purpose.size(), 2u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::ANY);
- EXPECT_EQ(manifest.icons[0].purpose[1], Manifest::Icon::IconPurpose::BADGE);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::ANY);
+ EXPECT_EQ(manifest.icons[0].purpose[1],
+ blink::Manifest::Icon::IconPurpose::BADGE);
EXPECT_EQ(0u, GetErrorCount());
}
// Twice the same value is parsed twice.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": \"badge badge\" } ] }");
ASSERT_EQ(manifest.icons[0].purpose.size(), 2u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::BADGE);
- EXPECT_EQ(manifest.icons[0].purpose[1], Manifest::Icon::IconPurpose::BADGE);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::BADGE);
+ EXPECT_EQ(manifest.icons[0].purpose[1],
+ blink::Manifest::Icon::IconPurpose::BADGE);
EXPECT_EQ(0u, GetErrorCount());
}
// Invalid icon purpose is ignored.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": \"badge notification\" } ] }");
ASSERT_EQ(manifest.icons[0].purpose.size(), 1u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::BADGE);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::BADGE);
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ(kPurposeInvalidValueError, errors()[0]);
}
// 'any' is added when developer-supplied purpose is invalid.
{
- Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ blink::Manifest manifest = ParseManifest(
+ "{ \"icons\": [ {\"src\": \"\","
"\"purpose\": \"notification\" } ] }");
ASSERT_EQ(manifest.icons[0].purpose.size(), 1u);
- EXPECT_EQ(manifest.icons[0].purpose[0], Manifest::Icon::IconPurpose::ANY);
+ EXPECT_EQ(manifest.icons[0].purpose[0],
+ blink::Manifest::Icon::IconPurpose::ANY);
ASSERT_EQ(1u, GetErrorCount());
EXPECT_EQ(kPurposeInvalidValueError, errors()[0]);
}
@@ -988,7 +1028,7 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) {
TEST_F(ManifestParserTest, ShareTargetParseRules) {
// Contains share_target field but no keys.
{
- Manifest manifest = ParseManifest("{ \"share_target\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"share_target\": {} }");
EXPECT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -996,7 +1036,7 @@ TEST_F(ManifestParserTest, ShareTargetParseRules) {
// Key in share_target that isn't valid.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"share_target\": {\"incorrect_key\": \"some_value\" } }");
ASSERT_FALSE(manifest.share_target.has_value());
EXPECT_TRUE(manifest.IsEmpty());
@@ -1010,7 +1050,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Contains share_target and url_template, but url_template is empty.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": { \"url_template\": \"\" } }", manifest_url,
document_url);
ASSERT_TRUE(manifest.share_target.has_value());
@@ -1022,7 +1062,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifestWithURLs("{ \"share_target\": { \"url_template\": {} } }",
manifest_url, document_url);
EXPECT_FALSE(manifest.share_target.has_value());
@@ -1034,7 +1074,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifestWithURLs("{ \"share_target\": { \"url_template\": 42 } }",
manifest_url, document_url);
EXPECT_FALSE(manifest.share_target.has_value());
@@ -1046,7 +1086,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Don't parse if property isn't a valid URL.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": { \"url_template\": \"https://foo.com:a\" } "
"}",
manifest_url, document_url);
@@ -1059,7 +1099,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Fail parsing if url_template is at a different origin than the Web
// Manifest.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": { \"url_template\": \"https://foo2.com/\" } }",
manifest_url, document_url);
EXPECT_FALSE(manifest.share_target.has_value());
@@ -1073,7 +1113,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Smoke test: Contains share_target and url_template, and url_template is
// valid template.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": {\"url_template\": \"share/?title={title}\" } }",
manifest_url, document_url);
ASSERT_TRUE(manifest.share_target.has_value());
@@ -1086,7 +1126,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Smoke test: Contains share_target and url_template, and url_template is
// invalid template.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": {\"url_template\": \"share/?title={title\" } }",
manifest_url, document_url);
ASSERT_FALSE(manifest.share_target.has_value());
@@ -1101,7 +1141,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Smoke test: Contains share_target and url_template, and url_template
// contains unknown placeholder.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": {\"url_template\": \"share/?title={abcxyz}\" } }",
manifest_url, document_url);
ASSERT_TRUE(manifest.share_target.has_value());
@@ -1115,7 +1155,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// '{' and '}' in path, query and fragment. Only '{' and '}' in path should be
// escaped.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": {\"url_template\": "
"\"share/a{text}/?title={title}#{frag}\" } }",
manifest_url, document_url);
@@ -1129,7 +1169,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
// Smoke test: Contains share_target and url_template. url_template is
// valid template and is absolute.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"share_target\": { \"url_template\": \"https://foo.com/#{text}\" } "
"}",
manifest_url, document_url);
@@ -1144,8 +1184,7 @@ TEST_F(ManifestParserTest, ShareTargetUrlTemplateParseRules) {
TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If no application, empty list.
{
- Manifest manifest = ParseManifest(
- "{ \"related_applications\": []}");
+ blink::Manifest manifest = ParseManifest("{ \"related_applications\": []}");
EXPECT_EQ(manifest.related_applications.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
@@ -1153,8 +1192,8 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If empty application, empty list.
{
- Manifest manifest = ParseManifest(
- "{ \"related_applications\": [{}]}");
+ blink::Manifest manifest =
+ ParseManifest("{ \"related_applications\": [{}]}");
EXPECT_EQ(manifest.related_applications.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
@@ -1164,8 +1203,8 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If invalid platform, application is ignored.
{
- Manifest manifest = ParseManifest(
- "{ \"related_applications\": [{\"platform\": 123}]}");
+ blink::Manifest manifest =
+ ParseManifest("{ \"related_applications\": [{\"platform\": 123}]}");
EXPECT_EQ(manifest.related_applications.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(2u, GetErrorCount());
@@ -1179,8 +1218,8 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If missing platform, application is ignored.
{
- Manifest manifest = ParseManifest(
- "{ \"related_applications\": [{\"id\": \"foo\"}]}");
+ blink::Manifest manifest =
+ ParseManifest("{ \"related_applications\": [{\"id\": \"foo\"}]}");
EXPECT_EQ(manifest.related_applications.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
EXPECT_EQ(1u, GetErrorCount());
@@ -1190,7 +1229,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// If missing id and url, application is ignored.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"related_applications\": [{\"platform\": \"play\"}]}");
EXPECT_EQ(manifest.related_applications.size(), 0u);
EXPECT_TRUE(manifest.IsEmpty());
@@ -1201,7 +1240,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// Valid application, with url.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"related_applications\": ["
"{\"platform\": \"play\", \"url\": \"http://www.foo.com\"}]}");
EXPECT_EQ(manifest.related_applications.size(), 1u);
@@ -1216,7 +1255,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// Application with an invalid url.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"related_applications\": ["
"{\"platform\": \"play\", \"url\": \"http://www.foo.com:co&uk\"}]}");
EXPECT_TRUE(manifest.IsEmpty());
@@ -1228,7 +1267,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// Valid application, with id.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"related_applications\": ["
"{\"platform\": \"itunes\", \"id\": \"foo\"}]}");
EXPECT_EQ(manifest.related_applications.size(), 1u);
@@ -1243,7 +1282,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// All valid applications are in list.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"related_applications\": ["
"{\"platform\": \"play\", \"id\": \"foo\"},"
"{\"platform\": \"itunes\", \"id\": \"bar\"}]}");
@@ -1265,7 +1304,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
// Two invalid applications and one valid. Only the valid application should
// be in the list.
{
- Manifest manifest = ParseManifest(
+ blink::Manifest manifest = ParseManifest(
"{ \"related_applications\": ["
"{\"platform\": \"itunes\"},"
"{\"platform\": \"play\", \"id\": \"foo\"},"
@@ -1288,7 +1327,7 @@ TEST_F(ManifestParserTest, RelatedApplicationsParseRules) {
TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
// Smoke test.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"prefer_related_applications\": true }");
EXPECT_TRUE(manifest.prefer_related_applications);
EXPECT_EQ(0u, GetErrorCount());
@@ -1296,7 +1335,7 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
// Don't parse if the property isn't a boolean.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"prefer_related_applications\": {} }");
EXPECT_FALSE(manifest.prefer_related_applications);
EXPECT_EQ(1u, GetErrorCount());
@@ -1306,8 +1345,8 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
errors()[0]);
}
{
- Manifest manifest = ParseManifest(
- "{ \"prefer_related_applications\": \"true\" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"prefer_related_applications\": \"true\" }");
EXPECT_FALSE(manifest.prefer_related_applications);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -1316,7 +1355,8 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
errors()[0]);
}
{
- Manifest manifest = ParseManifest("{ \"prefer_related_applications\": 1 }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"prefer_related_applications\": 1 }");
EXPECT_FALSE(manifest.prefer_related_applications);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
@@ -1327,7 +1367,7 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
// "False" should set the boolean false without throwing errors.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"prefer_related_applications\": false }");
EXPECT_FALSE(manifest.prefer_related_applications);
EXPECT_EQ(0u, GetErrorCount());
@@ -1337,23 +1377,25 @@ TEST_F(ManifestParserTest, ParsePreferRelatedApplicationsParseRules) {
TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"#FF0000\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0xFFFF0000u);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \"#FF0000\" }");
+ EXPECT_EQ(*manifest.theme_color, 0xFFFF0000u);
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \" blue \" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0xFF0000FFu);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \" blue \" }");
+ EXPECT_EQ(*manifest.theme_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if theme_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": {} }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": {} }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
errors()[0]);
@@ -1361,8 +1403,8 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": false }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": false }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
errors()[0]);
@@ -1370,8 +1412,8 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": null }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": null }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
errors()[0]);
@@ -1379,8 +1421,8 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": [] }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": [] }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
errors()[0]);
@@ -1388,8 +1430,8 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Don't parse if theme_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": 42 }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": 42 }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, type string expected.",
errors()[0]);
@@ -1397,8 +1439,9 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if string is not in a known format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"foo(bar)\" }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \"foo(bar)\" }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored,"
" 'foo(bar)' is not a valid color.",
@@ -1407,8 +1450,8 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if string is not in a known format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"bleu\" }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": \"bleu\" }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, 'bleu' is not a valid color.",
errors()[0]);
@@ -1416,8 +1459,8 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if string is not in a known format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"FF00FF\" }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": \"FF00FF\" }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, 'FF00FF'"
" is not a valid color.",
@@ -1426,8 +1469,9 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if multiple values for theme_color are given.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"#ABC #DEF\" }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \"#ABC #DEF\" }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, "
"'#ABC #DEF' is not a valid color.",
@@ -1436,9 +1480,9 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Parse fails if multiple values for theme_color are given.
{
- Manifest manifest = ParseManifest(
- "{ \"theme_color\": \"#AABBCC #DDEEFF\" }");
- EXPECT_EQ(manifest.theme_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \"#AABBCC #DDEEFF\" }");
+ EXPECT_FALSE(manifest.theme_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'theme_color' ignored, "
"'#AABBCC #DDEEFF' is not a valid color.",
@@ -1447,51 +1491,55 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
// Accept CSS color keyword format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"blue\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0xFF0000FFu);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": \"blue\" }");
+ EXPECT_EQ(*manifest.theme_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS color keyword format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"chartreuse\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0xFF7FFF00u);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \"chartreuse\" }");
+ EXPECT_EQ(*manifest.theme_color, 0xFF7FFF00u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"#FFF\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0xFFFFFFFFu);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": \"#FFF\" }");
+ EXPECT_EQ(*manifest.theme_color, 0xFFFFFFFFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"#ABC\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0xFFAABBCCu);
+ blink::Manifest manifest = ParseManifest("{ \"theme_color\": \"#ABC\" }");
+ EXPECT_EQ(*manifest.theme_color, 0xFFAABBCCu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RRGGBB format.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"#FF0000\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0xFFFF0000u);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \"#FF0000\" }");
+ EXPECT_EQ(*manifest.theme_color, 0xFFFF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept translucent colors.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"rgba(255,0,0,"
+ blink::Manifest manifest = ParseManifest(
+ "{ \"theme_color\": \"rgba(255,0,0,"
"0.4)\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0x66FF0000u);
+ EXPECT_EQ(*manifest.theme_color, 0x66FF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept transparent colors.
{
- Manifest manifest = ParseManifest("{ \"theme_color\": \"rgba(0,0,0,0)\" }");
- EXPECT_EQ(ExtractColor(manifest.theme_color), 0x00000000u);
+ blink::Manifest manifest =
+ ParseManifest("{ \"theme_color\": \"rgba(0,0,0,0)\" }");
+ EXPECT_EQ(*manifest.theme_color, 0x00000000u);
EXPECT_EQ(0u, GetErrorCount());
}
}
@@ -1499,24 +1547,25 @@ TEST_F(ManifestParserTest, ThemeColorParserRules) {
TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"#FF0000\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0xFFFF0000u);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"#FF0000\" }");
+ EXPECT_EQ(*manifest.background_color, 0xFFFF0000u);
EXPECT_FALSE(manifest.IsEmpty());
EXPECT_EQ(0u, GetErrorCount());
}
// Trim whitespaces.
{
- Manifest manifest = ParseManifest(
- "{ \"background_color\": \" blue \" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0xFF0000FFu);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \" blue \" }");
+ EXPECT_EQ(*manifest.background_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if background_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"background_color\": {} }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"background_color\": {} }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
errors()[0]);
@@ -1524,8 +1573,8 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"background_color\": false }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"background_color\": false }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
errors()[0]);
@@ -1533,8 +1582,8 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"background_color\": null }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"background_color\": null }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
errors()[0]);
@@ -1542,8 +1591,8 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"background_color\": [] }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"background_color\": [] }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
errors()[0]);
@@ -1551,8 +1600,8 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Don't parse if background_color isn't a string.
{
- Manifest manifest = ParseManifest("{ \"background_color\": 42 }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest = ParseManifest("{ \"background_color\": 42 }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, type string expected.",
errors()[0]);
@@ -1560,8 +1609,9 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if string is not in a known format.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"foo(bar)\" }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"foo(bar)\" }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored,"
" 'foo(bar)' is not a valid color.",
@@ -1570,8 +1620,9 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if string is not in a known format.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"bleu\" }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"bleu\" }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored,"
" 'bleu' is not a valid color.",
@@ -1580,8 +1631,9 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if string is not in a known format.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"FF00FF\" }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"FF00FF\" }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored,"
" 'FF00FF' is not a valid color.",
@@ -1590,9 +1642,9 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if multiple values for background_color are given.
{
- Manifest manifest = ParseManifest(
- "{ \"background_color\": \"#ABC #DEF\" }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"#ABC #DEF\" }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, "
"'#ABC #DEF' is not a valid color.",
@@ -1601,9 +1653,9 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Parse fails if multiple values for background_color are given.
{
- Manifest manifest = ParseManifest(
- "{ \"background_color\": \"#AABBCC #DDEEFF\" }");
- EXPECT_EQ(manifest.background_color, Manifest::kInvalidOrMissingColor);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"#AABBCC #DDEEFF\" }");
+ EXPECT_FALSE(manifest.background_color.has_value());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'background_color' ignored, "
"'#AABBCC #DDEEFF' is not a valid color.",
@@ -1612,53 +1664,59 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
// Accept CSS color keyword format.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"blue\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0xFF0000FFu);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"blue\" }");
+ EXPECT_EQ(*manifest.background_color, 0xFF0000FFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS color keyword format.
{
- Manifest manifest = ParseManifest(
- "{ \"background_color\": \"chartreuse\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0xFF7FFF00u);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"chartreuse\" }");
+ EXPECT_EQ(*manifest.background_color, 0xFF7FFF00u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"#FFF\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0xFFFFFFFFu);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"#FFF\" }");
+ EXPECT_EQ(*manifest.background_color, 0xFFFFFFFFu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RGB format.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"#ABC\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0xFFAABBCCu);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"#ABC\" }");
+ EXPECT_EQ(*manifest.background_color, 0xFFAABBCCu);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept CSS RRGGBB format.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"#FF0000\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0xFFFF0000u);
+ blink::Manifest manifest =
+ ParseManifest("{ \"background_color\": \"#FF0000\" }");
+ EXPECT_EQ(*manifest.background_color, 0xFFFF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept translucent colors.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"rgba(255,0,0,"
+ blink::Manifest manifest = ParseManifest(
+ "{ \"background_color\": \"rgba(255,0,0,"
"0.4)\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0x66FF0000u);
+ EXPECT_EQ(*manifest.background_color, 0x66FF0000u);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept transparent colors.
{
- Manifest manifest = ParseManifest("{ \"background_color\": \"rgba(0,0,0,"
+ blink::Manifest manifest = ParseManifest(
+ "{ \"background_color\": \"rgba(0,0,0,"
"0)\" }");
- EXPECT_EQ(ExtractColor(manifest.background_color), 0x00000000u);
+ EXPECT_EQ(*manifest.background_color, 0x00000000u);
EXPECT_EQ(0u, GetErrorCount());
}
}
@@ -1666,7 +1724,7 @@ TEST_F(ManifestParserTest, BackgroundColorParserRules) {
TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Smoke test.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"splash_screen_url\": \"splash.html\" }");
ASSERT_EQ(manifest.splash_screen_url.spec(),
default_document_url.Resolve("splash.html").spec());
@@ -1676,7 +1734,7 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Whitespaces.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"splash_screen_url\": \" splash.html\" }");
ASSERT_EQ(manifest.splash_screen_url.spec(),
default_document_url.Resolve("splash.html").spec());
@@ -1685,7 +1743,7 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"splash_screen_url\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"splash_screen_url\": {} }");
ASSERT_TRUE(manifest.splash_screen_url.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'splash_screen_url' ignored, type string expected.",
@@ -1694,7 +1752,7 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Don't parse if property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"splash_screen_url\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"splash_screen_url\": 42 }");
ASSERT_TRUE(manifest.splash_screen_url.is_empty());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'splash_screen_url' ignored, type string expected.",
@@ -1703,7 +1761,7 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Don't parse if property isn't a valid URL.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifest("{ \"splash_screen_url\": \"http://www.google.ca:a\" }");
ASSERT_TRUE(manifest.splash_screen_url.is_empty());
EXPECT_EQ(1u, GetErrorCount());
@@ -1713,7 +1771,7 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Absolute splash_screen_url, same origin with document.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"splash_screen_url\": \"http://foo.com/splash.html\" }",
GURL("http://foo.com/manifest.json"),
GURL("http://foo.com/index.html"));
@@ -1723,7 +1781,7 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Absolute splash_screen_url, cross origin with document.
{
- Manifest manifest = ParseManifestWithURLs(
+ blink::Manifest manifest = ParseManifestWithURLs(
"{ \"splash_screen_url\": \"http://bar.com/splash.html\" }",
GURL("http://foo.com/manifest.json"),
GURL("http://foo.com/index.html"));
@@ -1737,7 +1795,7 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
// Resolving has to happen based on the manifest_url.
{
- Manifest manifest =
+ blink::Manifest manifest =
ParseManifestWithURLs("{ \"splash_screen_url\": \"splash.html\" }",
GURL("http://foo.com/splashy/manifest.json"),
GURL("http://foo.com/index.html"));
@@ -1750,28 +1808,29 @@ TEST_F(ManifestParserTest, SplashScreenUrlParseRules) {
TEST_F(ManifestParserTest, GCMSenderIDParseRules) {
// Smoke test.
{
- Manifest manifest = ParseManifest("{ \"gcm_sender_id\": \"foo\" }");
+ blink::Manifest manifest = ParseManifest("{ \"gcm_sender_id\": \"foo\" }");
EXPECT_TRUE(base::EqualsASCII(manifest.gcm_sender_id.string(), "foo"));
EXPECT_EQ(0u, GetErrorCount());
}
// Trim whitespaces.
{
- Manifest manifest = ParseManifest("{ \"gcm_sender_id\": \" foo \" }");
+ blink::Manifest manifest =
+ ParseManifest("{ \"gcm_sender_id\": \" foo \" }");
EXPECT_TRUE(base::EqualsASCII(manifest.gcm_sender_id.string(), "foo"));
EXPECT_EQ(0u, GetErrorCount());
}
// Don't parse if the property isn't a string.
{
- Manifest manifest = ParseManifest("{ \"gcm_sender_id\": {} }");
+ blink::Manifest manifest = ParseManifest("{ \"gcm_sender_id\": {} }");
EXPECT_TRUE(manifest.gcm_sender_id.is_null());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'gcm_sender_id' ignored, type string expected.",
errors()[0]);
}
{
- Manifest manifest = ParseManifest("{ \"gcm_sender_id\": 42 }");
+ blink::Manifest manifest = ParseManifest("{ \"gcm_sender_id\": 42 }");
EXPECT_TRUE(manifest.gcm_sender_id.is_null());
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("property 'gcm_sender_id' ignored, type string expected.",
diff --git a/chromium/content/renderer/manifest/manifest_uma_util.cc b/chromium/content/renderer/manifest/manifest_uma_util.cc
index 3d37795db3d..7bb45b5c6da 100644
--- a/chromium/content/renderer/manifest/manifest_uma_util.cc
+++ b/chromium/content/renderer/manifest/manifest_uma_util.cc
@@ -5,7 +5,7 @@
#include "content/renderer/manifest/manifest_uma_util.h"
#include "base/metrics/histogram_macros.h"
-#include "content/public/common/manifest.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
namespace content {
@@ -29,7 +29,7 @@ enum ManifestFetchResultType {
} // anonymous namespace
-void ManifestUmaUtil::ParseSucceeded(const Manifest& manifest) {
+void ManifestUmaUtil::ParseSucceeded(const blink::Manifest& manifest) {
UMA_HISTOGRAM_BOOLEAN(kUMANameParseSuccess, true);
UMA_HISTOGRAM_BOOLEAN("Manifest.IsEmpty", manifest.IsEmpty());
if (manifest.IsEmpty())
diff --git a/chromium/content/renderer/manifest/manifest_uma_util.h b/chromium/content/renderer/manifest/manifest_uma_util.h
index 29a263d5cec..1bf569b8ca6 100644
--- a/chromium/content/renderer/manifest/manifest_uma_util.h
+++ b/chromium/content/renderer/manifest/manifest_uma_util.h
@@ -5,9 +5,11 @@
#ifndef CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
#define CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
-namespace content {
-
+namespace blink {
struct Manifest;
+}
+
+namespace content {
class ManifestUmaUtil {
public:
@@ -20,7 +22,7 @@ class ManifestUmaUtil {
// Record that the Manifest was successfully parsed. If it is an empty
// Manifest, it will recorded as so and nothing will happen. Otherwise, the
// presence of each properties will be recorded.
- static void ParseSucceeded(const Manifest& manifest);
+ static void ParseSucceeded(const blink::Manifest& manifest);
// Record that the Manifest parsing failed.
static void ParseFailed();
diff --git a/chromium/content/renderer/media/audio_device_factory.cc b/chromium/content/renderer/media/audio_device_factory.cc
index 82f0412dcc2..52a260eb6fe 100644
--- a/chromium/content/renderer/media/audio_device_factory.cc
+++ b/chromium/content/renderer/media/audio_device_factory.cc
@@ -21,7 +21,6 @@
#include "media/audio/audio_output_device.h"
#include "media/base/audio_renderer_mixer_input.h"
#include "media/base/media_switches.h"
-#include "url/origin.h"
namespace content {
@@ -44,12 +43,10 @@ const int64_t kMaxAuthorizationTimeoutMs = 0; // No timeout.
scoped_refptr<media::AudioOutputDevice> NewOutputDevice(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
auto device = base::MakeRefCounted<media::AudioOutputDevice>(
AudioOutputIPCFactory::get()->CreateAudioOutputIPC(render_frame_id),
AudioOutputIPCFactory::get()->io_task_runner(), session_id, device_id,
- security_origin,
// Set authorization request timeout at 80% of renderer hung timeout,
// but no more than kMaxAuthorizationTimeout.
base::TimeDelta::FromMilliseconds(
@@ -72,14 +69,13 @@ scoped_refptr<media::SwitchableAudioRendererSink> NewMixableSink(
AudioDeviceFactory::SourceType source_type,
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
DCHECK(render_thread) << "RenderThreadImpl is not instantiated, or "
<< "GetOutputDeviceInfo() is called on a wrong thread ";
return scoped_refptr<media::AudioRendererMixerInput>(
render_thread->GetAudioRendererMixerManager()->CreateInput(
- render_frame_id, session_id, device_id, security_origin,
+ render_frame_id, session_id, device_id,
AudioDeviceFactory::GetSourceLatencyType(source_type)));
}
@@ -106,13 +102,10 @@ media::AudioLatency::LatencyType AudioDeviceFactory::GetSourceLatencyType(
}
scoped_refptr<media::AudioRendererSink>
-AudioDeviceFactory::NewAudioRendererMixerSink(
- int render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
- return NewFinalAudioRendererSink(render_frame_id, session_id, device_id,
- security_origin);
+AudioDeviceFactory::NewAudioRendererMixerSink(int render_frame_id,
+ int session_id,
+ const std::string& device_id) {
+ return NewFinalAudioRendererSink(render_frame_id, session_id, device_id);
}
// static
@@ -120,25 +113,21 @@ scoped_refptr<media::AudioRendererSink>
AudioDeviceFactory::NewAudioRendererSink(SourceType source_type,
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
if (factory_) {
scoped_refptr<media::AudioRendererSink> device =
factory_->CreateAudioRendererSink(source_type, render_frame_id,
- session_id, device_id,
- security_origin);
+ session_id, device_id);
if (device)
return device;
}
if (IsMixable(source_type))
- return NewMixableSink(source_type, render_frame_id, session_id, device_id,
- security_origin);
+ return NewMixableSink(source_type, render_frame_id, session_id, device_id);
UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation",
false);
- return NewFinalAudioRendererSink(render_frame_id, session_id, device_id,
- security_origin);
+ return NewFinalAudioRendererSink(render_frame_id, session_id, device_id);
}
// static
@@ -147,20 +136,17 @@ AudioDeviceFactory::NewSwitchableAudioRendererSink(
SourceType source_type,
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
if (factory_) {
scoped_refptr<media::SwitchableAudioRendererSink> sink =
- factory_->CreateSwitchableAudioRendererSink(source_type,
- render_frame_id, session_id,
- device_id, security_origin);
+ factory_->CreateSwitchableAudioRendererSink(
+ source_type, render_frame_id, session_id, device_id);
if (sink)
return sink;
}
if (IsMixable(source_type))
- return NewMixableSink(source_type, render_frame_id, session_id, device_id,
- security_origin);
+ return NewMixableSink(source_type, render_frame_id, session_id, device_id);
// AudioOutputDevice is not RestartableAudioRendererSink, so we can't return
// anything for those who wants to create an unmixable sink.
@@ -170,8 +156,10 @@ AudioDeviceFactory::NewSwitchableAudioRendererSink(
// static
scoped_refptr<media::AudioCapturerSource>
-AudioDeviceFactory::NewAudioCapturerSource(int render_frame_id) {
+AudioDeviceFactory::NewAudioCapturerSource(int render_frame_id,
+ int session_id) {
if (factory_) {
+ // We don't pass on |session_id|, as this branch is only used for tests.
scoped_refptr<media::AudioCapturerSource> source =
factory_->CreateAudioCapturerSource(render_frame_id);
if (source)
@@ -179,21 +167,20 @@ AudioDeviceFactory::NewAudioCapturerSource(int render_frame_id) {
}
return base::MakeRefCounted<media::AudioInputDevice>(
- AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id),
- AudioInputIPCFactory::get()->io_task_runner());
+ AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id,
+ session_id));
}
// static
media::OutputDeviceInfo AudioDeviceFactory::GetOutputDeviceInfo(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
DCHECK(render_thread) << "RenderThreadImpl is not instantiated, or "
<< "GetOutputDeviceInfo() is called on a wrong thread ";
return render_thread->GetAudioRendererMixerManager()->GetOutputDeviceInfo(
- render_frame_id, session_id, device_id, security_origin);
+ render_frame_id, session_id, device_id);
}
AudioDeviceFactory::AudioDeviceFactory() {
@@ -207,21 +194,18 @@ AudioDeviceFactory::~AudioDeviceFactory() {
// static
scoped_refptr<media::AudioRendererSink>
-AudioDeviceFactory::NewFinalAudioRendererSink(
- int render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+AudioDeviceFactory::NewFinalAudioRendererSink(int render_frame_id,
+ int session_id,
+ const std::string& device_id) {
if (factory_) {
scoped_refptr<media::AudioRendererSink> sink =
factory_->CreateFinalAudioRendererSink(render_frame_id, session_id,
- device_id, security_origin);
+ device_id);
if (sink)
return sink;
}
- return NewOutputDevice(render_frame_id, session_id, device_id,
- security_origin);
+ return NewOutputDevice(render_frame_id, session_id, device_id);
}
} // namespace content
diff --git a/chromium/content/renderer/media/audio_device_factory.h b/chromium/content/renderer/media/audio_device_factory.h
index 194ef95e206..6184e7a0eca 100644
--- a/chromium/content/renderer/media/audio_device_factory.h
+++ b/chromium/content/renderer/media/audio_device_factory.h
@@ -20,10 +20,6 @@ class SwitchableAudioRendererSink;
class AudioCapturerSource;
}
-namespace url {
-class Origin;
-}
-
namespace content {
// A factory for creating AudioRendererSinks and AudioCapturerSources. There is
@@ -57,15 +53,14 @@ class CONTENT_EXPORT AudioDeviceFactory {
// |render_frame_id| refers to the RenderFrame containing the entity
// producing the audio. If |session_id| is nonzero, it is used by the browser
// to select the correct input device ID and its associated output device, if
- // it exists. If |session_id| is zero, |device_id| and |security_origin|
- // identify the output device to use.
- // If |session_id| is zero and |device_id| and |security_origin| are empty,
- // the default output device will be selected.
+ // it exists. If |session_id| is zero, |device_id| identify the output device
+ // to use.
+ // If |session_id| is zero and |device_id| is empty, the default output
+ // device will be selected.
static scoped_refptr<media::AudioRendererSink> NewAudioRendererMixerSink(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
// Creates an AudioRendererSink bound to an AudioOutputDevice.
// Basing on |source_type| and build configuration, audio played out through
@@ -76,8 +71,7 @@ class CONTENT_EXPORT AudioDeviceFactory {
SourceType source_type,
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
// Creates a SwitchableAudioRendererSink bound to an AudioOutputDevice
// Basing on |source_type| and build configuration, audio played out through
@@ -86,22 +80,21 @@ class CONTENT_EXPORT AudioDeviceFactory {
NewSwitchableAudioRendererSink(SourceType source_type,
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
// A helper to get device info in the absence of AudioOutputDevice.
// Must be called on renderer thread only.
static media::OutputDeviceInfo GetOutputDeviceInfo(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
// Creates an AudioCapturerSource using the currently registered factory.
// |render_frame_id| refers to the RenderFrame containing the entity
// consuming the audio.
static scoped_refptr<media::AudioCapturerSource> NewAudioCapturerSource(
- int render_frame_id);
+ int render_frame_id,
+ int session_id);
protected:
AudioDeviceFactory();
@@ -117,22 +110,19 @@ class CONTENT_EXPORT AudioDeviceFactory {
virtual scoped_refptr<media::AudioRendererSink> CreateFinalAudioRendererSink(
int render_frame_id,
int sesssion_id,
- const std::string& device_id,
- const url::Origin& security_origin) = 0;
+ const std::string& device_id) = 0;
virtual scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
SourceType source_type,
int render_frame_id,
int sesssion_id,
- const std::string& device_id,
- const url::Origin& security_origin) = 0;
+ const std::string& device_id) = 0;
virtual scoped_refptr<media::SwitchableAudioRendererSink>
CreateSwitchableAudioRendererSink(SourceType source_type,
int render_frame_id,
int sesssion_id,
- const std::string& device_id,
- const url::Origin& security_origin) = 0;
+ const std::string& device_id) = 0;
virtual scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
int render_frame_id) = 0;
@@ -145,8 +135,7 @@ class CONTENT_EXPORT AudioDeviceFactory {
static scoped_refptr<media::AudioRendererSink> NewFinalAudioRendererSink(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
DISALLOW_COPY_AND_ASSIGN(AudioDeviceFactory);
};
diff --git a/chromium/content/renderer/media/audio_input_ipc_factory.cc b/chromium/content/renderer/media/audio_input_ipc_factory.cc
index 2b67390af9c..7cafd730916 100644
--- a/chromium/content/renderer/media/audio_input_ipc_factory.cc
+++ b/chromium/content/renderer/media/audio_input_ipc_factory.cc
@@ -8,8 +8,8 @@
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
-#include "content/renderer/media/audio_input_message_filter.h"
#include "content/renderer/media/mojo_audio_input_ipc.h"
#include "content/renderer/render_frame_impl.h"
#include "services/service_manager/public/cpp/interface_provider.h"
@@ -20,8 +20,8 @@ namespace {
void CreateMojoAudioInputStreamOnMainThread(
int frame_id,
- mojom::RendererAudioInputStreamFactoryClientPtr client,
int32_t session_id,
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
@@ -36,27 +36,44 @@ void CreateMojoAudioInputStreamOnMainThread(
void CreateMojoAudioInputStream(
scoped_refptr<base::SequencedTaskRunner> main_task_runner,
int frame_id,
- mojom::RendererAudioInputStreamFactoryClientPtr client,
int32_t session_id,
+ mojom::RendererAudioInputStreamFactoryClientPtr client,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
main_task_runner->PostTask(
FROM_HERE, base::BindOnce(&CreateMojoAudioInputStreamOnMainThread,
- frame_id, std::move(client), session_id, params,
+ frame_id, session_id, std::move(client), params,
automatic_gain_control, total_segments));
}
+void AssociateInputAndOutputForAec(
+ scoped_refptr<base::SequencedTaskRunner> main_task_runner,
+ int frame_id,
+ const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id) {
+ main_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](int frame_id, const base::UnguessableToken& input_stream_id,
+ const std::string& output_device_id) {
+ RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(frame_id);
+ if (frame) {
+ frame->GetAudioInputStreamFactory()
+ ->AssociateInputAndOutputForAec(input_stream_id,
+ output_device_id);
+ }
+ },
+ frame_id, input_stream_id, output_device_id));
+}
} // namespace
AudioInputIPCFactory* AudioInputIPCFactory::instance_ = nullptr;
AudioInputIPCFactory::AudioInputIPCFactory(
- scoped_refptr<AudioInputMessageFilter> audio_input_message_filter,
scoped_refptr<base::SequencedTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : audio_input_message_filter_(std::move(audio_input_message_filter)),
- main_task_runner_(std::move(main_task_runner)),
+ : main_task_runner_(std::move(main_task_runner)),
io_task_runner_(std::move(io_task_runner)) {
DCHECK(!instance_);
instance_ = this;
@@ -68,11 +85,14 @@ AudioInputIPCFactory::~AudioInputIPCFactory() {
}
std::unique_ptr<media::AudioInputIPC> AudioInputIPCFactory::CreateAudioInputIPC(
- int frame_id) const {
- if (audio_input_message_filter_)
- return audio_input_message_filter_->CreateAudioInputIPC(frame_id);
- return std::make_unique<MojoAudioInputIPC>(base::BindRepeating(
- &CreateMojoAudioInputStream, main_task_runner_, frame_id));
+ int frame_id,
+ int session_id) const {
+ DCHECK_NE(0, session_id);
+ return std::make_unique<MojoAudioInputIPC>(
+ base::BindRepeating(&CreateMojoAudioInputStream, main_task_runner_,
+ frame_id, session_id),
+ base::BindRepeating(&AssociateInputAndOutputForAec, main_task_runner_,
+ frame_id));
}
} // namespace content
diff --git a/chromium/content/renderer/media/audio_input_ipc_factory.h b/chromium/content/renderer/media/audio_input_ipc_factory.h
index eac9eb0e3c5..7921cb74635 100644
--- a/chromium/content/renderer/media/audio_input_ipc_factory.h
+++ b/chromium/content/renderer/media/audio_input_ipc_factory.h
@@ -22,15 +22,10 @@ class AudioInputIPC;
namespace content {
-class AudioInputMessageFilter;
-
// This is a thread-safe factory for AudioInputIPC objects.
class CONTENT_EXPORT AudioInputIPCFactory {
public:
- // If |audio_input_message_filter| is given, it is used for creating
- // AudioInputIPC objects. Otherwise, MojoAudioInputIPC objects are created.
AudioInputIPCFactory(
- scoped_refptr<AudioInputMessageFilter> audio_input_message_filter,
scoped_refptr<base::SequencedTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
@@ -46,10 +41,11 @@ class CONTENT_EXPORT AudioInputIPCFactory {
}
// The returned object may only be used on io_task_runner().
- std::unique_ptr<media::AudioInputIPC> CreateAudioInputIPC(int frame_id) const;
+ std::unique_ptr<media::AudioInputIPC> CreateAudioInputIPC(
+ int frame_id,
+ int session_id) const;
private:
- const scoped_refptr<AudioInputMessageFilter> audio_input_message_filter_;
const scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
diff --git a/chromium/content/renderer/media/audio_input_message_filter.cc b/chromium/content/renderer/media/audio_input_message_filter.cc
deleted file mode 100644
index 7ddca260041..00000000000
--- a/chromium/content/renderer/media/audio_input_message_filter.cc
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/audio_input_message_filter.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "content/common/media/audio_messages.h"
-#include "content/renderer/media/webrtc_logging.h"
-#include "ipc/ipc_logging.h"
-#include "ipc/ipc_sender.h"
-
-namespace {
-
-const int kStreamIDNotSet = -1;
-
-void LogMessage(int stream_id, const std::string& msg) {
- std::ostringstream oss;
- oss << "[stream_id=" << stream_id << "] AIMF::" << msg;
- content::WebRtcLogMessage(oss.str());
- DVLOG(1) << oss.str();
-}
-
-} // namespace
-
-namespace content {
-
-class AudioInputMessageFilter::AudioInputIPCImpl : public media::AudioInputIPC {
- public:
- AudioInputIPCImpl(const scoped_refptr<AudioInputMessageFilter>& filter,
- int render_frame_id);
- ~AudioInputIPCImpl() override;
-
- // media::AudioInputIPC implementation.
- void CreateStream(media::AudioInputIPCDelegate* delegate,
- int session_id,
- const media::AudioParameters& params,
- bool automatic_gain_control,
- uint32_t total_segments) override;
- void RecordStream() override;
- void SetVolume(double volume) override;
- void CloseStream() override;
-
- private:
- const scoped_refptr<AudioInputMessageFilter> filter_;
- const int render_frame_id_;
- int stream_id_;
-};
-
-AudioInputMessageFilter* AudioInputMessageFilter::g_filter = nullptr;
-
-AudioInputMessageFilter::AudioInputMessageFilter(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : sender_(nullptr), io_task_runner_(io_task_runner) {
- DCHECK(!g_filter);
- g_filter = this;
-}
-
-AudioInputMessageFilter::~AudioInputMessageFilter() {
- DCHECK_EQ(g_filter, this);
- g_filter = nullptr;
-}
-
-// static
-AudioInputMessageFilter* AudioInputMessageFilter::Get() {
- return g_filter;
-}
-
-void AudioInputMessageFilter::Send(IPC::Message* message) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- if (!sender_) {
- delete message;
- } else {
- sender_->Send(message);
- }
-}
-
-bool AudioInputMessageFilter::OnMessageReceived(const IPC::Message& message) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(AudioInputMessageFilter, message)
- IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamCreated,
- OnStreamCreated)
- IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamError, OnStreamError)
- IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamMuted, OnStreamMuted)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void AudioInputMessageFilter::OnFilterAdded(IPC::Channel* channel) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- // Captures the sender for IPC.
- sender_ = channel;
-}
-
-void AudioInputMessageFilter::OnFilterRemoved() {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- // Once removed, a filter will not be used again. At this time all
- // delegates must be notified so they release their reference.
- OnChannelClosing();
-}
-
-void AudioInputMessageFilter::OnChannelClosing() {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- sender_ = nullptr;
-
- DLOG_IF(WARNING, !delegates_.IsEmpty())
- << "Not all audio devices have been closed.";
-
- base::IDMap<media::AudioInputIPCDelegate*>::iterator it(&delegates_);
- while (!it.IsAtEnd()) {
- it.GetCurrentValue()->OnIPCClosed();
- delegates_.Remove(it.GetCurrentKey());
- it.Advance();
- }
-}
-
-void AudioInputMessageFilter::OnStreamCreated(
- int stream_id,
- base::SharedMemoryHandle handle,
- base::SyncSocket::TransitDescriptor socket_descriptor,
- bool initially_muted) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- LogMessage(stream_id, "OnStreamCreated");
-
- base::SyncSocket::Handle socket_handle =
- base::SyncSocket::UnwrapHandle(socket_descriptor);
- media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
- if (!delegate) {
- DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
- << " audio capturer (stream_id=" << stream_id << ").";
- base::SharedMemory::CloseHandle(handle);
- base::SyncSocket socket(socket_handle);
- return;
- }
- // Forward message to the stream delegate.
- delegate->OnStreamCreated(handle, socket_handle, initially_muted);
-}
-
-void AudioInputMessageFilter::OnStreamError(int stream_id) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
- if (!delegate) {
- DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
- << " audio renderer.";
- return;
- }
- delegate->OnError();
-}
-
-void AudioInputMessageFilter::OnStreamMuted(int stream_id, bool is_muted) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
- if (!delegate) {
- DLOG(WARNING) << "Got audio stream muted event for a non-existent or "
- "removed audio renderer.";
- return;
- }
- delegate->OnMuted(is_muted);
-}
-
-AudioInputMessageFilter::AudioInputIPCImpl::AudioInputIPCImpl(
- const scoped_refptr<AudioInputMessageFilter>& filter,
- int render_frame_id)
- : filter_(filter),
- render_frame_id_(render_frame_id),
- stream_id_(kStreamIDNotSet) {
-}
-
-AudioInputMessageFilter::AudioInputIPCImpl::~AudioInputIPCImpl() {}
-
-std::unique_ptr<media::AudioInputIPC>
-AudioInputMessageFilter::CreateAudioInputIPC(int render_frame_id) {
- DCHECK_GT(render_frame_id, 0);
- return std::unique_ptr<media::AudioInputIPC>(
- new AudioInputIPCImpl(this, render_frame_id));
-}
-
-void AudioInputMessageFilter::AudioInputIPCImpl::CreateStream(
- media::AudioInputIPCDelegate* delegate,
- int session_id,
- const media::AudioParameters& params,
- bool automatic_gain_control,
- uint32_t total_segments) {
- DCHECK(filter_->io_task_runner_->BelongsToCurrentThread());
- DCHECK(delegate);
-
- stream_id_ = filter_->delegates_.Add(delegate);
- // TODO(henrika): remove all LogMessage calls when we have sorted out the
- // existing "no input audio" issues.
- LogMessage(stream_id_, "CreateStream");
-
- AudioInputHostMsg_CreateStream_Config config;
- config.params = params;
- config.automatic_gain_control = automatic_gain_control;
- config.shared_memory_count = total_segments;
- filter_->Send(new AudioInputHostMsg_CreateStream(stream_id_, render_frame_id_,
- session_id, config));
-}
-
-void AudioInputMessageFilter::AudioInputIPCImpl::RecordStream() {
- DCHECK_NE(stream_id_, kStreamIDNotSet);
- LogMessage(stream_id_, "RecordStream");
- filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_));
-}
-
-void AudioInputMessageFilter::AudioInputIPCImpl::SetVolume(double volume) {
- DCHECK_NE(stream_id_, kStreamIDNotSet);
- DCHECK_GE(volume, 0);
- DCHECK_LE(volume, 1);
- filter_->Send(new AudioInputHostMsg_SetVolume(stream_id_, volume));
-}
-
-void AudioInputMessageFilter::AudioInputIPCImpl::CloseStream() {
- DCHECK(filter_->io_task_runner_->BelongsToCurrentThread());
- DCHECK_NE(stream_id_, kStreamIDNotSet);
- LogMessage(stream_id_, "CloseStream");
- filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
- filter_->delegates_.Remove(stream_id_);
- stream_id_ = kStreamIDNotSet;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/audio_input_message_filter.h b/chromium/content/renderer/media/audio_input_message_filter.h
deleted file mode 100644
index cec8f6f9321..00000000000
--- a/chromium/content/renderer/media/audio_input_message_filter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_AUDIO_INPUT_MESSAGE_FILTER_H_
-#define CONTENT_RENDERER_MEDIA_AUDIO_INPUT_MESSAGE_FILTER_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/containers/id_map.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory.h"
-#include "base/sync_socket.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "ipc/message_filter.h"
-#include "media/audio/audio_input_ipc.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-
-// MessageFilter that handles audio input messages and delegates them to
-// audio capturers. Created on render thread, AudioMessageFilter is operated on
-// IO thread (secondary thread of render process), it intercepts audio messages
-// and process them on IO thread since these messages are time critical.
-class CONTENT_EXPORT AudioInputMessageFilter : public IPC::MessageFilter {
- public:
- explicit AudioInputMessageFilter(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
-
- // Getter for the one AudioInputMessageFilter object.
- static AudioInputMessageFilter* Get();
-
- // Create an AudioInputIPC to be owned by one delegate. |render_frame_id|
- // refers to the RenderFrame containing the entity consuming the audio.
- //
- // The returned object is not thread-safe, and must be used on
- // |io_task_runner|.
- std::unique_ptr<media::AudioInputIPC> CreateAudioInputIPC(
- int render_frame_id);
-
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() const {
- return io_task_runner_;
- }
-
- private:
- // Implementation of media::AudioInputIPC which augments IPC calls with
- // stream_id and the destination render_frame_id.
- class AudioInputIPCImpl;
-
- ~AudioInputMessageFilter() override;
-
- // Sends an IPC message using |channel_|.
- void Send(IPC::Message* message);
-
- // IPC::MessageFilter override. Called on |io_task_runner_|.
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnFilterAdded(IPC::Channel* channel) override;
- void OnFilterRemoved() override;
- void OnChannelClosing() override;
-
- // Received when browser process has created an audio input stream.
- void OnStreamCreated(int stream_id,
- base::SharedMemoryHandle handle,
-#if defined(OS_WIN)
- base::SyncSocket::Handle socket_handle,
-#else
- base::FileDescriptor socket_descriptor,
-#endif
- bool initially_muted);
-
- // Received when internal state of browser process' audio input stream has
- // encountered an error.
- void OnStreamError(int stream_id);
-
- // Received when a stream is muted or unmuted.
- void OnStreamMuted(int stream_id, bool is_muted);
-
- // A map of stream ids to delegates.
- base::IDMap<media::AudioInputIPCDelegate*> delegates_;
-
- // IPC sender for Send(), must only be accesed on |io_task_runner_|.
- IPC::Sender* sender_;
-
- // Task runner on which IPC calls are executed.
- const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- // The singleton instance for this filter.
- static AudioInputMessageFilter* g_filter;
-
- DISALLOW_COPY_AND_ASSIGN(AudioInputMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_AUDIO_INPUT_MESSAGE_FILTER_H_
diff --git a/chromium/content/renderer/media/audio_message_filter.cc b/chromium/content/renderer/media/audio_message_filter.cc
deleted file mode 100644
index b1f2106e781..00000000000
--- a/chromium/content/renderer/media/audio_message_filter.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/audio_message_filter.h"
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "content/common/media/audio_messages.h"
-#include "content/renderer/media/webrtc_logging.h"
-#include "content/renderer/render_thread_impl.h"
-#include "ipc/ipc_logging.h"
-
-namespace content {
-
-namespace {
-const int kStreamIDNotSet = -1;
-}
-
-class AudioMessageFilter::AudioOutputIPCImpl : public media::AudioOutputIPC {
- public:
- AudioOutputIPCImpl(const scoped_refptr<AudioMessageFilter>& filter,
- int render_frame_id);
- ~AudioOutputIPCImpl() override;
-
- // media::AudioOutputIPC implementation.
- void RequestDeviceAuthorization(media::AudioOutputIPCDelegate* delegate,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) override;
- void CreateStream(media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params) override;
- void PlayStream() override;
- void PauseStream() override;
- void CloseStream() override;
- void SetVolume(double volume) override;
-
- private:
- const scoped_refptr<AudioMessageFilter> filter_;
- const int render_frame_id_;
- int stream_id_;
- bool stream_created_;
-};
-
-AudioMessageFilter* AudioMessageFilter::g_filter = nullptr;
-
-AudioMessageFilter::AudioMessageFilter(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : sender_(nullptr), io_task_runner_(io_task_runner) {
- DCHECK(!g_filter);
- g_filter = this;
-}
-
-AudioMessageFilter::~AudioMessageFilter() {
- DCHECK_EQ(g_filter, this);
- g_filter = nullptr;
-}
-
-// static
-AudioMessageFilter* AudioMessageFilter::Get() {
- return g_filter;
-}
-
-AudioMessageFilter::AudioOutputIPCImpl::AudioOutputIPCImpl(
- const scoped_refptr<AudioMessageFilter>& filter,
- int render_frame_id)
- : filter_(filter),
- render_frame_id_(render_frame_id),
- stream_id_(kStreamIDNotSet),
- stream_created_(false) {}
-
-AudioMessageFilter::AudioOutputIPCImpl::~AudioOutputIPCImpl() {}
-
-std::unique_ptr<media::AudioOutputIPC> AudioMessageFilter::CreateAudioOutputIPC(
- int render_frame_id) {
- DCHECK_GT(render_frame_id, 0);
- return std::unique_ptr<media::AudioOutputIPC>(
- new AudioOutputIPCImpl(this, render_frame_id));
-}
-
-void AudioMessageFilter::AudioOutputIPCImpl::RequestDeviceAuthorization(
- media::AudioOutputIPCDelegate* delegate,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
- DCHECK(filter_->io_task_runner_->BelongsToCurrentThread());
- DCHECK(delegate);
- DCHECK_EQ(stream_id_, kStreamIDNotSet);
- DCHECK(!stream_created_);
-
- stream_id_ = filter_->delegates_.Add(delegate);
- filter_->Send(new AudioHostMsg_RequestDeviceAuthorization(
- stream_id_, render_frame_id_, session_id, device_id,
- url::Origin(security_origin)));
-}
-
-void AudioMessageFilter::AudioOutputIPCImpl::CreateStream(
- media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params) {
- DCHECK(filter_->io_task_runner_->BelongsToCurrentThread());
- DCHECK(!stream_created_);
- if (stream_id_ == kStreamIDNotSet)
- stream_id_ = filter_->delegates_.Add(delegate);
-
- filter_->Send(
- new AudioHostMsg_CreateStream(stream_id_, render_frame_id_, params));
- stream_created_ = true;
-}
-
-void AudioMessageFilter::AudioOutputIPCImpl::PlayStream() {
- DCHECK(stream_created_);
- filter_->Send(new AudioHostMsg_PlayStream(stream_id_));
-}
-
-void AudioMessageFilter::AudioOutputIPCImpl::PauseStream() {
- DCHECK(stream_created_);
- filter_->Send(new AudioHostMsg_PauseStream(stream_id_));
-}
-
-void AudioMessageFilter::AudioOutputIPCImpl::CloseStream() {
- DCHECK(filter_->io_task_runner_->BelongsToCurrentThread());
- DCHECK_NE(stream_id_, kStreamIDNotSet);
- filter_->Send(new AudioHostMsg_CloseStream(stream_id_));
- filter_->delegates_.Remove(stream_id_);
- stream_id_ = kStreamIDNotSet;
- stream_created_ = false;
-}
-
-void AudioMessageFilter::AudioOutputIPCImpl::SetVolume(double volume) {
- DCHECK(stream_created_);
- filter_->Send(new AudioHostMsg_SetVolume(stream_id_, volume));
-}
-
-void AudioMessageFilter::Send(IPC::Message* message) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- if (!sender_) {
- delete message;
- } else {
- sender_->Send(message);
- }
-}
-
-bool AudioMessageFilter::OnMessageReceived(const IPC::Message& message) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(AudioMessageFilter, message)
- IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized, OnDeviceAuthorized)
- IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated, OnStreamCreated)
- IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamError, OnStreamError)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void AudioMessageFilter::OnFilterAdded(IPC::Channel* channel) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- sender_ = channel;
-}
-
-void AudioMessageFilter::OnFilterRemoved() {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- // Once removed, a filter will not be used again. At this time all
- // delegates must be notified so they release their reference.
- OnChannelClosing();
-}
-
-void AudioMessageFilter::OnChannelClosing() {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- sender_ = nullptr;
-
- DLOG_IF(WARNING, !delegates_.IsEmpty())
- << "Not all audio devices have been closed.";
-
- base::IDMap<media::AudioOutputIPCDelegate*>::iterator it(&delegates_);
- while (!it.IsAtEnd()) {
- it.GetCurrentValue()->OnIPCClosed();
- delegates_.Remove(it.GetCurrentKey());
- it.Advance();
- }
-}
-
-void AudioMessageFilter::OnDeviceAuthorized(
- int stream_id,
- media::OutputDeviceStatus device_status,
- const media::AudioParameters& output_params,
- const std::string& matched_device_id) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id);
- if (!delegate)
- return;
-
- delegate->OnDeviceAuthorized(device_status, output_params, matched_device_id);
-}
-
-void AudioMessageFilter::OnStreamCreated(
- int stream_id,
- base::SharedMemoryHandle handle,
- base::SyncSocket::TransitDescriptor socket_descriptor) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- WebRtcLogMessage(base::StringPrintf(
- "AMF::OnStreamCreated. stream_id=%d",
- stream_id));
-
- base::SyncSocket::Handle socket_handle =
- base::SyncSocket::UnwrapHandle(socket_descriptor);
-
- media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id);
- if (!delegate) {
- DLOG(WARNING) << "Got OnStreamCreated() event for a non-existent or removed"
- << " audio renderer. (stream_id=" << stream_id << ").";
- base::SharedMemory::CloseHandle(handle);
- base::SyncSocket socket(socket_handle);
- return;
- }
- delegate->OnStreamCreated(handle, socket_handle);
-}
-
-void AudioMessageFilter::OnStreamError(int stream_id) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id);
- if (!delegate) {
- DLOG(WARNING) << "Got OnStreamError() event for a non-existent or"
- << " removed audio renderer.";
- return;
- }
- delegate->OnError();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/audio_message_filter.h b/chromium/content/renderer/media/audio_message_filter.h
deleted file mode 100644
index 22a15ca4e14..00000000000
--- a/chromium/content/renderer/media/audio_message_filter.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_AUDIO_MESSAGE_FILTER_H_
-#define CONTENT_RENDERER_MEDIA_AUDIO_MESSAGE_FILTER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/containers/id_map.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory.h"
-#include "base/sync_socket.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "ipc/message_filter.h"
-#include "media/audio/audio_output_ipc.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-
-// MessageFilter that handles audio messages and delegates them to audio
-// renderers. Created on render thread, AudioMessageFilter is operated on
-// IO thread (secondary thread of render process) it intercepts audio messages
-// and process them on IO thread since these messages are time critical.
-class CONTENT_EXPORT AudioMessageFilter : public IPC::MessageFilter {
- public:
- explicit AudioMessageFilter(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
-
- // Getter for the one AudioMessageFilter object.
- static AudioMessageFilter* Get();
-
- // Create an AudioOutputIPC to be owned by one delegate. |render_frame_id| is
- // the RenderFrame containing the entity producing the audio.
- //
- // The returned object is not thread-safe, and must be used on
- // |io_task_runner|.
- std::unique_ptr<media::AudioOutputIPC> CreateAudioOutputIPC(
- int render_frame_id);
-
- // IO task runner associated with this message filter.
- base::SingleThreadTaskRunner* io_task_runner() const {
- return io_task_runner_.get();
- }
-
- protected:
- ~AudioMessageFilter() override;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Basic);
- FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Delegates);
-
- // Implementation of media::AudioOutputIPC which augments IPC calls with
- // stream_id and the source render_frame_id.
- class AudioOutputIPCImpl;
-
- // Sends an IPC message using |sender_|.
- void Send(IPC::Message* message);
-
- // IPC::MessageFilter override. Called on |io_task_runner_|.
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnFilterAdded(IPC::Channel* channel) override;
- void OnFilterRemoved() override;
- void OnChannelClosing() override;
-
- // Received when the browser process has checked authorization to use an
- // audio output device.
- void OnDeviceAuthorized(int stream_id,
- media::OutputDeviceStatus device_status,
- const media::AudioParameters& output_params,
- const std::string& matched_device_id);
-
- // Received when browser process has created an audio output stream.
- void OnStreamCreated(int stream_id,
- base::SharedMemoryHandle handle,
- base::SyncSocket::TransitDescriptor socket_descriptor);
-
- // Received when internal state of browser process' audio output device has
- // changed.
- void OnStreamError(int stream_id);
-
- // IPC sender for Send(); must only be accessed on |io_task_runner_|.
- IPC::Sender* sender_;
-
- // A map of stream ids to delegates; must only be accessed on
- // |io_task_runner_|.
- base::IDMap<media::AudioOutputIPCDelegate*> delegates_;
-
- // Task runner on which IPC calls are executed.
- const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- // The singleton instance for this filter.
- static AudioMessageFilter* g_filter;
-
- DISALLOW_COPY_AND_ASSIGN(AudioMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_AUDIO_MESSAGE_FILTER_H_
diff --git a/chromium/content/renderer/media/audio_message_filter_unittest.cc b/chromium/content/renderer/media/audio_message_filter_unittest.cc
deleted file mode 100644
index f38c1ec47a5..00000000000
--- a/chromium/content/renderer/media/audio_message_filter_unittest.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "content/common/media/audio_messages.h"
-#include "content/renderer/media/audio_message_filter.h"
-#include "media/audio/audio_output_ipc.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-namespace {
-
-const int kRenderFrameId = 2;
-const char kEmptyMatchedDeviceId[] = "";
-
-class MockAudioDelegate : public media::AudioOutputIPCDelegate {
- public:
- MockAudioDelegate() {
- Reset();
- }
- ~MockAudioDelegate() override {
- if (handle_.IsValid())
- handle_.Close();
- }
-
- void OnError() override { error_received_ = true; }
-
- void OnDeviceAuthorized(media::OutputDeviceStatus device_status,
- const media::AudioParameters& output_params,
- const std::string& matched_device_id) override {
- device_authorized_received_ = true;
- device_status_ = device_status;
- output_params_ = output_params;
- matched_device_id_ = matched_device_id;
- }
-
- void OnStreamCreated(base::SharedMemoryHandle handle,
- base::SyncSocket::Handle) override {
- created_received_ = true;
- handle_ = handle;
- }
-
- void OnIPCClosed() override {}
-
- void Reset() {
- error_received_ = false;
-
- device_authorized_received_ = false;
- output_params_ = media::AudioParameters();
- device_status_ = media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
-
- created_received_ = false;
- if (handle_.IsValid())
- handle_.Close();
- handle_ = base::SharedMemoryHandle();
-
- volume_received_ = false;
- volume_ = 0;
- }
-
- bool error_received() { return error_received_; }
-
- bool device_authorized_received() { return device_authorized_received_; }
- media::AudioParameters output_params() { return output_params_; }
- media::OutputDeviceStatus device_status() { return device_status_; }
-
- bool created_received() { return created_received_; }
- base::SharedMemoryHandle handle() { return handle_; }
-
- private:
- bool error_received_;
-
- bool device_authorized_received_;
- media::AudioParameters output_params_;
- media::OutputDeviceStatus device_status_;
- std::string matched_device_id_;
-
- bool created_received_;
- base::SharedMemoryHandle handle_;
-
- bool volume_received_;
- double volume_;
-
- DISALLOW_COPY_AND_ASSIGN(MockAudioDelegate);
-};
-
-media::AudioParameters MockOutputParams() {
- return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16,
- 100);
-}
-
-} // namespace
-
-TEST(AudioMessageFilterTest, Basic) {
- base::MessageLoopForIO message_loop;
-
- scoped_refptr<AudioMessageFilter> filter(
- new AudioMessageFilter(message_loop.task_runner()));
-
- MockAudioDelegate delegate;
- const std::unique_ptr<media::AudioOutputIPC> ipc =
- filter->CreateAudioOutputIPC(kRenderFrameId);
- static const int kSessionId = 0;
- static const std::string kDeviceId;
- static const url::Origin kSecurityOrigin;
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId,
- kSecurityOrigin);
- ipc->CreateStream(&delegate, media::AudioParameters());
- static const int kStreamId = 1;
- EXPECT_EQ(&delegate, filter->delegates_.Lookup(kStreamId));
-
- // AudioMsg_NotifyDeviceAuthorized
- EXPECT_FALSE(delegate.device_authorized_received());
- filter->OnMessageReceived(AudioMsg_NotifyDeviceAuthorized(
- kStreamId, media::OUTPUT_DEVICE_STATUS_OK, MockOutputParams(),
- kEmptyMatchedDeviceId));
- EXPECT_TRUE(delegate.device_authorized_received());
- EXPECT_TRUE(delegate.output_params().Equals(MockOutputParams()));
- delegate.Reset();
-
- // AudioMsg_NotifyStreamCreated
- base::SyncSocket::TransitDescriptor socket_descriptor;
- EXPECT_FALSE(delegate.created_received());
- filter->OnMessageReceived(AudioMsg_NotifyStreamCreated(
- kStreamId, base::SharedMemoryHandle(), socket_descriptor));
- EXPECT_TRUE(delegate.created_received());
- EXPECT_FALSE(base::SharedMemory::IsHandleValid(delegate.handle()));
- delegate.Reset();
-
- // AudioMsg_NotifyStreamStateChanged
- EXPECT_FALSE(delegate.error_received());
- filter->OnMessageReceived(AudioMsg_NotifyStreamError(kStreamId));
- EXPECT_TRUE(delegate.error_received());
- delegate.Reset();
-
- ipc->CloseStream();
- EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(nullptr),
- filter->delegates_.Lookup(kStreamId));
-}
-
-TEST(AudioMessageFilterTest, Delegates) {
- base::MessageLoopForIO message_loop;
-
- scoped_refptr<AudioMessageFilter> filter(
- new AudioMessageFilter(message_loop.task_runner()));
-
- MockAudioDelegate delegate1;
- MockAudioDelegate delegate2;
- const std::unique_ptr<media::AudioOutputIPC> ipc1 =
- filter->CreateAudioOutputIPC(kRenderFrameId);
- const std::unique_ptr<media::AudioOutputIPC> ipc2 =
- filter->CreateAudioOutputIPC(kRenderFrameId);
- ipc1->CreateStream(&delegate1, media::AudioParameters());
- ipc2->CreateStream(&delegate2, media::AudioParameters());
- static const int kStreamId1 = 1;
- static const int kStreamId2 = 2;
- EXPECT_EQ(&delegate1, filter->delegates_.Lookup(kStreamId1));
- EXPECT_EQ(&delegate2, filter->delegates_.Lookup(kStreamId2));
-
- // Send an IPC message. Make sure the correct delegate gets called.
- EXPECT_FALSE(delegate1.error_received());
- EXPECT_FALSE(delegate2.error_received());
- filter->OnMessageReceived(AudioMsg_NotifyStreamError(kStreamId1));
- EXPECT_TRUE(delegate1.error_received());
- EXPECT_FALSE(delegate2.error_received());
- delegate1.Reset();
-
- EXPECT_FALSE(delegate1.error_received());
- EXPECT_FALSE(delegate2.error_received());
- filter->OnMessageReceived(AudioMsg_NotifyStreamError(kStreamId2));
- EXPECT_FALSE(delegate1.error_received());
- EXPECT_TRUE(delegate2.error_received());
- delegate2.Reset();
-
- base::RunLoop().RunUntilIdle();
-
- ipc1->CloseStream();
- ipc2->CloseStream();
- EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(nullptr),
- filter->delegates_.Lookup(kStreamId1));
- EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(nullptr),
- filter->delegates_.Lookup(kStreamId2));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/audio_output_ipc_factory.cc b/chromium/content/renderer/media/audio_output_ipc_factory.cc
index 8281bf4e185..829d85a8e6c 100644
--- a/chromium/content/renderer/media/audio_output_ipc_factory.cc
+++ b/chromium/content/renderer/media/audio_output_ipc_factory.cc
@@ -8,7 +8,6 @@
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
-#include "content/renderer/media/audio_message_filter.h"
#include "content/renderer/media/mojo_audio_output_ipc.h"
#include "services/service_manager/public/cpp/interface_provider.h"
@@ -17,10 +16,8 @@ namespace content {
AudioOutputIPCFactory* AudioOutputIPCFactory::instance_ = nullptr;
AudioOutputIPCFactory::AudioOutputIPCFactory(
- scoped_refptr<AudioMessageFilter> audio_message_filter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : audio_message_filter_(std::move(audio_message_filter)),
- io_task_runner_(std::move(io_task_runner)) {
+ : io_task_runner_(std::move(io_task_runner)) {
DCHECK(!instance_);
instance_ = this;
}
@@ -34,21 +31,16 @@ AudioOutputIPCFactory::~AudioOutputIPCFactory() {
std::unique_ptr<media::AudioOutputIPC>
AudioOutputIPCFactory::CreateAudioOutputIPC(int frame_id) const {
- if (UsingMojoFactories()) {
// Unretained is safe due to the contract at the top of the header file.
return std::make_unique<MojoAudioOutputIPC>(
base::BindRepeating(&AudioOutputIPCFactory::GetRemoteFactory,
base::Unretained(this), frame_id),
io_task_runner_);
- }
- return audio_message_filter_->CreateAudioOutputIPC(frame_id);
}
-void AudioOutputIPCFactory::MaybeRegisterRemoteFactory(
+void AudioOutputIPCFactory::RegisterRemoteFactory(
int frame_id,
service_manager::InterfaceProvider* interface_provider) {
- if (!UsingMojoFactories())
- return;
mojom::RendererAudioOutputStreamFactoryPtr factory_ptr;
interface_provider->GetInterface(&factory_ptr);
// PassInterface unbinds the message pipe from the current thread. This
@@ -62,8 +54,6 @@ void AudioOutputIPCFactory::MaybeRegisterRemoteFactory(
}
void AudioOutputIPCFactory::MaybeDeregisterRemoteFactory(int frame_id) {
- if (!UsingMojoFactories())
- return;
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
@@ -74,7 +64,6 @@ void AudioOutputIPCFactory::MaybeDeregisterRemoteFactory(int frame_id) {
mojom::RendererAudioOutputStreamFactory*
AudioOutputIPCFactory::GetRemoteFactory(int frame_id) const {
DCHECK(io_task_runner_->BelongsToCurrentThread());
- DCHECK(UsingMojoFactories());
auto it = factory_ptrs_.find(frame_id);
return it == factory_ptrs_.end() ? nullptr : it->second.get();
}
@@ -83,7 +72,6 @@ void AudioOutputIPCFactory::RegisterRemoteFactoryOnIOThread(
int frame_id,
mojom::RendererAudioOutputStreamFactoryPtrInfo factory_ptr_info) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
- DCHECK(UsingMojoFactories());
std::pair<StreamFactoryMap::iterator, bool> emplace_result =
factory_ptrs_.emplace(frame_id,
mojo::MakeProxy(std::move(factory_ptr_info)));
@@ -106,7 +94,6 @@ void AudioOutputIPCFactory::RegisterRemoteFactoryOnIOThread(
void AudioOutputIPCFactory::MaybeDeregisterRemoteFactoryOnIOThread(
int frame_id) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
- DCHECK(UsingMojoFactories());
// This function can be called both by the frame and the connection error
// handler of the factory pointer. Calling erase multiple times even though
// there is nothing to erase is safe, so we don't have to handle this in any
@@ -114,8 +101,4 @@ void AudioOutputIPCFactory::MaybeDeregisterRemoteFactoryOnIOThread(
factory_ptrs_.erase(frame_id);
}
-bool AudioOutputIPCFactory::UsingMojoFactories() const {
- return audio_message_filter_ == nullptr;
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/audio_output_ipc_factory.h b/chromium/content/renderer/media/audio_output_ipc_factory.h
index 0e6ff517b8c..6cb588204f5 100644
--- a/chromium/content/renderer/media/audio_output_ipc_factory.h
+++ b/chromium/content/renderer/media/audio_output_ipc_factory.h
@@ -11,7 +11,6 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
-#include "content/renderer/media/audio_message_filter.h"
namespace base {
class SingleThreadTaskRunner;
@@ -27,20 +26,18 @@ class InterfaceProvider;
namespace content {
-// This is a factory for AudioOutputIPC objects. It has two modes, using either
-// AudioMessageFilter or Mojo RendererAudioOutputStreamFactory objects. It is
-// threadsafe. This class is designed to be leaked at shutdown, as it posts
-// tasks to itself using base::Unretained and also hands out references to
-// itself in the AudioOutputIPCs it creates, but in the case where the owner is
-// sure that there are no outstanding references (such as in a unit test), the
-// class can be destructed.
+// This is a factory for AudioOutputIPC objects. It is threadsafe. This class
+// is designed to be leaked at shutdown, as it posts tasks to itself using
+// base::Unretained and also hands out references to itself in the
+// AudioOutputIPCs it creates, but in the case where the owner is sure that
+// there are no outstanding references (such as in a unit test), the class can
+// be destructed.
// TODO(maxmorin): Registering the factories for each frame will become
// unnecessary when https://crbug.com/668275 is fixed. When that is done, this
// class can be greatly simplified.
class CONTENT_EXPORT AudioOutputIPCFactory {
public:
AudioOutputIPCFactory(
- scoped_refptr<AudioMessageFilter> audio_message_filter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~AudioOutputIPCFactory();
@@ -52,7 +49,7 @@ class CONTENT_EXPORT AudioOutputIPCFactory {
// Enables |this| to create MojoAudioOutputIPCs for the specified frame.
// Does nothing if not using mojo factories.
- void MaybeRegisterRemoteFactory(
+ void RegisterRemoteFactory(
int frame_id,
service_manager::InterfaceProvider* interface_provider);
@@ -82,9 +79,6 @@ class CONTENT_EXPORT AudioOutputIPCFactory {
// Maps frame id to the corresponding factory.
StreamFactoryMap factory_ptrs_;
- // If this is non-null, it will be used rather than using mojo implementation.
- const scoped_refptr<AudioMessageFilter> audio_message_filter_;
-
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// Global instance, set in constructor and unset in destructor.
diff --git a/chromium/content/renderer/media/audio_output_ipc_factory_unittest.cc b/chromium/content/renderer/media/audio_output_ipc_factory_unittest.cc
index 68b5ee6d419..6f675a57444 100644
--- a/chromium/content/renderer/media/audio_output_ipc_factory_unittest.cc
+++ b/chromium/content/renderer/media/audio_output_ipc_factory_unittest.cc
@@ -11,7 +11,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
-#include "content/renderer/media/audio_message_filter.h"
+#include "media/audio/audio_output_ipc.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -73,7 +73,8 @@ class FakeAudioOutputIPCDelegate : public media::AudioOutputIPCDelegate {
const media::AudioParameters& output_params,
const std::string& matched_device_id) override {}
void OnStreamCreated(base::SharedMemoryHandle handle,
- base::SyncSocket::Handle socket_handle) override {}
+ base::SyncSocket::Handle socket_handle,
+ bool playing_automatically) override {}
void OnIPCClosed() override {}
};
@@ -86,8 +87,7 @@ class AudioOutputIPCFactoryTest : public testing::Test {
void RequestAuthorizationOnIOThread(
std::unique_ptr<media::AudioOutputIPC> output_ipc) {
- output_ipc->RequestDeviceAuthorization(&fake_delegate, 0, "",
- url::Origin());
+ output_ipc->RequestDeviceAuthorization(&fake_delegate, 0, "");
output_ipc->CloseStream();
}
@@ -112,9 +112,9 @@ TEST_F(AudioOutputIPCFactoryTest, CallFactoryFromIOThread) {
base::BindRepeating(&FakeRemoteFactory::Bind,
base::Unretained(&remote_factory)));
- AudioOutputIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+ AudioOutputIPCFactory ipc_factory(io_thread->task_runner());
- ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId, &interface_provider);
+ ipc_factory.RegisterRemoteFactory(kRenderFrameId, &interface_provider);
// To make sure that the pointer stored in |ipc_factory| is connected to
// |remote_factory|, and also that it's bound to |io_thread|, we create an
@@ -156,11 +156,11 @@ TEST_F(AudioOutputIPCFactoryTest, SeveralFactories) {
base::RunLoop().RunUntilIdle();
- AudioOutputIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+ AudioOutputIPCFactory ipc_factory(io_thread->task_runner());
for (size_t i = 0; i < n_factories; i++) {
- ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId + i,
- &interface_providers[i]);
+ ipc_factory.RegisterRemoteFactory(kRenderFrameId + i,
+ &interface_providers[i]);
}
base::RunLoop run_loop;
@@ -208,9 +208,9 @@ TEST_F(AudioOutputIPCFactoryTest, RegisterDeregisterBackToBack_Deregisters) {
base::BindRepeating(&FakeRemoteFactory::Bind,
base::Unretained(&remote_factory)));
- AudioOutputIPCFactory ipc_factory(nullptr, io_thread->task_runner());
+ AudioOutputIPCFactory ipc_factory(io_thread->task_runner());
- ipc_factory.MaybeRegisterRemoteFactory(kRenderFrameId, &interface_provider);
+ ipc_factory.RegisterRemoteFactory(kRenderFrameId, &interface_provider);
ipc_factory.MaybeDeregisterRemoteFactory(kRenderFrameId);
// That there is no factory remaining at destruction is DCHECKed in the
// AudioOutputIPCFactory destructor.
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
index 9d646f3f91c..942553572ad 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -81,11 +82,13 @@ media::AudioParameters GetMixerOutputParams(
DCHECK_NE(output_buffer_size, 0);
- // Force to 16-bit output for now since we know that works everywhere;
- // ChromeOS does not support other bit depths.
media::AudioParameters params(input_params.format(),
input_params.channel_layout(),
- output_sample_rate, 16, output_buffer_size);
+ output_sample_rate, output_buffer_size);
+
+ // Use the actual channel count when the channel layout is "DISCRETE".
+ if (input_params.channel_layout() == media::CHANNEL_LAYOUT_DISCRETE)
+ params.set_channels_for_discrete(input_params.channels());
// Specify the latency info to be passed to the browser side.
params.set_latency_tag(latency);
@@ -145,7 +148,6 @@ media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput(
int source_render_frame_id,
int session_id,
const std::string& device_id,
- const url::Origin& security_origin,
media::AudioLatency::LatencyType latency) {
// AudioRendererMixerManager lives on the renderer thread and is destroyed on
// renderer thread destruction, so it's safe to pass its pointer to a mixer
@@ -154,11 +156,10 @@ media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput(
this, source_render_frame_id,
media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
device_id)
- ? GetOutputDeviceInfo(source_render_frame_id, session_id, device_id,
- security_origin)
+ ? GetOutputDeviceInfo(source_render_frame_id, session_id, device_id)
.device_id()
: device_id,
- security_origin, latency);
+ latency);
}
media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
@@ -166,13 +167,11 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
const media::AudioParameters& input_params,
media::AudioLatency::LatencyType latency,
const std::string& device_id,
- const url::Origin& security_origin,
media::OutputDeviceStatus* device_status) {
// Effects are not passed through to output creation, so ensure none are set.
DCHECK_EQ(input_params.effects(), media::AudioParameters::NO_EFFECTS);
- const MixerKey key(source_render_frame_id, input_params, latency, device_id,
- security_origin);
+ const MixerKey key(source_render_frame_id, input_params, latency, device_id);
base::AutoLock auto_lock(mixers_lock_);
// Update latency map when the mixer is requested, i.e. there is an attempt to
@@ -199,7 +198,7 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
}
scoped_refptr<media::AudioRendererSink> sink =
- sink_cache_->GetSink(source_render_frame_id, device_id, security_origin);
+ sink_cache_->GetSink(source_render_frame_id, device_id);
const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo();
if (device_status)
@@ -244,23 +243,20 @@ void AudioRendererMixerManager::ReturnMixer(media::AudioRendererMixer* mixer) {
media::OutputDeviceInfo AudioRendererMixerManager::GetOutputDeviceInfo(
int source_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
- return sink_cache_->GetSinkInfo(source_render_frame_id, session_id, device_id,
- security_origin);
+ const std::string& device_id) {
+ return sink_cache_->GetSinkInfo(source_render_frame_id, session_id,
+ device_id);
}
AudioRendererMixerManager::MixerKey::MixerKey(
int source_render_frame_id,
const media::AudioParameters& params,
media::AudioLatency::LatencyType latency,
- const std::string& device_id,
- const url::Origin& security_origin)
+ const std::string& device_id)
: source_render_frame_id(source_render_frame_id),
params(params),
latency(latency),
- device_id(device_id),
- security_origin(security_origin) {}
+ device_id(device_id) {}
AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default;
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.h b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
index 7d77212bbe6..f7821b05759 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.h
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
@@ -18,7 +18,6 @@
#include "media/base/audio_parameters.h"
#include "media/base/audio_renderer_mixer_pool.h"
#include "media/base/output_device_info.h"
-#include "url/origin.h"
namespace media {
class AudioRendererMixer;
@@ -38,12 +37,6 @@ class AudioRendererSinkCache;
//
// There should only be one instance of AudioRendererMixerManager per render
// thread.
-//
-// TODO(dalecurtis): Right now we require AudioParameters to be an exact match
-// when we should be able to ignore bits per channel since we're only dealing
-// with floats. However, bits per channel is currently used to interleave the
-// audio data by AudioOutputDevice::AudioThreadCallback::Process for consumption
-// via the shared memory. See http://crbug.com/114700.
class CONTENT_EXPORT AudioRendererMixerManager
: public media::AudioRendererMixerPool {
public:
@@ -55,15 +48,14 @@ class CONTENT_EXPORT AudioRendererMixerManager
// retrieve an AudioRendererMixer instance from AudioRendererMixerManager.
// |source_render_frame_id| refers to the RenderFrame containing the entity
// rendering the audio. Caller must ensure AudioRendererMixerManager outlives
- // the returned input. |device_id|, |session_id| and |security_origin|
- // identify the output device to use. If |device_id| is empty and |session_id|
- // is nonzero, output device associated with the opened input device
- // designated by |session_id| is used. Otherwise, |session_id| is ignored.
+ // the returned input. |device_id| and |session_id| identify the output
+ // device to use. If |device_id| is empty and |session_id| is nonzero,
+ // output device associated with the opened input device designated by
+ // |session_id| is used. Otherwise, |session_id| is ignored.
media::AudioRendererMixerInput* CreateInput(
int source_render_frame_id,
int session_id,
const std::string& device_id,
- const url::Origin& security_origin,
media::AudioLatency::LatencyType latency);
// AudioRendererMixerPool implementation.
@@ -73,7 +65,6 @@ class CONTENT_EXPORT AudioRendererMixerManager
const media::AudioParameters& input_params,
media::AudioLatency::LatencyType latency,
const std::string& device_id,
- const url::Origin& security_origin,
media::OutputDeviceStatus* device_status) final;
void ReturnMixer(media::AudioRendererMixer* mixer) final;
@@ -81,8 +72,7 @@ class CONTENT_EXPORT AudioRendererMixerManager
media::OutputDeviceInfo GetOutputDeviceInfo(
int source_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) final;
+ const std::string& device_id) final;
protected:
explicit AudioRendererMixerManager(
@@ -97,18 +87,16 @@ class CONTENT_EXPORT AudioRendererMixerManager
MixerKey(int source_render_frame_id,
const media::AudioParameters& params,
media::AudioLatency::LatencyType latency,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
MixerKey(const MixerKey& other);
int source_render_frame_id;
media::AudioParameters params;
media::AudioLatency::LatencyType latency;
std::string device_id;
- url::Origin security_origin;
};
// Custom compare operator for the AudioRendererMixerMap. Allows reuse of
- // mixers where only irrelevant keys mismatch; e.g., effects, bits per sample.
+ // mixers where only irrelevant keys mismatch.
struct MixerKeyCompare {
bool operator()(const MixerKey& a, const MixerKey& b) const {
if (a.source_render_frame_id != b.source_render_frame_id)
@@ -123,24 +111,20 @@ class CONTENT_EXPORT AudioRendererMixerManager
// adding support for it.
DCHECK_NE(media::AudioLatency::LATENCY_EXACT_MS, a.latency);
- // Ignore effects(), bits_per_sample(), format(), and frames_per_buffer(),
- // these parameters do not affect mixer reuse. All AudioRendererMixer
- // units disable FIFO, so frames_per_buffer() can be safely ignored.
+ // Ignore effects(), format(), and frames_per_buffer(), these parameters
+ // do not affect mixer reuse. All AudioRendererMixer units disable FIFO,
+ // so frames_per_buffer() can be safely ignored.
if (a.params.channel_layout() != b.params.channel_layout())
return a.params.channel_layout() < b.params.channel_layout();
if (media::AudioDeviceDescription::IsDefaultDevice(a.device_id) &&
media::AudioDeviceDescription::IsDefaultDevice(b.device_id)) {
// Both device IDs represent the same default device => do not compare
- // them; the default device is always authorized => ignoring security
- // origin.
+ // them.
return false;
}
- if (a.device_id != b.device_id)
- return a.device_id < b.device_id;
-
- return a.security_origin < b.security_origin;
+ return a.device_id < b.device_id;
}
};
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
index 396256bd171..bba7a3e8224 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
@@ -20,12 +20,10 @@
#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
namespace content {
namespace {
-const int kBitsPerChannel = 16;
const int kSampleRate = 48000;
const int kBufferSize = 8192;
const int kHardwareSampleRate = 44100;
@@ -40,7 +38,7 @@ const char kNonexistentDeviceId[] = "nonexistent-device-id";
const int kRenderFrameId = 124;
const int kAnotherRenderFrameId = 678;
-} // namespace;
+} // namespace
using media::AudioParameters;
using media::AudioLatency;
@@ -51,8 +49,7 @@ class FakeAudioRendererSinkCache : public AudioRendererSinkCache {
base::Callback<scoped_refptr<media::AudioRendererSink>(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin)>;
+ const std::string& device_id)>;
using ReleaseSinkCallback =
base::Callback<void(const media::AudioRendererSink*)>;
@@ -61,22 +58,17 @@ class FakeAudioRendererSinkCache : public AudioRendererSinkCache {
const ReleaseSinkCallback& release_sink_cb)
: get_sink_cb_(get_sink_cb), release_sink_cb_(release_sink_cb) {}
- media::OutputDeviceInfo GetSinkInfo(
- int source_render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) final {
- return get_sink_cb_
- .Run(source_render_frame_id, session_id, device_id, security_origin)
+ media::OutputDeviceInfo GetSinkInfo(int source_render_frame_id,
+ int session_id,
+ const std::string& device_id) final {
+ return get_sink_cb_.Run(source_render_frame_id, session_id, device_id)
->GetOutputDeviceInfo();
}
scoped_refptr<media::AudioRendererSink> GetSink(
int source_render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) final {
- return get_sink_cb_.Run(source_render_frame_id, 0, device_id,
- security_origin);
+ const std::string& device_id) final {
+ return get_sink_cb_.Run(source_render_frame_id, 0, device_id);
}
void ReleaseSink(const media::AudioRendererSink* sink) final {
@@ -104,25 +96,22 @@ class AudioRendererMixerManagerTest : public testing::Test {
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout,
kHardwareSampleRate,
- kBitsPerChannel,
kHardwareBufferSize))),
mock_sink_no_device_(new media::MockAudioRendererSink(
kNonexistentDeviceId,
media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND)),
mock_sink_matched_device_(
new media::MockAudioRendererSink(kMatchedDeviceId,
- media::OUTPUT_DEVICE_STATUS_OK)),
- kSecurityOrigin2(url::Origin::Create(GURL("http://localhost"))) {}
+ media::OUTPUT_DEVICE_STATUS_OK)) {}
media::AudioRendererMixer* GetMixer(
int source_render_frame_id,
const media::AudioParameters& params,
AudioLatency::LatencyType latency,
const std::string& device_id,
- const url::Origin& security_origin,
media::OutputDeviceStatus* device_status) {
return manager_->GetMixer(source_render_frame_id, params, latency,
- device_id, security_origin, device_status);
+ device_id, device_status);
}
void ReturnMixer(media::AudioRendererMixer* mixer) {
@@ -138,8 +127,7 @@ class AudioRendererMixerManagerTest : public testing::Test {
scoped_refptr<media::AudioRendererSink> GetSinkPtr(
int source_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
if ((device_id == kDefaultDeviceId) || (device_id == kAnotherDeviceId)) {
// We don't care about separate sinks for these devices.
return mock_sink_;
@@ -165,10 +153,6 @@ class AudioRendererMixerManagerTest : public testing::Test {
scoped_refptr<media::MockAudioRendererSink> mock_sink_no_device_;
scoped_refptr<media::MockAudioRendererSink> mock_sink_matched_device_;
- // To avoid global/static non-POD constants.
- const url::Origin kSecurityOrigin;
- const url::Origin kSecurityOrigin2;
-
private:
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest);
};
@@ -188,31 +172,30 @@ TEST_F(AudioRendererMixerManagerTest, GetReturnMixer) {
EXPECT_EQ(0, mixer_count());
media::AudioParameters params1(media::AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, kSampleRate, kBitsPerChannel,
- kBufferSize);
+ kChannelLayout, kSampleRate, kBufferSize);
media::AudioRendererMixer* mixer1 =
GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
// The same parameters should return the same mixer1.
EXPECT_EQ(mixer1,
GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr));
+ kDefaultDeviceId, nullptr));
EXPECT_EQ(1, mixer_count());
// Return the extra mixer we just acquired.
ReturnMixer(mixer1);
EXPECT_EQ(1, mixer_count());
- media::AudioParameters params2(
- AudioParameters::AUDIO_PCM_LINEAR, kAnotherChannelLayout, kSampleRate * 2,
- kBitsPerChannel, kBufferSize * 2);
+ media::AudioParameters params2(AudioParameters::AUDIO_PCM_LINEAR,
+ kAnotherChannelLayout, kSampleRate * 2,
+ kBufferSize * 2);
media::AudioRendererMixer* mixer2 =
GetMixer(kRenderFrameId, params2, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer2);
EXPECT_EQ(2, mixer_count());
@@ -239,11 +222,10 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout,
kSampleRate,
- kBitsPerChannel,
kBufferSize);
media::AudioRendererMixer* mixer1 =
GetMixer(kRenderFrameId, params1, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
@@ -252,11 +234,10 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
media::AudioParameters params2(AudioParameters::AUDIO_PCM_LOW_LATENCY,
kChannelLayout,
kSampleRate * 2,
- kBitsPerChannel * 2,
kBufferSize * 2);
media::AudioRendererMixer* mixer2 =
GetMixer(kRenderFrameId, params2, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
EXPECT_EQ(mixer1, mixer2);
EXPECT_EQ(1, mixer_count());
ReturnMixer(mixer2);
@@ -266,12 +247,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
media::AudioParameters params3(AudioParameters::AUDIO_PCM_LOW_LATENCY,
kAnotherChannelLayout,
kSampleRate,
- kBitsPerChannel,
kBufferSize);
ASSERT_NE(params3.channel_layout(), params1.channel_layout());
media::AudioRendererMixer* mixer3 =
GetMixer(kRenderFrameId, params3, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
EXPECT_NE(mixer1, mixer3);
EXPECT_EQ(2, mixer_count());
ReturnMixer(mixer3);
@@ -295,22 +275,20 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) {
// We expect 2 mixers to be created; each of them should release the sink.
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2);
- media::AudioParameters params(
- AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
- kBitsPerChannel, kBufferSize);
+ media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout, kSampleRate, kBufferSize);
// Create two mixer inputs and ensure this doesn't instantiate any mixers yet.
EXPECT_EQ(0, mixer_count());
media::FakeAudioRenderCallback callback(0, kSampleRate);
- scoped_refptr<media::AudioRendererMixerInput> input(
- manager_->CreateInput(kRenderFrameId, 0, kDefaultDeviceId,
- kSecurityOrigin, AudioLatency::LATENCY_PLAYBACK));
+ scoped_refptr<media::AudioRendererMixerInput> input(manager_->CreateInput(
+ kRenderFrameId, 0, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK));
input->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
media::FakeAudioRenderCallback another_callback(1, kSampleRate);
scoped_refptr<media::AudioRendererMixerInput> another_input(
manager_->CreateInput(kAnotherRenderFrameId, 0, kDefaultDeviceId,
- kSecurityOrigin, AudioLatency::LATENCY_PLAYBACK));
+ AudioLatency::LATENCY_PLAYBACK));
another_input->Initialize(params, &another_callback);
EXPECT_EQ(0, mixer_count());
@@ -349,40 +327,36 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) {
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_matched_device_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, kSampleRate, kBitsPerChannel,
- kBufferSize);
+ kChannelLayout, kSampleRate, kBufferSize);
media::FakeAudioRenderCallback callback(0, kSampleRate);
EXPECT_EQ(0, mixer_count());
// Empty device id, zero session id;
scoped_refptr<media::AudioRendererMixerInput> input_to_default_device(
manager_->CreateInput(kRenderFrameId, 0, // session_id
- std::string(), kSecurityOrigin,
- AudioLatency::LATENCY_PLAYBACK));
+ std::string(), AudioLatency::LATENCY_PLAYBACK));
input_to_default_device->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
// Specific device id, zero session id;
scoped_refptr<media::AudioRendererMixerInput> input_to_matched_device(
manager_->CreateInput(kRenderFrameId, 0, // session_id
- kMatchedDeviceId, kSecurityOrigin,
- AudioLatency::LATENCY_PLAYBACK));
+ kMatchedDeviceId, AudioLatency::LATENCY_PLAYBACK));
input_to_matched_device->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
// Specific device id, non-zero session id (to be ignored);
scoped_refptr<media::AudioRendererMixerInput> input_to_another_device(
manager_->CreateInput(kRenderFrameId, 1, // session id
- kAnotherDeviceId, kSecurityOrigin,
- AudioLatency::LATENCY_PLAYBACK));
+ kAnotherDeviceId, AudioLatency::LATENCY_PLAYBACK));
input_to_another_device->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
// Empty device id, non-zero session id;
scoped_refptr<media::AudioRendererMixerInput>
- input_to_matched_device_with_session_id(manager_->CreateInput(
- kRenderFrameId, 2, // session id
- std::string(), kSecurityOrigin, AudioLatency::LATENCY_PLAYBACK));
+ input_to_matched_device_with_session_id(
+ manager_->CreateInput(kRenderFrameId, 2, // session id
+ std::string(), AudioLatency::LATENCY_PLAYBACK));
input_to_matched_device_with_session_id->Initialize(params, &callback);
EXPECT_EQ(0, mixer_count());
@@ -417,50 +391,39 @@ TEST_F(AudioRendererMixerManagerTest, CreateInputWithSessionId) {
}
// Verify GetMixer() correctly creates different mixers with the same
-// parameters, but different device ID and/or security origin
+// parameters, but different device ID.
TEST_F(AudioRendererMixerManagerTest, MixerDevices) {
- EXPECT_CALL(*mock_sink_.get(), Start()).Times(3);
- EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3);
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(2);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
EXPECT_EQ(0, mixer_count());
- // We expect 3 mixers to be created; each of them should release a sink.
- EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(3);
+ // We expect 2 mixers to be created; each of them should release a sink.
+ EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(2);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, kSampleRate, kBitsPerChannel,
- kBufferSize);
+ kChannelLayout, kSampleRate, kBufferSize);
media::AudioRendererMixer* mixer1 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
media::AudioRendererMixer* mixer2 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kAnotherDeviceId, kSecurityOrigin, nullptr);
+ kAnotherDeviceId, nullptr);
ASSERT_TRUE(mixer2);
EXPECT_EQ(2, mixer_count());
EXPECT_NE(mixer1, mixer2);
- media::AudioRendererMixer* mixer3 =
- GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kAnotherDeviceId, kSecurityOrigin2, nullptr);
- ASSERT_TRUE(mixer3);
- EXPECT_EQ(3, mixer_count());
- EXPECT_NE(mixer1, mixer3);
- EXPECT_NE(mixer2, mixer3);
-
ReturnMixer(mixer1);
- EXPECT_EQ(2, mixer_count());
- ReturnMixer(mixer2);
EXPECT_EQ(1, mixer_count());
- ReturnMixer(mixer3);
+ ReturnMixer(mixer2);
EXPECT_EQ(0, mixer_count());
}
// Verify GetMixer() correctly deduplicate mixers with the same
-// parameters, different security origins but default device ID
-TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) {
+// parameters and default device ID, even if one is "" and one is "default".
+TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentDefaultDeviceIDs) {
EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
EXPECT_EQ(0, mixer_count());
@@ -469,42 +432,23 @@ TEST_F(AudioRendererMixerManagerTest, OneMixerDifferentOriginsDefaultDevice) {
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, kSampleRate, kBitsPerChannel,
- kBufferSize);
+ kChannelLayout, kSampleRate, kBufferSize);
media::AudioRendererMixer* mixer1 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
media::AudioRendererMixer* mixer2 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- std::string(), kSecurityOrigin, nullptr);
+ std::string(), nullptr);
ASSERT_TRUE(mixer2);
EXPECT_EQ(1, mixer_count());
EXPECT_EQ(mixer1, mixer2);
- media::AudioRendererMixer* mixer3 =
- GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin2, nullptr);
- ASSERT_TRUE(mixer3);
- EXPECT_EQ(1, mixer_count());
- EXPECT_EQ(mixer1, mixer3);
-
- media::AudioRendererMixer* mixer4 =
- GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- std::string(), kSecurityOrigin2, nullptr);
- ASSERT_TRUE(mixer4);
- EXPECT_EQ(1, mixer_count());
- EXPECT_EQ(mixer1, mixer4);
-
ReturnMixer(mixer1);
EXPECT_EQ(1, mixer_count());
ReturnMixer(mixer2);
- EXPECT_EQ(1, mixer_count());
- ReturnMixer(mixer3);
- EXPECT_EQ(1, mixer_count());
- ReturnMixer(mixer4);
EXPECT_EQ(0, mixer_count());
}
@@ -517,13 +461,12 @@ TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) {
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_no_device_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, kSampleRate, kBitsPerChannel,
- kBufferSize);
+ kChannelLayout, kSampleRate, kBufferSize);
media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK;
media::AudioRendererMixer* mixer =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kNonexistentDeviceId, kSecurityOrigin, &device_status);
+ kNonexistentDeviceId, &device_status);
EXPECT_FALSE(mixer);
EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, device_status);
@@ -540,43 +483,42 @@ TEST_F(AudioRendererMixerManagerTest, LatencyMixing) {
EXPECT_EQ(0, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, kSampleRate, kBitsPerChannel,
- kBufferSize);
+ kChannelLayout, kSampleRate, kBufferSize);
media::AudioRendererMixer* mixer1 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer1);
EXPECT_EQ(1, mixer_count());
media::AudioRendererMixer* mixer2 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer2);
EXPECT_EQ(mixer1, mixer2); // Same latency => same mixer.
EXPECT_EQ(1, mixer_count());
media::AudioRendererMixer* mixer3 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer3);
EXPECT_NE(mixer1, mixer3);
EXPECT_EQ(2, mixer_count()); // Another latency => another mixer.
media::AudioRendererMixer* mixer4 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
EXPECT_EQ(mixer3, mixer4);
EXPECT_EQ(2, mixer_count()); // Same latency => same mixer.
media::AudioRendererMixer* mixer5 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_INTERACTIVE,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
ASSERT_TRUE(mixer5);
EXPECT_EQ(3, mixer_count()); // Another latency => another mixer.
media::AudioRendererMixer* mixer6 =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_INTERACTIVE,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
EXPECT_EQ(mixer5, mixer6);
EXPECT_EQ(3, mixer_count()); // Same latency => same mixer.
@@ -610,12 +552,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyPlayback) {
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, 32000, kBitsPerChannel, 512);
+ kChannelLayout, 32000, 512);
params.set_latency_tag(AudioLatency::LATENCY_PLAYBACK);
- media::AudioRendererMixer* mixer =
- GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
- kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer = GetMixer(
+ kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId, nullptr);
if (AudioLatency::IsResamplingPassthroughSupported(params.latency_tag())) {
// Expecting input sample rate
@@ -647,19 +588,18 @@ TEST_F(AudioRendererMixerManagerTest,
mock_sink_ = new media::MockAudioRendererSink(
std::string(), media::OUTPUT_DEVICE_STATUS_OK,
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 44100,
- kBitsPerChannel, 2048));
+ 2048));
EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, 32000, kBitsPerChannel, 512);
+ kChannelLayout, 32000, 512);
params.set_latency_tag(AudioLatency::LATENCY_PLAYBACK);
- media::AudioRendererMixer* mixer =
- GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
- kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer = GetMixer(
+ kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId, nullptr);
// 20 ms at 44100 is 882 frames per buffer.
if (AudioLatency::IsResamplingPassthroughSupported(params.latency_tag())) {
@@ -682,18 +622,18 @@ TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyPlaybackFakeAudio) {
mock_sink_ = new media::MockAudioRendererSink(
std::string(), media::OUTPUT_DEVICE_STATUS_OK,
AudioParameters(AudioParameters::AUDIO_FAKE, kChannelLayout, 44100,
- kBitsPerChannel, 2048));
+ 2048));
EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, 32000, kBitsPerChannel, 512);
+ kChannelLayout, 32000, 512);
media::AudioRendererMixer* mixer =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
// Expecting input sample rate
EXPECT_EQ(32000, mixer->GetOutputParamsForTesting().sample_rate());
@@ -725,12 +665,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyRtc) {
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, 32000, kBitsPerChannel, 512);
+ kChannelLayout, 32000, 512);
params.set_latency_tag(AudioLatency::LATENCY_RTC);
- media::AudioRendererMixer* mixer =
- GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
- kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer = GetMixer(
+ kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId, nullptr);
int output_sample_rate =
AudioLatency::IsResamplingPassthroughSupported(params.latency_tag())
@@ -761,19 +700,18 @@ TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyRtc) {
TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyRtcFakeAudio) {
mock_sink_ = new media::MockAudioRendererSink(
std::string(), media::OUTPUT_DEVICE_STATUS_OK,
- AudioParameters(AudioParameters::AUDIO_FAKE, kChannelLayout, 44100,
- kBitsPerChannel, 128));
+ AudioParameters(AudioParameters::AUDIO_FAKE, kChannelLayout, 44100, 128));
EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, 32000, kBitsPerChannel, 512);
+ kChannelLayout, 32000, 512);
media::AudioRendererMixer* mixer =
GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_RTC,
- kDefaultDeviceId, kSecurityOrigin, nullptr);
+ kDefaultDeviceId, nullptr);
// Expecting input sample rate.
EXPECT_EQ(32000, mixer->GetOutputParamsForTesting().sample_rate());
@@ -801,12 +739,11 @@ TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyInteractive) {
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
- kChannelLayout, 32000, kBitsPerChannel, 512);
+ kChannelLayout, 32000, 512);
params.set_latency_tag(AudioLatency::LATENCY_INTERACTIVE);
- media::AudioRendererMixer* mixer =
- GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
- kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer = GetMixer(
+ kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId, nullptr);
if (AudioLatency::IsResamplingPassthroughSupported(params.latency_tag())) {
// Expecting input sample rate.
@@ -828,19 +765,18 @@ TEST_F(AudioRendererMixerManagerTest, MixerParamsBitstreamFormat) {
mock_sink_ = new media::MockAudioRendererSink(
std::string(), media::OUTPUT_DEVICE_STATUS_OK,
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 44100,
- kBitsPerChannel, 2048));
+ 2048));
EXPECT_CALL(*mock_sink_.get(), Start()).Times(1);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(1);
EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(1);
media::AudioParameters params(AudioParameters::AUDIO_BITSTREAM_EAC3,
- kAnotherChannelLayout, 32000, 8, 512);
+ kAnotherChannelLayout, 32000, 512);
params.set_latency_tag(AudioLatency::LATENCY_PLAYBACK);
- media::AudioRendererMixer* mixer =
- GetMixer(kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId,
- kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer = GetMixer(
+ kRenderFrameId, params, params.latency_tag(), kDefaultDeviceId, nullptr);
// Output parameters should be the same as input properties for bitstream
// formats.
@@ -849,8 +785,6 @@ TEST_F(AudioRendererMixerManagerTest, MixerParamsBitstreamFormat) {
mixer->GetOutputParamsForTesting().channel_layout());
EXPECT_EQ(params.sample_rate(),
mixer->GetOutputParamsForTesting().sample_rate());
- EXPECT_EQ(params.bits_per_sample(),
- mixer->GetOutputParamsForTesting().bits_per_sample());
EXPECT_EQ(params.frames_per_buffer(),
mixer->GetOutputParamsForTesting().frames_per_buffer());
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache.h b/chromium/content/renderer/media/audio_renderer_sink_cache.h
index b4d7db98405..4a06a3fc0c6 100644
--- a/chromium/content/renderer/media/audio_renderer_sink_cache.h
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache.h
@@ -12,20 +12,17 @@
#include "content/common/content_export.h"
#include "media/base/output_device_info.h"
-namespace url {
-class Origin;
-}
-
namespace media {
class AudioRendererSink;
}
namespace content {
+class RenderFrame;
// Caches AudioRendererSink instances, provides them to the clients for usage,
// tracks their used/unused state, reuses them to obtain output device
// information, garbage-collects unused sinks.
-// Thread safe.
+// Must live on the main render thread. Thread safe.
class CONTENT_EXPORT AudioRendererSinkCache {
public:
virtual ~AudioRendererSinkCache() {}
@@ -33,20 +30,21 @@ class CONTENT_EXPORT AudioRendererSinkCache {
// Creates default cache, to be used by AudioRendererMixerManager.
static std::unique_ptr<AudioRendererSinkCache> Create();
+ // If called, the cache will drop sinks belonging to the specified frame on
+ // navigation.
+ static void ObserveFrame(RenderFrame* frame);
+
// Returns output device information for a specified sink.
- virtual media::OutputDeviceInfo GetSinkInfo(
- int source_render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) = 0;
+ virtual media::OutputDeviceInfo GetSinkInfo(int source_render_frame_id,
+ int session_id,
+ const std::string& device_id) = 0;
// Provides a sink for usage. The sink must be returned to the cache by
// calling ReleaseSink(). The sink must be stopped by the user before
// deletion, but after releasing it from the cache.
virtual scoped_refptr<media::AudioRendererSink> GetSink(
int source_render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) = 0;
+ const std::string& device_id) = 0;
// Notifies the cache that the sink is not in use any more. Must be
// called by the client, so that the cache can garbage-collect the sink
@@ -56,6 +54,7 @@ class CONTENT_EXPORT AudioRendererSinkCache {
protected:
AudioRendererSinkCache() {}
+ private:
DISALLOW_COPY_AND_ASSIGN(AudioRendererSinkCache);
};
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc
index 8b909f48a21..3dc8bebc611 100644
--- a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc
@@ -14,15 +14,45 @@
#include "base/metrics/histogram_macros.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "content/public/renderer/render_frame.h"
+#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/media/audio_device_factory.h"
#include "media/audio/audio_device_description.h"
#include "media/base/audio_renderer_sink.h"
-#include "url/origin.h"
namespace content {
+AudioRendererSinkCacheImpl* AudioRendererSinkCacheImpl::instance_ = nullptr;
constexpr int kDeleteTimeoutMs = 5000;
+class AudioRendererSinkCacheImpl::FrameObserver : public RenderFrameObserver {
+ public:
+ explicit FrameObserver(content::RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame) {}
+ ~FrameObserver() override{};
+
+ private:
+ // content::RenderFrameObserver implementation:
+ void DidCommitProvisionalLoad(bool is_new_navigation,
+ bool is_same_document_navigation) override {
+ if (!is_same_document_navigation)
+ DropFrameCache();
+ }
+
+ void OnDestruct() override {
+ DropFrameCache();
+ delete this;
+ }
+
+ void DropFrameCache() {
+ if (AudioRendererSinkCacheImpl::instance_)
+ AudioRendererSinkCacheImpl::instance_->DropSinksForFrame(routing_id());
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(FrameObserver);
+};
+
namespace {
enum GetOutputDeviceInfoCacheUtilization {
@@ -51,28 +81,36 @@ bool SinkIsHealthy(media::AudioRendererSink* sink) {
struct AudioRendererSinkCacheImpl::CacheEntry {
int source_render_frame_id;
std::string device_id;
- url::Origin security_origin;
scoped_refptr<media::AudioRendererSink> sink; // Sink instance
bool used; // True if in use by a client.
};
// static
std::unique_ptr<AudioRendererSinkCache> AudioRendererSinkCache::Create() {
- return base::WrapUnique(new AudioRendererSinkCacheImpl(
+ return std::make_unique<AudioRendererSinkCacheImpl>(
base::ThreadTaskRunnerHandle::Get(),
base::Bind(&AudioDeviceFactory::NewAudioRendererMixerSink),
- base::TimeDelta::FromMilliseconds(kDeleteTimeoutMs)));
+ base::TimeDelta::FromMilliseconds(kDeleteTimeoutMs));
+}
+
+// static
+void AudioRendererSinkCache::ObserveFrame(RenderFrame* frame) {
+ new AudioRendererSinkCacheImpl::FrameObserver(frame);
}
AudioRendererSinkCacheImpl::AudioRendererSinkCacheImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- const CreateSinkCallback& create_sink_cb,
+ CreateSinkCallback create_sink_cb,
base::TimeDelta delete_timeout)
: task_runner_(std::move(task_runner)),
- create_sink_cb_(create_sink_cb),
+ create_sink_cb_(std::move(create_sink_cb)),
delete_timeout_(delete_timeout),
weak_ptr_factory_(this) {
weak_this_ = weak_ptr_factory_.GetWeakPtr();
+ if (instance_)
+ LOG(ERROR) << "More that one AudioRendererSinkCache instance created. "
+ "Allowed in tests only.";
+ instance_ = this;
}
AudioRendererSinkCacheImpl::~AudioRendererSinkCacheImpl() {
@@ -82,56 +120,65 @@ AudioRendererSinkCacheImpl::~AudioRendererSinkCacheImpl() {
// is being destroyed anyways.
for (auto& entry : cache_)
entry.sink->Stop();
+
+ if (instance_ == this)
+ instance_ = nullptr;
}
media::OutputDeviceInfo AudioRendererSinkCacheImpl::GetSinkInfo(
int source_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
+ TRACE_EVENT_BEGIN2("audio", "AudioRendererSinkCacheImpl::GetSinkInfo",
+ "frame_id", source_render_frame_id, "device id",
+ device_id);
+
if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
device_id)) {
// We are provided with session id instead of device id. Session id is
// unique, so we can't find any matching sink. Creating a new one.
- scoped_refptr<media::AudioRendererSink> sink = create_sink_cb_.Run(
- source_render_frame_id, session_id, device_id, security_origin);
+ scoped_refptr<media::AudioRendererSink> sink =
+ create_sink_cb_.Run(source_render_frame_id, session_id, device_id);
CacheOrStopUnusedSink(source_render_frame_id,
- sink->GetOutputDeviceInfo().device_id(),
- security_origin, sink);
+ sink->GetOutputDeviceInfo().device_id(), sink);
UMA_HISTOGRAM_ENUMERATION(
"Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization",
SINK_CACHE_MISS_CANNOT_LOOKUP_BY_SESSION_ID, SINK_CACHE_LAST_ENTRY);
+ TRACE_EVENT_END1("audio", "AudioRendererSinkCacheImpl::GetSinkInfo",
+ "result", "Cache not used due to using |session_id|");
return sink->GetOutputDeviceInfo();
}
// Ignore session id.
{
base::AutoLock auto_lock(cache_lock_);
- auto cache_iter =
- FindCacheEntry_Locked(source_render_frame_id, device_id,
- security_origin, false /* unused_only */);
+ auto cache_iter = FindCacheEntry_Locked(source_render_frame_id, device_id,
+ false /* unused_only */);
if (cache_iter != cache_.end()) {
// A matching cached sink is found.
UMA_HISTOGRAM_ENUMERATION(
"Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization",
SINK_CACHE_HIT, SINK_CACHE_LAST_ENTRY);
+ TRACE_EVENT_END1("audio", "AudioRendererSinkCacheImpl::GetSinkInfo",
+ "result", "Cache hit");
return cache_iter->sink->GetOutputDeviceInfo();
}
}
// No matching sink found, create a new one.
scoped_refptr<media::AudioRendererSink> sink = create_sink_cb_.Run(
- source_render_frame_id, 0 /* session_id */, device_id, security_origin);
+ source_render_frame_id, 0 /* session_id */, device_id);
- CacheOrStopUnusedSink(source_render_frame_id, device_id, security_origin,
- sink);
+ CacheOrStopUnusedSink(source_render_frame_id, device_id, sink);
UMA_HISTOGRAM_ENUMERATION(
"Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization",
SINK_CACHE_MISS_NO_SINK, SINK_CACHE_LAST_ENTRY);
+ TRACE_EVENT_END1("audio", "AudioRendererSinkCacheImpl::GetSinkInfo", "result",
+ "Cache miss");
// |sink| is ref-counted, so it's ok if it is removed from cache before we get
// here.
return sink->GetOutputDeviceInfo();
@@ -139,35 +186,42 @@ media::OutputDeviceInfo AudioRendererSinkCacheImpl::GetSinkInfo(
scoped_refptr<media::AudioRendererSink> AudioRendererSinkCacheImpl::GetSink(
int source_render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation",
true);
+ TRACE_EVENT_BEGIN2("audio", "AudioRendererSinkCacheImpl::GetSink", "frame_id",
+ source_render_frame_id, "device id", device_id);
base::AutoLock auto_lock(cache_lock_);
- auto cache_iter =
- FindCacheEntry_Locked(source_render_frame_id, device_id, security_origin,
- true /* unused sink only */);
+ auto cache_iter = FindCacheEntry_Locked(source_render_frame_id, device_id,
+ true /* unused sink only */);
if (cache_iter != cache_.end()) {
// Found unused sink; mark it as used and return.
cache_iter->used = true;
UMA_HISTOGRAM_BOOLEAN(
"Media.Audio.Render.SinkCache.InfoSinkReusedForOutput", true);
+ TRACE_EVENT_END1("audio", "AudioRendererSinkCacheImpl::GetSink", "result",
+ "Cache hit");
return cache_iter->sink;
}
// No unused sink is found, create one, mark it used, cache it and return.
- CacheEntry cache_entry = {
- source_render_frame_id, device_id, security_origin,
- create_sink_cb_.Run(source_render_frame_id, 0 /* session_id */, device_id,
- security_origin),
- true /* used */};
-
- if (SinkIsHealthy(cache_entry.sink.get()))
+ CacheEntry cache_entry = {source_render_frame_id, device_id,
+ create_sink_cb_.Run(source_render_frame_id,
+ 0 /* session_id */, device_id),
+ true /* used */};
+
+ if (SinkIsHealthy(cache_entry.sink.get())) {
+ TRACE_EVENT_INSTANT0(
+ "audio", "AudioRendererSinkCacheImpl::GetSink: caching new sink",
+ TRACE_EVENT_SCOPE_THREAD);
cache_.push_back(cache_entry);
+ }
+ TRACE_EVENT_END1("audio", "AudioRendererSinkCacheImpl::GetSink", "result",
+ "Cache miss");
return cache_entry.sink;
}
@@ -236,12 +290,10 @@ AudioRendererSinkCacheImpl::CacheContainer::iterator
AudioRendererSinkCacheImpl::FindCacheEntry_Locked(
int source_render_frame_id,
const std::string& device_id,
- const url::Origin& security_origin,
bool unused_only) {
return std::find_if(
cache_.begin(), cache_.end(),
- [source_render_frame_id, &device_id, &security_origin,
- unused_only](const CacheEntry& val) {
+ [source_render_frame_id, &device_id, unused_only](const CacheEntry& val) {
if (val.used && unused_only)
return false;
if (val.source_render_frame_id != source_render_frame_id)
@@ -249,28 +301,27 @@ AudioRendererSinkCacheImpl::FindCacheEntry_Locked(
if (media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
media::AudioDeviceDescription::IsDefaultDevice(val.device_id)) {
// Both device IDs represent the same default device => do not compare
- // them; the default device is always authorized => ignore security
- // origin.
+ // them;
return true;
}
- return val.device_id == device_id &&
- val.security_origin == security_origin;
+ return val.device_id == device_id;
});
}
void AudioRendererSinkCacheImpl::CacheOrStopUnusedSink(
int source_render_frame_id,
const std::string& device_id,
- const url::Origin& security_origin,
scoped_refptr<media::AudioRendererSink> sink) {
if (!SinkIsHealthy(sink.get())) {
+ TRACE_EVENT_INSTANT0("audio", "CacheOrStopUnusedSink: Unhealthy sink",
+ TRACE_EVENT_SCOPE_THREAD);
// Since |sink| is not cached, we must make sure to Stop it now.
sink->Stop();
return;
}
- CacheEntry cache_entry = {source_render_frame_id, device_id, security_origin,
- std::move(sink), false /* not used */};
+ CacheEntry cache_entry = {source_render_frame_id, device_id, std::move(sink),
+ false /* not used */};
{
base::AutoLock auto_lock(cache_lock_);
@@ -280,6 +331,20 @@ void AudioRendererSinkCacheImpl::CacheOrStopUnusedSink(
DeleteLaterIfUnused(cache_entry.sink.get());
}
+void AudioRendererSinkCacheImpl::DropSinksForFrame(int source_render_frame_id) {
+ base::AutoLock auto_lock(cache_lock_);
+ cache_.erase(std::remove_if(cache_.begin(), cache_.end(),
+ [source_render_frame_id](const CacheEntry& val) {
+ if (val.source_render_frame_id ==
+ source_render_frame_id) {
+ val.sink->Stop();
+ return true;
+ }
+ return false;
+ }),
+ cache_.end());
+}
+
int AudioRendererSinkCacheImpl::GetCacheSizeForTesting() {
return cache_.size();
}
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h
index 8fa3a709917..93dd9adb2e3 100644
--- a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h
@@ -23,36 +23,36 @@ namespace content {
class CONTENT_EXPORT AudioRendererSinkCacheImpl
: public AudioRendererSinkCache {
public:
+ class FrameObserver;
+
// Callback to be used for AudioRendererSink creation
using CreateSinkCallback =
base::RepeatingCallback<scoped_refptr<media::AudioRendererSink>(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin)>;
+ const std::string& device_id)>;
AudioRendererSinkCacheImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- const CreateSinkCallback& create_sink_callback,
+ CreateSinkCallback create_sink_callback,
base::TimeDelta delete_timeout);
~AudioRendererSinkCacheImpl() final;
media::OutputDeviceInfo GetSinkInfo(int source_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) final;
+ const std::string& device_id) final;
scoped_refptr<media::AudioRendererSink> GetSink(
int source_render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) final;
+ const std::string& device_id) final;
void ReleaseSink(const media::AudioRendererSink* sink_ptr) final;
private:
friend class AudioRendererSinkCacheTest;
friend class CacheEntryFinder;
+ friend class AudioRendererSinkCacheImpl::FrameObserver;
struct CacheEntry;
using CacheContainer = std::vector<CacheEntry>;
@@ -70,18 +70,21 @@ class CONTENT_EXPORT AudioRendererSinkCacheImpl
CacheContainer::iterator FindCacheEntry_Locked(
int source_render_frame_id,
const std::string& device_id,
- const url::Origin& security_origin,
bool unused_only);
void CacheOrStopUnusedSink(int source_render_frame_id,
const std::string& device_id,
- const url::Origin& security_origin,
scoped_refptr<media::AudioRendererSink> sink);
+ void DropSinksForFrame(int source_render_frame_id);
+
// To avoid publishing CacheEntry structure in the header.
int GetCacheSizeForTesting();
- // Task runner for scheduled sink garbage collection.
+ // Global instance, set in constructor and unset in destructor.
+ static AudioRendererSinkCacheImpl* instance_;
+
+ // Renderer main task runner.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Callback used for sink creation.
diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc b/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc
index feebf4b5db9..bd510528654 100644
--- a/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc
+++ b/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc
@@ -16,7 +16,6 @@
#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "url/origin.h"
namespace content {
@@ -44,9 +43,8 @@ class AudioRendererSinkCacheTest : public testing::Test {
void GetSink(int render_frame_id,
const std::string& device_id,
- const url::Origin& security_origin,
media::AudioRendererSink** sink) {
- *sink = cache_->GetSink(render_frame_id, device_id, security_origin).get();
+ *sink = cache_->GetSink(render_frame_id, device_id).get();
}
protected:
@@ -58,8 +56,7 @@ class AudioRendererSinkCacheTest : public testing::Test {
scoped_refptr<media::AudioRendererSink> CreateSink(
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
return new testing::NiceMock<media::MockAudioRendererSink>(
device_id, (device_id == kUnhealthyDeviceId)
? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL
@@ -87,6 +84,8 @@ class AudioRendererSinkCacheTest : public testing::Test {
e.Wait();
}
+ void DropSinksForFrame(int frame_id) { cache_->DropSinksForFrame(frame_id); }
+
base::test::ScopedTaskEnvironment task_env_;
std::unique_ptr<AudioRendererSinkCacheImpl> cache_;
@@ -99,14 +98,14 @@ TEST_F(AudioRendererSinkCacheTest, GetReleaseSink) {
// Verify that a new sink is successfully created.
EXPECT_EQ(0, sink_count());
scoped_refptr<media::AudioRendererSink> sink =
- cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
ExpectNotToStop(sink.get()); // Cache should not stop sinks marked as used.
EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
EXPECT_EQ(1, sink_count());
// Verify that another sink with the same key is successfully created
scoped_refptr<media::AudioRendererSink> another_sink =
- cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
ExpectNotToStop(another_sink.get());
EXPECT_EQ(kDefaultDeviceId, another_sink->GetOutputDeviceInfo().device_id());
EXPECT_EQ(2, sink_count());
@@ -114,7 +113,7 @@ TEST_F(AudioRendererSinkCacheTest, GetReleaseSink) {
// Verify that another sink with a different kay is successfully created.
scoped_refptr<media::AudioRendererSink> yet_another_sink =
- cache_->GetSink(kRenderFrameId, kAnotherDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kAnotherDeviceId).get();
ExpectNotToStop(yet_another_sink.get());
EXPECT_EQ(kAnotherDeviceId,
yet_another_sink->GetOutputDeviceInfo().device_id());
@@ -147,32 +146,32 @@ TEST_F(AudioRendererSinkCacheTest, GetReleaseSink) {
TEST_F(AudioRendererSinkCacheTest, GetDeviceInfo) {
EXPECT_EQ(0, sink_count());
media::OutputDeviceInfo device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId);
EXPECT_EQ(1, sink_count());
// The info on the same device is requested, so no new sink is created.
media::OutputDeviceInfo one_more_device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId);
EXPECT_EQ(1, sink_count());
EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
// Aquire the sink that was created on GetSinkInfo().
scoped_refptr<media::AudioRendererSink> sink =
- cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
EXPECT_EQ(1, sink_count());
EXPECT_EQ(device_info.device_id(), sink->GetOutputDeviceInfo().device_id());
// Now the sink is in used, but we can still get the device info out of it, no
// new sink is created.
one_more_device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId);
EXPECT_EQ(1, sink_count());
EXPECT_EQ(device_info.device_id(), one_more_device_info.device_id());
// Request sink for the same device. The first sink is in use, so a new one
// should be created.
scoped_refptr<media::AudioRendererSink> another_sink =
- cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
EXPECT_EQ(2, sink_count());
EXPECT_EQ(device_info.device_id(),
another_sink->GetOutputDeviceInfo().device_id());
@@ -183,11 +182,11 @@ TEST_F(AudioRendererSinkCacheTest, GarbageCollection) {
EXPECT_EQ(0, sink_count());
media::OutputDeviceInfo device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId);
EXPECT_EQ(1, sink_count());
media::OutputDeviceInfo another_device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kAnotherDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kAnotherDeviceId);
EXPECT_EQ(2, sink_count());
// Wait for garbage collection. Doesn't actually sleep, just advances the mock
@@ -204,7 +203,7 @@ TEST_F(AudioRendererSinkCacheTest, NoGarbageCollectionForUsedSink) {
EXPECT_EQ(0, sink_count());
media::OutputDeviceInfo device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId);
EXPECT_EQ(1, sink_count());
// Wait less than garbage collection timeout.
@@ -217,7 +216,7 @@ TEST_F(AudioRendererSinkCacheTest, NoGarbageCollectionForUsedSink) {
// Request it:
scoped_refptr<media::AudioRendererSink> sink =
- cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
EXPECT_EQ(1, sink_count());
@@ -233,10 +232,10 @@ TEST_F(AudioRendererSinkCacheTest, NoGarbageCollectionForUsedSink) {
TEST_F(AudioRendererSinkCacheTest, UnhealthySinkIsNotCached) {
EXPECT_EQ(0, sink_count());
media::OutputDeviceInfo device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kUnhealthyDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kUnhealthyDeviceId);
EXPECT_EQ(0, sink_count());
scoped_refptr<media::AudioRendererSink> sink =
- cache_->GetSink(kRenderFrameId, kUnhealthyDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kUnhealthyDeviceId).get();
EXPECT_EQ(0, sink_count());
}
@@ -251,12 +250,10 @@ TEST_F(AudioRendererSinkCacheTest, UnhealthySinkIsStopped) {
task_env_.GetMainThreadTaskRunner(),
base::BindRepeating(
[](scoped_refptr<media::AudioRendererSink> sink, int render_frame_id,
- int session_id, const std::string& device_id,
- const url::Origin& security_origin) {
+ int session_id, const std::string& device_id) {
EXPECT_EQ(kRenderFrameId, render_frame_id);
EXPECT_EQ(0, session_id);
EXPECT_EQ(kUnhealthyDeviceId, device_id);
- EXPECT_TRUE(security_origin.unique());
return sink;
},
sink),
@@ -265,7 +262,7 @@ TEST_F(AudioRendererSinkCacheTest, UnhealthySinkIsStopped) {
EXPECT_CALL(*sink, Stop());
media::OutputDeviceInfo device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kUnhealthyDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kUnhealthyDeviceId);
}
// Verify that a sink created with GetSinkInfo() is stopped even if it's
@@ -279,12 +276,10 @@ TEST_F(AudioRendererSinkCacheTest, UnhealthySinkUsingSessionIdIsStopped) {
task_env_.GetMainThreadTaskRunner(),
base::BindRepeating(
[](scoped_refptr<media::AudioRendererSink> sink, int render_frame_id,
- int session_id, const std::string& device_id,
- const url::Origin& security_origin) {
+ int session_id, const std::string& device_id) {
EXPECT_EQ(kRenderFrameId, render_frame_id);
EXPECT_EQ(kNonZeroSessionId, session_id);
EXPECT_TRUE(device_id.empty());
- EXPECT_TRUE(security_origin.unique());
return sink;
},
sink),
@@ -292,8 +287,8 @@ TEST_F(AudioRendererSinkCacheTest, UnhealthySinkUsingSessionIdIsStopped) {
EXPECT_CALL(*sink, Stop());
- media::OutputDeviceInfo device_info = cache_->GetSinkInfo(
- kRenderFrameId, kNonZeroSessionId, std::string(), url::Origin());
+ media::OutputDeviceInfo device_info =
+ cache_->GetSinkInfo(kRenderFrameId, kNonZeroSessionId, std::string());
}
// Verify that cache works fine if a sink scheduled for deletion is acquired and
@@ -305,12 +300,12 @@ TEST_F(AudioRendererSinkCacheTest, ReleaseSinkBeforeScheduledDeletion) {
thread.Start();
media::OutputDeviceInfo device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kDefaultDeviceId);
EXPECT_EQ(1, sink_count()); // This sink is scheduled for deletion now.
// Request it:
scoped_refptr<media::AudioRendererSink> sink =
- cache_->GetSink(kRenderFrameId, kDefaultDeviceId, url::Origin()).get();
+ cache_->GetSink(kRenderFrameId, kDefaultDeviceId).get();
ExpectNotToStop(sink.get());
EXPECT_EQ(1, sink_count());
@@ -319,7 +314,7 @@ TEST_F(AudioRendererSinkCacheTest, ReleaseSinkBeforeScheduledDeletion) {
EXPECT_EQ(0, sink_count());
media::OutputDeviceInfo another_device_info =
- cache_->GetSinkInfo(kRenderFrameId, 0, kAnotherDeviceId, url::Origin());
+ cache_->GetSinkInfo(kRenderFrameId, 0, kAnotherDeviceId);
EXPECT_EQ(1, sink_count()); // This sink is scheduled for deletion now.
task_env_.FastForwardBy(kDeleteTimeout);
@@ -341,10 +336,10 @@ TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
// Request device information on the first thread.
PostAndWaitUntilDone(
- thread1, base::BindOnce(
- base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
- base::Unretained(cache_.get()), kRenderFrameId, 0,
- kDefaultDeviceId, url::Origin()));
+ thread1,
+ base::BindOnce(
+ base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
+ base::Unretained(cache_.get()), kRenderFrameId, 0, kDefaultDeviceId));
EXPECT_EQ(1, sink_count());
@@ -354,17 +349,17 @@ TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
PostAndWaitUntilDone(thread2,
base::BindOnce(&AudioRendererSinkCacheTest::GetSink,
base::Unretained(this), kRenderFrameId,
- kDefaultDeviceId, url::Origin(), &sink));
+ kDefaultDeviceId, &sink));
EXPECT_EQ(kDefaultDeviceId, sink->GetOutputDeviceInfo().device_id());
EXPECT_EQ(1, sink_count());
// Request device information on the first thread again.
PostAndWaitUntilDone(
- thread1, base::BindOnce(
- base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
- base::Unretained(cache_.get()), kRenderFrameId, 0,
- kDefaultDeviceId, url::Origin()));
+ thread1,
+ base::BindOnce(
+ base::IgnoreResult(&AudioRendererSinkCacheImpl::GetSinkInfo),
+ base::Unretained(cache_.get()), kRenderFrameId, 0, kDefaultDeviceId));
EXPECT_EQ(1, sink_count());
// Release the sink on the second thread.
@@ -376,4 +371,36 @@ TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) {
EXPECT_EQ(0, sink_count());
}
+TEST_F(AudioRendererSinkCacheTest, StopsAndDropsSinks) {
+ EXPECT_EQ(0, sink_count());
+ scoped_refptr<media::AudioRendererSink> sink1 =
+ cache_->GetSink(kRenderFrameId, "device1").get();
+ scoped_refptr<media::AudioRendererSink> sink2 =
+ cache_->GetSink(kRenderFrameId, "device2").get();
+ EXPECT_EQ(2, sink_count());
+
+ EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink1.get()), Stop());
+ EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink2.get()), Stop());
+ DropSinksForFrame(kRenderFrameId);
+ EXPECT_EQ(0, sink_count());
+}
+
+TEST_F(AudioRendererSinkCacheTest, StopsAndDropsCorrectSinks) {
+ EXPECT_EQ(0, sink_count());
+ scoped_refptr<media::AudioRendererSink> sink1 =
+ cache_->GetSink(kRenderFrameId, "device1").get();
+ scoped_refptr<media::AudioRendererSink> another_sink =
+ cache_->GetSink(kRenderFrameId + 1, "device1").get();
+ scoped_refptr<media::AudioRendererSink> sink2 =
+ cache_->GetSink(kRenderFrameId, "device2").get();
+ EXPECT_EQ(3, sink_count());
+
+ EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink1.get()), Stop());
+ EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(sink2.get()), Stop());
+ DropSinksForFrame(kRenderFrameId);
+ EXPECT_EQ(1, sink_count());
+ EXPECT_CALL(*static_cast<media::MockAudioRendererSink*>(another_sink.get()),
+ Stop());
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
index 11c82f8538e..8336e384eec 100644
--- a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
+++ b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -56,15 +56,17 @@ GpuVideoAcceleratorFactoriesImpl::Create(
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
- bool enable_gpu_memory_buffer_video_frames,
+ bool enable_video_gpu_memory_buffers,
+ bool enable_media_stream_gpu_memory_buffers,
bool enable_video_accelerator,
media::mojom::VideoEncodeAcceleratorProviderPtrInfo unbound_vea_provider) {
RecordContextProviderPhaseUmaEnum(
ContextProviderPhase::CONTEXT_PROVIDER_ACQUIRED);
return base::WrapUnique(new GpuVideoAcceleratorFactoriesImpl(
std::move(gpu_channel_host), main_thread_task_runner, task_runner,
- context_provider, enable_gpu_memory_buffer_video_frames,
- enable_video_accelerator, std::move(unbound_vea_provider)));
+ context_provider, enable_video_gpu_memory_buffers,
+ enable_media_stream_gpu_memory_buffers, enable_video_accelerator,
+ std::move(unbound_vea_provider)));
}
GpuVideoAcceleratorFactoriesImpl::GpuVideoAcceleratorFactoriesImpl(
@@ -72,16 +74,17 @@ GpuVideoAcceleratorFactoriesImpl::GpuVideoAcceleratorFactoriesImpl(
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
- bool enable_gpu_memory_buffer_video_frames,
+ bool enable_video_gpu_memory_buffers,
+ bool enable_media_stream_gpu_memory_buffers,
bool enable_video_accelerator,
media::mojom::VideoEncodeAcceleratorProviderPtrInfo unbound_vea_provider)
: main_thread_task_runner_(main_thread_task_runner),
task_runner_(task_runner),
gpu_channel_host_(std::move(gpu_channel_host)),
context_provider_(context_provider),
- context_provider_lost_(false),
- enable_gpu_memory_buffer_video_frames_(
- enable_gpu_memory_buffer_video_frames),
+ enable_video_gpu_memory_buffers_(enable_video_gpu_memory_buffers),
+ enable_media_stream_gpu_memory_buffers_(
+ enable_media_stream_gpu_memory_buffers),
video_accelerator_enabled_(enable_video_accelerator),
gpu_memory_buffer_manager_(
RenderThreadImpl::current()->GetGpuMemoryBufferManager()),
@@ -108,19 +111,31 @@ void GpuVideoAcceleratorFactoriesImpl::BindContextToTaskRunner() {
DCHECK(context_provider_);
if (context_provider_->BindToCurrentThread() !=
gpu::ContextResult::kSuccess) {
- ReleaseContextProvider();
+ SetContextProviderLost();
}
}
bool GpuVideoAcceleratorFactoriesImpl::CheckContextLost() {
DCHECK(task_runner_->BelongsToCurrentThread());
- if (context_provider_) {
- if (context_provider_->ContextGL()->GetGraphicsResetStatusKHR() !=
- GL_NO_ERROR) {
- ReleaseContextProvider();
- }
+ if (context_provider_lost_on_media_thread_)
+ return true;
+ if (context_provider_->ContextGL()->GetGraphicsResetStatusKHR() !=
+ GL_NO_ERROR) {
+ SetContextProviderLost();
+ return true;
}
- return !context_provider_;
+ return false;
+}
+
+void GpuVideoAcceleratorFactoriesImpl::DestroyContext() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(context_provider_lost_on_media_thread_);
+
+ if (!context_provider_)
+ return;
+ context_provider_ = nullptr;
+ RecordContextProviderPhaseUmaEnum(
+ ContextProviderPhase::CONTEXT_PROVIDER_RELEASED);
}
bool GpuVideoAcceleratorFactoriesImpl::IsGpuVideoAcceleratorEnabled() {
@@ -268,9 +283,10 @@ GpuVideoAcceleratorFactoriesImpl::CreateGpuMemoryBuffer(
return gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
size, format, usage, gpu::kNullSurfaceHandle);
}
-bool GpuVideoAcceleratorFactoriesImpl::ShouldUseGpuMemoryBuffersForVideoFrames()
- const {
- return enable_gpu_memory_buffer_video_frames_;
+bool GpuVideoAcceleratorFactoriesImpl::ShouldUseGpuMemoryBuffersForVideoFrames(
+ bool for_media_stream) const {
+ return for_media_stream ? enable_media_stream_gpu_memory_buffers_
+ : enable_video_gpu_memory_buffers_;
}
unsigned GpuVideoAcceleratorFactoriesImpl::ImageTextureTarget(
@@ -354,9 +370,9 @@ GpuVideoAcceleratorFactoriesImpl::GetVideoEncodeAcceleratorSupportedProfiles() {
.video_encode_accelerator_supported_profiles);
}
-viz::ContextProvider*
+scoped_refptr<ui::ContextProviderCommandBuffer>
GpuVideoAcceleratorFactoriesImpl::GetMediaContextProvider() {
- return CheckContextLost() ? nullptr : context_provider_.get();
+ return CheckContextLost() ? nullptr : context_provider_;
}
void GpuVideoAcceleratorFactoriesImpl::SetRenderingColorSpace(
@@ -364,7 +380,7 @@ void GpuVideoAcceleratorFactoriesImpl::SetRenderingColorSpace(
rendering_color_space_ = color_space;
}
-bool GpuVideoAcceleratorFactoriesImpl::CheckContextProviderLost() {
+bool GpuVideoAcceleratorFactoriesImpl::CheckContextProviderLostOnMainThread() {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
return context_provider_lost_;
}
@@ -378,20 +394,23 @@ void GpuVideoAcceleratorFactoriesImpl::
vea_provider_.Bind(std::move(unbound_vea_provider), task_runner_);
}
-void GpuVideoAcceleratorFactoriesImpl::ReleaseContextProvider() {
+void GpuVideoAcceleratorFactoriesImpl::SetContextProviderLost() {
DCHECK(task_runner_->BelongsToCurrentThread());
+ // Don't delete the |context_provider_| here, we could be in the middle of
+ // it notifying about the loss, and we'd be destroying it while it's on
+ // the stack.
+ context_provider_lost_on_media_thread_ = true;
+ // Inform the main thread of the loss as well, so that this class can be
+ // replaced.
main_thread_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::SetContextProviderLost,
- base::Unretained(this)));
-
- context_provider_ = nullptr;
- RecordContextProviderPhaseUmaEnum(
- ContextProviderPhase::CONTEXT_PROVIDER_RELEASED);
+ base::BindOnce(
+ &GpuVideoAcceleratorFactoriesImpl::SetContextProviderLostOnMainThread,
+ base::Unretained(this)));
}
-void GpuVideoAcceleratorFactoriesImpl::SetContextProviderLost() {
+void GpuVideoAcceleratorFactoriesImpl::SetContextProviderLostOnMainThread() {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
context_provider_lost_ = true;
}
diff --git a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
index 066ee94cf41..2085f328f91 100644
--- a/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
+++ b/chromium/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h
@@ -32,10 +32,6 @@ namespace ui {
class ContextProviderCommandBuffer;
}
-namespace viz {
-class ContextProvider;
-}
-
namespace content {
// Glue code to expose functionality needed by media::GpuVideoAccelerator to
@@ -59,7 +55,8 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
- bool enable_gpu_memory_buffer_video_frames,
+ bool enable_video_gpu_memory_buffers,
+ bool enable_media_stream_gpu_memory_buffers,
bool enable_video_accelerator,
media::mojom::VideoEncodeAcceleratorProviderPtrInfo unbound_vea_provider);
@@ -88,13 +85,24 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
gfx::BufferFormat format,
gfx::BufferUsage usage) override;
- bool ShouldUseGpuMemoryBuffersForVideoFrames() const override;
+ bool ShouldUseGpuMemoryBuffersForVideoFrames(
+ bool for_media_stream) const override;
unsigned ImageTextureTarget(gfx::BufferFormat format) override;
OutputFormat VideoFrameOutputFormat(size_t bit_depth) override;
+ // Called on the media thread. Returns the GLES2Interface unless the
+ // ContextProvider has been lost, in which case it returns null.
gpu::gles2::GLES2Interface* ContextGL() override;
void BindContextToTaskRunner();
+ // Called on the media thread. Verifies if the ContextProvider is lost and
+ // notifies the main thread of loss if it has occured, which can be seen later
+ // from CheckContextProviderLost().
bool CheckContextLost();
+ // Called on the media thread. Destroys the ContextProvider held in this
+ // class. Should only be called if the ContextProvider was previously lost,
+ // and this class will no longer be used, as it assumes a ContextProvider is
+ // present otherwise.
+ void DestroyContext();
std::unique_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
@@ -103,11 +111,15 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
std::vector<media::VideoEncodeAccelerator::SupportedProfile>
GetVideoEncodeAcceleratorSupportedProfiles() override;
- viz::ContextProvider* GetMediaContextProvider() override;
+ scoped_refptr<ui::ContextProviderCommandBuffer> GetMediaContextProvider()
+ override;
void SetRenderingColorSpace(const gfx::ColorSpace& color_space) override;
- bool CheckContextProviderLost();
+ // Called on the main thread. Returns whether the media thread has seen the
+ // ContextProvider become lost, in which case this class should be replaced
+ // with a new ContextProvider.
+ bool CheckContextProviderLostOnMainThread();
~GpuVideoAcceleratorFactoriesImpl() override;
@@ -118,15 +130,16 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
- bool enable_gpu_memory_buffer_video_frames,
+ bool enable_gpu_memory_buffer_video_frames_for_video,
+ bool enable_gpu_memory_buffer_video_frames_for_media_stream,
bool enable_video_accelerator,
media::mojom::VideoEncodeAcceleratorProviderPtrInfo unbound_vea_provider);
void BindVideoEncodeAcceleratorProviderOnTaskRunner(
media::mojom::VideoEncodeAcceleratorProviderPtrInfo unbound_vea_provider);
- void ReleaseContextProvider();
void SetContextProviderLost();
+ void SetContextProviderLostOnMainThread();
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -136,13 +149,17 @@ class CONTENT_EXPORT GpuVideoAcceleratorFactoriesImpl
// thread, but all subsequent access and destruction should happen only on the
// media thread.
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
- // Signals if |context_provider_| is alive on the media thread.
- bool context_provider_lost_;
+ // Signals if |context_provider_| is alive on the media thread. For use on the
+ // main thread.
+ bool context_provider_lost_ = false;
+ // A shadow of |context_provider_lost_| for the media thread.
+ bool context_provider_lost_on_media_thread_ = false;
base::UnguessableToken channel_token_;
// Whether gpu memory buffers should be used to hold video frames data.
- const bool enable_gpu_memory_buffer_video_frames_;
+ const bool enable_video_gpu_memory_buffers_;
+ const bool enable_media_stream_gpu_memory_buffers_;
// Whether video acceleration encoding/decoding should be enabled.
const bool video_accelerator_enabled_;
diff --git a/chromium/content/renderer/media/media_factory.cc b/chromium/content/renderer/media/media_factory.cc
index 59043b29fe8..5e2119c7f4c 100644
--- a/chromium/content/renderer/media/media_factory.cc
+++ b/chromium/content/renderer/media/media_factory.cc
@@ -4,6 +4,9 @@
#include "content/renderer/media/media_factory.h"
+#include <string>
+#include <utility>
+
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
@@ -26,11 +29,13 @@
#include "media/base/media_switches.h"
#include "media/base/renderer_factory_selector.h"
#include "media/base/surface_manager.h"
+#include "media/blink/remote_playback_client_wrapper_impl.h"
#include "media/blink/resource_fetch_context.h"
#include "media/blink/webencryptedmediaclient_impl.h"
#include "media/blink/webmediaplayer_impl.h"
#include "media/filters/context_3d.h"
#include "media/media_buildflags.h"
+#include "media/renderers/default_decoder_factory.h"
#include "media/renderers/default_renderer_factory.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
@@ -50,6 +55,7 @@
#include "content/renderer/media/android/stream_texture_wrapper_impl.h"
#include "media/base/android/media_codec_util.h"
#include "media/base/media.h"
+#include "media/renderers/flinging_renderer_client_factory.h"
#include "url/gurl.h"
#endif
@@ -96,11 +102,18 @@ class FrameFetchContext : public media::ResourceFetchContext {
};
void ObtainAndSetContextProvider(
- base::OnceCallback<void(viz::ContextProvider*)>
+ base::OnceCallback<void(bool,
+ scoped_refptr<ui::ContextProviderCommandBuffer>)>
set_context_provider_callback,
- media::GpuVideoAcceleratorFactories* factories) {
- viz::ContextProvider* context_provider = factories->GetMediaContextProvider();
- std::move(set_context_provider_callback).Run(context_provider);
+ std::pair<media::GpuVideoAcceleratorFactories*, bool> gpu_info) {
+ if (gpu_info.first) {
+ scoped_refptr<ui::ContextProviderCommandBuffer> context_provider =
+ gpu_info.first->GetMediaContextProvider();
+ std::move(set_context_provider_callback)
+ .Run(gpu_info.second, std::move(context_provider));
+ } else {
+ std::move(set_context_provider_callback).Run(false, nullptr);
+ }
}
// Obtains the media ContextProvider and calls the given callback on the same
@@ -109,11 +122,14 @@ void ObtainAndSetContextProvider(
// thread.
void PostMediaContextProviderToCallback(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
- base::OnceCallback<void(viz::ContextProvider*)>
+ base::OnceCallback<void(bool,
+ scoped_refptr<ui::ContextProviderCommandBuffer>)>
set_context_provider_callback) {
base::PostTaskAndReplyWithResult(
main_task_runner.get(), FROM_HERE, base::BindOnce([]() {
- return content::RenderThreadImpl::current()->GetGpuFactories();
+ return std::pair<media::GpuVideoAcceleratorFactories*, bool>(
+ content::RenderThreadImpl::current()->GetGpuFactories(),
+ !content::RenderThreadImpl::current()->IsGpuCompositingDisabled());
}),
base::BindOnce(&ObtainAndSetContextProvider,
std::move(set_context_provider_callback)));
@@ -199,7 +215,7 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
scoped_refptr<media::SwitchableAudioRendererSink> audio_renderer_sink =
AudioDeviceFactory::NewSwitchableAudioRendererSink(
AudioDeviceFactory::kSourceMediaElement,
- render_frame_->GetRoutingID(), 0, sink_id.Utf8(), security_origin);
+ render_frame_->GetRoutingID(), 0, sink_id.Utf8());
const WebPreferences webkit_preferences =
render_frame_->GetWebkitPreferences();
@@ -239,9 +255,10 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
base::WeakPtr<media::MediaObserver> media_observer;
- auto factory_selector =
- CreateRendererFactorySelector(media_log.get(), use_media_player_renderer,
- GetDecoderFactory(), &media_observer);
+ auto factory_selector = CreateRendererFactorySelector(
+ media_log.get(), use_media_player_renderer, GetDecoderFactory(),
+ std::make_unique<media::RemotePlaybackClientWrapperImpl>(client),
+ &media_observer);
#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
DCHECK(media_observer);
@@ -262,8 +279,7 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
video_frame_compositor_task_runner;
std::unique_ptr<blink::WebVideoFrameSubmitter> submitter;
bool use_surface_layer_for_video =
- base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo) &&
- !RenderThreadImpl::current()->IsGpuCompositingDisabled();
+ base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo);
if (use_surface_layer_for_video) {
// TODO(lethalantidote): Use a separate task_runner. https://crbug/753605.
video_frame_compositor_task_runner =
@@ -272,8 +288,7 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
base::BindRepeating(
&PostMediaContextProviderToCallback,
RenderThreadImpl::current()->GetCompositorMainThreadTaskRunner()),
- RenderThreadImpl::current()->GetSharedBitmapManager(),
- RenderThreadImpl::current()->GetGpuMemoryBufferManager(), settings);
+ settings);
} else {
video_frame_compositor_task_runner =
render_thread->compositor_task_runner()
@@ -303,12 +318,7 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer(
std::move(metrics_provider),
base::Bind(&blink::WebSurfaceLayerBridge::Create, layer_tree_view),
RenderThreadImpl::current()->SharedMainThreadContextProvider(),
- use_surface_layer_for_video,
- base::BindRepeating(
- &RenderFrameImpl::OnPictureInPictureSurfaceIdUpdated,
- base::Unretained(render_frame_)),
- base::BindRepeating(&RenderFrameImpl::OnExitPictureInPicture,
- base::Unretained(render_frame_))));
+ use_surface_layer_for_video));
std::unique_ptr<media::VideoFrameCompositor> vfc =
std::make_unique<media::VideoFrameCompositor>(
@@ -341,6 +351,7 @@ MediaFactory::CreateRendererFactorySelector(
media::MediaLog* media_log,
bool use_media_player,
media::DecoderFactory* decoder_factory,
+ std::unique_ptr<media::RemotePlaybackClientWrapper> client_wrapper,
base::WeakPtr<media::MediaObserver>* out_media_observer) {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
// Render thread may not exist in tests, returning nullptr if it does not.
@@ -352,6 +363,7 @@ MediaFactory::CreateRendererFactorySelector(
#if defined(OS_ANDROID)
DCHECK(remote_interfaces_);
+ // MediaPlayerRendererClientFactory setup.
auto mojo_media_player_renderer_factory =
std::make_unique<media::MojoRendererFactory>(
media::mojom::HostedRendererType::kMediaPlayer,
@@ -371,6 +383,38 @@ MediaFactory::CreateRendererFactorySelector(
base::ThreadTaskRunnerHandle::Get())));
factory_selector->SetUseMediaPlayer(use_media_player);
+
+ // FlingingRendererClientFactory (FRCF) setup.
+ auto mojo_flinging_factory = std::make_unique<media::MojoRendererFactory>(
+ media::mojom::HostedRendererType::kFlinging,
+ media::MojoRendererFactory::GetGpuFactoriesCB(),
+ GetMediaInterfaceFactory());
+
+ // Save a temp copy of the pointer, before moving it into the FRCF.
+ // The FRCF cannot be aware of the MojoRendererFactory directly, due to
+ // layering issues.
+ media::MojoRendererFactory* temp_mojo_flinging_factory =
+ mojo_flinging_factory.get();
+
+ auto flinging_factory =
+ std::make_unique<media::FlingingRendererClientFactory>(
+ std::move(mojo_flinging_factory), std::move(client_wrapper));
+
+ // base::Unretained is safe here because the FRCF owns the MojoRendererFactory
+ // and is guaranteed to outlive it.
+ temp_mojo_flinging_factory->SetGetTypeSpecificIdCB(base::BindRepeating(
+ &media::FlingingRendererClientFactory::GetActivePresentationId,
+ base::Unretained(flinging_factory.get())));
+
+ // base::Unretained is safe here because |factory_selector| owns
+ // |flinging_factory|.
+ factory_selector->SetQueryIsFlingingActiveCB(
+ base::Bind(&media::FlingingRendererClientFactory::IsFlingingActive,
+ base::Unretained(flinging_factory.get())));
+
+ factory_selector->AddFactory(
+ media::RendererFactorySelector::FactoryType::FLINGING,
+ std::move(flinging_factory));
#endif // defined(OS_ANDROID)
bool use_mojo_renderer_factory = false;
@@ -442,7 +486,6 @@ blink::WebMediaPlayer* MediaFactory::CreateWebMediaPlayerForMediaStream(
const blink::WebString& sink_id,
const blink::WebSecurityOrigin& security_origin,
blink::WebLocalFrame* frame) {
-#if BUILDFLAG(ENABLE_WEBRTC)
RenderThreadImpl* const render_thread = RenderThreadImpl::current();
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner =
@@ -459,10 +502,7 @@ blink::WebMediaPlayer* MediaFactory::CreateWebMediaPlayerForMediaStream(
CreateMediaStreamRendererFactory(), render_thread->GetIOTaskRunner(),
compositor_task_runner, render_thread->GetMediaThreadTaskRunner(),
render_thread->GetWorkerTaskRunner(), render_thread->GetGpuFactories(),
- sink_id, security_origin);
-#else
- return NULL;
-#endif // BUILDFLAG(ENABLE_WEBRTC)
+ sink_id);
}
media::RendererWebMediaPlayerDelegate*
@@ -480,22 +520,21 @@ MediaFactory::CreateMediaStreamRendererFactory() {
GetContentClient()->renderer()->CreateMediaStreamRendererFactory();
if (factory.get())
return factory;
-#if BUILDFLAG(ENABLE_WEBRTC)
return std::unique_ptr<MediaStreamRendererFactory>(
new MediaStreamRendererFactoryImpl());
-#else
- return std::unique_ptr<MediaStreamRendererFactory>(
- static_cast<MediaStreamRendererFactory*>(NULL));
-#endif
}
media::DecoderFactory* MediaFactory::GetDecoderFactory() {
-#if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) || BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
if (!decoder_factory_) {
- decoder_factory_.reset(
+ std::unique_ptr<media::DecoderFactory> external_decoder_factory;
+#if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) || BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
+ external_decoder_factory.reset(
new media::MojoDecoderFactory(GetMediaInterfaceFactory()));
- }
#endif
+ decoder_factory_.reset(
+ new media::DefaultDecoderFactory(std::move(external_decoder_factory)));
+ }
+
return decoder_factory_.get();
}
diff --git a/chromium/content/renderer/media/media_factory.h b/chromium/content/renderer/media/media_factory.h
index 406b172666c..1d5aeece741 100644
--- a/chromium/content/renderer/media/media_factory.h
+++ b/chromium/content/renderer/media/media_factory.h
@@ -43,6 +43,7 @@ class CdmFactory;
class DecoderFactory;
class MediaLog;
class MediaObserver;
+class RemotePlaybackClientWrapper;
class RendererWebMediaPlayerDelegate;
class SurfaceManager;
class WebEncryptedMediaClientImpl;
@@ -112,6 +113,7 @@ class MediaFactory {
media::MediaLog* media_log,
bool use_media_player,
media::DecoderFactory* decoder_factory,
+ std::unique_ptr<media::RemotePlaybackClientWrapper> client_wrapper,
base::WeakPtr<media::MediaObserver>* out_media_observer);
blink::WebMediaPlayer* CreateWebMediaPlayerForMediaStream(
diff --git a/chromium/content/renderer/media/media_interface_factory.cc b/chromium/content/renderer/media/media_interface_factory.cc
index 77c72875eec..f457c3854d8 100644
--- a/chromium/content/renderer/media/media_interface_factory.cc
+++ b/chromium/content/renderer/media/media_interface_factory.cc
@@ -82,6 +82,20 @@ void MediaInterfaceFactory::CreateCdm(
GetMediaInterfaceFactory()->CreateCdm(key_system, std::move(request));
}
+void MediaInterfaceFactory::CreateDecryptor(
+ int cdm_id,
+ media::mojom::DecryptorRequest request) {
+ if (!task_runner_->BelongsToCurrentThread()) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&MediaInterfaceFactory::CreateDecryptor,
+ weak_this_, cdm_id, std::move(request)));
+ return;
+ }
+
+ DVLOG(1) << __func__;
+ GetMediaInterfaceFactory()->CreateDecryptor(cdm_id, std::move(request));
+}
+
void MediaInterfaceFactory::CreateCdmProxy(
const std::string& cdm_guid,
media::mojom::CdmProxyRequest request) {
diff --git a/chromium/content/renderer/media/media_interface_factory.h b/chromium/content/renderer/media/media_interface_factory.h
index ee4a33d2953..54f8ab7710d 100644
--- a/chromium/content/renderer/media/media_interface_factory.h
+++ b/chromium/content/renderer/media/media_interface_factory.h
@@ -37,6 +37,8 @@ class CONTENT_EXPORT MediaInterfaceFactory
media::mojom::RendererRequest request) final;
void CreateCdm(const std::string& key_system,
media::mojom::ContentDecryptionModuleRequest request) final;
+ void CreateDecryptor(int cdm_id,
+ media::mojom::DecryptorRequest request) final;
// TODO(xhwang): We should not expose this here.
void CreateCdmProxy(const std::string& cdm_guid,
media::mojom::CdmProxyRequest request) final;
diff --git a/chromium/content/renderer/media/mock_audio_device_factory.cc b/chromium/content/renderer/media/mock_audio_device_factory.cc
index 80303c50f62..d4517c7250c 100644
--- a/chromium/content/renderer/media/mock_audio_device_factory.cc
+++ b/chromium/content/renderer/media/mock_audio_device_factory.cc
@@ -12,6 +12,9 @@ MockCapturerSource::~MockCapturerSource() {}
void MockCapturerSource::SetVolume(double volume) {}
+void MockCapturerSource::SetOutputDeviceForAec(
+ const std::string& output_device_id) {}
+
MockAudioDeviceFactory::MockAudioDeviceFactory()
: AudioDeviceFactory(), mock_capturer_source_(new MockCapturerSource()),
did_create_once_(false) {}
diff --git a/chromium/content/renderer/media/mock_audio_device_factory.h b/chromium/content/renderer/media/mock_audio_device_factory.h
index 62f2bea442b..33be7bf046c 100644
--- a/chromium/content/renderer/media/mock_audio_device_factory.h
+++ b/chromium/content/renderer/media/mock_audio_device_factory.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_RENDERER_MEDIA_MOCK_AUDIO_DEVICE_FACTORY_H_
#define CONTENT_RENDERER_MEDIA_MOCK_AUDIO_DEVICE_FACTORY_H_
-#include "content/renderer/media/audio_device_factory.h"
+#include <string>
+#include "content/renderer/media/audio_device_factory.h"
#include "media/base/audio_capturer_source.h"
#include "media/base/audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -17,13 +18,14 @@ namespace content {
class MockCapturerSource : public media::AudioCapturerSource {
public:
MockCapturerSource();
- MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
- CaptureCallback* callback,
- int session_id));
+ MOCK_METHOD2(Initialize,
+ void(const media::AudioParameters& params,
+ CaptureCallback* callback));
MOCK_METHOD0(Start, void());
MOCK_METHOD0(Stop, void());
MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
void SetVolume(double volume) override;
+ void SetOutputDeviceForAec(const std::string& output_device_id) override;
protected:
~MockCapturerSource() override;
@@ -44,26 +46,23 @@ class MockAudioDeviceFactory : public AudioDeviceFactory {
// These methods are just mocked because tests currently don't need them to be
// implemented.
- MOCK_METHOD4(CreateFinalAudioRendererSink,
- scoped_refptr<media::AudioRendererSink>(
- int render_frame_id,
- int sesssion_id,
- const std::string& device_id,
- const url::Origin& security_origin));
- MOCK_METHOD5(CreateAudioRendererSink,
- scoped_refptr<media::AudioRendererSink>(
- SourceType source_type,
- int render_frame_id,
- int sesssion_id,
- const std::string& device_id,
- const url::Origin& security_origin));
- MOCK_METHOD5(CreateSwitchableAudioRendererSink,
+ MOCK_METHOD3(
+ CreateFinalAudioRendererSink,
+ scoped_refptr<media::AudioRendererSink>(int render_frame_id,
+ int sesssion_id,
+ const std::string& device_id));
+ MOCK_METHOD4(
+ CreateAudioRendererSink,
+ scoped_refptr<media::AudioRendererSink>(SourceType source_type,
+ int render_frame_id,
+ int sesssion_id,
+ const std::string& device_id));
+ MOCK_METHOD4(CreateSwitchableAudioRendererSink,
scoped_refptr<media::SwitchableAudioRendererSink>(
SourceType source_type,
int render_frame_id,
int sesssion_id,
- const std::string& device_id,
- const url::Origin& security_origin));
+ const std::string& device_id));
// Returns mock_capturer_source_ once. If called a second time, the process
// will crash.
@@ -79,4 +78,4 @@ class MockAudioDeviceFactory : public AudioDeviceFactory {
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_FACTORY_H_
+#endif // CONTENT_RENDERER_MEDIA_MOCK_AUDIO_DEVICE_FACTORY_H_
diff --git a/chromium/content/renderer/media/mojo_audio_input_ipc.cc b/chromium/content/renderer/media/mojo_audio_input_ipc.cc
index a346a8442e8..44b2e55fb11 100644
--- a/chromium/content/renderer/media/mojo_audio_input_ipc.cc
+++ b/chromium/content/renderer/media/mojo_audio_input_ipc.cc
@@ -13,19 +13,21 @@
namespace content {
-MojoAudioInputIPC::MojoAudioInputIPC(StreamCreatorCB stream_creator)
+MojoAudioInputIPC::MojoAudioInputIPC(StreamCreatorCB stream_creator,
+ StreamAssociatorCB stream_associator)
: stream_creator_(std::move(stream_creator)),
+ stream_associator_(std::move(stream_associator)),
stream_client_binding_(this),
factory_client_binding_(this),
weak_factory_(this) {
DETACH_FROM_SEQUENCE(sequence_checker_);
DCHECK(stream_creator_);
+ DCHECK(stream_associator_);
}
MojoAudioInputIPC::~MojoAudioInputIPC() = default;
void MojoAudioInputIPC::CreateStream(media::AudioInputIPCDelegate* delegate,
- int session_id,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
@@ -41,8 +43,8 @@ void MojoAudioInputIPC::CreateStream(media::AudioInputIPCDelegate* delegate,
&media::AudioInputIPCDelegate::OnError, base::Unretained(delegate_)));
stream_creation_start_time_ = base::TimeTicks::Now();
- stream_creator_.Run(std::move(client), session_id, params,
- automatic_gain_control, total_segments);
+ stream_creator_.Run(std::move(client), params, automatic_gain_control,
+ total_segments);
}
void MojoAudioInputIPC::RecordStream() {
@@ -57,6 +59,15 @@ void MojoAudioInputIPC::SetVolume(double volume) {
stream_->SetVolume(volume);
}
+void MojoAudioInputIPC::SetOutputDeviceForAec(
+ const std::string& output_device_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(stream_) << "Can only be called after the stream has been created";
+ // Loopback streams have no stream ids and cannot be use echo cancellation
+ if (stream_id_.has_value())
+ stream_associator_.Run(*stream_id_, output_device_id);
+}
+
void MojoAudioInputIPC::CloseStream() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
delegate_ = nullptr;
@@ -71,7 +82,8 @@ void MojoAudioInputIPC::StreamCreated(
media::mojom::AudioInputStreamPtr stream,
media::mojom::AudioInputStreamClientRequest stream_client_request,
media::mojom::AudioDataPipePtr data_pipe,
- bool initially_muted) {
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(delegate_);
DCHECK(!stream_);
@@ -83,6 +95,10 @@ void MojoAudioInputIPC::StreamCreated(
stream_ = std::move(stream);
stream_client_binding_.Bind(std::move(stream_client_request));
+ // Keep the stream_id, if we get one. Regular input stream have stream ids,
+ // but Loopback streams do not.
+ stream_id_ = stream_id;
+
base::PlatformFile socket_handle;
auto result =
mojo::UnwrapPlatformFile(std::move(data_pipe->socket), &socket_handle);
diff --git a/chromium/content/renderer/media/mojo_audio_input_ipc.h b/chromium/content/renderer/media/mojo_audio_input_ipc.h
index 9b1533be68c..9161a53c62f 100644
--- a/chromium/content/renderer/media/mojo_audio_input_ipc.h
+++ b/chromium/content/renderer/media/mojo_audio_input_ipc.h
@@ -33,22 +33,26 @@ class CONTENT_EXPORT MojoAudioInputIPC
// called or |client| is destructed.
using StreamCreatorCB = base::RepeatingCallback<void(
mojom::RendererAudioInputStreamFactoryClientPtr client,
- int32_t session_id,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments)>;
- explicit MojoAudioInputIPC(StreamCreatorCB stream_creator);
+ using StreamAssociatorCB =
+ base::RepeatingCallback<void(const base::UnguessableToken& stream_id,
+ const std::string& output_device_id)>;
+
+ explicit MojoAudioInputIPC(StreamCreatorCB stream_creator,
+ StreamAssociatorCB stream_associator);
~MojoAudioInputIPC() override;
// AudioInputIPC implementation
void CreateStream(media::AudioInputIPCDelegate* delegate,
- int session_id,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) override;
void RecordStream() override;
void SetVolume(double volume) override;
+ void SetOutputDeviceForAec(const std::string& output_device_id) override;
void CloseStream() override;
private:
@@ -56,15 +60,19 @@ class CONTENT_EXPORT MojoAudioInputIPC
media::mojom::AudioInputStreamPtr stream,
media::mojom::AudioInputStreamClientRequest stream_client_request,
media::mojom::AudioDataPipePtr data_pipe,
- bool initially_muted) override;
+ bool initially_muted,
+ const base::Optional<base::UnguessableToken>& stream_id) override;
void OnError() override;
void OnMutedStateChanged(bool is_muted) override;
StreamCreatorCB stream_creator_;
+ StreamAssociatorCB stream_associator_;
SEQUENCE_CHECKER(sequence_checker_);
media::mojom::AudioInputStreamPtr stream_;
+ // Initialized on StreamCreated.
+ base::Optional<base::UnguessableToken> stream_id_;
mojo::Binding<AudioInputStreamClient> stream_client_binding_;
mojo::Binding<RendererAudioInputStreamFactoryClient> factory_client_binding_;
media::AudioInputIPCDelegate* delegate_ = nullptr;
diff --git a/chromium/content/renderer/media/mojo_audio_input_ipc_unittest.cc b/chromium/content/renderer/media/mojo_audio_input_ipc_unittest.cc
index b0f44bed901..540cb3125cd 100644
--- a/chromium/content/renderer/media/mojo_audio_input_ipc_unittest.cc
+++ b/chromium/content/renderer/media/mojo_audio_input_ipc_unittest.cc
@@ -32,10 +32,10 @@ namespace content {
namespace {
-const int kSessionId = 1234;
const size_t kMemoryLength = 4321;
const size_t kTotalSegments = 1;
const double kNewVolume = 0.271828;
+const char kOutputDeviceId[] = "2345";
media::AudioParameters Params() {
return media::AudioParameters::UnavailableDeviceParams();
@@ -74,7 +74,6 @@ class FakeStreamCreator {
: stream_(stream), binding_(stream_), initially_muted_(initially_muted) {}
void Create(mojom::RendererAudioInputStreamFactoryClientPtr factory_client,
- int32_t session_id,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
@@ -92,7 +91,7 @@ class FakeStreamCreator {
mojo::SharedBufferHandle::Create(kMemoryLength)
->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY),
mojo::WrapPlatformFile(foreign_socket.Release())},
- initially_muted_);
+ initially_muted_, base::UnguessableToken::Create());
}
MojoAudioInputIPC::StreamCreatorCB GetCallback() {
@@ -120,6 +119,12 @@ class FakeStreamCreator {
base::CancelableSyncSocket socket_;
};
+void AssociateOutputForAec(const base::UnguessableToken& stream_id,
+ const std::string& output_device_id) {
+ EXPECT_FALSE(stream_id.is_empty());
+ EXPECT_EQ(output_device_id, kOutputDeviceId);
+}
+
} // namespace
TEST(MojoAudioInputIPC, OnStreamCreated_Propagates) {
@@ -129,11 +134,12 @@ TEST(MojoAudioInputIPC, OnStreamCreated_Propagates) {
FakeStreamCreator creator(&stream, false);
const std::unique_ptr<media::AudioInputIPC> ipc =
- std::make_unique<MojoAudioInputIPC>(creator.GetCallback());
+ std::make_unique<MojoAudioInputIPC>(
+ creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(false));
- ipc->CreateStream(&delegate, kSessionId, Params(), false, kTotalSegments);
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
base::RunLoop().RunUntilIdle();
ipc->CloseStream();
@@ -145,14 +151,16 @@ TEST(MojoAudioInputIPC, FactoryDisconnected_SendsError) {
StrictMock<MockDelegate> delegate;
const std::unique_ptr<media::AudioInputIPC> ipc =
- std::make_unique<MojoAudioInputIPC>(base::BindRepeating(
- [](mojom::RendererAudioInputStreamFactoryClientPtr factory_client,
- int32_t session_id, const media::AudioParameters& params,
- bool automatic_gain_control, uint32_t total_segments) {}));
+ std::make_unique<MojoAudioInputIPC>(
+ base::BindRepeating(
+ [](mojom::RendererAudioInputStreamFactoryClientPtr factory_client,
+ const media::AudioParameters& params,
+ bool automatic_gain_control, uint32_t total_segments) {}),
+ base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, OnError());
- ipc->CreateStream(&delegate, kSessionId, Params(), false, kTotalSegments);
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
base::RunLoop().RunUntilIdle();
ipc->CloseStream();
@@ -166,11 +174,12 @@ TEST(MojoAudioInputIPC, OnStreamCreated_PropagatesInitiallyMuted) {
FakeStreamCreator creator(&stream, true);
const std::unique_ptr<media::AudioInputIPC> ipc =
- std::make_unique<MojoAudioInputIPC>(creator.GetCallback());
+ std::make_unique<MojoAudioInputIPC>(
+ creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(true));
- ipc->CreateStream(&delegate, kSessionId, Params(), false, kTotalSegments);
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
base::RunLoop().RunUntilIdle();
ipc->CloseStream();
@@ -184,14 +193,15 @@ TEST(MojoAudioInputIPC, IsReusable) {
FakeStreamCreator creator(&stream, false);
const std::unique_ptr<media::AudioInputIPC> ipc =
- std::make_unique<MojoAudioInputIPC>(creator.GetCallback());
+ std::make_unique<MojoAudioInputIPC>(
+ creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
for (int i = 0; i < 5; ++i) {
creator.Rearm();
EXPECT_CALL(delegate, GotOnStreamCreated(_));
- ipc->CreateStream(&delegate, kSessionId, Params(), false, kTotalSegments);
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(&delegate);
@@ -207,14 +217,15 @@ TEST(MojoAudioInputIPC, IsReusableAfterError) {
FakeStreamCreator creator(&stream, false);
const std::unique_ptr<media::AudioInputIPC> ipc =
- std::make_unique<MojoAudioInputIPC>(creator.GetCallback());
+ std::make_unique<MojoAudioInputIPC>(
+ creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
for (int i = 0; i < 5; ++i) {
creator.Rearm();
EXPECT_CALL(delegate, GotOnStreamCreated(_));
- ipc->CreateStream(&delegate, kSessionId, Params(), false, kTotalSegments);
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(&delegate);
@@ -235,12 +246,13 @@ TEST(MojoAudioInputIPC, Record_Records) {
FakeStreamCreator creator(&stream, false);
const std::unique_ptr<media::AudioInputIPC> ipc =
- std::make_unique<MojoAudioInputIPC>(creator.GetCallback());
+ std::make_unique<MojoAudioInputIPC>(
+ creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(_));
EXPECT_CALL(stream, Record());
- ipc->CreateStream(&delegate, kSessionId, Params(), false, kTotalSegments);
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
base::RunLoop().RunUntilIdle();
ipc->RecordStream();
base::RunLoop().RunUntilIdle();
@@ -256,12 +268,13 @@ TEST(MojoAudioInputIPC, SetVolume_SetsVolume) {
FakeStreamCreator creator(&stream, false);
const std::unique_ptr<media::AudioInputIPC> ipc =
- std::make_unique<MojoAudioInputIPC>(creator.GetCallback());
+ std::make_unique<MojoAudioInputIPC>(
+ creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
EXPECT_CALL(delegate, GotOnStreamCreated(_));
EXPECT_CALL(stream, SetVolume(kNewVolume));
- ipc->CreateStream(&delegate, kSessionId, Params(), false, kTotalSegments);
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
base::RunLoop().RunUntilIdle();
ipc->SetVolume(kNewVolume);
base::RunLoop().RunUntilIdle();
@@ -270,4 +283,25 @@ TEST(MojoAudioInputIPC, SetVolume_SetsVolume) {
base::RunLoop().RunUntilIdle();
}
+TEST(MojoAudioInputIPC, SetOutputDeviceForAec_AssociatesInputAndOutputForAec) {
+ base::MessageLoopForIO message_loop;
+ StrictMock<MockStream> stream;
+ StrictMock<MockDelegate> delegate;
+ FakeStreamCreator creator(&stream, false);
+
+ const std::unique_ptr<media::AudioInputIPC> ipc =
+ std::make_unique<MojoAudioInputIPC>(
+ creator.GetCallback(), base::BindRepeating(&AssociateOutputForAec));
+
+ EXPECT_CALL(delegate, GotOnStreamCreated(_));
+
+ ipc->CreateStream(&delegate, Params(), false, kTotalSegments);
+ base::RunLoop().RunUntilIdle();
+ ipc->SetOutputDeviceForAec(kOutputDeviceId);
+ base::RunLoop().RunUntilIdle();
+
+ ipc->CloseStream();
+ base::RunLoop().RunUntilIdle();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/mojo_audio_output_ipc.cc b/chromium/content/renderer/media/mojo_audio_output_ipc.cc
index 5a4c8671499..35ead19d6b9 100644
--- a/chromium/content/renderer/media/mojo_audio_output_ipc.cc
+++ b/chromium/content/renderer/media/mojo_audio_output_ipc.cc
@@ -32,16 +32,15 @@ MojoAudioOutputIPC::MojoAudioOutputIPC(
MojoAudioOutputIPC::~MojoAudioOutputIPC() {
DCHECK(!AuthorizationRequested() && !StreamCreationRequested())
<< "CloseStream must be called before destructing the AudioOutputIPC";
- // No thread check.
- // Destructing |weak_factory_| on any thread is safe since it's not used after
- // the final call to CloseStream, where its pointers are invalidated.
+ // No sequence check.
+ // Destructing |weak_factory_| on any sequence is safe since it's not used
+ // after the final call to CloseStream, where its pointers are invalidated.
}
void MojoAudioOutputIPC::RequestDeviceAuthorization(
media::AudioOutputIPCDelegate* delegate,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
DCHECK(delegate);
DCHECK(!delegate_);
@@ -57,7 +56,7 @@ void MojoAudioOutputIPC::RequestDeviceAuthorization(
session_id, device_id,
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
base::BindOnce(&MojoAudioOutputIPC::ReceivedDeviceAuthorization,
- weak_factory_.GetWeakPtr()),
+ weak_factory_.GetWeakPtr(), base::TimeTicks::Now()),
media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL,
media::AudioParameters::UnavailableDeviceParams(), std::string()));
}
@@ -82,29 +81,27 @@ void MojoAudioOutputIPC::CreateStream(media::AudioOutputIPCDelegate* delegate,
// Since the creation callback won't fire if the provider binding is gone
// and |this| owns |stream_provider_|, unretained is safe.
stream_creation_start_time_ = base::TimeTicks::Now();
- media::mojom::AudioOutputStreamClientPtr client_ptr;
+ media::mojom::AudioOutputStreamProviderClientPtr client_ptr;
binding_.Bind(mojo::MakeRequest(&client_ptr));
- stream_provider_->Acquire(mojo::MakeRequest(&stream_), std::move(client_ptr),
- params,
- base::BindOnce(&MojoAudioOutputIPC::StreamCreated,
- base::Unretained(this)));
-
- // Don't set a connection error handler. Either an error has already been
- // signaled through the AudioOutputStreamClient interface, or the connection
- // is broken because the frame owning |this| was destroyed, in which
- // case |this| will soon be cleaned up anyways.
+ // Unretained is safe because |this| owns |binding_|.
+ binding_.set_connection_error_with_reason_handler(
+ base::BindOnce(&MojoAudioOutputIPC::ProviderClientBindingDisconnected,
+ base::Unretained(this)));
+ stream_provider_->Acquire(params, std::move(client_ptr));
}
void MojoAudioOutputIPC::PlayStream() {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(stream_.is_bound());
- stream_->Play();
+ expected_state_ = kPlaying;
+ if (stream_.is_bound())
+ stream_->Play();
}
void MojoAudioOutputIPC::PauseStream() {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(stream_.is_bound());
- stream_->Pause();
+ expected_state_ = kPaused;
+ if (stream_.is_bound())
+ stream_->Pause();
}
void MojoAudioOutputIPC::CloseStream() {
@@ -113,6 +110,8 @@ void MojoAudioOutputIPC::CloseStream() {
stream_.reset();
binding_.Close();
delegate_ = nullptr;
+ expected_state_ = kPaused;
+ volume_ = base::nullopt;
// Cancel any pending callbacks for this stream.
weak_factory_.InvalidateWeakPtrs();
@@ -120,22 +119,33 @@ void MojoAudioOutputIPC::CloseStream() {
void MojoAudioOutputIPC::SetVolume(double volume) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(stream_.is_bound());
- stream_->SetVolume(volume);
+ volume_ = volume;
+ if (stream_.is_bound())
+ stream_->SetVolume(volume);
+ // else volume is set when the stream is created.
}
-void MojoAudioOutputIPC::OnError() {
+void MojoAudioOutputIPC::ProviderClientBindingDisconnected(
+ uint32_t disconnect_reason,
+ const std::string& description) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
DCHECK(delegate_);
- delegate_->OnError();
+ if (disconnect_reason ==
+ static_cast<uint32_t>(media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kPlatformError)) {
+ delegate_->OnError();
+ }
+ // Otherwise, disconnection was due to the frame owning |this| being
+ // destructed or having a navigation. In this case, |this| will soon be
+ // cleaned up.
}
-bool MojoAudioOutputIPC::AuthorizationRequested() {
+bool MojoAudioOutputIPC::AuthorizationRequested() const {
return stream_provider_.is_bound();
}
-bool MojoAudioOutputIPC::StreamCreationRequested() {
- return stream_.is_bound();
+bool MojoAudioOutputIPC::StreamCreationRequested() const {
+ return binding_.is_bound();
}
media::mojom::AudioOutputStreamProviderRequest
@@ -187,21 +197,31 @@ void MojoAudioOutputIPC::DoRequestDeviceAuthorization(
}
void MojoAudioOutputIPC::ReceivedDeviceAuthorization(
+ base::TimeTicks auth_start_time,
media::OutputDeviceStatus status,
const media::AudioParameters& params,
const std::string& device_id) const {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
DCHECK(delegate_);
+
+ // Times over 15 s should be very rare, so we don't lose interesting data by
+ // making it the upper limit.
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.Render.OutputDeviceAuthorizationTime",
+ base::TimeTicks::Now() - auth_start_time,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(15), 100);
+
delegate_->OnDeviceAuthorized(status, params, device_id);
}
-void MojoAudioOutputIPC::StreamCreated(
- media::mojom::AudioDataPipePtr data_pipe) {
+void MojoAudioOutputIPC::Created(media::mojom::AudioOutputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
DCHECK(delegate_);
UMA_HISTOGRAM_TIMES("Media.Audio.Render.OutputDeviceStreamCreationTime",
base::TimeTicks::Now() - stream_creation_start_time_);
+ stream_ = std::move(stream);
base::PlatformFile socket_handle;
auto result =
@@ -218,7 +238,13 @@ void MojoAudioOutputIPC::StreamCreated(
DCHECK_EQ(protection,
mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
- delegate_->OnStreamCreated(memory_handle, socket_handle);
+ delegate_->OnStreamCreated(memory_handle, socket_handle,
+ expected_state_ == kPlaying);
+
+ if (volume_)
+ stream_->SetVolume(*volume_);
+ if (expected_state_ == kPlaying)
+ stream_->Play();
}
} // namespace content
diff --git a/chromium/content/renderer/media/mojo_audio_output_ipc.h b/chromium/content/renderer/media/mojo_audio_output_ipc.h
index a38363bc0aa..bd78a490a92 100644
--- a/chromium/content/renderer/media/mojo_audio_output_ipc.h
+++ b/chromium/content/renderer/media/mojo_audio_output_ipc.h
@@ -10,6 +10,8 @@
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
@@ -24,7 +26,7 @@ namespace content {
// thread.
class CONTENT_EXPORT MojoAudioOutputIPC
: public media::AudioOutputIPC,
- public media::mojom::AudioOutputStreamClient {
+ public media::mojom::AudioOutputStreamProviderClient {
public:
using FactoryAccessorCB =
base::RepeatingCallback<mojom::RendererAudioOutputStreamFactory*()>;
@@ -40,8 +42,7 @@ class CONTENT_EXPORT MojoAudioOutputIPC
// AudioOutputIPC implementation.
void RequestDeviceAuthorization(media::AudioOutputIPCDelegate* delegate,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) override;
+ const std::string& device_id) override;
void CreateStream(media::AudioOutputIPCDelegate* delegate,
const media::AudioParameters& params) override;
void PlayStream() override;
@@ -49,15 +50,22 @@ class CONTENT_EXPORT MojoAudioOutputIPC
void CloseStream() override;
void SetVolume(double volume) override;
- // media::mojom::AudioOutputStreamClient implementation.
- void OnError() override;
+ // media::mojom::AudioOutputStreamProviderClient implementation.
+ void Created(media::mojom::AudioOutputStreamPtr stream,
+ media::mojom::AudioDataPipePtr data_pipe) override;
private:
+ static constexpr double kDefaultVolume = 1.0;
+
using AuthorizationCB = mojom::RendererAudioOutputStreamFactory::
RequestDeviceAuthorizationCallback;
- bool AuthorizationRequested();
- bool StreamCreationRequested();
+ bool AuthorizationRequested() const;
+ bool StreamCreationRequested() const;
+
+ void ProviderClientBindingDisconnected(uint32_t disconnect_reason,
+ const std::string& description);
+
media::mojom::AudioOutputStreamProviderRequest MakeProviderRequest();
// Tries to acquire a RendererAudioOutputStreamFactory and requests device
@@ -67,15 +75,19 @@ class CONTENT_EXPORT MojoAudioOutputIPC
const std::string& device_id,
AuthorizationCB callback);
- void ReceivedDeviceAuthorization(media::OutputDeviceStatus status,
+ void ReceivedDeviceAuthorization(base::TimeTicks auth_start_time,
+ media::OutputDeviceStatus status,
const media::AudioParameters& params,
const std::string& device_id) const;
- void StreamCreated(media::mojom::AudioDataPipePtr data_pipe);
-
const FactoryAccessorCB factory_accessor_;
- mojo::Binding<media::mojom::AudioOutputStreamClient> binding_;
+ // This is the state that |delegate_| expects the stream to be in. It is
+ // maintained for when the stream is created.
+ enum { kPaused, kPlaying } expected_state_ = kPaused;
+ base::Optional<double> volume_;
+
+ mojo::Binding<media::mojom::AudioOutputStreamProviderClient> binding_;
media::mojom::AudioOutputStreamProviderPtr stream_provider_;
media::mojom::AudioOutputStreamPtr stream_;
media::AudioOutputIPCDelegate* delegate_ = nullptr;
diff --git a/chromium/content/renderer/media/mojo_audio_output_ipc_unittest.cc b/chromium/content/renderer/media/mojo_audio_output_ipc_unittest.cc
index 8782f3ad04f..58be5468279 100644
--- a/chromium/content/renderer/media/mojo_audio_output_ipc_unittest.cc
+++ b/chromium/content/renderer/media/mojo_audio_output_ipc_unittest.cc
@@ -20,7 +20,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "url/origin.h"
using testing::_;
using testing::AtLeast;
@@ -38,10 +37,6 @@ const char kDeviceId[] = "device_id";
const char kReturnedDeviceId[] = "returned_device_id";
const double kNewVolume = 0.271828;
-url::Origin Origin() {
- return {};
-}
-
media::AudioParameters Params() {
return media::AudioParameters::UnavailableDeviceParams();
}
@@ -62,30 +57,33 @@ class TestStreamProvider : public media::mojom::AudioOutputStreamProvider {
EXPECT_TRUE(binding_);
}
- void Acquire(media::mojom::AudioOutputStreamRequest stream_request,
- media::mojom::AudioOutputStreamClientPtr client_ptr,
- const media::AudioParameters& params,
- AcquireCallback callback) override {
+ void Acquire(const media::AudioParameters& params,
+ media::mojom::AudioOutputStreamProviderClientPtr provider_client)
+ override {
EXPECT_EQ(binding_, base::nullopt);
EXPECT_NE(stream_, nullptr);
- std::swap(client_, client_ptr);
- binding_.emplace(stream_, std::move(stream_request));
+ std::swap(provider_client, provider_client_);
+ media::mojom::AudioOutputStreamPtr stream_ptr;
+ binding_.emplace(stream_, mojo::MakeRequest(&stream_ptr));
base::CancelableSyncSocket foreign_socket;
EXPECT_TRUE(
base::CancelableSyncSocket::CreatePair(&socket_, &foreign_socket));
- std::move(callback).Run({base::in_place,
- mojo::SharedBufferHandle::Create(kMemoryLength),
- mojo::WrapPlatformFile(foreign_socket.Release())});
+ provider_client_->Created(
+ std::move(stream_ptr),
+ {base::in_place, mojo::SharedBufferHandle::Create(kMemoryLength),
+ mojo::WrapPlatformFile(foreign_socket.Release())});
}
- media::mojom::AudioOutputStreamClient* client() {
- DCHECK(client_.get());
- return client_.get();
+ void SignalErrorToProviderClient() {
+ provider_client_.ResetWithReason(
+ static_cast<uint32_t>(media::mojom::AudioOutputStreamObserver::
+ DisconnectReason::kPlatformError),
+ std::string());
}
private:
media::mojom::AudioOutputStream* stream_;
- media::mojom::AudioOutputStreamClientPtr client_;
+ media::mojom::AudioOutputStreamProviderClientPtr provider_client_;
base::Optional<mojo::Binding<media::mojom::AudioOutputStream>> binding_;
base::CancelableSyncSocket socket_;
};
@@ -139,6 +137,10 @@ class TestRemoteFactory : public mojom::RendererAudioOutputStreamFactory {
expected_device_id_ = device_id;
}
+ void SignalErrorToProviderClient() {
+ provider_->SignalErrorToProviderClient();
+ }
+
void Disconnect() {
binding_.Close();
this_proxy_.reset();
@@ -148,10 +150,6 @@ class TestRemoteFactory : public mojom::RendererAudioOutputStreamFactory {
expect_request_ = false;
}
- media::mojom::AudioOutputStreamClient* client() {
- return provider_->client();
- }
-
MojoAudioOutputIPC::FactoryAccessorCB GetAccessor() {
return base::BindRepeating(&TestRemoteFactory::get, base::Unretained(this));
}
@@ -183,7 +181,8 @@ class MockDelegate : public media::AudioOutputIPCDelegate {
~MockDelegate() override {}
void OnStreamCreated(base::SharedMemoryHandle mem_handle,
- base::SyncSocket::Handle socket_handle) {
+ base::SyncSocket::Handle socket_handle,
+ bool playing_automatically) override {
base::SharedMemory sh_mem(
mem_handle, /*read_only*/ false); // Releases the shared memory handle.
base::SyncSocket socket(socket_handle); // Releases the socket descriptor.
@@ -210,7 +209,7 @@ TEST(MojoAudioOutputIPC, AuthorizeWithoutFactory_CallsAuthorizedWithError) {
NullAccessor(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
// Don't call OnDeviceAuthorized synchronously, should wait until we run the
// RunLoop.
@@ -251,7 +250,7 @@ TEST(MojoAudioOutputIPC, DeviceAuthorized_Propagates) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(nullptr));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
EXPECT_CALL(delegate, OnDeviceAuthorized(
media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
@@ -275,7 +274,7 @@ TEST(MojoAudioOutputIPC, OnDeviceCreated_Propagates) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
ipc->CreateStream(&delegate, Params());
EXPECT_CALL(delegate, OnDeviceAuthorized(
@@ -331,7 +330,7 @@ TEST(MojoAudioOutputIPC, IsReusable) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
ipc->CreateStream(&delegate, Params());
EXPECT_CALL(
@@ -360,7 +359,7 @@ TEST(MojoAudioOutputIPC, IsReusableAfterError) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(nullptr));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
EXPECT_CALL(delegate, OnDeviceAuthorized(
media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
@@ -379,7 +378,7 @@ TEST(MojoAudioOutputIPC, IsReusableAfterError) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
ipc->CreateStream(&delegate, Params());
EXPECT_CALL(
@@ -391,7 +390,7 @@ TEST(MojoAudioOutputIPC, IsReusableAfterError) {
Mock::VerifyAndClearExpectations(&delegate);
EXPECT_CALL(delegate, OnError());
- stream_factory.client()->OnError();
+ stream_factory.SignalErrorToProviderClient();
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(&delegate);
@@ -411,7 +410,7 @@ TEST(MojoAudioOutputIPC, DeviceNotAuthorized_Propagates) {
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
stream_factory.RefuseNextRequest(kSessionId, kDeviceId);
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
EXPECT_CALL(
delegate,
@@ -441,7 +440,7 @@ TEST(MojoAudioOutputIPC,
stream_factory.GetAccessor(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
EXPECT_CALL(
delegate,
@@ -473,7 +472,7 @@ TEST(MojoAudioOutputIPC,
stream_factory.GetAccessor(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
EXPECT_CALL(delegate, OnDeviceAuthorized(
media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
@@ -500,7 +499,7 @@ TEST(MojoAudioOutputIPC, AuthorizeNoClose_DCHECKs) {
stream_factory.GetAccessor(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
EXPECT_DCHECK_DEATH(ipc.reset());
ipc->CloseStream();
ipc.reset();
@@ -535,6 +534,12 @@ TEST(MojoAudioOutputIPC, Play_Plays) {
StrictMock<MockStream> stream;
StrictMock<MockDelegate> delegate;
+ EXPECT_CALL(delegate, OnDeviceAuthorized(
+ media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
+ _, std::string(kReturnedDeviceId)));
+ EXPECT_CALL(delegate, GotOnStreamCreated());
+ EXPECT_CALL(stream, Play());
+
const std::unique_ptr<media::AudioOutputIPC> ipc =
std::make_unique<MojoAudioOutputIPC>(
stream_factory.GetAccessor(),
@@ -542,17 +547,11 @@ TEST(MojoAudioOutputIPC, Play_Plays) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
ipc->CreateStream(&delegate, Params());
+ base::RunLoop().RunUntilIdle();
ipc->PlayStream();
-
- EXPECT_CALL(delegate, OnDeviceAuthorized(
- media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
- _, std::string(kReturnedDeviceId)));
- EXPECT_CALL(delegate, GotOnStreamCreated());
- EXPECT_CALL(stream, Play());
base::RunLoop().RunUntilIdle();
-
ipc->CloseStream();
base::RunLoop().RunUntilIdle();
}
@@ -563,6 +562,12 @@ TEST(MojoAudioOutputIPC, Pause_Pauses) {
StrictMock<MockStream> stream;
StrictMock<MockDelegate> delegate;
+ EXPECT_CALL(delegate, OnDeviceAuthorized(
+ media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
+ _, std::string(kReturnedDeviceId)));
+ EXPECT_CALL(delegate, GotOnStreamCreated());
+ EXPECT_CALL(stream, Pause());
+
const std::unique_ptr<media::AudioOutputIPC> ipc =
std::make_unique<MojoAudioOutputIPC>(
stream_factory.GetAccessor(),
@@ -570,17 +575,11 @@ TEST(MojoAudioOutputIPC, Pause_Pauses) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
ipc->CreateStream(&delegate, Params());
+ base::RunLoop().RunUntilIdle();
ipc->PauseStream();
-
- EXPECT_CALL(delegate, OnDeviceAuthorized(
- media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
- _, std::string(kReturnedDeviceId)));
- EXPECT_CALL(delegate, GotOnStreamCreated());
- EXPECT_CALL(stream, Pause());
base::RunLoop().RunUntilIdle();
-
ipc->CloseStream();
base::RunLoop().RunUntilIdle();
}
@@ -591,6 +590,12 @@ TEST(MojoAudioOutputIPC, SetVolume_SetsVolume) {
StrictMock<MockStream> stream;
StrictMock<MockDelegate> delegate;
+ EXPECT_CALL(delegate, OnDeviceAuthorized(
+ media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
+ _, std::string(kReturnedDeviceId)));
+ EXPECT_CALL(delegate, GotOnStreamCreated());
+ EXPECT_CALL(stream, SetVolume(kNewVolume));
+
const std::unique_ptr<media::AudioOutputIPC> ipc =
std::make_unique<MojoAudioOutputIPC>(
stream_factory.GetAccessor(),
@@ -598,17 +603,11 @@ TEST(MojoAudioOutputIPC, SetVolume_SetsVolume) {
stream_factory.PrepareProviderForAuthorization(
kSessionId, kDeviceId, std::make_unique<TestStreamProvider>(&stream));
- ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId, Origin());
+ ipc->RequestDeviceAuthorization(&delegate, kSessionId, kDeviceId);
ipc->CreateStream(&delegate, Params());
+ base::RunLoop().RunUntilIdle();
ipc->SetVolume(kNewVolume);
-
- EXPECT_CALL(delegate, OnDeviceAuthorized(
- media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
- _, std::string(kReturnedDeviceId)));
- EXPECT_CALL(delegate, GotOnStreamCreated());
- EXPECT_CALL(stream, SetVolume(kNewVolume));
base::RunLoop().RunUntilIdle();
-
ipc->CloseStream();
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/renderer/media/render_media_log.h b/chromium/content/renderer/media/render_media_log.h
index e3110a8a5a3..636be30574b 100644
--- a/chromium/content/renderer/media/render_media_log.h
+++ b/chromium/content/renderer/media/render_media_log.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
index 4a5d7103819..8c6ca64ef59 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <memory>
#include <string>
#include "base/bind.h"
@@ -88,13 +89,11 @@ int FrameIdFromCurrentContext() {
return render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE;
}
-media::AudioParameters GetOutputDeviceParameters(
- int frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+media::AudioParameters GetOutputDeviceParameters(int frame_id,
+ int session_id,
+ const std::string& device_id) {
return AudioDeviceFactory::GetOutputDeviceInfo(frame_id, session_id,
- device_id, security_origin)
+ device_id)
.output_params();
}
@@ -105,11 +104,10 @@ std::unique_ptr<RendererWebAudioDeviceImpl> RendererWebAudioDeviceImpl::Create(
int channels,
const blink::WebAudioLatencyHint& latency_hint,
WebAudioDevice::RenderCallback* callback,
- int session_id,
- const url::Origin& security_origin) {
+ int session_id) {
return std::unique_ptr<RendererWebAudioDeviceImpl>(
new RendererWebAudioDeviceImpl(layout, channels, latency_hint, callback,
- session_id, security_origin,
+ session_id,
base::Bind(&GetOutputDeviceParameters),
base::Bind(&FrameIdFromCurrentContext)));
}
@@ -120,19 +118,24 @@ RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
const blink::WebAudioLatencyHint& latency_hint,
WebAudioDevice::RenderCallback* callback,
int session_id,
- const url::Origin& security_origin,
const OutputDeviceParamsCallback& device_params_cb,
const RenderFrameIdCallback& render_frame_id_cb)
: latency_hint_(latency_hint),
client_callback_(callback),
session_id_(session_id),
- security_origin_(security_origin),
frame_id_(render_frame_id_cb.Run()) {
DCHECK(client_callback_);
DCHECK_NE(frame_id_, MSG_ROUTING_NONE);
- const media::AudioParameters hardware_params(device_params_cb.Run(
- frame_id_, session_id_, std::string(), security_origin_));
+ media::AudioParameters hardware_params(
+ device_params_cb.Run(frame_id_, session_id_, std::string()));
+
+ // On systems without audio hardware the returned parameters may be invalid.
+ // In which case just choose whatever we want for the fake device.
+ if (!hardware_params.IsValid()) {
+ hardware_params.Reset(media::AudioParameters::AUDIO_FAKE,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 480);
+ }
const media::AudioLatency::LatencyType latency =
AudioDeviceFactory::GetSourceLatencyType(
@@ -142,8 +145,9 @@ RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
GetOutputBufferSize(latency_hint_, latency, hardware_params);
DCHECK_NE(0, output_buffer_size);
- sink_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, layout,
- hardware_params.sample_rate(), 16, output_buffer_size);
+ sink_params_.Reset(hardware_params.format(), layout,
+ hardware_params.sample_rate(), output_buffer_size);
+
// Always set channels, this should be a no-op in all but the discrete case;
// this call will fail if channels doesn't match the layout in other cases.
sink_params_.set_channels_for_discrete(channels);
@@ -164,7 +168,7 @@ void RendererWebAudioDeviceImpl::Start() {
sink_ = AudioDeviceFactory::NewAudioRendererSink(
GetLatencyHintSourceType(latency_hint_.Category()), frame_id_,
- session_id_, std::string(), security_origin_);
+ session_id_, std::string());
// Use the media thread instead of the render thread for fake Render() calls
// since it has special connotations for Blink and garbage collection. Timeout
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
index 5edabfb3421..f6196ae82f2 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -7,6 +7,9 @@
#include <stdint.h>
+#include <memory>
+#include <string>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
@@ -15,7 +18,6 @@
#include "media/base/audio_renderer_sink.h"
#include "third_party/blink/public/platform/web_audio_device.h"
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
-#include "url/origin.h"
namespace base {
class SingleThreadTaskRunner;
@@ -37,8 +39,7 @@ class CONTENT_EXPORT RendererWebAudioDeviceImpl
int channels,
const blink::WebAudioLatencyHint& latency_hint,
blink::WebAudioDevice::RenderCallback* callback,
- int session_id,
- const url::Origin& security_origin);
+ int session_id);
// blink::WebAudioDevice implementation.
void Start() override;
@@ -63,11 +64,10 @@ class CONTENT_EXPORT RendererWebAudioDeviceImpl
protected:
// Callback to get output device params (for tests).
- using OutputDeviceParamsCallback = base::Callback<media::AudioParameters(
- int frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin)>;
+ using OutputDeviceParamsCallback =
+ base::Callback<media::AudioParameters(int frame_id,
+ int session_id,
+ const std::string& device_id)>;
// Callback get render frame ID for current context (for tests).
using RenderFrameIdCallback = base::Callback<int()>;
@@ -77,7 +77,6 @@ class CONTENT_EXPORT RendererWebAudioDeviceImpl
const blink::WebAudioLatencyHint& latency_hint,
blink::WebAudioDevice::RenderCallback* callback,
int session_id,
- const url::Origin& security_origin,
const OutputDeviceParamsCallback& device_params_cb,
const RenderFrameIdCallback& render_frame_id_cb);
@@ -101,9 +100,6 @@ class CONTENT_EXPORT RendererWebAudioDeviceImpl
// ID to allow browser to select the correct input device for unified IO.
int session_id_;
- // Security origin, used to check permissions for |output_device_|.
- url::Origin security_origin_;
-
// Used to suspend |sink_| usage when silence has been detected for too long.
std::unique_ptr<media::SilentSinkSuspender> webaudio_suspender_;
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
index 82327d64efb..5b338c5e67b 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
@@ -32,11 +32,10 @@ int MockFrameIdFromCurrentContext() {
media::AudioParameters MockGetOutputDeviceParameters(
int frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
- kHardwareSampleRate, 16, kHardwareBufferSize);
+ kHardwareSampleRate, kHardwareBufferSize);
}
class RendererWebAudioDeviceImplUnderTest : public RendererWebAudioDeviceImpl {
@@ -46,14 +45,12 @@ class RendererWebAudioDeviceImplUnderTest : public RendererWebAudioDeviceImpl {
int channels,
const blink::WebAudioLatencyHint& latency_hint,
blink::WebAudioDevice::RenderCallback* callback,
- int session_id,
- const url::Origin& security_origin)
+ int session_id)
: RendererWebAudioDeviceImpl(layout,
channels,
latency_hint,
callback,
session_id,
- security_origin,
base::Bind(&MockGetOutputDeviceParameters),
base::Bind(&MockFrameIdFromCurrentContext)) {
}
@@ -70,7 +67,7 @@ class RendererWebAudioDeviceImplTest
void SetupDevice(blink::WebAudioLatencyHint latencyHint) {
webaudio_device_.reset(new RendererWebAudioDeviceImplUnderTest(
- media::CHANNEL_LAYOUT_MONO, 1, latencyHint, this, 0, url::Origin()));
+ media::CHANNEL_LAYOUT_MONO, 1, latencyHint, this, 0));
webaudio_device_->SetMediaTaskRunnerForTesting(message_loop_.task_runner());
}
@@ -79,36 +76,33 @@ class RendererWebAudioDeviceImplTest
layout, channels,
blink::WebAudioLatencyHint(
blink::WebAudioLatencyHint::kCategoryInteractive),
- this, 0, url::Origin()));
+ this, 0));
webaudio_device_->SetMediaTaskRunnerForTesting(message_loop_.task_runner());
}
MOCK_METHOD1(CreateAudioCapturerSource,
scoped_refptr<media::AudioCapturerSource>(int));
- MOCK_METHOD4(CreateFinalAudioRendererSink,
+ MOCK_METHOD3(CreateFinalAudioRendererSink,
scoped_refptr<media::AudioRendererSink>(int,
int,
- const std::string&,
- const url::Origin&));
- MOCK_METHOD5(
+ const std::string&));
+ MOCK_METHOD4(
CreateSwitchableAudioRendererSink,
scoped_refptr<media::SwitchableAudioRendererSink>(SourceType,
int,
int,
- const std::string&,
- const url::Origin&));
+ const std::string&));
scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
SourceType source_type,
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) override {
scoped_refptr<media::MockAudioRendererSink> mock_sink =
new media::MockAudioRendererSink(
device_id, media::OUTPUT_DEVICE_STATUS_OK,
MockGetOutputDeviceParameters(render_frame_id, session_id,
- device_id, security_origin));
+ device_id));
EXPECT_CALL(*mock_sink.get(), Start());
EXPECT_CALL(*mock_sink.get(), Play());
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
index 2004df38223..31ba7ced7ae 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -16,6 +16,7 @@
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
+#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/web/web_scoped_user_gesture.h"
#include "ui/gfx/geometry/size.h"
@@ -52,7 +53,7 @@ RendererWebMediaPlayerDelegate::RendererWebMediaPlayerDelegate(
#endif
idle_cleanup_timer_.SetTaskRunner(
- render_frame->GetTaskRunner(blink::TaskType::kUnthrottled));
+ render_frame->GetTaskRunner(blink::TaskType::kInternalMedia));
}
RendererWebMediaPlayerDelegate::~RendererWebMediaPlayerDelegate() {}
@@ -117,16 +118,42 @@ void RendererWebMediaPlayerDelegate::DidPlayerMutedStatusChange(int delegate_id,
delegate_id, muted));
}
-void RendererWebMediaPlayerDelegate::DidPictureInPictureSourceChange(
- int delegate_id) {
- Send(new MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged(
- routing_id(), delegate_id));
+void RendererWebMediaPlayerDelegate::DidPictureInPictureModeStart(
+ int delegate_id,
+ const viz::SurfaceId& surface_id,
+ const gfx::Size& natural_size,
+ blink::WebMediaPlayer::PipWindowOpenedCallback callback) {
+ int request_id = next_picture_in_picture_callback_id_++;
+ enter_picture_in_picture_callback_map_.insert(
+ std::make_pair(request_id, std::move(callback)));
+ Send(new MediaPlayerDelegateHostMsg_OnPictureInPictureModeStarted(
+ routing_id(), delegate_id, surface_id, natural_size, request_id));
}
void RendererWebMediaPlayerDelegate::DidPictureInPictureModeEnd(
- int delegate_id) {
- Send(new MediaPlayerDelegateHostMsg_OnPictureInPictureModeEnded(routing_id(),
- delegate_id));
+ int delegate_id,
+ base::OnceClosure callback) {
+ int request_id = next_picture_in_picture_callback_id_++;
+ exit_picture_in_picture_callback_map_.insert(
+ std::make_pair(request_id, std::move(callback)));
+ Send(new MediaPlayerDelegateHostMsg_OnPictureInPictureModeEnded(
+ routing_id(), delegate_id, request_id));
+}
+
+void RendererWebMediaPlayerDelegate::DidPictureInPictureSurfaceChange(
+ int delegate_id,
+ const viz::SurfaceId& surface_id,
+ const gfx::Size& natural_size) {
+ Send(new MediaPlayerDelegateHostMsg_OnPictureInPictureSurfaceChanged(
+ routing_id(), delegate_id, surface_id, natural_size));
+}
+
+void RendererWebMediaPlayerDelegate::
+ RegisterPictureInPictureWindowResizeCallback(
+ int player_id,
+ blink::WebMediaPlayer::PipWindowResizedCallback callback) {
+ picture_in_picture_window_resize_observer_ =
+ std::make_pair(player_id, std::move(callback));
}
void RendererWebMediaPlayerDelegate::DidPause(int player_id) {
@@ -247,6 +274,15 @@ bool RendererWebMediaPlayerDelegate::OnMessageReceived(
OnMediaDelegateVolumeMultiplierUpdate)
IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_BecamePersistentVideo,
OnMediaDelegateBecamePersistentVideo)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_EndPictureInPictureMode,
+ OnPictureInPictureModeEnded)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_OnPictureInPictureModeEnded_ACK,
+ OnPictureInPictureModeEndedAck)
+ IPC_MESSAGE_HANDLER(
+ MediaPlayerDelegateMsg_OnPictureInPictureModeStarted_ACK,
+ OnPictureInPictureModeStartedAck)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_OnPictureInPictureWindowResize,
+ OnPictureInPictureWindowResize)
IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
@@ -351,6 +387,46 @@ void RendererWebMediaPlayerDelegate::OnMediaDelegateBecamePersistentVideo(
observer->OnBecamePersistentVideo(value);
}
+void RendererWebMediaPlayerDelegate::OnPictureInPictureModeEnded(
+ int player_id) {
+ Observer* observer = id_map_.Lookup(player_id);
+ if (observer)
+ observer->OnPictureInPictureModeEnded();
+}
+
+void RendererWebMediaPlayerDelegate::OnPictureInPictureModeEndedAck(
+ int player_id,
+ int request_id) {
+ auto iter = exit_picture_in_picture_callback_map_.find(request_id);
+ DCHECK(iter != exit_picture_in_picture_callback_map_.end());
+
+ std::move(iter->second).Run();
+ exit_picture_in_picture_callback_map_.erase(iter);
+}
+
+void RendererWebMediaPlayerDelegate::OnPictureInPictureModeStartedAck(
+ int player_id,
+ int request_id,
+ const gfx::Size& window_size) {
+ auto iter = enter_picture_in_picture_callback_map_.find(request_id);
+ DCHECK(iter != enter_picture_in_picture_callback_map_.end());
+
+ std::move(iter->second).Run(blink::WebSize(window_size));
+ enter_picture_in_picture_callback_map_.erase(iter);
+}
+
+void RendererWebMediaPlayerDelegate::OnPictureInPictureWindowResize(
+ int player_id,
+ const gfx::Size& window_size) {
+ if (!picture_in_picture_window_resize_observer_ ||
+ picture_in_picture_window_resize_observer_->first != player_id) {
+ return;
+ }
+
+ picture_in_picture_window_resize_observer_->second.Run(
+ blink::WebSize(window_size));
+}
+
void RendererWebMediaPlayerDelegate::ScheduleUpdateTask() {
if (!pending_update_task_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
index 913e1444e0b..171141ef960 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -65,8 +65,18 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate
blink::WebFullscreenVideoStatus fullscreen_video_status) override;
void DidPlayerSizeChange(int delegate_id, const gfx::Size& size) override;
void DidPlayerMutedStatusChange(int delegate_id, bool muted) override;
- void DidPictureInPictureSourceChange(int delegate_id) override;
- void DidPictureInPictureModeEnd(int delegate_id) override;
+ void DidPictureInPictureModeStart(
+ int delegate_id,
+ const viz::SurfaceId&,
+ const gfx::Size&,
+ blink::WebMediaPlayer::PipWindowOpenedCallback) override;
+ void DidPictureInPictureModeEnd(int delegate_id, base::OnceClosure) override;
+ void DidPictureInPictureSurfaceChange(int delegate_id,
+ const viz::SurfaceId&,
+ const gfx::Size&) override;
+ void RegisterPictureInPictureWindowResizeCallback(
+ int player_id,
+ blink::WebMediaPlayer::PipWindowResizedCallback) override;
// content::RenderFrameObserver overrides.
void WasHidden() override;
@@ -96,6 +106,12 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate
void OnMediaDelegateSuspendAllMediaPlayers();
void OnMediaDelegateVolumeMultiplierUpdate(int player_id, double multiplier);
void OnMediaDelegateBecamePersistentVideo(int player_id, bool value);
+ void OnPictureInPictureModeEnded(int player_id);
+ void OnPictureInPictureModeEndedAck(int player_id, int request_id);
+ void OnPictureInPictureModeStartedAck(int player_id,
+ int request_id,
+ const gfx::Size&);
+ void OnPictureInPictureWindowResize(int player_id, const gfx::Size&);
// Schedules UpdateTask() to run soon.
void ScheduleUpdateTask();
@@ -162,6 +178,35 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate
// when the idle cleanup timer should be fired more aggressively.
bool is_jelly_bean_;
+ // Map associating a callback with a request sent to the browser process. The
+ // index is used as a unique request id that is passed to the browser process
+ // and will then ACK with the same id which will be used to run the right
+ // callback.
+ using ExitPictureInPictureCallbackMap =
+ base::flat_map<int, base::OnceClosure>;
+ ExitPictureInPictureCallbackMap exit_picture_in_picture_callback_map_;
+
+ // Map associating a callback with a request sent to the browser process. The
+ // index is used as a unique request id that is passed to the browser process
+ // and will then ACK with the same id which will be used to run the right
+ // callback.
+ using EnterPictureInPictureCallbackMap =
+ base::flat_map<int, blink::WebMediaPlayer::PipWindowOpenedCallback>;
+ EnterPictureInPictureCallbackMap enter_picture_in_picture_callback_map_;
+
+ // Counter that is used to use unique request id associated with
+ // picture-in-picture callbacks. It is incremented every time it is used.
+ int next_picture_in_picture_callback_id_ = 0;
+
+ // Associating a player id and a Picture-in-Picture window resize callback.
+ // It holds the callback alive and guarantees that the notification sent from
+ // the browser proccess matches the player currently in Picture-in-Picture in
+ // the renderer.
+ using PictureInPictureWindowResizeObserver =
+ std::pair<int, blink::WebMediaPlayer::PipWindowResizedCallback>;
+ base::Optional<PictureInPictureWindowResizeObserver>
+ picture_in_picture_window_resize_observer_;
+
DISALLOW_COPY_AND_ASSIGN(RendererWebMediaPlayerDelegate);
};
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
index e1565a1d0fa..26d8e6ab43b 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
@@ -48,6 +48,7 @@ class MockWebMediaPlayerDelegateObserver
MOCK_METHOD1(OnSeekBackward, void(double));
MOCK_METHOD1(OnVolumeMultiplierUpdate, void(double));
MOCK_METHOD1(OnBecamePersistentVideo, void(bool));
+ MOCK_METHOD0(OnPictureInPictureModeEnded, void());
};
class RendererWebMediaPlayerDelegateTest : public content::RenderViewTest {
diff --git a/chromium/content/renderer/media/stream/apply_constraints_processor.cc b/chromium/content/renderer/media/stream/apply_constraints_processor.cc
index 41adbb2084b..874d3bd98b3 100644
--- a/chromium/content/renderer/media/stream/apply_constraints_processor.cc
+++ b/chromium/content/renderer/media/stream/apply_constraints_processor.cc
@@ -247,6 +247,8 @@ VideoCaptureSettings ApplyConstraintsProcessor::SelectVideoSettings(
blink::mojom::VideoInputDeviceCapabilities::New();
device_capabilities->device_id =
current_request_.Track().Source().Id().Ascii();
+ device_capabilities->group_id =
+ current_request_.Track().Source().GroupId().Ascii();
device_capabilities->facing_mode =
GetCurrentVideoSource() ? GetCurrentVideoSource()->device().video_facing
: media::MEDIA_VIDEO_FACING_NONE;
diff --git a/chromium/content/renderer/media/stream/apply_constraints_processor.h b/chromium/content/renderer/media/stream/apply_constraints_processor.h
index 08087cc8b51..a7182c2315d 100644
--- a/chromium/content/renderer/media/stream/apply_constraints_processor.h
+++ b/chromium/content/renderer/media/stream/apply_constraints_processor.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/renderer/media/stream/media_stream_constraints_util.h"
#include "media/capture/video_capture_types.h"
diff --git a/chromium/content/renderer/media/stream/external_media_stream_audio_source.cc b/chromium/content/renderer/media/stream/external_media_stream_audio_source.cc
index e66f1b71224..da39cf572b2 100644
--- a/chromium/content/renderer/media/stream/external_media_stream_audio_source.cc
+++ b/chromium/content/renderer/media/stream/external_media_stream_audio_source.cc
@@ -21,7 +21,6 @@ ExternalMediaStreamAudioSource::ExternalMediaStreamAudioSource(
MediaStreamAudioSource::SetFormat(media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
sample_rate,
- 16, // Legacy parameter (data is always in 32-bit float format).
frames_per_buffer));
}
@@ -39,7 +38,7 @@ bool ExternalMediaStreamAudioSource::EnsureSourceIsStarted() {
<< (is_local_source() ? "local" : "remote")
<< " source with audio parameters={"
<< GetAudioParameters().AsHumanReadableString() << "}.";
- source_->Initialize(GetAudioParameters(), this, -1);
+ source_->Initialize(GetAudioParameters(), this);
source_->Start();
was_started_ = true;
return true;
diff --git a/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc b/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc
index 4c065c21370..25d43bf45c8 100644
--- a/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc
+++ b/chromium/content/renderer/media/stream/local_media_stream_audio_source.cc
@@ -41,7 +41,6 @@ LocalMediaStreamAudioSource::LocalMediaStreamAudioSource(
SetFormat(media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
device.input.channel_layout(), device.input.sample_rate(),
- 16, // Legacy parameter (data is always in 32-bit float format).
frames_per_buffer));
}
@@ -66,9 +65,9 @@ bool LocalMediaStreamAudioSource::EnsureSourceIsStarted() {
<< consumer_render_frame_id_ << " with audio parameters={"
<< GetAudioParameters().AsHumanReadableString() << "}.";
- source_ =
- AudioDeviceFactory::NewAudioCapturerSource(consumer_render_frame_id_);
- source_->Initialize(GetAudioParameters(), this, device().session_id);
+ source_ = AudioDeviceFactory::NewAudioCapturerSource(
+ consumer_render_frame_id_, device().session_id);
+ source_->Initialize(GetAudioParameters(), this);
source_->Start();
return true;
}
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor.cc b/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
index c3d73e72304..9b76c672c26 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor.cc
@@ -629,6 +629,8 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
base::FeatureList::IsEnabled(features::kWebRtcAecBoundedErlSetup);
aec3_config.echo_removal_control.has_clock_drift =
base::FeatureList::IsEnabled(features::kWebRtcAecClockDriftSetup);
+ aec3_config.echo_audibility.use_stationary_properties =
+ base::FeatureList::IsEnabled(features::kWebRtcAecNoiseTransparency);
ap_builder.SetEchoControlFactory(
std::unique_ptr<webrtc::EchoControlFactory>(
@@ -738,7 +740,6 @@ void MediaStreamAudioProcessor::InitializeCaptureFifo(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
output_channel_layout,
output_sample_rate,
- 16,
output_frames);
capture_fifo_.reset(
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc
index 00e15c4c359..4c471a4ea36 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.cc
@@ -75,6 +75,7 @@ AudioProcessingProperties::~AudioProcessingProperties() = default;
void AudioProcessingProperties::DisableDefaultProperties() {
enable_sw_echo_cancellation = false;
+ disable_hw_echo_cancellation = false;
goog_auto_gain_control = false;
goog_experimental_echo_cancellation = false;
goog_typing_noise_detection = false;
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h
index 95240ed833c..235fd87a925 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor_options.h
@@ -46,9 +46,9 @@ struct CONTENT_EXPORT AudioProcessingProperties {
void DisableDefaultProperties();
bool enable_sw_echo_cancellation = true;
- bool disable_hw_echo_cancellation = false;
- bool disable_hw_noise_suppression = false;
+ bool disable_hw_echo_cancellation = true;
bool enable_experimental_hw_echo_cancellation = false;
+ bool disable_hw_noise_suppression = false;
bool goog_audio_mirroring = false;
bool goog_auto_gain_control = true;
bool goog_experimental_echo_cancellation =
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
index 36146788a5a..16e71069bdb 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
@@ -14,7 +14,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/aligned_memory.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/path_service.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -66,7 +66,7 @@ const int kMaxNumberOfPlayoutDataChannels = 2;
void ReadDataFromSpeechFile(char* data, int length) {
base::FilePath file;
- CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file));
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &file));
file = file.Append(FILE_PATH_LITERAL("media"))
.Append(FILE_PATH_LITERAL("test"))
.Append(FILE_PATH_LITERAL("data"))
@@ -85,8 +85,8 @@ class AecDumpMessageFilterForTest : public AecDumpMessageFilter {
// This class is only used for setting |override_aec3_|, so we simply inject
// the current task runner.
AecDumpMessageFilterForTest()
- : AecDumpMessageFilter(base::MessageLoop::current()->task_runner(),
- base::MessageLoop::current()->task_runner()) {}
+ : AecDumpMessageFilter(base::MessageLoopCurrent::Get()->task_runner(),
+ base::MessageLoopCurrent::Get()->task_runner()) {}
void set_override_aec3(base::Optional<bool> override_aec3) {
override_aec3_ = override_aec3;
@@ -115,7 +115,6 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
: params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
48000,
- 16,
480) {}
protected:
@@ -306,10 +305,9 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestAllSampleRates) {
{ 8000, 16000, 22050, 32000, 44100, 48000 };
for (size_t i = 0; i < arraysize(kSupportedSampleRates); ++i) {
int buffer_size = kSupportedSampleRates[i] / 100;
- media::AudioParameters params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, kSupportedSampleRates[i], 16,
- buffer_size);
+ media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO,
+ kSupportedSampleRates[i], buffer_size);
audio_processor->OnCaptureFormatChanged(params);
VerifyDefaultComponents(audio_processor.get());
@@ -394,7 +392,7 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
EXPECT_FALSE(audio_processor->has_audio_processing());
const media::AudioParameters source_params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 480);
+ media::CHANNEL_LAYOUT_STEREO, 48000, 480);
audio_processor->OnCaptureFormatChanged(source_params);
// There's no sense in continuing if this fails.
ASSERT_EQ(2, audio_processor->OutputFormat().channels());
@@ -456,7 +454,7 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestWithKeyboardMicChannel) {
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC,
- 48000, 16, 480);
+ 48000, 480);
audio_processor->OnCaptureFormatChanged(params);
ProcessDataAndVerifyFormat(audio_processor.get(),
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_source.cc b/chromium/content/renderer/media/stream/media_stream_audio_source.cc
index b11dd241ed6..8ceda6cb236 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_source.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_source.cc
@@ -168,4 +168,8 @@ void MediaStreamAudioSource::SetMutedState(bool muted_state) {
GetWeakPtr(), muted_state));
}
+base::SingleThreadTaskRunner* MediaStreamAudioSource::GetTaskRunner() const {
+ return task_runner_.get();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_source.h b/chromium/content/renderer/media/stream/media_stream_audio_source.h
index c8f1a87244a..cc55c329096 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_source.h
+++ b/chromium/content/renderer/media/stream/media_stream_audio_source.h
@@ -142,6 +142,9 @@ class CONTENT_EXPORT MediaStreamAudioSource : public MediaStreamSource {
// Sets muted state and notifies it to all registered tracks.
void SetMutedState(bool state);
+ // Gets the TaskRunner for the main thread, for subclasses that need it.
+ base::SingleThreadTaskRunner* GetTaskRunner() const;
+
private:
// MediaStreamSource override.
void DoStopSource() final;
diff --git a/chromium/content/renderer/media/stream/media_stream_audio_unittest.cc b/chromium/content/renderer/media/stream/media_stream_audio_unittest.cc
index bf1a301e1f9..abddd1deed5 100644
--- a/chromium/content/renderer/media/stream/media_stream_audio_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_audio_unittest.cc
@@ -93,7 +93,7 @@ class FakeMediaStreamAudioSource
if (!audio_bus_ || audio_bus_->frames() != buffer_size) {
MediaStreamAudioSource::SetFormat(media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, kSampleRate, 16, buffer_size));
+ media::CHANNEL_LAYOUT_MONO, kSampleRate, buffer_size));
audio_bus_ = media::AudioBus::Create(1, buffer_size);
}
@@ -300,7 +300,7 @@ TEST_F(MediaStreamAudioTest, BasicUsage) {
// Check that the audio parameters propagated to the track and sink.
const media::AudioParameters expected_params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- kSampleRate, 16, kBufferSize);
+ kSampleRate, kBufferSize);
EXPECT_TRUE(expected_params.Equals(track()->GetOutputFormat()));
EXPECT_TRUE(expected_params.Equals(sink.params()));
@@ -369,7 +369,7 @@ TEST_F(MediaStreamAudioTest, FormatChangesPropagate) {
base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
const media::AudioParameters expected_params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- kSampleRate, 16, kBufferSize);
+ kSampleRate, kBufferSize);
EXPECT_TRUE(expected_params.Equals(track()->GetOutputFormat()));
EXPECT_TRUE(expected_params.Equals(sink.params()));
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util.cc
index bcc96ef27ce..52a4824eae8 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util.cc
@@ -9,6 +9,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/media_stream_request.h"
#include "content/renderer/media/stream/media_stream_constraints_util_sets.h"
#include "content/renderer/media/stream/media_stream_constraints_util_video_device.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -327,11 +328,15 @@ blink::WebMediaStreamSource::Capabilities ComputeCapabilitiesForVideoSource(
const blink::WebString& device_id,
const media::VideoCaptureFormats& formats,
media::VideoFacingMode facing_mode,
- bool is_device_capture) {
+ bool is_device_capture,
+ const base::Optional<std::string>& group_id) {
blink::WebMediaStreamSource::Capabilities capabilities;
- capabilities.device_id = device_id;
- if (is_device_capture)
+ capabilities.device_id = std::move(device_id);
+ if (is_device_capture) {
capabilities.facing_mode = ToWebFacingMode(facing_mode);
+ if (group_id)
+ capabilities.group_id = blink::WebString::FromUTF8(*group_id);
+ }
if (!formats.empty()) {
int max_width = 1;
int max_height = 1;
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util.h b/chromium/content/renderer/media/stream/media_stream_constraints_util.h
index fcd85ec2588..0e40d0790ab 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util.h
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util.h
@@ -373,10 +373,12 @@ double StringConstraintFitnessDistance(
// This method computes capabilities for a video source based on the given
// |formats|. |facing_mode| is valid only in case of video device capture.
blink::WebMediaStreamSource::Capabilities CONTENT_EXPORT
-ComputeCapabilitiesForVideoSource(const blink::WebString& device_id,
- const media::VideoCaptureFormats& formats,
- media::VideoFacingMode facing_mode,
- bool is_device_capture);
+ComputeCapabilitiesForVideoSource(
+ const blink::WebString& device_id,
+ const media::VideoCaptureFormats& formats,
+ media::VideoFacingMode facing_mode,
+ bool is_device_capture,
+ const base::Optional<std::string>& group_id = base::nullopt);
} // namespace content
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc
index 80cce4b79a4..2b48e570ee7 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.cc
@@ -15,6 +15,7 @@
#include "content/renderer/media/stream/media_stream_constraints_util_sets.h"
#include "content/renderer/media/stream/media_stream_video_source.h"
#include "content/renderer/media/stream/processed_local_audio_source.h"
+#include "media/base/audio_parameters.h"
#include "media/base/limits.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -173,23 +174,9 @@ base::Optional<std::string> SelectOptionalString(
return set.FirstElement();
}
-bool SelectEnableSwEchoCancellation(
- base::Optional<bool> echo_cancellation,
- base::Optional<bool> goog_echo_cancellation,
- const media::AudioParameters& audio_parameters,
- bool default_audio_processing_value,
- bool should_enable_experimental_hw_echo_cancellation) {
- // If there is hardware echo cancellation, return false.
- const bool has_hw_echo_canceller =
- (audio_parameters.effects() & media::AudioParameters::ECHO_CANCELLER);
- const bool has_experimental_hw_echo_canceller =
- (audio_parameters.effects() &
- media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
- if (audio_parameters.IsValid() &&
- (has_hw_echo_canceller ||
- (has_experimental_hw_echo_canceller &&
- should_enable_experimental_hw_echo_cancellation)))
- return false;
+bool SelectUseEchoCancellation(base::Optional<bool> echo_cancellation,
+ base::Optional<bool> goog_echo_cancellation,
+ bool is_device_capture) {
DCHECK(echo_cancellation && goog_echo_cancellation
? *echo_cancellation == *goog_echo_cancellation
: true);
@@ -198,7 +185,22 @@ bool SelectEnableSwEchoCancellation(
if (goog_echo_cancellation)
return *goog_echo_cancellation;
- return default_audio_processing_value;
+ // Echo cancellation is enabled by default for device capture and disabled by
+ // default for content capture.
+ return is_device_capture;
+}
+
+std::vector<std::string> GetEchoCancellationTypesFromParameters(
+ const media::AudioParameters& audio_parameters) {
+ if (audio_parameters.effects() &
+ (media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER |
+ media::AudioParameters::ECHO_CANCELLER)) {
+ // If the hardware supports echo cancellation, return both echo cancellers.
+ return {blink::kEchoCancellationTypeBrowser,
+ blink::kEchoCancellationTypeSystem};
+ }
+ // The browser echo canceller is always available.
+ return {blink::kEchoCancellationTypeBrowser};
}
// This class represents all the candidates settings for a single audio device.
@@ -214,8 +216,14 @@ class SingleDeviceCandidateSet {
device_id_set_ = DiscreteSet<std::string>({capability.DeviceID()});
MediaStreamAudioSource* source = capability.source();
- if (!source)
+
+ // Set up echo cancellation types. Depending on if we have a source or not
+ // it's set up differently.
+ if (!source) {
+ echo_cancellation_type_set_ = DiscreteSet<std::string>(
+ GetEchoCancellationTypesFromParameters(parameters_));
return;
+ }
// Properties not related to audio processing.
bool_sets_[HOTWORD_ENABLED] =
@@ -234,22 +242,35 @@ class SingleDeviceCandidateSet {
properties.DisableDefaultProperties();
}
- bool echo_cancellation_enabled = false;
- if (properties.enable_sw_echo_cancellation) {
- echo_cancellation_enabled = true;
- } else if (properties.disable_hw_echo_cancellation) {
- // Software and hardware echo cancellation disabled.
- echo_cancellation_enabled = false;
- } else {
- // Software echo cancellation disabled, but hardware echo cancellation
- // allowed. In this case, look at device parameters.
- echo_cancellation_enabled = source->device().input.effects() &
- media::AudioParameters::ECHO_CANCELLER;
- }
+ const bool experimental_hardware_cancellation_available =
+ properties.enable_experimental_hw_echo_cancellation &&
+ (parameters_.effects() &
+ media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
+
+ const bool hardware_echo_cancellation_available =
+ parameters_.effects() & media::AudioParameters::ECHO_CANCELLER;
+
+ const bool hardware_echo_cancellation_enabled =
+ !properties.disable_hw_echo_cancellation &&
+ (hardware_echo_cancellation_available ||
+ experimental_hardware_cancellation_available);
+
+ const bool echo_cancellation_enabled =
+ properties.enable_sw_echo_cancellation ||
+ hardware_echo_cancellation_enabled;
+
bool_sets_[ECHO_CANCELLATION] =
DiscreteSet<bool>({echo_cancellation_enabled});
bool_sets_[GOOG_ECHO_CANCELLATION] = bool_sets_[ECHO_CANCELLATION];
+ if (properties.enable_sw_echo_cancellation) {
+ echo_cancellation_type_set_ =
+ DiscreteSet<std::string>({blink::kEchoCancellationTypeBrowser});
+ } else if (hardware_echo_cancellation_enabled) {
+ echo_cancellation_type_set_ =
+ DiscreteSet<std::string>({blink::kEchoCancellationTypeSystem});
+ }
+
bool_sets_[GOOG_AUDIO_MIRRORING] =
DiscreteSet<bool>({properties.goog_audio_mirroring});
@@ -319,6 +340,21 @@ class SingleDeviceCandidateSet {
blink::WebMediaTrackConstraintSet().echo_cancellation.GetName();
return;
}
+
+ echo_cancellation_type_set_ = echo_cancellation_type_set_.Intersection(
+ StringSetFromConstraint(constraint_set.echo_cancellation_type));
+ if (echo_cancellation_type_set_.IsEmpty()) {
+ failed_constraint_name_ = constraint_set.echo_cancellation_type.GetName();
+ return;
+ }
+
+ // If echo cancellation constraint is not true, the type set should not have
+ // explicit elements.
+ if (!bool_sets_[ECHO_CANCELLATION].Contains(true) &&
+ constraint_set.echo_cancellation_type.HasExact()) {
+ failed_constraint_name_ = constraint_set.echo_cancellation_type.GetName();
+ return;
+ }
}
// Fitness function to support device selection. Based on
@@ -355,6 +391,20 @@ class SingleDeviceCandidateSet {
}
}
+ // If echo cancellation constraint is not set to true, the type shall be
+ // ignored.
+ if ((constraint_set.*kBlinkBoolConstraintFields[ECHO_CANCELLATION])
+ .Matches(true) &&
+ constraint_set.echo_cancellation_type.HasIdeal()) {
+ for (const blink::WebString& ideal_value :
+ constraint_set.echo_cancellation_type.Ideal()) {
+ if (echo_cancellation_type_set_.Contains(ideal_value.Utf8())) {
+ fitness += 1.0;
+ break;
+ }
+ }
+ }
+
return fitness;
}
@@ -364,8 +414,7 @@ class SingleDeviceCandidateSet {
const blink::WebMediaTrackConstraintSet& basic_constraint_set,
const std::string& default_device_id,
const std::string& media_stream_source,
- bool should_disable_hardware_noise_suppression,
- bool should_enable_experimental_hw_echo_cancellation) const {
+ bool should_disable_hardware_noise_suppression) const {
std::string device_id = SelectString(
device_id_set_, basic_constraint_set.device_id, default_device_id);
bool hotword_enabled =
@@ -384,8 +433,7 @@ class SingleDeviceCandidateSet {
AudioProcessingProperties audio_processing_properties =
SelectAudioProcessingProperties(
basic_constraint_set, is_device_capture,
- should_disable_hardware_noise_suppression,
- should_enable_experimental_hw_echo_cancellation);
+ should_disable_hardware_noise_suppression);
return AudioCaptureSettings(
std::move(device_id), parameters_, hotword_enabled, disable_local_echo,
@@ -393,14 +441,60 @@ class SingleDeviceCandidateSet {
}
private:
+ void SelectEchoCancellationFlags(
+ const blink::StringConstraint& echo_cancellation_type,
+ const media::AudioParameters& audio_parameters,
+ AudioProcessingProperties* properties_out) const {
+ // Try to use an ideal candidate, if supplied.
+ base::Optional<std::string> selected_type;
+ if (echo_cancellation_type.HasIdeal()) {
+ for (const auto& ideal : echo_cancellation_type.Ideal()) {
+ std::string candidate = ideal.Utf8();
+ if (echo_cancellation_type_set_.Contains(candidate)) {
+ selected_type = candidate;
+ break;
+ }
+ }
+ }
+
+ // If no ideal, or none that worked, and the set contains only one value,
+ // pick that.
+ if (!selected_type) {
+ if (!echo_cancellation_type_set_.is_universal() &&
+ echo_cancellation_type_set_.elements().size() == 1) {
+ selected_type = echo_cancellation_type_set_.FirstElement();
+ }
+ }
+
+ // Set properties based the type selected.
+ if (selected_type == blink::kEchoCancellationTypeBrowser) {
+ properties_out->enable_sw_echo_cancellation = true;
+ properties_out->disable_hw_echo_cancellation = true;
+ properties_out->enable_experimental_hw_echo_cancellation = false;
+ } else if (selected_type == blink::kEchoCancellationTypeSystem) {
+ properties_out->enable_sw_echo_cancellation = false;
+ properties_out->disable_hw_echo_cancellation = false;
+ properties_out->enable_experimental_hw_echo_cancellation = true;
+ } else {
+ // If no type has been selected, choose 'system' if the device has the
+ // ECHO_CANCELLER flag set. Choose 'browser' otherwise. Never
+ // automatically enable an experimental hardware echo canceller.
+ const bool has_hw_echo_canceller =
+ audio_parameters.IsValid() &&
+ (audio_parameters.effects() & media::AudioParameters::ECHO_CANCELLER);
+ properties_out->enable_sw_echo_cancellation = !has_hw_echo_canceller;
+ properties_out->disable_hw_echo_cancellation = !has_hw_echo_canceller;
+ properties_out->enable_experimental_hw_echo_cancellation = false;
+ }
+ }
+
// Returns the audio-processing properties supported by this
// SingleDeviceCandidateSet that best satisfy the ideal values in
// |basic_constraint_set|.
AudioProcessingProperties SelectAudioProcessingProperties(
const blink::WebMediaTrackConstraintSet& basic_constraint_set,
bool is_device_capture,
- bool should_disable_hardware_noise_suppression,
- bool should_enable_experimental_hw_echo_cancellation) const {
+ bool should_disable_hardware_noise_suppression) const {
DCHECK(!IsEmpty());
base::Optional<bool> echo_cancellation = SelectOptionalBool(
bool_sets_[ECHO_CANCELLATION], basic_constraint_set.echo_cancellation);
@@ -414,17 +508,19 @@ class SingleDeviceCandidateSet {
SelectOptionalBool(bool_sets_[GOOG_ECHO_CANCELLATION],
basic_constraint_set.goog_echo_cancellation);
+ const bool use_echo_cancellation = SelectUseEchoCancellation(
+ echo_cancellation, goog_echo_cancellation, is_device_capture);
+
AudioProcessingProperties properties;
- properties.disable_hw_echo_cancellation =
- (echo_cancellation && !*echo_cancellation) ||
- (goog_echo_cancellation && !*goog_echo_cancellation);
- properties.enable_experimental_hw_echo_cancellation =
- should_enable_experimental_hw_echo_cancellation &&
- !properties.disable_hw_echo_cancellation;
- properties.enable_sw_echo_cancellation = SelectEnableSwEchoCancellation(
- echo_cancellation, goog_echo_cancellation, parameters_,
- default_audio_processing_value,
- properties.enable_experimental_hw_echo_cancellation);
+ if (use_echo_cancellation) {
+ SelectEchoCancellationFlags(basic_constraint_set.echo_cancellation_type,
+ parameters_, &properties);
+ } else {
+ properties.enable_sw_echo_cancellation = false;
+ properties.disable_hw_echo_cancellation = true;
+ properties.enable_experimental_hw_echo_cancellation = false;
+ }
+
properties.disable_hw_noise_suppression =
should_disable_hardware_noise_suppression &&
!properties.disable_hw_echo_cancellation;
@@ -482,6 +578,7 @@ class SingleDeviceCandidateSet {
DiscreteSet<std::string> device_id_set_;
std::array<DiscreteSet<bool>, NUM_BOOL_CONSTRAINTS> bool_sets_;
DiscreteSet<std::string> goog_array_geometry_set_;
+ DiscreteSet<std::string> echo_cancellation_type_set_;
media::AudioParameters parameters_;
};
@@ -541,15 +638,13 @@ class AudioCaptureCandidates {
const blink::WebMediaTrackConstraintSet& basic_constraint_set,
const std::string& default_device_id,
const std::string& media_stream_source,
- bool should_disable_hardware_noise_suppression,
- bool should_enable_experimental_hw_echo_cancellation) const {
+ bool should_disable_hardware_noise_suppression) const {
const SingleDeviceCandidateSet* device_candidate_set =
SelectBestDevice(basic_constraint_set, default_device_id);
DCHECK(!device_candidate_set->IsEmpty());
return device_candidate_set->SelectBestSettings(
basic_constraint_set, default_device_id, media_stream_source,
- should_disable_hardware_noise_suppression,
- should_enable_experimental_hw_echo_cancellation);
+ should_disable_hardware_noise_suppression);
}
private:
@@ -610,8 +705,7 @@ const media::AudioParameters& AudioDeviceCaptureCapability::Parameters() const {
AudioCaptureSettings SelectSettingsAudioCapture(
const AudioDeviceCaptureCapabilities& capabilities,
const blink::WebMediaConstraints& constraints,
- bool should_disable_hardware_noise_suppression,
- bool should_enable_experimental_hw_echo_cancellation) {
+ bool should_disable_hardware_noise_suppression) {
std::string media_stream_source = GetMediaStreamSource(constraints);
bool is_device_capture = media_stream_source.empty();
if (capabilities.empty())
@@ -635,8 +729,7 @@ AudioCaptureSettings SelectSettingsAudioCapture(
return candidates.SelectBestSettings(
constraints.Basic(), default_device_id, media_stream_source,
- should_disable_hardware_noise_suppression,
- should_enable_experimental_hw_echo_cancellation);
+ should_disable_hardware_noise_suppression);
}
AudioCaptureSettings CONTENT_EXPORT
@@ -676,9 +769,8 @@ SelectSettingsAudioCapture(MediaStreamAudioSource* source,
!(source->device().input.effects() &
media::AudioParameters::NOISE_SUPPRESSION);
- return SelectSettingsAudioCapture(
- capabilities, constraints, should_disable_hardware_noise_suppression,
- /* should_enable_experimental_hw_echo_cancellation */ false);
+ return SelectSettingsAudioCapture(capabilities, constraints,
+ should_disable_hardware_noise_suppression);
}
} // namespace content
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h
index b6f8d4837e2..6eb84383ff8 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h
@@ -146,11 +146,10 @@ using AudioDeviceCaptureCapabilities =
// their corresponding constraints.
// TODO(guidou): Add support for other standard constraints such as sampleRate,
// channelCount and groupId. http://crbug.com/731170
-AudioCaptureSettings CONTENT_EXPORT SelectSettingsAudioCapture(
- const AudioDeviceCaptureCapabilities& capabilities,
- const blink::WebMediaConstraints& constraints,
- bool should_disable_hardware_noise_suppression,
- bool should_enable_experimental_hw_echo_cancellation);
+AudioCaptureSettings CONTENT_EXPORT
+SelectSettingsAudioCapture(const AudioDeviceCaptureCapabilities& capabilities,
+ const blink::WebMediaConstraints& constraints,
+ bool should_disable_hardware_noise_suppression);
// This variant of SelectSettings takes an existing MediaStreamAudioSource
// as input in order to determine settings that are compatible with it.
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc
index 0fc9a21d9a3..00bb3314bd7 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc
@@ -17,6 +17,7 @@
#include "content/renderer/media/stream/mock_constraint_factory.h"
#include "content/renderer/media/stream/processed_local_audio_source.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
+#include "media/base/audio_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h"
#include "third_party/blink/public/platform/web_media_constraints.h"
@@ -68,13 +69,13 @@ class MediaStreamConstraintsUtilAudioTest
"default_device",
media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16,
+ media::AudioParameters::kAudioCDSampleRate,
1000));
media::AudioParameters hw_echo_canceller_parameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 24, 1000);
+ media::AudioParameters::kAudioCDSampleRate, 1000);
hw_echo_canceller_parameters.set_effects(
media::AudioParameters::ECHO_CANCELLER);
capabilities_.emplace_back("hw_echo_canceller_device",
@@ -83,7 +84,7 @@ class MediaStreamConstraintsUtilAudioTest
media::AudioParameters geometry_parameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16, 1000);
+ media::AudioParameters::kAudioCDSampleRate, 1000);
geometry_parameters.set_mic_positions(kMicPositions);
capabilities_.emplace_back("geometry device", geometry_parameters);
@@ -98,6 +99,17 @@ class MediaStreamConstraintsUtilAudioTest
}
protected:
+ void MakeHardwareEchoCancellerDeviceExperimental() {
+ media::AudioParameters experimental_hw_echo_canceller_parameters(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO,
+ media::AudioParameters::kAudioCDSampleRate, 1000);
+ experimental_hw_echo_canceller_parameters.set_effects(
+ media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
+ capabilities_[1] = {"experimental_hw_echo_canceller_device",
+ experimental_hw_echo_canceller_parameters};
+ }
+
void SetMediaStreamSource(const std::string& source) {}
void ResetFactory() {
@@ -122,18 +134,31 @@ class MediaStreamConstraintsUtilAudioTest
const AudioProcessingProperties& properties,
bool hotword_enabled,
bool disable_local_echo,
- bool render_to_associated_sink) {
+ bool render_to_associated_sink,
+ int effects) {
MediaStreamDevice device;
device.id = "processed_source";
device.type = GetMediaStreamType();
if (render_to_associated_sink)
device.matched_output_device_id = std::string("some_device_id");
+ device.input.set_effects(effects);
return std::make_unique<ProcessedLocalAudioSource>(
-1, device, hotword_enabled, disable_local_echo, properties,
MediaStreamSource::ConstraintsCallback(), &pc_factory_);
}
+ std::unique_ptr<ProcessedLocalAudioSource> GetProcessedLocalAudioSource(
+ const AudioProcessingProperties& properties,
+ bool hotword_enabled,
+ bool disable_local_echo,
+ bool render_to_associated_sink) {
+ return GetProcessedLocalAudioSource(
+ properties, hotword_enabled, disable_local_echo,
+ render_to_associated_sink,
+ media::AudioParameters::PlatformEffectsMask::NO_EFFECTS);
+ }
+
std::unique_ptr<LocalMediaStreamAudioSource> GetLocalMediaStreamAudioSource(
bool enable_hardware_echo_canceller,
bool hotword_enabled,
@@ -154,7 +179,7 @@ class MediaStreamConstraintsUtilAudioTest
AudioCaptureSettings SelectSettings() {
blink::WebMediaConstraints constraints =
constraint_factory_.CreateWebMediaConstraints();
- return SelectSettingsAudioCapture(capabilities_, constraints, false, false);
+ return SelectSettingsAudioCapture(capabilities_, constraints, false);
}
// When googExperimentalEchoCancellation is not explicitly set, its default
@@ -194,7 +219,12 @@ class MediaStreamConstraintsUtilAudioTest
}
if (!Contains(exclude_audio_properties,
&AudioProcessingProperties::disable_hw_echo_cancellation)) {
- EXPECT_FALSE(properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
+ }
+ if (!Contains(exclude_audio_properties,
+ &AudioProcessingProperties::
+ enable_experimental_hw_echo_cancellation)) {
+ EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation);
}
if (!Contains(exclude_audio_properties,
&AudioProcessingProperties::goog_audio_mirroring)) {
@@ -262,7 +292,12 @@ class MediaStreamConstraintsUtilAudioTest
}
if (!Contains(exclude_audio_properties,
&AudioProcessingProperties::disable_hw_echo_cancellation)) {
- EXPECT_FALSE(properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
+ }
+ if (!Contains(exclude_audio_properties,
+ &AudioProcessingProperties::
+ enable_experimental_hw_echo_cancellation)) {
+ EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation);
}
if (!Contains(exclude_audio_properties,
&AudioProcessingProperties::goog_audio_mirroring)) {
@@ -323,8 +358,6 @@ class MediaStreamConstraintsUtilAudioTest
EXPECT_EQ(expected_device.DeviceID(), result.device_id());
EXPECT_EQ(expected_device.Parameters().sample_rate(),
result.device_parameters().sample_rate());
- EXPECT_EQ(expected_device.Parameters().bits_per_sample(),
- result.device_parameters().bits_per_sample());
EXPECT_EQ(expected_device.Parameters().channels(),
result.device_parameters().channels());
EXPECT_EQ(expected_device.Parameters().effects(),
@@ -352,12 +385,95 @@ class MediaStreamConstraintsUtilAudioTest
CheckGeometryDefaults(result);
}
+ // Assumes that echoCancellation is set to true as a basic, exact constraint.
+ void CheckAudioProcessingPropertiesForExactEchoCancellationType(
+ bool request_hw_echo_cancellation,
+ const AudioCaptureSettings& result) {
+ const AudioProcessingProperties& properties =
+ result.audio_processing_properties();
+
+ // With device capture, the echo_cancellation constraint
+ // enables/disables all audio processing by default.
+ // With content capture, the echo_cancellation constraint controls
+ // only the echo_cancellation properties. The other audio processing
+ // properties default to false.
+ const bool enable_sw_audio_processing = IsDeviceCapture();
+
+ if (IsDeviceCapture()) {
+ EXPECT_NE(request_hw_echo_cancellation,
+ properties.enable_sw_echo_cancellation);
+ EXPECT_NE(request_hw_echo_cancellation,
+ properties.disable_hw_echo_cancellation);
+ EXPECT_EQ(request_hw_echo_cancellation,
+ properties.enable_experimental_hw_echo_cancellation);
+ } else {
+ EXPECT_TRUE(properties.enable_sw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
+ EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation);
+ }
+ EXPECT_EQ(enable_sw_audio_processing, properties.goog_auto_gain_control);
+ CheckGoogExperimentalEchoCancellationDefault(properties,
+ enable_sw_audio_processing);
+ EXPECT_EQ(enable_sw_audio_processing,
+ properties.goog_typing_noise_detection);
+ EXPECT_EQ(enable_sw_audio_processing, properties.goog_noise_suppression);
+ EXPECT_EQ(enable_sw_audio_processing,
+ properties.goog_experimental_noise_suppression);
+ EXPECT_EQ(enable_sw_audio_processing, properties.goog_beamforming);
+ EXPECT_EQ(enable_sw_audio_processing, properties.goog_highpass_filter);
+ EXPECT_EQ(enable_sw_audio_processing,
+ properties.goog_experimental_auto_gain_control);
+
+ // The following are not audio processing.
+ EXPECT_FALSE(properties.goog_audio_mirroring);
+ EXPECT_FALSE(result.hotword_enabled());
+ EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
+ result.disable_local_echo());
+ EXPECT_FALSE(result.render_to_associated_sink());
+ if (IsDeviceCapture()) {
+ CheckDevice(request_hw_echo_cancellation ? *hw_echo_canceller_device_
+ : *default_device_,
+ result);
+ } else {
+ EXPECT_TRUE(result.device_id().empty());
+ }
+ }
+
+ void CheckAudioProcessingPropertiesForIdealEchoCancellationType(
+ const AudioCaptureSettings& result) {
+ const AudioProcessingProperties& properties =
+ result.audio_processing_properties();
+
+ EXPECT_FALSE(properties.enable_sw_echo_cancellation);
+ EXPECT_FALSE(properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.enable_experimental_hw_echo_cancellation);
+ EXPECT_TRUE(properties.goog_auto_gain_control);
+ CheckGoogExperimentalEchoCancellationDefault(properties, true);
+ EXPECT_TRUE(properties.goog_typing_noise_detection);
+ EXPECT_TRUE(properties.goog_noise_suppression);
+ EXPECT_TRUE(properties.goog_experimental_noise_suppression);
+ EXPECT_TRUE(properties.goog_beamforming);
+ EXPECT_TRUE(properties.goog_highpass_filter);
+ EXPECT_TRUE(properties.goog_experimental_auto_gain_control);
+
+ // The following are not audio processing.
+ EXPECT_FALSE(properties.goog_audio_mirroring);
+ EXPECT_FALSE(result.hotword_enabled());
+ EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
+ result.disable_local_echo());
+ EXPECT_FALSE(result.render_to_associated_sink());
+ CheckDevice(*hw_echo_canceller_device_, result);
+ }
+
MockConstraintFactory constraint_factory_;
AudioDeviceCaptureCapabilities capabilities_;
const AudioDeviceCaptureCapability* default_device_ = nullptr;
const AudioDeviceCaptureCapability* hw_echo_canceller_device_ = nullptr;
const AudioDeviceCaptureCapability* geometry_device_ = nullptr;
const std::vector<media::Point> kMicPositions = {{8, 8, 8}, {4, 4, 4}};
+ const std::vector<blink::WebString> kEchoCancellationTypeValues = {
+ blink::WebString::FromASCII("browser"),
+ blink::WebString::FromASCII("system")};
private:
// Required for tests involving a MediaStreamAudioSource.
@@ -522,13 +638,18 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidDeviceID) {
auto result = SelectSettings();
EXPECT_TRUE(result.HasValue());
CheckDevice(device, result);
- CheckBoolDefaults(AudioSettingsBoolMembers(),
- {&AudioProcessingProperties::enable_sw_echo_cancellation},
- result);
+ CheckBoolDefaults(
+ AudioSettingsBoolMembers(),
+ {&AudioProcessingProperties::enable_sw_echo_cancellation,
+ &AudioProcessingProperties::disable_hw_echo_cancellation},
+ result);
bool has_hw_echo_cancellation =
device.Parameters().effects() & media::AudioParameters::ECHO_CANCELLER;
EXPECT_EQ(IsDeviceCapture() && !has_hw_echo_cancellation,
result.audio_processing_properties().enable_sw_echo_cancellation);
+ EXPECT_NE(
+ IsDeviceCapture() && has_hw_echo_cancellation,
+ result.audio_processing_properties().disable_hw_echo_cancellation);
if (&device == geometry_device_) {
EXPECT_EQ(kMicPositions,
result.audio_processing_properties().goog_array_geometry);
@@ -565,7 +686,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSw) {
// properties default to false.
bool enable_sw_audio_processing = IsDeviceCapture() ? value : false;
EXPECT_EQ(value, properties.enable_sw_echo_cancellation);
- EXPECT_EQ(!value, properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
EXPECT_EQ(enable_sw_audio_processing,
properties.goog_auto_gain_control);
CheckGoogExperimentalEchoCancellationDefault(
@@ -675,7 +796,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSw) {
// echo_cancellation properties. The other audio processing properties
// use the default values.
EXPECT_EQ(value, properties.enable_sw_echo_cancellation);
- EXPECT_EQ(!value, properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
CheckBoolDefaults(
AudioSettingsBoolMembers(),
{
@@ -693,7 +814,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSw) {
}
}
-// Tests the googEchoCancellation constraint with a device without hardware echo
+// Tests the googEchoCancellation constraint with a device with hardware echo
// cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithHw) {
// With content capture, there is no hardware echo cancellation, so
@@ -738,6 +859,206 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithHw) {
}
}
+// Tests the echoCancellationType constraint without constraining to a device
+// with hardware echo cancellation. Tested as basic exact constraints.
+TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeExact) {
+ for (blink::WebString value : kEchoCancellationTypeValues) {
+ const bool request_hw_echo_cancellation =
+ value == kEchoCancellationTypeValues[1];
+
+ ResetFactory();
+ constraint_factory_.basic().echo_cancellation.SetExact(true);
+ constraint_factory_.basic().echo_cancellation_type.SetExact(value);
+ auto result = SelectSettings();
+ // If content capture and EC type "system", we expect failure.
+ if (!IsDeviceCapture() && request_hw_echo_cancellation) {
+ EXPECT_FALSE(result.HasValue());
+ EXPECT_EQ(result.failed_constraint_name(),
+ constraint_factory_.basic().echo_cancellation_type.GetName());
+ continue;
+ }
+ ASSERT_TRUE(result.HasValue());
+
+ CheckAudioProcessingPropertiesForExactEchoCancellationType(
+ request_hw_echo_cancellation, result);
+ }
+}
+
+// Like the test above, but changes the device with hardware echo cancellation
+// support to only support experimental hardware echo cancellation. It should
+// still be picked if requested.
+TEST_P(MediaStreamConstraintsUtilAudioTest,
+ EchoCancellationTypeExact_Experimental) {
+ if (!IsDeviceCapture())
+ return;
+
+ // Replace the device with one that only supports experimental hardware echo
+ // cancellation.
+ MakeHardwareEchoCancellerDeviceExperimental();
+
+ for (blink::WebString value : kEchoCancellationTypeValues) {
+ ResetFactory();
+ constraint_factory_.basic().echo_cancellation.SetExact(true);
+ constraint_factory_.basic().echo_cancellation_type.SetExact(value);
+ auto result = SelectSettings();
+ ASSERT_TRUE(result.HasValue());
+ const bool request_hw_echo_cancellation =
+ value == kEchoCancellationTypeValues[1];
+ CheckAudioProcessingPropertiesForExactEchoCancellationType(
+ request_hw_echo_cancellation, result);
+ }
+}
+
+// Tests the echoCancellationType constraint without constraining to a device
+// with hardware echo cancellation. Tested as basic ideal constraints.
+TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeIdeal) {
+ // With content capture, there is no hardware echo cancellation, so
+ // nothing to test.
+ if (!IsDeviceCapture())
+ return;
+
+ constraint_factory_.basic().echo_cancellation.SetExact(true);
+ constraint_factory_.basic().echo_cancellation_type.SetIdeal(
+ kEchoCancellationTypeValues[1]);
+ auto result = SelectSettings();
+ ASSERT_TRUE(result.HasValue());
+ CheckAudioProcessingPropertiesForIdealEchoCancellationType(result);
+}
+
+// Like the test above, but only having a device with experimental hardware echo
+// cancellation available.
+TEST_P(MediaStreamConstraintsUtilAudioTest,
+ EchoCancellationTypeIdeal_Experimental) {
+ // With content capture, there is no hardware echo cancellation, so
+ // nothing to test.
+ if (!IsDeviceCapture())
+ return;
+
+ // Replace the device with one that only supports experimental hardware echo
+ // cancellation.
+ MakeHardwareEchoCancellerDeviceExperimental();
+
+ constraint_factory_.basic().echo_cancellation.SetExact(true);
+ constraint_factory_.basic().echo_cancellation_type.SetIdeal(
+ kEchoCancellationTypeValues[1]);
+ auto result = SelectSettings();
+ ASSERT_TRUE(result.HasValue());
+ CheckAudioProcessingPropertiesForIdealEchoCancellationType(result);
+}
+
+// Tests the echoCancellationType constraint with constraining to a device with
+// experimental hardware echo cancellation.
+TEST_P(MediaStreamConstraintsUtilAudioTest,
+ EchoCancellationTypeWithExpHwDeviceConstraint) {
+ // With content capture, there is no system echo cancellation, so
+ // nothing to test.
+ if (!IsDeviceCapture())
+ return;
+
+ MakeHardwareEchoCancellerDeviceExperimental();
+
+ // Include leaving the echoCancellationType constraint unset in the tests.
+ // It should then behave as before the constraint was introduced.
+ auto echo_cancellation_types_and_unset = kEchoCancellationTypeValues;
+ echo_cancellation_types_and_unset.push_back(blink::WebString());
+
+ for (auto set_function : kStringSetFunctions) {
+ for (auto accessor : kFactoryAccessors) {
+ // Ideal advanced is ignored by the SelectSettings algorithm.
+ // Using array elements instead of pointer values due to the comparison
+ // failing on some build configurations.
+ if (set_function == kStringSetFunctions[1] &&
+ accessor == kFactoryAccessors[1]) {
+ continue;
+ }
+ for (blink::WebString ec_type_value : echo_cancellation_types_and_unset) {
+ for (bool ec_value : kBoolValues) {
+ ResetFactory();
+ constraint_factory_.basic().device_id.SetExact(
+ blink::WebString::FromASCII(
+ hw_echo_canceller_device_->DeviceID()));
+ constraint_factory_.basic().echo_cancellation.SetExact(ec_value);
+ if (!ec_type_value.IsNull())
+ ((constraint_factory_.*accessor)().echo_cancellation_type.*
+ set_function)(ec_type_value);
+
+ // We should get a result if echo cancellation is enabled or if it's
+ // disabled and we set the type as an advanced or ideal constraint, or
+ // we've left the constraint unset.
+ auto result = SelectSettings();
+ const bool advanced_constraint = accessor == kFactoryAccessors[1];
+ const bool ideal_constraint = set_function == kStringSetFunctions[1];
+ const bool should_have_result = ec_value || advanced_constraint ||
+ ideal_constraint ||
+ ec_type_value.IsNull();
+ EXPECT_EQ(should_have_result, result.HasValue());
+ if (!should_have_result)
+ continue;
+
+ const AudioProcessingProperties& properties =
+ result.audio_processing_properties();
+
+ // With experimental hardware echo cancellation (echo canceller type
+ // "system"), the echo_cancellation constraint enables/disables all
+ // audio processing by default, software echo cancellation is always
+ // disabled, and experimental hardware echo cancellation is disabled
+ // if the echo_cancellation constraint is false.
+ bool request_hw_echo_cancellation =
+ ec_type_value == kEchoCancellationTypeValues[1];
+
+ if (ec_value) {
+ EXPECT_NE(request_hw_echo_cancellation,
+ properties.enable_sw_echo_cancellation);
+ EXPECT_NE(request_hw_echo_cancellation,
+ properties.disable_hw_echo_cancellation);
+ EXPECT_EQ(request_hw_echo_cancellation,
+ properties.enable_experimental_hw_echo_cancellation);
+ } else {
+ EXPECT_FALSE(properties.enable_sw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
+ EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation);
+ }
+ EXPECT_EQ(ec_value, properties.goog_auto_gain_control);
+ CheckGoogExperimentalEchoCancellationDefault(properties, ec_value);
+ EXPECT_EQ(ec_value, properties.goog_typing_noise_detection);
+ EXPECT_EQ(ec_value, properties.goog_noise_suppression);
+ EXPECT_EQ(ec_value, properties.goog_experimental_noise_suppression);
+ EXPECT_EQ(ec_value, properties.goog_beamforming);
+ EXPECT_EQ(ec_value, properties.goog_highpass_filter);
+ EXPECT_EQ(ec_value, properties.goog_experimental_auto_gain_control);
+
+ // The following are not audio processing.
+ EXPECT_FALSE(properties.goog_audio_mirroring);
+ EXPECT_FALSE(result.hotword_enabled());
+ EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
+ result.disable_local_echo());
+ EXPECT_FALSE(result.render_to_associated_sink());
+ CheckDevice(*hw_echo_canceller_device_, result);
+ }
+ }
+ }
+ }
+}
+
+// Tests the echoCancellationType constraint with constraining to a device
+// without experimental hardware echo cancellation, which should fail.
+TEST_P(MediaStreamConstraintsUtilAudioTest,
+ EchoCancellationTypeWithSwDeviceConstraint) {
+ if (!IsDeviceCapture())
+ return;
+
+ constraint_factory_.basic().device_id.SetExact(
+ blink::WebString::FromASCII(default_device_->DeviceID()));
+ constraint_factory_.basic().echo_cancellation.SetExact(true);
+ constraint_factory_.basic().echo_cancellation_type.SetExact(
+ kEchoCancellationTypeValues[1]);
+
+ auto result = SelectSettings();
+ EXPECT_FALSE(result.HasValue());
+ EXPECT_EQ(result.failed_constraint_name(),
+ constraint_factory_.basic().device_id.GetName());
+}
+
// Test that having differing mandatory values for echoCancellation and
// googEchoCancellation fails.
TEST_P(MediaStreamConstraintsUtilAudioTest, ContradictoryEchoCancellation) {
@@ -1009,8 +1330,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesNoConstraints) {
AudioDeviceCaptureCapabilities capabilities;
auto result = SelectSettingsAudioCapture(
- capabilities, constraint_factory_.CreateWebMediaConstraints(), false,
- false);
+ capabilities, constraint_factory_.CreateWebMediaConstraints(), false);
EXPECT_FALSE(result.HasValue());
EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
}
@@ -1023,8 +1343,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesWithConstraints) {
AudioDeviceCaptureCapabilities capabilities;
constraint_factory_.basic().sample_size.SetExact(16);
auto result = SelectSettingsAudioCapture(
- capabilities, constraint_factory_.CreateWebMediaConstraints(), false,
- false);
+ capabilities, constraint_factory_.CreateWebMediaConstraints(), false);
EXPECT_FALSE(result.HasValue());
EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
}
@@ -1081,6 +1400,33 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithNoAudioProcessing) {
}
}
+// Test functionality to support applyConstraints() for echo cancellation type
+// for tracks attached to sources that have no audio processing.
+TEST_P(MediaStreamConstraintsUtilAudioTest,
+ EchoCancellationTypeWithSourceWithNoAudioProcessing) {
+ for (blink::WebString value : kEchoCancellationTypeValues) {
+ std::unique_ptr<LocalMediaStreamAudioSource> source =
+ GetLocalMediaStreamAudioSource(
+ false /* enable_hardware_echo_canceller */,
+ false /* hotword_enabled */, false /* disable_local_echo */,
+ false /* render_to_associated_sink */);
+
+ // No echo cancellation is available so we expect failure.
+ constraint_factory_.Reset();
+ constraint_factory_.basic().echo_cancellation_type.SetExact(value);
+ auto result = SelectSettingsAudioCapture(
+ source.get(), constraint_factory_.CreateWebMediaConstraints());
+ EXPECT_FALSE(result.HasValue());
+
+ // Setting just ideal values should always succeed.
+ constraint_factory_.Reset();
+ constraint_factory_.basic().echo_cancellation_type.SetIdeal(value);
+ result = SelectSettingsAudioCapture(
+ source.get(), constraint_factory_.CreateWebMediaConstraints());
+ EXPECT_TRUE(result.HasValue());
+ }
+}
+
// Test functionality to support applyConstraints() for tracks attached to
// sources that have audio processing.
TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) {
@@ -1236,6 +1582,58 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) {
}
}
+// Test functionality to support applyConstraints() for echo cancellation type
+// for tracks attached to sources that have audio processing.
+TEST_P(MediaStreamConstraintsUtilAudioTest,
+ EchoCancellationTypeWithSourceWithAudioProcessing) {
+ // Processed audio sources are supported only for device capture.
+ if (!IsDeviceCapture())
+ return;
+
+ for (bool enable_sw_ec : kBoolValues) {
+ for (bool enable_exp_hw_ec : kBoolValues) {
+ // Both sw and hw echo cancellation can't be enabled.
+ if (enable_sw_ec && enable_exp_hw_ec)
+ continue;
+
+ AudioProcessingProperties properties;
+ properties.DisableDefaultProperties();
+ properties.enable_sw_echo_cancellation = enable_sw_ec;
+ properties.enable_experimental_hw_echo_cancellation = enable_exp_hw_ec;
+
+ std::unique_ptr<ProcessedLocalAudioSource> source =
+ GetProcessedLocalAudioSource(
+ properties, false /* hotword_enabled */,
+ false /* disable_local_echo */,
+ false /* render_to_associated_sink */,
+ enable_exp_hw_ec
+ ? media::AudioParameters::PlatformEffectsMask::
+ EXPERIMENTAL_ECHO_CANCELLER
+ : media::AudioParameters::PlatformEffectsMask::NO_EFFECTS);
+
+ for (blink::WebString value : kEchoCancellationTypeValues) {
+ bool system_ec_type = value == kEchoCancellationTypeValues[1];
+
+ constraint_factory_.Reset();
+ constraint_factory_.basic().echo_cancellation_type.SetExact(value);
+ auto result = SelectSettingsAudioCapture(
+ source.get(), constraint_factory_.CreateWebMediaConstraints());
+ const bool should_have_result_value =
+ (enable_sw_ec && !system_ec_type) ||
+ (enable_exp_hw_ec && system_ec_type);
+ EXPECT_EQ(should_have_result_value, result.HasValue());
+
+ // Setting just ideal values should always succeed.
+ constraint_factory_.Reset();
+ constraint_factory_.basic().echo_cancellation_type.SetIdeal(value);
+ result = SelectSettingsAudioCapture(
+ source.get(), constraint_factory_.CreateWebMediaConstraints());
+ EXPECT_TRUE(result.HasValue());
+ }
+ }
+ }
+}
+
TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) {
// The distinction of used and unused sources is relevant only for device
// capture.
@@ -1262,8 +1660,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) {
auto result = SelectSettingsAudioCapture(
capabilities, constraint_factory_.CreateWebMediaConstraints(),
- false /* should_disable_hardware_noise_suppression */,
- false /* should_enable_experimental_hw_echo_cancellation */);
+ false /* should_disable_hardware_noise_suppression */);
EXPECT_TRUE(result.HasValue());
EXPECT_EQ(result.device_id(), kUnusedDeviceID);
EXPECT_FALSE(
@@ -1275,8 +1672,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) {
constraint_factory_.basic().echo_cancellation.SetExact(true);
auto result = SelectSettingsAudioCapture(
capabilities, constraint_factory_.CreateWebMediaConstraints(),
- false /* should_disable_hardware_noise_suppression */,
- false /* should_enable_experimental_hw_echo_cancellation */);
+ false /* should_disable_hardware_noise_suppression */);
EXPECT_TRUE(result.HasValue());
EXPECT_EQ(result.device_id(), processed_source->device().id);
EXPECT_TRUE(
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
index a4642cd38be..1e361d3de3d 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
@@ -47,11 +47,13 @@ blink::WebString ToWebString(media::VideoFacingMode facing_mode) {
struct Candidate {
public:
Candidate(const std::string& device_id,
+ const std::string& group_id,
const media::VideoCaptureFormat& format,
media::VideoFacingMode facing_mode,
media::PowerLineFrequency power_line_frequency,
const base::Optional<bool>& noise_reduction)
: device_id_(device_id),
+ group_id_(group_id),
format_(format),
facing_mode_(facing_mode),
power_line_frequency_(power_line_frequency),
@@ -66,6 +68,9 @@ struct Candidate {
blink::WebString GetDeviceId() const {
return blink::WebString::FromASCII(device_id_.data());
}
+ blink::WebString GetGroupId() const {
+ return blink::WebString::FromASCII(group_id_.data());
+ }
blink::WebString GetVideoKind() const {
return GetVideoKindForFormat(format_);
}
@@ -73,6 +78,7 @@ struct Candidate {
// Accessors.
const media::VideoCaptureFormat& format() const { return format_; }
const std::string& device_id() const { return device_id_; }
+ const std::string& group_id() const { return group_id_; }
media::VideoFacingMode facing_mode() const { return facing_mode_; }
media::PowerLineFrequency power_line_frequency() const {
return power_line_frequency_;
@@ -83,6 +89,7 @@ struct Candidate {
private:
std::string device_id_;
+ std::string group_id_;
media::VideoCaptureFormat format_;
media::VideoFacingMode facing_mode_;
media::PowerLineFrequency power_line_frequency_;
@@ -429,12 +436,16 @@ double NoiseReductionConstraintSourceDistance(
// characteristics that have a fixed value.
double DeviceSourceDistance(
const std::string& device_id,
+ const std::string& group_id,
media::VideoFacingMode facing_mode,
const blink::WebMediaTrackConstraintSet& constraint_set,
const char** failed_constraint_name) {
return StringConstraintSourceDistance(blink::WebString::FromASCII(device_id),
constraint_set.device_id,
failed_constraint_name) +
+ StringConstraintSourceDistance(blink::WebString::FromASCII(group_id),
+ constraint_set.group_id,
+ failed_constraint_name) +
StringConstraintSourceDistance(ToWebString(facing_mode),
constraint_set.facing_mode,
failed_constraint_name);
@@ -483,8 +494,9 @@ double CandidateSourceDistance(
const ConstrainedFormat& constrained_format,
const blink::WebMediaTrackConstraintSet& constraint_set,
const char** failed_constraint_name) {
- return DeviceSourceDistance(candidate.device_id(), candidate.facing_mode(),
- constraint_set, failed_constraint_name) +
+ return DeviceSourceDistance(candidate.device_id(), candidate.group_id(),
+ candidate.facing_mode(), constraint_set,
+ failed_constraint_name) +
FormatSourceDistance(candidate.format(), constrained_format,
constraint_set, failed_constraint_name) +
PowerLineFrequencyConstraintSourceDistance(
@@ -640,6 +652,8 @@ double CandidateFitnessDistance(
constraint_set.aspect_ratio);
fitness += StringConstraintFitnessDistance(candidate.GetDeviceId(),
constraint_set.device_id);
+ fitness += StringConstraintFitnessDistance(candidate.GetGroupId(),
+ constraint_set.group_id);
fitness += StringConstraintFitnessDistance(candidate.GetFacingMode(),
constraint_set.facing_mode);
fitness += StringConstraintFitnessDistance(candidate.GetVideoKind(),
@@ -799,9 +813,9 @@ VideoCaptureSettings SelectSettingsVideoDeviceCapture(
const char* failed_constraint_name = result.failed_constraint_name();
for (auto& device : capabilities.device_capabilities) {
- double basic_device_distance =
- DeviceSourceDistance(device->device_id, device->facing_mode,
- constraints.Basic(), &failed_constraint_name);
+ double basic_device_distance = DeviceSourceDistance(
+ device->device_id, device->group_id, device->facing_mode,
+ constraints.Basic(), &failed_constraint_name);
if (!std::isfinite(basic_device_distance))
continue;
@@ -843,8 +857,9 @@ VideoCaptureSettings SelectSettingsVideoDeviceCapture(
// Custom distances must be added to the candidate distance vector
// after all the spec-mandated values.
DistanceVector advanced_custom_distance_vector;
- Candidate candidate(device->device_id, format, device->facing_mode,
- power_line_frequency, noise_reduction);
+ Candidate candidate(device->device_id, device->group_id, format,
+ device->facing_mode, power_line_frequency,
+ noise_reduction);
DistanceVector candidate_distance_vector;
// First criteria for valid candidates is satisfaction of advanced
// constraint sets.
diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc
index 9ba2bc4fb95..dc0188d8aaa 100644
--- a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/optional.h"
+#include "base/stl_util.h"
#include "content/renderer/media/stream/media_stream_video_source.h"
#include "content/renderer/media/stream/mock_constraint_factory.h"
#include "media/base/limits.h"
@@ -24,6 +25,12 @@ const char kDeviceID3[] = "fake_device_3";
const char kDeviceID4[] = "fake_device_4";
const char kDeviceID5[] = "fake_device_5";
+const char kGroupID1[] = "fake_group_1";
+const char kGroupID2[] = "fake_group_2";
+const char kGroupID3[] = "fake_group_3";
+const char kGroupID4[] = "fake_group_4";
+const char kGroupID5[] = "fake_group_5";
+
void CheckTrackAdapterSettingsEqualsResolution(
const VideoCaptureSettings& settings) {
EXPECT_EQ(settings.Format().frame_size.width(),
@@ -73,6 +80,7 @@ class MediaStreamConstraintsUtilVideoDeviceTest : public testing::Test {
blink::mojom::VideoInputDeviceCapabilitiesPtr device =
blink::mojom::VideoInputDeviceCapabilities::New();
device->device_id = kDeviceID1;
+ device->group_id = kGroupID1;
device->facing_mode = media::MEDIA_VIDEO_FACING_NONE;
device->formats = {
media::VideoCaptureFormat(gfx::Size(200, 200), 40.0f,
@@ -88,6 +96,7 @@ class MediaStreamConstraintsUtilVideoDeviceTest : public testing::Test {
// A low-resolution device.
device = blink::mojom::VideoInputDeviceCapabilities::New();
device->device_id = kDeviceID2;
+ device->group_id = kGroupID2;
device->facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
device->formats = {
media::VideoCaptureFormat(gfx::Size(40, 30), 20.0f,
@@ -108,6 +117,7 @@ class MediaStreamConstraintsUtilVideoDeviceTest : public testing::Test {
// A high-resolution device.
device = blink::mojom::VideoInputDeviceCapabilities::New();
device->device_id = kDeviceID3;
+ device->group_id = kGroupID3;
device->facing_mode = media::MEDIA_VIDEO_FACING_USER;
device->formats = {
media::VideoCaptureFormat(gfx::Size(600, 400), 10.0f,
@@ -139,6 +149,7 @@ class MediaStreamConstraintsUtilVideoDeviceTest : public testing::Test {
// A depth capture device.
device = blink::mojom::VideoInputDeviceCapabilities::New();
device->device_id = kDeviceID4;
+ device->group_id = kGroupID4;
device->facing_mode = media::MEDIA_VIDEO_FACING_ENVIRONMENT;
device->formats = {media::VideoCaptureFormat(gfx::Size(640, 480), 30.0f,
media::PIXEL_FORMAT_Y16)};
@@ -148,6 +159,7 @@ class MediaStreamConstraintsUtilVideoDeviceTest : public testing::Test {
// be supported if no constraints are placed on the frame rate.
device = blink::mojom::VideoInputDeviceCapabilities::New();
device->device_id = kDeviceID5;
+ device->group_id = kGroupID5;
device->facing_mode = media::MEDIA_VIDEO_FACING_NONE;
device->formats = {
media::VideoCaptureFormat(
@@ -227,6 +239,16 @@ TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnDeviceID) {
result.failed_constraint_name());
}
+TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnGroupID) {
+ constraint_factory_.Reset();
+ constraint_factory_.basic().group_id.SetExact(
+ blink::WebString::FromASCII("NONEXISTING"));
+ auto result = SelectSettings();
+ EXPECT_FALSE(result.HasValue());
+ EXPECT_EQ(constraint_factory_.basic().group_id.GetName(),
+ result.failed_constraint_name());
+}
+
TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnFacingMode) {
constraint_factory_.Reset();
// No device in |capabilities_| has facing mode equal to LEFT.
@@ -436,6 +458,37 @@ TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryDeviceID) {
CheckTrackAdapterSettingsEqualsFormat(result);
}
+TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryGroupID) {
+ constraint_factory_.Reset();
+ constraint_factory_.basic().group_id.SetExact(
+ blink::WebString::FromASCII(default_device_->group_id));
+ auto result = SelectSettings();
+ EXPECT_TRUE(result.HasValue());
+ EXPECT_EQ(default_device_->device_id, result.device_id());
+ EXPECT_EQ(*default_closest_format_, result.Format());
+ EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT,
+ result.PowerLineFrequency());
+ CheckTrackAdapterSettingsEqualsFormat(result);
+
+ constraint_factory_.basic().group_id.SetExact(
+ blink::WebString::FromASCII(low_res_device_->group_id));
+ result = SelectSettings();
+ EXPECT_EQ(low_res_device_->device_id, result.device_id());
+ EXPECT_EQ(*low_res_closest_format_, result.Format());
+ EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT,
+ result.PowerLineFrequency());
+ CheckTrackAdapterSettingsEqualsFormat(result);
+
+ constraint_factory_.basic().group_id.SetExact(
+ blink::WebString::FromASCII(high_res_device_->group_id));
+ result = SelectSettings();
+ EXPECT_EQ(high_res_device_->device_id, result.device_id());
+ EXPECT_EQ(*high_res_closest_format_, result.Format());
+ EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT,
+ result.PowerLineFrequency());
+ CheckTrackAdapterSettingsEqualsFormat(result);
+}
+
TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, MandatoryFacingMode) {
constraint_factory_.Reset();
constraint_factory_.basic().facing_mode.SetExact(
@@ -2127,13 +2180,13 @@ TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, AdvancedDeviceID) {
blink::WebString id_vector1[] = {blink::WebString::FromASCII(kDeviceID1),
blink::WebString::FromASCII(kDeviceID2)};
advanced1.device_id.SetExact(
- blink::WebVector<blink::WebString>(id_vector1, arraysize(id_vector1)));
+ blink::WebVector<blink::WebString>(id_vector1, base::size(id_vector1)));
blink::WebString id_vector2[] = {blink::WebString::FromASCII(kDeviceID2),
blink::WebString::FromASCII(kDeviceID3)};
blink::WebMediaTrackConstraintSet& advanced2 =
constraint_factory_.AddAdvanced();
advanced2.device_id.SetExact(
- blink::WebVector<blink::WebString>(id_vector2, arraysize(id_vector2)));
+ blink::WebVector<blink::WebString>(id_vector2, base::size(id_vector2)));
auto result = SelectSettings();
EXPECT_TRUE(result.HasValue());
// kDeviceID2 must be selected because it is the only one that satisfies both
@@ -2142,6 +2195,28 @@ TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, AdvancedDeviceID) {
CheckTrackAdapterSettingsEqualsFormat(result);
}
+TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, AdvancedGroupID) {
+ constraint_factory_.Reset();
+ blink::WebMediaTrackConstraintSet& advanced1 =
+ constraint_factory_.AddAdvanced();
+ blink::WebString id_vector1[] = {blink::WebString::FromASCII(kGroupID1),
+ blink::WebString::FromASCII(kGroupID2)};
+ advanced1.group_id.SetExact(
+ blink::WebVector<blink::WebString>(id_vector1, base::size(id_vector1)));
+ blink::WebString id_vector2[] = {blink::WebString::FromASCII(kGroupID2),
+ blink::WebString::FromASCII(kGroupID3)};
+ blink::WebMediaTrackConstraintSet& advanced2 =
+ constraint_factory_.AddAdvanced();
+ advanced2.group_id.SetExact(
+ blink::WebVector<blink::WebString>(id_vector2, base::size(id_vector2)));
+ auto result = SelectSettings();
+ EXPECT_TRUE(result.HasValue());
+ // The device with group_id kGroupID2 must be selected because it is the only
+ // one that satisfies both advanced sets.
+ EXPECT_EQ(std::string(kDeviceID2), result.device_id());
+ CheckTrackAdapterSettingsEqualsFormat(result);
+}
+
TEST_F(MediaStreamConstraintsUtilVideoDeviceTest,
AdvancedContradictoryDeviceID) {
constraint_factory_.Reset();
@@ -2150,13 +2225,36 @@ TEST_F(MediaStreamConstraintsUtilVideoDeviceTest,
blink::WebString id_vector1[] = {blink::WebString::FromASCII(kDeviceID1),
blink::WebString::FromASCII(kDeviceID2)};
advanced1.device_id.SetExact(
- blink::WebVector<blink::WebString>(id_vector1, arraysize(id_vector1)));
+ blink::WebVector<blink::WebString>(id_vector1, base::size(id_vector1)));
blink::WebString id_vector2[] = {blink::WebString::FromASCII(kDeviceID3),
blink::WebString::FromASCII(kDeviceID4)};
blink::WebMediaTrackConstraintSet& advanced2 =
constraint_factory_.AddAdvanced();
advanced2.device_id.SetExact(
- blink::WebVector<blink::WebString>(id_vector2, arraysize(id_vector2)));
+ blink::WebVector<blink::WebString>(id_vector2, base::size(id_vector2)));
+ auto result = SelectSettings();
+ EXPECT_TRUE(result.HasValue());
+ // The second advanced set must be ignored because it contradicts the first
+ // set.
+ EXPECT_EQ(std::string(kDeviceID1), result.device_id());
+ CheckTrackAdapterSettingsEqualsFormat(result);
+}
+
+TEST_F(MediaStreamConstraintsUtilVideoDeviceTest,
+ AdvancedContradictoryGroupID) {
+ constraint_factory_.Reset();
+ blink::WebMediaTrackConstraintSet& advanced1 =
+ constraint_factory_.AddAdvanced();
+ blink::WebString id_vector1[] = {blink::WebString::FromASCII(kGroupID1),
+ blink::WebString::FromASCII(kGroupID2)};
+ advanced1.group_id.SetExact(
+ blink::WebVector<blink::WebString>(id_vector1, base::size(id_vector1)));
+ blink::WebString id_vector2[] = {blink::WebString::FromASCII(kGroupID3),
+ blink::WebString::FromASCII(kGroupID4)};
+ blink::WebMediaTrackConstraintSet& advanced2 =
+ constraint_factory_.AddAdvanced();
+ advanced2.group_id.SetExact(
+ blink::WebVector<blink::WebString>(id_vector2, base::size(id_vector2)));
auto result = SelectSettings();
EXPECT_TRUE(result.HasValue());
// The second advanced set must be ignored because it contradicts the first
diff --git a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
index 1034558ddde..4e60ebaab8a 100644
--- a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
+++ b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc
@@ -74,8 +74,7 @@ scoped_refptr<MediaStreamAudioRenderer>
MediaStreamRendererFactoryImpl::GetAudioRenderer(
const blink::WebMediaStream& web_stream,
int render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) {
DCHECK(!web_stream.IsNull());
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
web_stream.AudioTracks(audio_tracks);
@@ -112,8 +111,7 @@ MediaStreamRendererFactoryImpl::GetAudioRenderer(
<< (audio_track->is_local_track() ? "local" : "remote")
<< " track.";
return new TrackAudioRenderer(audio_tracks[0], render_frame_id,
- 0 /* no session_id */, device_id,
- security_origin);
+ 0 /* no session_id */, device_id);
}
// This is a remote WebRTC media stream.
@@ -130,7 +128,7 @@ MediaStreamRendererFactoryImpl::GetAudioRenderer(
renderer = new WebRtcAudioRenderer(
GetPeerConnectionDependencyFactory()->GetWebRtcSignalingThread(),
web_stream, render_frame_id, GetSessionIdForWebRtcAudioRenderer(),
- device_id, security_origin);
+ device_id);
if (!audio_device->SetAudioRenderer(renderer.get())) {
WebRtcLogMessage("Error: SetAudioRenderer failed for remote track.");
diff --git a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h
index 9baf79a6e70..8233c308a6c 100644
--- a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h
+++ b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_RENDERER_FACTORY_IMPL_H_
#define CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_RENDERER_FACTORY_IMPL_H_
+#include <string>
+
#include "base/macros.h"
#include "content/public/renderer/media_stream_renderer_factory.h"
@@ -25,8 +27,7 @@ class MediaStreamRendererFactoryImpl : public MediaStreamRendererFactory {
scoped_refptr<MediaStreamAudioRenderer> GetAudioRenderer(
const blink::WebMediaStream& web_stream,
int render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) override;
+ const std::string& device_id) override;
private:
DISALLOW_COPY_AND_ASSIGN(MediaStreamRendererFactoryImpl);
@@ -34,4 +35,4 @@ class MediaStreamRendererFactoryImpl : public MediaStreamRendererFactory {
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_RENDERER_FACTORY_IMPL_H_
+#endif // CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_RENDERER_FACTORY_IMPL_H_
diff --git a/chromium/content/renderer/media/stream/media_stream_video_capturer_source_unittest.cc b/chromium/content/renderer/media/stream/media_stream_video_capturer_source_unittest.cc
index 715cda93b18..ea5e45fdbb7 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_capturer_source_unittest.cc
+++ b/chromium/content/renderer/media/stream/media_stream_video_capturer_source_unittest.cc
@@ -47,7 +47,7 @@ class MockVideoCapturerSource : public media::VideoCapturerSource {
MockStartCapture(params, new_frame_callback, running_callback);
SetRunning(true);
}
- void StopCapture() {
+ void StopCapture() override {
MockStopCapture();
SetRunning(false);
}
diff --git a/chromium/content/renderer/media/stream/media_stream_video_source.h b/chromium/content/renderer/media/stream/media_stream_video_source.h
index f29a1b1528f..4ef327f92f5 100644
--- a/chromium/content/renderer/media/stream/media_stream_video_source.h
+++ b/chromium/content/renderer/media/stream/media_stream_video_source.h
@@ -11,7 +11,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "content/common/content_export.h"
@@ -24,6 +23,10 @@
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace content {
class MediaStreamVideoTrack;
diff --git a/chromium/content/renderer/media/stream/mock_media_stream_registry.cc b/chromium/content/renderer/media/stream/mock_media_stream_registry.cc
index a3c084e5b99..88f1bc85cb2 100644
--- a/chromium/content/renderer/media/stream/mock_media_stream_registry.cc
+++ b/chromium/content/renderer/media/stream/mock_media_stream_registry.cc
@@ -28,7 +28,7 @@ class MockCDQualityAudioSource : public MediaStreamAudioSource {
SetFormat(media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16,
+ media::AudioParameters::kAudioCDSampleRate,
media::AudioParameters::kAudioCDSampleRate / 100));
SetDevice(MediaStreamDevice(
MEDIA_DEVICE_AUDIO_CAPTURE, "mock_audio_device_id", "Mock audio device",
diff --git a/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc b/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc
index 4450c05937b..1a4c168c461 100644
--- a/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc
+++ b/chromium/content/renderer/media/stream/mock_media_stream_video_source.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
+#include "base/single_thread_task_runner.h"
namespace content {
diff --git a/chromium/content/renderer/media/stream/mock_media_stream_video_source.h b/chromium/content/renderer/media/stream/mock_media_stream_video_source.h
index e495995048d..23076fb7aa2 100644
--- a/chromium/content/renderer/media/stream/mock_media_stream_video_source.h
+++ b/chromium/content/renderer/media/stream/mock_media_stream_video_source.h
@@ -18,7 +18,7 @@ class MockMediaStreamVideoSource : public MediaStreamVideoSource {
explicit MockMediaStreamVideoSource(bool respond_to_request_refresh_frame);
MockMediaStreamVideoSource(const media::VideoCaptureFormat& format,
bool respond_to_request_refresh_frame);
- virtual ~MockMediaStreamVideoSource();
+ ~MockMediaStreamVideoSource() override;
MOCK_METHOD1(DoSetMutedState, void(bool muted_state));
diff --git a/chromium/content/renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h b/chromium/content/renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h
index 4b57a260032..3fc8bf8cae7 100644
--- a/chromium/content/renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h
+++ b/chromium/content/renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h
@@ -20,7 +20,7 @@ class MockMojoMediaStreamDispatcherHost
: public mojom::MediaStreamDispatcherHost {
public:
MockMojoMediaStreamDispatcherHost();
- ~MockMojoMediaStreamDispatcherHost();
+ ~MockMojoMediaStreamDispatcherHost() override;
mojom::MediaStreamDispatcherHostPtr CreateInterfacePtrAndBind();
diff --git a/chromium/content/renderer/media/stream/processed_local_audio_source.cc b/chromium/content/renderer/media/stream/processed_local_audio_source.cc
index 0777780af3e..9a13797562c 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source.cc
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source.cc
@@ -46,7 +46,8 @@ ProcessedLocalAudioSource::ProcessedLocalAudioSource(
audio_processing_properties_(audio_processing_properties),
started_callback_(started_callback),
volume_(0),
- allow_invalid_render_frame_id_for_testing_(false) {
+ allow_invalid_render_frame_id_for_testing_(false),
+ weak_factory_(this) {
DCHECK(pc_factory_);
DVLOG(1) << "ProcessedLocalAudioSource::ProcessedLocalAudioSource()";
SetDevice(device);
@@ -71,13 +72,10 @@ void* ProcessedLocalAudioSource::GetClassIdentifier() const {
}
bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
- {
- base::AutoLock auto_lock(source_lock_);
- if (source_)
- return true;
- }
+ if (source_)
+ return true;
// Sanity-check that the consuming RenderFrame still exists. This is required
// to initialize the audio source.
@@ -188,7 +186,6 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
// ProcessedLocalAudioSource to the processor's output format.
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
channel_layout, device().input.sample_rate(),
- 16,
GetBufferSize(device().input.sample_rate()));
params.set_effects(device().input.effects());
DCHECK(params.IsValid());
@@ -201,14 +198,12 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
<< params.AsHumanReadableString() << "} and output parameters={"
<< GetAudioParameters().AsHumanReadableString() << '}';
scoped_refptr<media::AudioCapturerSource> new_source =
- AudioDeviceFactory::NewAudioCapturerSource(consumer_render_frame_id_);
- new_source->Initialize(params, this, device().session_id);
+ AudioDeviceFactory::NewAudioCapturerSource(consumer_render_frame_id_,
+ device().session_id);
+ new_source->Initialize(params, this);
// We need to set the AGC control before starting the stream.
new_source->SetAutomaticGainControl(true);
- {
- base::AutoLock auto_lock(source_lock_);
- source_ = std::move(new_source);
- }
+ source_ = std::move(new_source);
source_->Start();
// Register this source with the WebRtcAudioDeviceImpl.
@@ -218,15 +213,12 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
}
void ProcessedLocalAudioSource::EnsureSourceIsStopped() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- scoped_refptr<media::AudioCapturerSource> source_to_stop;
- {
- base::AutoLock auto_lock(source_lock_);
- if (!source_)
- return;
- source_to_stop = std::move(source_);
- }
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+
+ if (!source_)
+ return;
+
+ scoped_refptr<media::AudioCapturerSource> source_to_stop(std::move(source_));
if (WebRtcAudioDeviceImpl* rtc_audio_device =
pc_factory_->GetWebRtcAudioDevice()) {
@@ -245,21 +237,9 @@ void ProcessedLocalAudioSource::EnsureSourceIsStopped() {
void ProcessedLocalAudioSource::SetVolume(int volume) {
DVLOG(1) << "ProcessedLocalAudioSource::SetVolume()";
DCHECK_LE(volume, MaxVolume());
-
const double normalized_volume = static_cast<double>(volume) / MaxVolume();
-
- // Hold a strong reference to |source_| while its SetVolume() method is
- // called. This will prevent the object from being destroyed on another thread
- // in the meantime. It's possible the |source_| will be stopped on another
- // thread while calling SetVolume() here; but this is safe: The operation will
- // simply be ignored.
- scoped_refptr<media::AudioCapturerSource> maybe_source;
- {
- base::AutoLock auto_lock(source_lock_);
- maybe_source = source_;
- }
- if (maybe_source)
- maybe_source->SetVolume(normalized_volume);
+ if (source_)
+ source_->SetVolume(normalized_volume);
}
int ProcessedLocalAudioSource::Volume() const {
@@ -345,8 +325,9 @@ void ProcessedLocalAudioSource::Capture(const media::AudioBus* audio_bus,
reference_clock_snapshot - processed_data_audio_delay);
if (new_volume) {
- SetVolume(new_volume);
-
+ GetTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&ProcessedLocalAudioSource::SetVolume,
+ weak_factory_.GetWeakPtr(), new_volume));
// Update the |current_volume| to avoid passing the old volume to AGC.
current_volume = new_volume;
}
@@ -367,8 +348,15 @@ media::AudioParameters ProcessedLocalAudioSource::GetInputFormat() const {
: media::AudioParameters();
}
+void ProcessedLocalAudioSource::SetOutputDeviceForAec(
+ const std::string& output_device_id) {
+ DVLOG(1) << "ProcessedLocalAudioSource::SetOutputDeviceForAec()";
+ if (source_)
+ source_->SetOutputDeviceForAec(output_device_id);
+}
+
int ProcessedLocalAudioSource::GetBufferSize(int sample_rate) const {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread());
#if defined(OS_ANDROID)
// TODO(henrika): Re-evaluate whether to use same logic as other platforms.
// http://crbug.com/638081
diff --git a/chromium/content/renderer/media/stream/processed_local_audio_source.h b/chromium/content/renderer/media/stream/processed_local_audio_source.h
index 149c1d7de6b..bb62af4dd71 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source.h
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source.h
@@ -83,6 +83,8 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
// remove it.
media::AudioParameters GetInputFormat() const;
+ void SetOutputDeviceForAec(const std::string& output_device_id);
+
protected:
// MediaStreamAudioSource implementation.
void* GetClassIdentifier() const final;
@@ -110,10 +112,6 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
PeerConnectionDependencyFactory* const pc_factory_;
- // In debug builds, check that all methods that could cause object graph
- // or data flow changes are being called on the main thread.
- base::ThreadChecker thread_checker_;
-
AudioProcessingProperties audio_processing_properties_;
// Callback that's called when the audio source has been initialized.
@@ -126,9 +124,6 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
// The device created by the AudioDeviceFactory in EnsureSourceIsStarted().
scoped_refptr<media::AudioCapturerSource> source_;
- // Lock used to ensure thread-safe access to |source_| by SetVolume().
- mutable base::Lock source_lock_;
-
// Stores latest microphone volume received in a CaptureData() callback.
// Range is [0, 255].
base::subtle::Atomic32 volume_;
@@ -138,6 +133,9 @@ class CONTENT_EXPORT ProcessedLocalAudioSource final
bool allow_invalid_render_frame_id_for_testing_;
+ // Provides weak pointers for tasks posted by this instance.
+ base::WeakPtrFactory<ProcessedLocalAudioSource> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ProcessedLocalAudioSource);
};
diff --git a/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc b/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc
index c14fde2937c..19df6b92642 100644
--- a/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc
+++ b/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc
@@ -168,7 +168,7 @@ TEST_F(ProcessedLocalAudioSourceTest, VerifyAudioFlowWithoutAudioProcessing) {
// Connect the track, and expect the MockCapturerSource to be initialized and
// started by ProcessedLocalAudioSource.
EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(),
- Initialize(_, capture_source_callback(), -1))
+ Initialize(_, capture_source_callback()))
.WillOnce(WithArg<0>(Invoke(this, &ThisTest::CheckSourceFormatMatches)));
EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(),
SetAutomaticGainControl(true));
diff --git a/chromium/content/renderer/media/stream/secure_display_link_tracker.h b/chromium/content/renderer/media/stream/secure_display_link_tracker.h
index 9a3ab5a0ede..6f178c250db 100644
--- a/chromium/content/renderer/media/stream/secure_display_link_tracker.h
+++ b/chromium/content/renderer/media/stream/secure_display_link_tracker.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_STREAM_SECURE_DISPLAY_LINK_TRACKER_H_
#define CONTENT_RENDERER_MEDIA_STREAM_SECURE_DISPLAY_LINK_TRACKER_H_
+#include <algorithm>
#include <vector>
// Tracks all connected links (video sinks / tracks), and reports if they are
diff --git a/chromium/content/renderer/media/stream/track_audio_renderer.cc b/chromium/content/renderer/media/stream/track_audio_renderer.cc
index bab5cdd2a07..826d403c76d 100644
--- a/chromium/content/renderer/media/stream/track_audio_renderer.cc
+++ b/chromium/content/renderer/media/stream/track_audio_renderer.cc
@@ -74,7 +74,6 @@ void TrackAudioRenderer::OnRenderError() {
// content::MediaStreamAudioSink implementation
void TrackAudioRenderer::OnData(const media::AudioBus& audio_bus,
base::TimeTicks reference_time) {
- DCHECK(audio_thread_checker_.CalledOnValidThread());
DCHECK(!reference_time.is_null());
TRACE_EVENT1("audio", "TrackAudioRenderer::OnData", "reference time (ms)",
@@ -98,10 +97,6 @@ void TrackAudioRenderer::OnData(const media::AudioBus& audio_bus,
void TrackAudioRenderer::OnSetFormat(const media::AudioParameters& params) {
DVLOG(1) << "TrackAudioRenderer::OnSetFormat()";
- // If the source is restarted, we might have changed to another capture
- // thread.
- audio_thread_checker_.DetachFromThread();
- DCHECK(audio_thread_checker_.CalledOnValidThread());
// If the parameters changed, the audio in the AudioShifter is invalid and
// should be dropped.
@@ -125,8 +120,7 @@ TrackAudioRenderer::TrackAudioRenderer(
const blink::WebMediaStreamTrack& audio_track,
int playout_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin)
+ const std::string& device_id)
: audio_track_(audio_track),
playout_render_frame_id_(playout_render_frame_id),
session_id_(session_id),
@@ -134,7 +128,6 @@ TrackAudioRenderer::TrackAudioRenderer(
num_samples_rendered_(0),
playing_(false),
output_device_id_(device_id),
- security_origin_(security_origin),
volume_(0.0),
sink_started_(false) {
DCHECK(MediaStreamAudioTrack::From(audio_track_));
@@ -158,7 +151,7 @@ void TrackAudioRenderer::Start() {
DCHECK(!sink_);
sink_ = AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
- session_id_, output_device_id_, security_origin_);
+ session_id_, output_device_id_);
base::AutoLock auto_lock(thread_lock_);
prior_elapsed_render_time_ = base::TimeDelta();
@@ -248,7 +241,6 @@ bool TrackAudioRenderer::IsLocalRenderer() const {
void TrackAudioRenderer::SwitchOutputDevice(
const std::string& device_id,
- const url::Origin& security_origin,
const media::OutputDeviceStatusCB& callback) {
DVLOG(1) << "TrackAudioRenderer::SwitchOutputDevice()";
DCHECK(task_runner_->BelongsToCurrentThread());
@@ -261,7 +253,7 @@ void TrackAudioRenderer::SwitchOutputDevice(
scoped_refptr<media::AudioRendererSink> new_sink =
AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
- session_id_, device_id, security_origin);
+ session_id_, device_id);
media::OutputDeviceStatus new_sink_status =
new_sink->GetOutputDeviceInfo().device_status();
@@ -272,7 +264,6 @@ void TrackAudioRenderer::SwitchOutputDevice(
}
output_device_id_ = device_id;
- security_origin_ = security_origin;
bool was_sink_started = sink_started_;
if (sink_)
@@ -311,7 +302,7 @@ void TrackAudioRenderer::MaybeStartSink() {
const media::AudioParameters& hardware_params = device_info.output_params();
media::AudioParameters sink_params(
hardware_params.format(), source_params_.channel_layout(),
- source_params_.sample_rate(), source_params_.bits_per_sample(),
+ source_params_.sample_rate(),
media::AudioLatency::GetRtcBufferSize(
source_params_.sample_rate(), hardware_params.frames_per_buffer()));
DVLOG(1) << ("TrackAudioRenderer::MaybeStartSink() -- Starting sink. "
@@ -353,7 +344,7 @@ void TrackAudioRenderer::ReconfigureSink(const media::AudioParameters& params) {
sink_started_ = false;
sink_ = AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
- session_id_, output_device_id_, security_origin_);
+ session_id_, output_device_id_);
MaybeStartSink();
}
diff --git a/chromium/content/renderer/media/stream/track_audio_renderer.h b/chromium/content/renderer/media/stream/track_audio_renderer.h
index 358b43e97e9..7475f5c1c14 100644
--- a/chromium/content/renderer/media/stream/track_audio_renderer.h
+++ b/chromium/content/renderer/media/stream/track_audio_renderer.h
@@ -16,7 +16,6 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/public/renderer/media_stream_audio_renderer.h"
#include "content/public/renderer/media_stream_audio_sink.h"
@@ -65,8 +64,7 @@ class CONTENT_EXPORT TrackAudioRenderer
TrackAudioRenderer(const blink::WebMediaStreamTrack& audio_track,
int playout_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
// MediaStreamAudioRenderer implementation.
// Called on the main thread.
@@ -79,7 +77,6 @@ class CONTENT_EXPORT TrackAudioRenderer
base::TimeDelta GetCurrentRenderTime() const override;
bool IsLocalRenderer() const override;
void SwitchOutputDevice(const std::string& device_id,
- const url::Origin& security_origin,
const media::OutputDeviceStatusCB& callback) override;
protected:
@@ -164,7 +161,6 @@ class CONTENT_EXPORT TrackAudioRenderer
// The preferred device id of the output device or empty for the default
// output device.
std::string output_device_id_;
- url::Origin security_origin_;
// Cache value for the volume. Whenever |sink_| is re-created, its volume
// should be set to this.
@@ -173,9 +169,6 @@ class CONTENT_EXPORT TrackAudioRenderer
// Flag to indicate whether |sink_| has been started yet.
bool sink_started_;
- // Used to DCHECK that some methods are called on the audio thread.
- base::ThreadChecker audio_thread_checker_;
-
DISALLOW_COPY_AND_ASSIGN(TrackAudioRenderer);
};
diff --git a/chromium/content/renderer/media/stream/user_media_client_impl.h b/chromium/content/renderer/media/stream/user_media_client_impl.h
index e7b8c3b30fc..b87767c1b3b 100644
--- a/chromium/content/renderer/media/stream/user_media_client_impl.h
+++ b/chromium/content/renderer/media/stream/user_media_client_impl.h
@@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/common/media/media_devices.h"
#include "content/public/renderer/render_frame_observer.h"
diff --git a/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc b/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc
index c0b5acbd3ec..0415951c66b 100644
--- a/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc
+++ b/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc
@@ -860,7 +860,7 @@ TEST_F(UserMediaClientImplTest, DefaultConstraintsPropagate) {
const AudioProcessingProperties& properties =
audio_capture_settings.audio_processing_properties();
EXPECT_TRUE(properties.enable_sw_echo_cancellation);
- EXPECT_FALSE(properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
EXPECT_FALSE(properties.goog_audio_mirroring);
EXPECT_TRUE(properties.goog_auto_gain_control);
// The default value for goog_experimental_echo_cancellation is platform
@@ -929,7 +929,7 @@ TEST_F(UserMediaClientImplTest, DefaultTabCapturePropagate) {
const AudioProcessingProperties& properties =
audio_capture_settings.audio_processing_properties();
EXPECT_FALSE(properties.enable_sw_echo_cancellation);
- EXPECT_FALSE(properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
EXPECT_FALSE(properties.goog_audio_mirroring);
EXPECT_FALSE(properties.goog_auto_gain_control);
EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
@@ -992,7 +992,7 @@ TEST_F(UserMediaClientImplTest, DefaultDesktopCapturePropagate) {
const AudioProcessingProperties& properties =
audio_capture_settings.audio_processing_properties();
EXPECT_FALSE(properties.enable_sw_echo_cancellation);
- EXPECT_FALSE(properties.disable_hw_echo_cancellation);
+ EXPECT_TRUE(properties.disable_hw_echo_cancellation);
EXPECT_FALSE(properties.goog_audio_mirroring);
EXPECT_FALSE(properties.goog_auto_gain_control);
EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
diff --git a/chromium/content/renderer/media/stream/user_media_processor.cc b/chromium/content/renderer/media/stream/user_media_processor.cc
index 2a5c2ad894a..cba8d68a14e 100644
--- a/chromium/content/renderer/media/stream/user_media_processor.cc
+++ b/chromium/content/renderer/media/stream/user_media_processor.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <algorithm>
+#include <map>
#include <utility>
#include "base/location.h"
@@ -100,13 +101,8 @@ bool IsValidVideoContentSource(const std::string& source) {
void SurfaceAudioProcessingSettings(blink::WebMediaStreamSource* source) {
MediaStreamAudioSource* source_impl =
static_cast<MediaStreamAudioSource*>(source->GetExtraData());
- media::AudioParameters params = source_impl->GetAudioParameters();
- bool hw_echo_cancellation =
- params.IsValid() &&
- (params.effects() & media::AudioParameters::ECHO_CANCELLER);
-
bool sw_echo_cancellation = false, auto_gain_control = false,
- noise_supression = false;
+ noise_supression = false, hw_echo_cancellation = false;
if (ProcessedLocalAudioSource* processed_source =
ProcessedLocalAudioSource::From(source_impl)) {
AudioProcessingProperties properties =
@@ -114,10 +110,28 @@ void SurfaceAudioProcessingSettings(blink::WebMediaStreamSource* source) {
sw_echo_cancellation = properties.enable_sw_echo_cancellation;
auto_gain_control = properties.goog_auto_gain_control;
noise_supression = properties.goog_noise_suppression;
+ // The ECHO_CANCELLER flag will be set if either:
+ // - The device advertises the ECHO_CANCELLER flag and
+ // disable_hw_echo_cancellation is false; or if
+ // - The device advertises the EXPERIMENTAL_ECHO_CANCELLER flag and
+ // enable_experimental_hw_echo_cancellation is true.
+ // See: ProcessedLocalAudioSource::EnsureSourceIsStarted().
+ const media::AudioParameters& params = processed_source->device().input;
+ hw_echo_cancellation =
+ params.IsValid() &&
+ (params.effects() & media::AudioParameters::ECHO_CANCELLER);
}
- source->SetAudioProcessingProperties(
- hw_echo_cancellation || sw_echo_cancellation, auto_gain_control,
- noise_supression);
+
+ using blink::WebMediaStreamSource;
+ const WebMediaStreamSource::EchoCancellationMode echo_cancellation_mode =
+ hw_echo_cancellation
+ ? WebMediaStreamSource::EchoCancellationMode::kHardware
+ : sw_echo_cancellation
+ ? WebMediaStreamSource::EchoCancellationMode::kSoftware
+ : WebMediaStreamSource::EchoCancellationMode::kDisabled;
+
+ source->SetAudioProcessingProperties(echo_cancellation_mode,
+ auto_gain_control, noise_supression);
}
} // namespace
@@ -466,8 +480,7 @@ void UserMediaProcessor::SelectAudioSettings(
DCHECK(current_request_info_->stream_controls()->audio.requested);
auto settings = SelectSettingsAudioCapture(
capabilities, web_request.AudioConstraints(),
- web_request.ShouldDisableHardwareNoiseSuppression(),
- web_request.ShouldEnableExperimentalHardwareEchoCancellation());
+ web_request.ShouldDisableHardwareNoiseSuppression());
if (!settings.HasValue()) {
blink::WebString failed_constraint_name =
blink::WebString::FromASCII(settings.failed_constraint_name());
@@ -634,9 +647,6 @@ void UserMediaProcessor::OnStreamGenerated(
return;
}
- media_stream_device_observer_->AddStream(label, audio_devices, video_devices,
- weak_factory_.GetWeakPtr());
-
current_request_info_->set_state(RequestInfo::State::GENERATED);
for (const auto* devices : {&audio_devices, &video_devices}) {
@@ -811,7 +821,8 @@ blink::WebMediaStreamSource UserMediaProcessor::InitializeVideoSourceObject(
source.SetCapabilities(ComputeCapabilitiesForVideoSource(
blink::WebString::FromUTF8(device.id),
*current_request_info_->GetNativeVideoFormats(device.id),
- device.video_facing, current_request_info_->is_video_device_capture()));
+ device.video_facing, current_request_info_->is_video_device_capture(),
+ device.group_id));
local_sources_.push_back(source);
}
return source;
@@ -853,9 +864,20 @@ blink::WebMediaStreamSource UserMediaProcessor::InitializeAudioSourceObject(
blink::WebMediaStreamSource::Capabilities capabilities;
capabilities.echo_cancellation = {true, false};
+ capabilities.echo_cancellation_type.reserve(2);
+ capabilities.echo_cancellation_type.emplace_back(
+ blink::WebString::FromASCII(blink::kEchoCancellationTypeBrowser));
+ if (device.input.effects() &
+ (media::AudioParameters::ECHO_CANCELLER |
+ media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER)) {
+ capabilities.echo_cancellation_type.emplace_back(
+ blink::WebString::FromASCII(blink::kEchoCancellationTypeSystem));
+ }
capabilities.auto_gain_control = {true, false};
capabilities.noise_suppression = {true, false};
capabilities.device_id = blink::WebString::FromUTF8(device.id);
+ if (device.group_id)
+ capabilities.group_id = blink::WebString::FromUTF8(*device.group_id);
source.SetExtraData(audio_source); // Takes ownership.
source.SetCapabilities(capabilities);
@@ -905,6 +927,10 @@ MediaStreamVideoSource* UserMediaProcessor::CreateVideoSource(
void UserMediaProcessor::StartTracks(const std::string& label) {
DCHECK(!current_request_info_->web_request().IsNull());
+ media_stream_device_observer_->AddStream(
+ label, current_request_info_->audio_devices(),
+ current_request_info_->video_devices(), weak_factory_.GetWeakPtr());
+
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
current_request_info_->audio_devices().size());
CreateAudioTracks(current_request_info_->audio_devices(), &audio_tracks);
@@ -1158,6 +1184,8 @@ blink::WebMediaStreamSource UserMediaProcessor::FindOrInitializeSourceObject(
source.Initialize(blink::WebString::FromUTF8(device.id), type,
blink::WebString::FromUTF8(device.name),
false /* remote */);
+ if (device.group_id)
+ source.SetGroupId(blink::WebString::FromUTF8(*device.group_id));
DVLOG(1) << "Initialize source object :"
<< "id = " << source.Id().Utf8()
diff --git a/chromium/content/renderer/media/stream/webaudio_media_stream_source.cc b/chromium/content/renderer/media/stream/webaudio_media_stream_source.cc
index 30ef89959fe..e6a32f6a0d2 100644
--- a/chromium/content/renderer/media/stream/webaudio_media_stream_source.cc
+++ b/chromium/content/renderer/media/stream/webaudio_media_stream_source.cc
@@ -45,7 +45,7 @@ void WebAudioMediaStreamSource::SetFormat(size_t number_of_channels,
// I did not want to change behavior. http://crbug.com/577874
fifo_.Reset(sample_rate / 100);
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- channel_layout, sample_rate, 16,
+ channel_layout, sample_rate,
fifo_.frames_per_buffer());
// Take care of the discrete channel layout case.
params.set_channels_for_discrete(number_of_channels);
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
index 0ded108e9bb..d8483027e0a 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -12,11 +12,9 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "cc/blink/web_layer_impl.h"
#include "cc/layers/video_frame_provider_client_impl.h"
#include "cc/layers/video_layer.h"
#include "content/child/child_process.h"
-#include "content/public/common/content_features.h"
#include "content/public/renderer/media_stream_audio_renderer.h"
#include "content/public/renderer/media_stream_renderer_factory.h"
#include "content/public/renderer/media_stream_video_renderer.h"
@@ -43,12 +41,19 @@
#include "third_party/blink/public/web/web_local_frame.h"
namespace {
+
enum class RendererReloadAction {
KEEP_RENDERER,
REMOVE_RENDERER,
NEW_RENDERER
};
+bool IsPlayableTrack(const blink::WebMediaStreamTrack& track) {
+ return !track.IsNull() && !track.Source().IsNull() &&
+ track.Source().GetReadyState() !=
+ blink::WebMediaStreamSource::kReadyStateEnded;
+}
+
} // namespace
namespace content {
@@ -86,10 +91,8 @@ class WebMediaPlayerMS::FrameDeliverer {
weak_factory_(this) {
io_thread_checker_.DetachFromThread();
- if (gpu_factories &&
- gpu_factories->ShouldUseGpuMemoryBuffersForVideoFrames() &&
- base::FeatureList::IsEnabled(
- features::kWebRtcUseGpuMemoryBufferVideoFrames)) {
+ if (gpu_factories && gpu_factories->ShouldUseGpuMemoryBuffersForVideoFrames(
+ true /* for_media_stream */)) {
gpu_memory_buffer_pool_.reset(new media::GpuMemoryBufferVideoFramePool(
media_task_runner, worker_task_runner, gpu_factories));
}
@@ -259,8 +262,7 @@ WebMediaPlayerMS::WebMediaPlayerMS(
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
scoped_refptr<base::TaskRunner> worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories,
- const blink::WebString& sink_id,
- const blink::WebSecurityOrigin& security_origin)
+ const blink::WebString& sink_id)
: frame_(frame),
network_state_(WebMediaPlayer::kNetworkStateEmpty),
ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
@@ -278,9 +280,6 @@ WebMediaPlayerMS::WebMediaPlayerMS(
worker_task_runner_(worker_task_runner),
gpu_factories_(gpu_factories),
initial_audio_output_device_id_(sink_id.Utf8()),
- initial_security_origin_(security_origin.IsNull()
- ? url::Origin()
- : url::Origin(security_origin)),
volume_(1.0),
volume_multiplier_(1.0),
should_play_upon_shown_(false) {
@@ -301,9 +300,9 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
web_stream_.RemoveObserver(this);
// Destruct compositor resources in the proper order.
- get_client()->SetWebLayer(nullptr);
- if (video_weblayer_)
- static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider();
+ get_client()->SetCcLayer(nullptr);
+ if (video_layer_)
+ video_layer_->StopUsingProvider();
if (frame_deliverer_)
io_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release());
@@ -370,8 +369,7 @@ void WebMediaPlayerMS::Load(LoadType load_type,
}
audio_renderer_ = renderer_factory_->GetAudioRenderer(
- web_stream_, routing_id, initial_audio_output_device_id_,
- initial_security_origin_);
+ web_stream_, routing_id, initial_audio_output_device_id_);
if (!audio_renderer_)
WebRtcLogMessage("Warning: Failed to instantiate audio renderer.");
@@ -425,6 +423,26 @@ void WebMediaPlayerMS::TrackRemoved(const blink::WebMediaStreamTrack& track) {
Reload();
}
+void WebMediaPlayerMS::ActiveStateChanged(bool is_active) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // The case when the stream becomes active is handled by TrackAdded().
+ if (is_active)
+ return;
+
+ // This makes the media element elegible to be garbage collected. Otherwise,
+ // the element will be considered active and will never be garbage
+ // collected.
+ SetNetworkState(kNetworkStateIdle);
+
+ // Stop the audio renderer to free up resources that are not required for an
+ // inactive stream. This is useful if the media element is not garbage
+ // collected.
+ // Note that the video renderer should not be stopped because the ended video
+ // track is expected to produce a black frame after becoming inactive.
+ if (audio_renderer_)
+ audio_renderer_->Stop();
+}
+
void WebMediaPlayerMS::Reload() {
DCHECK(thread_checker_.CalledOnValidThread());
if (web_stream_.IsNull())
@@ -446,7 +464,8 @@ void WebMediaPlayerMS::ReloadVideo() {
if (video_frame_provider_)
renderer_action = RendererReloadAction::REMOVE_RENDERER;
current_video_track_id_ = blink::WebString();
- } else if (video_tracks[0].Id() != current_video_track_id_) {
+ } else if (video_tracks[0].Id() != current_video_track_id_ &&
+ IsPlayableTrack(video_tracks[0])) {
renderer_action = RendererReloadAction::NEW_RENDERER;
current_video_track_id_ = video_tracks[0].Id();
}
@@ -456,6 +475,7 @@ void WebMediaPlayerMS::ReloadVideo() {
if (video_frame_provider_)
video_frame_provider_->Stop();
+ SetNetworkState(kNetworkStateLoading);
video_frame_provider_ = renderer_factory_->GetVideoRenderer(
web_stream_,
media::BindToCurrentLoop(
@@ -495,7 +515,8 @@ void WebMediaPlayerMS::ReloadAudio() {
if (audio_renderer_)
renderer_action = RendererReloadAction::REMOVE_RENDERER;
current_audio_track_id_ = blink::WebString();
- } else if (audio_tracks[0].Id() != current_video_track_id_) {
+ } else if (audio_tracks[0].Id() != current_audio_track_id_ &&
+ IsPlayableTrack(audio_tracks[0])) {
renderer_action = RendererReloadAction::NEW_RENDERER;
current_audio_track_id_ = audio_tracks[0].Id();
}
@@ -505,9 +526,14 @@ void WebMediaPlayerMS::ReloadAudio() {
if (audio_renderer_)
audio_renderer_->Stop();
+ SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
audio_renderer_ = renderer_factory_->GetAudioRenderer(
- web_stream_, frame->GetRoutingID(), initial_audio_output_device_id_,
- initial_security_origin_);
+ web_stream_, frame->GetRoutingID(), initial_audio_output_device_id_);
+
+ // |audio_renderer_| can be null in tests.
+ if (!audio_renderer_)
+ break;
+
audio_renderer_->SetVolume(volume_);
audio_renderer_->Start();
audio_renderer_->Play();
@@ -598,13 +624,28 @@ void WebMediaPlayerMS::SetVolume(double volume) {
delegate_->DidPlayerMutedStatusChange(delegate_id_, volume == 0.0);
}
-void WebMediaPlayerMS::EnterPictureInPicture() {
+void WebMediaPlayerMS::EnterPictureInPicture(
+ blink::WebMediaPlayer::PipWindowOpenedCallback callback) {
+ // TODO(crbug.com/806249): Use Picture-in-Picture window size.
+ std::move(callback).Run(this->NaturalSize());
+
NOTIMPLEMENTED();
// TODO(apacible): Implement after video in surfaces is supported for
// WebMediaPlayerMS. See http://crbug/746182.
}
-void WebMediaPlayerMS::ExitPictureInPicture() {
+void WebMediaPlayerMS::ExitPictureInPicture(
+ blink::WebMediaPlayer::PipWindowClosedCallback callback) {
+ // TODO(crbug.com/806249): Run callback when Picture-in-Picture window closes.
+ std::move(callback).Run();
+
+ NOTIMPLEMENTED();
+ // TODO(apacible): Implement after video in surfaces is supported for
+ // WebMediaPlayerMS. See http://crbug/746182.
+}
+
+void WebMediaPlayerMS::RegisterPictureInPictureWindowResizeCallback(
+ blink::WebMediaPlayer::PipWindowResizedCallback) {
NOTIMPLEMENTED();
// TODO(apacible): Implement after video in surfaces is supported for
// WebMediaPlayerMS. See http://crbug/746182.
@@ -612,15 +653,13 @@ void WebMediaPlayerMS::ExitPictureInPicture() {
void WebMediaPlayerMS::SetSinkId(
const blink::WebString& sink_id,
- const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callback) {
DVLOG(1) << __func__;
DCHECK(thread_checker_.CalledOnValidThread());
const media::OutputDeviceStatusCB callback =
media::ConvertToOutputDeviceStatusCB(web_callback);
if (audio_renderer_) {
- audio_renderer_->SwitchOutputDevice(sink_id.Utf8(), security_origin,
- callback);
+ audio_renderer_->SwitchOutputDevice(sink_id.Utf8(), callback);
} else {
callback.Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
}
@@ -878,6 +917,10 @@ void WebMediaPlayerMS::OnBecamePersistentVideo(bool value) {
get_client()->OnBecamePersistentVideo(value);
}
+void WebMediaPlayerMS::OnPictureInPictureModeEnded() {
+ NOTIMPLEMENTED();
+}
+
bool WebMediaPlayerMS::CopyVideoTextureToPlatformTexture(
gpu::gles2::GLES2Interface* gl,
unsigned target,
@@ -968,8 +1011,8 @@ void WebMediaPlayerMS::OnOpacityChanged(bool is_opaque) {
DCHECK(thread_checker_.CalledOnValidThread());
// Opacity can be changed during the session without resetting
- // |video_weblayer_|.
- video_weblayer_->layer()->SetContentsOpaque(is_opaque);
+ // |video_layer_|.
+ video_layer_->SetContentsOpaque(is_opaque);
}
void WebMediaPlayerMS::OnRotationChanged(media::VideoRotation video_rotation,
@@ -978,13 +1021,15 @@ void WebMediaPlayerMS::OnRotationChanged(media::VideoRotation video_rotation,
DCHECK(thread_checker_.CalledOnValidThread());
video_rotation_ = video_rotation;
- std::unique_ptr<cc_blink::WebLayerImpl> rotated_weblayer =
- base::WrapUnique(new cc_blink::WebLayerImpl(
- cc::VideoLayer::Create(compositor_.get(), video_rotation)));
- rotated_weblayer->layer()->SetContentsOpaque(is_opaque);
- rotated_weblayer->SetContentsOpaqueIsFixed(true);
- get_client()->SetWebLayer(rotated_weblayer.get());
- video_weblayer_ = std::move(rotated_weblayer);
+ // Keep the old |video_layer_| alive until SetCcLayer() is called with a new
+ // pointer, as it may use the pointer from the last call.
+ auto new_video_layer =
+ cc::VideoLayer::Create(compositor_.get(), video_rotation);
+ new_video_layer->SetContentsOpaque(is_opaque);
+
+ get_client()->SetCcLayer(new_video_layer.get());
+
+ video_layer_ = std::move(new_video_layer);
}
void WebMediaPlayerMS::RepaintInternal() {
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.h b/chromium/content/renderer/media/stream/webmediaplayer_ms.h
index 00274face0d..fe0de43a473 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms.h
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.h
@@ -21,12 +21,10 @@
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/platform/web_media_stream.h"
-#include "url/origin.h"
namespace blink {
class WebLocalFrame;
class WebMediaPlayerClient;
-class WebSecurityOrigin;
class WebString;
}
@@ -35,8 +33,8 @@ class GpuMemoryBufferVideoFramePool;
class MediaLog;
}
-namespace cc_blink {
-class WebLayerImpl;
+namespace cc {
+class VideoLayer;
}
namespace gpu {
@@ -84,8 +82,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner,
scoped_refptr<base::TaskRunner> worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories,
- const blink::WebString& sink_id,
- const blink::WebSecurityOrigin& security_origin);
+ const blink::WebString& sink_id);
~WebMediaPlayerMS() override;
@@ -99,10 +96,13 @@ class CONTENT_EXPORT WebMediaPlayerMS
void Seek(double seconds) override;
void SetRate(double rate) override;
void SetVolume(double volume) override;
- void EnterPictureInPicture() override;
- void ExitPictureInPicture() override;
+ void EnterPictureInPicture(
+ blink::WebMediaPlayer::PipWindowOpenedCallback callback) override;
+ void ExitPictureInPicture(
+ blink::WebMediaPlayer::PipWindowClosedCallback callback) override;
+ void RegisterPictureInPictureWindowResizeCallback(
+ blink::WebMediaPlayer::PipWindowResizedCallback) override;
void SetSinkId(const blink::WebString& sink_id,
- const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callback) override;
void SetPreload(blink::WebMediaPlayer::Preload preload) override;
blink::WebTimeRanges Buffered() const override;
@@ -164,6 +164,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
void OnSeekBackward(double seconds) override;
void OnVolumeMultiplierUpdate(double multiplier) override;
void OnBecamePersistentVideo(bool value) override;
+ void OnPictureInPictureModeEnded() override;
bool CopyVideoTextureToPlatformTexture(
gpu::gles2::GLES2Interface* gl,
@@ -195,6 +196,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
// blink::WebMediaStreamObserver implementation
void TrackAdded(const blink::WebMediaStreamTrack& track) override;
void TrackRemoved(const blink::WebMediaStreamTrack& track) override;
+ void ActiveStateChanged(bool is_active) override;
private:
friend class WebMediaPlayerMSTest;
@@ -258,11 +260,11 @@ class CONTENT_EXPORT WebMediaPlayerMS
class FrameDeliverer;
std::unique_ptr<FrameDeliverer> frame_deliverer_;
- scoped_refptr<MediaStreamVideoRenderer> video_frame_provider_; // Weak
+ scoped_refptr<MediaStreamVideoRenderer> video_frame_provider_; // Weak
- std::unique_ptr<cc_blink::WebLayerImpl> video_weblayer_;
+ scoped_refptr<cc::VideoLayer> video_layer_;
- scoped_refptr<MediaStreamAudioRenderer> audio_renderer_; // Weak
+ scoped_refptr<MediaStreamAudioRenderer> audio_renderer_; // Weak
media::PaintCanvasVideoRenderer video_renderer_;
bool paused_;
@@ -284,7 +286,6 @@ class CONTENT_EXPORT WebMediaPlayerMS
scoped_refptr<WebMediaPlayerMSCompositor> compositor_;
const std::string initial_audio_output_device_id_;
- const url::Origin initial_security_origin_;
// The last volume received by setVolume() and the last volume multiplier from
// OnVolumeMultiplierUpdate(). The multiplier is typical 1.0, but may be less
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
index 148ba05ca54..207339b835a 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/hash.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/single_thread_task_runner.h"
#include "base/values.h"
#include "cc/paint/skia_paint_canvas.h"
@@ -134,13 +135,13 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor(
io_task_runner_(io_task_runner),
player_(player),
video_frame_provider_client_(nullptr),
- current_frame_used_by_compositor_(false),
+ current_frame_rendered_(false),
last_render_length_(base::TimeDelta::FromSecondsD(1.0 / 60.0)),
total_frame_count_(0),
dropped_frame_count_(0),
stopped_(true),
render_started_(!stopped_) {
- main_message_loop_ = base::MessageLoop::current();
+ main_message_loop_ = base::MessageLoopCurrent::Get();
blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
if (!web_stream.IsNull())
@@ -218,7 +219,7 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
// With algorithm off, just let |current_frame_| hold the incoming |frame|.
if (!rendering_frame_buffer_) {
- SetCurrentFrame(frame);
+ RenderWithoutAlgorithm(std::move(frame));
return;
}
@@ -228,7 +229,7 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
&end_of_stream) &&
end_of_stream) {
rendering_frame_buffer_.reset();
- SetCurrentFrame(frame);
+ RenderWithoutAlgorithm(std::move(frame));
return;
}
@@ -242,7 +243,7 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
<< "Incoming VideoFrames have no REFERENCE_TIME, switching off super "
"sophisticated rendering algorithm";
rendering_frame_buffer_.reset();
- SetCurrentFrame(frame);
+ RenderWithoutAlgorithm(std::move(frame));
return;
}
@@ -260,7 +261,7 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
dropped_frame_count_ += rendering_frame_buffer_->frames_queued() - 1;
rendering_frame_buffer_->Reset();
timestamps_to_clock_times_.clear();
- SetCurrentFrame(frame);
+ RenderWithoutAlgorithm(std::move(frame));
}
timestamps_to_clock_times_[frame->timestamp()] = render_time;
@@ -283,7 +284,7 @@ bool WebMediaPlayerMSCompositor::UpdateCurrentFrame(
base::AutoLock auto_lock(current_frame_lock_);
if (rendering_frame_buffer_)
- Render(deadline_min, deadline_max);
+ RenderUsingAlgorithm(deadline_min, deadline_max);
if (!current_frame_->metadata()->GetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
@@ -294,8 +295,7 @@ bool WebMediaPlayerMSCompositor::UpdateCurrentFrame(
TRACE_EVENT_END2("media", "UpdateCurrentFrame", "Ideal Render Instant",
render_time.ToInternalValue(), "Serial", serial_);
-
- return !current_frame_used_by_compositor_;
+ return !current_frame_rendered_;
}
bool WebMediaPlayerMSCompositor::HasCurrentFrame() {
@@ -305,6 +305,7 @@ bool WebMediaPlayerMSCompositor::HasCurrentFrame() {
scoped_refptr<media::VideoFrame> WebMediaPlayerMSCompositor::GetCurrentFrame() {
DVLOG(3) << __func__;
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
base::AutoLock auto_lock(current_frame_lock_);
TRACE_EVENT_INSTANT1("media", "WebMediaPlayerMSCompositor::GetCurrentFrame",
TRACE_EVENT_SCOPE_THREAD, "Timestamp",
@@ -312,12 +313,13 @@ scoped_refptr<media::VideoFrame> WebMediaPlayerMSCompositor::GetCurrentFrame() {
if (!render_started_)
return nullptr;
- current_frame_used_by_compositor_ = true;
return current_frame_;
}
void WebMediaPlayerMSCompositor::PutCurrentFrame() {
DVLOG(3) << __func__;
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ current_frame_rendered_ = true;
}
scoped_refptr<media::VideoFrame>
@@ -381,10 +383,10 @@ bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks(
return true;
}
-void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min,
- base::TimeTicks deadline_max) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread() ||
- thread_checker_.CalledOnValidThread());
+void WebMediaPlayerMSCompositor::RenderUsingAlgorithm(
+ base::TimeTicks deadline_min,
+ base::TimeTicks deadline_max) {
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
current_frame_lock_.AssertAcquired();
last_deadline_max_ = deadline_max;
last_render_length_ = deadline_max - deadline_min;
@@ -401,7 +403,7 @@ void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min,
if (!frame || frame == current_frame_)
return;
- SetCurrentFrame(frame);
+ SetCurrentFrame(std::move(frame));
const auto& end = timestamps_to_clock_times_.end();
const auto& begin = timestamps_to_clock_times_.begin();
@@ -411,20 +413,41 @@ void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min,
timestamps_to_clock_times_.erase(begin, iterator);
}
+void WebMediaPlayerMSCompositor::RenderWithoutAlgorithm(
+ const scoped_refptr<media::VideoFrame>& frame) {
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor, this,
+ frame));
+}
+
+void WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor(
+ const scoped_refptr<media::VideoFrame>& frame) {
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ {
+ base::AutoLock auto_lock(current_frame_lock_);
+ SetCurrentFrame(frame);
+ }
+ if (video_frame_provider_client_)
+ video_frame_provider_client_->DidReceiveFrame();
+}
+
void WebMediaPlayerMSCompositor::SetCurrentFrame(
const scoped_refptr<media::VideoFrame>& frame) {
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
current_frame_lock_.AssertAcquired();
TRACE_EVENT_INSTANT1("media", "WebMediaPlayerMSCompositor::SetCurrentFrame",
TRACE_EVENT_SCOPE_THREAD, "Timestamp",
frame->timestamp().InMicroseconds());
- if (!current_frame_used_by_compositor_)
+ if (!current_frame_rendered_)
++dropped_frame_count_;
- current_frame_used_by_compositor_ = false;
+ current_frame_rendered_ = false;
- const bool size_changed =
- !current_frame_ ||
- current_frame_->natural_size() != frame->natural_size();
+ const bool size_changed = !current_frame_ || current_frame_->natural_size() !=
+ frame->natural_size();
current_frame_ = frame;
if (size_changed) {
main_message_loop_->task_runner()->PostTask(
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
index fc0b4980c22..002b4c413fe 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.h
@@ -104,10 +104,21 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
const std::vector<base::TimeDelta>& timestamps,
std::vector<base::TimeTicks>* wall_clock_times);
- // For algorithm enabled case only: given the render interval, update
- // current_frame_ and dropped_frame_count_.
- void Render(base::TimeTicks deadline_min, base::TimeTicks deadline_max);
-
+ // For algorithm enabled case only: given the render interval, call
+ // SetCurrentFrame() if a new frame is available.
+ // |video_frame_provider_client_| gets notified about the new frame when it
+ // calls UpdateCurrentFrame().
+ void RenderUsingAlgorithm(base::TimeTicks deadline_min,
+ base::TimeTicks deadline_max);
+
+ // For algorithm disabled case only: call SetCurrentFrame() with the current
+ // frame immediately. |video_frame_provider_client_| gets notified about the
+ // new frame with a DidReceiveFrame() call.
+ void RenderWithoutAlgorithm(const scoped_refptr<media::VideoFrame>& frame);
+ void RenderWithoutAlgorithmOnCompositor(
+ const scoped_refptr<media::VideoFrame>& frame);
+
+ // Update |current_frame_| and |dropped_frame_count_|
void SetCurrentFrame(const scoped_refptr<media::VideoFrame>& frame);
void StartRenderingInternal();
@@ -151,10 +162,11 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
// selection method which returns the best frame for the render interval.
std::unique_ptr<media::VideoRendererAlgorithm> rendering_frame_buffer_;
- // |current_frame_used_by_compositor_| is updated on compositor thread only.
+ // |current_frame_rendered_| is updated on compositor thread only.
// It's used to track whether |current_frame_| was painted for detecting
- // when to increase |dropped_frame_count_|.
- bool current_frame_used_by_compositor_;
+ // when to increase |dropped_frame_count_|. It is also used when checking if
+ // new frame for display is available in UpdateCurrentFrame().
+ bool current_frame_rendered_;
// Historical data about last rendering. These are for detecting whether
// rendering is paused (one reason is that the tab is not in the front), in
@@ -170,8 +182,8 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
std::map<base::TimeDelta, base::TimeTicks> timestamps_to_clock_times_;
- // |current_frame_lock_| protects |current_frame_used_by_compositor_|,
- // |current_frame_|, |rendering_frame_buffer_|, and |render_started_|.
+ // |current_frame_lock_| protects |current_frame_|, |rendering_frame_buffer_|,
+ // |dropped_frame_count_|, and |render_started_|.
base::Lock current_frame_lock_;
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerMSCompositor);
diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
index 9ee03566248..00933375538 100644
--- a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
+++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -4,11 +4,15 @@
#include <stddef.h>
+#include <utility>
+#include <vector>
+
#include "base/containers/circular_deque.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
+#include "cc/layers/layer.h"
#include "content/public/renderer/media_stream_renderer_factory.h"
#include "content/renderer/media/stream/webmediaplayer_ms.h"
#include "content/renderer/media/stream/webmediaplayer_ms_compositor.h"
@@ -18,7 +22,6 @@
#include "media/video/mock_gpu_memory_buffer_video_frame_pool.h"
#include "media/video/mock_gpu_video_accelerator_factories.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
-#include "third_party/blink/public/platform/web_layer.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/platform/web_media_player_client.h"
#include "third_party/blink/public/platform/web_media_player_source.h"
@@ -73,11 +76,29 @@ class FakeWebMediaPlayerDelegate
EXPECT_EQ(delegate_id_, delegate_id);
}
- void DidPictureInPictureSourceChange(int delegate_id) override {
+ void DidPictureInPictureModeStart(
+ int delegate_id,
+ const viz::SurfaceId&,
+ const gfx::Size&,
+ blink::WebMediaPlayer::PipWindowOpenedCallback) override {
EXPECT_EQ(delegate_id_, delegate_id);
}
- void DidPictureInPictureModeEnd(int delegate_id) override {
+ void DidPictureInPictureModeEnd(
+ int delegate_id,
+ blink::WebMediaPlayer::PipWindowClosedCallback) override {
+ EXPECT_EQ(delegate_id_, delegate_id);
+ }
+
+ void DidPictureInPictureSurfaceChange(int delegate_id,
+ const viz::SurfaceId&,
+ const gfx::Size&) override {
+ EXPECT_EQ(delegate_id_, delegate_id);
+ }
+
+ void RegisterPictureInPictureWindowResizeCallback(
+ int delegate_id,
+ blink::WebMediaPlayer::PipWindowResizedCallback) override {
EXPECT_EQ(delegate_id_, delegate_id);
}
@@ -236,7 +257,6 @@ class MockMediaStreamAudioRenderer : public MediaStreamAudioRenderer {
void SwitchOutputDevice(
const std::string& device_id,
- const url::Origin& security_origin,
const media::OutputDeviceStatusCB& callback) override {}
base::TimeDelta GetCurrentRenderTime() const override {
return base::TimeDelta();
@@ -397,8 +417,7 @@ class MockRenderFactory : public MediaStreamRendererFactory {
scoped_refptr<MediaStreamAudioRenderer> GetAudioRenderer(
const blink::WebMediaStream& web_stream,
int render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) override {
+ const std::string& device_id) override {
return audio_renderer_;
}
@@ -441,8 +460,9 @@ scoped_refptr<MediaStreamVideoRenderer> MockRenderFactory::GetVideoRenderer(
// content::MediaStreamVideoRenderer.
// 2. content::MediaStreamVideoRenderer will start pushing frames into
// WebMediaPlayerMS repeatedly.
-// 3. On WebMediaPlayerMS receiving the first frame, a WebLayer will be created.
-// 4. The WebLayer will call
+// 3. On WebMediaPlayerMS receiving the first frame, a cc::Layer will be
+// created.
+// 4. The cc::Layer will call
// WebMediaPlayerMSCompositor::SetVideoFrameProviderClient, which in turn
// will trigger cc::VideoFrameProviderClient::StartRendering.
// 5. Then cc::VideoFrameProviderClient will start calling
@@ -476,9 +496,8 @@ class WebMediaPlayerMSTest
message_loop_.task_runner(),
message_loop_.task_runner(),
gpu_factories_.get(),
- blink::WebString(),
- blink::WebSecurityOrigin())),
- web_layer_set_(false),
+ blink::WebString())),
+ layer_set_(false),
rendering_(false),
background_rendering_(false) {}
~WebMediaPlayerMSTest() override {
@@ -496,7 +515,7 @@ class WebMediaPlayerMSTest
void DurationChanged() override {}
void SizeChanged() override;
void PlaybackStateChanged() override {}
- void SetWebLayer(blink::WebLayer* layer) override;
+ void SetCcLayer(cc::Layer* layer) override;
blink::WebMediaPlayer::TrackId AddAudioTrack(const blink::WebString& id,
AudioTrackKind,
const blink::WebString& label,
@@ -536,20 +555,19 @@ class WebMediaPlayerMSTest
blink::WebMediaPlayer::DisplayType DisplayType() const override {
return blink::WebMediaPlayer::DisplayType::kInline;
}
+ bool IsInAutoPIP() const override { return false; }
void ActivateViewportIntersectionMonitoring(bool activate) override {}
void MediaRemotingStarted(
const blink::WebString& remote_device_friendly_name) override {}
void MediaRemotingStopped(
blink::WebLocalizedString::Name error_msg) override {}
- void PictureInPictureStarted() override {}
void PictureInPictureStopped() override {}
- bool IsInPictureInPictureMode() override { return false; }
// Implementation of cc::VideoFrameProvider::Client
void StopUsingProvider() override;
void StartRendering() override;
void StopRendering() override;
- void DidReceiveFrame() override {}
+ void DidReceiveFrame() override;
// For test use
void SetBackgroundRendering(bool background_rendering) {
@@ -569,8 +587,9 @@ class WebMediaPlayerMSTest
protected:
MOCK_METHOD0(DoStartRendering, void());
MOCK_METHOD0(DoStopRendering, void());
+ MOCK_METHOD0(DoDidReceiveFrame, void());
- MOCK_METHOD1(DoSetWebLayer, void(bool));
+ MOCK_METHOD1(DoSetCcLayer, void(bool));
MOCK_METHOD1(DoNetworkStateChanged,
void(blink::WebMediaPlayer::NetworkState));
MOCK_METHOD1(DoReadyStateChanged, void(blink::WebMediaPlayer::ReadyState));
@@ -584,7 +603,7 @@ class WebMediaPlayerMSTest
std::unique_ptr<WebMediaPlayerMS> player_;
WebMediaPlayerMSCompositor* compositor_;
ReusableMessageLoopEvent message_loop_controller_;
- blink::WebLayer* web_layer_;
+ cc::Layer* layer_;
bool is_audio_element_ = false;
std::vector<base::OnceClosure> frame_ready_cbs_;
@@ -593,7 +612,7 @@ class WebMediaPlayerMSTest
// rendering.
void RenderFrame();
- bool web_layer_set_;
+ bool layer_set_;
bool rendering_;
bool background_rendering_;
};
@@ -643,16 +662,16 @@ void WebMediaPlayerMSTest::ReadyStateChanged() {
player_->Play();
}
-void WebMediaPlayerMSTest::SetWebLayer(blink::WebLayer* layer) {
+void WebMediaPlayerMSTest::SetCcLayer(cc::Layer* layer) {
// Make sure that the old layer is still alive, see http://crbug.com/705448.
- if (web_layer_set_)
- EXPECT_TRUE(web_layer_ != nullptr);
- web_layer_set_ = layer ? true : false;
+ if (layer_set_)
+ EXPECT_TRUE(layer_ != nullptr);
+ layer_set_ = layer ? true : false;
- web_layer_ = layer;
+ layer_ = layer;
if (layer)
compositor_->SetVideoFrameProviderClient(this);
- DoSetWebLayer(!!layer);
+ DoSetCcLayer(!!layer);
}
void WebMediaPlayerMSTest::StopUsingProvider() {
@@ -675,6 +694,11 @@ void WebMediaPlayerMSTest::StopRendering() {
DoStopRendering();
}
+void WebMediaPlayerMSTest::DidReceiveFrame() {
+ if (background_rendering_)
+ DoDidReceiveFrame();
+}
+
void WebMediaPlayerMSTest::RenderFrame() {
if (!rendering_ || !compositor_)
return;
@@ -719,7 +743,7 @@ TEST_F(WebMediaPlayerMSTest, NoDataDuringLoadForVideo) {
media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
}
TEST_F(WebMediaPlayerMSTest, NoWaitForFrameForAudio) {
@@ -745,7 +769,7 @@ TEST_F(WebMediaPlayerMSTest, NoWaitForFrameForAudio) {
media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
}
TEST_F(WebMediaPlayerMSTest, NoWaitForFrameForAudioOnly) {
@@ -758,7 +782,7 @@ TEST_F(WebMediaPlayerMSTest, NoWaitForFrameForAudioOnly) {
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveEnoughData));
LoadAndGetFrameProvider(true);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
}
TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
@@ -773,7 +797,7 @@ TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -788,7 +812,7 @@ TEST_F(WebMediaPlayerMSTest, Playing_Normal) {
EXPECT_EQ(kStandardHeight, natural_size.height);
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -804,7 +828,7 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -818,7 +842,7 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
media::PipelineStatus::PIPELINE_ERROR_NETWORK);
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -836,7 +860,7 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps, opaque_frame, odd_size_frame);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -860,7 +884,7 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
EXPECT_EQ(prev_frame->timestamp(), after_frame->timestamp());
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
}
TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
@@ -877,7 +901,7 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps, opaque_frame, odd_size_frame);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -911,7 +935,7 @@ TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -929,7 +953,7 @@ TEST_F(WebMediaPlayerMSTest, RotationChange) {
static int tokens[] = {0, 33, kTestBrake};
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps, false, false, 17, media::VIDEO_ROTATION_90);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -946,7 +970,7 @@ TEST_F(WebMediaPlayerMSTest, RotationChange) {
// Change rotation.
provider->QueueFrames(timestamps, false, false, 17, media::VIDEO_ROTATION_0);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStopRendering());
EXPECT_CALL(*this, DoStartRendering());
message_loop_controller_.RunAndWaitForStatus(
@@ -956,7 +980,7 @@ TEST_F(WebMediaPlayerMSTest, RotationChange) {
EXPECT_EQ(kStandardWidth, natural_size.width);
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -970,7 +994,7 @@ TEST_F(WebMediaPlayerMSTest, OpacityChange) {
static int tokens[] = {0, kTestBrake};
std::vector<int> timestamps(tokens, tokens + arraysize(tokens));
provider->QueueFrames(timestamps, true);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -980,23 +1004,23 @@ TEST_F(WebMediaPlayerMSTest, OpacityChange) {
CheckSizeChanged(gfx::Size(kStandardWidth, kStandardHeight)));
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- ASSERT_TRUE(web_layer_ != nullptr);
- EXPECT_TRUE(web_layer_->Opaque());
+ ASSERT_TRUE(layer_ != nullptr);
+ EXPECT_TRUE(layer_->contents_opaque());
// Push one transparent frame.
provider->QueueFrames(timestamps, false);
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- EXPECT_FALSE(web_layer_->Opaque());
+ EXPECT_FALSE(layer_->contents_opaque());
// Push another opaque frame.
provider->QueueFrames(timestamps, true);
message_loop_controller_.RunAndWaitForStatus(
media::PipelineStatus::PIPELINE_OK);
- EXPECT_TRUE(web_layer_->Opaque());
+ EXPECT_TRUE(layer_->contents_opaque());
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -1016,7 +1040,7 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) {
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -1028,7 +1052,9 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) {
media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this);
- // Switch to background rendering, expect rendering to continue.
+ // Switch to background rendering, expect rendering to continue for all the
+ // frames between kTestBrake frames.
+ EXPECT_CALL(*this, DoDidReceiveFrame()).Times(testing::AtLeast(1));
SetBackgroundRendering(true);
auto prev_frame = compositor_->GetCurrentFrameWithoutUpdatingStatistics();
message_loop_controller_.RunAndWaitForStatus(
@@ -1045,7 +1071,7 @@ TEST_F(WebMediaPlayerMSTest, BackgroundRendering) {
EXPECT_NE(prev_frame->timestamp(), after_frame->timestamp());
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -1060,7 +1086,7 @@ TEST_F(WebMediaPlayerMSTest, FrameSizeChange) {
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps, false, false, 7);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -1074,7 +1100,7 @@ TEST_F(WebMediaPlayerMSTest, FrameSizeChange) {
media::PipelineStatus::PIPELINE_OK);
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -1091,7 +1117,7 @@ TEST_F(WebMediaPlayerMSTest, CreateHardwareFrames) {
media::PipelineStatus::PIPELINE_OK);
ASSERT_EQ(1u, frame_ready_cbs_.size());
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -1106,7 +1132,7 @@ TEST_F(WebMediaPlayerMSTest, CreateHardwareFrames) {
ASSERT_TRUE(frame != nullptr);
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
@@ -1122,7 +1148,7 @@ TEST_F(WebMediaPlayerMSTest, StopsCreatingHardwareFramesWhenHiddenOrClosed) {
static int tokens[] = {0, kTestBrake};
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
provider->QueueFrames(timestamps);
- EXPECT_CALL(*this, DoSetWebLayer(true));
+ EXPECT_CALL(*this, DoSetCcLayer(true));
EXPECT_CALL(*this, DoStartRendering());
EXPECT_CALL(*this, DoReadyStateChanged(
blink::WebMediaPlayer::kReadyStateHaveMetadata));
@@ -1165,7 +1191,7 @@ TEST_F(WebMediaPlayerMSTest, StopsCreatingHardwareFramesWhenHiddenOrClosed) {
testing::Mock::VerifyAndClearExpectations(this);
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
EXPECT_CALL(*this, DoStopRendering());
}
#endif // !defined(OS_ANDROID)
@@ -1215,7 +1241,7 @@ TEST_F(WebMediaPlayerMSTest, HiddenPlayerTests) {
// OnShown() should restart after a forced suspension.
player_->OnFrameShown();
EXPECT_FALSE(player_->Paused());
- EXPECT_CALL(*this, DoSetWebLayer(false));
+ EXPECT_CALL(*this, DoSetCcLayer(false));
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc
index 30f013e2805..d5c5d8358c0 100644
--- a/chromium/content/renderer/media/video_capture_impl.cc
+++ b/chromium/content/renderer/media/video_capture_impl.cc
@@ -29,25 +29,73 @@
namespace content {
-// A holder of a memory-backed buffer and accessors to it.
-class VideoCaptureImpl::ClientBuffer
- : public base::RefCountedThreadSafe<ClientBuffer> {
+using VideoFrameBufferHandleType = media::mojom::VideoBufferHandle::Tag;
+
+struct VideoCaptureImpl::BufferContext
+ : public base::RefCountedThreadSafe<BufferContext> {
public:
- ClientBuffer(std::unique_ptr<base::SharedMemory> buffer, size_t buffer_size)
- : buffer_(std::move(buffer)), buffer_size_(buffer_size) {}
+ explicit BufferContext(media::mojom::VideoBufferHandlePtr buffer_handle)
+ : buffer_type_(buffer_handle->which()), shared_memory_size_(0u) {
+ switch (buffer_type_) {
+ case VideoFrameBufferHandleType::SHARED_BUFFER_HANDLE:
+ InitializeFromSharedMemory(
+ std::move(buffer_handle->get_shared_buffer_handle()));
+ break;
+ case VideoFrameBufferHandleType::MAILBOX_HANDLES:
+ InitializeFromMailbox(std::move(buffer_handle->get_mailbox_handles()));
+ break;
+ }
+ }
- base::SharedMemory* buffer() const { return buffer_.get(); }
- size_t buffer_size() const { return buffer_size_; }
+ VideoFrameBufferHandleType buffer_type() const { return buffer_type_; }
+ base::SharedMemory* shared_memory() { return shared_memory_.get(); }
+ size_t shared_memory_size() const { return shared_memory_size_; }
+ const std::vector<gpu::MailboxHolder>& mailbox_holders() const {
+ return mailbox_holders_;
+ }
private:
- friend class base::RefCountedThreadSafe<ClientBuffer>;
+ void InitializeFromSharedMemory(mojo::ScopedSharedBufferHandle handle) {
+ DCHECK(handle.is_valid());
+ base::SharedMemoryHandle memory_handle;
+ mojo::UnwrappedSharedMemoryHandleProtection protection;
+ const MojoResult result = mojo::UnwrapSharedMemoryHandle(
+ std::move(handle), &memory_handle, &shared_memory_size_, &protection);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ DCHECK_GT(shared_memory_size_, 0u);
+
+ // TODO(https://crbug.com/803136): We should also be able to assert that
+ // the unwrapped handle was shared for read-only mapping. That condition
+ // is not currently guaranteed to be met.
+
+ shared_memory_ = std::make_unique<base::SharedMemory>(memory_handle,
+ true /* read_only */);
+ if (!shared_memory_->Map(shared_memory_size_)) {
+ DLOG(ERROR) << "Mapping shared memory failed.";
+ return;
+ }
+ }
- virtual ~ClientBuffer() {}
+ void InitializeFromMailbox(
+ media::mojom::MailboxBufferHandleSetPtr mailbox_handles) {
+ DCHECK_EQ(media::VideoFrame::kMaxPlanes,
+ mailbox_handles->mailbox_holder.size());
+ mailbox_holders_ = std::move(mailbox_handles->mailbox_holder);
+ }
+
+ friend class base::RefCountedThreadSafe<BufferContext>;
+ virtual ~BufferContext() {}
+
+ VideoFrameBufferHandleType buffer_type_;
- const std::unique_ptr<base::SharedMemory> buffer_;
- const size_t buffer_size_;
+ // Only valid for |buffer_type_ == kSharedMemory|.
+ std::unique_ptr<base::SharedMemory> shared_memory_;
+ size_t shared_memory_size_;
- DISALLOW_COPY_AND_ASSIGN(ClientBuffer);
+ // Only valid for |buffer_type_ == kMailboxHolder|.
+ std::vector<gpu::MailboxHolder> mailbox_holders_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferContext);
};
// Information about a video capture client of ours.
@@ -234,35 +282,16 @@ void VideoCaptureImpl::OnStateChanged(media::mojom::VideoCaptureState state) {
}
}
-void VideoCaptureImpl::OnBufferCreated(int32_t buffer_id,
- mojo::ScopedSharedBufferHandle handle) {
+void VideoCaptureImpl::OnNewBuffer(
+ int32_t buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle) {
DVLOG(1) << __func__ << " buffer_id: " << buffer_id;
DCHECK(io_thread_checker_.CalledOnValidThread());
- DCHECK(handle.is_valid());
-
- base::SharedMemoryHandle memory_handle;
- size_t memory_size = 0;
- mojo::UnwrappedSharedMemoryHandleProtection protection;
- const MojoResult result = mojo::UnwrapSharedMemoryHandle(
- std::move(handle), &memory_handle, &memory_size, &protection);
- DCHECK_EQ(MOJO_RESULT_OK, result);
- DCHECK_GT(memory_size, 0u);
-
- // TODO(https://crbug.com/803136): We should also be able to assert that the
- // unwrapped handle was shared for read-only mapping. That condition is not
- // currently guaranteed to be met.
-
- std::unique_ptr<base::SharedMemory> shm(
- new base::SharedMemory(memory_handle, true /* read_only */));
- if (!shm->Map(memory_size)) {
- DLOG(ERROR) << "OnBufferCreated: Map failed.";
- return;
- }
const bool inserted =
client_buffers_
.insert(std::make_pair(buffer_id,
- new ClientBuffer(std::move(shm), memory_size)))
+ new BufferContext(std::move(buffer_handle))))
.second;
DCHECK(inserted);
}
@@ -273,14 +302,6 @@ void VideoCaptureImpl::OnBufferReady(int32_t buffer_id,
DCHECK(io_thread_checker_.CalledOnValidThread());
bool consume_buffer = state_ == VIDEO_CAPTURE_STATE_STARTED;
- if ((info->pixel_format != media::PIXEL_FORMAT_I420 &&
- info->pixel_format != media::PIXEL_FORMAT_Y16) ||
- info->storage_type != media::VideoPixelStorage::CPU) {
- consume_buffer = false;
- LOG(DFATAL) << "Wrong pixel format or storage, got pixel format:"
- << VideoPixelFormatToString(info->pixel_format)
- << ", storage:" << static_cast<int>(info->storage_type);
- }
if (!consume_buffer) {
GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, -1.0);
return;
@@ -313,14 +334,32 @@ void VideoCaptureImpl::OnBufferReady(int32_t buffer_id,
const auto& iter = client_buffers_.find(buffer_id);
DCHECK(iter != client_buffers_.end());
- scoped_refptr<ClientBuffer> buffer = iter->second;
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
+ scoped_refptr<BufferContext> buffer_context = iter->second;
+ scoped_refptr<media::VideoFrame> frame;
+ switch (buffer_context->buffer_type()) {
+ case VideoFrameBufferHandleType::SHARED_BUFFER_HANDLE:
+ frame = media::VideoFrame::WrapExternalSharedMemory(
static_cast<media::VideoPixelFormat>(info->pixel_format),
info->coded_size, info->visible_rect, info->visible_rect.size(),
- reinterpret_cast<uint8_t*>(buffer->buffer()->memory()),
- buffer->buffer_size(), buffer->buffer()->handle(),
+ reinterpret_cast<uint8_t*>(buffer_context->shared_memory()->memory()),
+ buffer_context->shared_memory_size(),
+ buffer_context->shared_memory()->handle(),
0 /* shared_memory_offset */, info->timestamp);
+ break;
+ case VideoFrameBufferHandleType::MAILBOX_HANDLES:
+ gpu::MailboxHolder mailbox_holder_array[media::VideoFrame::kMaxPlanes];
+ CHECK_EQ(media::VideoFrame::kMaxPlanes,
+ buffer_context->mailbox_holders().size());
+ for (int i = 0; i < media::VideoFrame::kMaxPlanes; i++) {
+ mailbox_holder_array[i] = buffer_context->mailbox_holders()[i];
+ }
+ frame = media::VideoFrame::WrapNativeTextures(
+ static_cast<media::VideoPixelFormat>(info->pixel_format),
+ mailbox_holder_array, media::VideoFrame::ReleaseMailboxCB(),
+ info->coded_size, info->visible_rect, info->visible_rect.size(),
+ info->timestamp);
+ break;
+ }
if (!frame) {
GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, -1.0);
return;
@@ -329,8 +368,8 @@ void VideoCaptureImpl::OnBufferReady(int32_t buffer_id,
frame->AddDestructionObserver(base::BindOnce(
&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(),
media::BindToCurrentLoop(base::BindOnce(
- &VideoCaptureImpl::OnClientBufferFinished, weak_factory_.GetWeakPtr(),
- buffer_id, std::move(buffer)))));
+ &VideoCaptureImpl::OnAllClientsFinishedConsumingFrame,
+ weak_factory_.GetWeakPtr(), buffer_id, std::move(buffer_context)))));
frame->metadata()->MergeInternalValuesFrom(info->metadata);
@@ -351,9 +390,9 @@ void VideoCaptureImpl::OnBufferDestroyed(int32_t buffer_id) {
}
}
-void VideoCaptureImpl::OnClientBufferFinished(
+void VideoCaptureImpl::OnAllClientsFinishedConsumingFrame(
int buffer_id,
- scoped_refptr<ClientBuffer> buffer,
+ scoped_refptr<BufferContext> buffer_context,
double consumer_resource_utilization) {
DCHECK(io_thread_checker_.CalledOnValidThread());
@@ -361,19 +400,19 @@ void VideoCaptureImpl::OnClientBufferFinished(
// std::move()'ed to this method and never copied. This is so that the caller,
// DidFinishConsumingFrame(), does not implicitly retain a reference while it
// is running the trampoline callback on another thread. This is necessary to
-// ensure the reference count on the ClientBuffer will be correct at the time
+// ensure the reference count on the BufferContext will be correct at the time
// OnBufferDestroyed() is called. http://crbug.com/797851
#if DCHECK_IS_ON()
- // The ClientBuffer should have exactly two references to it at this point,
+ // The BufferContext should have exactly two references to it at this point,
// one is this method's second argument and the other is from
// |client_buffers_|.
- DCHECK(!buffer->HasOneRef());
- ClientBuffer* const buffer_raw_ptr = buffer.get();
- buffer = nullptr;
+ DCHECK(!buffer_context->HasOneRef());
+ BufferContext* const buffer_raw_ptr = buffer_context.get();
+ buffer_context = nullptr;
// Now there should be only one reference, from |client_buffers_|.
DCHECK(buffer_raw_ptr->HasOneRef());
#else
- buffer = nullptr;
+ buffer_context = nullptr;
#endif
GetVideoCaptureHost()->ReleaseBuffer(
diff --git a/chromium/content/renderer/media/video_capture_impl.h b/chromium/content/renderer/media/video_capture_impl.h
index be95e4c275a..ddd06b323ab 100644
--- a/chromium/content/renderer/media/video_capture_impl.h
+++ b/chromium/content/renderer/media/video_capture_impl.h
@@ -69,8 +69,8 @@ class CONTENT_EXPORT VideoCaptureImpl
// media::mojom::VideoCaptureObserver implementation.
void OnStateChanged(media::mojom::VideoCaptureState state) override;
- void OnBufferCreated(int32_t buffer_id,
- mojo::ScopedSharedBufferHandle handle) override;
+ void OnNewBuffer(int32_t buffer_id,
+ media::mojom::VideoBufferHandlePtr buffer_handle) override;
void OnBufferReady(int32_t buffer_id,
media::mojom::VideoFrameInfoPtr info) override;
void OnBufferDestroyed(int32_t buffer_id) override;
@@ -79,9 +79,7 @@ class CONTENT_EXPORT VideoCaptureImpl
friend class VideoCaptureImplTest;
friend class MockVideoCaptureImpl;
- // Carries a shared memory for transferring video frames from browser to
- // renderer.
- class ClientBuffer;
+ struct BufferContext;
// Contains information about a video capture client, including capture
// parameters callbacks to the client.
@@ -91,11 +89,10 @@ class CONTENT_EXPORT VideoCaptureImpl
using BufferFinishedCallback =
base::OnceCallback<void(double consumer_resource_utilization)>;
- // Sends an IPC message to browser process when all clients are done with the
- // buffer.
- void OnClientBufferFinished(int buffer_id,
- scoped_refptr<ClientBuffer> buffer,
- double consumer_resource_utilization);
+ void OnAllClientsFinishedConsumingFrame(
+ int buffer_id,
+ scoped_refptr<BufferContext> buffer_context,
+ double consumer_resource_utilization);
void StopDevice();
void RestartCapture();
@@ -136,7 +133,7 @@ class CONTENT_EXPORT VideoCaptureImpl
mojo::Binding<media::mojom::VideoCaptureObserver> observer_binding_;
// Buffers available for sending to the client.
- using ClientBufferMap = std::map<int32_t, scoped_refptr<ClientBuffer>>;
+ using ClientBufferMap = std::map<int32_t, scoped_refptr<BufferContext>>;
ClientBufferMap client_buffers_;
ClientInfoMap clients_;
diff --git a/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc b/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
index f5f3e612b07..6a2d0ef4d7a 100644
--- a/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
@@ -69,7 +69,9 @@ class MockVideoCaptureImpl : public VideoCaptureImpl,
MOCK_METHOD1(Stop, void(int32_t));
- void Pause(int device_id) { pause_callback_->OnPaused(session_id()); }
+ void Pause(int device_id) override {
+ pause_callback_->OnPaused(session_id());
+ }
void Resume(int32_t device_id,
int32_t session_id,
diff --git a/chromium/content/renderer/media/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture_impl_unittest.cc
index f32e1484847..634cb052872 100644
--- a/chromium/content/renderer/media/video_capture_impl_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_unittest.cc
@@ -146,10 +146,12 @@ class VideoCaptureImplTest : public ::testing::Test {
}
void SimulateOnBufferCreated(int buffer_id, const base::SharedMemory& shm) {
- video_capture_impl_->OnBufferCreated(
- buffer_id, mojo::WrapSharedMemoryHandle(
- shm.GetReadOnlyHandle(), shm.mapped_size(),
- mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly));
+ media::mojom::VideoBufferHandlePtr buffer_handle =
+ media::mojom::VideoBufferHandle::New();
+ buffer_handle->set_shared_buffer_handle(mojo::WrapSharedMemoryHandle(
+ shm.GetReadOnlyHandle(), shm.mapped_size(),
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly));
+ video_capture_impl_->OnNewBuffer(buffer_id, std::move(buffer_handle));
}
void SimulateBufferReceived(int buffer_id, const gfx::Size& size) {
@@ -162,7 +164,6 @@ class VideoCaptureImplTest : public ::testing::Test {
info->timestamp = now - base::TimeTicks();
info->pixel_format = media::PIXEL_FORMAT_I420;
- info->storage_type = media::VideoPixelStorage::CPU;
info->coded_size = size;
info->visible_rect = gfx::Rect(size);
diff --git a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc
index 62b96aac885..be2d15aa1c5 100644
--- a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc
+++ b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc
@@ -41,8 +41,9 @@ struct NotAdvertisedEncoder {
}
static std::unique_ptr<webrtc::AudioEncoder> MakeAudioEncoder(
const Config& config,
- int payload_type) {
- return T::MakeAudioEncoder(config, payload_type);
+ int payload_type,
+ rtc::Optional<webrtc::AudioCodecPairId> codec_pair_id) {
+ return T::MakeAudioEncoder(config, payload_type, codec_pair_id);
}
};
@@ -59,8 +60,9 @@ struct NotAdvertisedDecoder {
// Don't advertise support for anything.
}
static std::unique_ptr<webrtc::AudioDecoder> MakeAudioDecoder(
- const Config& config) {
- return T::MakeAudioDecoder(config);
+ const Config& config,
+ rtc::Optional<webrtc::AudioCodecPairId> codec_pair_id) {
+ return T::MakeAudioDecoder(config, codec_pair_id);
}
};
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
index 8e82dd62ac2..eb85960b29c 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -18,7 +18,7 @@
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "third_party/webrtc/api/video/i420_buffer.h"
-#include "third_party/webrtc/api/videosinkinterface.h"
+#include "third_party/webrtc/api/video/video_sink_interface.h"
namespace content {
@@ -94,21 +94,22 @@ RemoteVideoSourceDelegate::~RemoteVideoSourceDelegate() {
namespace {
void DoNothing(const scoped_refptr<rtc::RefCountInterface>& ref) {}
-} // anonymous
+} // namespace
void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
const webrtc::VideoFrame& incoming_frame) {
- const base::TimeDelta incoming_timestamp = base::TimeDelta::FromMicroseconds(
- incoming_frame.timestamp_us());
+ const bool render_immediately = incoming_frame.timestamp_us() == 0;
+ const base::TimeDelta incoming_timestamp =
+ render_immediately
+ ? base::TimeTicks::Now() - base::TimeTicks()
+ : base::TimeDelta::FromMicroseconds(incoming_frame.timestamp_us());
const base::TimeTicks render_time =
- base::TimeTicks() + incoming_timestamp + time_diff_;
-
- CHECK_NE(media::kNoTimestamp, incoming_timestamp);
+ render_immediately ? base::TimeTicks() + incoming_timestamp
+ : base::TimeTicks() + incoming_timestamp + time_diff_;
if (start_timestamp_ == media::kNoTimestamp)
start_timestamp_ = incoming_timestamp;
const base::TimeDelta elapsed_timestamp =
incoming_timestamp - start_timestamp_;
-
TRACE_EVENT2("webrtc", "RemoteVideoSourceDelegate::RenderFrame",
"Ideal Render Instant", render_time.ToInternalValue(),
"Timestamp", elapsed_timestamp.InMicroseconds());
@@ -165,8 +166,12 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
media::VideoFrameMetadata::ROTATION,
WebRTCToMediaVideoRotation(incoming_frame.rotation()));
}
- video_frame->metadata()->SetTimeTicks(
- media::VideoFrameMetadata::REFERENCE_TIME, render_time);
+ // Run render smoothness algorithm only when we don't have to render
+ // immediately.
+ if (!render_immediately) {
+ video_frame->metadata()->SetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, render_time);
+ }
io_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
index a3bb09cf1f1..34db57bbd4b 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_task_environment.h"
diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
index 0ccf713a545..d8819aa62a5 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
@@ -29,9 +29,9 @@ namespace content {
class MockAudioTrackInterface : public AudioTrackInterface {
public:
explicit MockAudioTrackInterface(const std::string& id) : id_(id) {}
- virtual ~MockAudioTrackInterface() {}
+ ~MockAudioTrackInterface() override {}
- virtual std::string id() const override { return id_; }
+ std::string id() const override { return id_; }
MOCK_METHOD1(RegisterObserver, void(ObserverInterface*));
MOCK_METHOD1(UnregisterObserver, void(ObserverInterface*));
@@ -52,9 +52,9 @@ class MockAudioTrackInterface : public AudioTrackInterface {
class MockVideoTrackInterface : public VideoTrackInterface {
public:
explicit MockVideoTrackInterface(const std::string& id) : id_(id) {}
- virtual ~MockVideoTrackInterface() {}
+ ~MockVideoTrackInterface() override {}
- virtual std::string id() const override { return id_; }
+ std::string id() const override { return id_; }
MOCK_METHOD1(RegisterObserver, void(ObserverInterface*));
MOCK_METHOD1(UnregisterObserver, void(ObserverInterface*));
diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
index 8f36a8519d6..be896490fc6 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
@@ -28,7 +28,7 @@ namespace content {
namespace {
-rtc::Optional<bool> ToRtcOptional(const base::Optional<bool>& value) {
+rtc::Optional<bool> ToRtcOptionalBool(const base::Optional<bool>& value) {
return value ? rtc::Optional<bool>(*value) : rtc::Optional<bool>();
}
@@ -270,7 +270,8 @@ MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
DCHECK(video_track);
rtc::Optional<bool> needs_denoising =
- ToRtcOptional(video_track->noise_reduction());
+ ToRtcOptionalBool(video_track->noise_reduction());
+
bool is_screencast = video_track->is_screencast();
base::Optional<double> min_frame_rate = video_track->min_frame_rate();
base::Optional<double> max_frame_rate = video_track->max_frame_rate();
diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc
index 21616e414bb..ebc81901bd4 100644
--- a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc
+++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc
@@ -483,7 +483,7 @@ void MockPeerConnectionImpl::RegisterUMAObserver(
}
webrtc::RTCError MockPeerConnectionImpl::SetBitrate(
- const BitrateParameters& bitrate) {
+ const webrtc::BitrateSettings& bitrate) {
NOTIMPLEMENTED();
return webrtc::RTCError::OK();
}
diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h
index 6b8e6f25597..da06e71438e 100644
--- a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h
+++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h
@@ -176,9 +176,7 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
bool AddIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
void RegisterUMAObserver(webrtc::UMAObserver* observer) override;
- webrtc::RTCError SetBitrate(
- const webrtc::PeerConnectionInterface::BitrateParameters& bitrate)
- override;
+ webrtc::RTCError SetBitrate(const webrtc::BitrateSettings& bitrate) override;
void AddRemoteStream(webrtc::MediaStreamInterface* stream);
@@ -202,7 +200,7 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
static const char kDummyAnswer[];
protected:
- virtual ~MockPeerConnectionImpl();
+ ~MockPeerConnectionImpl() override;
private:
// Used for creating MockSessionDescription.
diff --git a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h
index 7b2fba5d5c5..6958818c8c2 100644
--- a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h
+++ b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h
@@ -21,7 +21,7 @@ class MockWebRTCPeerConnectionHandlerClient
: public blink::WebRTCPeerConnectionHandlerClient {
public:
MockWebRTCPeerConnectionHandlerClient();
- virtual ~MockWebRTCPeerConnectionHandlerClient();
+ ~MockWebRTCPeerConnectionHandlerClient() override;
// WebRTCPeerConnectionHandlerClient implementation.
MOCK_METHOD0(NegotiationNeeded, void());
@@ -31,15 +31,16 @@ class MockWebRTCPeerConnectionHandlerClient
MOCK_METHOD1(DidChangeICEGatheringState, void(ICEGatheringState state));
MOCK_METHOD1(DidChangeICEConnectionState, void(ICEConnectionState state));
void DidAddRemoteTrack(
- std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) {
+ std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override {
DidAddRemoteTrackForMock(&web_rtp_receiver);
}
void DidRemoveRemoteTrack(
- std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) {
+ std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override {
DidRemoveRemoteTrackForMock(&web_rtp_receiver);
}
MOCK_METHOD1(DidAddRemoteDataChannel, void(blink::WebRTCDataChannelHandler*));
MOCK_METHOD0(ReleasePeerConnectionHandler, void());
+ MOCK_METHOD0(GetOriginTrials, WebRTCOriginTrials());
// Move-only arguments do not play nicely with MOCK, the workaround is to
// EXPECT_CALL with these instead.
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 12f443e4e2f..d57e983c03b 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -166,7 +166,7 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
webrtc::DisableRtcUseH264();
#endif // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
- base::MessageLoop::current()->AddDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
// To allow sending to the signaling/worker threads.
jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index 13383b21066..8f1cbd22a8c 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -9,7 +9,7 @@
#include "base/files/file.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
@@ -46,7 +46,7 @@ class WebRtcAudioDeviceImpl;
// Object factory for RTC PeerConnections.
class CONTENT_EXPORT PeerConnectionDependencyFactory
- : base::MessageLoop::DestructionObserver {
+ : base::MessageLoopCurrent::DestructionObserver {
public:
PeerConnectionDependencyFactory(
P2PSocketDispatcher* p2p_socket_dispatcher);
@@ -110,7 +110,7 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
void EnsureWebRtcAudioDeviceImpl();
private:
- // Implement base::MessageLoop::DestructionObserver.
+ // Implement base::MessageLoopCurrent::DestructionObserver.
// This makes sure the libjingle PeerConnectionFactory is released before
// the renderer message loop is destroyed.
void WillDestroyCurrentMessageLoop() override;
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_remote_audio_source.cc b/chromium/content/renderer/media/webrtc/peer_connection_remote_audio_source.cc
index 733f9f38aef..238de5c6221 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_remote_audio_source.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_remote_audio_source.cc
@@ -142,7 +142,7 @@ void PeerConnectionRemoteAudioSource::OnData(const void* audio_data,
MediaStreamAudioSource::SetFormat(
media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::GuessChannelLayout(number_of_channels),
- sample_rate, bits_per_sample, number_of_frames));
+ sample_rate, number_of_frames));
}
MediaStreamAudioSource::DeliverDataToTracks(*audio_bus_, playout_time);
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
index b9316272341..85ce26f5918 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc
@@ -177,6 +177,21 @@ static const char* SerializeRtcpMuxPolicy(
return policy_str;
}
+static const char* SerializeSdpSemantics(webrtc::SdpSemantics sdp_semantics) {
+ const char* sdp_semantics_str = "";
+ switch (sdp_semantics) {
+ case webrtc::SdpSemantics::kPlanB:
+ sdp_semantics_str = "plan-b";
+ break;
+ case webrtc::SdpSemantics::kUnifiedPlan:
+ sdp_semantics_str = "unified-plan";
+ break;
+ default:
+ NOTREACHED();
+ }
+ return sdp_semantics_str;
+}
+
static std::string SerializeConfiguration(
const webrtc::PeerConnectionInterface::RTCConfiguration& config) {
std::ostringstream oss;
@@ -185,7 +200,9 @@ static std::string SerializeConfiguration(
<< ", iceTransportPolicy: " << SerializeIceTransportType(config.type)
<< ", bundlePolicy: " << SerializeBundlePolicy(config.bundle_policy)
<< ", rtcpMuxPolicy: " << SerializeRtcpMuxPolicy(config.rtcp_mux_policy)
- << ", iceCandidatePoolSize: " << config.ice_candidate_pool_size << " }";
+ << ", iceCandidatePoolSize: " << config.ice_candidate_pool_size
+ << ", sdpSemantics: \"" << SerializeSdpSemantics(config.sdp_semantics)
+ << "\" }";
return oss.str();
}
diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc
index 4019d764e3a..8eb3a817560 100644
--- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc
@@ -140,7 +140,6 @@ void RTCCertificateGenerator::generateCertificateWithOptionalExpiration(
std::unique_ptr<blink::WebRTCCertificateCallback> observer,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
DCHECK(IsSupportedKeyParams(key_params));
-#if BUILDFLAG(ENABLE_WEBRTC)
PeerConnectionDependencyFactory* pc_dependency_factory =
RenderThreadImpl::current()->GetPeerConnectionDependencyFactory();
pc_dependency_factory->EnsureInitialized();
@@ -150,9 +149,6 @@ void RTCCertificateGenerator::generateCertificateWithOptionalExpiration(
task_runner, pc_dependency_factory->GetWebRtcWorkerThread());
request->GenerateCertificateAsync(
key_params, expires_ms, std::move(observer));
-#else
- observer->onError();
-#endif
}
bool RTCCertificateGenerator::IsSupportedKeyParams(
diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h
index 25abfe8dc1a..248cd21846c 100644
--- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h
+++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_CERTIFICATE_GENERATOR_H_
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/web_rtc_certificate.h"
#include "third_party/blink/public/platform/web_rtc_certificate_generator.h"
#include "third_party/blink/public/platform/web_rtc_key_params.h"
diff --git a/chromium/content/renderer/media/webrtc/rtc_data_channel_handler.cc b/chromium/content/renderer/media/webrtc/rtc_data_channel_handler.cc
index aa5b7215a86..7937e537bd6 100644
--- a/chromium/content/renderer/media/webrtc/rtc_data_channel_handler.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_data_channel_handler.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/content/renderer/media/webrtc/rtc_error.cc b/chromium/content/renderer/media/webrtc/rtc_error.cc
deleted file mode 100644
index 4b79c809990..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_error.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 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/renderer/media/webrtc/rtc_error.h"
-
-#include "third_party/webrtc/api/rtcerror.h"
-
-namespace content {
-
-blink::WebRTCError ConvertToWebKitRTCError(
- const webrtc::RTCError& webrtc_error) {
- blink::WebString message = blink::WebString::FromUTF8(
- webrtc_error.message(), strlen(webrtc_error.message()));
- switch (webrtc_error.type()) {
- case webrtc::RTCErrorType::NONE:
- return blink::WebRTCError(blink::WebRTCErrorType::kNone, message);
- break;
- case webrtc::RTCErrorType::UNSUPPORTED_PARAMETER:
- return blink::WebRTCError(blink::WebRTCErrorType::kUnsupportedParameter,
- message);
- break;
- case webrtc::RTCErrorType::INVALID_PARAMETER:
- return blink::WebRTCError(blink::WebRTCErrorType::kInvalidParameter,
- message);
- break;
- case webrtc::RTCErrorType::INVALID_RANGE:
- return blink::WebRTCError(blink::WebRTCErrorType::kInvalidRange, message);
- break;
- case webrtc::RTCErrorType::SYNTAX_ERROR:
- return blink::WebRTCError(blink::WebRTCErrorType::kSyntaxError, message);
- break;
- case webrtc::RTCErrorType::INVALID_STATE:
- return blink::WebRTCError(blink::WebRTCErrorType::kInvalidState, message);
- break;
- case webrtc::RTCErrorType::INVALID_MODIFICATION:
- return blink::WebRTCError(blink::WebRTCErrorType::kInvalidModification,
- message);
- break;
- case webrtc::RTCErrorType::NETWORK_ERROR:
- return blink::WebRTCError(blink::WebRTCErrorType::kNetworkError, message);
- break;
- case webrtc::RTCErrorType::INTERNAL_ERROR:
- return blink::WebRTCError(blink::WebRTCErrorType::kInternalError,
- message);
- break;
- default:
- // If adding a new error type, need 3 CLs: One to add the enum to webrtc,
- // one to update this mapping code, and one to start using the enum in
- // webrtc.
- NOTREACHED() << "webrtc::RTCErrorType "
- << webrtc::ToString(webrtc_error.type())
- << " not covered by switch statement.";
- break;
- }
- NOTREACHED();
- return blink::WebRTCError(blink::WebRTCErrorType::kInternalError,
- "Impossible code path executed");
-}
-
-} // namespace content \ No newline at end of file
diff --git a/chromium/content/renderer/media/webrtc/rtc_error.h b/chromium/content/renderer/media/webrtc/rtc_error.h
deleted file mode 100644
index 6183a4eabf5..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_error.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 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_RENDERER_MEDIA_WEBRTC_RTC_ERROR_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_ERROR_H_
-
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "third_party/blink/public/platform/web_rtc_error.h"
-
-namespace webrtc {
-class RTCError;
-}
-
-namespace content {
-blink::WebRTCError ConvertToWebKitRTCError(
- const webrtc::RTCError& webrtc_error);
-}
-
-#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_ERROR_H_ \ No newline at end of file
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
index aba19e25317..e972ef0a8dd 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -32,7 +32,6 @@
#include "content/renderer/media/webrtc/rtc_certificate.h"
#include "content/renderer/media/webrtc/rtc_data_channel_handler.h"
#include "content/renderer/media/webrtc/rtc_dtmf_sender_handler.h"
-#include "content/renderer/media/webrtc/rtc_error.h"
#include "content/renderer/media/webrtc/rtc_event_log_output_sink.h"
#include "content/renderer/media/webrtc/rtc_event_log_output_sink_proxy.h"
#include "content/renderer/media/webrtc/rtc_stats.h"
@@ -46,7 +45,6 @@
#include "third_party/blink/public/platform/web_rtc_answer_options.h"
#include "third_party/blink/public/platform/web_rtc_configuration.h"
#include "third_party/blink/public/platform/web_rtc_data_channel_init.h"
-#include "third_party/blink/public/platform/web_rtc_error.h"
#include "third_party/blink/public/platform/web_rtc_ice_candidate.h"
#include "third_party/blink/public/platform/web_rtc_legacy_stats.h"
#include "third_party/blink/public/platform/web_rtc_offer_options.h"
@@ -415,7 +413,7 @@ class CreateSessionDescriptionRequest
tracker_.TrackOnFailure(error);
// TODO(hta): Convert CreateSessionDescriptionRequest.OnFailure
- webkit_request_.RequestFailed(ConvertToWebKitRTCError(error).message());
+ webkit_request_.RequestFailed(error);
webkit_request_.Reset();
}
@@ -469,7 +467,7 @@ class SetLocalDescriptionRequest
return;
}
tracker_.TrackOnFailure(error);
- webkit_request_.RequestFailed(ConvertToWebKitRTCError(error));
+ webkit_request_.RequestFailed(error);
webkit_request_.Reset();
}
@@ -1005,7 +1003,7 @@ class RTCPeerConnectionHandler::WebRtcSetRemoteDescriptionObserverImpl
PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION, "OnFailure",
error.message());
}
- web_request_.RequestFailed(ConvertToWebKitRTCError(error));
+ web_request_.RequestFailed(error);
web_request_.Reset();
return;
}
@@ -1515,9 +1513,8 @@ void RTCPeerConnectionHandler::SetLocalDescription(
reason_str.append(" ");
reason_str.append(error.description);
LOG(ERROR) << reason_str;
- request.RequestFailed(
- blink::WebRTCError(blink::WebRTCErrorType::kOperationError,
- blink::WebString::FromUTF8(reason_str)));
+ request.RequestFailed(webrtc::RTCError(webrtc::RTCErrorType::INTERNAL_ERROR,
+ std::move(reason_str)));
if (peer_connection_tracker_) {
peer_connection_tracker_->TrackSessionDescriptionCallback(
this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION,
@@ -1575,9 +1572,8 @@ void RTCPeerConnectionHandler::SetRemoteDescription(
reason_str.append(" ");
reason_str.append(error.description);
LOG(ERROR) << reason_str;
- request.RequestFailed(
- blink::WebRTCError(blink::WebRTCErrorType::kOperationError,
- blink::WebString::FromUTF8(reason_str)));
+ request.RequestFailed(webrtc::RTCError(
+ webrtc::RTCErrorType::UNSUPPORTED_OPERATION, std::move(reason_str)));
if (peer_connection_tracker_) {
peer_connection_tracker_->TrackSessionDescriptionCallback(
this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION,
@@ -1663,7 +1659,7 @@ blink::WebRTCSessionDescription RTCPeerConnectionHandler::RemoteDescription() {
return CreateWebKitSessionDescription(sdp, type);
}
-blink::WebRTCErrorType RTCPeerConnectionHandler::SetConfiguration(
+webrtc::RTCErrorType RTCPeerConnectionHandler::SetConfiguration(
const blink::WebRTCConfiguration& blink_config) {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setConfiguration");
@@ -1678,7 +1674,7 @@ blink::WebRTCErrorType RTCPeerConnectionHandler::SetConfiguration(
// The boolean return value is made redundant by the error output param; just
// DCHECK that they're consistent.
DCHECK_EQ(ret, webrtc_error.type() == webrtc::RTCErrorType::NONE);
- return ConvertToWebKitRTCError(webrtc_error).GetType();
+ return webrtc_error.type();
}
bool RTCPeerConnectionHandler::AddICECandidate(
@@ -1733,9 +1729,9 @@ void RTCPeerConnectionHandler::OnaddICECandidateResult(
if (!result) {
// We don't have the actual error code from the libjingle, so for now
// using a generic error string.
- return webkit_request.RequestFailed(blink::WebRTCError(
- blink::WebRTCErrorType::kOperationError,
- blink::WebString::FromUTF8("Error processing ICE candidate")));
+ return webkit_request.RequestFailed(
+ webrtc::RTCError(webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
+ std::move("Error processing ICE candidate")));
}
return webkit_request.RequestSucceeded();
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
index 9a1af0d2f77..a4b038365d2 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h
@@ -38,7 +38,7 @@ class WebRTCDataChannelHandler;
class WebRTCLegacyStats;
class WebRTCOfferOptions;
class WebRTCPeerConnectionHandlerClient;
-}
+} // namespace blink
namespace content {
@@ -50,8 +50,7 @@ class RtcDataChannelHandler;
class CONTENT_EXPORT LocalRTCStatsResponse : public rtc::RefCountInterface {
public:
explicit LocalRTCStatsResponse(const blink::WebRTCStatsResponse& impl)
- : impl_(impl) {
- }
+ : impl_(impl) {}
virtual blink::WebRTCStatsResponse webKitStatsResponse() const;
virtual void addStats(const blink::WebRTCLegacyStats& stats);
@@ -131,7 +130,7 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
blink::WebRTCSessionDescription LocalDescription() override;
blink::WebRTCSessionDescription RemoteDescription() override;
- blink::WebRTCErrorType SetConfiguration(
+ webrtc::RTCErrorType SetConfiguration(
const blink::WebRTCConfiguration& configuration) override;
bool AddICECandidate(
scoped_refptr<blink::WebRTCICECandidate> candidate) override;
@@ -205,8 +204,11 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
void OnRemoveRemoteTrack(
scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver);
void OnDataChannel(std::unique_ptr<RtcDataChannelHandler> handler);
- void OnIceCandidate(const std::string& sdp, const std::string& sdp_mid,
- int sdp_mline_index, int component, int address_family);
+ void OnIceCandidate(const std::string& sdp,
+ const std::string& sdp_mid,
+ int sdp_mline_index,
+ int component,
+ int address_family);
private:
// Record info about the first SessionDescription from the local and
@@ -222,7 +224,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
};
webrtc::SessionDescriptionInterface* CreateNativeSessionDescription(
- const std::string& sdp, const std::string& type,
+ const std::string& sdp,
+ const std::string& type,
webrtc::SdpParseError* error);
// Report to UMA whether an IceConnectionState has occurred. It only records
@@ -234,9 +237,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// constructor as well as after Ice Restart.
void ResetUMAStats();
- void ReportFirstSessionDescriptions(
- const FirstSessionDescription& local,
- const FirstSessionDescription& remote);
+ void ReportFirstSessionDescriptions(const FirstSessionDescription& local,
+ const FirstSessionDescription& remote);
std::vector<std::unique_ptr<RTCRtpSender>>::iterator FindSender(uintptr_t id);
@@ -285,16 +287,6 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// automatically disposed when there are no longer any components referencing
// it.
scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map_;
- // Remote stream adapters. Every stream that is in use by the peer connection
- // has an associated blink and webrtc layer representation of it. This vector
- // keeps track of the relationship between |webrtc::MediaStreamInterface|s and
- // |blink::WebMediaStream|s. Remote streams are added and removed from the
- // peer connection on events fired during |setRemoteDescription|.
- // TODO(hbos): |RTCPeerConnection::getRemoteStreams| should return all streams
- // of all receivers and this standalone vector should be removed.
- // https://crbug.com/741618
- std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>>
- remote_streams_;
// Content layer correspondents of |webrtc::RtpSenderInterface|.
std::vector<std::unique_ptr<RTCRtpSender>> rtp_senders_;
// Maps |RTCRtpReceiver::getId|s of |webrtc::RtpReceiverInterface|s to the
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
index be6131649f3..3d9ade84d75 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
@@ -48,7 +48,6 @@
#include "third_party/blink/public/platform/web_rtc_data_channel_handler.h"
#include "third_party/blink/public/platform/web_rtc_data_channel_init.h"
#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
-#include "third_party/blink/public/platform/web_rtc_error.h"
#include "third_party/blink/public/platform/web_rtc_ice_candidate.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h"
#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
@@ -335,7 +334,7 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
static_cast<size_t>(1));
audio_tracks[0].Initialize(blink_audio_source.Id(), blink_audio_source);
EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(),
- Initialize(_, _, -1));
+ Initialize(_, _));
EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(),
SetAutomaticGainControl(true));
EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), Start());
@@ -769,8 +768,7 @@ TEST_F(RTCPeerConnectionHandlerTest, setConfiguration) {
// TODO(perkj): Test that the parameters in |config| can be translated when a
// WebRTCConfiguration can be constructed. It's WebKit class and can't be
// initialized from a test.
- EXPECT_EQ(blink::WebRTCErrorType::kNone,
- pc_handler_->SetConfiguration(config));
+ EXPECT_EQ(webrtc::RTCErrorType::NONE, pc_handler_->SetConfiguration(config));
}
// Test that when an error occurs in SetConfiguration, it's converted to a
@@ -782,7 +780,7 @@ TEST_F(RTCPeerConnectionHandlerTest, setConfigurationError) {
webrtc::RTCErrorType::INVALID_MODIFICATION);
EXPECT_CALL(*mock_tracker_.get(),
TrackSetConfiguration(pc_handler_.get(), _));
- EXPECT_EQ(blink::WebRTCErrorType::kInvalidModification,
+ EXPECT_EQ(webrtc::RTCErrorType::INVALID_MODIFICATION,
pc_handler_->SetConfiguration(config));
}
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_parameters.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_parameters.cc
deleted file mode 100644
index f3938c62d0f..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_parameters.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) 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/renderer/media/webrtc/rtc_rtp_parameters.h"
-
-#include <utility>
-
-namespace {
-
-// Relative weights for each priority as defined in RTCWEB-DATA
-// https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel
-const double kPriorityWeightVeryLow = 0.5;
-const double kPriorityWeightLow = 1;
-const double kPriorityWeightMedium = 2;
-const double kPriorityWeightHigh = 4;
-
-template <typename T, typename F>
-base::Optional<T> ToBaseOptional(const rtc::Optional<F>& from) {
- if (from)
- return from.value();
- return base::nullopt;
-}
-
-blink::WebRTCPriorityType PriorityFromDouble(double priority) {
- // Find the middle point between 2 priority weights to match them to a
- // WebRTC priority
- const double very_low_upper_bound =
- (kPriorityWeightVeryLow + kPriorityWeightLow) / 2;
- const double low_upper_bound =
- (kPriorityWeightLow + kPriorityWeightMedium) / 2;
- const double medium_upper_bound =
- (kPriorityWeightMedium + kPriorityWeightHigh) / 2;
-
- if (priority < webrtc::kDefaultBitratePriority * very_low_upper_bound) {
- return blink::WebRTCPriorityType::VeryLow;
- }
- if (priority < webrtc::kDefaultBitratePriority * low_upper_bound) {
- return blink::WebRTCPriorityType::Low;
- }
- if (priority < webrtc::kDefaultBitratePriority * medium_upper_bound) {
- return blink::WebRTCPriorityType::Medium;
- }
- return blink::WebRTCPriorityType::High;
-}
-
-base::Optional<blink::WebRTCDtxStatus> FromRTCDtxStatus(
- rtc::Optional<webrtc::DtxStatus> status) {
- if (!status)
- return base::nullopt;
-
- blink::WebRTCDtxStatus result;
- switch (status.value()) {
- case webrtc::DtxStatus::DISABLED:
- result = blink::WebRTCDtxStatus::Disabled;
- break;
- case webrtc::DtxStatus::ENABLED:
- result = blink::WebRTCDtxStatus::Enabled;
- break;
- default:
- NOTREACHED();
- }
- return result;
-}
-
-base::Optional<blink::WebRTCDegradationPreference> FromRTCDegradationPreference(
- rtc::Optional<webrtc::DegradationPreference> degradation_preference) {
- if (!degradation_preference)
- return base::nullopt;
-
- blink::WebRTCDegradationPreference result;
- switch (degradation_preference.value()) {
- case webrtc::DegradationPreference::MAINTAIN_FRAMERATE:
- result = blink::WebRTCDegradationPreference::MaintainFramerate;
- break;
- case webrtc::DegradationPreference::MAINTAIN_RESOLUTION:
- result = blink::WebRTCDegradationPreference::MaintainResolution;
- break;
- case webrtc::DegradationPreference::BALANCED:
- result = blink::WebRTCDegradationPreference::Balanced;
- break;
- default:
- NOTREACHED();
- }
- return result;
-}
-
-} // namespace
-
-namespace content {
-
-blink::WebRTCRtpParameters GetWebRTCRtpParameters(
- const webrtc::RtpParameters& parameters) {
- blink::WebVector<blink::WebRTCRtpEncodingParameters> encodings;
- encodings.reserve(parameters.encodings.size());
- for (const auto& encoding_parameter : parameters.encodings) {
- encodings.emplace_back(GetWebRTCRtpEncodingParameters(encoding_parameter));
- }
-
- blink::WebVector<blink::WebRTCRtpHeaderExtensionParameters> header_extensions;
- header_extensions.reserve(parameters.header_extensions.size());
- for (const auto& extension_parameter : parameters.header_extensions) {
- header_extensions.emplace_back(
- GetWebRTCRtpHeaderExtensionParameters(extension_parameter));
- }
-
- blink::WebVector<blink::WebRTCRtpCodecParameters> codec_parameters;
- codec_parameters.reserve(parameters.codecs.size());
- for (const auto& codec_parameter : parameters.codecs) {
- codec_parameters.emplace_back(GetWebRTCRtpCodecParameters(codec_parameter));
- }
-
- return blink::WebRTCRtpParameters(
- blink::WebString::FromASCII(parameters.transaction_id),
- blink::WebRTCRtcpParameters(), std::move(encodings), header_extensions,
- codec_parameters,
- FromRTCDegradationPreference(parameters.degradation_preference));
-}
-
-blink::WebRTCRtpEncodingParameters GetWebRTCRtpEncodingParameters(
- const webrtc::RtpEncodingParameters& encoding_parameters) {
- return blink::WebRTCRtpEncodingParameters(
- ToBaseOptional<uint8_t>(encoding_parameters.codec_payload_type),
- FromRTCDtxStatus(encoding_parameters.dtx), encoding_parameters.active,
- PriorityFromDouble(encoding_parameters.bitrate_priority),
- ToBaseOptional<uint32_t>(encoding_parameters.ptime),
- ToBaseOptional<uint32_t>(encoding_parameters.max_bitrate_bps),
- ToBaseOptional<uint32_t>(encoding_parameters.max_framerate),
- encoding_parameters.scale_framerate_down_by,
- blink::WebString::FromASCII(encoding_parameters.rid));
-}
-
-blink::WebRTCRtpHeaderExtensionParameters GetWebRTCRtpHeaderExtensionParameters(
- const webrtc::RtpHeaderExtensionParameters& extension_parameters) {
- return blink::WebRTCRtpHeaderExtensionParameters(
- blink::WebString::FromASCII(extension_parameters.uri),
- extension_parameters.id, extension_parameters.encrypt);
-}
-
-// TODO(orphis): Copy the RTCP information
-// https://crbug.com/webrtc/7580
-blink::WebRTCRtcpParameters GetWebRTCRtcpParameters() {
- return blink::WebRTCRtcpParameters();
-}
-
-blink::WebRTCRtpCodecParameters GetWebRTCRtpCodecParameters(
- const webrtc::RtpCodecParameters& codec_parameters) {
- return blink::WebRTCRtpCodecParameters(
- codec_parameters.payload_type,
- blink::WebString::FromASCII(codec_parameters.mime_type()),
- ToBaseOptional<uint32_t>(codec_parameters.clock_rate),
- ToBaseOptional<uint16_t>(codec_parameters.num_channels),
- // TODO(orphis): Convert the parameters field to sdpFmtpLine
- // https://crbug.com/webrtc/7580
- blink::WebString());
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_parameters.h b/chromium/content/renderer/media/webrtc/rtc_rtp_parameters.h
deleted file mode 100644
index b8147eea16b..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_parameters.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 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_RENDERER_MEDIA_WEBRTC_RTC_RTP_PARAMETERS_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_PARAMETERS_H_
-
-#include "base/memory/ref_counted.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_rtc_rtp_parameters.h"
-#include "third_party/webrtc/api/rtpparameters.h"
-
-namespace content {
-
-CONTENT_EXPORT blink::WebRTCRtpEncodingParameters
-GetWebRTCRtpEncodingParameters(
- const webrtc::RtpEncodingParameters& encoding_parameters);
-
-CONTENT_EXPORT blink::WebRTCRtpHeaderExtensionParameters
-GetWebRTCRtpHeaderExtensionParameters(
- const webrtc::RtpHeaderExtensionParameters& extension_parameters);
-
-CONTENT_EXPORT blink::WebRTCRtcpParameters GetWebRTCRtcpParameters();
-
-CONTENT_EXPORT blink::WebRTCRtpCodecParameters GetWebRTCRtpCodecParameters(
- const webrtc::RtpCodecParameters& codec_parameters);
-
-CONTENT_EXPORT blink::WebRTCRtpParameters GetWebRTCRtpParameters(
- const webrtc::RtpParameters& parameters);
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_PARAMETERS_H_
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_parameters_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_parameters_unittest.cc
deleted file mode 100644
index b1d1629e9ee..00000000000
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_parameters_unittest.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/webrtc/rtc_rtp_parameters.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-TEST(RTCRtpParametersTest, Read) {
- webrtc::RtpParameters webrtc_parameters;
- webrtc_parameters.transaction_id = "transaction_id";
- webrtc_parameters.degradation_preference =
- webrtc::DegradationPreference::BALANCED;
-
- webrtc_parameters.encodings.emplace_back();
- webrtc::RtpEncodingParameters& webrtc_encoding =
- webrtc_parameters.encodings.front();
- webrtc_encoding.codec_payload_type = 42;
- webrtc_encoding.dtx = webrtc::DtxStatus::ENABLED;
- webrtc_encoding.active = true;
- webrtc_encoding.bitrate_priority = webrtc::kDefaultBitratePriority;
- webrtc_encoding.ptime = 1337;
- webrtc_encoding.max_bitrate_bps = 1337000;
- webrtc_encoding.max_framerate = 60;
- webrtc_encoding.scale_resolution_down_by = 1.;
- webrtc_encoding.rid = "rid";
-
- webrtc_parameters.header_extensions.emplace_back();
- webrtc::RtpHeaderExtensionParameters& webrtc_header_extension =
- webrtc_parameters.header_extensions.front();
- webrtc_header_extension.uri = "uri";
- webrtc_header_extension.id = 33;
- webrtc_header_extension.encrypt = true;
-
- webrtc_parameters.codecs.emplace_back();
- webrtc::RtpCodecParameters& webrtc_codec_parameter =
- webrtc_parameters.codecs.front();
- webrtc_codec_parameter.payload_type = 42;
- webrtc_codec_parameter.clock_rate = 1234;
- webrtc_codec_parameter.num_channels = 2;
-
- blink::WebRTCRtpParameters parameters =
- GetWebRTCRtpParameters(webrtc_parameters);
- EXPECT_EQ(parameters.TransactionId(), "transaction_id");
- EXPECT_EQ(parameters.DegradationPreference(),
- blink::WebRTCDegradationPreference::Balanced);
-
- ASSERT_EQ(parameters.Encodings().size(), 1u);
- for (const auto& encoding : parameters.Encodings()) {
- EXPECT_EQ(encoding.CodecPayloadType(), 42);
- EXPECT_EQ(encoding.Dtx(), blink::WebRTCDtxStatus::Enabled);
- EXPECT_EQ(encoding.Active(), true);
- EXPECT_EQ(encoding.Priority(), blink::WebRTCPriorityType::Low);
- EXPECT_EQ(encoding.Ptime(), 1337u);
- EXPECT_EQ(encoding.MaxBitrate(), 1337000u);
- EXPECT_EQ(encoding.MaxFramerate(), 60u);
- EXPECT_EQ(encoding.ScaleResolutionDownBy(), 1.);
- EXPECT_EQ(encoding.Rid(), "rid");
- }
-
- ASSERT_EQ(parameters.HeaderExtensions().size(), 1u);
- for (const auto& header_extension : parameters.HeaderExtensions()) {
- EXPECT_EQ(header_extension.URI(), "uri");
- EXPECT_EQ(header_extension.Id(), 33);
- EXPECT_EQ(header_extension.Encrypted(), true);
- }
-
- ASSERT_EQ(parameters.Codecs().size(), 1u);
- for (const auto& codec : parameters.Codecs()) {
- EXPECT_EQ(codec.PayloadType(), 42);
- EXPECT_EQ(codec.ClockRate(), 1234u);
- EXPECT_EQ(codec.Channels(), 2u);
- }
-}
-
-TEST(RTCRtpParametersTest, CheckDtxStatusEnum) {
- webrtc::RtpEncodingParameters webrtc_encoding_parameters;
-
- {
- webrtc_encoding_parameters.dtx = webrtc::DtxStatus::DISABLED;
- blink::WebRTCRtpEncodingParameters encoding_parameters =
- GetWebRTCRtpEncodingParameters(webrtc_encoding_parameters);
- EXPECT_EQ(encoding_parameters.Dtx(), blink::WebRTCDtxStatus::Disabled);
- }
-
- {
- webrtc_encoding_parameters.dtx = webrtc::DtxStatus::ENABLED;
- blink::WebRTCRtpEncodingParameters encoding_parameters =
- GetWebRTCRtpEncodingParameters(webrtc_encoding_parameters);
- EXPECT_EQ(encoding_parameters.Dtx(), blink::WebRTCDtxStatus::Enabled);
- }
-}
-
-TEST(RTCRtpParametersTest, CheckDegradationPreferenceEnum) {
- webrtc::RtpParameters webrtc_parameters;
-
- {
- webrtc_parameters.degradation_preference =
- webrtc::DegradationPreference::MAINTAIN_FRAMERATE;
- blink::WebRTCRtpParameters parameters =
- GetWebRTCRtpParameters(webrtc_parameters);
- EXPECT_EQ(parameters.DegradationPreference(),
- blink::WebRTCDegradationPreference::MaintainFramerate);
- }
-
- {
- webrtc_parameters.degradation_preference =
- webrtc::DegradationPreference::MAINTAIN_RESOLUTION;
- blink::WebRTCRtpParameters parameters =
- GetWebRTCRtpParameters(webrtc_parameters);
- EXPECT_EQ(parameters.DegradationPreference(),
- blink::WebRTCDegradationPreference::MaintainResolution);
- }
-
- {
- webrtc_parameters.degradation_preference =
- webrtc::DegradationPreference::BALANCED;
- blink::WebRTCRtpParameters parameters =
- GetWebRTCRtpParameters(webrtc_parameters);
- EXPECT_EQ(parameters.DegradationPreference(),
- blink::WebRTCDegradationPreference::Balanced);
- }
-}
-
-TEST(RTCRtpParametersTest, CheckPriorityEnum) {
- webrtc::RtpEncodingParameters webrtc_encoding_parameters;
-
- {
- webrtc_encoding_parameters.bitrate_priority =
- webrtc::kDefaultBitratePriority / 2;
- blink::WebRTCRtpEncodingParameters encoding_parameters =
- GetWebRTCRtpEncodingParameters(webrtc_encoding_parameters);
- EXPECT_EQ(encoding_parameters.Priority(),
- blink::WebRTCPriorityType::VeryLow);
- }
-
- {
- webrtc_encoding_parameters.bitrate_priority =
- webrtc::kDefaultBitratePriority;
- blink::WebRTCRtpEncodingParameters encoding_parameters =
- GetWebRTCRtpEncodingParameters(webrtc_encoding_parameters);
- EXPECT_EQ(encoding_parameters.Priority(), blink::WebRTCPriorityType::Low);
- }
-
- {
- webrtc_encoding_parameters.bitrate_priority =
- webrtc::kDefaultBitratePriority * 2;
- blink::WebRTCRtpEncodingParameters encoding_parameters =
- GetWebRTCRtpEncodingParameters(webrtc_encoding_parameters);
- EXPECT_EQ(encoding_parameters.Priority(),
- blink::WebRTCPriorityType::Medium);
- }
-
- {
- webrtc_encoding_parameters.bitrate_priority =
- webrtc::kDefaultBitratePriority * 4;
- blink::WebRTCRtpEncodingParameters encoding_parameters =
- GetWebRTCRtpEncodingParameters(webrtc_encoding_parameters);
- EXPECT_EQ(encoding_parameters.Priority(), blink::WebRTCPriorityType::High);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h
index 5d0c6b743ed..29420ae5220 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h"
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc
index df886ddc560..528c8d26a15 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc
@@ -4,11 +4,11 @@
#include "content/renderer/media/webrtc/rtc_rtp_sender.h"
+#include <memory>
#include <utility>
#include "base/logging.h"
#include "content/renderer/media/webrtc/rtc_dtmf_sender_handler.h"
-#include "content/renderer/media/webrtc/rtc_rtp_parameters.h"
#include "content/renderer/media/webrtc/rtc_stats.h"
namespace content {
@@ -22,8 +22,16 @@ void OnReplaceTrackCompleted(blink::WebRTCVoidRequest request, bool result) {
if (result)
request.RequestSucceeded();
else
- request.RequestFailed(blink::WebRTCError(
- blink::WebRTCErrorType::kInvalidModification, blink::WebString()));
+ request.RequestFailed(
+ webrtc::RTCError(webrtc::RTCErrorType::INVALID_MODIFICATION));
+}
+
+void OnSetParametersCompleted(blink::WebRTCVoidRequest request,
+ webrtc::RTCError result) {
+ if (result.ok())
+ request.RequestSucceeded();
+ else
+ request.RequestFailed(result);
}
} // namespace
@@ -130,10 +138,44 @@ class RTCRtpSender::RTCRtpSenderInternal
return std::make_unique<RtcDtmfSenderHandler>(dtmf_sender);
}
- std::unique_ptr<blink::WebRTCRtpParameters> GetParameters() const {
- webrtc::RtpParameters parameters = webrtc_sender_->GetParameters();
- return std::make_unique<blink::WebRTCRtpParameters>(
- GetWebRTCRtpParameters(parameters));
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() {
+ parameters_ = webrtc_sender_->GetParameters();
+ return std::make_unique<webrtc::RtpParameters>(parameters_);
+ }
+
+ void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters> encodings,
+ webrtc::DegradationPreference degradation_preference,
+ base::OnceCallback<void(webrtc::RTCError)> callback) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+
+ webrtc::RtpParameters new_parameters = parameters_;
+
+ new_parameters.degradation_preference = degradation_preference;
+
+ for (std::size_t i = 0; i < new_parameters.encodings.size(); ++i) {
+ // Encodings have other parameters in the native layer that aren't exposed
+ // to the blink layer. So instead of copying the new struct over the old
+ // one, we copy the members one by one over the old struct, effectively
+ // patching the changes done by the user.
+ const auto& encoding = encodings[i];
+ new_parameters.encodings[i].codec_payload_type =
+ encoding.codec_payload_type;
+ new_parameters.encodings[i].dtx = encoding.dtx;
+ new_parameters.encodings[i].active = encoding.active;
+ new_parameters.encodings[i].bitrate_priority = encoding.bitrate_priority;
+ new_parameters.encodings[i].ptime = encoding.ptime;
+ new_parameters.encodings[i].max_bitrate_bps = encoding.max_bitrate_bps;
+ new_parameters.encodings[i].max_framerate = encoding.max_framerate;
+ new_parameters.encodings[i].rid = encoding.rid;
+ new_parameters.encodings[i].scale_resolution_down_by =
+ encoding.scale_resolution_down_by;
+ }
+
+ signaling_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpSender::RTCRtpSenderInternal::SetParametersOnSignalingThread,
+ this, std::move(new_parameters), std::move(callback)));
}
void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback> callback) {
@@ -195,6 +237,25 @@ class RTCRtpSender::RTCRtpSenderInternal
main_thread_, std::move(callback)));
}
+ void SetParametersOnSignalingThread(
+ webrtc::RtpParameters parameters,
+ base::OnceCallback<void(webrtc::RTCError)> callback) {
+ DCHECK(signaling_thread_->BelongsToCurrentThread());
+ webrtc::RTCError result = webrtc_sender_->SetParameters(parameters);
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpSender::RTCRtpSenderInternal::SetParametersCallback, this,
+ std::move(result), std::move(callback)));
+ }
+
+ void SetParametersCallback(
+ webrtc::RTCError result,
+ base::OnceCallback<void(webrtc::RTCError)> callback) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ std::move(callback).Run(std::move(result));
+ }
+
const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
@@ -208,6 +269,7 @@ class RTCRtpSender::RTCRtpSenderInternal
// sender's associated set of streams.
std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>>
stream_refs_;
+ webrtc::RtpParameters parameters_;
};
struct RTCRtpSender::RTCRtpSenderInternalTraits {
@@ -301,11 +363,19 @@ std::unique_ptr<blink::WebRTCDTMFSenderHandler> RTCRtpSender::GetDtmfSender()
return internal_->GetDtmfSender();
}
-std::unique_ptr<blink::WebRTCRtpParameters> RTCRtpSender::GetParameters()
- const {
+std::unique_ptr<webrtc::RtpParameters> RTCRtpSender::GetParameters() const {
return internal_->GetParameters();
}
+void RTCRtpSender::SetParameters(
+ blink::WebVector<webrtc::RtpEncodingParameters> encodings,
+ webrtc::DegradationPreference degradation_preference,
+ blink::WebRTCVoidRequest request) {
+ internal_->SetParameters(
+ std::move(encodings), degradation_preference,
+ base::BindOnce(&OnSetParametersCompleted, std::move(request)));
+}
+
void RTCRtpSender::GetStats(
std::unique_ptr<blink::WebRTCStatsReportCallback> callback) {
internal_->GetStats(std::move(callback));
diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h
index f601e352184..990b21fb64c 100644
--- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h
+++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h"
@@ -62,7 +63,10 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender {
blink::WebRTCVoidRequest request) override;
std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender()
const override;
- std::unique_ptr<blink::WebRTCRtpParameters> GetParameters() const override;
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() const override;
+ void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters>,
+ webrtc::DegradationPreference,
+ blink::WebRTCVoidRequest) override;
void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override;
webrtc::RtpSenderInterface* webrtc_sender() const;
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder.cc
index f5ce84aad37..6e9f6ada346 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder.cc
@@ -13,6 +13,7 @@
#include "base/numerics/safe_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/task_runner_util.h"
+#include "build/build_config.h"
#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/bind_to_current_loop.h"
@@ -157,15 +158,24 @@ int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings,
}
int32_t RTCVideoDecoder::Decode(
- const webrtc::EncodedImage& inputImage,
- bool missingFrames,
- const webrtc::RTPFragmentationHeader* /*fragmentation*/,
- const webrtc::CodecSpecificInfo* /*codecSpecificInfo*/,
- int64_t /*renderTimeMs*/) {
+ const webrtc::EncodedImage& input_image,
+ bool missing_frames,
+ const webrtc::CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) {
DVLOG(3) << "Decode";
+ DCHECK(!codec_specific_info ||
+ video_codec_type_ == codec_specific_info->codecType);
- base::AutoLock auto_lock(lock_);
+ // Hardware VP9 decoders don't handle more than one spatial layer. Fall back
+ // to software decoding. See https://crbug.com/webrtc/9304,
+ // https://crbug.com/webrtc/9518.
+ if (video_codec_type_ == webrtc::kVideoCodecVP9 && codec_specific_info &&
+ codec_specific_info->codecSpecific.VP9.ss_data_available &&
+ codec_specific_info->codecSpecific.VP9.num_spatial_layers > 1) {
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
+ base::AutoLock auto_lock(lock_);
if (state_ == UNINITIALIZED || !decode_complete_callback_) {
LOG(ERROR) << "The decoder has not initialized.";
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
@@ -181,7 +191,7 @@ int32_t RTCVideoDecoder::Decode(
return WEBRTC_VIDEO_CODEC_ERROR;
}
- if (missingFrames || !inputImage._completeFrame) {
+ if (missing_frames || !input_image._completeFrame) {
DLOG(ERROR) << "Missing or incomplete frames.";
// Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames.
// Return an error to request a key frame.
@@ -199,8 +209,8 @@ int32_t RTCVideoDecoder::Decode(
#endif
bool need_to_reset_for_midstream_resize = false;
- const gfx::Size new_frame_size(inputImage._encodedWidth,
- inputImage._encodedHeight);
+ const gfx::Size new_frame_size(input_image._encodedWidth,
+ input_image._encodedHeight);
if (!new_frame_size.IsEmpty() && new_frame_size != frame_size_) {
DVLOG(2) << "Got new size=" << new_frame_size.ToString();
@@ -231,10 +241,8 @@ int32_t RTCVideoDecoder::Decode(
}
// Create buffer metadata.
- BufferData buffer_data(next_bitstream_buffer_id_,
- inputImage._timeStamp,
- inputImage._length,
- gfx::Rect(frame_size_));
+ BufferData buffer_data(next_bitstream_buffer_id_, input_image._timeStamp,
+ input_image._length, gfx::Rect(frame_size_));
// Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & ID_LAST;
@@ -243,9 +251,9 @@ int32_t RTCVideoDecoder::Decode(
// immediately. Otherwise, save the buffer in the queue for later decode.
std::unique_ptr<base::SharedMemory> shm_buffer;
if (!need_to_reset_for_midstream_resize && pending_buffers_.empty())
- shm_buffer = GetSHM_Locked(inputImage._length);
+ shm_buffer = GetSHM_Locked(input_image._length);
if (!shm_buffer) {
- if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) {
+ if (!SaveToPendingBuffers_Locked(input_image, buffer_data)) {
// We have exceeded the pending buffers count, we are severely behind.
// Since we are returning ERROR, WebRTC will not be interested in the
// remaining buffers, and will provide us with a new keyframe instead.
@@ -264,7 +272,7 @@ int32_t RTCVideoDecoder::Decode(
return WEBRTC_VIDEO_CODEC_OK;
}
- SaveToDecodeBuffers_Locked(inputImage, std::move(shm_buffer), buffer_data);
+ SaveToDecodeBuffers_Locked(input_image, std::move(shm_buffer), buffer_data);
factories_->GetTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&RTCVideoDecoder::RequestBufferDecode,
weak_factory_.GetWeakPtr()));
@@ -470,8 +478,8 @@ scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY,
picture.allow_overlay());
#if defined(OS_ANDROID)
- frame->metadata()->SetBoolean(media::VideoFrameMetadata::SURFACE_TEXTURE,
- picture.surface_texture());
+ frame->metadata()->SetBoolean(media::VideoFrameMetadata::TEXTURE_OWNER,
+ picture.texture_owner());
frame->metadata()->SetBoolean(
media::VideoFrameMetadata::WANTS_PROMOTION_HINT,
picture.wants_promotion_hint());
@@ -536,6 +544,10 @@ void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
++vda_error_counter_;
}
+const char* RTCVideoDecoder::ImplementationName() const {
+ return "ExternalDecoder";
+}
+
void RTCVideoDecoder::RequestBufferDecode() {
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
if (!vda_)
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder.h b/chromium/content/renderer/media/webrtc/rtc_video_decoder.h
index 783c62b727e..4db50b3bff3 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder.h
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder.h
@@ -70,9 +70,8 @@ class CONTENT_EXPORT RTCVideoDecoder
// Called on WebRTC DecodingThread.
int32_t Decode(const webrtc::EncodedImage& inputImage,
bool missingFrames,
- const webrtc::RTPFragmentationHeader* fragmentation,
- const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL,
- int64_t renderTimeMs = -1) override;
+ const webrtc::CodecSpecificInfo* codecSpecificInfo,
+ int64_t renderTimeMs) override;
// Called on WebRTC DecodingThread.
int32_t RegisterDecodeCompleteCallback(
webrtc::DecodedImageCallback* callback) override;
@@ -92,6 +91,7 @@ class CONTENT_EXPORT RTCVideoDecoder
void NotifyFlushDone() override;
void NotifyResetDone() override;
void NotifyError(media::VideoDecodeAccelerator::Error error) override;
+ const char* ImplementationName() const override;
private:
// Metadata of a bitstream buffer.
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc
index cd52471379d..050c9f61d84 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc
@@ -208,7 +208,7 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
CreateDecoder(webrtc::kVideoCodecVP8);
webrtc::EncodedImage input_image;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, 0));
}
TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
@@ -217,7 +217,7 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
webrtc::EncodedImage input_image;
input_image._completeFrame = false;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, 0));
}
TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
@@ -228,7 +228,7 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
bool missingFrames = true;
EXPECT_EQ(
WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, missingFrames, nullptr, 0));
}
TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
@@ -336,7 +336,7 @@ TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForNotifyError) {
input_image._frameType = webrtc::kVideoFrameDelta;
input_image._length = kMinResolutionWidth * kMaxResolutionHeight;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, 0));
RunUntilIdle();
// Notify the decoder about a platform error.
@@ -347,13 +347,13 @@ TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForNotifyError) {
// Expect decode call to reset decoder, and set up a new VDA to track it.
SetUpResetVDA();
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, 0));
EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
// Decoder expects a frame with size after reset, so drops any other frames.
// However, we should still increment the error counter.
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, 0));
EXPECT_EQ(2, rtc_decoder_->GetVDAErrorCounterForTesting());
}
@@ -379,7 +379,7 @@ TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForRunningOutOfPendingBuffers) {
uint32_t i = 0;
while (i++ < kMaxNumDecodeRequests) {
const int32_t result =
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0);
+ rtc_decoder_->Decode(input_image, false, nullptr, 0);
RunUntilIdle();
if (result == WEBRTC_VIDEO_CODEC_OK)
EXPECT_EQ(0, rtc_decoder_->GetVDAErrorCounterForTesting());
@@ -411,7 +411,7 @@ TEST_P(RTCVideoDecoderTest, Reinitialize) {
input_image._length = sizeof(buffer);
EXPECT_CALL(*mock_vda_, Decode(_)).Times(1);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, 0));
RunUntilIdle();
// InitDecode and Decode after Release should succeed.
@@ -419,7 +419,7 @@ TEST_P(RTCVideoDecoderTest, Reinitialize) {
rtc_decoder_->Release();
Initialize();
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
- rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, 0));
}
INSTANTIATE_TEST_CASE_P(CodecProfiles,
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
index 43449e5f758..bfa722c5fc2 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc
@@ -6,6 +6,7 @@
#include <string.h>
+#include <algorithm>
#include <memory>
#include <vector>
@@ -27,6 +28,7 @@
#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/bitstream_buffer.h"
+#include "media/base/video_bitrate_allocation.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "media/video/gpu_video_accelerator_factories.h"
@@ -139,7 +141,8 @@ class RTCVideoEncoder::Impl
void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id);
// Request encoding parameter change for the underlying encoder.
- void RequestEncodingParametersChange(uint32_t bitrate, uint32_t framerate);
+ void RequestEncodingParametersChange(webrtc::VideoBitrateAllocation bitrate,
+ uint32_t framerate);
void RegisterEncodeCompleteCallback(base::WaitableEvent* async_waiter,
int32_t* async_retval,
@@ -154,6 +157,8 @@ class RTCVideoEncoder::Impl
webrtc::VideoCodecType video_codec_type() const { return video_codec_type_; }
+ static const char* ImplementationName() { return "ExternalEncoder"; }
+
// media::VideoEncodeAccelerator::Client implementation.
void RequireBitstreamBuffers(unsigned int input_count,
const gfx::Size& input_coded_size,
@@ -388,17 +393,41 @@ void RTCVideoEncoder::Impl::UseOutputBitstreamBufferId(
}
void RTCVideoEncoder::Impl::RequestEncodingParametersChange(
- uint32_t bitrate,
+ webrtc::VideoBitrateAllocation bitrate,
uint32_t framerate) {
- DVLOG(3) << __func__ << " bitrate=" << bitrate << ", framerate=" << framerate;
+ DVLOG(3) << __func__ << " bitrate=" << bitrate.ToString()
+ << ", framerate=" << framerate;
DCHECK(thread_checker_.CalledOnValidThread());
- // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
- if (IsBitrateTooHigh(bitrate))
- return;
+ // This is a workaround to zero being temporarily provided, as part of the
+ // initial setup, by WebRTC.
+ if (bitrate.get_sum_bps() == 0) {
+ bitrate.SetBitrate(0, 0, 1);
+ }
+ framerate = std::max(1u, framerate);
- if (video_encoder_)
- video_encoder_->RequestEncodingParametersChange(bitrate * 1000, framerate);
+ if (video_encoder_) {
+ media::VideoBitrateAllocation allocation;
+ for (size_t spatial_id = 0;
+ spatial_id < media::VideoBitrateAllocation::kMaxSpatialLayers;
+ ++spatial_id) {
+ for (size_t temporal_id = 0;
+ temporal_id < media::VideoBitrateAllocation::kMaxTemporalLayers;
+ ++temporal_id) {
+ // TODO(sprang): Clean this up if/when webrtc struct moves to int.
+ uint32_t layer_bitrate = bitrate.GetBitrate(spatial_id, temporal_id);
+ RTC_CHECK_LE(layer_bitrate,
+ static_cast<uint32_t>(std::numeric_limits<int>::max()));
+ if (!allocation.SetBitrate(spatial_id, temporal_id, layer_bitrate)) {
+ LOG(WARNING) << "Overflow in bitrate allocation: "
+ << bitrate.ToString();
+ break;
+ }
+ }
+ }
+ DCHECK_EQ(allocation.GetSumBps(), static_cast<int>(bitrate.get_sum_bps()));
+ video_encoder_->RequestEncodingParametersChange(allocation, framerate);
+ }
}
void RTCVideoEncoder::Impl::Destroy(base::WaitableEvent* async_waiter) {
@@ -767,6 +796,7 @@ void RTCVideoEncoder::Impl::ReturnEncodedImage(
webrtc::CodecSpecificInfo info;
memset(&info, 0, sizeof(info));
info.codecType = video_codec_type_;
+ info.codec_name = ImplementationName();
if (video_codec_type_ == webrtc::kVideoCodecVP8) {
info.codecSpecific.VP8.pictureId = picture_id;
info.codecSpecific.VP8.tl0PicIdx = -1;
@@ -913,8 +943,10 @@ int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss,
return WEBRTC_VIDEO_CODEC_OK;
}
-int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
- DVLOG(3) << __func__ << " new_bit_rate=" << new_bit_rate
+int32_t RTCVideoEncoder::SetRateAllocation(
+ const webrtc::VideoBitrateAllocation& allocation,
+ uint32_t frame_rate) {
+ DVLOG(3) << __func__ << " new_bit_rate=" << allocation.ToString()
<< ", frame_rate=" << frame_rate;
if (!impl_.get()) {
DVLOG(3) << "Encoder is not initialized";
@@ -930,7 +962,7 @@ int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
gpu_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&RTCVideoEncoder::Impl::RequestEncodingParametersChange,
- impl_, new_bit_rate, frame_rate));
+ impl_, allocation, frame_rate));
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -938,4 +970,8 @@ bool RTCVideoEncoder::SupportsNativeHandle() const {
return true;
}
+const char* RTCVideoEncoder::ImplementationName() const {
+ return RTCVideoEncoder::Impl::ImplementationName();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder.h b/chromium/content/renderer/media/webrtc/rtc_video_encoder.h
index 3f1d98f348c..57ffd316a28 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_encoder.h
+++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder.h
@@ -18,6 +18,7 @@
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "media/base/video_decoder_config.h"
+#include "third_party/webrtc/api/video/video_bitrate_allocation.h"
#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
#include "ui/gfx/geometry/size.h"
@@ -57,8 +58,10 @@ class CONTENT_EXPORT RTCVideoEncoder : public webrtc::VideoEncoder {
webrtc::EncodedImageCallback* callback) override;
int32_t Release() override;
int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
- int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) override;
+ int32_t SetRateAllocation(const webrtc::VideoBitrateAllocation& allocation,
+ uint32_t framerate) override;
bool SupportsNativeHandle() const override;
+ const char* ImplementationName() const override;
private:
class Impl;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc
index 0d91e4518b1..f0e7046d201 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.cc
@@ -120,6 +120,16 @@ void WebRtcAudioDeviceImpl::AudioRendererThreadStopped() {
sink->OnPlayoutDataSourceChanged();
}
+void WebRtcAudioDeviceImpl::SetOutputDeviceForAec(
+ const std::string& output_device_id) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ output_device_id_for_aec_ = output_device_id;
+ base::AutoLock lock(lock_);
+ for (auto* capturer : capturers_) {
+ capturer->SetOutputDeviceForAec(output_device_id);
+ }
+}
+
int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback(
webrtc::AudioTransport* audio_callback) {
DVLOG(1) << "WebRtcAudioDeviceImpl::RegisterAudioCallback()";
@@ -390,6 +400,7 @@ void WebRtcAudioDeviceImpl::AddAudioCapturer(
base::AutoLock auto_lock(lock_);
DCHECK(!base::ContainsValue(capturers_, capturer));
capturers_.push_back(capturer);
+ capturer->SetOutputDeviceForAec(output_device_id_for_aec_);
}
void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h
index 3348f3747cd..9a6d343cf15 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_device_impl.h
@@ -64,6 +64,9 @@ class WebRtcAudioRendererSource {
// Otherwise a race may occur.
virtual void AudioRendererThreadStopped() = 0;
+ // Callback to notify the client of the output device the renderer is using.
+ virtual void SetOutputDeviceForAec(const std::string& output_device_id) = 0;
+
protected:
virtual ~WebRtcAudioRendererSource() {}
};
@@ -199,6 +202,7 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl : public WebRtcAudioDeviceNotImpl,
// Called on the main render thread.
void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) override;
void AudioRendererThreadStopped() override;
+ void SetOutputDeviceForAec(const std::string& output_device_id) override;
// WebRtcPlayoutDataSource implementation.
void AddPlayoutSink(WebRtcPlayoutDataSource::Sink* sink) override;
@@ -245,6 +249,9 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl : public WebRtcAudioDeviceNotImpl,
// It is only accessed by the audio render thread.
std::vector<int16_t> render_buffer_;
+ // The output device used for echo cancellation
+ std::string output_device_id_for_aec_;
+
DISALLOW_COPY_AND_ASSIGN(WebRtcAudioDeviceImpl);
};
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
index 6cd303ffbb3..b18f49d21f8 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc
@@ -39,7 +39,6 @@ const media::AudioParameters::Format kFormat =
media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO;
const int kChannels = 2;
-const int kBitsPerSample = 16;
// Used for UMA histograms.
const int kRenderTimeHistogramMinMicroseconds = 100;
@@ -133,10 +132,9 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
void SwitchOutputDevice(
const std::string& device_id,
- const url::Origin& security_origin,
const media::OutputDeviceStatusCB& callback) override {
DCHECK(thread_checker_.CalledOnValidThread());
- return delegate_->SwitchOutputDevice(device_id, security_origin, callback);
+ return delegate_->SwitchOutputDevice(device_id, callback);
}
base::TimeDelta GetCurrentRenderTime() const override {
@@ -166,8 +164,7 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(
const blink::WebMediaStream& media_stream,
int source_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin)
+ const std::string& device_id)
: state_(UNINITIALIZED),
source_render_frame_id_(source_render_frame_id),
session_id_(session_id),
@@ -176,9 +173,8 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(
source_(nullptr),
play_ref_count_(0),
start_ref_count_(0),
- sink_params_(kFormat, kChannelLayout, 0, kBitsPerSample, 0),
- output_device_id_(device_id),
- security_origin_(security_origin) {
+ sink_params_(kFormat, kChannelLayout, 0, 0),
+ output_device_id_(device_id) {
WebRtcLogMessage(base::StringPrintf(
"WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i",
source_render_frame_id, session_id, sink_params_.effects()));
@@ -203,7 +199,7 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
sink_ = AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_, session_id_,
- output_device_id_, security_origin_);
+ output_device_id_);
if (sink_->GetOutputDeviceInfo().device_status() !=
media::OUTPUT_DEVICE_STATUS_OK) {
@@ -221,6 +217,7 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
// User must call Play() before any audio can be heard.
state_ = PAUSED;
}
+ source_->SetOutputDeviceForAec(output_device_id_);
sink_->Start();
sink_->Play(); // Not all the sinks play on start.
@@ -374,21 +371,24 @@ bool WebRtcAudioRenderer::IsLocalRenderer() const {
void WebRtcAudioRenderer::SwitchOutputDevice(
const std::string& device_id,
- const url::Origin& security_origin,
const media::OutputDeviceStatusCB& callback) {
DVLOG(1) << "WebRtcAudioRenderer::SwitchOutputDevice()";
DCHECK(thread_checker_.CalledOnValidThread());
+ if (!source_) {
+ callback.Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
+ return;
+ }
+
DCHECK_GE(session_id_, 0);
{
base::AutoLock auto_lock(lock_);
- DCHECK(source_);
DCHECK_NE(state_, UNINITIALIZED);
}
scoped_refptr<media::AudioRendererSink> new_sink =
AudioDeviceFactory::NewAudioRendererSink(
AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_,
- session_id_, device_id, security_origin);
+ session_id_, device_id);
media::OutputDeviceStatus status =
new_sink->GetOutputDeviceInfo().device_status();
if (status != media::OUTPUT_DEVICE_STATUS_OK) {
@@ -403,11 +403,11 @@ void WebRtcAudioRenderer::SwitchOutputDevice(
sink_->Stop();
sink_ = new_sink;
output_device_id_ = device_id;
- security_origin_ = security_origin;
{
base::AutoLock auto_lock(lock_);
source_->AudioRendererThreadStopped();
}
+ source_->SetOutputDeviceForAec(output_device_id_);
PrepareSink();
sink_->Start();
sink_->Play(); // Not all the sinks play on start.
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.h b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.h
index 9d42e00bc78..7983fd7217e 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.h
@@ -83,8 +83,7 @@ class CONTENT_EXPORT WebRtcAudioRenderer
const blink::WebMediaStream& media_stream,
int source_render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
+ const std::string& device_id);
// Initialize function called by clients like WebRtcAudioDeviceImpl.
// Stop() has to be called before |source| is deleted.
@@ -126,7 +125,6 @@ class CONTENT_EXPORT WebRtcAudioRenderer
base::TimeDelta GetCurrentRenderTime() const override;
bool IsLocalRenderer() const override;
void SwitchOutputDevice(const std::string& device_id,
- const url::Origin& security_origin,
const media::OutputDeviceStatusCB& callback) override;
// Called when an audio renderer, either the main or a proxy, starts playing.
@@ -250,7 +248,6 @@ class CONTENT_EXPORT WebRtcAudioRenderer
// The preferred device id of the output device or empty for the default
// output device. Can change as a result of a SetSinkId() call.
std::string output_device_id_;
- url::Origin security_origin_;
// Maps audio sources to a list of active audio renderers.
// Pointers to PlayingState objects are only kept in this map while the
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
index be938b0180d..7e886d27945 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
@@ -41,13 +41,14 @@ const char kInvalidOutputDeviceId[] = "invalid-device";
class MockAudioRendererSource : public WebRtcAudioRendererSource {
public:
MockAudioRendererSource() {}
- virtual ~MockAudioRendererSource() {}
+ ~MockAudioRendererSource() override {}
MOCK_METHOD4(RenderData, void(media::AudioBus* audio_bus,
int sample_rate,
int audio_delay_milliseconds,
base::TimeDelta* current_time));
MOCK_METHOD1(RemoveAudioRenderer, void(WebRtcAudioRenderer* renderer));
MOCK_METHOD0(AudioRendererThreadStopped, void());
+ MOCK_METHOD1(SetOutputDeviceForAec, void(const std::string&));
};
} // namespace
@@ -73,38 +74,34 @@ class WebRtcAudioRendererTest : public testing::Test,
void SetupRenderer(const std::string& device_id) {
renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_,
- 1, 1, device_id, url::Origin());
- EXPECT_CALL(
- *this, MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
- _, device_id, _));
+ 1, 1, device_id);
+ EXPECT_CALL(*this, MockCreateAudioRendererSink(
+ AudioDeviceFactory::kSourceWebRtc, _, _, device_id));
+ EXPECT_CALL(*source_.get(), SetOutputDeviceForAec(device_id));
EXPECT_TRUE(renderer_->Initialize(source_.get()));
renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_);
}
MOCK_METHOD1(CreateAudioCapturerSource,
scoped_refptr<media::AudioCapturerSource>(int));
- MOCK_METHOD4(CreateFinalAudioRendererSink,
+ MOCK_METHOD3(CreateFinalAudioRendererSink,
scoped_refptr<media::AudioRendererSink>(int,
int,
- const std::string&,
- const url::Origin&));
- MOCK_METHOD5(
+ const std::string&));
+ MOCK_METHOD4(
CreateSwitchableAudioRendererSink,
scoped_refptr<media::SwitchableAudioRendererSink>(SourceType,
int,
int,
- const std::string&,
- const url::Origin&));
- MOCK_METHOD5(
- MockCreateAudioRendererSink,
- void(SourceType, int, int, const std::string&, const url::Origin&));
+ const std::string&));
+ MOCK_METHOD4(MockCreateAudioRendererSink,
+ void(SourceType, int, int, const std::string&));
scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
SourceType source_type,
int render_frame_id,
int session_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
+ const std::string& device_id) override {
mock_sink_ = new media::MockAudioRendererSink(
device_id,
device_id == kInvalidOutputDeviceId
@@ -112,7 +109,7 @@ class WebRtcAudioRendererTest : public testing::Test,
: media::OUTPUT_DEVICE_STATUS_OK,
media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
- kHardwareSampleRate, 16, kHardwareBufferSize));
+ kHardwareSampleRate, kHardwareBufferSize));
if (device_id != kInvalidOutputDeviceId) {
EXPECT_CALL(*mock_sink_.get(), Start());
@@ -122,7 +119,7 @@ class WebRtcAudioRendererTest : public testing::Test,
}
MockCreateAudioRendererSink(source_type, render_frame_id, session_id,
- device_id, security_origin);
+ device_id);
return mock_sink_;
}
@@ -240,12 +237,13 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDevice) {
EXPECT_CALL(*mock_sink_.get(), Stop());
EXPECT_CALL(*this,
MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
- _, kOtherOutputDeviceId, _));
+ _, kOtherOutputDeviceId));
EXPECT_CALL(*source_.get(), AudioRendererThreadStopped());
+ EXPECT_CALL(*source_.get(), SetOutputDeviceForAec(kOtherOutputDeviceId));
EXPECT_CALL(*this, MockSwitchDeviceCallback(media::OUTPUT_DEVICE_STATUS_OK));
base::RunLoop loop;
renderer_proxy_->SwitchOutputDevice(
- kOtherOutputDeviceId, url::Origin(),
+ kOtherOutputDeviceId,
base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback,
base::Unretained(this), &loop));
loop.Run();
@@ -266,12 +264,12 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceInvalidDevice) {
EXPECT_CALL(*this,
MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
- _, kInvalidOutputDeviceId, _));
+ _, kInvalidOutputDeviceId));
EXPECT_CALL(*this, MockSwitchDeviceCallback(
media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
base::RunLoop loop;
renderer_proxy_->SwitchOutputDevice(
- kInvalidOutputDeviceId, url::Origin(),
+ kInvalidOutputDeviceId,
base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback,
base::Unretained(this), &loop));
loop.Run();
@@ -285,11 +283,11 @@ TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceInvalidDevice) {
TEST_F(WebRtcAudioRendererTest, InitializeWithInvalidDevice) {
renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_, 1,
- 1, kInvalidOutputDeviceId, url::Origin());
+ 1, kInvalidOutputDeviceId);
EXPECT_CALL(*this,
MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
- _, kInvalidOutputDeviceId, _));
+ _, kInvalidOutputDeviceId));
EXPECT_FALSE(renderer_->Initialize(source_.get()));
@@ -299,4 +297,22 @@ TEST_F(WebRtcAudioRendererTest, InitializeWithInvalidDevice) {
mock_sink_->GetOutputDeviceInfo().device_id());
}
+TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceStoppedSource) {
+ SetupRenderer(kDefaultOutputDeviceId);
+ auto original_sink = mock_sink_;
+ renderer_proxy_->Start();
+
+ EXPECT_CALL(*original_sink.get(), Stop());
+ EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
+ EXPECT_CALL(*this, MockSwitchDeviceCallback(
+ media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
+ base::RunLoop loop;
+ renderer_proxy_->Stop();
+ renderer_proxy_->SwitchOutputDevice(
+ kInvalidOutputDeviceId,
+ base::BindRepeating(&WebRtcAudioRendererTest::SwitchDeviceCallback,
+ base::Unretained(this), &loop));
+ loop.Run();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
index e9e9147c765..49c6388ec5a 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h"
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc
index dcf3844ecd6..b445ce8c893 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc
@@ -77,8 +77,8 @@ WebRtcMediaStreamAdapterMap::WebRtcMediaStreamAdapterMap(
}
WebRtcMediaStreamAdapterMap::~WebRtcMediaStreamAdapterMap() {
- DCHECK(main_thread_->BelongsToCurrentThread());
DCHECK(local_stream_adapters_.empty());
+ DCHECK(remote_stream_adapters_.empty());
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
index babc38f4ed7..ec8ffdca628 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
@@ -88,7 +88,7 @@ class LocalWebRtcMediaStreamAdapterTest : public WebRtcMediaStreamAdapterTest {
audio_tracks[0].Initialize(blink::WebString::FromUTF8(audio_track_id),
audio_source);
EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(),
- Initialize(_, _, -1));
+ Initialize(_, _));
EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(),
SetAutomaticGainControl(true));
EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), Start());
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc
index 165c22fd603..e03d1719ee0 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc
@@ -69,7 +69,6 @@ WebRtcMediaStreamTrackAdapter::WebRtcMediaStreamTrackAdapter(
}
WebRtcMediaStreamTrackAdapter::~WebRtcMediaStreamTrackAdapter() {
- DCHECK(main_thread_->BelongsToCurrentThread());
DCHECK(!remote_track_can_complete_initialization_.IsSignaled());
DCHECK(!is_initialized_);
}
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc
index 3504e3d6817..8c5fd3e426f 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc
@@ -215,4 +215,99 @@ TEST_F(WebRtcMediaStreamTrackAdapterMapTest, GetMissingRemoteTrackAdapter) {
EXPECT_EQ(nullptr, map_->GetRemoteTrackAdapter(webrtc_track.get()));
}
+// Continuously calls GetOrCreateLocalTrackAdapter() on the main thread and
+// GetOrCreateRemoteTrackAdapter() on the signaling thread hoping to hit
+// deadlocks if the operations were to synchronize with the other thread while
+// holding the lock.
+//
+// Note that this deadlock has been notoriously difficult to reproduce. This
+// test is added as an attempt to guard against this type of regression, but do
+// not trust that if this test passes there is no risk of deadlock.
+class WebRtcMediaStreamTrackAdapterMapStressTest
+ : public WebRtcMediaStreamTrackAdapterMapTest {
+ public:
+ WebRtcMediaStreamTrackAdapterMapStressTest()
+ : WebRtcMediaStreamTrackAdapterMapTest(), remaining_iterations_(0u) {}
+
+ void RunStressTest(size_t iterations) {
+ base::RunLoop run_loop;
+ remaining_iterations_ = iterations;
+ PostSignalingThreadLoop();
+ MainThreadLoop(&run_loop);
+ run_loop.Run();
+ // The run loop ensures all operations have began executing, but does not
+ // guarantee that all of them are complete, i.e. that track adapters have
+ // been fully initialized and subequently disposed. For that we need to run
+ // until idle or else we may tear down the test prematurely.
+ RunMessageLoopsUntilIdle();
+ }
+
+ void MainThreadLoop(base::RunLoop* run_loop) {
+ for (size_t i = 0u; i < 5u; ++i) {
+ map_->GetOrCreateLocalTrackAdapter(CreateLocalTrack("local_track_id"));
+ }
+ if (--remaining_iterations_ > 0) {
+ PostSignalingThreadLoop();
+ PostMainThreadLoop(run_loop);
+ } else {
+ // We are now done, but there may still be operations pending to execute
+ // on signaling thread so we perform Quit() in a post to the signaling
+ // thread. This ensures that Quit() is called after all operations have
+ // began executing (but does not guarantee that all operations have
+ // completed).
+ signaling_thread()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapterMapStressTest::
+ QuitRunLoopOnSignalingThread,
+ base::Unretained(this), base::Unretained(run_loop)));
+ }
+ }
+
+ void PostMainThreadLoop(base::RunLoop* run_loop) {
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterMapStressTest::MainThreadLoop,
+ base::Unretained(this), base::Unretained(run_loop)));
+ }
+
+ void SignalingThreadLoop() {
+ std::vector<std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>
+ track_refs;
+ for (size_t i = 0u; i < 5u; ++i) {
+ track_refs.push_back(map_->GetOrCreateRemoteTrackAdapter(
+ MockWebRtcAudioTrack::Create("remote_track_id")));
+ }
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapterMapStressTest::
+ DestroyAdapterRefsOnMainThread,
+ base::Unretained(this), std::move(track_refs)));
+ }
+
+ void PostSignalingThreadLoop() {
+ signaling_thread()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterMapStressTest::SignalingThreadLoop,
+ base::Unretained(this)));
+ }
+
+ void DestroyAdapterRefsOnMainThread(
+ std::vector<std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>
+ track_refs) {}
+
+ void QuitRunLoopOnSignalingThread(base::RunLoop* run_loop) {
+ run_loop->Quit();
+ }
+
+ private:
+ size_t remaining_iterations_;
+};
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapStressTest, StressTest) {
+ const size_t kNumStressTestIterations = 1000u;
+ RunStressTest(kNumStressTestIterations);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
index 5785a4d3c33..a59e3c693ac 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
@@ -4,13 +4,14 @@
#include "content/renderer/media/webrtc_local_audio_source_provider.h"
+#include <string>
+
#include "base/logging.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/media/audio_device_factory.h"
#include "media/base/audio_fifo.h"
#include "media/base/audio_parameters.h"
#include "third_party/blink/public/platform/web_audio_source_provider_client.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/web/web_local_frame.h"
using blink::WebVector;
@@ -39,12 +40,11 @@ WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider(
RenderFrame* const render_frame = RenderFrame::FromWebFrame(web_frame);
if (render_frame) {
int sample_rate = AudioDeviceFactory::GetOutputDeviceInfo(
- render_frame->GetRoutingID(), 0, std::string(),
- web_frame->GetSecurityOrigin())
+ render_frame->GetRoutingID(), 0, std::string())
.output_params()
.sample_rate();
sink_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, sample_rate, 16,
+ media::CHANNEL_LAYOUT_STEREO, sample_rate,
kWebAudioRenderBufferSize);
}
// Connect the source provider to the track as a sink.
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
index d318d41ac61..bb0b138ac19 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
@@ -20,10 +20,10 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test {
protected:
void SetUp() override {
source_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, 48000, 16, 480);
+ media::CHANNEL_LAYOUT_MONO, 48000, 480);
sink_params_.Reset(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 44100, 16,
+ media::CHANNEL_LAYOUT_STEREO, 44100,
WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize);
sink_bus_ = media::AudioBus::Create(sink_params_);
blink::WebMediaStreamSource audio_source;
diff --git a/chromium/content/renderer/media/webrtc_logging_noop.cc b/chromium/content/renderer/media/webrtc_logging_noop.cc
deleted file mode 100644
index 00bfdefbe3b..00000000000
--- a/chromium/content/renderer/media/webrtc_logging_noop.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 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/renderer/media/webrtc_logging.h"
-
-namespace content {
-
-void WebRtcLogMessage(const std::string& message) {}
-
-} // namespace content
diff --git a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc b/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc
index cb0b8e983e1..c2d9031674a 100644
--- a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc
+++ b/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc
@@ -20,12 +20,12 @@
#include "content/renderer/media/webrtc/webrtc_uma_histograms.h"
#include "content/renderer/render_thread_impl.h"
#include "media/base/limits.h"
-#include "skia/ext/texture_handle.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/gpu/GrBackendSurface.h"
using media::VideoFrame;
@@ -62,12 +62,15 @@ class VideoCapturerSource : public media::VideoCapturerSource {
const VideoCaptureDeliverFrameCB& frame_callback,
const RunningCallback& running_callback) override {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
- canvas_handler_->StartVideoCapture(params, frame_callback,
- running_callback);
+ if (canvas_handler_.get()) {
+ canvas_handler_->StartVideoCapture(params, frame_callback,
+ running_callback);
+ }
}
void RequestRefreshFrame() override {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
- canvas_handler_->RequestRefreshFrame();
+ if (canvas_handler_.get())
+ canvas_handler_->RequestRefreshFrame();
}
void StopCapture() override {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
@@ -80,8 +83,10 @@ class VideoCapturerSource : public media::VideoCapturerSource {
const float frame_rate_;
// Bound to Main Render thread.
base::ThreadChecker main_render_thread_checker_;
- // CanvasCaptureHandler is owned by CanvasDrawListener in blink and might be
- // destroyed before StopCapture() call.
+ // CanvasCaptureHandler is owned by CanvasDrawListener in blink. It is
+ // guaranteed to be destroyed on Main Render thread and it would happen
+ // independently of this class. Therefore, WeakPtr should always be checked
+ // before use.
base::WeakPtr<CanvasCaptureHandler> canvas_handler_;
};
@@ -280,12 +285,15 @@ void CanvasCaptureHandler::ReadARGBPixelsAsync(
return;
}
GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
- const GrGLTextureInfo* texture_info = skia::GrBackendObjectToGrGLTextureInfo(
- image->getTextureHandle(true, &surface_origin));
- DCHECK(texture_info);
+ GrBackendTexture backend_texture =
+ image->getBackendTexture(true, &surface_origin);
+ DCHECK(backend_texture.isValid());
+ GrGLTextureInfo texture_info;
+ const bool result = backend_texture.getGLTextureInfo(&texture_info);
+ DCHECK(result);
DCHECK(context_provider->GetGLHelper());
context_provider->GetGLHelper()->ReadbackTextureAsync(
- texture_info->fID, image_size,
+ texture_info.fID, image_size,
temp_argb_frame->visible_data(VideoFrame::kARGBPlane), kN32_SkColorType,
base::Bind(&CanvasCaptureHandler::OnARGBPixelsReadAsync,
weak_ptr_factory_.GetWeakPtr(), image, temp_argb_frame,
@@ -308,14 +316,17 @@ void CanvasCaptureHandler::ReadYUVPixelsAsync(
}
GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin;
- const GrGLTextureInfo* texture_info = skia::GrBackendObjectToGrGLTextureInfo(
- image->getTextureHandle(true, &surface_origin));
- DCHECK(texture_info);
+ GrBackendTexture backend_texture =
+ image->getBackendTexture(true, &surface_origin);
+ DCHECK(backend_texture.isValid());
+ GrGLTextureInfo texture_info;
+ const bool result = backend_texture.getGLTextureInfo(&texture_info);
+ DCHECK(result);
DCHECK(context_provider->GetGLHelper());
const gpu::MailboxHolder& mailbox_holder =
context_provider->GetGLHelper()->ProduceMailboxHolderFromTexture(
- texture_info->fID);
- DCHECK_EQ(static_cast<int>(texture_info->fTarget), GL_TEXTURE_2D);
+ texture_info.fID);
+ DCHECK_EQ(static_cast<int>(texture_info.fTarget), GL_TEXTURE_2D);
viz::ReadbackYUVInterface* const yuv_reader =
context_provider->GetGLHelper()->GetReadbackPipelineYUV(
surface_origin != kTopLeft_GrSurfaceOrigin);
diff --git a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
index 4711085149e..80afeef5aa2 100644
--- a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
+++ b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
@@ -89,7 +89,7 @@ void HtmlAudioElementCapturerSource::OnAudioBus(
MediaStreamAudioSource::SetFormat(
media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::GuessChannelLayout(audio_bus->channels()),
- sample_rate, 16, audio_bus->frames()));
+ sample_rate, audio_bus->frames()));
last_sample_rate_ = sample_rate;
last_num_channels_ = audio_bus->channels();
last_bus_frames_ = audio_bus->frames();
diff --git a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
index f06640d7735..95df6c2efca 100644
--- a/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
+++ b/chromium/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
@@ -44,7 +44,7 @@ ACTION_P(RunClosure, closure) {
class MockMediaStreamAudioSink final : public MediaStreamAudioSink {
public:
MockMediaStreamAudioSink() : MediaStreamAudioSink() {}
- ~MockMediaStreamAudioSink() = default;
+ ~MockMediaStreamAudioSink() override = default;
MOCK_METHOD1(OnSetFormat, void(const media::AudioParameters& params));
MOCK_METHOD2(OnData,
@@ -102,7 +102,7 @@ class HTMLAudioElementCapturerSourceTest : public testing::Test {
const media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::GuessChannelLayout(kNumChannelsForTest),
- kAudioTrackSampleRate /* sample_rate */, 16 /* bits_per_sample */,
+ kAudioTrackSampleRate /* sample_rate */,
kAudioTrackSamplesPerBuffer /* frames_per_buffer */);
audio_source_->Initialize(params, &fake_callback_);
diff --git a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
index bc7b05c6f10..528442cfc54 100644
--- a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
+++ b/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -3,6 +3,10 @@
// found in the LICENSE file.
#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
+
+#include <memory>
+#include <utility>
+
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
@@ -39,8 +43,10 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer,
void Seek(double seconds) override {}
void SetRate(double) override {}
void SetVolume(double) override {}
- void EnterPictureInPicture() override {}
- void ExitPictureInPicture() override {}
+ void EnterPictureInPicture(PipWindowOpenedCallback) override {}
+ void ExitPictureInPicture(PipWindowClosedCallback) override {}
+ void RegisterPictureInPictureWindowResizeCallback(
+ PipWindowResizedCallback) override {}
blink::WebTimeRanges Buffered() const override {
return blink::WebTimeRanges();
}
@@ -48,7 +54,6 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer,
return blink::WebTimeRanges();
}
void SetSinkId(const blink::WebString& sinkId,
- const blink::WebSecurityOrigin&,
blink::WebSetSinkIdCallbacks*) override {}
bool HasVideo() const override { return true; }
bool HasAudio() const override { return false; }
diff --git a/chromium/content/renderer/media_recorder/audio_track_opus_encoder.cc b/chromium/content/renderer/media_recorder/audio_track_opus_encoder.cc
index 3f92f4f2ec3..46fe61a9c13 100644
--- a/chromium/content/renderer/media_recorder/audio_track_opus_encoder.cc
+++ b/chromium/content/renderer/media_recorder/audio_track_opus_encoder.cc
@@ -47,8 +47,7 @@ bool DoEncode(OpusEncoder* opus_encoder,
data_out->resize(kOpusMaxDataBytes);
const opus_int32 result = opus_encode_float(
opus_encoder, data_in, num_samples,
- reinterpret_cast<uint8_t*>(base::string_as_array(data_out)),
- kOpusMaxDataBytes);
+ reinterpret_cast<uint8_t*>(base::data(*data_out)), kOpusMaxDataBytes);
if (result > 1) {
// TODO(ajose): Investigate improving this. http://crbug.com/547918
@@ -108,8 +107,7 @@ void AudioTrackOpusEncoder::OnSetFormat(
converted_params_ = media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::GuessChannelLayout(std::min(input_params_.channels(), 2)),
- kOpusPreferredSamplingRate, input_params_.bits_per_sample(),
- kOpusPreferredFramesPerBuffer);
+ kOpusPreferredSamplingRate, kOpusPreferredFramesPerBuffer);
DVLOG(1) << "|input_params_|:" << input_params_.AsHumanReadableString()
<< " -->|converted_params_|:"
<< converted_params_.AsHumanReadableString();
diff --git a/chromium/content/renderer/media_recorder/audio_track_pcm_encoder.cc b/chromium/content/renderer/media_recorder/audio_track_pcm_encoder.cc
index 6bae562f8d4..cae7dd78ed0 100644
--- a/chromium/content/renderer/media_recorder/audio_track_pcm_encoder.cc
+++ b/chromium/content/renderer/media_recorder/audio_track_pcm_encoder.cc
@@ -42,7 +42,7 @@ void AudioTrackPcmEncoder::EncodeAudio(
std::unique_ptr<std::string> encoded_data_string(new std::string());
encoded_data_string->resize(input_bus->frames() * input_bus->channels() *
sizeof(float));
- char* encoded_data_ptr = base::string_as_array(encoded_data_string.get());
+ char* encoded_data_ptr = base::data(*encoded_data_string);
input_bus->ToInterleaved<media::Float32SampleTypeTraits>(
input_bus->frames(), reinterpret_cast<float*>(encoded_data_ptr));
diff --git a/chromium/content/renderer/media_recorder/audio_track_recorder_unittest.cc b/chromium/content/renderer/media_recorder/audio_track_recorder_unittest.cc
index c3440cf2c51..0f3c0974a45 100644
--- a/chromium/content/renderer/media_recorder/audio_track_recorder_unittest.cc
+++ b/chromium/content/renderer/media_recorder/audio_track_recorder_unittest.cc
@@ -36,7 +36,6 @@ using base::TimeTicks;
namespace {
-const int kDefaultBitsPerSample = 16;
const int kDefaultSampleRate = 48000;
// The |frames_per_buffer| field of AudioParameters is not used by ATR.
const int kIgnoreFramesPerBuffer = 1;
@@ -62,7 +61,6 @@ struct ATRTestParams {
const media::AudioParameters::Format input_format;
const media::ChannelLayout channel_layout;
const int sample_rate;
- const int bits_per_sample;
const AudioTrackRecorder::CodecId codec;
};
@@ -71,32 +69,26 @@ const ATRTestParams kATRTestParams[] = {
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY, /* input format */
media::CHANNEL_LAYOUT_STEREO, /* channel layout */
kDefaultSampleRate, /* sample rate */
- kDefaultBitsPerSample, /* bits per sample */
AudioTrackRecorder::CodecId::OPUS}, /* codec for encoding */
// Change to mono:
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- kDefaultSampleRate, kDefaultBitsPerSample,
- AudioTrackRecorder::CodecId::OPUS},
+ kDefaultSampleRate, AudioTrackRecorder::CodecId::OPUS},
// Different sampling rate as well:
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- 24000, kDefaultBitsPerSample, AudioTrackRecorder::CodecId::OPUS},
+ 24000, AudioTrackRecorder::CodecId::OPUS},
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 8000, kDefaultBitsPerSample,
- AudioTrackRecorder::CodecId::OPUS},
+ media::CHANNEL_LAYOUT_STEREO, 8000, AudioTrackRecorder::CodecId::OPUS},
// Using a non-default Opus sampling rate (48, 24, 16, 12, or 8 kHz).
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- 22050, kDefaultBitsPerSample, AudioTrackRecorder::CodecId::OPUS},
+ 22050, AudioTrackRecorder::CodecId::OPUS},
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 44100, kDefaultBitsPerSample,
- AudioTrackRecorder::CodecId::OPUS},
+ media::CHANNEL_LAYOUT_STEREO, 44100, AudioTrackRecorder::CodecId::OPUS},
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 96000, kDefaultBitsPerSample,
- AudioTrackRecorder::CodecId::OPUS},
+ media::CHANNEL_LAYOUT_STEREO, 96000, AudioTrackRecorder::CodecId::OPUS},
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- kDefaultSampleRate, kDefaultBitsPerSample,
- AudioTrackRecorder::CodecId::PCM},
+ kDefaultSampleRate, AudioTrackRecorder::CodecId::PCM},
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, kDefaultSampleRate, kDefaultBitsPerSample,
+ media::CHANNEL_LAYOUT_STEREO, kDefaultSampleRate,
AudioTrackRecorder::CodecId::PCM},
};
@@ -109,12 +101,10 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
first_params_(GetParam().input_format,
GetParam().channel_layout,
GetParam().sample_rate,
- GetParam().bits_per_sample,
kIgnoreFramesPerBuffer),
second_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
kDefaultSampleRate,
- kDefaultBitsPerSample,
kIgnoreFramesPerBuffer),
first_source_(first_params_.channels(), /* # channels */
440, /* frequency */
@@ -203,11 +193,10 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
// per buffer.
EXPECT_EQ(
kDefaultSampleRate * kOpusBufferDurationMs / 1000,
- opus_decode_float(opus_decoder_,
- reinterpret_cast<uint8_t*>(
- base::string_as_array(encoded_data.get())),
- encoded_data->size(), opus_buffer_.get(),
- kFramesPerBuffer, 0));
+ opus_decode_float(
+ opus_decoder_,
+ reinterpret_cast<uint8_t*>(base::data(*encoded_data)),
+ encoded_data->size(), opus_buffer_.get(), kFramesPerBuffer, 0));
} else if (codec_ == AudioTrackRecorder::CodecId::PCM) {
// Manually confirm that we're getting the same data out as what we
// generated from the sine wave.
diff --git a/chromium/content/renderer/media_recorder/h264_encoder.h b/chromium/content/renderer/media_recorder/h264_encoder.h
index 7074ffb3a63..3e20e3f694f 100644
--- a/chromium/content/renderer/media_recorder/h264_encoder.h
+++ b/chromium/content/renderer/media_recorder/h264_encoder.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_RECORDER_H264_ENCODER_H_
#define CONTENT_RENDERER_MEDIA_RECORDER_H264_ENCODER_H_
+#include "base/single_thread_task_runner.h"
#include "content/public/common/buildflags.h"
#if !BUILDFLAG(RTC_USE_H264)
diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler.h b/chromium/content/renderer/media_recorder/media_recorder_handler.h
index e17fea43df1..bffe011b465 100644
--- a/chromium/content/renderer/media_recorder/media_recorder_handler.h
+++ b/chromium/content/renderer/media_recorder/media_recorder_handler.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc b/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc
index 7cda7426677..82975448f1e 100644
--- a/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc
+++ b/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc
@@ -45,7 +45,6 @@ static const std::string kTestStreamUrl = "stream_url";
static const std::string kTestVideoTrackId = "video_track_id";
static const std::string kTestAudioTrackId = "audio_track_id";
static const int kTestAudioChannels = 2;
-static const int kTestAudioBitsPerSample = 16;
static const int kTestAudioSampleRate = 48000;
static const int kTestAudioBufferDurationMs = 10;
// Opus works with 60ms buffers, so 6 MediaStreamAudioTrack Buffers are needed
@@ -340,7 +339,7 @@ TEST_P(MediaRecorderHandlerTest, OpusEncodeAudioFrames) {
media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO,
- kTestAudioSampleRate, kTestAudioBitsPerSample,
+ kTestAudioSampleRate,
kTestAudioSampleRate * kTestAudioBufferDurationMs / 1000);
SetAudioFormatForTesting(params);
diff --git a/chromium/content/renderer/media_recorder/vea_encoder.cc b/chromium/content/renderer/media_recorder/vea_encoder.cc
index 26e51c2fcc6..6ace838170a 100644
--- a/chromium/content/renderer/media_recorder/vea_encoder.cc
+++ b/chromium/content/renderer/media_recorder/vea_encoder.cc
@@ -29,6 +29,8 @@ const int kVEADefaultBitratePerPixel = 2;
// Number of output buffers used to copy the encoded data coming from HW
// encoders.
const int kVEAEncoderOutputBufferCount = 4;
+// Force a keyframe in regular intervals.
+const uint32_t kMaxKeyframeInterval = 100;
} // anonymous namespace
@@ -47,6 +49,8 @@ VEAEncoder::VEAEncoder(
gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()),
codec_(codec),
error_notified_(false),
+ num_frames_after_keyframe_(0),
+ force_next_frame_to_be_keyframe_(false),
on_error_callback_(on_error_callback) {
DCHECK(gpu_factories_);
DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth);
@@ -103,9 +107,14 @@ void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id,
DVLOG(3) << __func__;
DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+ num_frames_after_keyframe_ = keyframe ? 0 : num_frames_after_keyframe_ + 1;
+ if (num_frames_after_keyframe_ > kMaxKeyframeInterval) {
+ force_next_frame_to_be_keyframe_ = true;
+ num_frames_after_keyframe_ = 0;
+ }
+
base::SharedMemory* output_buffer =
output_buffers_[bitstream_buffer_id].get();
-
std::unique_ptr<std::string> data(new std::string);
data->append(reinterpret_cast<char*>(output_buffer->memory()), payload_size);
@@ -231,7 +240,8 @@ void VEAEncoder::EncodeOnEncodingTaskRunner(scoped_refptr<VideoFrame> frame,
frames_in_encode_.push(std::make_pair(
media::WebmMuxer::VideoParameters(frame), capture_timestamp));
- video_encoder_->Encode(video_frame, false);
+ video_encoder_->Encode(video_frame, force_next_frame_to_be_keyframe_);
+ force_next_frame_to_be_keyframe_ = false;
}
void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
diff --git a/chromium/content/renderer/media_recorder/vea_encoder.h b/chromium/content/renderer/media_recorder/vea_encoder.h
index 64bceb80e41..e4b64fa70b7 100644
--- a/chromium/content/renderer/media_recorder/vea_encoder.h
+++ b/chromium/content/renderer/media_recorder/vea_encoder.h
@@ -8,6 +8,7 @@
#include <queue>
#include "base/containers/queue.h"
+#include "base/single_thread_task_runner.h"
#include "content/renderer/media_recorder/video_track_recorder.h"
#include "media/video/video_encode_accelerator.h"
#include "ui/gfx/geometry/size.h"
@@ -92,6 +93,12 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder,
// Frames and corresponding timestamps in encode as FIFO.
base::queue<VideoParamsAndTimestamp> frames_in_encode_;
+ // Number of encoded frames produced consecutively without a keyframe.
+ uint32_t num_frames_after_keyframe_;
+
+ // Forces next frame to be a keyframe.
+ bool force_next_frame_to_be_keyframe_;
+
// This callback can be exercised on any thread.
const VideoTrackRecorder::OnErrorCB on_error_callback_;
};
diff --git a/chromium/content/renderer/media_recorder/vpx_encoder.h b/chromium/content/renderer/media_recorder/vpx_encoder.h
index 68db00c4c2a..888f34b3d5c 100644
--- a/chromium/content/renderer/media_recorder/vpx_encoder.h
+++ b/chromium/content/renderer/media_recorder/vpx_encoder.h
@@ -7,6 +7,7 @@
#include <vector>
+#include "base/single_thread_task_runner.h"
#include "content/renderer/media_recorder/video_track_recorder.h"
#include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
#include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
diff --git a/chromium/content/renderer/mojo/blink_interface_provider_impl.h b/chromium/content/renderer/mojo/blink_interface_provider_impl.h
index f4b7cee1e50..b016db92c34 100644
--- a/chromium/content/renderer/mojo/blink_interface_provider_impl.h
+++ b/chromium/content/renderer/mojo/blink_interface_provider_impl.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "third_party/blink/public/platform/interface_provider.h"
@@ -23,7 +24,8 @@ namespace content {
// An implementation of blink::InterfaceProvider that forwards to a
// service_manager::InterfaceProvider.
-class BlinkInterfaceProviderImpl final : public blink::InterfaceProvider {
+class CONTENT_EXPORT BlinkInterfaceProviderImpl final
+ : public blink::InterfaceProvider {
public:
explicit BlinkInterfaceProviderImpl(service_manager::Connector* connector);
~BlinkInterfaceProviderImpl();
diff --git a/chromium/content/renderer/mojo/blink_interface_registry_impl.h b/chromium/content/renderer/mojo/blink_interface_registry_impl.h
index 103ab6b4c7f..fbee9230c84 100644
--- a/chromium/content/renderer/mojo/blink_interface_registry_impl.h
+++ b/chromium/content/renderer/mojo/blink_interface_registry_impl.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/associated_interface_registry_impl.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "third_party/blink/public/platform/interface_registry.h"
diff --git a/chromium/content/renderer/mus/BUILD.gn b/chromium/content/renderer/mus/BUILD.gn
index 559eae55f80..718ad1c98d1 100644
--- a/chromium/content/renderer/mus/BUILD.gn
+++ b/chromium/content/renderer/mus/BUILD.gn
@@ -26,7 +26,6 @@ static_library("mus") {
"//content/public/child:child_sources",
"//content/public/common:common_sources",
"//media/mojo/interfaces:remoting",
- "//mojo/common",
"//services/service_manager/public/cpp",
"//services/ui/public/cpp",
"//services/ui/public/interfaces",
diff --git a/chromium/content/renderer/mus/OWNERS b/chromium/content/renderer/mus/OWNERS
index 7def73e60b3..fa103a4a859 100644
--- a/chromium/content/renderer/mus/OWNERS
+++ b/chromium/content/renderer/mus/OWNERS
@@ -3,4 +3,4 @@ sadrul@chromium.org
fsamuel@chromium.org
rjkroege@chromium.org
-# COMPONENT: Internals>MUS
+# COMPONENT: Internals>Services>WindowService
diff --git a/chromium/content/renderer/mus/mus_embedded_frame.cc b/chromium/content/renderer/mus/mus_embedded_frame.cc
index f6b3d1e439f..25c6d8d81a8 100644
--- a/chromium/content/renderer/mus/mus_embedded_frame.cc
+++ b/chromium/content/renderer/mus/mus_embedded_frame.cc
@@ -80,7 +80,7 @@ MusEmbeddedFrame::MusEmbeddedFrame(
void MusEmbeddedFrame::CreateChildWindowAndEmbed(
const base::UnguessableToken& token) {
// Set a name for debugging.
- std::unordered_map<std::string, std::vector<uint8_t>> properties;
+ base::flat_map<std::string, std::vector<uint8_t>> properties;
properties[ui::mojom::WindowManager::kName_Property] =
mojo::ConvertTo<std::vector<uint8_t>>(std::string("RendererFrame"));
window_tree()->NewWindow(GetAndAdvanceNextChangeId(), window_id_, properties);
diff --git a/chromium/content/renderer/mus/renderer_window_tree_client.cc b/chromium/content/renderer/mus/renderer_window_tree_client.cc
index 1a9d6b6454b..77db183fc29 100644
--- a/chromium/content/renderer/mus/renderer_window_tree_client.cc
+++ b/chromium/content/renderer/mus/renderer_window_tree_client.cc
@@ -12,7 +12,6 @@
#include "components/viz/client/client_layer_tree_frame_sink.h"
#include "components/viz/client/hit_test_data_provider.h"
#include "components/viz/client/hit_test_data_provider_draw_quad.h"
-#include "components/viz/client/hit_test_data_provider_surface_layer.h"
#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/common/features.h"
#include "content/renderer/mus/mus_embedded_frame.h"
@@ -32,7 +31,7 @@ base::LazyInstance<ConnectionMap>::Leaky g_connections =
// static
void RendererWindowTreeClient::CreateIfNecessary(int routing_id) {
- if (!features::IsMusEnabled() || Get(routing_id))
+ if (!features::IsMashEnabled() || Get(routing_id))
return;
RendererWindowTreeClient* connection =
new RendererWindowTreeClient(routing_id);
@@ -145,9 +144,6 @@ void RendererWindowTreeClient::RequestLayerTreeFrameSinkInternal(
params.hit_test_data_provider =
std::make_unique<viz::HitTestDataProviderDrawQuad>(
true /* should_ask_for_child_region */);
- } else if (features::IsVizHitTestingSurfaceLayerEnabled()) {
- params.hit_test_data_provider =
- std::make_unique<viz::HitTestDataProviderSurfaceLayer>();
}
auto frame_sink = std::make_unique<viz::ClientLayerTreeFrameSink>(
std::move(context_provider), nullptr /* worker_context_provider */,
@@ -348,7 +344,7 @@ void RendererWindowTreeClient::OnWindowSurfaceChanged(
}
void RendererWindowTreeClient::OnDragDropStart(
- const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) {}
+ const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) {}
void RendererWindowTreeClient::OnDragEnter(ui::Id window_id,
uint32_t event_flags,
diff --git a/chromium/content/renderer/mus/renderer_window_tree_client.h b/chromium/content/renderer/mus/renderer_window_tree_client.h
index b85fd04ae74..a8e4e5d8368 100644
--- a/chromium/content/renderer/mus/renderer_window_tree_client.h
+++ b/chromium/content/renderer/mus/renderer_window_tree_client.h
@@ -183,9 +183,8 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient,
void OnWindowCursorChanged(ui::Id window_id, ui::CursorData cursor) override;
void OnWindowSurfaceChanged(ui::Id window_id,
const viz::SurfaceInfo& surface_info) override;
- void OnDragDropStart(
- const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data)
- override;
+ void OnDragDropStart(const base::flat_map<std::string, std::vector<uint8_t>>&
+ mime_data) override;
void OnDragEnter(ui::Id window_id,
uint32_t event_flags,
const gfx::Point& position,
diff --git a/chromium/content/renderer/notifications/notification_data_conversions.cc b/chromium/content/renderer/notifications/notification_data_conversions.cc
index 638a5e550ec..65556cd4b51 100644
--- a/chromium/content/renderer/notifications/notification_data_conversions.cc
+++ b/chromium/content/renderer/notifications/notification_data_conversions.cc
@@ -19,66 +19,6 @@ using blink::WebString;
namespace content {
-PlatformNotificationData ToPlatformNotificationData(
- const WebNotificationData& web_data) {
- PlatformNotificationData platform_data;
- platform_data.title = web_data.title.Utf16();
-
- switch (web_data.direction) {
- case WebNotificationData::kDirectionLeftToRight:
- platform_data.direction =
- PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT;
- break;
- case WebNotificationData::kDirectionRightToLeft:
- platform_data.direction =
- PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
- break;
- case WebNotificationData::kDirectionAuto:
- platform_data.direction = PlatformNotificationData::DIRECTION_AUTO;
- break;
- }
-
- platform_data.lang = web_data.lang.Utf8(
- WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD);
- platform_data.body = web_data.body.Utf16();
- platform_data.tag = web_data.tag.Utf8(
- WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD);
- platform_data.image = WebStringToGURL(web_data.image.GetString());
- platform_data.icon = WebStringToGURL(web_data.icon.GetString());
- platform_data.badge = WebStringToGURL(web_data.badge.GetString());
- platform_data.vibration_pattern.assign(web_data.vibrate.begin(),
- web_data.vibrate.end());
- platform_data.timestamp = base::Time::FromJsTime(web_data.timestamp);
- platform_data.renotify = web_data.renotify;
- platform_data.silent = web_data.silent;
- platform_data.require_interaction = web_data.require_interaction;
- platform_data.data.assign(web_data.data.begin(), web_data.data.end());
- platform_data.actions.resize(web_data.actions.size());
- for (size_t i = 0; i < web_data.actions.size(); ++i) {
- switch (web_data.actions[i].type) {
- case blink::WebNotificationAction::kButton:
- platform_data.actions[i].type =
- PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON;
- break;
- case blink::WebNotificationAction::kText:
- platform_data.actions[i].type = PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
- break;
- default:
- NOTREACHED() << "Unknown notification action type: "
- << web_data.actions[i].type;
- }
- platform_data.actions[i].action = web_data.actions[i].action.Utf8(
- WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD);
- platform_data.actions[i].title = web_data.actions[i].title.Utf16();
- platform_data.actions[i].icon =
- WebStringToGURL(web_data.actions[i].icon.GetString());
- platform_data.actions[i].placeholder =
- WebString::ToNullableString16(web_data.actions[i].placeholder);
- }
-
- return platform_data;
-}
-
WebNotificationData ToWebNotificationData(
const PlatformNotificationData& platform_data) {
WebNotificationData web_data;
diff --git a/chromium/content/renderer/notifications/notification_data_conversions.h b/chromium/content/renderer/notifications/notification_data_conversions.h
index 1d7c7a13346..d6bf25e5b91 100644
--- a/chromium/content/renderer/notifications/notification_data_conversions.h
+++ b/chromium/content/renderer/notifications/notification_data_conversions.h
@@ -11,10 +11,6 @@
namespace content {
-// Converts Blink WebNotificationData to PlatformNotificationData.
-CONTENT_EXPORT PlatformNotificationData
-ToPlatformNotificationData(const blink::WebNotificationData& web_data);
-
// Converts PlatformNotificationData to Blink WebNotificationData.
CONTENT_EXPORT blink::WebNotificationData ToWebNotificationData(
const PlatformNotificationData& platform_data);
diff --git a/chromium/content/renderer/notifications/notification_data_conversions_unittest.cc b/chromium/content/renderer/notifications/notification_data_conversions_unittest.cc
index 7d5eb0cece1..35fd3f2b894 100644
--- a/chromium/content/renderer/notifications/notification_data_conversions_unittest.cc
+++ b/chromium/content/renderer/notifications/notification_data_conversions_unittest.cc
@@ -36,77 +36,6 @@ const char kAction2Name[] = "btn2";
const char kAction2Title[] = "Button 2";
const char kAction2IconUrl[] = "https://example.com/action_icon_2.png";
-TEST(NotificationDataConversionsTest, ToPlatformNotificationData) {
- blink::WebNotificationData web_data;
- web_data.title = blink::WebString::FromUTF8(kNotificationTitle);
- web_data.direction = blink::WebNotificationData::kDirectionLeftToRight;
- web_data.lang = blink::WebString::FromUTF8(kNotificationLang);
- web_data.body = blink::WebString::FromUTF8(kNotificationBody);
- web_data.tag = blink::WebString::FromUTF8(kNotificationTag);
- web_data.image = blink::WebURL(GURL(kNotificationImageUrl));
- web_data.icon = blink::WebURL(GURL(kNotificationIconUrl));
- web_data.badge = blink::WebURL(GURL(kNotificationBadgeUrl));
- web_data.vibrate = blink::WebVector<int>(
- kNotificationVibrationPattern, arraysize(kNotificationVibrationPattern));
- web_data.timestamp = kNotificationTimestamp;
- web_data.renotify = true;
- web_data.silent = true;
- web_data.require_interaction = true;
- web_data.data =
- blink::WebVector<char>(kNotificationData, arraysize(kNotificationData));
-
- web_data.actions =
- blink::WebVector<blink::WebNotificationAction>(static_cast<size_t>(2));
- web_data.actions[0].type = blink::WebNotificationAction::kButton;
- web_data.actions[0].action = blink::WebString::FromUTF8(kAction1Name);
- web_data.actions[0].title = blink::WebString::FromUTF8(kAction1Title);
- web_data.actions[0].icon = blink::WebURL(GURL(kAction1IconUrl));
- web_data.actions[0].placeholder =
- blink::WebString::FromUTF8(kAction1Placeholder);
- web_data.actions[1].type = blink::WebNotificationAction::kText;
- web_data.actions[1].action = blink::WebString::FromUTF8(kAction2Name);
- web_data.actions[1].title = blink::WebString::FromUTF8(kAction2Title);
- web_data.actions[1].icon = blink::WebURL(GURL(kAction2IconUrl));
- web_data.actions[1].placeholder = blink::WebString();
-
- PlatformNotificationData platform_data = ToPlatformNotificationData(web_data);
- EXPECT_EQ(base::ASCIIToUTF16(kNotificationTitle), platform_data.title);
- EXPECT_EQ(PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT,
- platform_data.direction);
- EXPECT_EQ(kNotificationLang, platform_data.lang);
- EXPECT_EQ(base::ASCIIToUTF16(kNotificationBody), platform_data.body);
- EXPECT_EQ(kNotificationTag, platform_data.tag);
- EXPECT_EQ(kNotificationImageUrl, platform_data.image.spec());
- EXPECT_EQ(kNotificationIconUrl, platform_data.icon.spec());
- EXPECT_EQ(kNotificationBadgeUrl, platform_data.badge.spec());
- EXPECT_TRUE(platform_data.renotify);
- EXPECT_TRUE(platform_data.silent);
- EXPECT_TRUE(platform_data.require_interaction);
-
- EXPECT_THAT(platform_data.vibration_pattern,
- testing::ElementsAreArray(kNotificationVibrationPattern));
-
- EXPECT_DOUBLE_EQ(kNotificationTimestamp, platform_data.timestamp.ToJsTime());
- ASSERT_EQ(web_data.data.size(), platform_data.data.size());
- for (size_t i = 0; i < web_data.data.size(); ++i)
- EXPECT_EQ(web_data.data[i], platform_data.data[i]);
- ASSERT_EQ(web_data.actions.size(), platform_data.actions.size());
- EXPECT_EQ(PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON,
- platform_data.actions[0].type);
- EXPECT_EQ(kAction1Name, platform_data.actions[0].action);
- EXPECT_EQ(base::ASCIIToUTF16(kAction1Title), platform_data.actions[0].title);
- EXPECT_EQ(kAction1IconUrl, platform_data.actions[0].icon.spec());
- EXPECT_EQ(base::ASCIIToUTF16(kAction1Placeholder),
- platform_data.actions[0].placeholder.string());
- EXPECT_FALSE(platform_data.actions[0].placeholder.is_null());
- EXPECT_EQ(PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT,
- platform_data.actions[1].type);
- EXPECT_EQ(kAction2Name, platform_data.actions[1].action);
- EXPECT_EQ(base::ASCIIToUTF16(kAction2Title), platform_data.actions[1].title);
- EXPECT_EQ(kAction2IconUrl, platform_data.actions[1].icon.spec());
- EXPECT_TRUE(platform_data.actions[1].placeholder.is_null());
-}
-
TEST(NotificationDataConversionsTest, ToWebNotificationData) {
std::vector<int> vibration_pattern(
kNotificationVibrationPattern,
@@ -180,72 +109,4 @@ TEST(NotificationDataConversionsTest, ToWebNotificationData) {
EXPECT_TRUE(web_data.actions[1].placeholder.IsNull());
}
-TEST(NotificationDataConversionsTest, NotificationDataDirectionality) {
- std::map<blink::WebNotificationData::Direction,
- PlatformNotificationData::Direction> mappings;
-
- mappings[blink::WebNotificationData::kDirectionLeftToRight] =
- PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT;
- mappings[blink::WebNotificationData::kDirectionRightToLeft] =
- PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT;
- mappings[blink::WebNotificationData::kDirectionAuto] =
- PlatformNotificationData::DIRECTION_AUTO;
-
- for (const auto& pair : mappings) {
- {
- blink::WebNotificationData web_data;
- web_data.direction = pair.first;
-
- PlatformNotificationData platform_data =
- ToPlatformNotificationData(web_data);
- EXPECT_EQ(pair.second, platform_data.direction);
- }
- {
- PlatformNotificationData platform_data;
- platform_data.direction = pair.second;
-
- blink::WebNotificationData web_data =
- ToWebNotificationData(platform_data);
- EXPECT_EQ(pair.first, web_data.direction);
- }
- }
-}
-
-TEST(NotificationDataConversionsTest, TimeEdgeCaseValueBehaviour) {
- {
- blink::WebNotificationData web_data;
- web_data.timestamp =
- static_cast<double>(std::numeric_limits<unsigned long long>::max());
-
- blink::WebNotificationData copied_data =
- ToWebNotificationData(ToPlatformNotificationData(web_data));
- EXPECT_NE(web_data.timestamp, copied_data.timestamp);
- }
- {
- blink::WebNotificationData web_data;
- web_data.timestamp =
- static_cast<double>(9211726771200000000ull); // January 1, 293878
-
- blink::WebNotificationData copied_data =
- ToWebNotificationData(ToPlatformNotificationData(web_data));
- EXPECT_NE(web_data.timestamp, copied_data.timestamp);
- }
- {
- blink::WebNotificationData web_data;
- web_data.timestamp = 0;
-
- blink::WebNotificationData copied_data =
- ToWebNotificationData(ToPlatformNotificationData(web_data));
- EXPECT_EQ(web_data.timestamp, copied_data.timestamp);
- }
- {
- blink::WebNotificationData web_data;
- web_data.timestamp = 0;
-
- blink::WebNotificationData copied_data =
- ToWebNotificationData(ToPlatformNotificationData(web_data));
- EXPECT_EQ(web_data.timestamp, copied_data.timestamp);
- }
-}
-
} // namespace content
diff --git a/chromium/content/renderer/notifications/notification_dispatcher.cc b/chromium/content/renderer/notifications/notification_dispatcher.cc
deleted file mode 100644
index 9508f95e778..00000000000
--- a/chromium/content/renderer/notifications/notification_dispatcher.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 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/renderer/notifications/notification_dispatcher.h"
-
-#include <limits>
-
-#include "content/renderer/notifications/notification_manager.h"
-
-namespace content {
-
-NotificationDispatcher::NotificationDispatcher(
- ThreadSafeSender* thread_safe_sender,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
- : WorkerThreadMessageFilter(thread_safe_sender,
- std::move(main_thread_task_runner)) {}
-
-NotificationDispatcher::~NotificationDispatcher() {}
-
-int NotificationDispatcher::GenerateNotificationRequestId(int thread_id) {
- base::AutoLock lock(notification_request_id_map_lock_);
- CHECK_LT(next_notification_request_id_, std::numeric_limits<int>::max());
-
- notification_request_id_map_[next_notification_request_id_] = thread_id;
- return next_notification_request_id_++;
-}
-
-bool NotificationDispatcher::ShouldHandleMessage(
- const IPC::Message& msg) const {
- return IPC_MESSAGE_CLASS(msg) == PlatformNotificationMsgStart;
-}
-
-void NotificationDispatcher::OnFilteredMessageReceived(
- const IPC::Message& msg) {
- NotificationManager::ThreadSpecificInstance(thread_safe_sender(), this)
- ->OnMessageReceived(msg);
-}
-
-bool NotificationDispatcher::GetWorkerThreadIdForMessage(
- const IPC::Message& msg,
- int* ipc_thread_id) {
- int notification_request_id = -1;
- const bool success =
- base::PickleIterator(msg).ReadInt(&notification_request_id);
- DCHECK(success);
-
- base::AutoLock lock(notification_request_id_map_lock_);
- auto iterator = notification_request_id_map_.find(notification_request_id);
- if (iterator != notification_request_id_map_.end()) {
- *ipc_thread_id = iterator->second;
- return true;
- }
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/notifications/notification_dispatcher.h b/chromium/content/renderer/notifications/notification_dispatcher.h
deleted file mode 100644
index 15cdc4a03ee..00000000000
--- a/chromium/content/renderer/notifications/notification_dispatcher.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 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_RENDERER_NOTIFICATIONS_NOTIFICATION_DISPATCHER_H_
-#define CONTENT_RENDERER_NOTIFICATIONS_NOTIFICATION_DISPATCHER_H_
-
-#include <map>
-
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "content/renderer/worker_thread_message_filter.h"
-
-namespace content {
-
-class NotificationDispatcher : public WorkerThreadMessageFilter {
- public:
- NotificationDispatcher(
- ThreadSafeSender* thread_safe_sender,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
-
- // Generates and stores a new process-unique notification request ID mapped to
- // |thread_id|, and returns the generated request ID. This method can be
- // called on any thread.
- int GenerateNotificationRequestId(int thread_id);
-
- protected:
- ~NotificationDispatcher() override;
-
- private:
- // WorkerThreadMessageFilter:
- bool ShouldHandleMessage(const IPC::Message& msg) const override;
- void OnFilteredMessageReceived(const IPC::Message& msg) override;
- bool GetWorkerThreadIdForMessage(const IPC::Message& msg,
- int* ipc_thread_id) override;
-
- using NotificationRequestIdToThreadId = std::map<int, int>;
-
- base::Lock notification_request_id_map_lock_;
- NotificationRequestIdToThreadId notification_request_id_map_;
- int next_notification_request_id_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(NotificationDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_NOTIFICATIONS_NOTIFICATION_DISPATCHER_H_
diff --git a/chromium/content/renderer/notifications/notification_manager.cc b/chromium/content/renderer/notifications/notification_manager.cc
deleted file mode 100644
index 44b927cc2d6..00000000000
--- a/chromium/content/renderer/notifications/notification_manager.cc
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2014 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/renderer/notifications/notification_manager.h"
-
-#include <utility>
-
-#include "base/lazy_instance.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_local.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/public/common/notification_resources.h"
-#include "content/public/common/platform_notification_data.h"
-#include "content/renderer/notifications/notification_data_conversions.h"
-#include "content/renderer/notifications/notification_dispatcher.h"
-#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
-#include "third_party/blink/public/platform/url_conversion.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
-#include "url/origin.h"
-
-using blink::WebString;
-
-namespace content {
-namespace {
-
-int NotificationWorkerId() {
- return WorkerThread::GetCurrentId();
-}
-
-NotificationResources ToNotificationResources(
- std::unique_ptr<blink::WebNotificationResources> web_resources) {
- NotificationResources resources;
- resources.image = web_resources->image;
- resources.notification_icon = web_resources->icon;
- resources.badge = web_resources->badge;
- for (const auto& action_icon : web_resources->action_icons)
- resources.action_icons.push_back(action_icon);
- return resources;
-}
-
-} // namespace
-
-static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
- g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER;
-
-NotificationManager::NotificationManager(
- ThreadSafeSender* thread_safe_sender,
- NotificationDispatcher* notification_dispatcher)
- : thread_safe_sender_(thread_safe_sender),
- notification_dispatcher_(notification_dispatcher) {
- g_notification_manager_tls.Pointer()->Set(this);
-}
-
-NotificationManager::~NotificationManager() {
- g_notification_manager_tls.Pointer()->Set(nullptr);
-}
-
-NotificationManager* NotificationManager::ThreadSpecificInstance(
- ThreadSafeSender* thread_safe_sender,
- NotificationDispatcher* notification_dispatcher) {
- if (g_notification_manager_tls.Pointer()->Get())
- return g_notification_manager_tls.Pointer()->Get();
-
- NotificationManager* manager =
- new NotificationManager(thread_safe_sender, notification_dispatcher);
- if (NotificationWorkerId())
- WorkerThread::AddObserver(manager);
- return manager;
-}
-
-void NotificationManager::WillStopCurrentWorkerThread() {
- delete this;
-}
-
-void NotificationManager::ShowPersistent(
- const blink::WebSecurityOrigin& origin,
- const blink::WebNotificationData& notification_data,
- std::unique_ptr<blink::WebNotificationResources> notification_resources,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- std::unique_ptr<blink::WebNotificationShowCallbacks> callbacks) {
- DCHECK(service_worker_registration);
- DCHECK_EQ(notification_data.actions.size(),
- notification_resources->action_icons.size());
-
- int64_t service_worker_registration_id =
- static_cast<WebServiceWorkerRegistrationImpl*>(
- service_worker_registration)
- ->RegistrationId();
-
- // Verify that the author-provided payload size does not exceed our limit.
- // This is an implementation-defined limit to prevent abuse of notification
- // data as a storage mechanism. A UMA histogram records the requested sizes,
- // which enables us to track how much data authors are attempting to store.
- //
- // If the size exceeds this limit, reject the showNotification() promise. This
- // is outside of the boundaries set by the specification, but it gives authors
- // an indication that something has gone wrong.
- size_t author_data_size = notification_data.data.size();
-
- UMA_HISTOGRAM_COUNTS_1000("Notifications.AuthorDataSize", author_data_size);
-
- if (author_data_size > PlatformNotificationData::kMaximumDeveloperDataSize) {
- callbacks->OnError();
- return;
- }
-
- int request_id = notification_dispatcher_->GenerateNotificationRequestId(
- NotificationWorkerId());
-
- pending_show_notification_requests_.AddWithID(std::move(callbacks),
- request_id);
-
- // TODO(mkwst): This is potentially doing the wrong thing with unique
- // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
- // https://crbug.com/490074 for detail.
- thread_safe_sender_->Send(new PlatformNotificationHostMsg_ShowPersistent(
- request_id, service_worker_registration_id, url::Origin(origin).GetURL(),
- ToPlatformNotificationData(notification_data),
- ToNotificationResources(std::move(notification_resources))));
-}
-
-void NotificationManager::GetNotifications(
- const blink::WebString& filter_tag,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- std::unique_ptr<blink::WebNotificationGetCallbacks> callbacks) {
- DCHECK(service_worker_registration);
- DCHECK(callbacks);
-
- WebServiceWorkerRegistrationImpl* service_worker_registration_impl =
- static_cast<WebServiceWorkerRegistrationImpl*>(
- service_worker_registration);
-
- GURL origin = GURL(service_worker_registration_impl->Scope()).GetOrigin();
- int64_t service_worker_registration_id =
- service_worker_registration_impl->RegistrationId();
-
- int request_id = notification_dispatcher_->GenerateNotificationRequestId(
- NotificationWorkerId());
-
- pending_get_notification_requests_.AddWithID(std::move(callbacks),
- request_id);
-
- thread_safe_sender_->Send(new PlatformNotificationHostMsg_GetNotifications(
- request_id, service_worker_registration_id, origin,
- filter_tag.Utf8(
- WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD)));
-}
-
-void NotificationManager::ClosePersistent(
- const blink::WebSecurityOrigin& origin,
- const blink::WebString& tag,
- const blink::WebString& notification_id) {
- thread_safe_sender_->Send(new PlatformNotificationHostMsg_ClosePersistent(
- // TODO(mkwst): This is potentially doing the wrong thing with unique
- // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
- // https://crbug.com/490074 for detail.
- url::Origin(origin).GetURL(),
- tag.Utf8(WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD),
- notification_id.Utf8(
- WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD)));
-}
-
-bool NotificationManager::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(NotificationManager, message)
- IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidShowPersistent,
- OnDidShowPersistent)
- IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidGetNotifications,
- OnDidGetNotifications)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void NotificationManager::OnDidShowPersistent(int request_id, bool success) {
- blink::WebNotificationShowCallbacks* callbacks =
- pending_show_notification_requests_.Lookup(request_id);
- DCHECK(callbacks);
-
- if (!callbacks)
- return;
-
- if (success)
- callbacks->OnSuccess();
- else
- callbacks->OnError();
-
- pending_show_notification_requests_.Remove(request_id);
-}
-
-void NotificationManager::OnDidGetNotifications(
- int request_id,
- const std::vector<PersistentNotificationInfo>& notification_infos) {
- blink::WebNotificationGetCallbacks* callbacks =
- pending_get_notification_requests_.Lookup(request_id);
- DCHECK(callbacks);
- if (!callbacks)
- return;
-
- blink::WebVector<blink::WebPersistentNotificationInfo> notifications(
- notification_infos.size());
-
- for (size_t i = 0; i < notification_infos.size(); ++i) {
- blink::WebPersistentNotificationInfo web_notification_info;
- web_notification_info.notification_id =
- blink::WebString::FromUTF8(notification_infos[i].first);
- web_notification_info.data =
- ToWebNotificationData(notification_infos[i].second);
-
- notifications[i] = web_notification_info;
- }
-
- callbacks->OnSuccess(notifications);
-
- pending_get_notification_requests_.Remove(request_id);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/notifications/notification_manager.h b/chromium/content/renderer/notifications/notification_manager.h
deleted file mode 100644
index 72190e3fe3d..00000000000
--- a/chromium/content/renderer/notifications/notification_manager.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2014 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_RENDERER_NOTIFICATIONS_NOTIFICATION_MANAGER_H_
-#define CONTENT_RENDERER_NOTIFICATIONS_NOTIFICATION_MANAGER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/containers/id_map.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/common/platform_notification_messages.h"
-#include "content/public/renderer/worker_thread.h"
-#include "content/renderer/notifications/notification_dispatcher.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_manager.h"
-
-namespace content {
-
-class ThreadSafeSender;
-
-class NotificationManager : public blink::WebNotificationManager,
- public WorkerThread::Observer {
- public:
- ~NotificationManager() override;
-
- // |thread_safe_sender| and |notification_dispatcher| are used if
- // calling this leads to construction.
- static NotificationManager* ThreadSpecificInstance(
- ThreadSafeSender* thread_safe_sender,
- NotificationDispatcher* notification_dispatcher);
-
- // WorkerThread::Observer implementation.
- void WillStopCurrentWorkerThread() override;
-
- void ShowPersistent(
- const blink::WebSecurityOrigin& origin,
- const blink::WebNotificationData& notification_data,
- std::unique_ptr<blink::WebNotificationResources> notification_resources,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- std::unique_ptr<blink::WebNotificationShowCallbacks> callbacks) override;
- void GetNotifications(
- const blink::WebString& filter_tag,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- std::unique_ptr<blink::WebNotificationGetCallbacks> callbacks) override;
- void ClosePersistent(const blink::WebSecurityOrigin& origin,
- const blink::WebString& tag,
- const blink::WebString& notification_id) override;
-
- // Called by the NotificationDispatcher.
- bool OnMessageReceived(const IPC::Message& message);
-
- private:
- NotificationManager(ThreadSafeSender* thread_safe_sender,
- NotificationDispatcher* notification_dispatcher);
-
- // IPC message handlers.
- void OnDidShowPersistent(int request_id, bool success);
- void OnDidGetNotifications(
- int request_id,
- const std::vector<PersistentNotificationInfo>& notification_infos);
-
- scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- scoped_refptr<NotificationDispatcher> notification_dispatcher_;
-
- // Tracks pending requests for getting a list of notifications.
- base::IDMap<std::unique_ptr<blink::WebNotificationGetCallbacks>>
- pending_get_notification_requests_;
-
- // Tracks pending requests for displaying persistent notifications.
- base::IDMap<std::unique_ptr<blink::WebNotificationShowCallbacks>>
- pending_show_notification_requests_;
-
- DISALLOW_COPY_AND_ASSIGN(NotificationManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_NOTIFICATIONS_NOTIFICATION_MANAGER_H_
diff --git a/chromium/content/renderer/origin_trials/OWNERS b/chromium/content/renderer/origin_trials/OWNERS
deleted file mode 100644
index 0d67a41a799..00000000000
--- a/chromium/content/renderer/origin_trials/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://content/common/origin_trials/OWNERS
diff --git a/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc b/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc
deleted file mode 100644
index b17913fde02..00000000000
--- a/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 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/renderer/origin_trials/web_trial_token_validator_impl.h"
-
-#include "base/time/time.h"
-#include "third_party/blink/public/common/origin_trials/trial_token.h"
-#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
-
-namespace content {
-
-WebTrialTokenValidatorImpl::WebTrialTokenValidatorImpl(
- std::unique_ptr<blink::TrialTokenValidator> validator)
- : validator_(std::move(validator)) {
- DCHECK(validator_.get()) << "Should not pass null validator.";
-}
-
-WebTrialTokenValidatorImpl::~WebTrialTokenValidatorImpl() {}
-
-blink::OriginTrialTokenStatus WebTrialTokenValidatorImpl::ValidateToken(
- const blink::WebString& token,
- const blink::WebSecurityOrigin& origin,
- blink::WebString* feature_name) {
- std::string feature;
- blink::OriginTrialTokenStatus status = validator_->ValidateToken(
- token.Utf8(), origin, &feature, base::Time::Now());
- if (status == blink::OriginTrialTokenStatus::kSuccess)
- *feature_name = blink::WebString::FromUTF8(feature);
- return status;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h b/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h
deleted file mode 100644
index 4f33737f845..00000000000
--- a/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 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_RENDERER_ORIGIN_TRIALS_WEB_TRIAL_TOKEN_VALIDATOR_IMPL_H_
-#define CONTENT_RENDERER_ORIGIN_TRIALS_WEB_TRIAL_TOKEN_VALIDATOR_IMPL_H_
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_trial_token_validator.h"
-
-namespace blink {
-class TrialTokenValidator;
-}
-
-namespace content {
-
-// The TrialTokenValidator is called by the Origin Trials Framework code in
-// Blink to validate tokens to enable experimental features.
-//
-// This class is thread-safe.
-// TODO(crbug.com/738505) Move this to WebKit/core once conversion between
-// blink::WebSecurityOrigin and url::Origin is allowed in blink. See
-// https://crbug.com/490074
-class CONTENT_EXPORT WebTrialTokenValidatorImpl
- : public blink::WebTrialTokenValidator {
- public:
- WebTrialTokenValidatorImpl(
- std::unique_ptr<blink::TrialTokenValidator> validator);
- ~WebTrialTokenValidatorImpl() override;
-
- // blink::WebTrialTokenValidator implementation
- blink::OriginTrialTokenStatus ValidateToken(
- const blink::WebString& token,
- const blink::WebSecurityOrigin& origin,
- blink::WebString* feature_name) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebTrialTokenValidatorImpl);
-
- std::unique_ptr<blink::TrialTokenValidator> validator_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ORIGIN_TRIALS_WEB_TRIAL_TOKEN_VALIDATOR_IMPL_H_
diff --git a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
index c721ccd0e6d..2c396ffb834 100644
--- a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
+++ b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -55,7 +55,6 @@ namespace content {
namespace {
-#if BUILDFLAG(ENABLE_WEBRTC)
bool CanUseMediaStreamAPI(const RendererPpapiHost* host, PP_Instance instance) {
blink::WebPluginContainer* container =
host->GetContainerForInstance(instance);
@@ -67,7 +66,6 @@ bool CanUseMediaStreamAPI(const RendererPpapiHost* host, PP_Instance instance) {
GetContentClient()->renderer();
return content_renderer_client->AllowPepperMediaStreamAPI(document_url);
}
-#endif // BUILDFLAG(ENABLE_WEBRTC)
static bool CanUseCameraDeviceAPI(const RendererPpapiHost* host,
PP_Instance instance) {
@@ -186,7 +184,6 @@ ContentRendererPepperHostFactory::CreateResourceHost(
resource);
case PpapiHostMsg_WebSocket_Create::ID:
return std::make_unique<PepperWebSocketHost>(host_, instance, resource);
-#if BUILDFLAG(ENABLE_WEBRTC)
case PpapiHostMsg_MediaStreamVideoTrack_Create::ID:
return std::make_unique<PepperMediaStreamVideoTrackHost>(host_, instance,
resource);
@@ -203,7 +200,6 @@ ContentRendererPepperHostFactory::CreateResourceHost(
return std::make_unique<PepperVideoSourceHost>(host_, instance,
resource);
return nullptr;
-#endif // BUILDFLAG(ENABLE_WEBRTC)
}
// Dev interfaces.
diff --git a/chromium/content/renderer/pepper/event_conversion.cc b/chromium/content/renderer/pepper/event_conversion.cc
index 7327a395dc4..8d6ffbd3776 100644
--- a/chromium/content/renderer/pepper/event_conversion.cc
+++ b/chromium/content/renderer/pepper/event_conversion.cc
@@ -156,7 +156,7 @@ int ConvertEventModifiers(int modifiers) {
InputEventData GetEventWithCommonFieldsAndType(const WebInputEvent& web_event) {
InputEventData result;
result.event_type = ConvertEventTypes(web_event);
- result.event_time_stamp = web_event.TimeStampSeconds();
+ result.event_time_stamp = web_event.TimeStamp().since_origin().InSecondsF();
return result;
}
@@ -396,7 +396,9 @@ WebTouchEvent* BuildTouchEvent(const InputEventData& event) {
NOTREACHED();
}
WebTouchEventTraits::ResetType(
- type, event.event_time_stamp, web_event);
+ type,
+ base::TimeTicks() + base::TimeDelta::FromSecondsD(event.event_time_stamp),
+ web_event);
web_event->touches_length = 0;
// First add all changed touches, then add only the remaining unset
@@ -424,15 +426,19 @@ WebKeyboardEvent* BuildKeyEvent(const InputEventData& event) {
default:
NOTREACHED();
}
- WebKeyboardEvent* key_event =
- new WebKeyboardEvent(type, event.event_modifiers, event.event_time_stamp);
+ WebKeyboardEvent* key_event = new WebKeyboardEvent(
+ type, event.event_modifiers,
+ base::TimeTicks() +
+ base::TimeDelta::FromSecondsD(event.event_time_stamp));
key_event->windows_key_code = event.key_code;
return key_event;
}
WebKeyboardEvent* BuildCharEvent(const InputEventData& event) {
WebKeyboardEvent* key_event = new WebKeyboardEvent(
- WebInputEvent::kChar, event.event_modifiers, event.event_time_stamp);
+ WebInputEvent::kChar, event.event_modifiers,
+ base::TimeTicks() +
+ base::TimeDelta::FromSecondsD(event.event_time_stamp));
// Make sure to not read beyond the buffer in case some bad code doesn't
// NULL-terminate it (this is called from plugins).
@@ -470,8 +476,10 @@ WebMouseEvent* BuildMouseEvent(const InputEventData& event) {
default:
NOTREACHED();
}
- WebMouseEvent* mouse_event =
- new WebMouseEvent(type, event.event_modifiers, event.event_time_stamp);
+ WebMouseEvent* mouse_event = new WebMouseEvent(
+ type, event.event_modifiers,
+ base::TimeTicks() +
+ base::TimeDelta::FromSecondsD(event.event_time_stamp));
mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kMouse;
mouse_event->button = static_cast<WebMouseEvent::Button>(event.mouse_button);
if (mouse_event->GetType() == WebInputEvent::kMouseMove) {
@@ -491,9 +499,10 @@ WebMouseEvent* BuildMouseEvent(const InputEventData& event) {
}
WebMouseWheelEvent* BuildMouseWheelEvent(const InputEventData& event) {
- WebMouseWheelEvent* mouse_wheel_event =
- new WebMouseWheelEvent(WebInputEvent::kMouseWheel, event.event_modifiers,
- event.event_time_stamp);
+ WebMouseWheelEvent* mouse_wheel_event = new WebMouseWheelEvent(
+ WebInputEvent::kMouseWheel, event.event_modifiers,
+ base::TimeTicks() +
+ base::TimeDelta::FromSecondsD(event.event_time_stamp));
mouse_wheel_event->delta_x = event.wheel_delta.x;
mouse_wheel_event->delta_y = event.wheel_delta.y;
mouse_wheel_event->wheel_ticks_x = event.wheel_ticks.x;
@@ -737,7 +746,7 @@ std::vector<std::unique_ptr<WebInputEvent>> CreateSimulatedWebInputEvents(
WebInputEvent::kRawKeyDown,
needs_shift_modifier ? WebInputEvent::kShiftKey
: WebInputEvent::kNoModifiers,
- web_char_event->TimeStampSeconds()));
+ web_char_event->TimeStamp()));
std::unique_ptr<WebKeyboardEvent> key_up_event(new WebKeyboardEvent());
key_down_event->windows_key_code = code;
diff --git a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc
index 28fbd56cd00..9f6607467cf 100644
--- a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc
+++ b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc
@@ -89,6 +89,24 @@ bool FakePepperPluginInstance::CanEditText() {
return false;
}
+bool FakePepperPluginInstance::HasEditableText() {
+ return false;
+}
+
void FakePepperPluginInstance::ReplaceSelection(const std::string& text) {}
+void FakePepperPluginInstance::SelectAll() {}
+
+bool FakePepperPluginInstance::CanUndo() {
+ return false;
+}
+
+bool FakePepperPluginInstance::CanRedo() {
+ return false;
+}
+
+void FakePepperPluginInstance::Undo() {}
+
+void FakePepperPluginInstance::Redo() {}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
index b596e14f102..1f19eb728a1 100644
--- a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
+++ b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <string>
+
#include "content/public/renderer/pepper_plugin_instance.h"
#include "url/gurl.h"
@@ -48,7 +50,13 @@ class FakePepperPluginInstance : public PepperPluginInstance {
void SetSelectionBounds(const gfx::PointF& base,
const gfx::PointF& extent) override;
bool CanEditText() override;
+ bool HasEditableText() override;
void ReplaceSelection(const std::string& text) override;
+ void SelectAll() override;
+ bool CanUndo() override;
+ bool CanRedo() override;
+ void Undo() override;
+ void Redo() override;
private:
GURL gurl_;
diff --git a/chromium/content/renderer/pepper/fullscreen_container.h b/chromium/content/renderer/pepper/fullscreen_container.h
index 75fbc1cac50..2855b9ed62a 100644
--- a/chromium/content/renderer/pepper/fullscreen_container.h
+++ b/chromium/content/renderer/pepper/fullscreen_container.h
@@ -6,11 +6,14 @@
#define CONTENT_RENDERER_PEPPER_FULLSCREEN_CONTAINER_H_
namespace blink {
-class WebLayer;
struct WebCursorInfo;
struct WebRect;
} // namespace blink
+namespace cc {
+class Layer;
+}
+
namespace content {
// This class is like a lightweight WebPluginContainer for fullscreen PPAPI
@@ -33,7 +36,7 @@ class FullscreenContainer {
// Notifies the container that the mouse cursor has changed.
virtual void PepperDidChangeCursor(const blink::WebCursorInfo& cursor) = 0;
- virtual void SetLayer(blink::WebLayer* layer) = 0;
+ virtual void SetLayer(cc::Layer* layer) = 0;
protected:
virtual ~FullscreenContainer() {}
diff --git a/chromium/content/renderer/pepper/pepper_audio_output_host.cc b/chromium/content/renderer/pepper/pepper_audio_output_host.cc
index 6aa32bde455..9322bd0cc5f 100644
--- a/chromium/content/renderer/pepper/pepper_audio_output_host.cc
+++ b/chromium/content/renderer/pepper/pepper_audio_output_host.cc
@@ -97,16 +97,12 @@ int32_t PepperAudioOutputHost::OnOpen(ppapi::host::HostMessageContext* context,
if (audio_output_)
return PP_ERROR_FAILED;
- GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance());
- if (!document_url.is_valid())
- return PP_ERROR_FAILED;
-
// When it is done, we'll get called back on StreamCreated() or
// StreamCreationFailed().
audio_output_ = PepperPlatformAudioOutputDev::Create(
renderer_ppapi_host_->GetRenderFrameForInstance(pp_instance())
->GetRoutingID(),
- device_id, document_url, static_cast<int>(sample_rate),
+ device_id, static_cast<int>(sample_rate),
static_cast<int>(sample_frame_count), this);
if (audio_output_) {
open_context_ = context->MakeReplyMessageContext();
diff --git a/chromium/content/renderer/pepper/pepper_compositor_host.cc b/chromium/content/renderer/pepper/pepper_compositor_host.cc
index 7bafb0143dc..74389fe12f6 100644
--- a/chromium/content/renderer/pepper/pepper_compositor_host.cc
+++ b/chromium/content/renderer/pepper/pepper_compositor_host.cc
@@ -10,12 +10,10 @@
#include "base/logging.h"
#include "base/memory/shared_memory.h"
-#include "cc/blink/web_layer_impl.h"
#include "cc/layers/layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/texture_layer.h"
#include "cc/trees/layer_tree_host.h"
-#include "components/viz/client/client_shared_bitmap_manager.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/pepper/gfx_conversion.h"
#include "content/renderer/pepper/host_globals.h"
@@ -191,12 +189,10 @@ void PepperCompositorHost::ViewInitiatedPaint() {
void PepperCompositorHost::ImageReleased(
int32_t id,
- std::unique_ptr<base::SharedMemory> shared_memory,
- std::unique_ptr<viz::SharedBitmap> bitmap,
+ scoped_refptr<cc::CrossThreadSharedBitmap> shared_bitmap,
+ cc::SharedBitmapIdRegistration registration,
const gpu::SyncToken& sync_token,
bool is_lost) {
- bitmap.reset();
- shared_memory.reset();
ResourceReleased(id, sync_token, is_lost);
}
@@ -268,11 +264,9 @@ void PepperCompositorHost::UpdateLayer(
}
if (new_layer->color) {
- layer->SetBackgroundColor(SkColorSetARGBMacro(
- new_layer->color->alpha * 255,
- new_layer->color->red * 255,
- new_layer->color->green * 255,
- new_layer->color->blue * 255));
+ layer->SetBackgroundColor(SkColorSetARGB(
+ new_layer->color->alpha * 255, new_layer->color->red * 255,
+ new_layer->color->green * 255, new_layer->color->blue * 255));
return;
}
@@ -314,20 +308,25 @@ void PepperCompositorHost::UpdateLayer(
DCHECK_EQ(rv, PP_TRUE);
DCHECK_EQ(desc.stride, desc.size.width * 4);
DCHECK_EQ(desc.format, PP_IMAGEDATAFORMAT_RGBA_PREMUL);
- std::unique_ptr<viz::SharedBitmap> bitmap =
- RenderThreadImpl::current()
- ->shared_bitmap_manager()
- ->GetBitmapForSharedMemory(image_shm.get());
- auto resource = viz::TransferableResource::MakeSoftware(
- bitmap->id(), bitmap->sequence_number(), PP_ToGfxSize(desc.size),
+ viz::SharedBitmapId shared_bitmap_id = viz::SharedBitmap::GenerateId();
+ // TODO(danakj): These bitmaps could be reused for future frames instead
+ // of malloc/free for each frame.
+ auto shared_bitmap = base::MakeRefCounted<cc::CrossThreadSharedBitmap>(
+ shared_bitmap_id, std::move(image_shm), PP_ToGfxSize(desc.size),
viz::RGBA_8888);
+
+ cc::SharedBitmapIdRegistration registration =
+ image_layer->RegisterSharedBitmapId(shared_bitmap_id, shared_bitmap);
+
+ auto resource = viz::TransferableResource::MakeSoftware(
+ shared_bitmap_id, PP_ToGfxSize(desc.size), viz::RGBA_8888);
image_layer->SetTransferableResource(
resource,
viz::SingleReleaseCallback::Create(base::BindOnce(
&PepperCompositorHost::ImageReleased, weak_factory_.GetWeakPtr(),
- new_layer->common.resource_id, std::move(image_shm),
- std::move(bitmap))));
+ new_layer->common.resource_id, std::move(shared_bitmap),
+ std::move(registration))));
// TODO(penghuang): get a damage region from the application and
// pass it to SetNeedsDisplayRect().
image_layer->SetNeedsDisplay();
diff --git a/chromium/content/renderer/pepper/pepper_compositor_host.h b/chromium/content/renderer/pepper/pepper_compositor_host.h
index b2bc049d576..4824410afb0 100644
--- a/chromium/content/renderer/pepper/pepper_compositor_host.h
+++ b/chromium/content/renderer/pepper/pepper_compositor_host.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "cc/resources/shared_bitmap_id_registrar.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/shared_impl/compositor_layer_data.h"
@@ -21,6 +22,7 @@ class SharedMemory;
} // namespace
namespace cc {
+class CrossThreadSharedBitmap;
class Layer;
} // namespace cc
@@ -28,10 +30,6 @@ namespace gpu {
struct SyncToken;
} // namespace gpu
-namespace viz {
-class SharedBitmap;
-}
-
namespace content {
class PepperPluginInstanceImpl;
@@ -61,8 +59,8 @@ class PepperCompositorHost : public ppapi::host::ResourceHost {
private:
void ImageReleased(int32_t id,
- std::unique_ptr<base::SharedMemory> shared_memory,
- std::unique_ptr<viz::SharedBitmap> bitmap,
+ scoped_refptr<cc::CrossThreadSharedBitmap> shared_bitmap,
+ cc::SharedBitmapIdRegistration registration,
const gpu::SyncToken& sync_token,
bool is_lost);
void ResourceReleased(int32_t id,
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
index 005c65438fe..b5c5bc9d90a 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -784,8 +784,7 @@ bool PepperGraphics2DHost::PrepareTransferableResource(
image_data_->Unmap();
*transferable_resource = viz::TransferableResource::MakeSoftware(
- shared_bitmap->id(), /*sequence_number=*/0, pixel_image_size,
- viz::RGBA_8888);
+ shared_bitmap->id(), pixel_image_size, viz::RGBA_8888);
*release_callback = viz::SingleReleaseCallback::Create(base::BindOnce(
&PepperGraphics2DHost::ReleaseSoftwareCallback, this->AsWeakPtr(),
std::move(shared_bitmap), std::move(registration)));
diff --git a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
index e733e3380a3..29331380673 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
+++ b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "content/child/browser_font_resource_trusted.h"
#include "content/renderer/pepper/pepper_in_process_router.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.cc b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
index 2a1593afe48..606cec34a66 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
@@ -102,7 +102,6 @@ PepperMediaDeviceManager::~PepperMediaDeviceManager() {
void PepperMediaDeviceManager::EnumerateDevices(
PP_DeviceType_Dev type,
const DevicesCallback& callback) {
-#if BUILDFLAG(ENABLE_WEBRTC)
bool request_audio_input = type == PP_DEVICETYPE_DEV_AUDIOCAPTURE;
bool request_video_input = type == PP_DEVICETYPE_DEV_VIDEOCAPTURE;
bool request_audio_output = type == PP_DEVICETYPE_DEV_AUDIOOUTPUT;
@@ -112,18 +111,11 @@ void PepperMediaDeviceManager::EnumerateDevices(
false /* request_video_input_capabilities */,
base::BindOnce(&PepperMediaDeviceManager::DevicesEnumerated, AsWeakPtr(),
callback, ToMediaDeviceType(type)));
-#else
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&PepperMediaDeviceManager::DevicesEnumerated,
- AsWeakPtr(), callback, ToMediaDeviceType(type),
- std::vector<MediaDeviceInfoArray>()));
-#endif
}
size_t PepperMediaDeviceManager::StartMonitoringDevices(
PP_DeviceType_Dev type,
const DevicesCallback& callback) {
-#if BUILDFLAG(ENABLE_WEBRTC)
bool subscribe_audio_input = type == PP_DEVICETYPE_DEV_AUDIOCAPTURE;
bool subscribe_video_input = type == PP_DEVICETYPE_DEV_VIDEOCAPTURE;
bool subscribe_audio_output = type == PP_DEVICETYPE_DEV_AUDIOOUTPUT;
@@ -140,14 +132,10 @@ size_t PepperMediaDeviceManager::StartMonitoringDevices(
subscriptions.push_back(Subscription{subscription_id, callback});
return subscription_id;
-#else
- return 0u;
-#endif
}
void PepperMediaDeviceManager::StopMonitoringDevices(PP_DeviceType_Dev type,
size_t subscription_id) {
-#if BUILDFLAG(ENABLE_WEBRTC)
SubscriptionList& subscriptions =
device_change_subscriptions_[ToMediaDeviceType(type)];
base::EraseIf(subscriptions,
@@ -155,7 +143,6 @@ void PepperMediaDeviceManager::StopMonitoringDevices(PP_DeviceType_Dev type,
return subscription.first == subscription_id;
});
bindings_.RemoveBinding(subscription_id);
-#endif
}
int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type,
@@ -180,18 +167,11 @@ int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type,
return request_id;
}
-#if BUILDFLAG(ENABLE_WEBRTC)
GetMediaStreamDispatcherHost()->OpenDevice(
request_id, device_id,
PepperMediaDeviceManager::FromPepperDeviceType(type),
base::BindOnce(&PepperMediaDeviceManager::OnDeviceOpened, AsWeakPtr(),
request_id));
-#else
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&PepperMediaDeviceManager::OnDeviceOpened, AsWeakPtr(),
- request_id, false, std::string(), MediaStreamDevice()));
-#endif
return request_id;
}
@@ -199,23 +179,18 @@ int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type,
void PepperMediaDeviceManager::CancelOpenDevice(int request_id) {
open_callbacks_.erase(request_id);
-#if BUILDFLAG(ENABLE_WEBRTC)
GetMediaStreamDispatcherHost()->CancelRequest(request_id);
-#endif
}
void PepperMediaDeviceManager::CloseDevice(const std::string& label) {
-#if BUILDFLAG(ENABLE_WEBRTC)
if (!GetMediaStreamDeviceObserver()->RemoveStream(label))
return;
GetMediaStreamDispatcherHost()->CloseDevice(label);
-#endif
}
int PepperMediaDeviceManager::GetSessionID(PP_DeviceType_Dev type,
const std::string& label) {
-#if BUILDFLAG(ENABLE_WEBRTC)
switch (type) {
case PP_DEVICETYPE_DEV_AUDIOCAPTURE:
return GetMediaStreamDeviceObserver()->audio_session_id(label);
@@ -225,9 +200,6 @@ int PepperMediaDeviceManager::GetSessionID(PP_DeviceType_Dev type,
NOTREACHED();
return 0;
}
-#else
- return 0;
-#endif
}
// static
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc b/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc
index 331bce1b327..133684f536d 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc
+++ b/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc
@@ -22,6 +22,7 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "ppapi/shared_impl/media_stream_buffer.h"
+#include "ppapi/shared_impl/ppb_audio_config_shared.h"
using media::AudioParameters;
using ppapi::host::HostMessageContext;
@@ -211,8 +212,6 @@ void PepperMediaStreamAudioTrackHost::AudioSink::OnData(
if (first_frame_capture_time_.is_null())
first_frame_capture_time_ = estimated_capture_time;
- const int bytes_per_frame = audio_params_.GetBytesPerFrame();
-
base::AutoLock lock(lock_);
for (int frame_offset = 0; frame_offset < audio_bus.frames(); ) {
if (active_buffers_generation_ != buffers_generation_) {
@@ -248,20 +247,19 @@ void PepperMediaStreamAudioTrackHost::AudioSink::OnData(
static_cast<PP_AudioBuffer_SampleRate>(audio_params_.sample_rate());
buffer->data_size = output_buffer_size_;
buffer->number_of_channels = audio_params_.channels();
- buffer->number_of_samples = buffer->data_size * audio_params_.channels() /
- bytes_per_frame;
+ buffer->number_of_samples =
+ buffer->data_size * audio_params_.channels() / bytes_per_frame_;
}
const int frames_per_buffer =
buffer->number_of_samples / audio_params_.channels();
- const int frames_to_copy = std::min(
- frames_per_buffer - active_buffer_frame_offset_,
- audio_bus.frames() - frame_offset);
- audio_bus.ToInterleavedPartial(
- frame_offset,
- frames_to_copy,
- audio_params_.bits_per_sample() / 8,
- buffer->data + active_buffer_frame_offset_ * bytes_per_frame);
+ const int frames_to_copy =
+ std::min(frames_per_buffer - active_buffer_frame_offset_,
+ audio_bus.frames() - frame_offset);
+ audio_bus.ToInterleavedPartial<media::SignedInt16SampleTypeTraits>(
+ frame_offset, frames_to_copy,
+ reinterpret_cast<int16_t*>(buffer->data + active_buffer_frame_offset_ *
+ bytes_per_frame_));
active_buffer_frame_offset_ += frames_to_copy;
frame_offset += frames_to_copy;
@@ -286,24 +284,25 @@ void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
// max(user requested duration, received buffer duration). There are other
// ways of dealing with it, but which one is "correct"?
DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMinDuration);
- DCHECK_EQ(params.bits_per_sample(), 16);
DCHECK_NE(GetPPSampleRate(params.sample_rate()),
PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN);
// TODO(penghuang): support setting format more than once.
if (audio_params_.IsValid()) {
DCHECK_EQ(params.sample_rate(), audio_params_.sample_rate());
- DCHECK_EQ(params.bits_per_sample(), audio_params_.bits_per_sample());
DCHECK_EQ(params.channels(), audio_params_.channels());
} else {
audio_thread_checker_.DetachFromThread();
audio_params_ = params;
+ static_assert(ppapi::kBitsPerAudioOutputSample == 16,
+ "Data must be pcm_s16le.");
+ int bytes_per_frame = params.GetBytesPerFrame(media::kSampleFormatS16);
+ int bytes_per_second = params.sample_rate() * bytes_per_frame;
main_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&AudioSink::SetFormatOnMainThread,
- weak_factory_.GetWeakPtr(), params.GetBytesPerSecond(),
- params.GetBytesPerFrame()));
+ FROM_HERE, base::BindOnce(&AudioSink::SetFormatOnMainThread,
+ weak_factory_.GetWeakPtr(), bytes_per_second,
+ bytes_per_frame));
}
}
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
index 963ce9c355c..1d8fb3ff295 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
@@ -133,7 +133,8 @@ PepperPlatformAudioInput::PepperPlatformAudioInput()
render_frame_id_(MSG_ROUTING_NONE),
create_stream_sent_(false),
pending_open_device_(false),
- pending_open_device_id_(-1) {}
+ pending_open_device_id_(-1),
+ ipc_startup_state_(kIdle) {}
bool PepperPlatformAudioInput::Initialize(
int render_frame_id,
@@ -154,12 +155,10 @@ bool PepperPlatformAudioInput::Initialize(
if (!GetMediaDeviceManager())
return false;
- ipc_ = AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id);
params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR,
media::CHANNEL_LAYOUT_MONO,
sample_rate,
- ppapi::kBitsPerAudioInputSample,
frames_per_buffer);
// We need to open the device and obtain the label and session ID before
@@ -178,24 +177,39 @@ bool PepperPlatformAudioInput::Initialize(
void PepperPlatformAudioInput::InitializeOnIOThread(int session_id) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
+ if (ipc_startup_state_ != kStopped)
+ ipc_ = AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id_,
+ session_id);
if (!ipc_)
return;
// We will be notified by OnStreamCreated().
create_stream_sent_ = true;
- ipc_->CreateStream(this, session_id, params_, false, 1);
+ ipc_->CreateStream(this, params_, false, 1);
+
+ if (ipc_startup_state_ == kStarted)
+ ipc_->RecordStream();
}
void PepperPlatformAudioInput::StartCaptureOnIOThread() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
- if (ipc_)
- ipc_->RecordStream();
+ if (!ipc_) {
+ ipc_startup_state_ = kStarted;
+ return;
+ }
+
+ ipc_->RecordStream();
}
void PepperPlatformAudioInput::StopCaptureOnIOThread() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
+ if (!ipc_) {
+ ipc_startup_state_ = kStopped;
+ return;
+ }
+
// TODO(yzshen): We cannot re-start capturing if the stream is closed.
if (ipc_ && create_stream_sent_) {
ipc_->CloseStream();
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.h b/chromium/content/renderer/pepper/pepper_platform_audio_input.h
index 13b0137706b..d7f69bbd6f0 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_input.h
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.h
@@ -122,6 +122,10 @@ class PepperPlatformAudioInput
// THIS MUST ONLY BE ACCESSED ON THE MAIN THREAD.
int pending_open_device_id_;
+ // Used to handle cases where (Start|Stop)CaptureOnIOThread runs before the
+ // InitializeOnIOThread. THIS MUST ONLY BE ACCESSED ON THE IO THREAD.
+ enum { kIdle, kStarted, kStopped } ipc_startup_state_;
+
DISALLOW_COPY_AND_ASSIGN(PepperPlatformAudioInput);
};
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
index a271c30ec62..267fe95c276 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc
@@ -90,7 +90,8 @@ void PepperPlatformAudioOutput::OnDeviceAuthorized(
void PepperPlatformAudioOutput::OnStreamCreated(
base::SharedMemoryHandle handle,
- base::SyncSocket::Handle socket_handle) {
+ base::SyncSocket::Handle socket_handle,
+ bool playing_automatically) {
DCHECK(handle.IsValid());
#if defined(OS_WIN)
DCHECK(socket_handle);
@@ -106,8 +107,9 @@ void PepperPlatformAudioOutput::OnStreamCreated(
client_->StreamCreated(handle, handle.GetSize(), socket_handle);
} else {
main_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&PepperPlatformAudioOutput::OnStreamCreated,
- this, handle, socket_handle));
+ FROM_HERE,
+ base::BindOnce(&PepperPlatformAudioOutput::OnStreamCreated, this,
+ handle, socket_handle, playing_automatically));
}
}
@@ -139,7 +141,6 @@ bool PepperPlatformAudioOutput::Initialize(int sample_rate,
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
sample_rate,
- ppapi::kBitsPerAudioOutputSample,
frames_per_buffer);
io_task_runner_->PostTask(
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.h b/chromium/content/renderer/pepper/pepper_platform_audio_output.h
index a24a629e269..43be22d0076 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output.h
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.h
@@ -58,7 +58,8 @@ class PepperPlatformAudioOutput
const media::AudioParameters& output_params,
const std::string& matched_device_id) override;
void OnStreamCreated(base::SharedMemoryHandle handle,
- base::SyncSocket::Handle socket_handle) override;
+ base::SyncSocket::Handle socket_handle,
+ bool playing_automatically) override;
void OnIPCClosed() override;
protected:
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc
index ce1639ac6fd..c4f75ab84a7 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc
@@ -36,13 +36,12 @@ namespace content {
PepperPlatformAudioOutputDev* PepperPlatformAudioOutputDev::Create(
int render_frame_id,
const std::string& device_id,
- const GURL& document_url,
int sample_rate,
int frames_per_buffer,
PepperAudioOutputHost* client) {
scoped_refptr<PepperPlatformAudioOutputDev> audio_output(
new PepperPlatformAudioOutputDev(
- render_frame_id, device_id, document_url,
+ render_frame_id, device_id,
// Set authorization request timeout at 80% of renderer hung timeout,
// but no more than kMaxAuthorizationTimeout.
base::TimeDelta::FromMilliseconds(std::min(
@@ -182,7 +181,8 @@ void PepperPlatformAudioOutputDev::OnDeviceAuthorized(
void PepperPlatformAudioOutputDev::OnStreamCreated(
base::SharedMemoryHandle handle,
- base::SyncSocket::Handle socket_handle) {
+ base::SyncSocket::Handle socket_handle,
+ bool playing_automatically) {
DCHECK(handle.IsValid());
#if defined(OS_WIN)
DCHECK(socket_handle);
@@ -208,7 +208,7 @@ void PepperPlatformAudioOutputDev::OnStreamCreated(
main_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&PepperPlatformAudioOutputDev::OnStreamCreated, this,
- handle, socket_handle));
+ handle, socket_handle, playing_automatically));
}
}
@@ -231,7 +231,6 @@ PepperPlatformAudioOutputDev::~PepperPlatformAudioOutputDev() {
PepperPlatformAudioOutputDev::PepperPlatformAudioOutputDev(
int render_frame_id,
const std::string& device_id,
- const GURL& document_url,
base::TimeDelta authorization_timeout)
: client_(nullptr),
main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
@@ -242,7 +241,6 @@ PepperPlatformAudioOutputDev::PepperPlatformAudioOutputDev(
play_on_start_(false),
session_id_(0),
device_id_(device_id),
- security_origin_(url::Origin::Create(document_url)),
did_receive_auth_(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED),
device_status_(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL),
@@ -264,8 +262,7 @@ bool PepperPlatformAudioOutputDev::Initialize(int sample_rate,
CHECK(ipc_);
params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, sample_rate,
- ppapi::kBitsPerAudioOutputSample, frames_per_buffer);
+ media::CHANNEL_LAYOUT_STEREO, sample_rate, frames_per_buffer);
io_task_runner_->PostTask(
FROM_HERE,
@@ -283,8 +280,7 @@ void PepperPlatformAudioOutputDev::RequestDeviceAuthorizationOnIOThread() {
return;
state_ = AUTHORIZING;
- ipc_->RequestDeviceAuthorization(this, session_id_, device_id_,
- security_origin_);
+ ipc_->RequestDeviceAuthorization(this, session_id_, device_id_);
if (auth_timeout_ > base::TimeDelta()) {
// Create the timer on the thread it's used on. It's guaranteed to be
@@ -311,8 +307,7 @@ void PepperPlatformAudioOutputDev::CreateStreamOnIOThread(
break;
case IDLE:
- if (did_receive_auth_.IsSignaled() && device_id_.empty() &&
- security_origin_.unique()) {
+ if (did_receive_auth_.IsSignaled() && device_id_.empty()) {
state_ = CREATING_STREAM;
ipc_->CreateStream(this, params);
} else {
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h
index 24ab7da0b54..71ca14500f7 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h
@@ -32,7 +32,6 @@ class PepperPlatformAudioOutputDev
// when the stream is created.
static PepperPlatformAudioOutputDev* Create(int render_frame_id,
const std::string& device_id,
- const GURL& document_url,
int sample_rate,
int frames_per_buffer,
PepperAudioOutputHost* client);
@@ -64,7 +63,8 @@ class PepperPlatformAudioOutputDev
const media::AudioParameters& output_params,
const std::string& matched_device_id) override;
void OnStreamCreated(base::SharedMemoryHandle handle,
- base::SyncSocket::Handle socket_handle) override;
+ base::SyncSocket::Handle socket_handle,
+ bool playing_automatically) override;
void OnIPCClosed() override;
protected:
@@ -86,7 +86,6 @@ class PepperPlatformAudioOutputDev
PepperPlatformAudioOutputDev();
PepperPlatformAudioOutputDev(int render_frame_id,
const std::string& device_id,
- const GURL& document_url,
base::TimeDelta authorization_timeout);
// Creates audio stream. Used for new Pepper audio output interface
@@ -133,7 +132,6 @@ class PepperPlatformAudioOutputDev
// ID of hardware output device to be used (provided session_id_ is zero)
const std::string device_id_;
- const url::Origin security_origin_;
// If |device_id_| is empty and |session_id_| is not, |matched_device_id_| is
// received in OnDeviceAuthorized().
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 1249b89a155..931e2e7408a 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -22,7 +22,6 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "cc/blink/web_layer_impl.h"
#include "cc/layers/texture_layer.h"
#include "content/common/content_constants_internal.h"
#include "content/common/frame_messages.h"
@@ -125,6 +124,7 @@
#include "third_party/blink/public/web/web_view.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/events/blink/blink_event_util.h"
+#include "ui/events/blink/web_input_event.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
@@ -134,7 +134,7 @@
#if BUILDFLAG(ENABLE_PRINTING)
// nogncheck because dependency on //printing is conditional upon
-// enable_basic_printing or enable_print_preview flags.
+// enable_basic_printing flags.
#include "printing/metafile_skia_wrapper.h" // nogncheck
#include "printing/pdf_metafile_skia.h" // nogncheck
#endif
@@ -443,7 +443,7 @@ void PepperPluginInstanceImpl::ExternalDocumentLoader::ReplayReceivedData(
document_loader->DidReceiveData(it->c_str(), it->length());
}
if (finished_loading_) {
- document_loader->DidFinishLoading(0 /* finish_time */);
+ document_loader->DidFinishLoading();
} else if (error_.get()) {
DCHECK(!finished_loading_);
document_loader->DidFail(*error_);
@@ -456,8 +456,7 @@ void PepperPluginInstanceImpl::ExternalDocumentLoader::DidReceiveData(
data_.push_back(std::string(data, data_length));
}
-void PepperPluginInstanceImpl::ExternalDocumentLoader::DidFinishLoading(
- double finish_time) {
+void PepperPluginInstanceImpl::ExternalDocumentLoader::DidFinishLoading() {
DCHECK(!finished_loading_);
if (error_.get())
@@ -542,9 +541,6 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
input_event_mask_(0),
filtered_input_event_mask_(0),
text_input_type_(kPluginDefaultTextInputType),
- text_input_caret_(0, 0, 0, 0),
- text_input_caret_bounds_(0, 0, 0, 0),
- text_input_caret_set_(false),
selection_caret_(0),
selection_anchor_(0),
pending_user_gesture_(0.0),
@@ -667,10 +663,6 @@ v8::Local<v8::Context> PepperPluginInstanceImpl::GetMainWorldContext() {
void PepperPluginInstanceImpl::Delete() {
is_deleted_ = true;
- if (render_frame_ && render_frame_->plugin_find_handler() == this) {
- render_frame_->set_plugin_find_handler(nullptr);
- }
-
// Keep a reference on the stack. See NOTE above.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
@@ -1103,7 +1095,7 @@ bool PepperPluginInstanceImpl::IsPluginAcceptingCompositionEvents() const {
}
gfx::Rect PepperPluginInstanceImpl::GetCaretBounds() const {
- if (!text_input_caret_set_) {
+ if (!text_input_caret_info_) {
// If it is never set by the plugin, use the bottom left corner.
gfx::Rect rect(view_data_.rect.point.x,
view_data_.rect.point.y + view_data_.rect.size.height,
@@ -1113,12 +1105,12 @@ gfx::Rect PepperPluginInstanceImpl::GetCaretBounds() const {
}
// TODO(kinaba) Take CSS transformation into account.
- // TODO(kinaba) Take |text_input_caret_bounds_| into account. On
- // some platforms, an "exclude rectangle" where candidate window
- // must avoid the region can be passed to IME. Currently, we pass
- // only the caret rectangle because it is the only information
- // supported uniformly in Chromium.
- gfx::Rect caret(text_input_caret_);
+ // TODO(kinaba) Take |text_input_caret_info_->caret_bounds| into account. On
+ // some platforms, an "exclude rectangle" where candidate window must avoid
+ // the region can be passed to IME. Currently, we pass only the caret
+ // rectangle because it is the only information supported uniformly in
+ // Chromium.
+ gfx::Rect caret = text_input_caret_info_->caret;
caret.Offset(view_data_.rect.point.x, view_data_.rect.point.y);
ConvertDIPToViewport(&caret);
return caret;
@@ -1520,15 +1512,87 @@ void PepperPluginInstanceImpl::SetSelectionBounds(const gfx::PointF& base,
bool PepperPluginInstanceImpl::CanEditText() {
if (!LoadPdfInterface())
return false;
+ // No reference to |this| on the stack. Do not do any more work after this.
+ // See NOTE above.
return PP_ToBool(plugin_pdf_interface_->CanEditText(pp_instance()));
}
+bool PepperPluginInstanceImpl::HasEditableText() {
+ if (!LoadPdfInterface())
+ return false;
+
+ // No reference to |this| on the stack. Do not do any more work after this.
+ // See NOTE above.
+ return PP_ToBool(plugin_pdf_interface_->HasEditableText(pp_instance()));
+}
+
void PepperPluginInstanceImpl::ReplaceSelection(const std::string& text) {
if (!LoadPdfInterface())
return;
+
+ // No reference to |this| on the stack. Do not do any more work after this.
+ // See NOTE above.
plugin_pdf_interface_->ReplaceSelection(pp_instance(), text.c_str());
}
+void PepperPluginInstanceImpl::SelectAll() {
+ if (!LoadPdfInterface())
+ return;
+
+ // Keep a reference on the stack. See NOTE above.
+ scoped_refptr<PepperPluginInstanceImpl> ref(this);
+
+ // TODO(https://crbug.com/836074) |kPlatformModifier| should be
+ // |ui::EF_PLATFORM_ACCELERATOR| (|ui::EF_COMMAND_DOWN| on Mac).
+ static const ui::EventFlags kPlatformModifier = ui::EF_CONTROL_DOWN;
+ // Synthesize a ctrl + a key event to send to the plugin and let it sort out
+ // the event. See also https://crbug.com/739529.
+ ui::KeyEvent char_event(L'A', ui::VKEY_A, kPlatformModifier);
+
+ // Also synthesize a key up event to look more like a real key press.
+ // Otherwise the plugin will not do all the required work to keep the renderer
+ // in sync.
+ ui::KeyEvent keyup_event(ui::ET_KEY_RELEASED, ui::VKEY_A, kPlatformModifier);
+
+ WebCursorInfo dummy_cursor_info;
+ HandleInputEvent(MakeWebKeyboardEvent(char_event), &dummy_cursor_info);
+ HandleInputEvent(MakeWebKeyboardEvent(keyup_event), &dummy_cursor_info);
+}
+
+bool PepperPluginInstanceImpl::CanUndo() {
+ if (!LoadPdfInterface())
+ return false;
+
+ // No reference to |this| on the stack. Do not do any more work after this.
+ // See NOTE above.
+ return PP_ToBool(plugin_pdf_interface_->CanUndo(pp_instance()));
+}
+
+bool PepperPluginInstanceImpl::CanRedo() {
+ if (!LoadPdfInterface())
+ return false;
+
+ // No reference to |this| on the stack. Do not do any more work after this.
+ // See NOTE above.
+ return PP_ToBool(plugin_pdf_interface_->CanRedo(pp_instance()));
+}
+
+void PepperPluginInstanceImpl::Undo() {
+ if (!LoadPdfInterface())
+ return;
+
+ // No reference to |this| on the stack. Do not do any more work after this.
+ // See NOTE above.
+ plugin_pdf_interface_->Undo(pp_instance());
+}
+
+void PepperPluginInstanceImpl::Redo() {
+ if (!LoadPdfInterface())
+ return;
+
+ plugin_pdf_interface_->Redo(pp_instance());
+}
+
void PepperPluginInstanceImpl::RequestSurroundingText(
size_t desired_number_of_characters) {
// Keep a reference on the stack. See NOTE above.
@@ -1900,7 +1964,8 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) {
NOTREACHED();
return 0;
}
- int num_pages = 0;
+
+ int num_pages;
PP_PrintSettings_Dev print_settings;
print_settings.printable_area = PP_FromGfxRect(print_params.printable_area);
print_settings.content_area = PP_FromGfxRect(print_params.print_content_area);
@@ -1911,9 +1976,20 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) {
print_settings.print_scaling_option =
static_cast<PP_PrintScalingOption_Dev>(print_params.print_scaling_option);
print_settings.format = format;
- num_pages = plugin_print_interface_->Begin(pp_instance(), &print_settings);
+
+ if (LoadPdfInterface()) {
+ PP_PdfPrintSettings_Dev pdf_print_settings;
+ pdf_print_settings.num_pages_per_sheet = print_params.num_pages_per_sheet;
+ pdf_print_settings.scale_factor = print_params.scale_factor;
+
+ num_pages = plugin_pdf_interface_->PrintBegin(
+ pp_instance(), &print_settings, &pdf_print_settings);
+ } else {
+ num_pages = plugin_print_interface_->Begin(pp_instance(), &print_settings);
+ }
if (!num_pages)
return 0;
+
current_print_settings_ = print_settings;
metafile_ = nullptr;
ranges_.clear();
@@ -2143,10 +2219,9 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
if (texture_layer_ || compositor_layer_) {
if (!layer_bound_to_fullscreen_)
- container_->SetWebLayer(nullptr);
+ container_->SetCcLayer(nullptr, false);
else if (fullscreen_container_)
fullscreen_container_->SetLayer(nullptr);
- web_layer_.reset();
if (texture_layer_) {
texture_layer_->ClearClient();
texture_layer_ = nullptr;
@@ -2154,6 +2229,7 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
compositor_layer_ = nullptr;
}
+ cc::Layer* either_layer = nullptr;
if (want_texture_layer) {
bool opaque = false;
if (want_3d_layer) {
@@ -2170,28 +2246,24 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
texture_layer_->SetFlipped(false);
}
- auto layer = std::make_unique<cc_blink::WebLayerImpl>(texture_layer_);
// Ignore transparency in fullscreen, since that's what Flash always
// wants to do, and that lets it not recreate a context if
// wmode=transparent was specified.
opaque = opaque || fullscreen_container_;
- layer->layer()->SetContentsOpaque(opaque);
- layer->SetContentsOpaqueIsFixed(true);
- web_layer_ = std::move(layer);
+ texture_layer_->SetContentsOpaque(opaque);
+ either_layer = texture_layer_.get();
} else if (want_compositor_layer) {
compositor_layer_ = bound_compositor_->layer();
- web_layer_ = std::make_unique<cc_blink::WebLayerImpl>(compositor_layer_);
+ either_layer = compositor_layer_.get();
}
- if (web_layer_) {
- if (fullscreen_container_) {
- fullscreen_container_->SetLayer(web_layer_.get());
- } else {
- container_->SetWebLayer(web_layer_.get());
- }
- if (is_flash_plugin_) {
- web_layer_->CcLayer()->SetMayContainVideo(true);
- }
+ if (either_layer) {
+ if (fullscreen_container_)
+ fullscreen_container_->SetLayer(either_layer);
+ else
+ container_->SetCcLayer(either_layer, true);
+ if (is_flash_plugin_)
+ either_layer->SetMayContainVideo(true);
}
layer_bound_to_fullscreen_ = !!fullscreen_container_;
@@ -2536,8 +2608,7 @@ uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputSampleRate(
PP_Instance instance) {
return render_frame() ? AudioDeviceFactory::GetOutputDeviceInfo(
render_frame()->GetRoutingID(),
- 0 /* session_id */, std::string() /* device_id */,
- url::Origin::Create(document_url()))
+ 0 /* session_id */, std::string() /* device_id */)
.output_params()
.sample_rate()
: 0;
@@ -2547,8 +2618,8 @@ uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputBufferSize(
PP_Instance instance) {
return render_frame() ? AudioDeviceFactory::GetOutputDeviceInfo(
render_frame()->GetRoutingID(),
- 0 /* session_id */, std::string() /* device_id */,
- url::Origin::Create(document_url()))
+ 0 /* session_id */, std::string() /* device_id */
+ )
.output_params()
.frames_per_buffer()
: 0;
@@ -2570,7 +2641,7 @@ void PepperPluginInstanceImpl::SetPluginToHandleFindRequests(
render_frame_->GetRenderView()->GetMainRenderFrame() == render_frame_;
if (!is_main_frame)
return;
- render_frame_->set_plugin_find_handler(this);
+ container_->UsePluginAsFindHandler();
}
void PepperPluginInstanceImpl::NumberOfFindResultsChanged(
@@ -2804,9 +2875,8 @@ void PepperPluginInstanceImpl::UpdateCaretPosition(
const PP_Rect& bounding_box) {
if (!render_frame_)
return;
- text_input_caret_ = PP_ToGfxRect(caret);
- text_input_caret_bounds_ = PP_ToGfxRect(bounding_box);
- text_input_caret_set_ = true;
+ TextInputCaretInfo info = {PP_ToGfxRect(caret), PP_ToGfxRect(bounding_box)};
+ text_input_caret_info_ = std::move(info);
render_frame_->PepperCaretPositionChanged(this);
}
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
index c1819eb3ab6..6d554119935 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -20,6 +20,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "cc/layers/content_layer_client.h"
@@ -73,7 +74,6 @@ class SkBitmap;
namespace blink {
class WebCoalescedInputEvent;
class WebInputEvent;
-class WebLayer;
class WebMouseEvent;
class WebPluginContainer;
class WebURLResponse;
@@ -416,7 +416,13 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
void SetSelectionBounds(const gfx::PointF& base,
const gfx::PointF& extent) override;
bool CanEditText() override;
+ bool HasEditableText() override;
void ReplaceSelection(const std::string& text) override;
+ void SelectAll() override;
+ bool CanUndo() override;
+ bool CanRedo() override;
+ void Undo() override;
+ void Redo() override;
// PPB_Instance_API implementation.
PP_Bool BindGraphics(PP_Instance instance, PP_Resource device) override;
@@ -540,7 +546,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// blink::WebAssociatedURLLoaderClient implementation.
void DidReceiveData(const char* data, int data_length) override;
- void DidFinishLoading(double finish_time) override;
+ void DidFinishLoading() override;
void DidFail(const blink::WebURLError& error) override;
private:
@@ -706,7 +712,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
blink::WebPluginContainer* container_;
scoped_refptr<cc::Layer> compositor_layer_;
scoped_refptr<cc::TextureLayer> texture_layer_;
- std::unique_ptr<blink::WebLayer> web_layer_;
bool layer_bound_to_fullscreen_;
bool layer_is_hardware_;
@@ -857,10 +862,12 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
uint32_t filtered_input_event_mask_;
// Text composition status.
+ struct TextInputCaretInfo {
+ gfx::Rect caret;
+ gfx::Rect caret_bounds;
+ };
+ base::Optional<TextInputCaretInfo> text_input_caret_info_;
ui::TextInputType text_input_type_;
- gfx::Rect text_input_caret_;
- gfx::Rect text_input_caret_bounds_;
- bool text_input_caret_set_;
// Text selection status.
std::string surrounding_text_;
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
index 269ac2300e0..3d2914bfb7d 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
@@ -167,7 +167,7 @@ void PepperURLLoaderHost::DidReceiveData(const char* data, int data_length) {
SendUpdateToPlugin(std::move(message));
}
-void PepperURLLoaderHost::DidFinishLoading(double finish_time) {
+void PepperURLLoaderHost::DidFinishLoading() {
// Note that |loader| will be NULL for document loads.
SendUpdateToPlugin(
std::make_unique<PpapiPluginMsg_URLLoader_FinishedLoading>(PP_OK));
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.h b/chromium/content/renderer/pepper/pepper_url_loader_host.h
index a6ccb12b85e..1f3510907d3 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.h
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.h
@@ -52,7 +52,7 @@ class PepperURLLoaderHost : public ppapi::host::ResourceHost,
void DidReceiveResponse(const blink::WebURLResponse& response) override;
void DidDownloadData(int data_length) override;
void DidReceiveData(const char* data, int data_length) override;
- void DidFinishLoading(double finish_time) override;
+ void DidFinishLoading() override;
void DidFail(const blink::WebURLError& error) override;
private:
diff --git a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
index 3d35e16725c..845aca9a3ef 100644
--- a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
@@ -131,10 +131,10 @@ TEST_F(URLRequestInfoTest, StreamToFile) {
EXPECT_FALSE(GetDownloadToFile());
- EXPECT_TRUE(SetBooleanProperty(PP_URLREQUESTPROPERTY_STREAMTOFILE, true));
- EXPECT_TRUE(GetDownloadToFile());
+ EXPECT_FALSE(SetBooleanProperty(PP_URLREQUESTPROPERTY_STREAMTOFILE, true));
+ EXPECT_FALSE(GetDownloadToFile());
- EXPECT_TRUE(SetBooleanProperty(PP_URLREQUESTPROPERTY_STREAMTOFILE, false));
+ EXPECT_FALSE(SetBooleanProperty(PP_URLREQUESTPROPERTY_STREAMTOFILE, false));
EXPECT_FALSE(GetDownloadToFile());
}
diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.h b/chromium/content/renderer/pepper/pepper_video_encoder_host.h
index 4e1e12c6739..264c668cdc8 100644
--- a/chromium/content/renderer/pepper/pepper_video_encoder_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.h
@@ -78,6 +78,10 @@ class CONTENT_EXPORT PepperVideoEncoderHost
void OnGpuControlLostContext() final;
void OnGpuControlLostContextMaybeReentrant() final;
void OnGpuControlErrorMessage(const char* msg, int id) final {}
+ void OnGpuControlSwapBuffersCompleted(
+ const gpu::SwapBuffersCompleteParams& params) final {}
+ void OnSwapBufferPresented(uint64_t swap_id,
+ const gfx::PresentationFeedback& feedback) final {}
int32_t OnHostMsgGetSupportedProfiles(
ppapi::host::HostMessageContext* context);
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
index a45960809f5..a2701cacf15 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -11,6 +11,7 @@
#include "base/debug/crash_logging.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/pepper/message_channel.h"
@@ -22,7 +23,8 @@
#include "content/renderer/renderer_blink_platform_impl.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/var_tracker.h"
-#include "third_party/blink/public/platform/web_clipboard.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/public/platform/web_rect.h"
@@ -256,7 +258,7 @@ void PepperWebPluginImpl::DidFinishLoading() {
blink::WebAssociatedURLLoaderClient* document_loader =
instance_->document_loader();
if (document_loader)
- document_loader->DidFinishLoading(0.0);
+ document_loader->DidFinishLoading();
}
void PepperWebPluginImpl::DidFailLoading(const blink::WebURLError& error) {
@@ -294,6 +296,18 @@ bool PepperWebPluginImpl::CanEditText() const {
return instance_ && instance_->CanEditText();
}
+bool PepperWebPluginImpl::HasEditableText() const {
+ return instance_ && instance_->HasEditableText();
+}
+
+bool PepperWebPluginImpl::CanUndo() const {
+ return instance_ && instance_->CanUndo();
+}
+
+bool PepperWebPluginImpl::CanRedo() const {
+ return instance_ && instance_->CanRedo();
+}
+
bool PepperWebPluginImpl::ExecuteEditCommand(const blink::WebString& name) {
return ExecuteEditCommand(name, WebString());
}
@@ -307,27 +321,67 @@ bool PepperWebPluginImpl::ExecuteEditCommand(const blink::WebString& name,
if (!HasSelection() || !CanEditText())
return false;
- blink::Platform::Current()->Clipboard()->WriteHTML(
- SelectionAsMarkup(), WebURL(), SelectionAsText(), false);
+ if (!clipboard_) {
+ blink::Platform::Current()->GetConnector()->BindInterface(
+ blink::Platform::Current()->GetBrowserServiceName(), &clipboard_);
+ }
+ base::string16 markup;
+ base::string16 text;
+ if (instance_) {
+ markup = instance_->GetSelectedText(true);
+ text = instance_->GetSelectedText(false);
+ }
+ clipboard_->WriteHtml(ui::CLIPBOARD_TYPE_COPY_PASTE, markup, GURL());
+ clipboard_->WriteText(ui::CLIPBOARD_TYPE_COPY_PASTE, text);
+ clipboard_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE);
instance_->ReplaceSelection("");
return true;
}
+
// If the clipboard contains something other than text (e.g. an image),
- // WebClipboard::ReadPlainText() returns an empty string. The empty string is
+ // ClipboardHost::ReadText() returns an empty string. The empty string is
// then pasted, replacing any selected text. This behavior is consistent with
// that of HTML text form fields.
if (name == "Paste" || name == "PasteAndMatchStyle") {
if (!CanEditText())
return false;
- blink::WebString text =
- blink::Platform::Current()->Clipboard()->ReadPlainText(
- blink::mojom::ClipboardBuffer::kStandard);
+ if (!clipboard_) {
+ blink::Platform::Current()->GetConnector()->BindInterface(
+ blink::Platform::Current()->GetBrowserServiceName(), &clipboard_);
+ }
+ base::string16 text;
+ clipboard_->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &text);
+
+ instance_->ReplaceSelection(base::UTF16ToUTF8(text));
+ return true;
+ }
+
+ if (name == "SelectAll") {
+ if (!CanEditText())
+ return false;
+
+ instance_->SelectAll();
+ return true;
+ }
+
+ if (name == "Undo") {
+ if (!CanUndo())
+ return false;
+
+ instance_->Undo();
+ return true;
+ }
+
+ if (name == "Redo") {
+ if (!CanRedo())
+ return false;
- instance_->ReplaceSelection(text.Utf8());
+ instance_->Redo();
return true;
}
+
return false;
}
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.h b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
index a53cb887bcf..64e09efce8f 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.h
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "ppapi/c/pp_var.h"
+#include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "ui/gfx/geometry/rect.h"
@@ -61,6 +62,9 @@ class PepperWebPluginImpl : public blink::WebPlugin {
blink::WebString SelectionAsText() const override;
blink::WebString SelectionAsMarkup() const override;
bool CanEditText() const override;
+ bool HasEditableText() const override;
+ bool CanUndo() const override;
+ bool CanRedo() const override;
bool ExecuteEditCommand(const blink::WebString& name) override;
bool ExecuteEditCommand(const blink::WebString& name,
const blink::WebString& value) override;
@@ -101,6 +105,7 @@ class PepperWebPluginImpl : public blink::WebPlugin {
gfx::Rect plugin_rect_;
PP_Var instance_object_;
blink::WebPluginContainer* container_;
+ blink::mojom::ClipboardHostPtr clipboard_;
DISALLOW_COPY_AND_ASSIGN(PepperWebPluginImpl);
};
diff --git a/chromium/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc b/chromium/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc
index 8dfd8c37cbe..1165db9b75e 100644
--- a/chromium/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc
+++ b/chromium/content/renderer/pepper/plugin_instance_throttler_impl_unittest.cc
@@ -67,9 +67,9 @@ class PluginInstanceThrottlerImplTest
bool expect_consumed,
bool expect_throttled,
int expect_change_callback_count) {
- blink::WebMouseEvent event(
- event_type, blink::WebInputEvent::Modifiers::kLeftButtonDown,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebMouseEvent event(event_type,
+ blink::WebInputEvent::Modifiers::kLeftButtonDown,
+ ui::EventTimeForNow());
EXPECT_EQ(expect_consumed, throttler()->ConsumeInputEvent(event));
EXPECT_EQ(expect_throttled, throttler()->IsThrottled());
EXPECT_EQ(expect_change_callback_count, change_callback_calls());
@@ -206,10 +206,9 @@ TEST_F(PluginInstanceThrottlerImplTest, ThrottleOnLeftClickOnly) {
EXPECT_TRUE(throttler()->IsThrottled());
EXPECT_EQ(1, change_callback_calls());
- blink::WebMouseEvent event(
- blink::WebInputEvent::Type::kMouseUp,
- blink::WebInputEvent::Modifiers::kRightButtonDown,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebMouseEvent event(blink::WebInputEvent::Type::kMouseUp,
+ blink::WebInputEvent::Modifiers::kRightButtonDown,
+ ui::EventTimeForNow());
EXPECT_FALSE(throttler()->ConsumeInputEvent(event));
EXPECT_TRUE(throttler()->IsThrottled());
diff --git a/chromium/content/renderer/pepper/plugin_module.cc b/chromium/content/renderer/pepper/plugin_module.cc
index 8659dd80113..48954c1da95 100644
--- a/chromium/content/renderer/pepper/plugin_module.cc
+++ b/chromium/content/renderer/pepper/plugin_module.cc
@@ -15,7 +15,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "build/build_config.h"
diff --git a/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.cc b/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.cc
index e5e4ed2e129..ec02280deb6 100644
--- a/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.cc
@@ -5,7 +5,6 @@
#include "content/renderer/pepper/ppb_flash_message_loop_impl.h"
#include "base/callback.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "ppapi/c/pp_errors.h"
#include "third_party/blink/public/web/web_view.h"
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
index 8d65ba893f2..50f971cd3d4 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -330,6 +330,9 @@ void PPB_Graphics3D_Impl::OnGpuControlLostContextMaybeReentrant() {
// No internal state to update on lost context.
}
+void PPB_Graphics3D_Impl::OnGpuControlSwapBuffersCompleted(
+ const gpu::SwapBuffersCompleteParams& params) {}
+
void PPB_Graphics3D_Impl::OnSwapBuffers() {
if (HasPendingSwap()) {
// If we're off-screen, no need to trigger and wait for compositing.
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
index 269fe939857..396faa7e1aa 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -89,6 +89,10 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared,
void OnGpuControlLostContext() final;
void OnGpuControlLostContextMaybeReentrant() final;
void OnGpuControlErrorMessage(const char* msg, int id) final;
+ void OnGpuControlSwapBuffersCompleted(
+ const gpu::SwapBuffersCompleteParams& params) final;
+ void OnSwapBufferPresented(uint64_t swap_id,
+ const gfx::PresentationFeedback& feedback) final {}
// Other notifications from the GPU process.
void OnSwapBuffers();
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
index 3437b190f03..e1d813c0896 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
@@ -7,7 +7,6 @@
#include <string>
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
diff --git a/chromium/content/renderer/pepper/resource_converter.cc b/chromium/content/renderer/pepper/resource_converter.cc
index ce072cd15fa..c2c6b691472 100644
--- a/chromium/content/renderer/pepper/resource_converter.cc
+++ b/chromium/content/renderer/pepper/resource_converter.cc
@@ -7,7 +7,6 @@
#include <stddef.h>
#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/pepper/pepper_file_system_host.h"
#include "content/renderer/pepper/pepper_media_stream_audio_track_host.h"
@@ -164,7 +163,6 @@ bool DOMMediaStreamTrackToResource(
std::unique_ptr<IPC::Message>* create_message) {
DCHECK(!dom_media_stream_track.IsNull());
*pending_renderer_id = 0;
-#if BUILDFLAG(ENABLE_WEBRTC)
const blink::WebMediaStreamTrack track = dom_media_stream_track.Component();
const std::string id = track.Source().Id().Utf8();
@@ -190,7 +188,6 @@ bool DOMMediaStreamTrackToResource(
new PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost(id));
return true;
}
-#endif
return false;
}
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.cc b/chromium/content/renderer/pepper/video_decoder_shim.cc
index c6522e4f6cf..231a4f63044 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_decoder_shim.cc
@@ -365,13 +365,13 @@ void VideoDecoderShim::YUVConverter::Convert(
// numbers that are used in the transformation from YUV to RGB color values.
// They are taken from the following webpage:
// http://www.fourcc.org/fccyvrgb.php
- const float yuv_to_rgb_rec601[9] = {
+ static const float yuv_to_rgb_rec601[9] = {
1.164f, 1.164f, 1.164f, 0.0f, -.391f, 2.018f, 1.596f, -.813f, 0.0f,
};
- const float yuv_to_rgb_jpeg[9] = {
+ static const float yuv_to_rgb_jpeg[9] = {
1.f, 1.f, 1.f, 0.0f, -.34414f, 1.772f, 1.402f, -.71414f, 0.0f,
};
- const float yuv_to_rgb_rec709[9] = {
+ static const float yuv_to_rgb_rec709[9] = {
1.164f, 1.164f, 1.164f, 0.0f, -0.213f, 2.112f, 1.793f, -0.533f, 0.0f,
};
@@ -381,11 +381,11 @@ void VideoDecoderShim::YUVConverter::Convert(
// Y - 16 : Gives 16 values of head and footroom for overshooting
// U - 128 : Turns unsigned U into signed U [-128,127]
// V - 128 : Turns unsigned V into signed V [-128,127]
- const float yuv_adjust_constrained[3] = {
+ static const float yuv_adjust_constrained[3] = {
-0.0625f, -0.5f, -0.5f,
};
// Same as above, but without the head and footroom.
- const float yuv_adjust_full[3] = {
+ static const float yuv_adjust_full[3] = {
0.0f, -0.5f, -0.5f,
};
diff --git a/chromium/content/renderer/presentation/OWNERS b/chromium/content/renderer/presentation/OWNERS
deleted file mode 100644
index 51249427f7e..00000000000
--- a/chromium/content/renderer/presentation/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://content/browser/presentation/OWNERS
diff --git a/chromium/content/renderer/presentation/presentation_dispatcher.cc b/chromium/content/renderer/presentation/presentation_dispatcher.cc
deleted file mode 100644
index 5743fe82104..00000000000
--- a/chromium/content/renderer/presentation/presentation_dispatcher.cc
+++ /dev/null
@@ -1,46 +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.
-
-#include "content/renderer/presentation/presentation_dispatcher.h"
-
-#include "content/public/renderer/render_frame.h"
-#include "third_party/blink/public/platform/modules/presentation/web_presentation_receiver.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-
-namespace content {
-
-PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame)
- : RenderFrameObserver(render_frame), receiver_(nullptr) {}
-
-PresentationDispatcher::~PresentationDispatcher() {
-}
-
-void PresentationDispatcher::SetReceiver(
- blink::WebPresentationReceiver* receiver) {
- receiver_ = receiver;
-
- DCHECK(!render_frame() || render_frame()->IsMainFrame());
-
- // Init |receiver_| after loading document.
- if (receiver_ && render_frame() && render_frame()->GetWebFrame() &&
- !render_frame()->GetWebFrame()->IsLoading()) {
- receiver_->Init();
- }
-}
-
-void PresentationDispatcher::DidFinishDocumentLoad() {
- if (receiver_)
- receiver_->Init();
-}
-
-void PresentationDispatcher::OnDestruct() {
- delete this;
-}
-
-void PresentationDispatcher::WidgetWillClose() {
- if (receiver_)
- receiver_->OnReceiverTerminated();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/presentation/presentation_dispatcher.h b/chromium/content/renderer/presentation/presentation_dispatcher.h
deleted file mode 100644
index 294ff8c0b50..00000000000
--- a/chromium/content/renderer/presentation/presentation_dispatcher.h
+++ /dev/null
@@ -1,67 +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 CONTENT_RENDERER_PRESENTATION_PRESENTATION_DISPATCHER_H_
-#define CONTENT_RENDERER_PRESENTATION_PRESENTATION_DISPATCHER_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/public/renderer/render_frame_observer.h"
-#include "third_party/blink/public/platform/modules/presentation/web_presentation_client.h"
-
-namespace blink {
-class WebPresentationReceiver;
-} // namespace blink
-
-namespace content {
-
-// PresentationDispatcher is a delegate for Presentation API used by
-// Blink. It forwards the calls to the Mojo PresentationService.
-// NOTE: This class is being removed as part of the Onion Soup effort.
-class CONTENT_EXPORT PresentationDispatcher
- : public RenderFrameObserver,
- public blink::WebPresentationClient {
- public:
- explicit PresentationDispatcher(RenderFrame* render_frame);
- ~PresentationDispatcher() override;
-
- private:
- friend class TestPresentationDispatcher;
- friend class PresentationDispatcherTest;
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest, TestStartPresentation);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestStartPresentationError);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestReconnectPresentation);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestReconnectPresentationError);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestReconnectPresentationNoConnection);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestOnReceiverConnectionAvailable);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest, TestCloseConnection);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestTerminatePresentation);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestListenForScreenAvailability);
- FRIEND_TEST_ALL_PREFIXES(PresentationDispatcherTest,
- TestSetDefaultPresentationUrls);
-
- // WebPresentationClient implementation.
- void SetReceiver(blink::WebPresentationReceiver*) override;
-
- // RenderFrameObserver implementation.
- void DidFinishDocumentLoad() override;
- void OnDestruct() override;
- void WidgetWillClose() override;
-
- // Used as a weak reference. Can be null since lifetime is bound to the frame.
- blink::WebPresentationReceiver* receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(PresentationDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PRESENTATION_PRESENTATION_DISPATCHER_H_
diff --git a/chromium/content/renderer/push_messaging/push_messaging_client.cc b/chromium/content/renderer/push_messaging/push_messaging_client.cc
index 7ab8191e0be..9fc24d41d5d 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_client.cc
+++ b/chromium/content/renderer/push_messaging/push_messaging_client.cc
@@ -17,7 +17,7 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
#include "services/service_manager/public/cpp/connector.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h"
+#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
#include "third_party/blink/public/platform/modules/push_messaging/web_push_error.h"
#include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription.h"
#include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription_options.h"
@@ -78,7 +78,7 @@ void PushMessagingClient::DidGetManifest(
bool user_gesture,
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
const GURL& manifest_url,
- const Manifest& manifest) {
+ const blink::Manifest& manifest) {
// Get the sender_info from the manifest since it wasn't provided by
// the caller.
if (manifest.IsEmpty()) {
diff --git a/chromium/content/renderer/push_messaging/push_messaging_client.h b/chromium/content/renderer/push_messaging/push_messaging_client.h
index 20142f3e8d8..c8d6e8e3bb5 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_client.h
+++ b/chromium/content/renderer/push_messaging/push_messaging_client.h
@@ -14,12 +14,13 @@
#include "base/macros.h"
#include "content/common/push_messaging.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest.mojom.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
#include "third_party/blink/public/platform/modules/push_messaging/web_push_client.h"
class GURL;
namespace blink {
+struct Manifest;
struct WebPushSubscriptionOptions;
}
@@ -29,7 +30,6 @@ namespace mojom {
enum class PushRegistrationStatus;
}
-struct Manifest;
struct PushSubscriptionOptions;
class PushMessagingClient : public RenderFrameObserver,
@@ -55,7 +55,7 @@ class PushMessagingClient : public RenderFrameObserver,
bool user_gesture,
std::unique_ptr<blink::WebPushSubscriptionCallbacks> callbacks,
const GURL& manifest_url,
- const Manifest& manifest);
+ const blink::Manifest& manifest);
void DoSubscribe(
blink::WebServiceWorkerRegistration* service_worker_registration,
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index 5efb96acfd7..c027c4df342 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -47,7 +47,7 @@
#include "content/common/associated_interface_provider_impl.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_constants_internal.h"
-#include "content/common/content_security_policy/csp_context.h"
+#include "content/common/content_security_policy/content_security_policy.h"
#include "content/common/content_security_policy_header.h"
#include "content/common/download/mhtml_save_status.h"
#include "content/common/edit_command.h"
@@ -57,13 +57,13 @@
#include "content/common/input_messages.h"
#include "content/common/navigation_params.h"
#include "content/common/page_messages.h"
+#include "content/common/possibly_associated_wrapper_shared_url_loader_factory.h"
#include "content/common/renderer_host.mojom.h"
#include "content/common/savable_subframe.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/appcache_info.h"
#include "content/public/common/bind_interface_helpers.h"
#include "content/public/common/bindings_policy.h"
@@ -107,8 +107,8 @@
#include "content/renderer/image_downloader/image_downloader_impl.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/input/frame_input_handler_impl.h"
-#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/input/input_target_client_impl.h"
+#include "content/renderer/input/widget_input_handler_manager.h"
#include "content/renderer/installedapp/related_apps_fetcher.h"
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/loader/request_extra_data.h"
@@ -120,14 +120,15 @@
#include "content/renderer/manifest/manifest_manager.h"
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/media/audio_output_ipc_factory.h"
+#include "content/renderer/media/audio_renderer_sink_cache.h"
#include "content/renderer/media/media_permission_dispatcher.h"
#include "content/renderer/media/stream/media_stream_device_observer.h"
#include "content/renderer/media/stream/user_media_client_impl.h"
+#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
#include "content/renderer/mojo/blink_interface_registry_impl.h"
#include "content/renderer/navigation_state_impl.h"
#include "content/renderer/pepper/pepper_audio_controller.h"
#include "content/renderer/pepper/plugin_instance_throttler_impl.h"
-#include "content/renderer/presentation/presentation_dispatcher.h"
#include "content/renderer/push_messaging/push_messaging_client.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process.h"
@@ -181,7 +182,6 @@
#include "third_party/blink/public/platform/web_media_player_source.h"
#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
@@ -231,10 +231,6 @@
#include "content/renderer/pepper/plugin_module.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
-#endif
-
#if defined(OS_ANDROID)
#include <cpu-features.h>
@@ -327,6 +323,9 @@ const base::Feature kConsumeGestureOnNavigation = {
const int kExtraCharsBeforeAndAfterSelection = 100;
+// Maximum number of burst download requests allowed.
+const int kBurstDownloadLimit = 10;
+
const PreviewsState kDisabledPreviewsBits =
PREVIEWS_OFF | PREVIEWS_NO_TRANSFORM;
@@ -422,7 +421,7 @@ bool IsTopLevelNavigation(WebFrame* frame) {
WebURLRequest CreateURLRequestForNavigation(
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
- std::unique_ptr<StreamOverrideParameters> stream_override,
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override,
bool is_view_source_mode_enabled,
bool is_same_document_navigation) {
// Use the original navigation url to construct the WebURLRequest. The
@@ -462,7 +461,7 @@ WebURLRequest CreateURLRequestForNavigation(
static_cast<WebURLRequest::PreviewsState>(common_params.previews_state));
auto extra_data = std::make_unique<RequestExtraData>();
- extra_data->set_stream_override(std::move(stream_override));
+ extra_data->set_navigation_response_override(std::move(response_override));
extra_data->set_navigation_initiated_by_renderer(
request_params.nav_entry_id == 0);
request.SetExtraData(std::move(extra_data));
@@ -557,9 +556,10 @@ CommonNavigationParams MakeCommonNavigationParams(
GetRequestBodyForWebURLRequest(info.url_request), source_location,
should_check_main_world_csp, false /* started_from_context_menu */,
info.url_request.HasUserGesture(),
- info.url_request.GetSuggestedFilename().has_value()
- ? base::Optional<std::string>(
- info.url_request.GetSuggestedFilename()->Utf8())
+ BuildContentSecurityPolicyList(info.url_request.GetNavigationCSP()),
+ info.url_request.GetNavigationCSP().self_source.has_value()
+ ? base::Optional<CSPSource>(BuildCSPSource(
+ info.url_request.GetNavigationCSP().self_source.value()))
: base::nullopt);
}
@@ -724,10 +724,6 @@ MhtmlSaveStatus WriteMHTMLToDisk(std::vector<WebThreadSafeData> mhtml_contents,
return save_status;
}
-double ConvertToBlinkTime(const base::TimeTicks& time_ticks) {
- return (time_ticks - base::TimeTicks()).InSecondsF();
-}
-
FaviconURL::IconType ToFaviconType(blink::WebIconURL::Type type) {
switch (type) {
case blink::WebIconURL::kTypeFavicon:
@@ -807,6 +803,19 @@ void RecordReadyToCommitUntilCommitHistogram(base::TimeDelta delay,
}
}
+blink::mojom::BlobURLTokenPtrInfo CloneBlobURLToken(
+ mojo::MessagePipeHandle handle) {
+ if (!handle.is_valid())
+ return nullptr;
+ blink::mojom::BlobURLTokenPtrInfo result;
+ blink::mojom::BlobURLTokenPtr token(
+ blink::mojom::BlobURLTokenPtrInfo(mojo::ScopedMessagePipeHandle(handle),
+ blink::mojom::BlobURLToken::Version_));
+ token->Clone(MakeRequest(&result));
+ ignore_result(token.PassInterface().PassHandle().release());
+ return result;
+}
+
} // namespace
class RenderFrameImpl::FrameURLLoaderFactory
@@ -1300,14 +1309,12 @@ RenderFrameImpl::RenderFrameImpl(CreateParams params)
proxy_routing_id_(MSG_ROUTING_NONE),
#if BUILDFLAG(ENABLE_PLUGINS)
plugin_power_saver_helper_(nullptr),
- plugin_find_handler_(nullptr),
#endif
cookie_jar_(this),
selection_text_offset_(0),
selection_range_(gfx::Range::InvalidRange()),
handling_select_range_(false),
web_user_media_client_(nullptr),
- presentation_dispatcher_(nullptr),
push_messaging_client_(nullptr),
render_accessibility_(nullptr),
previews_state_(PREVIEWS_UNSPECIFIED),
@@ -1391,13 +1398,6 @@ RenderFrameImpl::~RenderFrameImpl() {
base::trace_event::TraceLog::GetInstance()->RemoveProcessLabel(routing_id_);
- // Unregister from InputHandlerManager. render_thread may be NULL in tests.
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- InputHandlerManager* input_handler_manager =
- render_thread ? render_thread->input_handler_manager() : nullptr;
- if (input_handler_manager)
- input_handler_manager->UnregisterRoutingID(GetRoutingID());
-
if (auto* factory = AudioOutputIPCFactory::get())
factory->MaybeDeregisterRemoteFactory(GetRoutingID());
@@ -1450,19 +1450,11 @@ void RenderFrameImpl::Initialize() {
// embedder can call GetWebFrame on any RenderFrame.
GetContentClient()->renderer()->RenderFrameCreated(this);
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- // render_thread may be NULL in tests.
- InputHandlerManager* input_handler_manager =
- render_thread ? render_thread->input_handler_manager() : nullptr;
- if (input_handler_manager) {
- DCHECK(render_view_->HasAddedInputHandler());
- input_handler_manager->RegisterAssociatedRenderFrameRoutingID(
- GetRoutingID(), render_view_->GetRoutingID());
- }
-
// AudioOutputIPCFactory may be null in tests.
if (auto* factory = AudioOutputIPCFactory::get())
- factory->MaybeRegisterRemoteFactory(GetRoutingID(), GetRemoteInterfaces());
+ factory->RegisterRemoteFactory(GetRoutingID(), GetRemoteInterfaces());
+
+ AudioRendererSinkCache::ObserveFrame(this);
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
@@ -1539,7 +1531,11 @@ void RenderFrameImpl::PepperCancelComposition(
PepperPluginInstanceImpl* instance) {
if (instance != focused_pepper_plugin_)
return;
- Send(new InputHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));
+ if (mojom::WidgetInputHandlerHost* host = GetRenderWidget()
+ ->widget_input_handler_manager()
+ ->GetWidgetInputHandlerHost()) {
+ host->ImeCancelComposition();
+ }
#if defined(OS_MACOSX) || defined(USE_AURA)
GetRenderWidget()->UpdateCompositionInfo(
false /* not an immediate request */);
@@ -1733,38 +1729,8 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
#if BUILDFLAG(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER(FrameMsg_SetPepperVolume, OnSetPepperVolume)
#endif
- IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
- IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
- IPC_MESSAGE_HANDLER(InputMsg_Cut, OnCut)
- IPC_MESSAGE_HANDLER(InputMsg_Copy, OnCopy)
- IPC_MESSAGE_HANDLER(InputMsg_Paste, OnPaste)
- IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
- IPC_MESSAGE_HANDLER(InputMsg_Delete, OnDelete)
- IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
- IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
- IPC_MESSAGE_HANDLER(InputMsg_AdjustSelectionByCharacterOffset,
- OnAdjustSelectionByCharacterOffset)
- IPC_MESSAGE_HANDLER(InputMsg_CollapseSelection, OnCollapseSelection)
- IPC_MESSAGE_HANDLER(InputMsg_MoveRangeSelectionExtent,
- OnMoveRangeSelectionExtent)
- IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
- IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
- IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret)
- IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect,
- OnScrollFocusedEditableNodeIntoRect)
IPC_MESSAGE_HANDLER(FrameMsg_CopyImageAt, OnCopyImageAt)
IPC_MESSAGE_HANDLER(FrameMsg_SaveImageAt, OnSaveImageAt)
- IPC_MESSAGE_HANDLER(InputMsg_ExtendSelectionAndDelete,
- OnExtendSelectionAndDelete)
- IPC_MESSAGE_HANDLER(InputMsg_DeleteSurroundingText, OnDeleteSurroundingText)
- IPC_MESSAGE_HANDLER(InputMsg_DeleteSurroundingTextInCodePoints,
- OnDeleteSurroundingTextInCodePoints)
- IPC_MESSAGE_HANDLER(InputMsg_SetCompositionFromExistingText,
- OnSetCompositionFromExistingText)
- IPC_MESSAGE_HANDLER(InputMsg_SetEditableSelectionOffsets,
- OnSetEditableSelectionOffsets)
- IPC_MESSAGE_HANDLER(InputMsg_ExecuteNoValueEditCommand,
- OnExecuteNoValueEditCommand)
IPC_MESSAGE_HANDLER(FrameMsg_AddMessageToConsole, OnAddMessageToConsole)
IPC_MESSAGE_HANDLER(FrameMsg_JavaScriptExecuteRequest,
OnJavaScriptExecuteRequest)
@@ -1801,8 +1767,6 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
OnGetSerializedHtmlWithLocalLinks)
IPC_MESSAGE_HANDLER(FrameMsg_SerializeAsMHTML, OnSerializeAsMHTML)
IPC_MESSAGE_HANDLER(FrameMsg_Find, OnFind)
- IPC_MESSAGE_HANDLER(FrameMsg_ClearActiveFindMatch, OnClearActiveFindMatch)
- IPC_MESSAGE_HANDLER(FrameMsg_StopFinding, OnStopFinding)
IPC_MESSAGE_HANDLER(FrameMsg_EnableViewSourceMode, OnEnableViewSourceMode)
IPC_MESSAGE_HANDLER(FrameMsg_SuppressFurtherDialogs,
OnSuppressFurtherDialogs)
@@ -1815,14 +1779,6 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
OnSetOverlayRoutingToken)
IPC_MESSAGE_HANDLER(FrameMsg_NotifyUserActivation, OnNotifyUserActivation)
-#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(FrameMsg_ActivateNearestFindResult,
- OnActivateNearestFindResult)
- IPC_MESSAGE_HANDLER(FrameMsg_GetNearestFindResult,
- OnGetNearestFindResult)
- IPC_MESSAGE_HANDLER(FrameMsg_FindMatchRects, OnFindMatchRects)
-#endif
-
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
@@ -1831,9 +1787,6 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
#endif
#endif
-#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
-#endif
IPC_END_MESSAGE_MAP()
return handled;
@@ -1897,10 +1850,10 @@ void RenderFrameImpl::OnBeforeUnload(bool is_reload) {
base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
- // TODO(clamy): Ensure BeforeUnload is dispatched to all subframes, even when
- // --site-per-process is enabled. |dispatchBeforeUnloadEvent| will only
- // execute the BeforeUnload event in this frame and local child frames. It
- // should also be dispatched to out-of-process child frames.
+ // This will execute the BeforeUnload event in this frame and all of its
+ // local descendant frames, including children of remote frames. The browser
+ // process will send separate IPCs to dispatch beforeunload in any
+ // out-of-process child frames.
bool proceed = frame_->DispatchBeforeUnloadEvent(is_reload);
base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
@@ -2038,50 +1991,6 @@ void RenderFrameImpl::OnCustomContextMenuAction(
}
}
-void RenderFrameImpl::OnMoveCaret(const gfx::Point& point) {
- Send(new InputHostMsg_MoveCaret_ACK(render_view_->GetRoutingID()));
- frame_->MoveCaretSelection(render_view_->ConvertWindowPointToViewport(point));
-}
-
-void RenderFrameImpl::OnScrollFocusedEditableNodeIntoRect(
- const gfx::Rect& rect) {
- ScrollFocusedEditableElementIntoRect(rect);
-}
-
-void RenderFrameImpl::OnUndo() {
- frame_->ExecuteCommand(WebString::FromUTF8("Undo"));
-}
-
-void RenderFrameImpl::OnRedo() {
- frame_->ExecuteCommand(WebString::FromUTF8("Redo"));
-}
-
-void RenderFrameImpl::OnCut() {
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- frame_->ExecuteCommand(WebString::FromUTF8("Cut"));
-}
-
-void RenderFrameImpl::OnCopy() {
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- frame_->ExecuteCommand(WebString::FromUTF8("Copy"));
-}
-
-void RenderFrameImpl::OnPaste() {
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- AutoResetMember<bool> handling_paste(this, &RenderFrameImpl::is_pasting_,
- true);
- frame_->ExecuteCommand(WebString::FromUTF8("Paste"));
-}
-
-void RenderFrameImpl::OnPasteAndMatchStyle() {
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- frame_->ExecuteCommand(WebString::FromUTF8("PasteAndMatchStyle"));
-}
-
#if defined(OS_MACOSX)
void RenderFrameImpl::OnCopyToFindPboard() {
// Since the find pasteboard supports only plain text, this can be simpler
@@ -2098,92 +2007,6 @@ void RenderFrameImpl::OnCopyToFindPboard() {
}
#endif
-void RenderFrameImpl::OnDelete() {
- frame_->ExecuteCommand(WebString::FromUTF8("Delete"));
-}
-
-void RenderFrameImpl::OnSelectAll() {
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- frame_->ExecuteCommand(WebString::FromUTF8("SelectAll"));
-}
-
-void RenderFrameImpl::OnSelectRange(const gfx::Point& base,
- const gfx::Point& extent) {
- // This IPC is dispatched by RenderWidgetHost, so use its routing id.
- Send(new InputHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
-
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- frame_->SelectRange(render_view_->ConvertWindowPointToViewport(base),
- render_view_->ConvertWindowPointToViewport(extent));
-}
-
-void RenderFrameImpl::OnAdjustSelectionByCharacterOffset(
- int start_adjust,
- int end_adjust,
- bool show_selection_menu) {
- WebRange range = frame_->GetInputMethodController()->GetSelectionOffsets();
- if (range.IsNull())
- return;
-
- // Sanity checks to disallow empty and out of range selections.
- if (start_adjust - end_adjust > range.length() ||
- range.StartOffset() + start_adjust < 0)
- return;
-
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
-
- // A negative adjust amount moves the selection towards the beginning of
- // the document, a positive amount moves the selection towards the end of
- // the document.
- frame_->SelectRange(WebRange(range.StartOffset() + start_adjust,
- range.length() + end_adjust - start_adjust),
- WebLocalFrame::kPreserveHandleVisibility,
- show_selection_menu ? SelectionMenuBehavior::kShow
- : SelectionMenuBehavior::kHide);
-}
-
-void RenderFrameImpl::OnCollapseSelection() {
- const WebRange& range =
- frame_->GetInputMethodController()->GetSelectionOffsets();
- if (range.IsNull())
- return;
-
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- frame_->SelectRange(WebRange(range.EndOffset(), 0),
- WebLocalFrame::kHideSelectionHandle,
- SelectionMenuBehavior::kHide);
-}
-
-void RenderFrameImpl::OnMoveRangeSelectionExtent(const gfx::Point& point) {
- // This IPC is dispatched by RenderWidgetHost, so use its routing id.
- Send(new InputHostMsg_MoveRangeSelectionExtent_ACK(
- GetRenderWidget()->routing_id()));
-
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- frame_->MoveRangeSelectionExtent(
- render_view_->ConvertWindowPointToViewport(point));
-}
-
-void RenderFrameImpl::OnReplace(const base::string16& text) {
- if (!frame_->HasSelection())
- frame_->SelectWordAroundCaret();
-
- frame_->ReplaceSelection(WebString::FromUTF16(text));
- SyncSelectionIfRequired();
-}
-
-void RenderFrameImpl::OnReplaceMisspelling(const base::string16& text) {
- if (!frame_->HasSelection())
- return;
-
- frame_->ReplaceMisspelledRange(WebString::FromUTF16(text));
-}
-
void RenderFrameImpl::OnCopyImageAt(int x, int y) {
blink::WebFloatRect viewport_position(x, y, 0, 0);
GetRenderWidget()->ConvertWindowToViewport(&viewport_position);
@@ -2339,41 +2162,6 @@ void RenderFrameImpl::OnVisualStateRequest(uint64_t id) {
MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
}
-void RenderFrameImpl::OnSetEditableSelectionOffsets(int start, int end) {
- AutoResetMember<bool> handling_select_range(
- this, &RenderFrameImpl::handling_select_range_, true);
- ImeEventGuard guard(GetRenderWidget());
- frame_->SetEditableSelectionOffsets(start, end);
-}
-
-void RenderFrameImpl::OnSetCompositionFromExistingText(
- int start,
- int end,
- const std::vector<blink::WebImeTextSpan>& ime_text_spans) {
- ImeEventGuard guard(GetRenderWidget());
- frame_->SetCompositionFromExistingText(start, end, ime_text_spans);
-}
-
-void RenderFrameImpl::OnExecuteNoValueEditCommand(const std::string& name) {
- frame_->ExecuteCommand(WebString::FromUTF8(name));
-}
-
-void RenderFrameImpl::OnExtendSelectionAndDelete(int before, int after) {
- ImeEventGuard guard(GetRenderWidget());
- frame_->ExtendSelectionAndDelete(before, after);
-}
-
-void RenderFrameImpl::OnDeleteSurroundingText(int before, int after) {
- ImeEventGuard guard(GetRenderWidget());
- frame_->DeleteSurroundingText(before, after);
-}
-
-void RenderFrameImpl::OnDeleteSurroundingTextInCodePoints(int before,
- int after) {
- ImeEventGuard guard(GetRenderWidget());
- frame_->DeleteSurroundingTextInCodePoints(before, after);
-}
-
void RenderFrameImpl::OnSetAccessibilityMode(ui::AXMode new_mode) {
if (accessibility_mode_ == new_mode)
return;
@@ -2411,8 +2199,9 @@ void RenderFrameImpl::ExtractSmartClipData(
ExtractSmartClipDataCallback callback) {
blink::WebString clip_text;
blink::WebString clip_html;
- GetWebFrame()->ExtractSmartClipData(rect, clip_text, clip_html);
- std::move(callback).Run(clip_text.Utf16(), clip_html.Utf16());
+ blink::WebRect clip_rect;
+ GetWebFrame()->ExtractSmartClipData(rect, clip_text, clip_html, clip_rect);
+ std::move(callback).Run(clip_text.Utf16(), clip_html.Utf16(), clip_rect);
}
#endif // defined(OS_ANDROID)
@@ -2513,33 +2302,9 @@ void RenderFrameImpl::OnPostMessageEvent(
WebString::FromUTF16(params.target_origin));
}
- WebDOMMessageEvent msg_event;
- if (params.is_data_raw_string) {
- v8::Isolate* isolate = blink::MainThreadIsolate();
- v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> context = frame_->MainWorldScriptContext();
- v8::Context::Scope context_scope(context);
- V8ValueConverterImpl converter;
- converter.SetDateAllowed(true);
- converter.SetRegExpAllowed(true);
- base::string16 data;
- data.resize(params.message->data.encoded_message.size() /
- sizeof(base::char16));
- std::memcpy(&data[0], params.message->data.encoded_message.data(),
- data.length() * sizeof(base::char16));
- base::Value value(data);
- v8::Local<v8::Value> result_value = converter.ToV8Value(&value, context);
- WebSerializedScriptValue serialized_script_value =
- WebSerializedScriptValue::Serialize(isolate, result_value);
- msg_event = WebDOMMessageEvent(serialized_script_value,
- WebString::FromUTF16(params.source_origin),
- source_frame, frame_->GetDocument(),
- std::move(params.message->data.ports));
- } else {
- msg_event = WebDOMMessageEvent(std::move(params.message->data),
- WebString::FromUTF16(params.source_origin),
- source_frame, frame_->GetDocument());
- }
+ WebDOMMessageEvent msg_event(std::move(params.message->data),
+ WebString::FromUTF16(params.source_origin),
+ source_frame, frame_->GetDocument());
frame_->DispatchMessageEventWithOriginCheck(
target_origin, msg_event, params.message->data.has_user_gesture);
@@ -3096,7 +2861,6 @@ void RenderFrameImpl::AllowBindings(int32_t enabled_bindings_flags) {
void RenderFrameImpl::CommitNavigation(
const network::ResourceResponseHead& head,
- const GURL& body_url,
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
@@ -3187,13 +2951,12 @@ void RenderFrameImpl::CommitNavigation(
} else {
WebURLRequest request = CreateURLRequestForCommit(
common_params, request_params, std::move(url_loader_client_endpoints),
- head, body_url);
+ head);
- // Load the request.
- frame_->Load(request, load_type, item_for_history_navigation,
- blink::kWebHistoryDifferentDocumentLoad, is_client_redirect,
- devtools_navigation_token);
- // The load of the URL can result in this frame being removed. Use a
+ frame_->CommitNavigation(request, load_type, item_for_history_navigation,
+ blink::kWebHistoryDifferentDocumentLoad,
+ is_client_redirect, devtools_navigation_token);
+ // The commit can result in this frame being removed. Use a
// WeakPtr as an easy way to detect whether this has occured. If so, this
// method should return immediately and not touch any part of the object,
// otherwise it will result in a use-after-free bug.
@@ -3222,10 +2985,10 @@ void RenderFrameImpl::CommitNavigation(
// Continue the navigation.
// TODO(arthursonzogni): Pass the data needed to continue the navigation to
- // this function instead of storing it in the StreamOverrideParameters.
- // The architecture of committing the navigation in the renderer process
- // should be simplified and avoid going through the ResourceFetcher for the
- // main resource.
+ // this function instead of storing it in the
+ // NavigationResponseOverrideParameters. The architecture of committing the
+ // navigation in the renderer process should be simplified and avoid going
+ // through the ResourceFetcher for the main resource.
if (continue_navigation)
std::move(continue_navigation).Run();
}
@@ -3270,11 +3033,10 @@ void RenderFrameImpl::CommitFailedNavigation(
has_stale_copy_in_cache ? WebURLError::HasCopyInCache::kTrue
: WebURLError::HasCopyInCache::kFalse,
WebURLError::IsWebSecurityViolation::kFalse, common_params.url);
- WebURLRequest failed_request =
- CreateURLRequestForNavigation(common_params, request_params,
- std::unique_ptr<StreamOverrideParameters>(),
- frame_->IsViewSourceModeEnabled(),
- false); // is_same_document_navigation
+ WebURLRequest failed_request = CreateURLRequestForNavigation(
+ common_params, request_params,
+ /*response_override=*/nullptr, frame_->IsViewSourceModeEnabled(),
+ false); // is_same_document_navigation
if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) {
// The browser expects this frame to be loading an error page. Inform it
@@ -3575,25 +3337,18 @@ RenderFrameImpl::CreateWorkerFetchContext() {
container_host_ptr_info = provider_context->CloneContainerHostPtrInfo();
}
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- direct_network_loader_factory_info;
- // Could be null in tests.
- if (render_thread) {
- direct_network_loader_factory_info =
- base::MakeRefCounted<PossiblyAssociatedWrapperSharedURLLoaderFactory>(
- render_thread->blink_platform_impl()
- ->CreateNetworkURLLoaderFactory())
- ->Clone();
- }
-
std::unique_ptr<WorkerFetchContextImpl> worker_fetch_context =
std::make_unique<WorkerFetchContextImpl>(
std::move(service_worker_client_request),
std::move(container_host_ptr_info), GetLoaderFactoryBundle()->Clone(),
- std::move(direct_network_loader_factory_info),
+ GetLoaderFactoryBundle()->CloneWithoutDefaultFactory(),
GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
- URLLoaderThrottleProviderType::kWorker));
+ URLLoaderThrottleProviderType::kWorker),
+ GetContentClient()
+ ->renderer()
+ ->CreateWebSocketHandshakeThrottleProvider(),
+ ChildThreadImpl::current()->thread_safe_sender(),
+ RenderThreadImpl::current()->GetIOTaskRunner());
worker_fetch_context->set_parent_frame_id(routing_id_);
worker_fetch_context->set_site_for_cookies(
@@ -3605,6 +3360,9 @@ RenderFrameImpl::CreateWorkerFetchContext() {
provider->IsControlledByServiceWorker());
worker_fetch_context->set_origin_url(
GURL(frame_->GetDocument().Url()).GetOrigin());
+ if (provider_context)
+ worker_fetch_context->set_client_id(provider_context->client_id());
+
for (auto& observer : observers_)
observer.WillCreateWorkerFetchContext(worker_fetch_context.get());
return std::move(worker_fetch_context);
@@ -3938,6 +3696,10 @@ void RenderFrameImpl::SetHasReceivedUserGestureBeforeNavigation(bool value) {
value));
}
+void RenderFrameImpl::SetMouseCapture(bool capture) {
+ GetRenderWidget()->SetMouseCapture(capture);
+}
+
bool RenderFrameImpl::ShouldReportDetailedMessageForSource(
const blink::WebString& source) {
return GetContentClient()->renderer()->ShouldReportDetailedMessageForSource(
@@ -3980,7 +3742,12 @@ void RenderFrameImpl::DidAddMessageToConsole(
static_cast<int32_t>(source_line), source_name.Utf16()));
}
-void RenderFrameImpl::DownloadURL(const blink::WebURLRequest& request) {
+void RenderFrameImpl::DownloadURL(
+ const blink::WebURLRequest& request,
+ mojo::ScopedMessagePipeHandle blob_url_token) {
+ if (ShouldThrottleDownload())
+ return;
+
FrameHostMsg_DownloadUrl_Params params;
params.render_view_id = render_view_->GetRoutingID();
params.render_frame_id = GetRoutingID();
@@ -3989,6 +3756,7 @@ void RenderFrameImpl::DownloadURL(const blink::WebURLRequest& request) {
params.initiator_origin = request.RequestorOrigin();
if (request.GetSuggestedFilename().has_value())
params.suggested_name = request.GetSuggestedFilename()->Utf16();
+ params.blob_url_token = blob_url_token.release();
Send(new FrameHostMsg_DownloadUrl(params));
}
@@ -4104,19 +3872,14 @@ void RenderFrameImpl::DidCreateDocumentLoader(
if (document_loader->GetServiceWorkerNetworkProvider())
return;
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- scoped_refptr<network::SharedURLLoaderFactory> direct_network_loader_factory;
- if (render_thread) {
- direct_network_loader_factory =
- base::MakeRefCounted<PossiblyAssociatedWrapperSharedURLLoaderFactory>(
- render_thread->blink_platform_impl()
- ->CreateNetworkURLLoaderFactory());
- }
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory =
+ network::SharedURLLoaderFactory::Create(
+ GetLoaderFactoryBundle()->CloneWithoutDefaultFactory());
document_loader->SetServiceWorkerNetworkProvider(
ServiceWorkerNetworkProvider::CreateForNavigation(
routing_id_, navigation_state->request_params(), frame_,
content_initiated, std::move(controller_service_worker_info_),
- std::move(direct_network_loader_factory)));
+ std::move(fallback_factory)));
}
void RenderFrameImpl::DidStartProvisionalLoad(
@@ -4324,8 +4087,7 @@ void RenderFrameImpl::DidCommitProvisionalLoad(
// factory to be registered here, make this a RenderFrameObserver.
// code.
factory->MaybeDeregisterRemoteFactory(GetRoutingID());
- factory->MaybeRegisterRemoteFactory(GetRoutingID(),
- GetRemoteInterfaces());
+ factory->RegisterRemoteFactory(GetRoutingID(), GetRemoteInterfaces());
}
// If the request for |audio_input_stream_factory_| is in flight when
@@ -4590,12 +4352,13 @@ void RenderFrameImpl::DidFinishLoad() {
memory_metrics, ".ServiceWorkerControlledMainFrameDidFinishLoad");
}
-void RenderFrameImpl::DidNavigateWithinPage(
+void RenderFrameImpl::DidFinishSameDocumentNavigation(
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type,
bool content_initiated) {
- TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didNavigateWithinPage",
- "id", routing_id_);
+ TRACE_EVENT1("navigation,rail",
+ "RenderFrameImpl::didFinishSameDocumentNavigation", "id",
+ routing_id_);
DocumentState* document_state =
DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
UpdateNavigationState(document_state, true /* was_within_same_document */,
@@ -4866,7 +4629,7 @@ void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) {
// There may also be a stream url associated with the request.
WebString custom_user_agent;
WebString requested_with;
- std::unique_ptr<StreamOverrideParameters> stream_override;
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override;
if (request.GetExtraData()) {
RequestExtraData* old_extra_data =
static_cast<RequestExtraData*>(request.GetExtraData());
@@ -4886,19 +4649,14 @@ void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) {
else
request.SetHTTPHeaderField("X-Requested-With", requested_with);
}
- stream_override = old_extra_data->TakeStreamOverrideOwnership();
+ response_override =
+ old_extra_data->TakeNavigationResponseOverrideOwnership();
}
// Set an empty HTTP origin header for non GET methods if none is currently
// present.
request.SetHTTPOriginIfNeeded(WebSecurityOrigin::CreateUnique());
- // Attach |should_replace_current_entry| state to requests so that, should
- // this navigation later require a request transfer, all state is preserved
- // when it is re-created in the new process.
- bool should_replace_current_entry =
- document_loader->ReplacesCurrentHistoryItem();
-
WebFrame* parent = frame_->Parent();
ResourceType resource_type = WebURLRequestToResourceType(request);
@@ -4914,8 +4672,7 @@ void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) {
extra_data->set_allow_download(
navigation_state->common_params().allow_download);
extra_data->set_transition_type(transition_type);
- extra_data->set_should_replace_current_entry(should_replace_current_entry);
- extra_data->set_stream_override(std::move(stream_override));
+ extra_data->set_navigation_response_override(std::move(response_override));
bool is_for_no_state_prefetch =
GetContentClient()->renderer()->IsPrefetchOnly(this, request);
extra_data->set_is_for_no_state_prefetch(is_for_no_state_prefetch);
@@ -5210,12 +4967,6 @@ void RenderFrameImpl::ReportFindInPageSelection(
selection_rect, false /* final_status_update */);
}
-blink::WebPresentationClient* RenderFrameImpl::PresentationClient() {
- if (!presentation_dispatcher_)
- presentation_dispatcher_ = new PresentationDispatcher(this);
- return presentation_dispatcher_;
-}
-
blink::WebPushClient* RenderFrameImpl::PushClient() {
if (!push_messaging_client_)
push_messaging_client_ = new PushMessagingClient(this);
@@ -5231,9 +4982,7 @@ blink::WebRelatedAppsFetcher* RenderFrameImpl::GetRelatedAppsFetcher() {
void RenderFrameImpl::WillStartUsingPeerConnectionHandler(
blink::WebRTCPeerConnectionHandler* handler) {
-#if BUILDFLAG(ENABLE_WEBRTC)
static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame_);
-#endif
}
blink::WebUserMediaClient* RenderFrameImpl::UserMediaClient() {
@@ -5330,12 +5079,13 @@ void RenderFrameImpl::DidChangeManifest() {
observer.DidChangeManifest();
}
-void RenderFrameImpl::EnterFullscreen() {
- Send(new FrameHostMsg_ToggleFullscreen(routing_id_, true));
+void RenderFrameImpl::EnterFullscreen(
+ const blink::WebFullscreenOptions& options) {
+ Send(new FrameHostMsg_EnterFullscreen(routing_id_, options));
}
void RenderFrameImpl::ExitFullscreen() {
- Send(new FrameHostMsg_ToggleFullscreen(routing_id_, false));
+ Send(new FrameHostMsg_ExitFullscreen(routing_id_));
}
void RenderFrameImpl::SuddenTerminationDisablerChanged(
@@ -5763,11 +5513,12 @@ void RenderFrameImpl::UpdateStateForCommit(
engagement_level_.first = url::Origin();
}
- // If we are a top frame navigation we should clear any existing autoplay
- // flags on the Page. This is because flags are stored at the page level so
- // subframes would only add to them.
- if (!frame_->Parent())
+ // If we are a top frame navigation to another document we should clear any
+ // existing autoplay flags on the Page. This is because flags are stored at
+ // the page level so subframes would only add to them.
+ if (!frame_->Parent() && !navigation_state->WasWithinSameDocument()) {
render_view_->webview()->ClearAutoplayFlags();
+ }
// Set the correct autoplay flags on the Page and wipe the cached origin so
// this will not be used incorrectly.
@@ -6182,10 +5933,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
info.url_request.CheckForBrowserSideNavigation() &&
// No need to dispatch beforeunload if the frame has not committed a
// navigation and contains an empty initial document.
- (has_accessed_initial_document_ || !current_history_item_.IsNull()) &&
- // Don't dispatch beforeunload if the navigation might end up as a
- // download.
- !info.url_request.GetSuggestedFilename().has_value();
+ (has_accessed_initial_document_ || !current_history_item_.IsNull());
if (should_dispatch_before_unload) {
// Execute the BeforeUnload event. If asked not to proceed or the frame is
@@ -6227,7 +5975,9 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
}
if (info.default_policy == blink::kWebNavigationPolicyDownload) {
- DownloadURL(info.url_request);
+ blink::mojom::BlobURLTokenPtrInfo blob_url_token =
+ CloneBlobURLToken(info.blob_url_token.get());
+ DownloadURL(info.url_request, blob_url_token.PassHandle());
} else {
OpenURL(info, /*send_referrer=*/true,
/*is_history_navigation_in_new_child=*/false);
@@ -6380,36 +6130,11 @@ void RenderFrameImpl::OnFind(int request_id,
frame_->RequestFind(request_id, WebString::FromUTF16(search_text), options);
}
-void RenderFrameImpl::OnClearActiveFindMatch() {
- frame_->ExecuteCommand(WebString::FromUTF8("CollapseSelection"));
- frame_->ClearActiveFindMatch();
-}
-
#define STATIC_ASSERT_ENUM(a, b) \
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enums: " #a)
-
-// Ensure that content::StopFindAction and blink::WebLocalFrame::StopFindAction
-// are kept in sync.
-STATIC_ASSERT_ENUM(STOP_FIND_ACTION_CLEAR_SELECTION,
- WebLocalFrame::kStopFindActionClearSelection);
-STATIC_ASSERT_ENUM(STOP_FIND_ACTION_KEEP_SELECTION,
- WebLocalFrame::kStopFindActionKeepSelection);
-STATIC_ASSERT_ENUM(STOP_FIND_ACTION_ACTIVATE_SELECTION,
- WebLocalFrame::kStopFindActionActivateSelection);
-
#undef STATIC_ASSERT_ENUM
-void RenderFrameImpl::OnStopFinding(StopFindAction action) {
- blink::WebPlugin* plugin = GetWebPluginForFind();
- if (plugin) {
- plugin->StopFind();
- return;
- }
-
- frame_->StopFinding(static_cast<WebLocalFrame::StopFindAction>(action));
-}
-
void RenderFrameImpl::OnEnableViewSourceMode() {
DCHECK(frame_);
DCHECK(!frame_->Parent());
@@ -6498,51 +6223,6 @@ void RenderFrameImpl::OnMixedContentFound(
params.had_redirect, source_location);
}
-#if defined(OS_ANDROID)
-void RenderFrameImpl::OnActivateNearestFindResult(int request_id,
- float x,
- float y) {
- WebRect selection_rect;
- int ordinal =
- frame_->SelectNearestFindMatch(WebFloatPoint(x, y), &selection_rect);
- if (ordinal == -1) {
- // Something went wrong, so send a no-op reply (force the frame to report
- // the current match count) in case the host is waiting for a response due
- // to rate-limiting.
- frame_->IncreaseMatchCount(0, request_id);
- return;
- }
-
- SendFindReply(request_id, -1 /* number_of_matches */, ordinal, selection_rect,
- true /* final_update */);
-}
-
-void RenderFrameImpl::OnGetNearestFindResult(int nfr_request_id,
- float x,
- float y) {
- float distance = frame_->DistanceToNearestFindMatch(WebFloatPoint(x, y));
- Send(new FrameHostMsg_GetNearestFindResult_Reply(
- routing_id_, nfr_request_id, distance));
-}
-
-void RenderFrameImpl::OnFindMatchRects(int current_version) {
- std::vector<gfx::RectF> match_rects;
-
- int rects_version = frame_->FindMatchMarkersVersion();
- if (current_version != rects_version) {
- WebVector<WebFloatRect> web_match_rects;
- frame_->FindMatchRects(web_match_rects);
- match_rects.reserve(web_match_rects.size());
- for (size_t i = 0; i < web_match_rects.size(); ++i)
- match_rects.push_back(gfx::RectF(web_match_rects[i]));
- }
-
- gfx::RectF active_rect = frame_->ActiveFindMatchRect();
- Send(new FrameHostMsg_FindMatchRects_Reply(routing_id_, rects_version,
- match_rects, active_rect));
-}
-#endif
-
void RenderFrameImpl::OnSetOverlayRoutingToken(
const base::UnguessableToken& token) {
overlay_routing_token_ = token;
@@ -6612,11 +6292,8 @@ void RenderFrameImpl::OpenURL(const NavigationPolicyInfo& info,
: content::Referrer();
params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy);
params.triggering_event_info = info.triggering_event_info;
- params.suggested_filename =
- info.url_request.GetSuggestedFilename().has_value()
- ? base::Optional<std::string>(
- info.url_request.GetSuggestedFilename()->Utf8())
- : base::nullopt;
+ params.blob_url_token =
+ CloneBlobURLToken(info.blob_url_token.get()).PassHandle().release();
if (IsBrowserInitiated(pending_navigation_params_.get())) {
// This is necessary to preserve the should_replace_current_entry value on
@@ -6652,34 +6329,20 @@ WebURLRequest RenderFrameImpl::CreateURLRequestForCommit(
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- const network::ResourceResponseHead& head,
- const GURL& body_url) {
+ const network::ResourceResponseHead& head) {
// This will override the url requested by the WebURLLoader, as well as
// provide it with the response to the request.
- std::unique_ptr<StreamOverrideParameters> stream_override(
- new StreamOverrideParameters());
- stream_override->stream_url = body_url;
- stream_override->url_loader_client_endpoints =
+ std::unique_ptr<NavigationResponseOverrideParameters> response_override(
+ new NavigationResponseOverrideParameters());
+ response_override->url_loader_client_endpoints =
std::move(url_loader_client_endpoints);
- stream_override->response = head;
- stream_override->redirects = request_params.redirects;
- stream_override->redirect_responses = request_params.redirect_response;
- stream_override->redirect_infos = request_params.redirect_infos;
-
- // Used to notify the browser that it can release its |stream_handle_| when
- // the |stream_override| object isn't used anymore.
- // TODO(clamy): Remove this when we switch to Mojo streams.
- stream_override->on_delete = base::BindOnce(
- [](base::WeakPtr<RenderFrameImpl> weak_self, const GURL& url) {
- if (RenderFrameImpl* self = weak_self.get()) {
- self->Send(
- new FrameHostMsg_StreamHandleConsumed(self->routing_id_, url));
- }
- },
- weak_factory_.GetWeakPtr());
+ response_override->response = head;
+ response_override->redirects = request_params.redirects;
+ response_override->redirect_responses = request_params.redirect_response;
+ response_override->redirect_infos = request_params.redirect_infos;
WebURLRequest request = CreateURLRequestForNavigation(
- common_params, request_params, std::move(stream_override),
+ common_params, request_params, std::move(response_override),
frame_->IsViewSourceModeEnabled(), false /* is_same_document */);
request.SetFrameType(IsTopLevelNavigation(frame_)
? network::mojom::RequestContextFrameType::kTopLevel
@@ -6702,8 +6365,7 @@ WebURLRequest RenderFrameImpl::CreateURLRequestForCommit(
// for this request (since it already went to the browser).
request.SetCheckForBrowserSideNavigation(false);
- request.SetNavigationStartTime(
- ConvertToBlinkTime(common_params.navigation_start));
+ request.SetNavigationStartTime(common_params.navigation_start);
return request;
}
@@ -6857,13 +6519,11 @@ void RenderFrameImpl::InitializeUserMediaClient() {
if (!render_thread) // Will be NULL during unit tests.
return;
-#if BUILDFLAG(ENABLE_WEBRTC)
DCHECK(!web_user_media_client_);
web_user_media_client_ = new UserMediaClientImpl(
this, RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(),
std::make_unique<MediaStreamDeviceObserver>(this),
GetTaskRunner(blink::TaskType::kInternalMedia));
-#endif
}
void RenderFrameImpl::PrepareRenderViewForNavigation(
@@ -6978,14 +6638,8 @@ void RenderFrameImpl::BeginNavigation(const NavigationPolicyInfo& info) {
if (info.is_client_redirect)
client_side_redirect_url = frame_->GetDocument().Url();
- blink::mojom::BlobURLTokenPtr blob_url_token;
- if (info.blob_url_token.is_valid()) {
- blink::mojom::BlobURLTokenPtr token(blink::mojom::BlobURLTokenPtrInfo(
- mojo::ScopedMessagePipeHandle(info.blob_url_token.get()),
- blink::mojom::BlobURLToken::Version_));
- token->Clone(MakeRequest(&blob_url_token));
- ignore_result(token.PassInterface().PassHandle().release());
- }
+ blink::mojom::BlobURLTokenPtr blob_url_token(
+ CloneBlobURLToken(info.blob_url_token.get()));
int load_flags = GetLoadFlagsForWebURLRequest(info.url_request);
std::unique_ptr<base::DictionaryValue> initiator =
@@ -7207,9 +6861,9 @@ void RenderFrameImpl::HandlePepperImeCommit(const base::string16& text) {
base::i18n::UTF16CharIterator iterator(&text);
int32_t i = 0;
while (iterator.Advance()) {
- blink::WebKeyboardEvent char_event(
- blink::WebInputEvent::kChar, blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebKeyboardEvent char_event(blink::WebInputEvent::kChar,
+ blink::WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
char_event.windows_key_code = text[i];
char_event.native_key_code = text[i];
@@ -7294,13 +6948,11 @@ void RenderFrameImpl::OnHostZoomClientRequest(
void RenderFrameImpl::CheckIfAudioSinkExistsAndIsAuthorized(
const blink::WebString& sink_id,
- const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callbacks) {
media::OutputDeviceStatusCB callback =
media::ConvertToOutputDeviceStatusCB(web_callbacks);
std::move(callback).Run(
- AudioDeviceFactory::GetOutputDeviceInfo(GetRoutingID(), 0, sink_id.Utf8(),
- security_origin)
+ AudioDeviceFactory::GetOutputDeviceInfo(GetRoutingID(), 0, sink_id.Utf8())
.device_status());
}
@@ -7346,6 +6998,15 @@ void RenderFrameImpl::ScrollRectToVisibleInParentFrame(
routing_id_, rect_to_scroll, params));
}
+void RenderFrameImpl::BubbleLogicalScrollInParentFrame(
+ blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity) {
+ DCHECK(IsLocalRoot());
+ DCHECK(!IsMainFrame());
+ Send(new FrameHostMsg_BubbleLogicalScrollInParentFrame(routing_id_, direction,
+ granularity));
+}
+
blink::mojom::PageVisibilityState RenderFrameImpl::GetVisibilityState() const {
return VisibilityState();
}
@@ -7367,16 +7028,6 @@ void RenderFrameImpl::FrameDidCallFocus() {
Send(new FrameHostMsg_FrameDidCallFocus(routing_id_));
}
-void RenderFrameImpl::OnPictureInPictureSurfaceIdUpdated(
- const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size) {
- GetFrameHost()->OnUpdatePictureInPictureSurfaceId(surface_id, natural_size);
-}
-
-void RenderFrameImpl::OnExitPictureInPicture() {
- GetFrameHost()->OnExitPictureInPicture();
-}
-
void RenderFrameImpl::SetAccessibilityModeForTest(ui::AXMode new_mode) {
OnSetAccessibilityMode(new_mode);
}
@@ -7387,15 +7038,7 @@ RenderFrameImpl::GetURLLoaderFactory() {
}
blink::WebPlugin* RenderFrameImpl::GetWebPluginForFind() {
- if (frame_->GetDocument().IsPluginDocument())
- return frame_->GetDocument().To<WebPluginDocument>().Plugin();
-
-#if BUILDFLAG(ENABLE_PLUGINS)
- if (plugin_find_handler_)
- return plugin_find_handler_->container()->Plugin();
-#endif
-
- return nullptr;
+ return frame_->GetWebPluginForFind();
}
void RenderFrameImpl::SendFindReply(int request_id,
@@ -7548,15 +7191,8 @@ RenderFrameImpl::PendingNavigationInfo::PendingNavigationInfo(
triggering_event_info(info.triggering_event_info),
form(info.form),
source_location(info.source_location),
- devtools_initiator_info(info.devtools_initiator_info) {
- if (info.blob_url_token.is_valid()) {
- blink::mojom::BlobURLTokenPtr token(blink::mojom::BlobURLTokenPtrInfo(
- mojo::ScopedMessagePipeHandle(info.blob_url_token.get()),
- blink::mojom::BlobURLToken::Version_));
- token->Clone(MakeRequest(&blob_url_token));
- ignore_result(token.PassInterface().PassHandle().release());
- }
-}
+ devtools_initiator_info(info.devtools_initiator_info),
+ blob_url_token(CloneBlobURLToken(info.blob_url_token.get())) {}
RenderFrameImpl::PendingNavigationInfo::~PendingNavigationInfo() = default;
@@ -7570,4 +7206,47 @@ blink::WebComputedAXTree* RenderFrameImpl::GetOrCreateWebComputedAXTree() {
return computed_ax_tree_.get();
}
+std::unique_ptr<blink::WebSocketHandshakeThrottle>
+RenderFrameImpl::CreateWebSocketHandshakeThrottle() {
+ WebLocalFrame* web_local_frame = GetWebFrame();
+ if (!web_local_frame)
+ return nullptr;
+ auto* render_frame = content::RenderFrame::FromWebFrame(web_local_frame);
+ if (!render_frame)
+ return nullptr;
+ int render_frame_id = render_frame->GetRoutingID();
+
+ // Lazily create the provider.
+ if (!websocket_handshake_throttle_provider_) {
+ websocket_handshake_throttle_provider_ =
+ GetContentClient()
+ ->renderer()
+ ->CreateWebSocketHandshakeThrottleProvider();
+ if (!websocket_handshake_throttle_provider_)
+ return nullptr;
+ }
+
+ return websocket_handshake_throttle_provider_->CreateThrottle(
+ render_frame_id);
+}
+
+bool RenderFrameImpl::ShouldThrottleDownload() {
+ const auto now = base::TimeTicks::Now();
+ if (num_burst_download_requests_ == 0) {
+ burst_download_start_time_ = now;
+ } else if (num_burst_download_requests_ >= kBurstDownloadLimit) {
+ static constexpr auto kBurstDownloadLimitResetInterval =
+ TimeDelta::FromSeconds(1);
+ if (now - burst_download_start_time_ > kBurstDownloadLimitResetInterval) {
+ num_burst_download_requests_ = 1;
+ burst_download_start_time_ = now;
+ return false;
+ }
+ return true;
+ }
+
+ num_burst_download_requests_++;
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index 9acff93b62e..d841189173c 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -49,6 +49,8 @@
#include "content/public/common/request_context_type.h"
#include "content/public/common/stop_find_action.h"
#include "content/public/renderer/render_frame.h"
+#include "content/public/renderer/websocket_handshake_throttle_provider.h"
+#include "content/renderer/content_security_policy_util.h"
#include "content/renderer/frame_blame_context.h"
#include "content/renderer/input/input_target_client_impl.h"
#include "content/renderer/loader/child_url_loader_factory_bundle.h"
@@ -69,9 +71,9 @@
#include "services/service_manager/public/mojom/connector.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
#include "third_party/blink/public/platform/autoplay.mojom.h"
-#include "third_party/blink/public/platform/modules/manifest/manifest_manager.mojom.h"
#include "third_party/blink/public/platform/site_engagement.mojom.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/public/platform/web_focus_type.h"
@@ -111,7 +113,6 @@ class WebComputedAXTree;
class WebContentDecryptionModule;
class WebLayerTreeView;
class WebLocalFrame;
-class WebPresentationClient;
class WebPushClient;
class WebRelatedAppsFetcher;
class WebSecurityOrigin;
@@ -158,7 +159,6 @@ class MediaPermissionDispatcher;
class MediaStreamDeviceObserver;
class NavigationState;
class PepperPluginInstanceImpl;
-class PresentationDispatcher;
class PushMessagingClient;
class RelatedAppsFetcher;
class RenderAccessibilityImpl;
@@ -361,14 +361,6 @@ class CONTENT_EXPORT RenderFrameImpl
void RenderWidgetWillHandleMouseEvent();
#if BUILDFLAG(ENABLE_PLUGINS)
- // Get/set the plugin which will be used to handle document find requests.
- void set_plugin_find_handler(PepperPluginInstanceImpl* plugin) {
- plugin_find_handler_ = plugin;
- }
- PepperPluginInstanceImpl* plugin_find_handler() {
- return plugin_find_handler_;
- }
-
// Notification that a PPAPI plugin has been created.
void PepperPluginCreated(RendererPpapiHost* host);
@@ -526,7 +518,6 @@ class CONTENT_EXPORT RenderFrameImpl
// mojom::FrameNavigationControl implementation:
void CommitNavigation(
const network::ResourceResponseHead& head,
- const GURL& body_url,
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
@@ -618,13 +609,15 @@ class CONTENT_EXPORT RenderFrameImpl
override;
void SetHasReceivedUserGesture() override;
void SetHasReceivedUserGestureBeforeNavigation(bool value) override;
+ void SetMouseCapture(bool capture) override;
bool ShouldReportDetailedMessageForSource(
const blink::WebString& source) override;
void DidAddMessageToConsole(const blink::WebConsoleMessage& message,
const blink::WebString& source_name,
unsigned source_line,
const blink::WebString& stack_trace) override;
- void DownloadURL(const blink::WebURLRequest& request) override;
+ void DownloadURL(const blink::WebURLRequest& request,
+ mojo::ScopedMessagePipeHandle blob_url_token) override;
void LoadErrorPage(int reason) override;
blink::WebNavigationPolicy DecidePolicyForNavigation(
const NavigationPolicyInfo& info) override;
@@ -655,9 +648,9 @@ class CONTENT_EXPORT RenderFrameImpl
void DidFailLoad(const blink::WebURLError& error,
blink::WebHistoryCommitType commit_type) override;
void DidFinishLoad() override;
- void DidNavigateWithinPage(const blink::WebHistoryItem& item,
- blink::WebHistoryCommitType commit_type,
- bool content_initiated) override;
+ void DidFinishSameDocumentNavigation(const blink::WebHistoryItem& item,
+ blink::WebHistoryCommitType commit_type,
+ bool content_initiated) override;
void DidUpdateCurrentHistoryItem() override;
void DidChangeThemeColor() override;
void ForwardResourceTimingToParent(
@@ -717,7 +710,6 @@ class CONTENT_EXPORT RenderFrameImpl
int active_match_ordinal,
const blink::WebRect& sel) override;
blink::WebPushClient* PushClient() override;
- blink::WebPresentationClient* PresentationClient() override;
blink::WebRelatedAppsFetcher* GetRelatedAppsFetcher() override;
void WillStartUsingPeerConnectionHandler(
blink::WebRTCPeerConnectionHandler* handler) override;
@@ -738,7 +730,7 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebNode& end_node,
int end_offset) override;
void DidChangeManifest() override;
- void EnterFullscreen() override;
+ void EnterFullscreen(const blink::WebFullscreenOptions& options) override;
void ExitFullscreen() override;
void SuddenTerminationDisablerChanged(
bool present,
@@ -750,7 +742,6 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebURL& url) override;
void CheckIfAudioSinkExistsAndIsAuthorized(
const blink::WebString& sink_id,
- const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callbacks) override;
blink::WebSpeechRecognizer* SpeechRecognizer() override;
blink::mojom::PageVisibilityState VisibilityState() const override;
@@ -762,6 +753,9 @@ class CONTENT_EXPORT RenderFrameImpl
void ScrollRectToVisibleInParentFrame(
const blink::WebRect& rect_to_scroll,
const blink::WebScrollIntoViewParams& params) override;
+ void BubbleLogicalScrollInParentFrame(
+ blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity) override;
// WebFrameSerializerClient implementation:
void DidSerializeDataForFrame(
@@ -877,14 +871,6 @@ class CONTENT_EXPORT RenderFrameImpl
// frame.
void FrameDidCallFocus();
- // Send viz::SurfaceId and video information to FrameHost to use for
- // Picture-in-Picture.
- void OnPictureInPictureSurfaceIdUpdated(const viz::SurfaceId& surface_id,
- const gfx::Size& natural_size);
-
- // Send signal that Picture-in-Picture mode has ended.
- void OnExitPictureInPicture();
-
protected:
explicit RenderFrameImpl(CreateParams params);
@@ -1004,22 +990,7 @@ class CONTENT_EXPORT RenderFrameImpl
unsigned action);
void OnMoveCaret(const gfx::Point& point);
void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
- void OnUndo();
- void OnRedo();
- void OnCut();
- void OnCopy();
- void OnPaste();
- void OnPasteAndMatchStyle();
- void OnDelete();
- void OnSelectAll();
void OnSelectRange(const gfx::Point& base, const gfx::Point& extent);
- void OnAdjustSelectionByCharacterOffset(int start_adjust,
- int end_adjust,
- bool show_selection_menu);
- void OnCollapseSelection();
- void OnMoveRangeSelectionExtent(const gfx::Point& point);
- void OnReplace(const base::string16& text);
- void OnReplaceMisspelling(const base::string16& text);
void OnCopyImageAt(int x, int y);
void OnSaveImageAt(int x, int y);
void OnAddMessageToConsole(ConsoleMessageLevel level,
@@ -1036,15 +1007,6 @@ class CONTENT_EXPORT RenderFrameImpl
bool notify_result,
int world_id);
void OnVisualStateRequest(uint64_t key);
- void OnSetEditableSelectionOffsets(int start, int end);
- void OnSetCompositionFromExistingText(
- int start,
- int end,
- const std::vector<blink::WebImeTextSpan>& ime_text_spans);
- void OnExecuteNoValueEditCommand(const std::string& name);
- void OnExtendSelectionAndDelete(int before, int after);
- void OnDeleteSurroundingText(int before, int after);
- void OnDeleteSurroundingTextInCodePoints(int before, int after);
void OnReload(bool bypass_cache);
void OnReloadLoFiImages();
void OnTextSurroundingSelectionRequest(uint32_t max_length);
@@ -1071,8 +1033,6 @@ class CONTENT_EXPORT RenderFrameImpl
void OnFind(int request_id,
const base::string16& search_text,
const blink::WebFindOptions& options);
- void OnClearActiveFindMatch();
- void OnStopFinding(StopFindAction action);
void OnEnableViewSourceMode();
void OnSuppressFurtherDialogs();
void OnFileChooserResponse(
@@ -1080,11 +1040,6 @@ class CONTENT_EXPORT RenderFrameImpl
void OnClearFocusedElement();
void OnBlinkFeatureUsageReport(const std::set<int>& features);
void OnMixedContentFound(const FrameMsg_MixedContentFound_Params& params);
-#if defined(OS_ANDROID)
- void OnActivateNearestFindResult(int request_id, float x, float y);
- void OnGetNearestFindResult(int request_id, float x, float y);
- void OnFindMatchRects(int current_version);
-#endif
void OnSetOverlayRoutingToken(const base::UnguessableToken& token);
void OnNotifyUserActivation();
@@ -1118,8 +1073,7 @@ class CONTENT_EXPORT RenderFrameImpl
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- const network::ResourceResponseHead& head,
- const GURL& body_url);
+ const network::ResourceResponseHead& head);
// Returns a ChildURLLoaderFactoryBundle which can be used to request
// subresources for this frame.
@@ -1319,6 +1273,9 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebComputedAXTree* GetOrCreateWebComputedAXTree() override;
+ std::unique_ptr<blink::WebSocketHandshakeThrottle>
+ CreateWebSocketHandshakeThrottle() override;
+
// Updates the state of this frame when asked to commit a navigation.
void PrepareFrameForCommit();
@@ -1352,6 +1309,9 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebHistoryItem* item_for_history_navigation,
blink::WebFrameLoadType* load_type);
+ // Whether url download should be throttled.
+ bool ShouldThrottleDownload();
+
// Stores the WebLocalFrame we are associated with. This is null from the
// constructor until BindToFrame() is called, and it is null after
// FrameDetached() is called until destruction (which is asynchronous in the
@@ -1447,8 +1407,6 @@ class CONTENT_EXPORT RenderFrameImpl
base::string16 pepper_composition_text_;
PluginPowerSaverHelper* plugin_power_saver_helper_;
-
- PepperPluginInstanceImpl* plugin_find_handler_;
#endif
RendererWebCookieJarImpl cookie_jar_;
@@ -1481,7 +1439,7 @@ class CONTENT_EXPORT RenderFrameImpl
// could correspond to a substring of |selection_text_|; see above).
gfx::Range selection_range_;
// Used to inform didChangeSelection() when it is called in the context
- // of handling a InputMsg_SelectRange IPC.
+ // of handling a FrameInputHandler::SelectRange IPC.
bool handling_select_range_;
// The next group of objects all implement RenderFrameObserver, so are deleted
@@ -1496,10 +1454,6 @@ class CONTENT_EXPORT RenderFrameImpl
// The media permission dispatcher attached to this frame.
std::unique_ptr<MediaPermissionDispatcher> media_permission_dispatcher_;
- // The presentation dispatcher implementation attached to this frame, lazily
- // initialized.
- PresentationDispatcher* presentation_dispatcher_;
-
// The PushMessagingClient attached to this frame, lazily initialized.
PushMessagingClient* push_messaging_client_;
@@ -1704,6 +1658,13 @@ class CONTENT_EXPORT RenderFrameImpl
// The origins for which a legacy certificate warning has been printed.
std::set<url::Origin> certificate_warning_origins_;
+ std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ websocket_handshake_throttle_provider_;
+
+ // Variable to control burst of download requests.
+ int num_burst_download_requests_ = 0;
+ base::TimeTicks burst_download_start_time_;
+
base::WeakPtrFactory<RenderFrameImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc
index fb6a85c3b65..a04c30ff0d6 100644
--- a/chromium/content/renderer/render_frame_impl_browsertest.cc
+++ b/chromium/content/renderer/render_frame_impl_browsertest.cc
@@ -29,6 +29,7 @@
#include "content/renderer/mojo/blink_interface_registry_impl.h"
#include "content/renderer/navigation_state_impl.h"
#include "content/renderer/render_frame_impl.h"
+#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_view_impl.h"
#include "content/test/fake_compositor_dependencies.h"
#include "content/test/frame_host_test_interface.mojom.h"
@@ -188,18 +189,17 @@ TEST_F(RenderFrameImplTest, SubframeWidget) {
// Verify a subframe RenderWidget properly processes its viewport being
// resized.
TEST_F(RenderFrameImplTest, FrameResize) {
- ResizeParams resize_params;
+ VisualProperties visual_properties;
gfx::Size size(200, 200);
- resize_params.screen_info = ScreenInfo();
- resize_params.new_size = size;
- resize_params.compositor_viewport_pixel_size = size;
- resize_params.visible_viewport_size = size;
- resize_params.top_controls_height = 0.f;
- resize_params.browser_controls_shrink_blink_size = false;
- resize_params.is_fullscreen_granted = false;
- resize_params.content_source_id = frame_widget()->GetContentSourceId();
-
- ViewMsg_Resize resize_message(0, resize_params);
+ visual_properties.screen_info = ScreenInfo();
+ visual_properties.new_size = size;
+ visual_properties.compositor_viewport_pixel_size = size;
+ visual_properties.visible_viewport_size = size;
+ visual_properties.top_controls_height = 0.f;
+ visual_properties.browser_controls_shrink_blink_size = false;
+ visual_properties.is_fullscreen_granted = false;
+
+ ViewMsg_SynchronizeVisualProperties resize_message(0, visual_properties);
frame_widget()->OnMessageReceived(resize_message);
EXPECT_EQ(frame_widget()->GetWebWidget()->Size(), blink::WebSize(size));
@@ -270,11 +270,12 @@ TEST_F(RenderFrameImplTest, LoFiNotUpdatedOnSubframeCommits) {
item.Initialize();
// The main frame's and subframe's LoFi states should stay the same on
- // navigations within the page.
- frame()->DidNavigateWithinPage(item, blink::kWebStandardCommit, true);
+ // same-document navigations.
+ frame()->DidFinishSameDocumentNavigation(item, blink::kWebStandardCommit,
+ true);
EXPECT_EQ(SERVER_LOFI_ON, frame()->GetPreviewsState());
- GetMainRenderFrame()->DidNavigateWithinPage(item, blink::kWebStandardCommit,
- true);
+ GetMainRenderFrame()->DidFinishSameDocumentNavigation(
+ item, blink::kWebStandardCommit, true);
EXPECT_EQ(SERVER_LOFI_ON, GetMainRenderFrame()->GetPreviewsState());
// The subframe's LoFi state should not be reset on commit.
@@ -331,11 +332,12 @@ TEST_F(RenderFrameImplTest, EffectiveConnectionType) {
item.Initialize();
// The main frame's and subframe's effective connection type should stay the
- // same on navigations within the page.
- frame()->DidNavigateWithinPage(item, blink::kWebStandardCommit, true);
+ // same on same-document navigations.
+ frame()->DidFinishSameDocumentNavigation(item, blink::kWebStandardCommit,
+ true);
EXPECT_EQ(tests[i].type, frame()->GetEffectiveConnectionType());
- GetMainRenderFrame()->DidNavigateWithinPage(item, blink::kWebStandardCommit,
- true);
+ GetMainRenderFrame()->DidFinishSameDocumentNavigation(
+ item, blink::kWebStandardCommit, true);
EXPECT_EQ(tests[i].type, frame()->GetEffectiveConnectionType());
// The subframe's effective connection type should not be reset on commit.
@@ -413,6 +415,35 @@ TEST_F(RenderFrameImplTest, SaveImageFromDataURL) {
EXPECT_FALSE(msg4);
}
+// Tests that url download are throttled when reaching the limit.
+TEST_F(RenderFrameImplTest, DownloadUrlLimit) {
+ const IPC::Message* msg1 = render_thread_->sink().GetFirstMessageMatching(
+ FrameHostMsg_DownloadUrl::ID);
+ EXPECT_FALSE(msg1);
+ render_thread_->sink().ClearMessages();
+
+ WebURLRequest request;
+ request.SetURL(GURL("http://test/test.pdf"));
+ request.SetRequestorOrigin(
+ blink::WebSecurityOrigin::Create(GURL("http://test")));
+
+ for (int i = 0; i < 10; ++i) {
+ frame()->DownloadURL(request, mojo::ScopedMessagePipeHandle());
+ base::RunLoop().RunUntilIdle();
+ const IPC::Message* msg2 = render_thread_->sink().GetFirstMessageMatching(
+ FrameHostMsg_DownloadUrl::ID);
+ EXPECT_TRUE(msg2);
+ base::RunLoop().RunUntilIdle();
+ render_thread_->sink().ClearMessages();
+ }
+
+ frame()->DownloadURL(request, mojo::ScopedMessagePipeHandle());
+ base::RunLoop().RunUntilIdle();
+ const IPC::Message* msg3 = render_thread_->sink().GetFirstMessageMatching(
+ FrameHostMsg_DownloadUrl::ID);
+ EXPECT_FALSE(msg3);
+}
+
TEST_F(RenderFrameImplTest, ZoomLimit) {
const double kMinZoomLevel = ZoomFactorToZoomLevel(kMinimumZoomFactor);
const double kMaxZoomLevel = ZoomFactorToZoomLevel(kMaximumZoomFactor);
diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc
index 515172448f0..902038d46d7 100644
--- a/chromium/content/renderer/render_frame_proxy.cc
+++ b/chromium/content/renderer/render_frame_proxy.cc
@@ -54,7 +54,7 @@
#if BUILDFLAG(ENABLE_PRINTING)
// nogncheck because dependency on //printing is conditional upon
-// enable_basic_printing or enable_print_preview flags.
+// enable_basic_printing flags.
#include "printing/metafile_skia_wrapper.h" // nogncheck
#include "printing/pdf_metafile_skia.h" // nogncheck
#endif
@@ -239,10 +239,11 @@ void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
compositing_helper_ = std::make_unique<ChildFrameCompositingHelper>(this);
- pending_resize_params_.screen_info = render_widget_->GetOriginalScreenInfo();
+ pending_visual_properties_.screen_info =
+ render_widget_->GetOriginalScreenInfo();
#if defined(USE_AURA)
- if (features::IsMusEnabled()) {
+ if (features::IsMashEnabled()) {
RendererWindowTreeClient* renderer_window_tree_client =
RendererWindowTreeClient::Get(render_widget_->routing_id());
// It's possible a MusEmbeddedFrame has already been scheduled for creation
@@ -256,9 +257,10 @@ void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
}
void RenderFrameProxy::ResendResizeParams() {
- // Reset |sent_resize_params_| in order to allocate a new viz::LocalSurfaceId.
- sent_resize_params_ = base::nullopt;
- WasResized();
+ // Reset |sent_visual_properties_| in order to allocate a new
+ // viz::LocalSurfaceId.
+ sent_visual_properties_ = base::nullopt;
+ SynchronizeVisualProperties();
}
void RenderFrameProxy::WillBeginCompositorFrame() {
@@ -273,14 +275,20 @@ void RenderFrameProxy::WillBeginCompositorFrame() {
}
void RenderFrameProxy::OnScreenInfoChanged(const ScreenInfo& screen_info) {
- pending_resize_params_.screen_info = screen_info;
+ pending_visual_properties_.screen_info = screen_info;
if (crashed_) {
// Update the sad page to match the current ScreenInfo.
compositing_helper_->ChildFrameGone(local_frame_size(),
screen_info.device_scale_factor);
return;
}
- WasResized();
+ SynchronizeVisualProperties();
+}
+
+void RenderFrameProxy::UpdateCaptureSequenceNumber(
+ uint32_t capture_sequence_number) {
+ pending_visual_properties_.capture_sequence_number = capture_sequence_number;
+ SynchronizeVisualProperties();
}
void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) {
@@ -417,7 +425,8 @@ bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) {
OnSetFrameOwnerProperties)
IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateOrigin, OnDidUpdateOrigin)
IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetPageFocus)
- IPC_MESSAGE_HANDLER(FrameMsg_ResizeDueToAutoResize, OnResizeDueToAutoResize)
+ IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateVisualProperties,
+ OnDidUpdateVisualProperties)
IPC_MESSAGE_HANDLER(FrameMsg_EnableAutoResize, OnEnableAutoResize)
IPC_MESSAGE_HANDLER(FrameMsg_DisableAutoResize, OnDisableAutoResize)
IPC_MESSAGE_HANDLER(FrameMsg_SetFocusedFrame, OnSetFocusedFrame)
@@ -425,6 +434,7 @@ bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameMsg_SetHasReceivedUserGesture,
OnSetHasReceivedUserGesture)
IPC_MESSAGE_HANDLER(FrameMsg_ScrollRectToVisible, OnScrollRectToVisible)
+ IPC_MESSAGE_HANDLER(FrameMsg_BubbleLogicalScroll, OnBubbleLogicalScroll)
IPC_MESSAGE_HANDLER(FrameMsg_SetHasReceivedUserGestureBeforeNavigation,
OnSetHasReceivedUserGestureBeforeNavigation)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -564,22 +574,35 @@ void RenderFrameProxy::OnScrollRectToVisible(
web_frame_->ScrollRectToVisible(rect_to_scroll, params);
}
-void RenderFrameProxy::OnResizeDueToAutoResize(uint64_t sequence_number) {
- pending_resize_params_.auto_resize_sequence_number = sequence_number;
- WasResized();
+void RenderFrameProxy::OnBubbleLogicalScroll(
+ blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity) {
+ web_frame_->BubbleLogicalScroll(direction, granularity);
+}
+
+void RenderFrameProxy::OnDidUpdateVisualProperties(
+ const cc::RenderFrameMetadata& metadata) {
+ if (!parent_local_surface_id_allocator_.UpdateFromChild(
+ metadata.local_surface_id.value_or(viz::LocalSurfaceId()))) {
+ return;
+ }
+
+ // The viz::LocalSurfaceId has changed so we call SynchronizeVisualProperties
+ // here to embed it.
+ SynchronizeVisualProperties();
}
void RenderFrameProxy::OnEnableAutoResize(const gfx::Size& min_size,
const gfx::Size& max_size) {
- pending_resize_params_.auto_resize_enabled = true;
- pending_resize_params_.min_size_for_auto_resize = min_size;
- pending_resize_params_.max_size_for_auto_resize = max_size;
- WasResized();
+ pending_visual_properties_.auto_resize_enabled = true;
+ pending_visual_properties_.min_size_for_auto_resize = min_size;
+ pending_visual_properties_.max_size_for_auto_resize = max_size;
+ SynchronizeVisualProperties();
}
void RenderFrameProxy::OnDisableAutoResize() {
- pending_resize_params_.auto_resize_enabled = false;
- WasResized();
+ pending_visual_properties_.auto_resize_enabled = false;
+ SynchronizeVisualProperties();
}
#if defined(USE_AURA)
@@ -589,57 +612,69 @@ void RenderFrameProxy::SetMusEmbeddedFrame(
}
#endif
-void RenderFrameProxy::WasResized() {
+void RenderFrameProxy::SynchronizeVisualProperties() {
if (!frame_sink_id_.is_valid() || crashed_)
return;
- bool synchronized_params_changed =
- !sent_resize_params_ ||
- sent_resize_params_->auto_resize_enabled !=
- pending_resize_params_.auto_resize_enabled ||
- sent_resize_params_->min_size_for_auto_resize !=
- pending_resize_params_.min_size_for_auto_resize ||
- sent_resize_params_->max_size_for_auto_resize !=
- pending_resize_params_.max_size_for_auto_resize ||
- sent_resize_params_->local_frame_size !=
- pending_resize_params_.local_frame_size ||
- sent_resize_params_->screen_space_rect.size() !=
- pending_resize_params_.screen_space_rect.size() ||
- sent_resize_params_->screen_info != pending_resize_params_.screen_info ||
- sent_resize_params_->auto_resize_sequence_number !=
- pending_resize_params_.auto_resize_sequence_number;
-
- if (synchronized_params_changed)
- local_surface_id_ = parent_local_surface_id_allocator_.GenerateId();
-
- viz::SurfaceId surface_id(frame_sink_id_, local_surface_id_);
+ // Note that the following flag is true if the capture sequence number
+ // actually changed. That is, it is false if we did not have
+ // |sent_visual_properties_|, which is different from
+ // |synchronized_props_changed| below.
+ bool capture_sequence_number_changed =
+ sent_visual_properties_ &&
+ sent_visual_properties_->capture_sequence_number !=
+ pending_visual_properties_.capture_sequence_number;
+
+ bool synchronized_props_changed =
+ !sent_visual_properties_ ||
+ sent_visual_properties_->auto_resize_enabled !=
+ pending_visual_properties_.auto_resize_enabled ||
+ sent_visual_properties_->min_size_for_auto_resize !=
+ pending_visual_properties_.min_size_for_auto_resize ||
+ sent_visual_properties_->max_size_for_auto_resize !=
+ pending_visual_properties_.max_size_for_auto_resize ||
+ sent_visual_properties_->local_frame_size !=
+ pending_visual_properties_.local_frame_size ||
+ sent_visual_properties_->screen_space_rect.size() !=
+ pending_visual_properties_.screen_space_rect.size() ||
+ sent_visual_properties_->screen_info !=
+ pending_visual_properties_.screen_info ||
+ capture_sequence_number_changed;
+
+ if (synchronized_props_changed)
+ parent_local_surface_id_allocator_.GenerateId();
+
+ viz::SurfaceId surface_id(frame_sink_id_, GetLocalSurfaceId());
if (enable_surface_synchronization_) {
- // TODO(vmpstr): When capture_sequence_number is available, the deadline
- // should be infinite if the sequence number has changed.
- compositing_helper_->SetPrimarySurfaceId(
- surface_id, local_frame_size(),
- cc::DeadlinePolicy::UseDefaultDeadline());
+ // If we're synchronizing surfaces, then use an infinite deadline to ensure
+ // everything is synchronized.
+ cc::DeadlinePolicy deadline =
+ capture_sequence_number_changed
+ ? cc::DeadlinePolicy::UseInfiniteDeadline()
+ : cc::DeadlinePolicy::UseDefaultDeadline();
+ compositing_helper_->SetPrimarySurfaceId(surface_id, local_frame_size(),
+ deadline);
}
- bool rect_changed =
- !sent_resize_params_ || sent_resize_params_->screen_space_rect !=
- pending_resize_params_.screen_space_rect;
- bool resize_params_changed = synchronized_params_changed || rect_changed;
+ bool rect_changed = !sent_visual_properties_ ||
+ sent_visual_properties_->screen_space_rect !=
+ pending_visual_properties_.screen_space_rect;
+ bool visual_properties_changed = synchronized_props_changed || rect_changed;
#if defined(USE_AURA)
if (rect_changed && mus_embedded_frame_) {
- mus_embedded_frame_->SetWindowBounds(local_surface_id_,
+ mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(),
gfx::Rect(local_frame_size()));
}
#endif
- if (!resize_params_changed)
+ if (!visual_properties_changed)
return;
// Let the browser know about the updated view rect.
- Send(new FrameHostMsg_UpdateResizeParams(routing_id_, surface_id,
- pending_resize_params_));
- sent_resize_params_ = pending_resize_params_;
+ Send(new FrameHostMsg_SynchronizeVisualProperties(
+ routing_id_, surface_id, pending_visual_properties_));
+ sent_visual_properties_ = pending_visual_properties_;
// The visible rect that the OOPIF needs to raster depends partially on
// parameters that might have changed. If they affect the raster area, resend
@@ -705,7 +740,6 @@ void RenderFrameProxy::ForwardPostMessage(
DCHECK(!web_frame_ || web_frame_ == target_frame);
FrameMsg_PostMessage_Params params;
- params.is_data_raw_string = false;
params.message =
new base::RefCountedData<blink::TransferableMessage>(event.AsMessage());
params.message->data.has_user_gesture = has_user_gesture;
@@ -728,7 +762,8 @@ void RenderFrameProxy::ForwardPostMessage(
}
void RenderFrameProxy::Navigate(const blink::WebURLRequest& request,
- bool should_replace_current_entry) {
+ bool should_replace_current_entry,
+ mojo::ScopedMessagePipeHandle blob_url_token) {
FrameHostMsg_OpenURL_Params params;
params.url = request.Url();
params.uses_post = request.HttpMethod().Utf8() == "POST";
@@ -741,10 +776,7 @@ void RenderFrameProxy::Navigate(const blink::WebURLRequest& request,
params.should_replace_current_entry = should_replace_current_entry;
params.user_gesture = request.HasUserGesture();
params.triggering_event_info = blink::WebTriggeringEventInfo::kUnknown;
- params.suggested_filename =
- request.GetSuggestedFilename().has_value()
- ? base::Optional<std::string>(request.GetSuggestedFilename()->Utf8())
- : base::nullopt;
+ params.blob_url_token = blob_url_token.release();
Send(new FrameHostMsg_OpenURL(routing_id_, params));
}
@@ -752,17 +784,18 @@ void RenderFrameProxy::Navigate(const blink::WebURLRequest& request,
void RenderFrameProxy::FrameRectsChanged(
const blink::WebRect& local_frame_rect,
const blink::WebRect& screen_space_rect) {
- pending_resize_params_.screen_space_rect = gfx::Rect(screen_space_rect);
- pending_resize_params_.local_frame_size =
+ pending_visual_properties_.screen_space_rect = gfx::Rect(screen_space_rect);
+ pending_visual_properties_.local_frame_size =
gfx::Size(local_frame_rect.width, local_frame_rect.height);
- pending_resize_params_.screen_info = render_widget_->GetOriginalScreenInfo();
+ pending_visual_properties_.screen_info =
+ render_widget_->GetOriginalScreenInfo();
if (crashed_) {
// Update the sad page to match the current size.
compositing_helper_->ChildFrameGone(local_frame_size(),
screen_info().device_scale_factor);
return;
}
- WasResized();
+ SynchronizeVisualProperties();
}
void RenderFrameProxy::UpdateRemoteViewportIntersection(
@@ -782,6 +815,12 @@ void RenderFrameProxy::SetIsInert(bool inert) {
Send(new FrameHostMsg_SetIsInert(routing_id_, inert));
}
+void RenderFrameProxy::SetInheritedEffectiveTouchAction(
+ cc::TouchAction touch_action) {
+ Send(new FrameHostMsg_SetInheritedEffectiveTouchAction(routing_id_,
+ touch_action));
+}
+
void RenderFrameProxy::UpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled) {
Send(new FrameHostMsg_UpdateRenderThrottlingStatus(routing_id_, is_throttled,
@@ -835,14 +874,15 @@ void RenderFrameProxy::OnMusEmbeddedFrameSinkIdAllocated(
}
#endif
-blink::WebLayer* RenderFrameProxy::GetLayer() {
- return web_layer_.get();
+cc::Layer* RenderFrameProxy::GetLayer() {
+ return embedded_layer_.get();
}
-void RenderFrameProxy::SetLayer(std::unique_ptr<blink::WebLayer> web_layer) {
+void RenderFrameProxy::SetLayer(scoped_refptr<cc::Layer> layer,
+ bool prevent_contents_opaque_changes) {
if (web_frame())
- web_frame()->SetWebLayer(web_layer.get());
- web_layer_ = std::move(web_layer);
+ web_frame()->SetCcLayer(layer.get(), prevent_contents_opaque_changes);
+ embedded_layer_ = std::move(layer);
}
SkBitmap* RenderFrameProxy::GetSadPageBitmap() {
@@ -870,4 +910,8 @@ uint32_t RenderFrameProxy::Print(const blink::WebRect& rect,
#endif
}
+const viz::LocalSurfaceId& RenderFrameProxy::GetLocalSurfaceId() const {
+ return parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h
index fde712e1477..06f4981a856 100644
--- a/chromium/content/renderer/render_frame_proxy.h
+++ b/chromium/content/renderer/render_frame_proxy.h
@@ -10,7 +10,7 @@
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "content/common/content_export.h"
#include "content/common/frame_messages.h"
-#include "content/common/frame_resize_params.h"
+#include "content/common/frame_visual_properties.h"
#include "content/public/common/screen_info.h"
#include "content/renderer/child_frame_compositor.h"
#include "ipc/ipc_listener.h"
@@ -123,6 +123,9 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
// IPC::Sender
bool Send(IPC::Message* msg) override;
+ // IPC::Listener
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
// Out-of-process child frames receive a signal from RenderWidgetCompositor
// when a compositor frame will begin.
void WillBeginCompositorFrame();
@@ -131,6 +134,10 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
// ScreenInfo has changed.
void OnScreenInfoChanged(const ScreenInfo& screen_info);
+ // Invoked by RenderWidget when a new capture sequence number was set,
+ // indicating that surfaces should be synchronized.
+ void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
+
// Pass replicated information, such as security origin, to this
// RenderFrameProxy's WebRemoteFrame.
void SetReplicatedState(const FrameReplicationState& state);
@@ -154,22 +161,18 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame);
#endif
- void WasResized();
+ void SynchronizeVisualProperties();
const gfx::Rect& screen_space_rect() const {
- return pending_resize_params_.screen_space_rect;
+ return pending_visual_properties_.screen_space_rect;
}
const gfx::Size& local_frame_size() const {
- return pending_resize_params_.local_frame_size;
+ return pending_visual_properties_.local_frame_size;
}
const ScreenInfo& screen_info() const {
- return pending_resize_params_.screen_info;
- }
-
- uint64_t auto_size_sequence_number() const {
- return pending_resize_params_.auto_resize_sequence_number;
+ return pending_visual_properties_.screen_info;
}
const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
@@ -183,13 +186,15 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
blink::WebDOMMessageEvent event,
bool has_user_gesture) override;
void Navigate(const blink::WebURLRequest& request,
- bool should_replace_current_entry) override;
+ bool should_replace_current_entry,
+ mojo::ScopedMessagePipeHandle blob_url_token) override;
void FrameRectsChanged(const blink::WebRect& local_frame_rect,
const blink::WebRect& screen_space_rect) override;
void UpdateRemoteViewportIntersection(
const blink::WebRect& viewport_intersection) override;
void VisibilityChanged(bool visible) override;
void SetIsInert(bool) override;
+ void SetInheritedEffectiveTouchAction(cc::TouchAction) override;
void UpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled) override;
void DidChangeOpener(blink::WebFrame* opener) override;
@@ -213,9 +218,6 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
void SetChildFrameSurface(const viz::SurfaceInfo& surface_info);
- // IPC::Listener
- bool OnMessageReceived(const IPC::Message& msg) override;
-
// IPC handlers
void OnDeleteProxy();
void OnChildFrameProcessGone();
@@ -250,7 +252,9 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
void OnSetHasReceivedUserGesture();
void OnScrollRectToVisible(const gfx::Rect& rect_to_scroll,
const blink::WebScrollIntoViewParams& params);
- void OnResizeDueToAutoResize(uint64_t sequence_number);
+ void OnBubbleLogicalScroll(blink::WebScrollDirection direction,
+ blink::WebScrollGranularity granularity);
+ void OnDidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
void OnEnableAutoResize(const gfx::Size& min_size, const gfx::Size& max_size);
void OnDisableAutoResize();
void OnSetHasReceivedUserGestureBeforeNavigation(bool value);
@@ -264,10 +268,13 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
#endif
// ChildFrameCompositor:
- blink::WebLayer* GetLayer() override;
- void SetLayer(std::unique_ptr<blink::WebLayer> web_layer) override;
+ cc::Layer* GetLayer() override;
+ void SetLayer(scoped_refptr<cc::Layer> layer,
+ bool prevent_contents_opaque_changes) override;
SkBitmap* GetSadPageBitmap() override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const;
+
// The routing ID by which this RenderFrameProxy is known.
const int routing_id_;
@@ -292,16 +299,15 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
// therefore don't care to synchronize ResizeParams with viz::LocalSurfaceIds.
// Perhaps this can be moved to ChildFrameCompositingHelper?
// The last ResizeParams sent to the browser process, if any.
- base::Optional<FrameResizeParams> sent_resize_params_;
+ base::Optional<FrameVisualProperties> sent_visual_properties_;
// The current set of ResizeParams. This may or may not match
- // |sent_resize_params_|.
- FrameResizeParams pending_resize_params_;
+ // |sent_visual_properties_|.
+ FrameVisualProperties pending_visual_properties_;
bool crashed_ = false;
viz::FrameSinkId frame_sink_id_;
- viz::LocalSurfaceId local_surface_id_;
viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
bool enable_surface_synchronization_ = false;
@@ -314,7 +320,7 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener,
#endif
// The layer used to embed the out-of-process content.
- std::unique_ptr<blink::WebLayer> web_layer_;
+ scoped_refptr<cc::Layer> embedded_layer_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameProxy);
};
diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc
index 33800c023f5..f839d5610a1 100644
--- a/chromium/content/renderer/render_process_impl.cc
+++ b/chromium/content/renderer/render_process_impl.cc
@@ -143,6 +143,10 @@ RenderProcessImpl::RenderProcessImpl(
SetV8FlagIfFeature(features::kV8VmFuture, "--future");
SetV8FlagIfNotFeature(features::kV8VmFuture, "--no-future");
+
+ SetV8FlagIfFeature(features::kWebAssemblyBaseline, "--wasm-tier-up");
+ SetV8FlagIfNotFeature(features::kWebAssemblyBaseline, "--no-wasm-tier-up");
+
SetV8FlagIfFeature(features::kSharedArrayBuffer,
"--harmony-sharedarraybuffer");
SetV8FlagIfNotFeature(features::kSharedArrayBuffer,
@@ -150,10 +154,6 @@ RenderProcessImpl::RenderProcessImpl(
SetV8FlagIfNotFeature(features::kWebAssemblyTrapHandler,
"--no-wasm-trap-handler");
- SetV8FlagIfFeature(features::kArrayPrototypeValues,
- "--harmony-array-prototype-values");
- SetV8FlagIfNotFeature(features::kArrayPrototypeValues,
- "--no-harmony-array-prototype-values");
#if defined(OS_LINUX) && defined(ARCH_CPU_X86_64) && !defined(OS_ANDROID)
if (base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler)) {
bool use_v8_signal_handler = false;
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index 089bc9a3188..06f7d448799 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -26,6 +26,7 @@
#include "base/path_service.h"
#include "base/process/process_metrics.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -41,7 +42,6 @@
#include "build/build_config.h"
#include "cc/base/histograms.h"
#include "cc/base/switches.h"
-#include "cc/blink/web_layer_impl.h"
#include "cc/raster/task_graph_runner.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host_common.h"
@@ -50,13 +50,12 @@
#include "components/metrics/public/interfaces/single_sample_metrics.mojom.h"
#include "components/metrics/single_sample_metrics.h"
#include "components/viz/client/client_layer_tree_frame_sink.h"
-#include "components/viz/client/client_shared_bitmap_manager.h"
#include "components/viz/client/hit_test_data_provider.h"
#include "components/viz/client/hit_test_data_provider_draw_quad.h"
-#include "components/viz/client/hit_test_data_provider_surface_layer.h"
#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
+#include "components/viz/common/switches.h"
#include "content/child/memory/child_memory_coordinator_impl.h"
#include "content/child/runtime_features.h"
#include "content/child/thread_safe_sender.h"
@@ -93,23 +92,22 @@
#include "content/renderer/fileapi/webfilesystem_impl.h"
#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "content/renderer/indexed_db/indexed_db_dispatcher.h"
-#include "content/renderer/input/input_event_filter.h"
-#include "content/renderer/input/input_handler_manager.h"
-#include "content/renderer/input/main_thread_input_event_filter.h"
#include "content/renderer/input/widget_input_handler_manager.h"
#include "content/renderer/loader/resource_dispatcher.h"
-#include "content/renderer/media/audio_input_message_filter.h"
-#include "content/renderer/media/audio_message_filter.h"
#include "content/renderer/media/audio_renderer_mixer_manager.h"
#include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h"
#include "content/renderer/media/midi/midi_message_filter.h"
#include "content/renderer/media/render_media_client.h"
+#include "content/renderer/media/stream/aec_dump_message_filter.h"
#include "content/renderer/media/stream/media_stream_center.h"
#include "content/renderer/media/video_capture_impl_manager.h"
+#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
+#include "content/renderer/media/webrtc/peer_connection_tracker.h"
+#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
#include "content/renderer/mus/render_widget_window_tree_client_factory.h"
#include "content/renderer/mus/renderer_window_tree_client.h"
#include "content/renderer/net_info_helper.h"
-#include "content/renderer/notifications/notification_dispatcher.h"
+#include "content/renderer/p2p/socket_dispatcher.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process_impl.h"
#include "content/renderer/render_view_impl.h"
@@ -173,16 +171,10 @@
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
-#include "ui/gl/gl_switches.h"
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "content/renderer/p2p/socket_dispatcher.h"
-#endif
#if defined(OS_ANDROID)
#include <cpu-features.h>
-#include "content/renderer/android/synchronous_compositor_filter.h"
-#include "content/renderer/android/synchronous_compositor_proxy.h"
#include "content/renderer/android/synchronous_layer_tree_frame_sink.h"
#include "content/renderer/media/android/stream_texture_factory.h"
#include "media/base/android/media_codec_util.h"
@@ -199,13 +191,6 @@
#include <objbase.h>
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "content/renderer/media/stream/aec_dump_message_filter.h"
-#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
-#include "content/renderer/media/webrtc/peer_connection_tracker.h"
-#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
-#endif
-
#ifdef ENABLE_VTUNE_JIT_INTERFACE
#include "v8/src/third_party/vtune/v8-vtune.h"
#endif
@@ -382,16 +367,11 @@ scoped_refptr<ui::ContextProviderCommandBuffer> CreateOffscreenContext(
attributes.lose_context_when_out_of_memory = true;
attributes.enable_gles2_interface = support_gles2_interface;
attributes.enable_raster_interface = support_raster_interface;
- attributes.enable_oop_rasterization = support_oop_rasterization;
-
- bool enable_raster_decoder =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableRasterDecoder);
- // --enable-raster-decoder supports raster interface, but not
- // gles2 interface
- attributes.enable_raster_decoder = enable_raster_decoder &&
- support_raster_interface &&
- !support_gles2_interface;
+ // Using RasterDecoder for OOP-R backend, so we need support_raster_interface
+ // and !support_gles2_interface.
+ attributes.enable_oop_rasterization = support_oop_rasterization &&
+ support_raster_interface &&
+ !support_gles2_interface;
const bool automatic_flushes = false;
return base::MakeRefCounted<ui::ContextProviderCommandBuffer>(
@@ -400,7 +380,7 @@ scoped_refptr<ui::ContextProviderCommandBuffer> CreateOffscreenContext(
GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext/" +
ui::command_buffer_metrics::ContextTypeToString(type)),
automatic_flushes, support_locking, support_grcontext, limits, attributes,
- nullptr /* share_context */, type);
+ type);
}
// Hook that allows single-sample metric code from //components/metrics to
@@ -426,17 +406,15 @@ class RendererLocalSurfaceIdProvider : public viz::LocalSurfaceIdProvider {
const viz::CompositorFrame& frame) override {
auto new_surface_properties =
RenderWidgetSurfaceProperties::FromCompositorFrame(frame);
- if (!local_surface_id_.is_valid() ||
- new_surface_properties != surface_properties_) {
- local_surface_id_ = parent_local_surface_id_allocator_.GenerateId();
+ if (new_surface_properties != surface_properties_) {
+ parent_local_surface_id_allocator_.GenerateId();
surface_properties_ = new_surface_properties;
}
- return local_surface_id_;
+ return parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
}
private:
viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
- viz::LocalSurfaceId local_surface_id_;
RenderWidgetSurfaceProperties surface_properties_;
};
@@ -809,7 +787,7 @@ void RenderThreadImpl::Init(
metrics::InitializeSingleSampleMetricsFactory(
base::BindRepeating(&CreateSingleSampleMetricsProvider,
- message_loop()->task_runner(), GetConnector()));
+ main_thread_runner(), GetConnector()));
gpu_ = ui::Gpu::Create(GetConnector(),
base::FeatureList::IsEnabled(features::kMash)
@@ -817,20 +795,6 @@ void RenderThreadImpl::Init(
: mojom::kBrowserServiceName,
GetIOTaskRunner());
- viz::mojom::SharedBitmapAllocationNotifierPtr
- shared_bitmap_allocation_notifier_ptr;
- GetConnector()->BindInterface(
- mojom::kBrowserServiceName,
- mojo::MakeRequest(&shared_bitmap_allocation_notifier_ptr));
- shared_bitmap_manager_ = std::make_unique<viz::ClientSharedBitmapManager>(
- viz::mojom::ThreadSafeSharedBitmapAllocationNotifierPtr::Create(
- shared_bitmap_allocation_notifier_ptr.PassInterface(),
- GetChannel()->ipc_task_runner_refptr()));
-
- notification_dispatcher_ = new NotificationDispatcher(
- thread_safe_sender(), GetWebMainThreadScheduler()->IPCTaskRunner());
- AddFilter(notification_dispatcher_->GetFilter());
-
resource_dispatcher_.reset(new ResourceDispatcher());
url_loader_throttle_provider_ =
GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
@@ -862,7 +826,6 @@ void RenderThreadImpl::Init(
browser_plugin_manager_.reset(new BrowserPluginManager());
AddObserver(browser_plugin_manager_.get());
-#if BUILDFLAG(ENABLE_WEBRTC)
peer_connection_tracker_.reset(new PeerConnectionTracker());
AddObserver(peer_connection_tracker_.get());
@@ -872,49 +835,20 @@ void RenderThreadImpl::Init(
peer_connection_factory_.reset(
new PeerConnectionDependencyFactory(p2p_socket_dispatcher_.get()));
- aec_dump_message_filter_ = new AecDumpMessageFilter(
- GetIOTaskRunner(), message_loop()->task_runner());
+ aec_dump_message_filter_ =
+ new AecDumpMessageFilter(GetIOTaskRunner(), main_thread_runner());
AddFilter(aec_dump_message_filter_.get());
-#endif // BUILDFLAG(ENABLE_WEBRTC)
- {
- scoped_refptr<AudioInputMessageFilter> audio_input_message_filter;
- if (!base::FeatureList::IsEnabled(
- features::kUseMojoAudioInputStreamFactory)) {
- // In case we shouldn't use mojo factories, we need to create an
- // AudioInputMessageFilter which |audio_input_ipc_factory_| can use for
- // IPC.
- audio_input_message_filter =
- base::MakeRefCounted<AudioInputMessageFilter>(GetIOTaskRunner());
- AddFilter(audio_input_message_filter.get());
- }
-
- audio_input_ipc_factory_.emplace(std::move(audio_input_message_filter),
- message_loop()->task_runner(),
- GetIOTaskRunner());
- }
+ audio_input_ipc_factory_.emplace(main_thread_runner(), GetIOTaskRunner());
- {
- scoped_refptr<AudioMessageFilter> audio_output_message_filter;
- if (!base::FeatureList::IsEnabled(
- features::kUseMojoAudioOutputStreamFactory)) {
- // In case we shouldn't use mojo factories, we need to create an
- // AudioMessageFilter which |audio_output_ipc_factory_| can use for IPC.
- audio_output_message_filter =
- base::MakeRefCounted<AudioMessageFilter>(GetIOTaskRunner());
- AddFilter(audio_output_message_filter.get());
- }
-
- audio_output_ipc_factory_.emplace(std::move(audio_output_message_filter),
- GetIOTaskRunner());
- }
+ audio_output_ipc_factory_.emplace(GetIOTaskRunner());
midi_message_filter_ = new MidiMessageFilter(GetIOTaskRunner());
AddFilter(midi_message_filter_.get());
#if defined(USE_AURA)
- if (features::IsMusEnabled())
+ if (features::IsMashEnabled())
CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection());
#endif
@@ -1068,10 +1002,23 @@ void RenderThreadImpl::Init(
DCHECK(parsed_num_raster_threads) << string_value;
DCHECK_GT(num_raster_threads, 0);
+#if defined(OS_LINUX)
+ categorized_worker_pool_->SetBackgroundingCallback(
+ main_thread_scheduler_->DefaultTaskRunner(),
+ base::BindOnce(
+ [](base::WeakPtr<RenderThreadImpl> render_thread,
+ base::PlatformThreadId thread_id) {
+ if (!render_thread)
+ return;
+ render_thread->render_message_filter()->SetThreadPriority(
+ thread_id, base::ThreadPriority::BACKGROUND);
+ },
+ weak_factory_.GetWeakPtr()));
+#endif
categorized_worker_pool_->Start(num_raster_threads);
discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
- if (features::IsMusEnabled()) {
+ if (features::IsMashEnabled()) {
#if defined(USE_AURA)
GetServiceManagerConnection()->GetConnector()->BindInterface(
ui::mojom::kServiceName, &manager_ptr);
@@ -1099,9 +1046,6 @@ void RenderThreadImpl::Init(
#if defined(OS_LINUX)
render_message_filter()->SetThreadPriority(
ChildProcess::current()->io_thread_id(), base::ThreadPriority::DISPLAY);
- render_message_filter()->SetThreadPriority(
- categorized_worker_pool_->background_worker_thread_id(),
- base::ThreadPriority::BACKGROUND);
#endif
process_foregrounded_count_ = 0;
@@ -1308,30 +1252,6 @@ void RenderThreadImpl::InitializeCompositorThread() {
render_message_filter()->SetThreadPriority(compositor_thread_->ThreadId(),
base::ThreadPriority::DISPLAY);
#endif
-
- if (!base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- SynchronousInputHandlerProxyClient* synchronous_input_handler_proxy_client =
- nullptr;
-#if defined(OS_ANDROID)
- if (GetContentClient()->UsingSynchronousCompositing()) {
- sync_compositor_message_filter_ =
- new SynchronousCompositorFilter(compositor_task_runner_);
- AddFilter(sync_compositor_message_filter_.get());
- synchronous_input_handler_proxy_client =
- sync_compositor_message_filter_.get();
- }
-#endif
- scoped_refptr<InputEventFilter> compositor_input_event_filter(
- new InputEventFilter(main_input_callback_.callback(),
- main_thread_compositor_task_runner_,
- compositor_task_runner_));
- InputHandlerManagerClient* input_handler_manager_client =
- compositor_input_event_filter.get();
- input_event_filter_ = compositor_input_event_filter;
- input_handler_manager_.reset(new InputHandlerManager(
- compositor_task_runner_, input_handler_manager_client,
- synchronous_input_handler_proxy_client, main_thread_scheduler_.get()));
- }
}
void RenderThreadImpl::InitializeWebKit(
@@ -1363,23 +1283,9 @@ void RenderThreadImpl::InitializeWebKit(
main_thread_compositor_task_runner_ =
main_thread_scheduler_->CompositorTaskRunner();
- main_input_callback_.Reset(
- base::Bind(base::IgnoreResult(&RenderThreadImpl::OnMessageReceived),
- base::Unretained(this)));
-
if (!command_line.HasSwitch(switches::kDisableThreadedCompositing))
InitializeCompositorThread();
- if (!input_event_filter_.get()) {
- // Always provide an input event filter implementation to ensure consistent
- // input event scheduling and prioritization.
- // TODO(jdduke): Merge InputEventFilter, InputHandlerManager and
- // MainThreadInputEventFilter, crbug.com/436057.
- input_event_filter_ = new MainThreadInputEventFilter(
- main_input_callback_.callback(), main_thread_compositor_task_runner_);
- }
- AddFilter(input_event_filter_.get());
-
scoped_refptr<base::SingleThreadTaskRunner> compositor_impl_side_task_runner;
if (compositor_task_runner_)
compositor_impl_side_task_runner = compositor_task_runner_;
@@ -1404,8 +1310,8 @@ void RenderThreadImpl::InitializeWebKit(
thread_safe_sender(), GetWebMainThreadScheduler()->IPCTaskRunner());
AddFilter(service_worker_message_filter_->GetFilter());
- main_thread_scheduler_->SetStoppingWhenBackgroundedEnabled(
- GetContentClient()->renderer()->AllowStoppingWhenProcessBackgrounded());
+ main_thread_scheduler_->SetFreezingWhenBackgroundedEnabled(
+ GetContentClient()->renderer()->AllowFreezingWhenProcessBackgrounded());
SkGraphics::SetResourceCacheSingleAllocationByteLimit(
kImageCacheSingleAllocationByteLimit);
@@ -1455,10 +1361,6 @@ RenderThreadImpl::HostAllocateSharedMemoryBuffer(size_t size) {
return ChildThreadImpl::AllocateSharedMemory(size);
}
-viz::SharedBitmapManager* RenderThreadImpl::GetSharedBitmapManager() {
- return shared_bitmap_manager();
-}
-
void RenderThreadImpl::RegisterExtension(v8::Extension* extension) {
WebScriptController::RegisterExtension(extension);
}
@@ -1545,13 +1447,12 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
DCHECK(IsMainThread());
if (!gpu_factories_.empty()) {
- if (!gpu_factories_.back()->CheckContextProviderLost())
+ if (!gpu_factories_.back()->CheckContextProviderLostOnMainThread())
return gpu_factories_.back().get();
GetMediaThreadTaskRunner()->PostTask(
FROM_HERE,
- base::BindOnce(base::IgnoreResult(
- &GpuVideoAcceleratorFactoriesImpl::CheckContextLost),
+ base::BindOnce(&GpuVideoAcceleratorFactoriesImpl::DestroyContext,
base::Unretained(gpu_factories_.back().get())));
}
@@ -1582,17 +1483,24 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
(gpu_channel_host->gpu_feature_info()
.status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE] ==
gpu::kGpuFeatureStatusEnabled);
- const bool enable_gpu_memory_buffer_video_frames =
+ const bool enable_gpu_memory_buffers =
!is_gpu_compositing_disabled_ &&
-#if defined(OS_MACOSX) || defined(OS_LINUX)
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_WIN)
!cmd_line->HasSwitch(switches::kDisableGpuMemoryBufferVideoFrames);
-#elif defined(OS_WIN)
- !cmd_line->HasSwitch(switches::kDisableGpuMemoryBufferVideoFrames) &&
- (cmd_line->HasSwitch(switches::kEnableGpuMemoryBufferVideoFrames) ||
- gpu_channel_host->gpu_info().supports_overlays);
#else
cmd_line->HasSwitch(switches::kEnableGpuMemoryBufferVideoFrames);
-#endif
+#endif // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_WIN)
+ const bool enable_media_stream_gpu_memory_buffers =
+ enable_gpu_memory_buffers &&
+ base::FeatureList::IsEnabled(
+ features::kWebRtcUseGpuMemoryBufferVideoFrames);
+ bool enable_video_gpu_memory_buffers = enable_gpu_memory_buffers;
+#if defined(OS_WIN)
+ enable_video_gpu_memory_buffers =
+ enable_video_gpu_memory_buffers &&
+ (cmd_line->HasSwitch(switches::kEnableGpuMemoryBufferVideoFrames) ||
+ gpu_channel_host->gpu_info().supports_overlays);
+#endif // defined(OS_WIN)
media::mojom::VideoEncodeAcceleratorProviderPtr vea_provider;
gpu_->CreateVideoEncodeAcceleratorProvider(mojo::MakeRequest(&vea_provider));
@@ -1600,8 +1508,8 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
gpu_factories_.push_back(GpuVideoAcceleratorFactoriesImpl::Create(
std::move(gpu_channel_host), base::ThreadTaskRunnerHandle::Get(),
GetMediaThreadTaskRunner(), std::move(media_context_provider),
- enable_gpu_memory_buffer_video_frames, enable_video_accelerator,
- vea_provider.PassInterface()));
+ enable_video_gpu_memory_buffers, enable_media_stream_gpu_memory_buffers,
+ enable_video_accelerator, vea_provider.PassInterface()));
gpu_factories_.back()->SetRenderingColorSpace(rendering_color_space_);
return gpu_factories_.back().get();
}
@@ -1686,6 +1594,11 @@ void RenderThreadImpl::SetRendererProcessType(
main_thread_scheduler_->SetRendererProcessType(type);
}
+blink::WebString RenderThreadImpl::GetUserAgent() const {
+ DCHECK(!user_agent_.IsNull());
+ return user_agent_;
+}
+
bool RenderThreadImpl::OnMessageReceived(const IPC::Message& msg) {
if (file_system_dispatcher_->OnMessageReceived(msg))
return true;
@@ -2090,23 +2003,18 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
params.hit_test_data_provider =
std::make_unique<viz::HitTestDataProviderDrawQuad>(
true /* should_ask_for_child_region */);
- } else if (features::IsVizHitTestingSurfaceLayerEnabled()) {
- params.hit_test_data_provider =
- std::make_unique<viz::HitTestDataProviderSurfaceLayer>();
}
// The renderer runs animations and layout for animate_only BeginFrames.
params.wants_animate_only_begin_frames = true;
- // In disable gpu vsync mode, also let the renderer tick as fast as it
- // can. The top level begin frame source will also be running as a back
- // to back begin frame source, but using a synthetic begin frame source
- // here reduces latency when in this mode (at least for frames
- // starting--it potentially increases it for input on the other hand.)
- if (command_line.HasSwitch(switches::kDisableGpuVsync) &&
- command_line.GetSwitchValueASCII(switches::kDisableGpuVsync) != "gpu") {
+ // In disable frame rate limit mode, also let the renderer tick as fast as it
+ // can. The top level begin frame source will also be running as a back to
+ // back begin frame source, but using a synthetic begin frame source here
+ // reduces latency when in this mode (at least for frames starting--it
+ // potentially increases it for input on the other hand.)
+ if (command_line.HasSwitch(switches::kDisableFrameRateLimit))
params.synthetic_begin_frame_source = CreateSyntheticBeginFrameSource();
- }
#if defined(USE_AURA)
if (base::FeatureList::IsEnabled(features::kMash)) {
@@ -2125,6 +2033,9 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
->RequestLayerTreeFrameSink(
gpu_->CreateContextProvider(std::move(channel)),
GetGpuMemoryBufferManager(), callback);
+ frame_sink_provider_->RegisterRenderFrameMetadataObserver(
+ routing_id, std::move(render_frame_metadata_observer_client_request),
+ std::move(render_frame_metadata_observer_ptr));
return;
}
#endif
@@ -2139,10 +2050,10 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
DCHECK(!layout_test_mode());
frame_sink_provider_->CreateForWidget(
routing_id, std::move(compositor_frame_sink_request),
- std::move(compositor_frame_sink_client),
- std::move(render_frame_metadata_observer_client_request),
+ std::move(compositor_frame_sink_client));
+ frame_sink_provider_->RegisterRenderFrameMetadataObserver(
+ routing_id, std::move(render_frame_metadata_observer_client_request),
std::move(render_frame_metadata_observer_ptr));
- params.shared_bitmap_manager = shared_bitmap_manager();
callback.Run(std::make_unique<viz::ClientLayerTreeFrameSink>(
nullptr, nullptr, &params));
return;
@@ -2193,51 +2104,46 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink(
gpu_channel_host, GetGpuMemoryBufferManager(), kGpuStreamIdDefault,
kGpuStreamPriorityDefault, gpu::kNullSurfaceHandle, url,
automatic_flushes, support_locking, support_grcontext, limits,
- attributes, nullptr /* share_context */,
- ui::command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT));
+ attributes, ui::command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT));
if (layout_test_deps_) {
- callback.Run(layout_test_deps_->CreateLayerTreeFrameSink(
- routing_id, std::move(gpu_channel_host), std::move(context_provider),
- std::move(worker_context_provider), GetGpuMemoryBufferManager(), this));
- return;
+ if (!layout_test_deps_->UseDisplayCompositorPixelDump()) {
+ callback.Run(layout_test_deps_->CreateLayerTreeFrameSink(
+ routing_id, std::move(gpu_channel_host), std::move(context_provider),
+ std::move(worker_context_provider), GetGpuMemoryBufferManager(),
+ this));
+ return;
+ } else if (!params.compositor_task_runner) {
+ // The frame sink provider expects a compositor task runner, but we might
+ // not have that if we're running layout tests in single threaded mode.
+ // Set it to be our thread's task runner instead.
+ params.compositor_task_runner = GetCompositorMainThreadTaskRunner();
+ }
}
#if defined(OS_ANDROID)
if (GetContentClient()->UsingSynchronousCompositing()) {
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- RenderViewImpl* view = RenderViewImpl::FromRoutingID(routing_id);
- if (view) {
- callback.Run(std::make_unique<SynchronousLayerTreeFrameSink>(
- std::move(context_provider), std::move(worker_context_provider),
- compositor_task_runner_, GetGpuMemoryBufferManager(),
- sync_message_filter(), routing_id,
- g_next_layer_tree_frame_sink_id++,
- std::move(params.synthetic_begin_frame_source),
- view->widget_input_handler_manager()
- ->GetSynchronousCompositorRegistry(),
- std::move(frame_swap_message_queue)));
- return;
- } else {
- NOTREACHED();
- }
- } else {
+ RenderViewImpl* view = RenderViewImpl::FromRoutingID(routing_id);
+ if (view) {
callback.Run(std::make_unique<SynchronousLayerTreeFrameSink>(
std::move(context_provider), std::move(worker_context_provider),
compositor_task_runner_, GetGpuMemoryBufferManager(),
- sync_compositor_message_filter_.get(), routing_id,
- g_next_layer_tree_frame_sink_id++,
+ sync_message_filter(), routing_id, g_next_layer_tree_frame_sink_id++,
std::move(params.synthetic_begin_frame_source),
- sync_compositor_message_filter_.get(),
+ view->widget_input_handler_manager()
+ ->GetSynchronousCompositorRegistry(),
std::move(frame_swap_message_queue)));
return;
+ } else {
+ NOTREACHED();
}
}
#endif
frame_sink_provider_->CreateForWidget(
routing_id, std::move(compositor_frame_sink_request),
- std::move(compositor_frame_sink_client),
- std::move(render_frame_metadata_observer_client_request),
+ std::move(compositor_frame_sink_client));
+ frame_sink_provider_->RegisterRenderFrameMetadataObserver(
+ routing_id, std::move(render_frame_metadata_observer_client_request),
std::move(render_frame_metadata_observer_ptr));
params.gpu_memory_buffer_manager = GetGpuMemoryBufferManager();
callback.Run(std::make_unique<viz::ClientLayerTreeFrameSink>(
@@ -2254,7 +2160,8 @@ std::unique_ptr<cc::SwapPromise>
RenderThreadImpl::RequestCopyOfOutputForLayoutTest(
int32_t routing_id,
std::unique_ptr<viz::CopyOutputRequest> request) {
- DCHECK(layout_test_deps_);
+ DCHECK(layout_test_deps_ &&
+ !layout_test_deps_->UseDisplayCompositorPixelDump());
return layout_test_deps_->RequestCopyOfOutput(routing_id, std::move(request));
}
@@ -2262,21 +2169,17 @@ std::unique_ptr<blink::WebMediaStreamCenter>
RenderThreadImpl::CreateMediaStreamCenter(
blink::WebMediaStreamCenterClient* client) {
std::unique_ptr<blink::WebMediaStreamCenter> media_stream_center;
-#if BUILDFLAG(ENABLE_WEBRTC)
if (!media_stream_center) {
media_stream_center = std::make_unique<MediaStreamCenter>(
client, GetPeerConnectionDependencyFactory());
}
-#endif
return media_stream_center;
}
-#if BUILDFLAG(ENABLE_WEBRTC)
PeerConnectionDependencyFactory*
RenderThreadImpl::GetPeerConnectionDependencyFactory() {
return peer_connection_factory_.get();
}
-#endif
mojom::RenderFrameMessageFilter*
RenderThreadImpl::render_frame_message_filter() {
@@ -2323,12 +2226,6 @@ void RenderThreadImpl::CreateFrame(mojom::CreateFrameParamsPtr params) {
params->has_committed_real_load);
}
-void RenderThreadImpl::SetUpEmbeddedWorkerChannelForServiceWorker(
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest client_request) {
- EmbeddedWorkerInstanceClientImpl::Create(
- blink_initialized_time_, GetIOTaskRunner(), std::move(client_request));
-}
-
void RenderThreadImpl::CreateFrameProxy(
int32_t routing_id,
int32_t render_view_routing_id,
@@ -2342,6 +2239,12 @@ void RenderThreadImpl::CreateFrameProxy(
replicated_state, devtools_frame_token);
}
+void RenderThreadImpl::SetUpEmbeddedWorkerChannelForServiceWorker(
+ mojom::EmbeddedWorkerInstanceClientRequest client_request) {
+ EmbeddedWorkerInstanceClientImpl::Create(
+ blink_initialized_time_, GetIOTaskRunner(), std::move(client_request));
+}
+
void RenderThreadImpl::OnNetworkConnectionChanged(
net::NetworkChangeNotifier::ConnectionType type,
double max_bandwidth_mbps) {
@@ -2377,6 +2280,11 @@ void RenderThreadImpl::SetWebKitSharedTimersSuspended(bool suspend) {
#endif
}
+void RenderThreadImpl::SetUserAgent(const std::string& user_agent) {
+ DCHECK(user_agent_.IsNull());
+ user_agent_ = WebString::FromUTF8(user_agent);
+}
+
void RenderThreadImpl::UpdateScrollbarTheme(
mojom::UpdateScrollbarThemeParamsPtr params) {
#if defined(OS_MACOSX)
@@ -2476,7 +2384,7 @@ void RenderThreadImpl::RecordPurgeMemory(RendererMemoryMetrics before) {
scoped_refptr<base::SingleThreadTaskRunner>
RenderThreadImpl::GetMediaThreadTaskRunner() {
- DCHECK(message_loop()->task_runner()->BelongsToCurrentThread());
+ DCHECK(main_thread_runner()->BelongsToCurrentThread());
if (!media_thread_) {
media_thread_.reset(new base::Thread("Media"));
media_thread_->Start();
diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h
index b88425f8da9..6ab16c9a4fa 100644
--- a/chromium/content/renderer/render_thread_impl.h
+++ b/chromium/content/renderer/render_thread_impl.h
@@ -121,7 +121,6 @@ class Extension;
namespace viz {
class BeginFrameSource;
-class ClientSharedBitmapManager;
class RasterContextProvider;
class SyntheticBeginFrameSource;
}
@@ -130,7 +129,6 @@ namespace content {
class AppCacheDispatcher;
class AecDumpMessageFilter;
-class AudioMessageFilter;
class AudioRendererMixerManager;
class BrowserPluginManager;
class CategorizedWorkerPool;
@@ -139,9 +137,7 @@ class FileSystemDispatcher;
class FrameSwapMessageQueue;
class GpuVideoAcceleratorFactoriesImpl;
class IndexedDBDispatcher;
-class InputHandlerManager;
class MidiMessageFilter;
-class NotificationDispatcher;
class P2PSocketDispatcher;
class PeerConnectionDependencyFactory;
class PeerConnectionTracker;
@@ -153,7 +149,6 @@ class VideoCaptureImplManager;
#if defined(OS_ANDROID)
class StreamTextureFactory;
-class SynchronousCompositorFilter;
#endif
#if defined(COMPILER_MSVC)
@@ -224,7 +219,6 @@ class CONTENT_EXPORT RenderThreadImpl
ResourceDispatcherDelegate* delegate) override;
std::unique_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
size_t buffer_size) override;
- viz::SharedBitmapManager* GetSharedBitmapManager() override;
void RegisterExtension(v8::Extension* extension) override;
void ScheduleIdleHandler(int64_t initial_delay_ms) override;
void IdleHandler() override;
@@ -237,6 +231,7 @@ class CONTENT_EXPORT RenderThreadImpl
int32_t GetClientId() override;
void SetRendererProcessType(
blink::scheduler::RendererProcessType type) override;
+ blink::WebString GetUserAgent() const override;
// IPC::Listener implementation via ChildThreadImpl:
bool OnMessageReceived(const IPC::Message& msg) override;
@@ -321,10 +316,6 @@ class CONTENT_EXPORT RenderThreadImpl
return blink_platform_impl_.get();
}
- InputHandlerManager* input_handler_manager() const {
- return input_handler_manager_.get();
- }
-
// Will be null if threaded compositing has not been enabled.
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner() const {
return compositor_task_runner_;
@@ -355,10 +346,6 @@ class CONTENT_EXPORT RenderThreadImpl
}
#if defined(OS_ANDROID)
- SynchronousCompositorFilter* sync_compositor_message_filter() {
- return sync_compositor_message_filter_.get();
- }
-
scoped_refptr<StreamTextureFactory> GetStreamTexureFactory();
bool EnableStreamTextureCopy();
#endif
@@ -372,7 +359,6 @@ class CONTENT_EXPORT RenderThreadImpl
return browser_plugin_manager_.get();
}
-#if BUILDFLAG(ENABLE_WEBRTC)
// Returns a factory used for creating RTC PeerConnection objects.
PeerConnectionDependencyFactory* GetPeerConnectionDependencyFactory();
@@ -384,21 +370,11 @@ class CONTENT_EXPORT RenderThreadImpl
P2PSocketDispatcher* p2p_socket_dispatcher() {
return p2p_socket_dispatcher_.get();
}
-#endif
VideoCaptureImplManager* video_capture_impl_manager() const {
return vc_manager_.get();
}
- viz::ClientSharedBitmapManager* shared_bitmap_manager() const {
- DCHECK(shared_bitmap_manager_);
- return shared_bitmap_manager_.get();
- }
-
- NotificationDispatcher* notification_dispatcher() const {
- return notification_dispatcher_.get();
- }
-
mojom::RenderFrameMessageFilter* render_frame_message_filter();
mojom::RenderMessageFilter* render_message_filter();
@@ -578,9 +554,6 @@ class CONTENT_EXPORT RenderThreadImpl
service_manager::mojom::ServiceRequest service_request) override;
void CreateView(mojom::CreateViewParamsPtr params) override;
void CreateFrame(mojom::CreateFrameParamsPtr params) override;
- void SetUpEmbeddedWorkerChannelForServiceWorker(
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest client_request)
- override;
void CreateFrameProxy(
int32_t routing_id,
int32_t render_view_routing_id,
@@ -588,6 +561,8 @@ class CONTENT_EXPORT RenderThreadImpl
int32_t parent_routing_id,
const FrameReplicationState& replicated_state,
const base::UnguessableToken& devtools_frame_token) override;
+ void SetUpEmbeddedWorkerChannelForServiceWorker(
+ mojom::EmbeddedWorkerInstanceClientRequest client_request) override;
void OnNetworkConnectionChanged(
net::NetworkChangeNotifier::ConnectionType type,
double max_bandwidth_mbps) override;
@@ -596,6 +571,7 @@ class CONTENT_EXPORT RenderThreadImpl
base::TimeDelta transport_rtt,
double bandwidth_kbps) override;
void SetWebKitSharedTimersSuspended(bool suspend) override;
+ void SetUserAgent(const std::string& user_agent) override;
void UpdateScrollbarTheme(
mojom::UpdateScrollbarThemeParamsPtr params) override;
void OnSystemColorsChanged(int32_t aqua_color_variant,
@@ -649,7 +625,6 @@ class CONTENT_EXPORT RenderThreadImpl
std::unique_ptr<BrowserPluginManager> browser_plugin_manager_;
-#if BUILDFLAG(ENABLE_WEBRTC)
std::unique_ptr<PeerConnectionDependencyFactory> peer_connection_factory_;
// This is used to communicate to the browser process the status
@@ -664,23 +639,17 @@ class CONTENT_EXPORT RenderThreadImpl
// diagnostic audio data for WebRTC stored locally when enabled by the user in
// chrome://webrtc-internals.
scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
-#endif
// Provides AudioInputIPC objects for audio input devices. Initialized in
// Init.
base::Optional<AudioInputIPCFactory> audio_input_ipc_factory_;
- // Provides AudioOutputIPC objects for audio output devices. It either uses
- // an AudioMessageFilter for this or provides MojoAudioOutputIPC objects.
- // Initialized in Init.
+ // Provides AudioOutputIPC objects for audio output devices. Initialized in
+ // Init.
base::Optional<AudioOutputIPCFactory> audio_output_ipc_factory_;
// Used on the render thread.
std::unique_ptr<VideoCaptureImplManager> vc_manager_;
- std::unique_ptr<viz::ClientSharedBitmapManager> shared_bitmap_manager_;
-
- scoped_refptr<NotificationDispatcher> notification_dispatcher_;
-
// The time Blink was initialized. Used for UMA.
base::TimeTicks blink_initialized_time_;
@@ -698,6 +667,8 @@ class CONTENT_EXPORT RenderThreadImpl
bool webkit_shared_timer_suspended_;
+ blink::WebString user_agent_;
+
// Used to control layout test specific behavior.
std::unique_ptr<LayoutTestDependencies> layout_test_deps_;
@@ -737,12 +708,7 @@ class CONTENT_EXPORT RenderThreadImpl
// Pool of workers used for raster operations (e.g., tile rasterization).
scoped_refptr<CategorizedWorkerPool> categorized_worker_pool_;
- base::CancelableCallback<void(const IPC::Message&)> main_input_callback_;
- scoped_refptr<IPC::MessageFilter> input_event_filter_;
- std::unique_ptr<InputHandlerManager> input_handler_manager_;
-
#if defined(OS_ANDROID)
- scoped_refptr<SynchronousCompositorFilter> sync_compositor_message_filter_;
scoped_refptr<StreamTextureFactory> stream_texture_factory_;
#endif
diff --git a/chromium/content/renderer/render_thread_impl_browsertest.cc b/chromium/content/renderer/render_thread_impl_browsertest.cc
index b649ae5669b..f5977ad2ea6 100644
--- a/chromium/content/renderer/render_thread_impl_browsertest.cc
+++ b/chromium/content/renderer/render_thread_impl_browsertest.cc
@@ -307,21 +307,6 @@ class RenderThreadImplBrowserTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderThreadImplBrowserTest);
};
-class RenderThreadImplMojoInputMessagesDisabledBrowserTest
- : public RenderThreadImplBrowserTest {
- public:
- RenderThreadImplMojoInputMessagesDisabledBrowserTest() {
- feature_list_.InitAndDisableFeature(features::kMojoInputMessages);
- }
-
- private:
- base::test::ScopedFeatureList feature_list_;
-};
-
-void CheckRenderThreadInputHandlerManager(RenderThreadImpl* thread) {
- ASSERT_TRUE(thread->input_handler_manager());
-}
-
// Check that InputHandlerManager outlives compositor thread because it uses
// raw pointers to post tasks.
// Disabled under LeakSanitizer due to memory leaks. http://crbug.com/348994
@@ -333,14 +318,6 @@ void CheckRenderThreadInputHandlerManager(RenderThreadImpl* thread) {
#define MAYBE_InputHandlerManagerDestroyedAfterCompositorThread \
InputHandlerManagerDestroyedAfterCompositorThread
#endif
-TEST_F(RenderThreadImplMojoInputMessagesDisabledBrowserTest,
- WILL_LEAK(MAYBE_InputHandlerManagerDestroyedAfterCompositorThread)) {
- ASSERT_TRUE(thread_->input_handler_manager());
-
- thread_->compositor_task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&CheckRenderThreadInputHandlerManager, thread_));
-}
// Disabled under LeakSanitizer due to memory leaks.
TEST_F(RenderThreadImplBrowserTest,
diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc
index 944d93eaefd..79c8ff2cff0 100644
--- a/chromium/content/renderer/render_view_browsertest.cc
+++ b/chromium/content/renderer/render_view_browsertest.cc
@@ -440,18 +440,21 @@ class RenderViewImplBlinkSettingsTest : public RenderViewImplTest {
class RenderViewImplScaleFactorTest : public RenderViewImplBlinkSettingsTest {
protected:
void SetDeviceScaleFactor(float dsf) {
- ResizeParams params;
- params.screen_info.device_scale_factor = dsf;
- params.new_size = gfx::Size(100, 100);
- params.compositor_viewport_pixel_size = gfx::Size(200, 200);
- params.visible_viewport_size = params.new_size;
- params.auto_resize_enabled = view()->auto_resize_mode();
- params.auto_resize_sequence_number = view()->auto_resize_sequence_number();
- params.min_size_for_auto_resize = view()->min_size_for_auto_resize();
- params.max_size_for_auto_resize = view()->max_size_for_auto_resize();
- params.needs_resize_ack = false;
- params.content_source_id = view()->GetContentSourceId();
- view()->OnResize(params);
+ VisualProperties visual_properties;
+ visual_properties.screen_info.device_scale_factor = dsf;
+ visual_properties.new_size = gfx::Size(100, 100);
+ visual_properties.compositor_viewport_pixel_size = gfx::Size(200, 200);
+ visual_properties.visible_viewport_size = visual_properties.new_size;
+ visual_properties.auto_resize_enabled = view()->auto_resize_mode();
+ visual_properties.capture_sequence_number =
+ view()->capture_sequence_number();
+ visual_properties.min_size_for_auto_resize =
+ view()->min_size_for_auto_resize();
+ visual_properties.max_size_for_auto_resize =
+ view()->max_size_for_auto_resize();
+ visual_properties.local_surface_id = base::Optional<viz::LocalSurfaceId>(
+ viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
+ view()->OnSynchronizeVisualProperties(visual_properties);
ASSERT_EQ(dsf, view()->GetWebScreenInfo().device_scale_factor);
ASSERT_EQ(dsf, view()->GetOriginalScreenInfo().device_scale_factor);
}
@@ -1497,8 +1500,7 @@ TEST_F(RenderViewImplTest, ContextMenu) {
// Create a right click in the center of the iframe. (I'm hoping this will
// make this a bit more robust in case of some other formatting or other bug.)
WebMouseEvent mouse_event(WebInputEvent::kMouseDown,
- WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebInputEvent::kNoModifiers, ui::EventTimeForNow());
mouse_event.button = WebMouseEvent::Button::kRight;
mouse_event.SetPositionInWidget(250, 250);
mouse_event.SetPositionInScreen(250, 250);
@@ -1523,9 +1525,9 @@ TEST_F(RenderViewImplTest, AndroidContextMenuSelectionOrdering) {
// Create a long press in the center of the iframe. (I'm hoping this will
// make this a bit more robust in case of some other formatting or other bug.)
- WebGestureEvent gesture_event(
- WebInputEvent::kGestureLongPress, WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ WebGestureEvent gesture_event(WebInputEvent::kGestureLongPress,
+ WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
gesture_event.SetPositionInWidget(gfx::PointF(250, 250));
SendWebGestureEvent(gesture_event);
@@ -1698,8 +1700,9 @@ TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) {
"</html>");
ExecuteJavaScriptForTests("document.getElementById('test1').focus();");
frame()->SetEditableSelectionOffsets(4, 8);
- const std::vector<blink::WebImeTextSpan> empty_ime_text_span;
+ const std::vector<ui::ImeTextSpan> empty_ime_text_span;
frame()->SetCompositionFromExistingText(7, 10, empty_ime_text_span);
+ base::RunLoop().RunUntilIdle();
blink::WebInputMethodController* controller =
frame()->GetWebFrame()->GetInputMethodController();
blink::WebTextInputInfo info = controller->TextInputInfo();
@@ -1708,6 +1711,7 @@ TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) {
EXPECT_EQ(7, info.composition_start);
EXPECT_EQ(10, info.composition_end);
frame()->CollapseSelection();
+ base::RunLoop().RunUntilIdle();
info = controller->TextInputInfo();
EXPECT_EQ(8, info.selection_start);
EXPECT_EQ(8, info.selection_end);
@@ -1725,6 +1729,7 @@ TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) {
ExecuteJavaScriptForTests("document.getElementById('test1').focus();");
frame()->SetEditableSelectionOffsets(10, 10);
frame()->ExtendSelectionAndDelete(3, 4);
+ base::RunLoop().RunUntilIdle();
blink::WebInputMethodController* controller =
frame()->GetWebFrame()->GetInputMethodController();
blink::WebTextInputInfo info = controller->TextInputInfo();
@@ -1733,6 +1738,7 @@ TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) {
EXPECT_EQ(7, info.selection_end);
frame()->SetEditableSelectionOffsets(4, 8);
frame()->ExtendSelectionAndDelete(2, 5);
+ base::RunLoop().RunUntilIdle();
info = controller->TextInputInfo();
EXPECT_EQ("abuvwxyz", info.value);
EXPECT_EQ(2, info.selection_start);
@@ -1753,6 +1759,7 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingText) {
frame()->SetEditableSelectionOffsets(10, 10);
frame()->DeleteSurroundingText(3, 4);
+ base::RunLoop().RunUntilIdle();
blink::WebInputMethodController* controller =
frame()->GetWebFrame()->GetInputMethodController();
blink::WebTextInputInfo info = controller->TextInputInfo();
@@ -1762,6 +1769,7 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingText) {
frame()->SetEditableSelectionOffsets(4, 8);
frame()->DeleteSurroundingText(2, 5);
+ base::RunLoop().RunUntilIdle();
info = controller->TextInputInfo();
EXPECT_EQ("abefgouvwxyz", info.value);
EXPECT_EQ(2, info.selection_start);
@@ -1769,18 +1777,21 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingText) {
frame()->SetEditableSelectionOffsets(5, 5);
frame()->DeleteSurroundingText(10, 0);
+ base::RunLoop().RunUntilIdle();
info = controller->TextInputInfo();
EXPECT_EQ("ouvwxyz", info.value);
EXPECT_EQ(0, info.selection_start);
EXPECT_EQ(0, info.selection_end);
frame()->DeleteSurroundingText(0, 10);
+ base::RunLoop().RunUntilIdle();
info = controller->TextInputInfo();
EXPECT_EQ("", info.value);
EXPECT_EQ(0, info.selection_start);
EXPECT_EQ(0, info.selection_end);
frame()->DeleteSurroundingText(10, 10);
+ base::RunLoop().RunUntilIdle();
info = controller->TextInputInfo();
EXPECT_EQ("", info.value);
@@ -1797,6 +1808,7 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingTextInCodePoints) {
frame()->SetEditableSelectionOffsets(4, 4);
frame()->DeleteSurroundingTextInCodePoints(2, 2);
+ base::RunLoop().RunUntilIdle();
blink::WebInputMethodController* controller =
frame()->GetWebFrame()->GetInputMethodController();
blink::WebTextInputInfo info = controller->TextInputInfo();
@@ -1807,6 +1819,7 @@ TEST_F(RenderViewImplTest, OnDeleteSurroundingTextInCodePoints) {
frame()->SetEditableSelectionOffsets(1, 3);
frame()->DeleteSurroundingTextInCodePoints(1, 4);
+ base::RunLoop().RunUntilIdle();
info = controller->TextInputInfo();
EXPECT_EQ("deh", info.value);
EXPECT_EQ(0, info.selection_start);
diff --git a/chromium/content/renderer/render_view_browsertest_mac.mm b/chromium/content/renderer/render_view_browsertest_mac.mm
index 9674a212aac..19778ed3a9f 100644
--- a/chromium/content/renderer/render_view_browsertest_mac.mm
+++ b/chromium/content/renderer/render_view_browsertest_mac.mm
@@ -179,15 +179,6 @@ TEST_F(RenderViewTest, HandleIPCsInSwappedOutState) {
TextInputClientMsg_StringForRange(routing_id, Range()));
view->OnMessageReceived(
TextInputClientMsg_CharacterIndexForPoint(routing_id, Point()));
-
- // Simulate some IME related IPCs.
- using Text = base::string16;
- using ImeTextSpans = std::vector<blink::WebImeTextSpan>;
- view->OnMessageReceived(InputMsg_ImeSetComposition(
- routing_id, Text(), ImeTextSpans(), Range(), 0, 0));
- view->OnMessageReceived(
- InputMsg_ImeCommitText(routing_id, Text(), ImeTextSpans(), Range(), 0));
- view->OnMessageReceived(InputMsg_ImeFinishComposingText(routing_id, false));
}
} // namespace content
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index 7a866ded50f..4aba7a9e290 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -76,12 +76,13 @@
#include "content/renderer/history_serialization.h"
#include "content/renderer/idle_user_detector.h"
#include "content/renderer/ime_event_guard.h"
-#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/media/stream/media_stream_device_observer.h"
#include "content/renderer/media/video_capture_impl_manager.h"
+#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
+#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
#include "content/renderer/navigation_state_impl.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
@@ -194,15 +195,9 @@
#include "content/renderer/pepper/pepper_plugin_registry.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
-#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
-#endif
-
using blink::WebAXObject;
using blink::WebApplicationCacheHost;
using blink::WebApplicationCacheHostClient;
-using blink::WebColor;
using blink::WebConsoleMessage;
using blink::WebData;
using blink::WebDocument;
@@ -468,7 +463,7 @@ RenderViewImpl::RenderViewImpl(
: RenderWidget(params.view_id,
compositor_deps,
blink::kWebPopupTypeNone,
- params.initial_size.screen_info,
+ params.visual_properties.screen_info,
params.swapped_out,
params.hidden,
params.never_visible,
@@ -513,7 +508,7 @@ void RenderViewImpl::Initialize(
was_created_by_renderer_ = was_created_by_renderer;
#endif
renderer_wide_named_frame_lookup_ = params->renderer_wide_named_frame_lookup;
- display_mode_ = params->initial_size.display_mode;
+ display_mode_ = params->visual_properties.display_mode;
WebFrame* opener_frame =
RenderFrameImpl::ResolveOpener(params->opener_frame_route_id);
@@ -545,9 +540,6 @@ void RenderViewImpl::Initialize(
if (switches::IsTouchDragDropEnabled())
webview()->GetSettings()->SetTouchDragDropEnabled(true);
- webview()->GetSettings()->SetBrowserSideNavigationEnabled(
- IsBrowserSideNavigationEnabled());
-
WebSettings::SelectionStrategyType selection_strategy =
WebSettings::SelectionStrategyType::kCharacter;
const std::string selection_strategy_str =
@@ -612,9 +604,9 @@ void RenderViewImpl::Initialize(
UpdateWebViewWithDeviceScaleFactor();
OnSetRendererPrefs(params->renderer_preferences);
- OnResize(params->initial_size);
+ OnSynchronizeVisualProperties(params->visual_properties);
- idle_user_detector_.reset(new IdleUserDetector(this));
+ idle_user_detector_.reset(new IdleUserDetector());
GetContentClient()->renderer()->RenderViewCreated(this);
@@ -727,9 +719,7 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
WebRuntimeFeatures::EnableXSLT(prefs.xslt_enabled);
settings->SetXSSAuditorEnabled(prefs.xss_auditor_enabled);
settings->SetDNSPrefetchingEnabled(prefs.dns_prefetching_enabled);
- blink::WebNetworkStateNotifier::SetSaveDataEnabled(
- prefs.data_saver_enabled &&
- !base::FeatureList::IsEnabled(features::kDataSaverHoldback));
+ blink::WebNetworkStateNotifier::SetSaveDataEnabled(prefs.data_saver_enabled);
settings->SetLocalStorageEnabled(prefs.local_storage_enabled);
settings->SetSyncXHRInDocumentsEnabled(prefs.sync_xhr_in_documents_enabled);
WebRuntimeFeatures::EnableDatabase(prefs.databases_enabled);
@@ -973,6 +963,11 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->SetPictureInPictureEnabled(prefs.picture_in_picture_enabled);
+ settings->SetDataSaverHoldbackWebApi(
+ prefs.data_saver_holdback_web_api_enabled);
+ settings->SetDataSaverHoldbackMediaApi(
+ prefs.data_saver_holdback_media_api_enabled);
+
#if defined(OS_MACOSX)
settings->SetDoubleTapToZoomEnabled(true);
web_view->SetMaximumLegibleScale(prefs.default_maximum_page_scale_factor);
@@ -1047,16 +1042,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
active_url, main_frame->Top()->GetSecurityOrigin().ToString().Utf8());
}
- // Input IPC messages must not be processed if the RenderView is in
- // swapped out state.
- if (is_swapped_out_ &&
- IPC_MESSAGE_ID_CLASS(message.type()) == InputMsgStart) {
- IPC_BEGIN_MESSAGE_MAP(RenderViewImpl, message)
- IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnDiscardInputEvent)
- IPC_END_MESSAGE_MAP()
- return false;
- }
-
for (auto& observer : observers_) {
if (observer.OnMessageReceived(message))
return true;
@@ -1296,8 +1281,8 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator,
// TODO(vangelis): Can we tell if the new view will be a background page?
bool never_visible = false;
- ResizeParams initial_size = ResizeParams();
- initial_size.screen_info = screen_info_;
+ VisualProperties visual_properties = VisualProperties();
+ visual_properties.screen_info = screen_info_;
// The initial hidden state for the RenderViewImpl here has to match what the
// browser will eventually decide for the given disposition. Since we have to
@@ -1328,10 +1313,7 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator,
// the empty string.
view_params->hidden = is_background_tab;
view_params->never_visible = never_visible;
- view_params->initial_size = initial_size;
- view_params->enable_auto_resize = false;
- view_params->min_size = gfx::Size();
- view_params->max_size = gfx::Size();
+ view_params->visual_properties = visual_properties;
view_params->page_zoom_level = page_zoom_level_;
// Unretained() is safe here because our calling function will also call
@@ -1342,7 +1324,7 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator,
RenderViewImpl* view = RenderViewImpl::Create(
compositor_deps_, std::move(view_params), std::move(show_callback),
- creator->GetTaskRunner(blink::TaskType::kUnthrottled));
+ creator->GetTaskRunner(blink::TaskType::kInternalDefault));
return view->webview();
}
@@ -1351,7 +1333,7 @@ WebWidget* RenderViewImpl::CreatePopup(blink::WebLocalFrame* creator,
blink::WebPopupType popup_type) {
RenderWidget* widget = RenderWidget::CreateForPopup(
this, compositor_deps_, popup_type, screen_info_,
- creator->GetTaskRunner(blink::TaskType::kUnthrottled));
+ creator->GetTaskRunner(blink::TaskType::kInternalDefault));
if (!widget)
return nullptr;
if (screen_metrics_emulator_) {
@@ -1590,13 +1572,7 @@ void RenderViewImpl::DidFocus(blink::WebLocalFrame* calling_frame) {
// TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
// we won't have to test for user gesture anymore and we can
// move that code back to render_widget.cc
- WebFrame* main_frame = webview() ? webview()->MainFrame() : nullptr;
- bool is_processing_user_gesture =
- WebUserGestureIndicator::IsProcessingUserGesture(
- main_frame && main_frame->IsWebLocalFrame()
- ? main_frame->ToWebLocalFrame()
- : nullptr);
- if (is_processing_user_gesture &&
+ if (WebUserGestureIndicator::IsProcessingUserGesture(calling_frame) &&
!RenderThreadImpl::current()->layout_test_mode()) {
Send(new ViewHostMsg_Focus(GetRoutingID()));
@@ -1680,7 +1656,7 @@ void RenderViewImpl::DidOverscroll(
const blink::WebFloatSize& accumulatedOverscroll,
const blink::WebFloatPoint& positionInViewport,
const blink::WebFloatSize& velocityInViewport,
- const blink::WebOverscrollBehavior& behavior) {
+ const cc::OverscrollBehavior& behavior) {
RenderWidget::DidOverscroll(overscrollDelta, accumulatedOverscroll,
positionInViewport, velocityInViewport, behavior);
}
@@ -1712,10 +1688,6 @@ blink::WebWidgetClient* RenderViewImpl::WidgetClient() {
// blink::WebFrameClient -----------------------------------------------------
-void RenderViewImpl::Repaint(const gfx::Size& size) {
- OnRepaint(size);
-}
-
void RenderViewImpl::SetEditCommandForNextKeyEvent(const std::string& name,
const std::string& value) {
GetWidget()->SetEditCommandForNextKeyEvent(name, value);
@@ -1740,10 +1712,6 @@ gfx::RectF RenderViewImpl::ElementBoundsInWindow(
return gfx::RectF(bounding_box_in_window);
}
-bool RenderViewImpl::HasAddedInputHandler() const {
- return has_added_input_handler_;
-}
-
void RenderViewImpl::CheckPreferredSize() {
// We don't always want to send the change messages over IPC, only if we've
// been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
@@ -1959,8 +1927,9 @@ void RenderViewImpl::ResizeWebWidget() {
browser_controls_shrink_blink_size_);
}
-void RenderViewImpl::OnResize(const ResizeParams& params) {
- TRACE_EVENT0("renderer", "RenderViewImpl::OnResize");
+void RenderViewImpl::OnSynchronizeVisualProperties(
+ const VisualProperties& params) {
+ TRACE_EVENT0("renderer", "RenderViewImpl::OnSynchronizeVisualProperties");
if (webview()) {
// Only hide popups when the size changes. There are situations (e.g. hiding
@@ -1999,8 +1968,6 @@ void RenderViewImpl::OnResize(const ResizeParams& params) {
params.max_size_for_auto_resize);
}
} else if (auto_resize_mode_changed) {
- auto_resize_ack_callback_.Cancel();
- need_resize_ack_for_auto_resize_ = false;
webview()->DisableAutoResizeMode();
if (params.new_size.IsEmpty())
return;
@@ -2012,13 +1979,13 @@ void RenderViewImpl::OnResize(const ResizeParams& params) {
bottom_controls_height_ = params.bottom_controls_height;
if (device_scale_factor_for_testing_) {
- ResizeParams p(params);
+ VisualProperties p(params);
p.screen_info.device_scale_factor = *device_scale_factor_for_testing_;
p.compositor_viewport_pixel_size =
gfx::ScaleToCeiledSize(p.new_size, p.screen_info.device_scale_factor);
- RenderWidget::OnResize(p);
+ RenderWidget::OnSynchronizeVisualProperties(p);
} else {
- RenderWidget::OnResize(params);
+ RenderWidget::OnSynchronizeVisualProperties(params);
}
if (!params.scroll_focused_node_into_view)
@@ -2308,7 +2275,6 @@ bool RenderViewImpl::DidTapMultipleTargets(
}
void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) {
-#if BUILDFLAG(ENABLE_WEBRTC)
if (!main_render_frame_)
return;
@@ -2321,7 +2287,6 @@ void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) {
media_stream_device_observer->GetNonScreenCaptureDevices();
RenderThreadImpl::current()->video_capture_impl_manager()->SuspendDevices(
video_devices, suspend);
-#endif // BUILDFLAG(ENABLE_WEBRTC)
}
#endif // defined(OS_ANDROID)
@@ -2330,6 +2295,12 @@ unsigned RenderViewImpl::GetLocalSessionHistoryLengthForTesting() const {
}
void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) {
+ // If the main frame is remote, return immediately. Page level focus
+ // should be set from the browser process, so if needed by tests it should
+ // be properly supported.
+ if (webview()->MainFrame()->IsWebRemoteFrame())
+ return;
+
if (enable) {
if (has_focus())
return;
@@ -2346,34 +2317,45 @@ void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) {
void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
device_scale_factor_for_testing_ = factor;
- ResizeParams params;
- params.screen_info = screen_info_;
- params.screen_info.device_scale_factor = factor;
- params.new_size = size();
- params.visible_viewport_size = visible_viewport_size_;
- params.compositor_viewport_pixel_size =
+ VisualProperties visual_properties;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.screen_info.device_scale_factor = factor;
+ visual_properties.new_size = size();
+ visual_properties.visible_viewport_size = visible_viewport_size_;
+ visual_properties.compositor_viewport_pixel_size =
gfx::ScaleToCeiledSize(size(), factor);
- params.browser_controls_shrink_blink_size = false;
- params.top_controls_height = 0.f;
- params.is_fullscreen_granted = is_fullscreen_granted();
- params.display_mode = display_mode_;
- params.content_source_id = GetContentSourceId();
- OnResize(params);
+ visual_properties.browser_controls_shrink_blink_size = false;
+ visual_properties.top_controls_height = 0.f;
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted();
+ visual_properties.display_mode = display_mode_;
+ visual_properties.local_surface_id = local_surface_id_from_parent_;
+ // We are changing the device scale factor from the renderer, so allocate a
+ // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ if (compositor_)
+ compositor_->RequestNewLocalSurfaceId();
+
+ OnSynchronizeVisualProperties(visual_properties);
}
void RenderViewImpl::SetDeviceColorSpaceForTesting(
const gfx::ColorSpace& color_space) {
- ResizeParams params;
- params.screen_info = screen_info_;
- params.screen_info.color_space = color_space;
- params.new_size = size();
- params.visible_viewport_size = visible_viewport_size_;
- params.compositor_viewport_pixel_size = compositor_viewport_pixel_size_;
- params.browser_controls_shrink_blink_size = false;
- params.top_controls_height = 0.f;
- params.is_fullscreen_granted = is_fullscreen_granted();
- params.display_mode = display_mode_;
- OnResize(params);
+ VisualProperties visual_properties;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.screen_info.color_space = color_space;
+ visual_properties.new_size = size();
+ visual_properties.visible_viewport_size = visible_viewport_size_;
+ visual_properties.compositor_viewport_pixel_size =
+ compositor_viewport_pixel_size_;
+ visual_properties.browser_controls_shrink_blink_size = false;
+ visual_properties.top_controls_height = 0.f;
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted();
+ visual_properties.display_mode = display_mode_;
+ visual_properties.local_surface_id = local_surface_id_from_parent_;
+ // We are changing the device color space from the renderer, so allocate a
+ // new viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ if (compositor_)
+ compositor_->RequestNewLocalSurfaceId();
+ OnSynchronizeVisualProperties(visual_properties);
}
void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) {
@@ -2388,37 +2370,39 @@ void RenderViewImpl::UseSynchronousResizeModeForTesting(bool enable) {
void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size,
const gfx::Size& max_size) {
- ResizeParams resize_params;
- resize_params.auto_resize_enabled = true;
- resize_params.min_size_for_auto_resize = min_size;
- resize_params.max_size_for_auto_resize = max_size;
- OnResize(resize_params);
+ VisualProperties visual_properties;
+ visual_properties.auto_resize_enabled = true;
+ visual_properties.min_size_for_auto_resize = min_size;
+ 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()));
+ OnSynchronizeVisualProperties(visual_properties);
}
void RenderViewImpl::DisableAutoResizeForTesting(const gfx::Size& new_size) {
if (!auto_resize_mode_)
return;
- ResizeParams resize_params;
- resize_params.auto_resize_enabled = false;
- resize_params.screen_info = screen_info_;
- resize_params.new_size = new_size;
- resize_params.compositor_viewport_pixel_size =
+ VisualProperties visual_properties;
+ visual_properties.auto_resize_enabled = false;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.new_size = new_size;
+ visual_properties.compositor_viewport_pixel_size =
compositor_viewport_pixel_size_;
- resize_params.browser_controls_shrink_blink_size =
+ visual_properties.browser_controls_shrink_blink_size =
browser_controls_shrink_blink_size_;
- resize_params.top_controls_height = top_controls_height_;
- resize_params.visible_viewport_size = visible_viewport_size_;
- resize_params.is_fullscreen_granted = is_fullscreen_granted();
- resize_params.display_mode = display_mode_;
- resize_params.needs_resize_ack = false;
- OnResize(resize_params);
-}
-
-void RenderViewImpl::OnResolveTapDisambiguation(double timestamp_seconds,
- gfx::Point tap_viewport_offset,
- bool is_long_press) {
- webview()->ResolveTapDisambiguation(timestamp_seconds, tap_viewport_offset,
+ visual_properties.top_controls_height = top_controls_height_;
+ visual_properties.visible_viewport_size = visible_viewport_size_;
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted();
+ visual_properties.display_mode = display_mode_;
+ OnSynchronizeVisualProperties(visual_properties);
+}
+
+void RenderViewImpl::OnResolveTapDisambiguation(
+ base::TimeTicks timestamp,
+ const gfx::Point& tap_viewport_offset,
+ bool is_long_press) {
+ webview()->ResolveTapDisambiguation(timestamp, tap_viewport_offset,
is_long_press);
}
@@ -2428,20 +2412,6 @@ void RenderViewImpl::DidCommitCompositorFrame() {
observer.DidCommitCompositorFrame();
}
-void RenderViewImpl::OnDiscardInputEvent(
- const blink::WebInputEvent* input_event,
- const std::vector<const blink::WebInputEvent*>& coalesced_events,
- const ui::LatencyInfo& latency_info,
- InputEventDispatchType dispatch_type) {
- if (!input_event || dispatch_type == DISPATCH_TYPE_NON_BLOCKING) {
- return;
- }
-
- InputEventAck ack(InputEventAckSource::MAIN_THREAD, input_event->GetType(),
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- Send(new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack));
-}
-
void RenderViewImpl::HandleInputEvent(
const blink::WebCoalescedInputEvent& input_event,
const ui::LatencyInfo& latency_info,
diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h
index 6862496a25e..77f18279cdd 100644
--- a/chromium/content/renderer/render_view_impl.h
+++ b/chromium/content/renderer/render_view_impl.h
@@ -19,6 +19,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/process/process.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/timer/timer.h"
@@ -91,7 +92,7 @@ class RenderViewImplTest;
class RenderViewObserver;
class RenderViewTest;
struct FileChooserParams;
-struct ResizeParams;
+struct VisualProperties;
namespace mojom {
class CreateViewParams;
@@ -262,7 +263,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
const blink::WebFloatSize& accumulatedOverscroll,
const blink::WebFloatPoint& positionInViewport,
const blink::WebFloatSize& velocityInViewport,
- const blink::WebOverscrollBehavior& behavior) override;
+ const cc::OverscrollBehavior& behavior) override;
void HasTouchEventHandlers(bool has_handlers) override;
blink::WebScreenInfo GetScreenInfo() override;
void SetToolTipText(const blink::WebString&,
@@ -341,7 +342,6 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
blink::WebFrameWidget* GetWebFrameWidget() override;
bool ShouldDisplayScrollbars(int width, int height) const override;
bool GetContentStateImmediately() const override;
- void Repaint(const gfx::Size& size) override;
void SetEditCommandForNextKeyEvent(const std::string& name,
const std::string& value) override;
void ClearEditCommands() override;
@@ -353,7 +353,6 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
#endif
void ConvertViewportToWindowViaWidget(blink::WebRect* rect) override;
gfx::RectF ElementBoundsInWindow(const blink::WebElement& element) override;
- bool HasAddedInputHandler() const override;
bool uses_temporary_zoom_level() const { return uses_temporary_zoom_level_; }
@@ -378,7 +377,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
blink::WebWidget* GetWebWidget() const override;
void CloseForFrame() override;
void Close() override;
- void OnResize(const ResizeParams& params) override;
+ void OnSynchronizeVisualProperties(const VisualProperties& params) override;
void OnSetFocus(bool enable) override;
GURL GetURLForGraphicsContext3D() override;
void DidCommitCompositorFrame() override;
@@ -514,8 +513,8 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
void OnPluginActionAt(const gfx::Point& location,
const blink::WebPluginAction& action);
void OnMoveOrResizeStarted();
- void OnResolveTapDisambiguation(double timestamp_seconds,
- gfx::Point tap_viewport_offset,
+ void OnResolveTapDisambiguation(base::TimeTicks timestamp,
+ const gfx::Point& tap_viewport_offset,
bool is_long_press);
void OnSetActive(bool active);
void OnSetBackgroundOpaque(bool opaque);
@@ -555,10 +554,10 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
void SuspendVideoCaptureDevices(bool suspend);
#endif
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
- void UpdateFontRenderingFromRendererPrefs();
-#else
+#if defined(OS_MACOSX)
void UpdateFontRenderingFromRendererPrefs() {}
+#else
+ void UpdateFontRenderingFromRendererPrefs();
#endif
// In OOPIF-enabled modes, this tells each RenderFrame with a pending state
@@ -586,17 +585,10 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
// Platform specific theme preferences if any are updated here.
#if defined(OS_WIN)
void UpdateThemePrefs();
-#else
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
void UpdateThemePrefs() {}
#endif
- // Send the appropriate ack to be able discard this input event message.
- void OnDiscardInputEvent(
- const blink::WebInputEvent* input_event,
- const std::vector<const blink::WebInputEvent*>& coalesced_events,
- const ui::LatencyInfo& latency_info,
- InputEventDispatchType dispatch_type);
-
// ---------------------------------------------------------------------------
// ADDING NEW FUNCTIONS? Please keep private functions alphabetized and put
// it in the same order in the .cc file as it was in the header.
diff --git a/chromium/content/renderer/render_view_impl_android.cc b/chromium/content/renderer/render_view_impl_android.cc
index c77e4c6be57..2d9f48df496 100644
--- a/chromium/content/renderer/render_view_impl_android.cc
+++ b/chromium/content/renderer/render_view_impl_android.cc
@@ -5,7 +5,6 @@
#include "content/renderer/render_view_impl.h"
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
#include "cc/trees/layer_tree_host.h"
#include "content/common/view_messages.h"
#include "content/renderer/gpu/render_widget_compositor.h"
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index 5b535201d5d..f0374259db0 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -31,7 +30,6 @@
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "content/common/drag_event_source_info.h"
#include "content/common/drag_messages.h"
-#include "content/common/input_messages.h"
#include "content/common/render_frame_metadata.mojom.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/common/swapped_out_messages.h"
@@ -54,7 +52,6 @@
#include "content/renderer/gpu/queue_message_swap_promise.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/ime_event_guard.h"
-#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/input/main_thread_event_queue.h"
#include "content/renderer/input/widget_input_handler_manager.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
@@ -379,9 +376,7 @@ RenderWidget::RenderWidget(
compositor_deps_(compositor_deps),
webwidget_internal_(nullptr),
owner_delegate_(nullptr),
- next_paint_flags_(0),
auto_resize_mode_(false),
- need_resize_ack_for_auto_resize_(false),
did_show_(false),
is_hidden_(hidden),
compositor_never_visible_(never_visible),
@@ -405,7 +400,6 @@ RenderWidget::RenderWidget(
frame_swap_message_queue_(new FrameSwapMessageQueue(routing_id_)),
resizing_mode_selector_(new ResizingModeSelector()),
has_host_context_menu_location_(false),
- has_added_input_handler_(false),
has_focus_(false),
for_oopif_(false),
#if defined(OS_MACOSX)
@@ -431,7 +425,7 @@ RenderWidget::RenderWidget(
}
#if defined(USE_AURA)
RendererWindowTreeClient::CreateIfNecessary(routing_id_);
- if (features::IsMusEnabled())
+ if (features::IsMashEnabled())
RendererWindowTreeClient::Get(routing_id_)->SetVisible(!is_hidden_);
#endif
}
@@ -511,7 +505,7 @@ RenderWidget* RenderWidget::CreateForFrame(
return view->GetWidget();
}
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- frame->GetTaskRunner(blink::TaskType::kUnthrottled);
+ frame->GetTaskRunner(blink::TaskType::kInternalDefault);
scoped_refptr<RenderWidget> widget(
g_create_render_widget
? g_create_render_widget(widget_routing_id, compositor_deps,
@@ -577,17 +571,15 @@ void RenderWidget::Init(const ShowCallback& show_callback,
input_handler_ = std::make_unique<RenderWidgetInputHandler>(this, this);
- if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
- RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
+ RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
- widget_input_handler_manager_ = WidgetInputHandlerManager::Create(
- weak_ptr_factory_.GetWeakPtr(),
- render_thread_impl && compositor_
- ? render_thread_impl->compositor_task_runner()
- : nullptr,
- render_thread_impl ? render_thread_impl->GetWebMainThreadScheduler()
- : nullptr);
- }
+ widget_input_handler_manager_ = WidgetInputHandlerManager::Create(
+ weak_ptr_factory_.GetWeakPtr(),
+ render_thread_impl && compositor_
+ ? render_thread_impl->compositor_task_runner()
+ : nullptr,
+ render_thread_impl ? render_thread_impl->GetWebMainThreadScheduler()
+ : nullptr);
show_callback_ = show_callback;
@@ -620,7 +612,8 @@ void RenderWidget::SetPopupOriginAdjustmentsForEmulation(
popup_view_origin_for_emulation_ = emulator->applied_widget_rect().origin();
popup_screen_origin_for_emulation_ =
emulator->original_screen_rect().origin();
- UpdateSurfaceAndScreenInfo(local_surface_id_, compositor_viewport_pixel_size_,
+ UpdateSurfaceAndScreenInfo(local_surface_id_from_parent_,
+ compositor_viewport_pixel_size_,
emulator->original_screen_info());
}
@@ -654,39 +647,28 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidget, message)
- IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
- IPC_MESSAGE_HANDLER(InputMsg_CursorVisibilityChange,
- OnCursorVisibilityChange)
- IPC_MESSAGE_HANDLER(InputMsg_ImeSetComposition, OnImeSetComposition)
- IPC_MESSAGE_HANDLER(InputMsg_ImeCommitText, OnImeCommitText)
- IPC_MESSAGE_HANDLER(InputMsg_ImeFinishComposingText,
- OnImeFinishComposingText)
- IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost)
- IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent,
- OnSetEditCommandsForNextKeyEvent)
- IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus)
IPC_MESSAGE_HANDLER(ViewMsg_ShowContextMenu, OnShowContextMenu)
IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
- IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
+ IPC_MESSAGE_HANDLER(ViewMsg_SynchronizeVisualProperties,
+ OnSynchronizeVisualProperties)
IPC_MESSAGE_HANDLER(ViewMsg_EnableDeviceEmulation,
OnEnableDeviceEmulation)
IPC_MESSAGE_HANDLER(ViewMsg_DisableDeviceEmulation,
OnDisableDeviceEmulation)
IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
IPC_MESSAGE_HANDLER(ViewMsg_WasShown, OnWasShown)
- IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnRepaint)
IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects)
IPC_MESSAGE_HANDLER(ViewMsg_SetViewportIntersection,
OnSetViewportIntersection)
IPC_MESSAGE_HANDLER(ViewMsg_SetIsInert, OnSetIsInert)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetInheritedEffectiveTouchAction,
+ OnSetInheritedEffectiveTouchAction)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateRenderThrottlingStatus,
OnUpdateRenderThrottlingStatus)
IPC_MESSAGE_HANDLER(ViewMsg_WaitForNextFrameForTests,
OnWaitNextFrameForTests)
- IPC_MESSAGE_HANDLER(InputMsg_RequestCompositionUpdates,
- OnRequestCompositionUpdates)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver)
IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave)
@@ -694,10 +676,6 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(DragMsg_SourceEnded, OnDragSourceEnded)
IPC_MESSAGE_HANDLER(DragMsg_SourceSystemDragEnded,
OnDragSourceSystemDragEnded)
-#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(InputMsg_RequestTextInputStateUpdate,
- OnRequestTextInputStateUpdate)
-#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -737,16 +715,20 @@ bool RenderWidget::ShouldHandleImeEvents() const {
void RenderWidget::SetWindowRectSynchronously(
const gfx::Rect& new_window_rect) {
- ResizeParams params;
- params.screen_info = screen_info_;
- params.new_size = new_window_rect.size();
- params.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
+ VisualProperties visual_properties;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.new_size = new_window_rect.size();
+ visual_properties.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
new_window_rect.size(), GetWebScreenInfo().device_scale_factor);
- params.visible_viewport_size = new_window_rect.size();
- params.is_fullscreen_granted = is_fullscreen_granted_;
- params.display_mode = display_mode_;
- params.needs_resize_ack = false;
- Resize(params);
+ visual_properties.visible_viewport_size = new_window_rect.size();
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+ visual_properties.display_mode = display_mode_;
+ visual_properties.local_surface_id = local_surface_id_from_parent_;
+ // We are resizing the window from the renderer, so allocate a new
+ // viz::LocalSurfaceId to avoid surface invariants violations in tests.
+ if (compositor_)
+ compositor_->RequestNewLocalSurfaceId();
+ SynchronizeVisualProperties(visual_properties);
view_screen_rect_ = new_window_rect;
window_screen_rect_ = new_window_rect;
@@ -788,18 +770,20 @@ void RenderWidget::OnClose() {
Release();
}
-void RenderWidget::OnResize(const ResizeParams& params) {
+void RenderWidget::OnSynchronizeVisualProperties(
+ const VisualProperties& params) {
gfx::Size old_visible_viewport_size = visible_viewport_size_;
- if (resizing_mode_selector_->ShouldAbortOnResize(this, params))
+ if (resizing_mode_selector_->ShouldAbortOnResize(this, params)) {
return;
+ }
if (screen_metrics_emulator_) {
- screen_metrics_emulator_->OnResize(params);
+ screen_metrics_emulator_->OnSynchronizeVisualProperties(params);
return;
}
- Resize(params);
+ SynchronizeVisualProperties(params);
if (old_visible_viewport_size != visible_viewport_size_) {
for (auto& render_frame : render_frames_)
@@ -810,18 +794,18 @@ void RenderWidget::OnResize(const ResizeParams& params) {
void RenderWidget::OnEnableDeviceEmulation(
const blink::WebDeviceEmulationParams& params) {
if (!screen_metrics_emulator_) {
- ResizeParams resize_params;
- resize_params.screen_info = screen_info_;
- resize_params.new_size = size_;
- resize_params.compositor_viewport_pixel_size =
+ VisualProperties visual_properties;
+ visual_properties.screen_info = screen_info_;
+ visual_properties.new_size = size_;
+ visual_properties.compositor_viewport_pixel_size =
compositor_viewport_pixel_size_;
- resize_params.local_surface_id = local_surface_id_;
- resize_params.content_source_id = current_content_source_id_;
- resize_params.visible_viewport_size = visible_viewport_size_;
- resize_params.is_fullscreen_granted = is_fullscreen_granted_;
- resize_params.display_mode = display_mode_;
+ visual_properties.local_surface_id = local_surface_id_from_parent_;
+ visual_properties.visible_viewport_size = visible_viewport_size_;
+ visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
+ visual_properties.display_mode = display_mode_;
screen_metrics_emulator_.reset(new RenderWidgetScreenMetricsEmulator(
- this, params, resize_params, view_screen_rect_, window_screen_rect_));
+ this, params, visual_properties, view_screen_rect_,
+ window_screen_rect_));
screen_metrics_emulator_->Apply();
} else {
screen_metrics_emulator_->ChangeEmulationParams(params);
@@ -838,11 +822,6 @@ void RenderWidget::OnWasHidden() {
SetHidden(true);
for (auto& observer : render_frames_)
observer.WasHidden();
-
- // Ack the resize if we have to, so that the next time we're visible we get a
- // fresh ResizeParams right away; otherwise we'll start painting based on a
- // stale ResizeParams.
- DidResizeOrRepaintAck();
}
void RenderWidget::OnWasShown(bool needs_repainting,
@@ -879,25 +858,6 @@ GURL RenderWidget::GetURLForGraphicsContext3D() {
return GURL();
}
-void RenderWidget::OnHandleInputEvent(
- const blink::WebInputEvent* input_event,
- const std::vector<const blink::WebInputEvent*>& coalesced_events,
- const ui::LatencyInfo& latency_info,
- InputEventDispatchType dispatch_type) {
- if (!input_event)
- return;
-
- HandledEventCallback callback;
- if (dispatch_type == DISPATCH_TYPE_BLOCKING) {
- callback = base::Bind(
- &RenderWidget::SendInputEventAck, this, input_event->GetType(),
- ui::WebInputEventTraits::GetUniqueTouchEventId(*input_event));
- }
- input_handler_->HandleInputEvent(
- blink::WebCoalescedInputEvent(*input_event, coalesced_events),
- latency_info, std::move(callback));
-}
-
viz::FrameSinkId RenderWidget::GetFrameSinkIdAtPoint(const gfx::Point& point) {
return input_handler_->GetFrameSinkIdAtPoint(point);
}
@@ -910,19 +870,6 @@ void RenderWidget::HandleInputEvent(
std::move(callback));
}
-void RenderWidget::SendInputEventAck(
- blink::WebInputEvent::Type type,
- uint32_t touch_event_id,
- InputEventAckState ack_state,
- const ui::LatencyInfo& latency_info,
- std::unique_ptr<ui::DidOverscrollParams> overscroll_params,
- base::Optional<cc::TouchAction> touch_action) {
- InputEventAck ack(InputEventAckSource::MAIN_THREAD, type, ack_state,
- latency_info, std::move(overscroll_params), touch_event_id,
- touch_action);
- Send(new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack));
-}
-
scoped_refptr<MainThreadEventQueue> RenderWidget::GetInputEventQueue() {
return input_event_queue_;
}
@@ -984,15 +931,13 @@ void RenderWidget::RecordWheelAndTouchScrollingCount(
has_scrolled_by_touch);
}
-void RenderWidget::BeginMainFrame(double frame_time_sec) {
+void RenderWidget::BeginMainFrame(base::TimeTicks frame_time) {
if (!GetWebWidget())
return;
- if (input_event_queue_) {
- input_event_queue_->DispatchRafAlignedInput(
- ui::EventTimeStampFromSeconds(frame_time_sec));
- }
+ if (input_event_queue_)
+ input_event_queue_->DispatchRafAlignedInput(frame_time);
- GetWebWidget()->BeginFrame(frame_time_sec);
+ GetWebWidget()->BeginFrame(frame_time);
}
void RenderWidget::RequestNewLayerTreeFrameSink(
@@ -1029,7 +974,6 @@ void RenderWidget::DidCommitAndDrawCompositorFrame() {
}
void RenderWidget::DidCommitCompositorFrame() {
- DidResizeOrRepaintAck();
}
void RenderWidget::DidCompletePageScaleAnimation() {}
@@ -1132,16 +1076,8 @@ void RenderWidget::ObserveGestureEventAndResult(
scroll_result.unused_scroll_delta = unused_delta;
scroll_result.overscroll_behavior = overscroll_behavior;
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- InputHandlerManager* input_handler_manager =
- render_thread ? render_thread->input_handler_manager() : nullptr;
- if (input_handler_manager) {
- input_handler_manager->ObserveGestureEventAndResultOnMainThread(
- routing_id_, gesture_event, scroll_result);
- } else if (widget_input_handler_manager_) {
- widget_input_handler_manager_->ObserveGestureEventOnMainThread(
- gesture_event, scroll_result);
- }
+ widget_input_handler_manager_->ObserveGestureEventOnMainThread(gesture_event,
+ scroll_result);
}
void RenderWidget::OnDidHandleKeyEvent() {
@@ -1159,13 +1095,9 @@ void RenderWidget::ClearEditCommands() {
}
void RenderWidget::OnDidOverscroll(const ui::DidOverscrollParams& params) {
- if (widget_input_handler_manager_) {
- if (mojom::WidgetInputHandlerHost* host =
- widget_input_handler_manager_->GetWidgetInputHandlerHost()) {
- host->DidOverscroll(params);
- }
- } else {
- Send(new InputHostMsg_DidOverscroll(routing_id_, params));
+ if (mojom::WidgetInputHandlerHost* host =
+ widget_input_handler_manager_->GetWidgetInputHandlerHost()) {
+ host->DidOverscroll(params);
}
}
@@ -1296,7 +1228,6 @@ bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
// RenderWidgetScreenMetricsDelegate
void RenderWidget::Redraw() {
- set_next_paint_is_resize_ack();
if (compositor_)
compositor_->SetNeedsRedrawRect(gfx::Rect(size_));
}
@@ -1314,61 +1245,27 @@ gfx::Size RenderWidget::GetSizeForWebWidget() const {
return size_;
}
-void RenderWidget::Resize(const ResizeParams& params) {
- if (params.auto_resize_enabled && auto_resize_mode_ &&
- (!params.auto_resize_sequence_number ||
- auto_resize_sequence_number_ != params.auto_resize_sequence_number)) {
- DidResizeOrRepaintAck();
- return;
- }
-
- // The content_source_id that the browser sends us should never be larger than
- // |current_content_source_id_|.
- DCHECK_GE(1u << 30, current_content_source_id_ - params.content_source_id);
-
+void RenderWidget::SynchronizeVisualProperties(const VisualProperties& params) {
// Inform the rendering thread of the color space indicate the presence of HDR
// capabilities.
RenderThreadImpl* render_thread = RenderThreadImpl::current();
if (render_thread)
render_thread->SetRenderingColorSpace(params.screen_info.color_space);
- if (resizing_mode_selector_->NeverUsesSynchronousResize()) {
- // A resize ack shouldn't be requested if we have not ACK'd the previous
- // one.
- DCHECK(!compositor_ || !params.needs_resize_ack ||
- !next_paint_is_resize_ack());
- }
-
// Ignore this during shutdown.
if (!GetWebWidget())
return;
- // If the content_source_id of ResizeParams doesn't match
- // |current_content_source_id_|, then the given LocalSurfaceId was generated
- // before the navigation. Continue with the resize but don't use the
- // LocalSurfaceId until the right one comes.
- viz::LocalSurfaceId new_local_surface_id;
- if (params.local_surface_id &&
- params.content_source_id == current_content_source_id_) {
- new_local_surface_id = *params.local_surface_id;
- }
gfx::Size new_compositor_viewport_pixel_size =
params.auto_resize_enabled
? gfx::ScaleToCeiledSize(size_,
params.screen_info.device_scale_factor)
: params.compositor_viewport_pixel_size;
- UpdateSurfaceAndScreenInfo(new_local_surface_id,
- new_compositor_viewport_pixel_size,
- params.screen_info);
+ UpdateSurfaceAndScreenInfo(
+ params.local_surface_id.value_or(viz::LocalSurfaceId()),
+ new_compositor_viewport_pixel_size, params.screen_info);
+ UpdateCaptureSequenceNumber(params.capture_sequence_number);
if (compositor_) {
- // If surface synchronization is enabled, then this will use the provided
- // |local_surface_id_| to submit the next generated CompositorFrame.
- // If the ID is not valid, then the compositor will defer commits until
- // it receives a valid surface ID. This is a no-op if surface
- // synchronization is disabled.
- DCHECK(!compositor_->IsSurfaceSynchronizationEnabled() ||
- !params.needs_resize_ack || !params.local_surface_id ||
- params.local_surface_id->is_valid());
compositor_->SetBrowserControlsHeight(
params.top_controls_height, params.bottom_controls_height,
params.browser_controls_shrink_blink_size);
@@ -1401,36 +1298,8 @@ void RenderWidget::Resize(const ResizeParams& params) {
}
GetWebWidget()->ResizeVisualViewport(visual_viewport_size);
- // When resizing, we want to wait to paint before ACK'ing the resize. This
- // ensures that we only resize as fast as we can paint. We only need to
- // send an ACK if we are resized to a non-empty rect.
- if (params.new_size.IsEmpty() ||
- params.compositor_viewport_pixel_size.IsEmpty()) {
- // In this case there is no paint/composite and therefore no
- // ViewHostMsg_ResizeOrRepaint_ACK to send the resize ack with. We'd need to
- // send the ack through a fake ViewHostMsg_ResizeOrRepaint_ACK or a
- // different message.
- DCHECK(!params.needs_resize_ack);
- }
-
- // Send the Resize_ACK flag once we paint again if requested.
- if (params.needs_resize_ack)
- set_next_paint_is_resize_ack();
-
if (fullscreen_change)
DidToggleFullscreen();
-
- // If a resize ack is requested and it isn't set-up, then no more resizes will
- // come in and in general things will go wrong.
- DCHECK(!params.needs_resize_ack || next_paint_is_resize_ack());
-
- // If this resize was initiated before navigation and surface synchronization
- // is on, it is not expected to be acked.
- if (compositor_ && compositor_->IsSurfaceSynchronizationEnabled() &&
- params.needs_resize_ack && !local_surface_id_.is_valid()) {
- DCHECK_NE(params.content_source_id, current_content_source_id_);
- reset_next_paint_is_resize_ack();
- }
}
void RenderWidget::SetScreenMetricsEmulationParameters(
@@ -1463,16 +1332,8 @@ blink::WebLayerTreeView* RenderWidget::InitializeLayerTreeView() {
compositor_->Initialize(std::move(layer_tree_host),
std::move(animation_host));
- // We can get into this state if surface synchronization is on and the last
- // resize was initiated before navigation, in which case we don't have to ack
- // it.
- if (compositor_->IsSurfaceSynchronizationEnabled() && !auto_resize_mode_ &&
- next_paint_is_resize_ack() && !local_surface_id_.is_valid()) {
- reset_next_paint_is_resize_ack();
- }
-
- UpdateSurfaceAndScreenInfo(local_surface_id_, compositor_viewport_pixel_size_,
- screen_info_);
+ UpdateSurfaceAndScreenInfo(local_surface_id_from_parent_,
+ compositor_viewport_pixel_size_, screen_info_);
compositor_->SetRasterColorSpace(
screen_info_.color_space.GetRasterColorSpace());
compositor_->SetContentSourceId(current_content_source_id_);
@@ -1493,16 +1354,6 @@ blink::WebLayerTreeView* RenderWidget::InitializeLayerTreeView() {
input_event_queue_ = new MainThreadEventQueue(
this, render_thread->GetWebMainThreadScheduler()->InputTaskRunner(),
render_thread->GetWebMainThreadScheduler(), should_generate_frame_sink);
-
- InputHandlerManager* input_handler_manager =
- render_thread->input_handler_manager();
- if (input_handler_manager) {
- input_handler_manager->AddInputHandler(
- routing_id_, compositor()->GetInputHandler(), input_event_queue_,
- weak_ptr_factory_.GetWeakPtr(),
- compositor_deps_->IsScrollAnimatorEnabled());
- has_added_input_handler_ = true;
- }
}
UpdateURLForCompositorUkm();
@@ -1827,13 +1678,9 @@ void RenderWidget::OnImeSetComposition(
// If we failed to set the composition text, then we need to let the browser
// process to cancel the input method's ongoing composition session, to make
// sure we are in a consistent state.
- if (widget_input_handler_manager_) {
- if (mojom::WidgetInputHandlerHost* host =
- widget_input_handler_manager_->GetWidgetInputHandlerHost()) {
- host->ImeCancelComposition();
- }
- } else {
- Send(new InputHostMsg_ImeCancelComposition(routing_id()));
+ if (mojom::WidgetInputHandlerHost* host =
+ widget_input_handler_manager_->GetWidgetInputHandlerHost()) {
+ host->ImeCancelComposition();
}
}
UpdateCompositionInfo(false /* not an immediate request */);
@@ -1893,7 +1740,7 @@ void RenderWidget::OnImeFinishComposingText(bool keep_selection) {
}
void RenderWidget::UpdateSurfaceAndScreenInfo(
- viz::LocalSurfaceId new_local_surface_id,
+ const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Size& new_compositor_viewport_pixel_size,
const ScreenInfo& new_screen_info) {
bool orientation_changed =
@@ -1903,7 +1750,7 @@ void RenderWidget::UpdateSurfaceAndScreenInfo(
screen_info_.device_scale_factor != new_screen_info.device_scale_factor;
ScreenInfo previous_original_screen_info = GetOriginalScreenInfo();
- local_surface_id_ = new_local_surface_id;
+ local_surface_id_from_parent_ = new_local_surface_id;
compositor_viewport_pixel_size_ = new_compositor_viewport_pixel_size;
screen_info_ = new_screen_info;
@@ -1913,7 +1760,8 @@ void RenderWidget::UpdateSurfaceAndScreenInfo(
// DSF used by the compositor during device emulation!
compositor_->SetViewportSizeAndScale(
compositor_viewport_pixel_size_,
- GetOriginalScreenInfo().device_scale_factor, local_surface_id_);
+ GetOriginalScreenInfo().device_scale_factor,
+ local_surface_id_from_parent_);
}
if (orientation_changed)
@@ -1932,20 +1780,17 @@ void RenderWidget::UpdateSurfaceAndScreenInfo(
UpdateWebViewWithDeviceScaleFactor();
}
-void RenderWidget::OnRepaint(gfx::Size size_to_paint) {
- // During shutdown we can just ignore this message.
- if (!GetWebWidget())
+void RenderWidget::UpdateCaptureSequenceNumber(
+ uint32_t capture_sequence_number) {
+ if (capture_sequence_number == last_capture_sequence_number_)
return;
+ last_capture_sequence_number_ = capture_sequence_number;
- // Even if the browser provides an empty damage rect, it's still expecting to
- // receive a repaint ack so just damage the entire widget bounds.
- if (size_to_paint.IsEmpty()) {
- size_to_paint = size_;
- }
-
- set_next_paint_is_repaint_ack();
- if (compositor_)
- compositor_->SetNeedsRedrawRect(gfx::Rect(size_to_paint));
+ // Notify observers of the new capture sequence number.
+ for (auto& observer : render_frame_proxies_)
+ observer.UpdateCaptureSequenceNumber(capture_sequence_number);
+ for (auto& observer : browser_plugins_)
+ observer.UpdateCaptureSequenceNumber(capture_sequence_number);
}
void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
@@ -1990,6 +1835,14 @@ void RenderWidget::OnSetIsInert(bool inert) {
}
}
+void RenderWidget::OnSetInheritedEffectiveTouchAction(
+ cc::TouchAction touch_action) {
+ if (auto* frame_widget = GetFrameWidget()) {
+ DCHECK_EQ(popup_type_, WebPopupType::kWebPopupTypeNone);
+ frame_widget->SetInheritedEffectiveTouchAction(touch_action);
+ }
+}
+
void RenderWidget::OnUpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled) {
if (auto* frame_widget = GetFrameWidget()) {
@@ -2122,15 +1975,10 @@ void RenderWidget::UpdateCompositionInfo(bool immediate_request) {
}
composition_character_bounds_ = character_bounds;
composition_range_ = range;
- if (widget_input_handler_manager_) {
- if (mojom::WidgetInputHandlerHost* host =
- widget_input_handler_manager_->GetWidgetInputHandlerHost()) {
- host->ImeCompositionRangeChanged(composition_range_,
- composition_character_bounds_);
- }
- } else {
- Send(new InputHostMsg_ImeCompositionRangeChanged(
- routing_id(), composition_range_, composition_character_bounds_));
+ if (mojom::WidgetInputHandlerHost* host =
+ widget_input_handler_manager_->GetWidgetInputHandlerHost()) {
+ host->ImeCompositionRangeChanged(composition_range_,
+ composition_character_bounds_);
}
}
@@ -2195,7 +2043,7 @@ void RenderWidget::SetHidden(bool hidden) {
is_hidden_ = hidden;
#if defined(USE_AURA)
- if (features::IsMusEnabled())
+ if (features::IsMashEnabled())
RendererWindowTreeClient::Get(routing_id_)->SetVisible(!hidden);
#endif
@@ -2224,24 +2072,6 @@ void RenderWidget::DidToggleFullscreen() {
}
}
-bool RenderWidget::next_paint_is_resize_ack() const {
- return ViewHostMsg_ResizeOrRepaint_ACK_Flags::is_resize_ack(
- next_paint_flags_);
-}
-
-void RenderWidget::set_next_paint_is_resize_ack() {
- next_paint_flags_ |= ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK;
-}
-
-void RenderWidget::set_next_paint_is_repaint_ack() {
- next_paint_flags_ |= ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_REPAINT_ACK;
-}
-
-void RenderWidget::reset_next_paint_is_resize_ack() {
- DCHECK(next_paint_is_resize_ack());
- next_paint_flags_ ^= ViewHostMsg_ResizeOrRepaint_ACK_Flags::IS_RESIZE_ACK;
-}
-
void RenderWidget::OnImeEventGuardStart(ImeEventGuard* guard) {
if (!ime_event_guard_)
ime_event_guard_ = guard;
@@ -2347,29 +2177,13 @@ void RenderWidget::DidAutoResize(const gfx::Size& new_size) {
// |size_| from |compositor_viewport_pixel_size_|. Also note that the
// calculation of |new_compositor_viewport_pixel_size| does not appear to
// take into account device emulation.
- ++auto_resize_sequence_number_;
+ if (compositor_)
+ compositor_->RequestNewLocalSurfaceId();
gfx::Size new_compositor_viewport_pixel_size =
gfx::ScaleToCeiledSize(size_, GetWebScreenInfo().device_scale_factor);
- UpdateSurfaceAndScreenInfo(viz::LocalSurfaceId(),
+ UpdateSurfaceAndScreenInfo(local_surface_id_from_parent_,
new_compositor_viewport_pixel_size,
screen_info_);
-
- if (!resizing_mode_selector_->is_synchronous_mode()) {
- need_resize_ack_for_auto_resize_ = true;
- // If surface synchronization is off, then ResizeAcks go to the browser in
- // response to a DidReceiveCompositorFrame. With surface synchronization
- // on, that notification will not arrive here because the compositor is
- // deferring commits and thus submission of CompositorFrames.
- if (!size_.IsEmpty() && compositor_ &&
- compositor_->IsSurfaceSynchronizationEnabled() &&
- !auto_resize_ack_callback_.callback()) {
- auto_resize_ack_callback_.Reset(
- base::BindOnce(&RenderWidget::DidResizeOrRepaintAck,
- weak_ptr_factory_.GetWeakPtr()));
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, auto_resize_ack_callback_.callback());
- }
- }
}
}
@@ -2508,7 +2322,7 @@ void RenderWidget::DidOverscroll(
const blink::WebFloatSize& accumulatedOverscroll,
const blink::WebFloatPoint& position,
const blink::WebFloatSize& velocity,
- const blink::WebOverscrollBehavior& behavior) {
+ const cc::OverscrollBehavior& behavior) {
#if defined(OS_MACOSX)
// On OSX the user can disable the elastic overscroll effect. If that's the
// case, don't forward the overscroll notification.
@@ -2557,11 +2371,7 @@ void RenderWidget::SetTouchAction(cc::TouchAction touch_action) {
if (!input_handler_->ProcessTouchAction(touch_action))
return;
- if (widget_input_handler_manager_) {
- widget_input_handler_manager_->ProcessTouchAction(touch_action);
- } else {
- Send(new InputHostMsg_SetTouchAction(routing_id_, touch_action));
- }
+ widget_input_handler_manager_->ProcessTouchAction(touch_action);
}
void RenderWidget::RegisterRenderFrameProxy(RenderFrameProxy* proxy) {
@@ -2652,17 +2462,6 @@ void RenderWidget::DidNavigate() {
if (!compositor_)
return;
compositor_->SetContentSourceId(current_content_source_id_);
-
- UpdateSurfaceAndScreenInfo(viz::LocalSurfaceId(),
- compositor_viewport_pixel_size_, screen_info_);
-
- // If surface synchronization is on, navigation implicitly acks any resize
- // that has happened so far so we can get the next ResizeParams containing the
- // LocalSurfaceId that should be used after navigation.
- if (compositor_->IsSurfaceSynchronizationEnabled() && !auto_resize_mode_ &&
- next_paint_is_resize_ack()) {
- reset_next_paint_is_resize_ack();
- }
}
blink::WebWidget* RenderWidget::GetWebWidget() const {
@@ -2691,18 +2490,15 @@ void RenderWidget::SetWidgetBinding(mojom::WidgetRequest request) {
widget_binding_.Bind(std::move(request));
}
-void RenderWidget::DidResizeOrRepaintAck() {
- if (!next_paint_flags_ && !need_resize_ack_for_auto_resize_)
- return;
-
- ViewHostMsg_ResizeOrRepaint_ACK_Params params;
- params.view_size = size_;
- params.flags = next_paint_flags_;
- params.sequence_number = auto_resize_sequence_number_;
+void RenderWidget::SetMouseCapture(bool capture) {
+ if (mojom::WidgetInputHandlerHost* host =
+ widget_input_handler_manager_->GetWidgetInputHandlerHost()) {
+ host->SetMouseCapture(capture);
+ }
+}
- Send(new ViewHostMsg_ResizeOrRepaint_ACK(routing_id_, params));
- next_paint_flags_ = 0;
- need_resize_ack_for_auto_resize_ = false;
+bool RenderWidget::IsSurfaceSynchronizationEnabled() const {
+ return compositor_ && compositor_->IsSurfaceSynchronizationEnabled();
}
void RenderWidget::UpdateURLForCompositorUkm() {
diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h
index 57d685870ba..480c020d340 100644
--- a/chromium/content/renderer/render_widget.h
+++ b/chromium/content/renderer/render_widget.h
@@ -21,6 +21,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/input/overscroll_behavior.h"
@@ -47,7 +48,7 @@
#include "ipc/ipc_sender.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "ppapi/buildflags/buildflags.h"
-#include "third_party/blink/public/platform/web_display_mode.h"
+#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_referrer_policy.h"
@@ -117,7 +118,7 @@ class ResizingModeSelector;
class TextInputClientObserver;
class WidgetInputHandlerManager;
struct ContextMenuParams;
-struct ResizeParams;
+struct VisualProperties;
// RenderWidget provides a communication bridge between a WebWidget and
// a RenderWidgetHost, the latter of which lives in a different process.
@@ -256,7 +257,7 @@ class CONTENT_EXPORT RenderWidget
float top_controls_delta) override;
void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel,
bool has_scrolled_by_touch) override;
- void BeginMainFrame(double frame_time_sec) override;
+ void BeginMainFrame(base::TimeTicks frame_time) override;
void RequestNewLayerTreeFrameSink(
const LayerTreeFrameSinkCallback& callback) override;
void DidCommitAndDrawCompositorFrame() override;
@@ -289,7 +290,8 @@ class CONTENT_EXPORT RenderWidget
// RenderWidgetScreenMetricsEmulatorDelegate
void Redraw() override;
- void Resize(const ResizeParams& resize_params) override;
+ void SynchronizeVisualProperties(
+ const VisualProperties& resize_params) override;
void SetScreenMetricsEmulationParameters(
bool enabled,
const blink::WebDeviceEmulationParams& params) override;
@@ -319,7 +321,7 @@ class CONTENT_EXPORT RenderWidget
const blink::WebFloatSize& accumulatedOverscroll,
const blink::WebFloatPoint& position,
const blink::WebFloatSize& velocity,
- const blink::WebOverscrollBehavior& behavior) override;
+ const cc::OverscrollBehavior& behavior) override;
void ShowVirtualKeyboardOnElementFocus() override;
void ConvertViewportToWindow(blink::WebRect* rect) override;
void ConvertWindowToViewport(blink::WebFloatRect* rect) override;
@@ -417,10 +419,6 @@ class CONTENT_EXPORT RenderWidget
bool auto_resize_mode() const { return auto_resize_mode_; }
- uint64_t auto_resize_sequence_number() const {
- return auto_resize_sequence_number_;
- }
-
const gfx::Size& min_size_for_auto_resize() const {
return min_size_for_auto_resize_;
}
@@ -428,6 +426,11 @@ class CONTENT_EXPORT RenderWidget
const gfx::Size& max_size_for_auto_resize() const {
return max_size_for_auto_resize_;
}
+
+ uint32_t capture_sequence_number() const {
+ return last_capture_sequence_number_;
+ }
+
// MainThreadEventQueueClient overrides.
// Requests a BeginMainFrame callback from the compositor.
@@ -464,8 +467,8 @@ class CONTENT_EXPORT RenderWidget
void OnRequestTextInputStateUpdate();
// Called by the browser process to update the cursor and composition
- // information by sending InputHostMsg_ImeCompositionRangeChanged. If
- // |immediate_request| is true, an IPC is sent back with current state.
+ // information by sending WidgetInputHandlerHost::ImeCompositionRangeChanged.
+ // If |immediate_request| is true, an IPC is sent back with current state.
// When |monitor_update| is true, then RenderWidget will send the updates
// in each compositor frame when there are changes. Outside of compositor
// frame updates, a change in text selection might also lead to an update for
@@ -474,13 +477,15 @@ class CONTENT_EXPORT RenderWidget
bool monitor_updates);
void SetWidgetBinding(mojom::WidgetRequest request);
+ void SetMouseCapture(bool capture);
+
// Time-To-First-Active-Paint(TTFAP) type
enum {
TTFAP_AFTER_PURGED,
TTFAP_5MIN_AFTER_BACKGROUNDED,
};
- void DidResizeOrRepaintAck();
+ bool IsSurfaceSynchronizationEnabled() const;
base::WeakPtr<RenderWidget> AsWeakPtr();
@@ -558,7 +563,7 @@ class CONTENT_EXPORT RenderWidget
InputEventDispatchType dispatch_type);
void OnClose();
void OnCreatingNewAck();
- virtual void OnResize(const ResizeParams& params);
+ virtual void OnSynchronizeVisualProperties(const VisualProperties& params);
void OnEnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
void OnDisableDeviceEmulation();
virtual void OnWasHidden();
@@ -571,7 +576,6 @@ class CONTENT_EXPORT RenderWidget
virtual void OnShowContextMenu(ui::MenuSourceType source_type,
const gfx::Point& location);
- void OnRepaint(gfx::Size size_to_paint);
void OnSetTextDirection(blink::WebTextDirection direction);
void OnGetFPS();
void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
@@ -580,6 +584,7 @@ class CONTENT_EXPORT RenderWidget
void OnSetViewportIntersection(const gfx::Rect& viewport_intersection,
const gfx::Rect& compositor_visible_rect);
void OnSetIsInert(bool);
+ void OnSetInheritedEffectiveTouchAction(cc::TouchAction touch_action);
void OnUpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled);
// Real data that is dragged is not included at DragEnter time.
@@ -620,11 +625,6 @@ class CONTENT_EXPORT RenderWidget
void DidToggleFullscreen();
- bool next_paint_is_resize_ack() const;
- void set_next_paint_is_resize_ack();
- void set_next_paint_is_repaint_ack();
- void reset_next_paint_is_resize_ack();
-
// Returns a rect that the compositor needs to raster. For a main frame this
// is always the entire viewprot, but for out-of-process iframes this can be
// constrained to limit overdraw.
@@ -722,31 +722,16 @@ class CONTENT_EXPORT RenderWidget
// The size of the visible viewport in pixels.
gfx::Size visible_viewport_size_;
- // Flags for the next ViewHostMsg_ResizeOrRepaint_ACK message.
- int next_paint_flags_;
-
// Whether the WebWidget is in auto resize mode, which is used for example
// by extension popups.
bool auto_resize_mode_;
- // True if we need to send a ViewHsotMsg_ResizeOrRepaint_ACK message to notify
- // the browser about an already-completed auto-resize.
- bool need_resize_ack_for_auto_resize_;
-
- // The sequence number used for the auto-resize request.
- uint64_t auto_resize_sequence_number_ = 0;
-
// The minimum size to use for auto-resize.
gfx::Size min_size_for_auto_resize_;
// The maximum size to use for auto-resize.
gfx::Size max_size_for_auto_resize_;
- // A pending ResizeOrRepaintAck callback in response to an auto-resize
- // initiated by Blink. If auto-resize mode is canceled with an in-flight
- // Ack, then the Ack will be canceled.
- base::CancelableOnceClosure auto_resize_ack_callback_;
-
// Set to true if we should ignore RenderWidget::Show calls.
bool did_show_;
@@ -866,9 +851,7 @@ class CONTENT_EXPORT RenderWidget
// Wraps the |webwidget_| as a MouseLockDispatcher::LockTarget interface.
std::unique_ptr<MouseLockDispatcher::LockTarget> webwidget_mouse_lock_target_;
- bool has_added_input_handler_;
-
- viz::LocalSurfaceId local_surface_id_;
+ viz::LocalSurfaceId local_surface_id_from_parent_;
private:
// TODO(ekaramad): This method should not be confused with its RenderView
@@ -893,10 +876,12 @@ class CONTENT_EXPORT RenderWidget
int32_t* routing_id);
void UpdateSurfaceAndScreenInfo(
- viz::LocalSurfaceId new_local_surface_id,
+ const viz::LocalSurfaceId& new_local_surface_id,
const gfx::Size& new_compositor_viewport_pixel_size,
const ScreenInfo& new_screen_info);
+ void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
+
// A variant of Send but is fatal if it fails. The browser may
// be waiting for this IPC Message and if the send fails the browser will
// be left in a state waiting for something that never comes. And if it
@@ -988,11 +973,12 @@ class CONTENT_EXPORT RenderWidget
gfx::Rect compositor_visible_rect_;
- // Cache whether or not we have touch handlers, to reduce IPCs sent.
// Different consumers in the browser process makes different assumptions, so
// must always send the first IPC regardless of value.
base::Optional<bool> has_touch_handlers_;
+ uint32_t last_capture_sequence_number_ = 0u;
+
base::WeakPtrFactory<RenderWidget> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidget);
diff --git a/chromium/content/renderer/render_widget_browsertest.cc b/chromium/content/renderer/render_widget_browsertest.cc
index 713c6e6793b..f1732625658 100644
--- a/chromium/content/renderer/render_widget_browsertest.cc
+++ b/chromium/content/renderer/render_widget_browsertest.cc
@@ -5,7 +5,7 @@
#include "base/strings/utf_string_conversions.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "content/common/resize_params.h"
+#include "content/common/visual_properties.h"
#include "content/public/renderer/render_frame_visitor.h"
#include "content/public/test/render_view_test.h"
#include "content/renderer/render_frame_proxy.h"
@@ -26,18 +26,14 @@ class RenderWidgetTest : public RenderViewTest {
return static_cast<RenderViewImpl*>(view_)->GetWidget();
}
- void OnResize(const ResizeParams& params) {
- widget()->OnResize(params);
+ void OnSynchronizeVisualProperties(const VisualProperties& params) {
+ widget()->OnSynchronizeVisualProperties(params);
}
void GetCompositionRange(gfx::Range* range) {
widget()->GetCompositionRange(range);
}
- bool next_paint_is_resize_ack() {
- return widget()->next_paint_is_resize_ack();
- }
-
blink::WebInputMethodController* GetInputMethodController() {
return widget()->GetInputMethodController();
}
@@ -53,64 +49,52 @@ class RenderWidgetTest : public RenderViewTest {
void SetFocus(bool focused) { widget()->OnSetFocus(focused); }
};
-TEST_F(RenderWidgetTest, OnResize) {
+TEST_F(RenderWidgetTest, OnSynchronizeVisualProperties) {
widget()->DidNavigate();
// The initial bounds is empty, so setting it to the same thing should do
// nothing.
- ResizeParams resize_params;
- resize_params.screen_info = ScreenInfo();
- resize_params.new_size = gfx::Size();
- resize_params.compositor_viewport_pixel_size = gfx::Size();
- resize_params.top_controls_height = 0.f;
- resize_params.browser_controls_shrink_blink_size = false;
- resize_params.is_fullscreen_granted = false;
- resize_params.needs_resize_ack = false;
- resize_params.content_source_id = 0u;
- OnResize(resize_params);
- EXPECT_EQ(resize_params.needs_resize_ack, next_paint_is_resize_ack());
+ VisualProperties visual_properties;
+ visual_properties.screen_info = ScreenInfo();
+ visual_properties.new_size = gfx::Size();
+ visual_properties.compositor_viewport_pixel_size = gfx::Size();
+ visual_properties.top_controls_height = 0.f;
+ visual_properties.browser_controls_shrink_blink_size = false;
+ visual_properties.is_fullscreen_granted = false;
+ OnSynchronizeVisualProperties(visual_properties);
// Setting empty physical backing size should not send the ack.
- resize_params.new_size = gfx::Size(10, 10);
- OnResize(resize_params);
- EXPECT_EQ(resize_params.needs_resize_ack, next_paint_is_resize_ack());
+ visual_properties.new_size = gfx::Size(10, 10);
+ OnSynchronizeVisualProperties(visual_properties);
// Setting the bounds to a "real" rect should send the ack.
render_thread_->sink().ClearMessages();
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator;
gfx::Size size(100, 100);
- resize_params.local_surface_id = local_surface_id_allocator.GenerateId();
- resize_params.new_size = size;
- resize_params.compositor_viewport_pixel_size = size;
- resize_params.content_source_id = 1u;
- resize_params.needs_resize_ack = true;
- OnResize(resize_params);
- EXPECT_EQ(resize_params.needs_resize_ack, next_paint_is_resize_ack());
+ visual_properties.local_surface_id = local_surface_id_allocator.GenerateId();
+ visual_properties.new_size = size;
+ visual_properties.compositor_viewport_pixel_size = size;
+ OnSynchronizeVisualProperties(visual_properties);
// Clear the flag.
widget()->DidCommitCompositorFrame();
widget()->DidCommitAndDrawCompositorFrame();
// Setting the same size again should not send the ack.
- resize_params.needs_resize_ack = false;
- OnResize(resize_params);
- EXPECT_EQ(resize_params.needs_resize_ack, next_paint_is_resize_ack());
+ OnSynchronizeVisualProperties(visual_properties);
// Resetting the rect to empty should not send the ack.
- resize_params.new_size = gfx::Size();
- resize_params.compositor_viewport_pixel_size = gfx::Size();
- resize_params.local_surface_id = base::nullopt;
- OnResize(resize_params);
- EXPECT_EQ(resize_params.needs_resize_ack, next_paint_is_resize_ack());
+ visual_properties.new_size = gfx::Size();
+ visual_properties.compositor_viewport_pixel_size = gfx::Size();
+ visual_properties.local_surface_id = base::nullopt;
+ OnSynchronizeVisualProperties(visual_properties);
// Changing the screen info should not send the ack.
- resize_params.screen_info.orientation_angle = 90;
- OnResize(resize_params);
- EXPECT_EQ(resize_params.needs_resize_ack, next_paint_is_resize_ack());
+ visual_properties.screen_info.orientation_angle = 90;
+ OnSynchronizeVisualProperties(visual_properties);
- resize_params.screen_info.orientation_type =
+ visual_properties.screen_info.orientation_type =
SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY;
- OnResize(resize_params);
- EXPECT_EQ(resize_params.needs_resize_ack, next_paint_is_resize_ack());
+ OnSynchronizeVisualProperties(visual_properties);
}
class RenderWidgetInitialSizeTest : public RenderWidgetTest {
@@ -120,13 +104,13 @@ class RenderWidgetInitialSizeTest : public RenderWidgetTest {
}
protected:
- std::unique_ptr<ResizeParams> InitialSizeParams() override {
- std::unique_ptr<ResizeParams> initial_size_params(new ResizeParams());
- initial_size_params->new_size = initial_size_;
- initial_size_params->compositor_viewport_pixel_size = initial_size_;
- initial_size_params->needs_resize_ack = true;
- initial_size_params->local_surface_id = local_surface_id_;
- return initial_size_params;
+ std::unique_ptr<VisualProperties> InitialVisualProperties() override {
+ std::unique_ptr<VisualProperties> initial_visual_properties(
+ new VisualProperties());
+ initial_visual_properties->new_size = initial_size_;
+ initial_visual_properties->compositor_viewport_pixel_size = initial_size_;
+ initial_visual_properties->local_surface_id = local_surface_id_;
+ return initial_visual_properties;
}
gfx::Size initial_size_;
@@ -134,12 +118,6 @@ class RenderWidgetInitialSizeTest : public RenderWidgetTest {
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
};
-TEST_F(RenderWidgetInitialSizeTest, InitialSize) {
- EXPECT_EQ(initial_size_, widget()->size());
- EXPECT_EQ(initial_size_, gfx::Size(widget()->GetWebWidget()->Size()));
- EXPECT_TRUE(next_paint_is_resize_ack());
-}
-
TEST_F(RenderWidgetTest, HitTestAPI) {
LoadHTML(
"<body style='padding: 0px; margin: 0px'>"
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
index 2a9d9a6fde7..1e908be6d0f 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
@@ -22,7 +21,6 @@
#include "third_party/blink/public/platform/web_canvas.h"
#include "third_party/blink/public/platform/web_cursor_info.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
-#include "third_party/blink/public/platform/web_layer.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/web/web_widget.h"
@@ -98,7 +96,7 @@ WebMouseEvent WebMouseEventFromGestureEvent(const WebGestureEvent& gesture) {
WebMouseEvent mouse(type,
gesture.GetModifiers() | WebInputEvent::kLeftButtonDown,
- gesture.TimeStampSeconds());
+ gesture.TimeStamp());
mouse.button = WebMouseEvent::Button::kLeft;
mouse.click_count = (mouse.GetType() == WebInputEvent::kMouseDown ||
mouse.GetType() == WebInputEvent::kMouseUp);
@@ -178,7 +176,7 @@ class PepperWidget : public WebWidget {
case WebInputEvent::kGestureTap: {
WebMouseEvent mouse(WebInputEvent::kMouseMove,
gesture_event->GetModifiers(),
- gesture_event->TimeStampSeconds());
+ gesture_event->TimeStamp());
mouse.SetPositionInWidget(gesture_event->PositionInWidget().x,
gesture_event->PositionInWidget().y);
mouse.SetPositionInScreen(gesture_event->PositionInScreen().x,
@@ -333,7 +331,8 @@ void RenderWidgetFullscreenPepper::PepperDidChangeCursor(
DidChangeCursor(cursor);
}
-void RenderWidgetFullscreenPepper::SetLayer(blink::WebLayer* layer) {
+// TODO(danakj): These should be a scoped_refptr<cc::Layer>.
+void RenderWidgetFullscreenPepper::SetLayer(cc::Layer* layer) {
layer_ = layer;
if (!layer_) {
if (compositor_)
@@ -343,8 +342,8 @@ void RenderWidgetFullscreenPepper::SetLayer(blink::WebLayer* layer) {
if (!compositor())
InitializeLayerTreeView();
UpdateLayerBounds();
- layer_->SetDrawsContent(true);
- compositor_->SetRootLayer(*layer_);
+ layer_->SetIsDrawable(true);
+ compositor_->SetRootLayer(layer_);
}
bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) {
@@ -379,8 +378,9 @@ void RenderWidgetFullscreenPepper::Close() {
RenderWidget::Close();
}
-void RenderWidgetFullscreenPepper::OnResize(const ResizeParams& params) {
- RenderWidget::OnResize(params);
+void RenderWidgetFullscreenPepper::OnSynchronizeVisualProperties(
+ const VisualProperties& visual_properties) {
+ RenderWidget::OnSynchronizeVisualProperties(visual_properties);
UpdateLayerBounds();
}
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.h b/chromium/content/renderer/render_widget_fullscreen_pepper.h
index 585270d4ccd..0faccb2ee7c 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.h
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.h
@@ -16,8 +16,8 @@
#include "third_party/blink/public/web/web_widget.h"
#include "url/gurl.h"
-namespace blink {
-class WebLayer;
+namespace cc {
+class Layer;
}
namespace content {
@@ -45,7 +45,7 @@ class RenderWidgetFullscreenPepper : public RenderWidget,
void ScrollRect(int dx, int dy, const blink::WebRect& rect) override;
void Destroy() override;
void PepperDidChangeCursor(const blink::WebCursorInfo& cursor) override;
- void SetLayer(blink::WebLayer* layer) override;
+ void SetLayer(cc::Layer* layer) override;
// RenderWidget overrides.
bool OnMessageReceived(const IPC::Message& msg) override;
@@ -69,7 +69,8 @@ class RenderWidgetFullscreenPepper : public RenderWidget,
// RenderWidget API.
void DidInitiatePaint() override;
void Close() override;
- void OnResize(const ResizeParams& params) override;
+ void OnSynchronizeVisualProperties(
+ const VisualProperties& visual_properties) override;
// RenderWidget overrides.
GURL GetURLForGraphicsContext3D() override;
@@ -83,7 +84,7 @@ class RenderWidgetFullscreenPepper : public RenderWidget,
// The plugin instance this widget wraps.
PepperPluginInstanceImpl* plugin_;
- blink::WebLayer* layer_;
+ cc::Layer* layer_;
std::unique_ptr<MouseLockDispatcher> mouse_lock_dispatcher_;
diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc
index 0dffdc9eb7d..8a4a85433a9 100644
--- a/chromium/content/renderer/render_widget_unittest.cc
+++ b/chromium/content/renderer/render_widget_unittest.cc
@@ -11,18 +11,18 @@
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "content/common/input/input_handler.mojom.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
-#include "content/common/resize_params.h"
#include "content/common/view_messages.h"
+#include "content/common/visual_properties.h"
#include "content/public/common/content_features.h"
#include "content/public/test/mock_render_thread.h"
#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h"
+#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/input/widget_input_handler_manager.h"
#include "content/test/fake_compositor_dependencies.h"
#include "content/test/mock_render_process.h"
@@ -66,7 +66,7 @@ enum {
PASSIVE_LISTENER_UMA_ENUM_CANCELABLE,
PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED,
PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING,
- PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS,
+ PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS_DEPRECATED,
PASSIVE_LISTENER_UMA_ENUM_COUNT
};
@@ -91,6 +91,8 @@ class MockWidgetInputHandlerHost : public mojom::WidgetInputHandlerHost {
MOCK_METHOD2(ImeCompositionRangeChanged,
void(const gfx::Range&, const std::vector<gfx::Rect>&));
+ MOCK_METHOD1(SetMouseCapture, void(bool));
+
private:
mojo::Binding<mojom::WidgetInputHandlerHost> binding_;
@@ -175,12 +177,10 @@ class InteractiveRenderWidget : public RenderWidget {
return mock_input_handler_host_.get();
}
- const viz::LocalSurfaceId& local_surface_id() const {
- return local_surface_id_;
+ const viz::LocalSurfaceId& local_surface_id_from_parent() const {
+ return local_surface_id_from_parent_;
}
- void SetAutoResizeMode(bool enable) { auto_resize_mode_ = enable; }
-
protected:
~InteractiveRenderWidget() override { webwidget_internal_ = nullptr; }
@@ -195,7 +195,7 @@ class InteractiveRenderWidget : public RenderWidget {
event.PositionInWidget(),
blink::WebFloatSize(event.data.scroll_update.velocity_x,
event.data.scroll_update.velocity_y),
- blink::WebOverscrollBehavior());
+ cc::OverscrollBehavior());
return true;
}
@@ -223,7 +223,6 @@ int InteractiveRenderWidget::next_routing_id_ = 0;
class RenderWidgetUnittest : public testing::Test {
public:
RenderWidgetUnittest() {
- mojo_feature_list_.InitAndEnableFeature(features::kMojoInputMessages);
widget_ = new InteractiveRenderWidget(&compositor_deps_);
// RenderWidget::Init does an AddRef that's balanced by a browser-initiated
// Close IPC. That Close will never happen in this test, so do a Release
@@ -242,7 +241,6 @@ class RenderWidgetUnittest : public testing::Test {
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
- base::test::ScopedFeatureList mojo_feature_list_;
private:
MockRenderProcess render_process_;
@@ -261,10 +259,9 @@ TEST_F(RenderWidgetUnittest, EventOverscroll) {
.WillRepeatedly(
::testing::Return(blink::WebInputEventResult::kNotHandled));
- blink::WebGestureEvent scroll(
- blink::WebInputEvent::kGestureScrollUpdate,
- blink::WebInputEvent::kNoModifiers,
- ui::EventTimeStampToSeconds(ui::EventTimeForNow()));
+ blink::WebGestureEvent scroll(blink::WebInputEvent::kGestureScrollUpdate,
+ blink::WebInputEvent::kNoModifiers,
+ ui::EventTimeForNow());
scroll.SetPositionInWidget(gfx::PointF(-10, 0));
scroll.data.scroll_update.delta_y = 10;
MockHandledEventCallback handled_event;
@@ -299,8 +296,7 @@ TEST_F(RenderWidgetUnittest, FlingOverscroll) {
// be sent as a separate IPC.
widget()->DidOverscroll(blink::WebFloatSize(10, 5), blink::WebFloatSize(5, 5),
blink::WebFloatPoint(1, 1),
- blink::WebFloatSize(10, 5),
- blink::WebOverscrollBehavior());
+ blink::WebFloatSize(10, 5), cc::OverscrollBehavior());
base::RunLoop().RunUntilIdle();
}
@@ -310,12 +306,12 @@ TEST_F(RenderWidgetUnittest, RenderWidgetInputEventUmaMetrics) {
touch.touch_start_or_first_touch_move = true;
EXPECT_CALL(*widget()->mock_webwidget(), HandleInputEvent(_))
- .Times(7)
+ .Times(5)
.WillRepeatedly(
::testing::Return(blink::WebInputEventResult::kNotHandled));
EXPECT_CALL(*widget()->mock_webwidget(), DispatchBufferedTouchEvents())
- .Times(7)
+ .Times(5)
.WillRepeatedly(
::testing::Return(blink::WebInputEventResult::kNotHandled));
@@ -351,24 +347,6 @@ TEST_F(RenderWidgetUnittest, RenderWidgetInputEventUmaMetrics) {
EVENT_LISTENER_RESULT_HISTOGRAM,
PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING, 2);
- touch.dispatch_type = blink::WebInputEvent::DispatchType::
- kListenersForcedNonBlockingDueToMainThreadResponsiveness;
- widget()->SendInputEvent(touch, HandledEventCallback());
- histogram_tester().ExpectBucketCount(
- EVENT_LISTENER_RESULT_HISTOGRAM,
- PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS,
- 1);
-
- touch.MovePoint(0, 10, 10);
- touch.touch_start_or_first_touch_move = true;
- touch.dispatch_type = blink::WebInputEvent::DispatchType::
- kListenersForcedNonBlockingDueToMainThreadResponsiveness;
- widget()->SendInputEvent(touch, HandledEventCallback());
- histogram_tester().ExpectBucketCount(
- EVENT_LISTENER_RESULT_HISTOGRAM,
- PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS,
- 2);
-
EXPECT_CALL(*widget()->mock_webwidget(), HandleInputEvent(_))
.WillOnce(::testing::Return(blink::WebInputEventResult::kNotHandled));
EXPECT_CALL(*widget()->mock_webwidget(), DispatchBufferedTouchEvents())
@@ -391,73 +369,29 @@ TEST_F(RenderWidgetUnittest, RenderWidgetInputEventUmaMetrics) {
PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED, 1);
}
-// Tests that if a RenderWidget goes invisible while performing a resize, the
-// resize is acked immediately.
-TEST_F(RenderWidgetUnittest, AckResizeOnHide) {
- // The widget should start off visible.
- ASSERT_FALSE(widget()->is_hidden());
-
- // Send a ResizeParams that needs to be acked.
- constexpr gfx::Size size(200, 200);
- ResizeParams resize_params;
- resize_params.screen_info = ScreenInfo();
- resize_params.new_size = size;
- resize_params.compositor_viewport_pixel_size = size;
- resize_params.visible_viewport_size = size;
- resize_params.content_source_id = widget()->GetContentSourceId();
- resize_params.needs_resize_ack = true;
- widget()->OnMessageReceived(
- ViewMsg_Resize(widget()->routing_id(), resize_params));
-
- // Hide the widget. Make sure the resize is acked.
- widget()->sink()->ClearMessages();
- widget()->OnMessageReceived(ViewMsg_WasHidden(widget()->routing_id()));
- EXPECT_TRUE(widget()->sink()->GetUniqueMessageMatching(
- ViewHostMsg_ResizeOrRepaint_ACK::ID));
-}
-
-// Tests that if a RenderWidget auto-resizes multiple times and receives an IPC
-// with a LocalSurfaceId, it will drop that LocalSurfaceId if it does not
-// correspond to the latest auto-resize request.
-TEST_F(RenderWidgetUnittest, SurfaceSynchronizationAutoResizeThrottling) {
- if (!features::IsSurfaceSynchronizationEnabled())
- return;
-
- constexpr gfx::Size auto_size(100, 100);
+// Tests that if a RenderWidget is auto-resized, it requests a new
+// viz::LocalSurfaceId to be allocated on the impl thread.
+TEST_F(RenderWidgetUnittest, AutoResizeAllocatedLocalSurfaceId) {
widget()->InitializeLayerTreeView();
- widget()->SetAutoResizeMode(true);
- // Issue an auto-resize.
- widget()->DidAutoResize(auto_size);
- widget()->sink()->ClearMessages();
- base::RunLoop().RunUntilIdle();
- const IPC::Message* message = widget()->sink()->GetUniqueMessageMatching(
- ViewHostMsg_ResizeOrRepaint_ACK::ID);
- ASSERT_TRUE(message);
- ViewHostMsg_ResizeOrRepaint_ACK::Param params;
- ViewHostMsg_ResizeOrRepaint_ACK::Read(message, &params);
- EXPECT_EQ(auto_size, std::get<0>(params).view_size);
- uint64_t auto_resize_sequence_number = std::get<0>(params).sequence_number;
- EXPECT_GT(auto_resize_sequence_number, 0lu);
-
- // Issue another auto-resize but keep it in-flight.
- constexpr gfx::Size auto_size2(200, 200);
- widget()->DidAutoResize(auto_size2);
-
- // Send the LocalSurfaceId for the first Auto-Resize.
viz::ParentLocalSurfaceIdAllocator allocator;
- content::ResizeParams resize_params;
- resize_params.auto_resize_enabled = true;
- resize_params.auto_resize_sequence_number = auto_resize_sequence_number;
- resize_params.min_size_for_auto_resize = auto_size;
- resize_params.max_size_for_auto_resize = auto_size2;
- resize_params.local_surface_id = allocator.GenerateId();
- widget()->OnMessageReceived(
- ViewMsg_Resize(widget()->routing_id(), resize_params));
-
- // The LocalSurfaceId should not take because there's another in-flight auto-
- // resize operation.
- EXPECT_FALSE(widget()->local_surface_id().is_valid());
+
+ // Enable auto-resize.
+ content::VisualProperties visual_properties;
+ visual_properties.auto_resize_enabled = true;
+ visual_properties.min_size_for_auto_resize = gfx::Size(100, 100);
+ visual_properties.max_size_for_auto_resize = gfx::Size(200, 200);
+ visual_properties.local_surface_id = allocator.GetCurrentLocalSurfaceId();
+ widget()->SynchronizeVisualProperties(visual_properties);
+ EXPECT_EQ(allocator.GetCurrentLocalSurfaceId(),
+ widget()->local_surface_id_from_parent());
+ EXPECT_FALSE(widget()->compositor()->HasNewLocalSurfaceIdRequest());
+
+ constexpr gfx::Size size(200, 200);
+ widget()->DidAutoResize(size);
+ EXPECT_EQ(allocator.GetCurrentLocalSurfaceId(),
+ widget()->local_surface_id_from_parent());
+ EXPECT_TRUE(widget()->compositor()->HasNewLocalSurfaceIdRequest());
}
class PopupRenderWidget : public RenderWidget {
@@ -505,7 +439,6 @@ int PopupRenderWidget::routing_id_ = 1;
class RenderWidgetPopupUnittest : public testing::Test {
public:
RenderWidgetPopupUnittest() {
- mojo_feature_list_.InitAndEnableFeature(features::kMojoInputMessages);
widget_ = new PopupRenderWidget(&compositor_deps_);
// RenderWidget::Init does an AddRef that's balanced by a browser-initiated
// Close IPC. That Close will never happen in this test, so do a Release
@@ -520,7 +453,6 @@ class RenderWidgetPopupUnittest : public testing::Test {
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
- base::test::ScopedFeatureList mojo_feature_list_;
private:
MockRenderProcess render_process_;
@@ -551,15 +483,15 @@ TEST_F(RenderWidgetPopupUnittest, EmulatingPopupRect) {
gfx::Rect parent_window_rect = gfx::Rect(0, 0, 800, 600);
- ResizeParams resize_params;
- resize_params.new_size = parent_window_rect.size();
+ VisualProperties visual_properties;
+ visual_properties.new_size = parent_window_rect.size();
scoped_refptr<PopupRenderWidget> parent_widget(
new PopupRenderWidget(&compositor_deps_));
parent_widget->Release(); // Balance Init().
RenderWidgetScreenMetricsEmulator emulator(
- parent_widget.get(), emulation_params, resize_params, parent_window_rect,
- parent_window_rect);
+ parent_widget.get(), emulation_params, visual_properties,
+ parent_window_rect, parent_window_rect);
emulator.Apply();
widget()->SetPopupOriginAdjustmentsForEmulation(&emulator);
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc
index c2c62bae127..4205c92765a 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.cc
+++ b/chromium/content/renderer/renderer_blink_platform_impl.cc
@@ -33,9 +33,7 @@
#include "content/child/thread_safe_sender.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu_stream_constants.h"
-#include "content/common/origin_trials/trial_policy_impl.h"
#include "content/common/render_message_filter.mojom.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
@@ -44,7 +42,6 @@
#include "content/public/renderer/media_stream_utils.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/blob_storage/webblobregistry_impl.h"
-#include "content/renderer/cache_storage/webserviceworkercachestorage_impl.h"
#include "content/renderer/device_sensors/device_motion_event_pump.h"
#include "content/renderer/device_sensors/device_orientation_event_pump.h"
#include "content/renderer/dom_storage/local_storage_cached_areas.h"
@@ -69,13 +66,10 @@
#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
#include "content/renderer/media_recorder/media_recorder_handler.h"
#include "content/renderer/mojo/blink_interface_provider_impl.h"
-#include "content/renderer/notifications/notification_dispatcher.h"
-#include "content/renderer/notifications/notification_manager.h"
#include "content/renderer/push_messaging/push_provider.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/storage_util.h"
#include "content/renderer/web_database_observer_impl.h"
-#include "content/renderer/webfileutilities_impl.h"
#include "content/renderer/webgraphicscontext3d_provider_impl.h"
#include "content/renderer/webpublicsuffixlist_impl.h"
#include "content/renderer/worker_thread_registry.h"
@@ -94,6 +88,7 @@
#include "ppapi/buildflags/buildflags.h"
#include "services/device/public/cpp/generic_sensor/motion_data.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
@@ -117,12 +112,12 @@
#include "third_party/blink/public/platform/web_rtc_certificate_generator.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/public/platform/web_socket_handshake_throttle.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/gurl.h"
@@ -155,11 +150,9 @@
#define WebScrollbarBehaviorImpl blink::WebScrollbarBehavior
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/rtc_certificate_generator.h"
#include "content/renderer/media/webrtc/webrtc_uma_histograms.h"
-#endif
using blink::Platform;
using blink::WebAudioDevice;
@@ -203,8 +196,7 @@ media::AudioParameters GetAudioHardwareParams() {
return media::AudioParameters::UnavailableDeviceParams();
return AudioDeviceFactory::GetOutputDeviceInfo(render_frame->GetRoutingID(),
- 0, std::string(),
- web_frame->GetSecurityOrigin())
+ 0, std::string())
.output_params();
}
@@ -234,21 +226,6 @@ gpu::ContextType ToGpuContextType(blink::Platform::ContextType type) {
//------------------------------------------------------------------------------
-class RendererBlinkPlatformImpl::FileUtilities : public WebFileUtilitiesImpl {
- public:
- explicit FileUtilities(
- scoped_refptr<mojom::ThreadSafeFileUtilitiesHostPtr> host)
- : file_utilities_host_(std::move(host)) {}
- bool GetFileInfo(const WebString& path, WebFileInfo& result) override;
-
- private:
- mojom::FileUtilitiesHost& GetFileUtilitiesHost() {
- return **file_utilities_host_;
- }
-
- scoped_refptr<mojom::ThreadSafeFileUtilitiesHostPtr> file_utilities_host_;
-};
-
#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_FUCHSIA)
class RendererBlinkPlatformImpl::SandboxSupport
: public blink::WebSandboxSupport {
@@ -309,14 +286,10 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
->Clone();
sync_message_filter_ = RenderThreadImpl::current()->sync_message_filter();
thread_safe_sender_ = RenderThreadImpl::current()->thread_safe_sender();
- shared_bitmap_manager_ =
- RenderThreadImpl::current()->shared_bitmap_manager();
blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get()));
web_idb_factory_.reset(new WebIDBFactoryImpl(
sync_message_filter_,
RenderThreadImpl::current()->GetIOTaskRunner().get()));
- notification_dispatcher_ =
- RenderThreadImpl::current()->notification_dispatcher();
} else {
service_manager::mojom::ConnectorRequest request;
connector_ = service_manager::Connector::Create(&request);
@@ -329,15 +302,11 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
GetInterfaceProvider()->GetInterface(
mojo::MakeRequest(&web_database_host_info_));
-
- GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&file_utilities_host_info_));
}
RendererBlinkPlatformImpl::~RendererBlinkPlatformImpl() {
WebFileSystemImpl::DeleteThreadSpecificInstance();
main_thread_scheduler_->SetTopLevelBlameContext(nullptr);
- shared_bitmap_manager_ = nullptr;
}
void RendererBlinkPlatformImpl::Shutdown() {
@@ -367,9 +336,9 @@ RendererBlinkPlatformImpl::CreateDefaultURLLoaderFactory() {
std::unique_ptr<blink::WebURLLoaderFactory>
RendererBlinkPlatformImpl::WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) {
- return std::make_unique<content::WebURLLoaderFactoryImpl>(
+ return std::make_unique<WebURLLoaderFactoryImpl>(
RenderThreadImpl::current()->resource_dispatcher()->GetWeakPtr(),
- base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
network::mojom::URLLoaderFactoryPtrInfo(
std::move(url_loader_factory_handle),
network::mojom::URLLoaderFactory::Version_)));
@@ -427,27 +396,6 @@ blink::BlameContext* RendererBlinkPlatformImpl::GetTopLevelBlameContext() {
return &top_level_blame_context_;
}
-blink::WebClipboard* RendererBlinkPlatformImpl::Clipboard() {
- blink::WebClipboard* clipboard =
- GetContentClient()->renderer()->OverrideWebClipboard();
- if (clipboard)
- return clipboard;
-
- return BlinkPlatformImpl::Clipboard();
-}
-
-blink::WebFileUtilities* RendererBlinkPlatformImpl::GetFileUtilities() {
- if (!file_utilities_) {
- file_utilities_.reset(
- new FileUtilities(mojom::ThreadSafeFileUtilitiesHostPtr::Create(
- std::move(file_utilities_host_info_),
- base::CreateSequencedTaskRunnerWithTraits(
- {base::WithBaseSyncPrimitives()}))));
- file_utilities_->set_sandbox_enabled(sandboxEnabled());
- }
- return file_utilities_.get();
-}
-
blink::WebSandboxSupport* RendererBlinkPlatformImpl::GetSandboxSupport() {
#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_FUCHSIA)
// These platforms do not require sandbox support.
@@ -497,6 +445,14 @@ RendererBlinkPlatformImpl::PrescientNetworking() {
return GetContentClient()->renderer()->GetPrescientNetworking();
}
+blink::WebString RendererBlinkPlatformImpl::UserAgent() {
+ auto* render_thread = RenderThreadImpl::current();
+ // RenderThreadImpl is null in some tests.
+ if (!render_thread)
+ return WebString();
+ return render_thread->GetUserAgent();
+}
+
void RendererBlinkPlatformImpl::CacheMetadata(const blink::WebURL& url,
base::Time response_time,
const char* data,
@@ -595,9 +551,12 @@ void RendererBlinkPlatformImpl::CloneSessionStorageNamespace(
const std::string& source_namespace,
const std::string& destination_namespace) {
if (!local_storage_cached_areas_) {
+ // Some browser tests don't have a RenderThreadImpl.
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ if (!render_thread)
+ return;
local_storage_cached_areas_.reset(new LocalStorageCachedAreas(
- RenderThreadImpl::current()->GetStoragePartitionService(),
- main_thread_scheduler_));
+ render_thread->GetStoragePartitionService(), main_thread_scheduler_));
}
local_storage_cached_areas_->CloneNamespace(source_namespace,
destination_namespace);
@@ -611,16 +570,6 @@ WebIDBFactory* RendererBlinkPlatformImpl::IdbFactory() {
//------------------------------------------------------------------------------
-std::unique_ptr<blink::WebServiceWorkerCacheStorage>
-RendererBlinkPlatformImpl::CreateCacheStorage(
- service_manager::InterfaceProvider* mojo_provider) {
- // Requires the Interface Provider from ExecutionContext, because it can be
- // different of RendererBlinkPlatformImpl::GetInterfaceProvider()
- return std::make_unique<WebServiceWorkerCacheStorageImpl>(mojo_provider);
-}
-
-//------------------------------------------------------------------------------
-
WebFileSystem* RendererBlinkPlatformImpl::FileSystem() {
return WebFileSystemImpl::ThreadSpecificInstance(default_task_runner_);
}
@@ -633,22 +582,6 @@ WebString RendererBlinkPlatformImpl::FileSystemCreateOriginIdentifier(
//------------------------------------------------------------------------------
-bool RendererBlinkPlatformImpl::FileUtilities::GetFileInfo(
- const WebString& path,
- WebFileInfo& web_file_info) {
- base::Optional<base::File::Info> file_info;
- if (!GetFileUtilitiesHost().GetFileInfo(blink::WebStringToFilePath(path),
- &file_info) ||
- !file_info) {
- return false;
- }
- FileInfoToWebFileInfo(file_info.value(), &web_file_info);
- web_file_info.platform_path = path;
- return true;
-}
-
-//------------------------------------------------------------------------------
-
#if defined(OS_MACOSX)
bool RendererBlinkPlatformImpl::SandboxSupport::LoadFont(CTFontRef src_font,
@@ -793,14 +726,7 @@ std::unique_ptr<WebAudioDevice> RendererBlinkPlatformImpl::CreateAudioDevice(
unsigned channels,
const blink::WebAudioLatencyHint& latency_hint,
WebAudioDevice::RenderCallback* callback,
- const blink::WebString& input_device_id,
- const blink::WebSecurityOrigin& security_origin) {
- // Use a mock for testing.
- std::unique_ptr<blink::WebAudioDevice> mock_device =
- GetContentClient()->renderer()->OverrideCreateAudioDevice(latency_hint);
- if (mock_device)
- return mock_device;
-
+ const blink::WebString& input_device_id) {
// The |channels| does not exactly identify the channel layout of the
// device. The switch statement below assigns a best guess to the channel
// layout based on number of channels.
@@ -814,9 +740,8 @@ std::unique_ptr<WebAudioDevice> RendererBlinkPlatformImpl::CreateAudioDevice(
session_id = 0;
}
- return RendererWebAudioDeviceImpl::Create(
- layout, channels, latency_hint, callback, session_id,
- static_cast<url::Origin>(security_origin));
+ return RendererWebAudioDeviceImpl::Create(layout, channels, latency_hint,
+ callback, session_id);
}
bool RendererBlinkPlatformImpl::DecodeAudioFileData(
@@ -904,12 +829,8 @@ void RendererBlinkPlatformImpl::SampleGamepads(device::Gamepads& gamepads) {
std::unique_ptr<WebMediaRecorderHandler>
RendererBlinkPlatformImpl::CreateMediaRecorderHandler(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-#if BUILDFLAG(ENABLE_WEBRTC)
return std::make_unique<content::MediaRecorderHandler>(
std::move(task_runner));
-#else
- return nullptr;
-#endif
}
//------------------------------------------------------------------------------
@@ -923,25 +844,17 @@ RendererBlinkPlatformImpl::CreateRTCPeerConnectionHandler(
if (!render_thread)
return nullptr;
-#if BUILDFLAG(ENABLE_WEBRTC)
PeerConnectionDependencyFactory* rtc_dependency_factory =
render_thread->GetPeerConnectionDependencyFactory();
return rtc_dependency_factory->CreateRTCPeerConnectionHandler(client,
task_runner);
-#else
- return nullptr;
-#endif // BUILDFLAG(ENABLE_WEBRTC)
}
//------------------------------------------------------------------------------
std::unique_ptr<blink::WebRTCCertificateGenerator>
RendererBlinkPlatformImpl::CreateRTCCertificateGenerator() {
-#if BUILDFLAG(ENABLE_WEBRTC)
return std::make_unique<RTCCertificateGenerator>();
-#else
- return nullptr;
-#endif // BUILDFLAG(ENABLE_WEBRTC)
}
//------------------------------------------------------------------------------
@@ -970,12 +883,8 @@ RendererBlinkPlatformImpl::CreateCanvasCaptureHandler(
const WebSize& size,
double frame_rate,
WebMediaStreamTrack* track) {
-#if BUILDFLAG(ENABLE_WEBRTC)
return CanvasCaptureHandler::CreateCanvasCaptureHandler(
size, frame_rate, RenderThread::Get()->GetIOTaskRunner(), track);
-#else
- return nullptr;
-#endif // BUILDFLAG(ENABLE_WEBRTC)
}
//------------------------------------------------------------------------------
@@ -984,7 +893,6 @@ void RendererBlinkPlatformImpl::CreateHTMLVideoElementCapturer(
WebMediaStream* web_media_stream,
WebMediaPlayer* web_media_player,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-#if BUILDFLAG(ENABLE_WEBRTC)
DCHECK(web_media_stream);
DCHECK(web_media_player);
AddVideoTrackToMediaStream(
@@ -993,13 +901,11 @@ void RendererBlinkPlatformImpl::CreateHTMLVideoElementCapturer(
task_runner),
false, // is_remote
web_media_stream);
-#endif
}
void RendererBlinkPlatformImpl::CreateHTMLAudioElementCapturer(
WebMediaStream* web_media_stream,
WebMediaPlayer* web_media_player) {
-#if BUILDFLAG(ENABLE_WEBRTC)
DCHECK(web_media_stream);
DCHECK(web_media_player);
@@ -1028,25 +934,18 @@ void RendererBlinkPlatformImpl::CreateHTMLAudioElementCapturer(
media_stream_source->ConnectToTrack(web_media_stream_track);
web_media_stream->AddTrack(web_media_stream_track);
-#endif
}
//------------------------------------------------------------------------------
std::unique_ptr<WebImageCaptureFrameGrabber>
RendererBlinkPlatformImpl::CreateImageCaptureFrameGrabber() {
-#if BUILDFLAG(ENABLE_WEBRTC)
return std::make_unique<ImageCaptureFrameGrabber>();
-#else
- return nullptr;
-#endif // BUILDFLAG(ENABLE_WEBRTC)
}
void RendererBlinkPlatformImpl::UpdateWebRTCAPICount(
blink::WebRTCAPIName api_name) {
-#if BUILDFLAG(ENABLE_WEBRTC)
UpdateWebRTCMethodCount(api_name);
-#endif
}
//------------------------------------------------------------------------------
@@ -1086,7 +985,6 @@ std::unique_ptr<blink::WebGraphicsContext3DProvider>
RendererBlinkPlatformImpl::CreateOffscreenGraphicsContext3DProvider(
const blink::Platform::ContextAttributes& web_attributes,
const blink::WebURL& top_document_web_url,
- blink::WebGraphicsContext3DProvider* share_provider,
blink::Platform::GraphicsInfo* gl_info) {
DCHECK(gl_info);
if (!RenderThreadImpl::current()) {
@@ -1105,22 +1003,6 @@ RendererBlinkPlatformImpl::CreateOffscreenGraphicsContext3DProvider(
}
Collect3DContextInformation(gl_info, gpu_channel_host->gpu_info());
- content::WebGraphicsContext3DProviderImpl* share_provider_impl =
- static_cast<content::WebGraphicsContext3DProviderImpl*>(share_provider);
- ui::ContextProviderCommandBuffer* share_context = nullptr;
-
- // WebGL contexts must fail creation if the share group is lost.
- if (share_provider_impl) {
- auto* gl = share_provider_impl->ContextGL();
- if (gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
- std::string error_message(
- "OffscreenContext Creation failed, Shared context is lost");
- gl_info->error_message = WebString::FromUTF8(error_message);
- return nullptr;
- }
- share_context = share_provider_impl->context_provider();
- }
-
bool is_software_rendering = gpu_channel_host->gpu_info().software_rendering;
// This is an offscreen context. Generally it won't use the default
@@ -1157,7 +1039,7 @@ RendererBlinkPlatformImpl::CreateOffscreenGraphicsContext3DProvider(
kGpuStreamIdDefault, kGpuStreamPriorityDefault,
gpu::kNullSurfaceHandle, GURL(top_document_web_url),
automatic_flushes, support_locking, web_attributes.support_grcontext,
- gpu::SharedMemoryLimits(), attributes, share_context,
+ gpu::SharedMemoryLimits(), attributes,
ui::command_buffer_metrics::OFFSCREEN_CONTEXT_FOR_WEBGL));
return std::make_unique<WebGraphicsContext3DProviderImpl>(
std::move(provider), is_software_rendering);
@@ -1200,24 +1082,9 @@ RendererBlinkPlatformImpl::GetGpuMemoryBufferManager() {
//------------------------------------------------------------------------------
-std::unique_ptr<viz::SharedBitmap>
-RendererBlinkPlatformImpl::AllocateSharedBitmap(const blink::WebSize& size,
- viz::ResourceFormat format) {
- return shared_bitmap_manager_->AllocateSharedBitmap(
- gfx::Size(size.width, size.height), format);
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebCompositorSupport* RendererBlinkPlatformImpl::CompositorSupport() {
- return &compositor_support_;
-}
-
-//------------------------------------------------------------------------------
-
blink::WebString RendererBlinkPlatformImpl::ConvertIDNToUnicode(
const blink::WebString& host) {
- return WebString::FromUTF16(url_formatter::IDNToUnicode(host.Utf8()));
+ return WebString::FromUTF16(url_formatter::IDNToUnicode(host.Ascii()));
}
//------------------------------------------------------------------------------
@@ -1374,26 +1241,6 @@ blink::WebPushProvider* RendererBlinkPlatformImpl::PushProvider() {
//------------------------------------------------------------------------------
-std::unique_ptr<blink::WebTrialTokenValidator>
-RendererBlinkPlatformImpl::CreateTrialTokenValidator() {
- return std::make_unique<WebTrialTokenValidatorImpl>(
- TrialPolicyImpl::CreateValidatorForPolicy());
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebNotificationManager*
-RendererBlinkPlatformImpl::GetWebNotificationManager() {
- if (!thread_safe_sender_.get() || !notification_dispatcher_.get())
- return nullptr;
-
- return NotificationManager::ThreadSpecificInstance(
- thread_safe_sender_.get(),
- notification_dispatcher_.get());
-}
-
-//------------------------------------------------------------------------------
-
void RendererBlinkPlatformImpl::DidStartWorkerThread() {
WorkerThreadRegistry::Instance()->DidStartCurrentWorkerThread();
}
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h
index 611b6b70f3c..ecb5ce6d6aa 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.h
+++ b/chromium/content/renderer/renderer_blink_platform_impl.h
@@ -9,26 +9,25 @@
#include <stdint.h>
#include <memory>
+#include <string>
#include "base/compiler_specific.h"
#include "base/containers/id_map.h"
#include "base/macros.h"
+#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "cc/blink/web_compositor_support_impl.h"
-#include "components/viz/client/client_shared_bitmap_manager.h"
#include "content/child/blink_platform_impl.h"
#include "content/common/content_export.h"
-#include "content/common/file_utilities.mojom.h"
#include "content/common/possibly_associated_interface_ptr.h"
-#include "content/renderer/origin_trials/web_trial_token_validator_impl.h"
#include "content/renderer/top_level_blame_context.h"
#include "content/renderer/webpublicsuffixlist_impl.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
-#include "third_party/blink/public/platform/modules/screen_orientation/web_screen_orientation_type.h"
#include "third_party/blink/public/platform/modules/webdatabase/web_database.mojom.h"
namespace IPC {
@@ -46,7 +45,6 @@ class WebMediaPlayer;
class WebMediaRecorderHandler;
class WebMediaStream;
class WebSecurityOrigin;
-class WebServiceWorkerCacheStorage;
} // namespace blink
namespace device {
@@ -59,7 +57,6 @@ namespace content {
class BlinkInterfaceProviderImpl;
class ChildURLLoaderFactoryBundle;
class LocalStorageCachedAreas;
-class NotificationDispatcher;
class PlatformEventObserverBase;
class ThreadSafeSender;
class WebDatabaseObserverImpl;
@@ -77,8 +74,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
plugin_refresh_allowed_ = plugin_refresh_allowed;
}
// Platform methods:
- blink::WebClipboard* Clipboard() override;
- blink::WebFileUtilities* GetFileUtilities() override;
blink::WebSandboxSupport* GetSandboxSupport() override;
blink::WebCookieJar* CookieJar() override;
blink::WebThemeEngine* ThemeEngine() override;
@@ -89,6 +84,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
size_t length) override;
bool IsLinkVisited(unsigned long long linkHash) override;
blink::WebPrescientNetworking* PrescientNetworking() override;
+ blink::WebString UserAgent() override;
void CacheMetadata(const blink::WebURL&,
base::Time,
const char*,
@@ -131,8 +127,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::WebPublicSuffixList* PublicSuffixList() override;
blink::WebScrollbarBehavior* ScrollbarBehavior() override;
blink::WebIDBFactory* IdbFactory() override;
- std::unique_ptr<blink::WebServiceWorkerCacheStorage> CreateCacheStorage(
- service_manager::InterfaceProvider* mojo_provider) override;
blink::WebFileSystem* FileSystem() override;
blink::WebString FileSystemCreateOriginIdentifier(
const blink::WebSecurityOrigin& origin) override;
@@ -150,8 +144,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
unsigned channels,
const blink::WebAudioLatencyHint& latency_hint,
blink::WebAudioDevice::RenderCallback* callback,
- const blink::WebString& input_device_id,
- const blink::WebSecurityOrigin& security_origin) override;
+ const blink::WebString& input_device_id) override;
bool DecodeAudioFileData(blink::WebAudioBus* destination_bus,
const char* audio_file_data,
@@ -192,15 +185,10 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
CreateOffscreenGraphicsContext3DProvider(
const blink::Platform::ContextAttributes& attributes,
const blink::WebURL& top_document_web_url,
- blink::WebGraphicsContext3DProvider* share_provider,
blink::Platform::GraphicsInfo* gl_info) override;
std::unique_ptr<blink::WebGraphicsContext3DProvider>
CreateSharedOffscreenGraphicsContext3DProvider() override;
gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
- std::unique_ptr<viz::SharedBitmap> AllocateSharedBitmap(
- const blink::WebSize& size,
- viz::ResourceFormat format) override;
- blink::WebCompositorSupport* CompositorSupport() override;
blink::WebString ConvertIDNToUnicode(const blink::WebString& host) override;
service_manager::Connector* GetConnector() override;
blink::InterfaceProvider* GetInterfaceProvider() override;
@@ -213,9 +201,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
const blink::WebString& sample) override;
void RecordRapporURL(const char* metric, const blink::WebURL& url) override;
blink::WebPushProvider* PushProvider() override;
- std::unique_ptr<blink::WebTrialTokenValidator> CreateTrialTokenValidator()
- override;
- blink::WebNotificationManager* GetWebNotificationManager() override;
void DidStartWorkerThread() override;
void WillStopWorkerThread() override;
void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
@@ -297,9 +282,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
std::unique_ptr<blink::WebThread> main_thread_;
std::unique_ptr<service_manager::Connector> connector_;
- class FileUtilities;
- std::unique_ptr<FileUtilities> file_utilities_;
-
#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_FUCHSIA)
class SandboxSupport;
std::unique_ptr<SandboxSupport> sandbox_support_;
@@ -323,12 +305,9 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- viz::ClientSharedBitmapManager* shared_bitmap_manager_;
std::unique_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
- cc_blink::WebCompositorSupportImpl compositor_support_;
-
std::unique_ptr<blink::WebScrollbarBehavior> web_scrollbar_behavior_;
base::IDMap<std::unique_ptr<PlatformEventObserverBase>>
@@ -346,10 +325,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::mojom::WebDatabaseHostPtrInfo web_database_host_info_;
scoped_refptr<blink::mojom::ThreadSafeWebDatabaseHostPtr> web_database_host_;
- mojom::FileUtilitiesHostPtrInfo file_utilities_host_info_;
-
- scoped_refptr<NotificationDispatcher> notification_dispatcher_;
-
THREAD_CHECKER(main_thread_checker_);
DISALLOW_COPY_AND_ASSIGN(RendererBlinkPlatformImpl);
diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc
index 43eb2aa4338..f3664c6e0eb 100644
--- a/chromium/content/renderer/renderer_main.cc
+++ b/chromium/content/renderer/renderer_main.cc
@@ -33,8 +33,10 @@
#include "content/renderer/renderer_main_platform_delegate.h"
#include "media/media_buildflags.h"
#include "ppapi/buildflags/buildflags.h"
+#include "services/service_manager/sandbox/switches.h"
#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
#include "third_party/skia/include/core/SkGraphics.h"
+#include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck
#include "ui/base/ui_base_switches.h"
#if defined(OS_ANDROID)
@@ -44,8 +46,8 @@
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
!defined(OS_FUCHSIA)
#include "content/common/font_config_ipc_linux.h"
-#include "content/public/common/common_sandbox_support_linux.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#endif
@@ -63,10 +65,6 @@
#include "content/renderer/pepper/pepper_plugin_registry.h"
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
-#include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck
-#endif
-
namespace content {
namespace {
// This function provides some ways to test crash and assertion handling
@@ -131,8 +129,8 @@ int RendererMain(const MainFunctionParams& parameters) {
// This call could already have been made from zygote_main_linux.cc. However
// we need to do it here if Zygote is disabled.
if (process_command_line.HasSwitch(switches::kNoZygote)) {
- SkFontConfigInterface::SetGlobal(new FontConfigIPC(GetSandboxFD()))
- ->unref();
+ SkFontConfigInterface::SetGlobal(
+ sk_make_sp<FontConfigIPC>(service_manager::GetSandboxFD()));
}
#endif
@@ -185,7 +183,8 @@ int RendererMain(const MainFunctionParams& parameters) {
base::PlatformThread::SetName("CrRendererMain");
- bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);
+ bool no_sandbox =
+ command_line.HasSwitch(service_manager::switches::kNoSandbox);
#if defined(OS_ANDROID)
// If we have any pending LibraryLoader histograms, record them.
@@ -212,13 +211,11 @@ int RendererMain(const MainFunctionParams& parameters) {
// Load pepper plugins before engaging the sandbox.
PepperPluginRegistry::GetInstance();
#endif
-#if BUILDFLAG(ENABLE_WEBRTC)
// Initialize WebRTC before engaging the sandbox.
// NOTE: On linux, this call could already have been made from
// zygote_main_linux.cc. However, calling multiple times from the same thread
// is OK.
InitializeWebRtcModule();
-#endif
{
#if defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
index eeb53a45092..c3d7bd9e714 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
@@ -35,8 +35,6 @@ bool RendererMainPlatformDelegate::EnableSandbox() {
//
// Anything else is started in InitializeSandbox().
service_manager::SandboxLinux::Options options;
- options.has_wasm_trap_handler =
- base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler);
service_manager::Sandbox::Initialize(
service_manager::SandboxTypeFromCommandLine(
*base::CommandLine::ForCurrentProcess()),
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
index 6b955bdb372..1e2cc38d386 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
+++ b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm
@@ -49,8 +49,11 @@ void DisconnectWindowServer() {
// launchservicesd to get an ASN. By setting this flag, HIServices skips
// that.
SetApplicationIsDaemon(true);
- // Tell LaunchServices to continue without a connection to the daemon.
- _LSSetApplicationLaunchServicesServerConnectionStatus(0, nullptr);
+ // Tell LaunchServices no connections are ever allowed.
+ _LSSetApplicationLaunchServicesServerConnectionStatus(
+ 0, ^bool(CFDictionaryRef options) {
+ return false;
+ });
}
// You are about to read a pretty disgusting hack. In a static initializer,
@@ -101,15 +104,9 @@ void DisconnectCFNotificationCenter() {
// Convert the string to an address.
std::string port_address_std_string =
base::SysCFStringRefToUTF8(port_address_string);
-#if __LP64__
uint64_t port_address = 0;
if (!base::HexStringToUInt64(port_address_std_string, &port_address))
continue;
-#else
- uint32_t port_address = 0;
- if (!base::HexStringToUInt(port_address_std_string, &port_address))
- continue;
-#endif
// Cast the address to an object.
CFMachPortRef mach_port = reinterpret_cast<CFMachPortRef>(port_address);
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_win.cc b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
index bb193916caf..d121f97ad00 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_win.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
@@ -15,11 +15,11 @@
#include "base/win/windows_version.h"
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.h"
#include "content/child/font_warmup_win.h"
-#include "content/public/common/content_switches.h"
#include "content/public/common/injection_test_win.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/render_thread_impl.h"
#include "sandbox/win/src/sandbox.h"
+#include "services/service_manager/sandbox/switches.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/web/win/web_font_rendering.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
@@ -41,7 +41,8 @@ void RendererMainPlatformDelegate::PlatformInitialize() {
// Be mindful of what resources you acquire here. They can be used by
// malicious code if the renderer gets compromised.
- bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);
+ bool no_sandbox =
+ command_line.HasSwitch(service_manager::switches::kNoSandbox);
if (!no_sandbox) {
// ICU DateFormat class (used in base/time_format.cc) needs to get the
diff --git a/chromium/content/renderer/resizing_mode_selector.cc b/chromium/content/renderer/resizing_mode_selector.cc
index d94a7a65b8c..5e2235301dd 100644
--- a/chromium/content/renderer/resizing_mode_selector.cc
+++ b/chromium/content/renderer/resizing_mode_selector.cc
@@ -17,12 +17,14 @@ bool ResizingModeSelector::NeverUsesSynchronousResize() const {
!RenderThreadImpl::current()->layout_test_mode();
}
-bool ResizingModeSelector::ShouldAbortOnResize(RenderWidget* widget,
- const ResizeParams& params) {
+bool ResizingModeSelector::ShouldAbortOnResize(
+ RenderWidget* widget,
+ const VisualProperties& visual_properties) {
return is_synchronous_mode_ &&
- params.is_fullscreen_granted == widget->is_fullscreen_granted() &&
- params.display_mode == widget->display_mode() &&
- params.screen_info.device_scale_factor ==
+ visual_properties.is_fullscreen_granted ==
+ widget->is_fullscreen_granted() &&
+ visual_properties.display_mode == widget->display_mode() &&
+ visual_properties.screen_info.device_scale_factor ==
widget->GetScreenInfo().device_scale_factor;
}
diff --git a/chromium/content/renderer/resizing_mode_selector.h b/chromium/content/renderer/resizing_mode_selector.h
index 7b92b9d70e4..46a71826723 100644
--- a/chromium/content/renderer/resizing_mode_selector.h
+++ b/chromium/content/renderer/resizing_mode_selector.h
@@ -10,7 +10,7 @@
namespace content {
class RenderWidget;
-struct ResizeParams;
+struct VisualProperties;
// Enables switching between two modes of resizing:
// 1) The "normal" (asynchronous) resizing, which involves sending messages to
@@ -25,7 +25,8 @@ class ResizingModeSelector {
public:
ResizingModeSelector();
bool NeverUsesSynchronousResize() const;
- bool ShouldAbortOnResize(RenderWidget* widget, const ResizeParams& params);
+ bool ShouldAbortOnResize(RenderWidget* widget,
+ const VisualProperties& visual_properties);
void set_is_synchronous_mode(bool mode);
bool is_synchronous_mode() const;
diff --git a/chromium/content/renderer/service_worker/controller_service_worker_connector.cc b/chromium/content/renderer/service_worker/controller_service_worker_connector.cc
index b8bc7f4b0a6..c1677a25c30 100644
--- a/chromium/content/renderer/service_worker/controller_service_worker_connector.cc
+++ b/chromium/content/renderer/service_worker/controller_service_worker_connector.cc
@@ -11,31 +11,38 @@
namespace content {
ControllerServiceWorkerConnector::ControllerServiceWorkerConnector(
- mojom::ServiceWorkerContainerHost* container_host)
- : container_host_(container_host) {}
-
-ControllerServiceWorkerConnector::ControllerServiceWorkerConnector(
mojom::ServiceWorkerContainerHost* container_host,
mojom::ControllerServiceWorkerPtr controller_ptr,
const std::string& client_id)
- : container_host_(container_host) {
- ResetControllerConnection(std::move(controller_ptr), client_id);
+ : container_host_(container_host), client_id_(client_id) {
+ SetControllerServiceWorkerPtr(std::move(controller_ptr));
+}
+
+ControllerServiceWorkerConnector::ControllerServiceWorkerConnector(
+ mojom::ServiceWorkerContainerHostPtrInfo container_host_info,
+ const std::string& client_id)
+ : client_id_(client_id) {
+ container_host_ptr_.Bind(std::move(container_host_info));
+ container_host_ptr_.set_connection_error_handler(base::BindOnce(
+ &ControllerServiceWorkerConnector::OnContainerHostConnectionClosed,
+ base::Unretained(this)));
+ container_host_ = container_host_ptr_.get();
+ SetControllerServiceWorkerPtr(nullptr /* controller_ptr */);
}
mojom::ControllerServiceWorker*
ControllerServiceWorkerConnector::GetControllerServiceWorker(
mojom::ControllerServiceWorkerPurpose purpose) {
switch (state_) {
- case State::kDisconnected:
+ case State::kDisconnected: {
DCHECK(!controller_service_worker_);
DCHECK(container_host_);
+ mojom::ControllerServiceWorkerPtr controller_ptr;
container_host_->EnsureControllerServiceWorker(
- mojo::MakeRequest(&controller_service_worker_), purpose);
- controller_service_worker_.set_connection_error_handler(base::BindOnce(
- &ControllerServiceWorkerConnector::OnControllerConnectionClosed,
- base::Unretained(this)));
- state_ = State::kConnected;
+ mojo::MakeRequest(&controller_ptr), purpose);
+ SetControllerServiceWorkerPtr(std::move(controller_ptr));
return controller_service_worker_.get();
+ }
case State::kConnected:
DCHECK(controller_service_worker_.is_bound());
return controller_service_worker_.get();
@@ -62,6 +69,7 @@ void ControllerServiceWorkerConnector::RemoveObserver(Observer* observer) {
void ControllerServiceWorkerConnector::OnContainerHostConnectionClosed() {
state_ = State::kNoContainerHost;
container_host_ = nullptr;
+ container_host_ptr_.reset();
controller_service_worker_.reset();
}
@@ -74,20 +82,22 @@ void ControllerServiceWorkerConnector::OnControllerConnectionClosed() {
}
void ControllerServiceWorkerConnector::ResetControllerConnection(
- mojom::ControllerServiceWorkerPtr controller_ptr,
- const std::string& client_id) {
+ mojom::ControllerServiceWorkerPtr controller_ptr) {
if (state_ == State::kNoContainerHost)
return;
+ SetControllerServiceWorkerPtr(std::move(controller_ptr));
+ if (!controller_service_worker_)
+ state_ = State::kNoController;
+}
+
+void ControllerServiceWorkerConnector::SetControllerServiceWorkerPtr(
+ mojom::ControllerServiceWorkerPtr controller_ptr) {
controller_service_worker_ = std::move(controller_ptr);
if (controller_service_worker_) {
- DCHECK(client_id_.empty() || client_id_ == client_id);
- client_id_ = client_id;
- state_ = State::kConnected;
controller_service_worker_.set_connection_error_handler(base::BindOnce(
&ControllerServiceWorkerConnector::OnControllerConnectionClosed,
base::Unretained(this)));
- } else {
- state_ = State::kNoController;
+ state_ = State::kConnected;
}
}
diff --git a/chromium/content/renderer/service_worker/controller_service_worker_connector.h b/chromium/content/renderer/service_worker/controller_service_worker_connector.h
index dbab8d8c557..9be6d162087 100644
--- a/chromium/content/renderer/service_worker/controller_service_worker_connector.h
+++ b/chromium/content/renderer/service_worker/controller_service_worker_connector.h
@@ -51,20 +51,23 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector
kNoContainerHost,
};
- // Use this ctor when no |controller_ptr| is available at creation time.
- // |state_| is set to kDisconnected.
- // TODO(bashi): Remove this one constructor. We need to update
- // WorkerFetchContextImpl to remove this constructor.
- explicit ControllerServiceWorkerConnector(
- mojom::ServiceWorkerContainerHost* container_host);
-
- // Use this ctor when |controller_ptr| is given by the browser at the
- // creation time. |state_| is set to either kConnected or kNoController.
+ // This class should only be created if a controller exists for the client.
+ // |controller_ptr| may be nullptr if the caller does not yet have a Mojo
+ // connection to the controller. |state_| is set to kDisconnected in that
+ // case.
ControllerServiceWorkerConnector(
mojom::ServiceWorkerContainerHost* container_host,
mojom::ControllerServiceWorkerPtr controller_ptr,
const std::string& client_id);
+ // Used by service worker clients that are workers (i.e., dedicated workers
+ // and shared workers). Creates and holds the ownership of
+ // |container_host_ptr_| (as |this| will be created on a different thread from
+ // the worker thread that has the original |container_host|).
+ ControllerServiceWorkerConnector(
+ mojom::ServiceWorkerContainerHostPtrInfo container_host_info,
+ const std::string& client_id);
+
// This may return nullptr if the connection to the ContainerHost (in the
// browser process) is already terminated.
mojom::ControllerServiceWorker* GetControllerServiceWorker(
@@ -79,14 +82,16 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector
// Resets the controller connection with the given |controller_ptr|, this
// can be called when a new controller is given, e.g. due to claim().
void ResetControllerConnection(
- mojom::ControllerServiceWorkerPtr controller_ptr,
- const std::string& client_id);
+ mojom::ControllerServiceWorkerPtr controller_ptr);
State state() const { return state_; }
const std::string& client_id() const { return client_id_; }
private:
+ void SetControllerServiceWorkerPtr(
+ mojom::ControllerServiceWorkerPtr controller_ptr);
+
State state_ = State::kDisconnected;
friend class base::RefCounted<ControllerServiceWorkerConnector>;
@@ -98,6 +103,11 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector
// Cleared when the connection is dropped.
mojom::ServiceWorkerContainerHost* container_host_;
+ // Keeps the mojo end to the browser process on its own.
+ // Non-null only for the service worker clients that are workers (i.e., only
+ // when created for dedicated workers or shared workers).
+ mojom::ServiceWorkerContainerHostPtr container_host_ptr_;
+
// Connection to the ControllerServiceWorker. The consumer of this connection
// should not need to know which process this is connected to.
// (Currently this is connected to BrowserSideControllerServiceWorker,
diff --git a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
index d1c2549f738..5b7ceb07604 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
+++ b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -14,6 +14,7 @@
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/service_worker/service_worker_context_client.h"
#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_installed_scripts_manager.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_security_origin.h"
@@ -33,7 +34,7 @@ EmbeddedWorkerInstanceClientImpl::WorkerWrapper::~WorkerWrapper() = default;
void EmbeddedWorkerInstanceClientImpl::Create(
base::TimeTicks blink_initialized_time,
scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request) {
+ mojom::EmbeddedWorkerInstanceClientRequest request) {
// This won't be leaked because the lifetime will be managed internally.
// See the class documentation for detail.
EmbeddedWorkerInstanceClientImpl* client =
@@ -56,20 +57,24 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker(
DCHECK(!wrapper_);
TRACE_EVENT0("ServiceWorker",
"EmbeddedWorkerInstanceClientImpl::StartWorker");
- service_manager::mojom::InterfaceProviderPtr interface_provider(
- std::move(params->provider_info->interface_provider));
+ DCHECK(!params->provider_info->cache_storage ||
+ base::FeatureList::IsEnabled(
+ blink::features::kEagerCacheStorageSetupForServiceWorkers));
+ blink::mojom::CacheStoragePtrInfo cache_storage =
+ std::move(params->provider_info->cache_storage);
+ service_manager::mojom::InterfaceProviderPtrInfo interface_provider =
+ std::move(params->provider_info->interface_provider);
+
auto client = std::make_unique<ServiceWorkerContextClient>(
params->embedded_worker_id, params->service_worker_version_id,
params->scope, params->script_url,
!params->installed_scripts_info.is_null(),
std::move(params->dispatcher_request),
- std::move(params->controller_request),
- std::move(params->service_worker_host), std::move(params->instance_host),
+ std::move(params->controller_request), std::move(params->instance_host),
std::move(params->provider_info), std::move(temporal_self_),
RenderThreadImpl::current()
->GetWebMainThreadScheduler()
- ->DefaultTaskRunner(),
- io_thread_runner_);
+ ->DefaultTaskRunner());
client->set_blink_initialized_time(blink_initialized_time_);
client->set_start_worker_received_time(base::TimeTicks::Now());
// Record UMA to indicate StartWorker is received on renderer.
@@ -80,6 +85,7 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker(
"ServiceWorker.EmbeddedWorkerInstanceClient.StartWorker", metric,
StartWorkerHistogramEnum::NUM_TYPES);
wrapper_ = StartWorkerContext(std::move(params), std::move(client),
+ std::move(cache_storage),
std::move(interface_provider));
}
@@ -116,7 +122,7 @@ void EmbeddedWorkerInstanceClientImpl::BindDevToolsAgent(
EmbeddedWorkerInstanceClientImpl::EmbeddedWorkerInstanceClientImpl(
scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request)
+ mojom::EmbeddedWorkerInstanceClientRequest request)
: binding_(this, std::move(request)),
temporal_self_(this),
io_thread_runner_(std::move(io_thread_runner)) {
@@ -136,7 +142,8 @@ std::unique_ptr<EmbeddedWorkerInstanceClientImpl::WorkerWrapper>
EmbeddedWorkerInstanceClientImpl::StartWorkerContext(
mojom::EmbeddedWorkerStartParamsPtr params,
std::unique_ptr<ServiceWorkerContextClient> context_client,
- service_manager::mojom::InterfaceProviderPtr interface_provider) {
+ blink::mojom::CacheStoragePtrInfo cache_storage,
+ service_manager::mojom::InterfaceProviderPtrInfo interface_provider) {
std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager;
// |installed_scripts_info| is null if scripts should be served by net layer,
// when the worker is not installed, or the worker is launched for checking
@@ -150,7 +157,7 @@ EmbeddedWorkerInstanceClientImpl::StartWorkerContext(
std::make_unique<WorkerWrapper>(blink::WebEmbeddedWorker::Create(
std::move(context_client), std::move(manager),
params->content_settings_proxy.PassHandle(),
- interface_provider.PassInterface().PassHandle()));
+ cache_storage.PassHandle(), interface_provider.PassHandle()));
blink::WebEmbeddedWorkerStartData start_data;
start_data.script_url = params->script_url;
diff --git a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h
index e71ab87b7b9..e755302db45 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h
+++ b/chromium/content/renderer/service_worker/embedded_worker_instance_client_impl.h
@@ -8,10 +8,11 @@
#include <memory>
#include "base/containers/id_map.h"
+#include "base/single_thread_task_runner.h"
#include "content/child/child_thread_impl.h"
#include "content/child/scoped_child_process_reference.h"
#include "content/common/service_worker/embedded_worker.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "third_party/blink/public/web/worker_content_settings_proxy.mojom.h"
@@ -55,10 +56,12 @@ class EmbeddedWorkerInstanceClientImpl
// Creates a new EmbeddedWorkerInstanceClientImpl instance bound to
// |request|. The instance destroys itself when needed, see the class
// documentation.
+ // TODO(shimazu): Create a service worker's execution context by this method
+ // instead of just creating an instance of EmbeddedWorkerInstanceClient.
static void Create(
base::TimeTicks blink_initialized_time,
scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request);
+ mojom::EmbeddedWorkerInstanceClientRequest request);
~EmbeddedWorkerInstanceClientImpl() override;
@@ -82,7 +85,7 @@ class EmbeddedWorkerInstanceClientImpl
EmbeddedWorkerInstanceClientImpl(
scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner,
- mojom::EmbeddedWorkerInstanceClientAssociatedRequest request);
+ mojom::EmbeddedWorkerInstanceClientRequest request);
// mojom::EmbeddedWorkerInstanceClient implementation
void StartWorker(mojom::EmbeddedWorkerStartParamsPtr params) override;
@@ -99,9 +102,10 @@ class EmbeddedWorkerInstanceClientImpl
std::unique_ptr<WorkerWrapper> StartWorkerContext(
mojom::EmbeddedWorkerStartParamsPtr params,
std::unique_ptr<ServiceWorkerContextClient> context_client,
- service_manager::mojom::InterfaceProviderPtr interface_provider);
+ blink::mojom::CacheStoragePtrInfo cache_storage,
+ service_manager::mojom::InterfaceProviderPtrInfo interface_provider);
- mojo::AssociatedBinding<mojom::EmbeddedWorkerInstanceClient> binding_;
+ mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_;
// This is valid before StartWorker is called. After that, this object
// will be passed to ServiceWorkerContextClient.
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc
index 9a1972a65a1..31065358f6e 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc
@@ -8,9 +8,11 @@
#include <memory>
#include <utility>
+#include "base/feature_list.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_local.h"
@@ -24,7 +26,6 @@
#include "content/public/common/content_features.h"
#include "content/public/common/push_event_payload.h"
#include "content/public/common/referrer.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/worker_thread.h"
@@ -38,7 +39,6 @@
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/service_worker/controller_service_worker_impl.h"
#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "content/renderer/service_worker/service_worker_fetch_context_impl.h"
#include "content/renderer/service_worker/service_worker_network_provider.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
@@ -52,6 +52,8 @@
#include "ipc/ipc_message_macros.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/request_context_frame_type.mojom.h"
#include "storage/common/blob_storage/blob_handle.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
@@ -124,7 +126,7 @@ class WebServiceWorkerNetworkProviderImpl
// mojom::URLLoaderFactory pointer into SharedURLLoaderFactory.
return std::make_unique<WebURLLoaderImpl>(
render_thread->resource_dispatcher(), std::move(task_runner),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
provider_->script_loader_factory()));
}
return nullptr;
@@ -185,6 +187,7 @@ void ToWebServiceWorkerRequest(const network::ResourceRequest& request,
uint64_t request_body_blob_size,
blink::mojom::BlobPtrInfo request_body_blob,
const std::string& client_id,
+ std::vector<blink::mojom::BlobPtrInfo> blob_ptrs,
blink::WebServiceWorkerRequest* web_request) {
DCHECK(web_request);
web_request->SetURL(blink::WebURL(request.url));
@@ -198,7 +201,7 @@ void ToWebServiceWorkerRequest(const network::ResourceRequest& request,
// Non-S13nServiceWorker: The body is provided as a blob.
if (request_body_blob) {
- DCHECK(!ServiceWorkerUtils::IsServicificationEnabled());
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
mojo::ScopedMessagePipeHandle blob_pipe = request_body_blob.PassHandle();
web_request->SetBlob(blink::WebString::FromASCII(request_body_blob_uuid),
request_body_blob_size, std::move(blob_pipe));
@@ -206,8 +209,11 @@ void ToWebServiceWorkerRequest(const network::ResourceRequest& request,
// S13nServiceWorker: The body is provided in |request|.
else if (request.request_body) {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
- blink::WebHTTPBody body =
- GetWebHTTPBodyForRequestBody(*request.request_body);
+ // |blob_ptrs| should be empty when Network Service is enabled.
+ DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+ blob_ptrs.empty());
+ blink::WebHTTPBody body = GetWebHTTPBodyForRequestBodyWithBlobPtrs(
+ *request.request_body, std::move(blob_ptrs));
body.SetUniqueBoundary();
web_request->SetBody(body);
}
@@ -339,71 +345,6 @@ base::OnceCallback<void(int /* event_id */)> CreateAbortCallback(MapType* map,
map, std::forward<Args>(args)..., base::Time::Now());
}
-template <typename Signature>
-class CallbackWrapperOnWorkerThread;
-
-// Always lives (create/run/destroy) on the same one worker thread.
-// This is needed because we're using Mojo ThreadSafeAssociatedInterfacePtr for
-// |context_->service_worker_host|, so we need to ensure Web*Callbacks are
-// destructed on the worker thread. If the worker thread dies before the
-// callback is run, this gets notified in WillStopCurrentWorkerThread() and
-// deletes itself and the callback on the worker thread, otherwise, it runs the
-// callback on the worker thread as normal and deletes itself.
-//
-// TODO(leonhsl): Once we can detach ServiceWorkerHost interface's association
-// on the legacy IPC channel, we can avoid using
-// ThreadSafeAssociatedInterfacePtr for |context_->service_worker_host|, then we
-// can eliminate this wrapping mechanism.
-template <typename... Args>
-class CallbackWrapperOnWorkerThread<void(Args...)>
- : public WorkerThread::Observer {
- public:
- using Signature = void(Args...);
-
- static base::WeakPtr<CallbackWrapperOnWorkerThread<Signature>> Create(
- base::OnceCallback<Signature> callback) {
- // |wrapper| controls its own lifetime via WorkerThread::Observer
- // implementation.
- auto* wrapper =
- new CallbackWrapperOnWorkerThread<Signature>(std::move(callback));
- return wrapper->weak_ptr_factory_.GetWeakPtr();
- }
-
- ~CallbackWrapperOnWorkerThread() override {
- DCHECK_GT(WorkerThread::GetCurrentId(), 0);
- WorkerThread::RemoveObserver(this);
- }
-
- void Run(Args... args) {
- DCHECK(callback_);
- std::move(callback_).Run(std::forward<Args>(args)...);
- delete this;
- }
-
- private:
- explicit CallbackWrapperOnWorkerThread(base::OnceCallback<Signature> callback)
- : callback_(std::move(callback)), weak_ptr_factory_(this) {
- DCHECK_GT(WorkerThread::GetCurrentId(), 0);
- WorkerThread::AddObserver(this);
- }
-
- // WorkerThread::Observer implementation.
- void WillStopCurrentWorkerThread() override { delete this; }
-
- base::OnceCallback<Signature> callback_;
- base::WeakPtrFactory<CallbackWrapperOnWorkerThread> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CallbackWrapperOnWorkerThread);
-};
-
-template <typename Signature>
-base::OnceCallback<Signature> WrapCallbackThreadSafe(
- base::OnceCallback<Signature> callback) {
- return base::BindOnce(
- &CallbackWrapperOnWorkerThread<Signature>::Run,
- CallbackWrapperOnWorkerThread<Signature>::Create(std::move(callback)));
-}
-
void DidGetClients(
std::unique_ptr<blink::WebServiceWorkerClientsCallbacks> callbacks,
std::vector<blink::mojom::ServiceWorkerClientInfoPtr> clients) {
@@ -520,17 +461,14 @@ struct ServiceWorkerContextClient::WorkerContextData {
DCHECK(thread_checker.CalledOnValidThread());
}
+ // Map from version id to JavaScript ServiceWorker object.
+ std::map<int64_t, WebServiceWorkerImpl*> workers_;
+
mojo::Binding<mojom::ServiceWorkerEventDispatcher> event_dispatcher_binding;
- // |service_worker_host| is used on the worker thread but bound on the IO
- // thread, because it's a channel-associated interface which can be bound
- // only on the main or IO thread.
- // TODO(xiaofeng.zhang): Once we can detach this interface out from the legacy
- // IPC channel-associated interfaces world, we should bind it always on the
- // worker thread on which |this| lives. Although it is a scoped_refptr, the
- // only owner is |this|.
- scoped_refptr<blink::mojom::ThreadSafeServiceWorkerHostAssociatedPtr>
- service_worker_host;
+ // Bound by the first Mojo call received on the service worker thread
+ // ServiceWorkerEventDispatcher::InitializeGlobalScope().
+ blink::mojom::ServiceWorkerHostAssociatedPtr service_worker_host;
// Maps for inflight event callbacks.
// These are mapped from an event id issued from ServiceWorkerTimeoutTimer to
@@ -560,6 +498,8 @@ struct ServiceWorkerContextClient::WorkerContextData {
notification_close_event_callbacks;
std::map<int, DispatchPushEventCallback> push_event_callbacks;
std::map<int, DispatchFetchEventCallback> fetch_event_callbacks;
+ std::map<int, DispatchCookieChangeEventCallback>
+ cookie_change_event_callbacks;
std::map<int, DispatchExtendableMessageEventCallback> message_event_callbacks;
// Maps for response callbacks.
@@ -756,22 +696,18 @@ ServiceWorkerContextClient::ServiceWorkerContextClient(
bool is_script_streaming,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
: embedded_worker_id_(embedded_worker_id),
service_worker_version_id_(service_worker_version_id),
service_worker_scope_(service_worker_scope),
script_url_(script_url),
main_thread_task_runner_(std::move(main_thread_task_runner)),
- io_thread_task_runner_(io_thread_task_runner),
proxy_(nullptr),
pending_dispatcher_request_(std::move(dispatcher_request)),
pending_controller_request_(std::move(controller_request)),
- pending_service_worker_host_(std::move(service_worker_host)),
embedded_worker_client_(std::move(embedded_worker_client)) {
instance_host_ =
mojom::ThreadSafeEmbeddedWorkerInstanceHostAssociatedPtr::Create(
@@ -793,13 +729,27 @@ ServiceWorkerContextClient::ServiceWorkerContextClient(
ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
+scoped_refptr<WebServiceWorkerImpl>
+ServiceWorkerContextClient::GetOrCreateServiceWorkerObject(
+ blink::mojom::ServiceWorkerObjectInfoPtr info) {
+ if (!info)
+ return nullptr;
+
+ auto found = context_->workers_.find(info->version_id);
+ if (found != context_->workers_.end()) {
+ return found->second;
+ }
+
+ return WebServiceWorkerImpl::CreateForServiceWorkerGlobalScope(
+ std::move(info));
+}
+
void ServiceWorkerContextClient::GetClient(
const blink::WebString& id,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
- (*context_->service_worker_host)
- ->GetClient(id.Utf8(), WrapCallbackThreadSafe(base::BindOnce(
- &DidGetClient, std::move(callbacks))));
+ context_->service_worker_host->GetClient(
+ id.Utf8(), base::BindOnce(&DidGetClient, std::move(callbacks)));
}
void ServiceWorkerContextClient::GetClients(
@@ -808,42 +758,35 @@ void ServiceWorkerContextClient::GetClients(
DCHECK(callbacks);
auto options = blink::mojom::ServiceWorkerClientQueryOptions::New(
weboptions.include_uncontrolled, weboptions.client_type);
- (*context_->service_worker_host)
- ->GetClients(std::move(options),
- WrapCallbackThreadSafe(
- base::BindOnce(&DidGetClients, std::move(callbacks))));
+ context_->service_worker_host->GetClients(
+ std::move(options), base::BindOnce(&DidGetClients, std::move(callbacks)));
}
void ServiceWorkerContextClient::OpenNewTab(
const blink::WebURL& url,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
- (*context_->service_worker_host)
- ->OpenNewTab(url, WrapCallbackThreadSafe(base::BindOnce(
- &DidOpenWindow, std::move(callbacks))));
+ context_->service_worker_host->OpenNewTab(
+ url, base::BindOnce(&DidOpenWindow, std::move(callbacks)));
}
void ServiceWorkerContextClient::OpenPaymentHandlerWindow(
const blink::WebURL& url,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
- (*context_->service_worker_host)
- ->OpenPaymentHandlerWindow(
- url, WrapCallbackThreadSafe(
- base::BindOnce(&DidOpenWindow, std::move(callbacks))));
+ context_->service_worker_host->OpenPaymentHandlerWindow(
+ url, base::BindOnce(&DidOpenWindow, std::move(callbacks)));
}
void ServiceWorkerContextClient::SetCachedMetadata(const blink::WebURL& url,
const char* data,
size_t size) {
- DCHECK(context_->service_worker_host);
- (*context_->service_worker_host)
- ->SetCachedMetadata(url, std::vector<uint8_t>(data, data + size));
+ context_->service_worker_host->SetCachedMetadata(
+ url, std::vector<uint8_t>(data, data + size));
}
void ServiceWorkerContextClient::ClearCachedMetadata(const blink::WebURL& url) {
- DCHECK(context_->service_worker_host);
- (*context_->service_worker_host)->ClearCachedMetadata(url);
+ context_->service_worker_host->ClearCachedMetadata(url);
}
void ServiceWorkerContextClient::WorkerReadyForInspection() {
@@ -888,10 +831,6 @@ void ServiceWorkerContextClient::WorkerContextStarted(
// same thread before the worker context goes away in
// willDestroyWorkerContext.
context_.reset(new WorkerContextData(this));
- // Create ServiceWorkerDispatcher first for this worker thread to be used
- // later by TakeRegistrationForServiceWorkerGlobalScope() etc.
- ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance()
- ->SetIOThreadTaskRunner(io_thread_task_runner_);
DCHECK(pending_dispatcher_request_.is_pending());
DCHECK(pending_controller_request_.is_pending());
@@ -905,16 +844,6 @@ void ServiceWorkerContextClient::WorkerContextStarted(
std::move(pending_controller_request_), GetWeakPtr());
}
- DCHECK(pending_service_worker_host_.is_valid());
- DCHECK(!context_->service_worker_host);
- context_->service_worker_host =
- blink::mojom::ThreadSafeServiceWorkerHostAssociatedPtr::Create(
- std::move(pending_service_worker_host_), io_thread_task_runner_);
- // Set ServiceWorkerGlobalScope#registration.
- proxy_->SetRegistration(WebServiceWorkerRegistrationImpl::CreateHandle(
- provider_context_->TakeRegistrationForServiceWorkerGlobalScope(
- io_thread_task_runner_)));
-
(*instance_host_)->OnThreadStarted(WorkerThread::GetCurrentId());
TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "START_WORKER_CONTEXT",
@@ -1063,6 +992,15 @@ void ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent(
base::Time::FromDoubleT(event_dispatch_time));
}
+void ServiceWorkerContextClient::DidHandleCookieChangeEvent(
+ int request_id,
+ blink::mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ RunEventCallback(&context_->cookie_change_event_callbacks,
+ context_->timeout_timer.get(), request_id, status,
+ base::Time::FromDoubleT(event_dispatch_time));
+}
+
void ServiceWorkerContextClient::DidHandleExtendableMessageEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
@@ -1293,7 +1231,10 @@ ServiceWorkerContextClient::CreateServiceWorkerFetchContext() {
script_url_, url_loader_factory_bundle->Clone(),
provider_context_->provider_id(),
GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
- URLLoaderThrottleProviderType::kWorker));
+ URLLoaderThrottleProviderType::kWorker),
+ GetContentClient()
+ ->renderer()
+ ->CreateWebSocketHandshakeThrottleProvider());
}
std::unique_ptr<blink::WebServiceWorkerProvider>
@@ -1308,17 +1249,16 @@ ServiceWorkerContextClient::CreateServiceWorkerProvider() {
void ServiceWorkerContextClient::PostMessageToClient(
const blink::WebString& uuid,
blink::TransferableMessage message) {
- (*context_->service_worker_host)
- ->PostMessageToClient(uuid.Utf8(), std::move(message));
+ context_->service_worker_host->PostMessageToClient(uuid.Utf8(),
+ std::move(message));
}
void ServiceWorkerContextClient::Focus(
const blink::WebString& uuid,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
- (*context_->service_worker_host)
- ->FocusClient(uuid.Utf8(), WrapCallbackThreadSafe(base::BindOnce(
- &DidFocusClient, std::move(callbacks))));
+ context_->service_worker_host->FocusClient(
+ uuid.Utf8(), base::BindOnce(&DidFocusClient, std::move(callbacks)));
}
void ServiceWorkerContextClient::Navigate(
@@ -1326,28 +1266,23 @@ void ServiceWorkerContextClient::Navigate(
const blink::WebURL& url,
std::unique_ptr<blink::WebServiceWorkerClientCallbacks> callbacks) {
DCHECK(callbacks);
- (*context_->service_worker_host)
- ->NavigateClient(uuid.Utf8(), url,
- WrapCallbackThreadSafe(base::BindOnce(
- &DidNavigateClient, std::move(callbacks))));
+ context_->service_worker_host->NavigateClient(
+ uuid.Utf8(), url,
+ base::BindOnce(&DidNavigateClient, std::move(callbacks)));
}
void ServiceWorkerContextClient::SkipWaiting(
std::unique_ptr<blink::WebServiceWorkerSkipWaitingCallbacks> callbacks) {
DCHECK(callbacks);
- DCHECK(context_->service_worker_host);
- (*context_->service_worker_host)
- ->SkipWaiting(WrapCallbackThreadSafe(
- base::BindOnce(&DidSkipWaiting, std::move(callbacks))));
+ context_->service_worker_host->SkipWaiting(
+ base::BindOnce(&DidSkipWaiting, std::move(callbacks)));
}
void ServiceWorkerContextClient::Claim(
std::unique_ptr<blink::WebServiceWorkerClientsClaimCallbacks> callbacks) {
DCHECK(callbacks);
- DCHECK(context_->service_worker_host);
- (*context_->service_worker_host)
- ->ClaimClients(WrapCallbackThreadSafe(
- base::BindOnce(&DidClaimClients, std::move(callbacks))));
+ context_->service_worker_host->ClaimClients(
+ base::BindOnce(&DidClaimClients, std::move(callbacks)));
}
void ServiceWorkerContextClient::DispatchOrQueueFetchEvent(
@@ -1462,6 +1397,8 @@ void ServiceWorkerContextClient::DispatchActivateEvent(
void ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchAbortEventCallback callback) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent");
@@ -1469,8 +1406,17 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent(
CreateAbortCallback(&context_->background_fetch_abort_event_callbacks));
context_->background_fetch_abort_event_callbacks.emplace(request_id,
std::move(callback));
+
+ blink::WebVector<blink::WebBackgroundFetchSettledFetch> web_fetches(
+ fetches.size());
+ for (size_t i = 0; i < fetches.size(); ++i) {
+ ToWebServiceWorkerRequest(fetches[i].request, &web_fetches[i].request);
+ ToWebServiceWorkerResponse(fetches[i].response, &web_fetches[i].response);
+ }
+
proxy_->DispatchBackgroundFetchAbortEvent(
- request_id, blink::WebString::FromUTF8(developer_id));
+ request_id, blink::WebString::FromUTF8(developer_id),
+ blink::WebString::FromUTF8(unique_id), web_fetches);
}
void ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent(
@@ -1494,6 +1440,7 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent(
void ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchFailEventCallback callback) {
TRACE_EVENT0("ServiceWorker",
@@ -1511,7 +1458,8 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent(
}
proxy_->DispatchBackgroundFetchFailEvent(
- request_id, blink::WebString::FromUTF8(developer_id), web_fetches);
+ request_id, blink::WebString::FromUTF8(developer_id),
+ blink::WebString::FromUTF8(unique_id), web_fetches);
}
void ServiceWorkerContextClient::DispatchBackgroundFetchedEvent(
@@ -1538,6 +1486,25 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchedEvent(
blink::WebString::FromUTF8(unique_id), web_fetches);
}
+void ServiceWorkerContextClient::InitializeGlobalScope(
+ blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info) {
+ DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
+ // Connect to the blink::mojom::ServiceWorkerHost.
+ DCHECK(!context_->service_worker_host);
+ context_->service_worker_host.Bind(std::move(service_worker_host));
+ // Set ServiceWorkerGlobalScope#registration.
+ DCHECK_NE(registration_info->registration_id,
+ blink::mojom::kInvalidServiceWorkerRegistrationId);
+ DCHECK(registration_info->host_ptr_info.is_valid());
+ DCHECK(registration_info->request.is_pending());
+ proxy_->SetRegistration(WebServiceWorkerRegistrationImpl::CreateHandle(
+ WebServiceWorkerRegistrationImpl::CreateForServiceWorkerGlobalScope(
+ std::move(registration_info))));
+
+ proxy_->ReadyToEvaluateScript();
+}
+
void ServiceWorkerContextClient::DispatchInstallEvent(
DispatchInstallEventCallback callback) {
TRACE_EVENT0("ServiceWorker",
@@ -1567,14 +1534,10 @@ void ServiceWorkerContextClient::DispatchExtendableMessageEvent(
return;
}
- DCHECK(event->source_info_for_service_worker->handle_id !=
- blink::mojom::kInvalidServiceWorkerHandleId &&
- event->source_info_for_service_worker->version_id !=
- blink::mojom::kInvalidServiceWorkerVersionId);
- scoped_refptr<WebServiceWorkerImpl> worker =
- ServiceWorkerDispatcher::GetThreadSpecificInstance()
- ->GetOrCreateServiceWorker(
- std::move(event->source_info_for_service_worker));
+ DCHECK_NE(event->source_info_for_service_worker->version_id,
+ blink::mojom::kInvalidServiceWorkerVersionId);
+ scoped_refptr<WebServiceWorkerImpl> worker = GetOrCreateServiceWorkerObject(
+ std::move(event->source_info_for_service_worker));
proxy_->DispatchExtendableMessageEvent(
request_id, std::move(event->message), event->source_origin,
WebServiceWorkerImpl::CreateHandle(worker));
@@ -1609,7 +1572,8 @@ void ServiceWorkerContextClient::DispatchFetchEvent(
ToWebServiceWorkerRequest(
std::move(params->request), params->request_body_blob_uuid,
params->request_body_blob_size, std::move(params->request_body_blob),
- params->client_id, &web_request);
+ params->client_id, std::move(params->request_body_blob_ptrs),
+ &web_request);
proxy_->DispatchFetchEvent(event_id, web_request, navigation_preload_sent);
}
@@ -1670,6 +1634,27 @@ void ServiceWorkerContextClient::DispatchPushEvent(
proxy_->DispatchPushEvent(request_id, data);
}
+void ServiceWorkerContextClient::DispatchCookieChangeEvent(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ DispatchCookieChangeEventCallback callback) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerContextClient::DispatchCookieChangeEvent");
+
+ int request_id = context_->timeout_timer->StartEvent(
+ CreateAbortCallback(&context_->cookie_change_event_callbacks));
+ context_->cookie_change_event_callbacks.emplace(request_id,
+ std::move(callback));
+
+ // TODO(pwnall): Map |cause| to a blink enum. Currently, a cookie overwrite
+ // shows up as delete + insert.
+ bool is_cookie_delete =
+ cause != ::network::mojom::CookieChangeCause::INSERTED;
+ proxy_->DispatchCookieChangeEvent(
+ request_id, blink::WebString::FromUTF8(cookie.Name()),
+ blink::WebString::FromUTF8(cookie.Value()), is_cookie_delete);
+}
+
void ServiceWorkerContextClient::Ping(PingCallback callback) {
std::move(callback).Run();
}
@@ -1702,9 +1687,9 @@ void ServiceWorkerContextClient::OnNavigationPreloadComplete(
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) {
- proxy_->OnNavigationPreloadComplete(
- fetch_event_id, (completion_time - base::TimeTicks()).InSecondsF(),
- encoded_data_length, encoded_body_length, decoded_body_length);
+ proxy_->OnNavigationPreloadComplete(fetch_event_id, completion_time,
+ encoded_data_length, encoded_body_length,
+ decoded_body_length);
context_->preload_requests.Remove(fetch_event_id);
}
@@ -1730,6 +1715,23 @@ bool ServiceWorkerContextClient::RequestedTermination() const {
return context_->timeout_timer->did_idle_timeout();
}
+void ServiceWorkerContextClient::AddServiceWorkerObject(
+ int64_t version_id,
+ WebServiceWorkerImpl* worker) {
+ DCHECK(!base::ContainsKey(context_->workers_, version_id));
+ context_->workers_[version_id] = worker;
+}
+
+void ServiceWorkerContextClient::RemoveServiceWorkerObject(int64_t version_id) {
+ DCHECK(base::ContainsKey(context_->workers_, version_id));
+ context_->workers_.erase(version_id);
+}
+
+bool ServiceWorkerContextClient::ContainsServiceWorkerObjectForTesting(
+ int64_t version_id) {
+ return base::ContainsKey(context_->workers_, version_id);
+}
+
base::WeakPtr<ServiceWorkerContextClient>
ServiceWorkerContextClient::GetWeakPtr() {
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h
index f3f8557433f..61085729f81 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.h
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.h
@@ -52,10 +52,6 @@ class WebServiceWorkerResponse;
class WebURLResponse;
}
-namespace IPC {
-class Message;
-}
-
namespace content {
struct PlatformNotificationData;
@@ -64,6 +60,7 @@ class EmbeddedWorkerInstanceClientImpl;
class ServiceWorkerNetworkProvider;
class ServiceWorkerProviderContext;
class ServiceWorkerTimeoutTimer;
+class WebServiceWorkerImpl;
class WebWorkerFetchContext;
// ServiceWorkerContextClient is a "client" of a service worker execution
@@ -93,12 +90,10 @@ class CONTENT_EXPORT ServiceWorkerContextClient
bool is_script_streaming,
mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
mojom::ControllerServiceWorkerRequest controller_request,
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
~ServiceWorkerContextClient() override;
// Called on the main thread.
@@ -110,6 +105,11 @@ class CONTENT_EXPORT ServiceWorkerContextClient
start_worker_received_time_ = start_worker_received_time;
}
+ // Returns the service worker object described by |info|. Creates a new object
+ // if needed, or else returns the existing one.
+ scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorkerObject(
+ blink::mojom::ServiceWorkerObjectInfoPtr info);
+
// WebServiceWorkerContextClient overrides.
void GetClient(
const blink::WebString& client_id,
@@ -165,6 +165,9 @@ class CONTENT_EXPORT ServiceWorkerContextClient
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
double dispatch_event_time) override;
+ void DidHandleCookieChangeEvent(int request_id,
+ blink::mojom::ServiceWorkerEventStatus status,
+ double dispatch_event_time) override;
void DidHandleExtendableMessageEvent(
int request_id,
blink::mojom::ServiceWorkerEventStatus status,
@@ -257,6 +260,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
class NavigationPreloadRequest;
friend class ControllerServiceWorkerImpl;
friend class ServiceWorkerContextClientTest;
+ friend class WebServiceWorkerImpl;
FRIEND_TEST_ALL_PREFIXES(
ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_RequestedTerminationAndDie);
@@ -270,15 +274,20 @@ class CONTENT_EXPORT ServiceWorkerContextClient
// in the browser process.
int GetRoutingID() const { return embedded_worker_id_; }
- void Send(IPC::Message* message);
void SendWorkerStarted();
- // mojom::ServiceWorkerEventDispatcher
+ // Implements mojom::ServiceWorkerEventDispatcher.
+ void InitializeGlobalScope(
+ blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host,
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info)
+ override;
void DispatchInstallEvent(
DispatchInstallEventCallback callback) override;
void DispatchActivateEvent(DispatchActivateEventCallback callback) override;
void DispatchBackgroundFetchAbortEvent(
const std::string& developer_id,
+ const std::string& unique_id,
+ const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchAbortEventCallback callback) override;
void DispatchBackgroundFetchClickEvent(
const std::string& developer_id,
@@ -286,6 +295,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
DispatchBackgroundFetchClickEventCallback callback) override;
void DispatchBackgroundFetchFailEvent(
const std::string& developer_id,
+ const std::string& unique_id,
const std::vector<BackgroundFetchSettledFetch>& fetches,
DispatchBackgroundFetchFailEventCallback callback) override;
void DispatchBackgroundFetchedEvent(
@@ -330,6 +340,10 @@ class CONTENT_EXPORT ServiceWorkerContextClient
payments::mojom::PaymentRequestEventDataPtr event_data,
payments::mojom::PaymentHandlerResponseCallbackPtr response_callback,
DispatchPaymentRequestEventCallback callback) override;
+ void DispatchCookieChangeEvent(
+ const net::CanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ DispatchCookieChangeEventCallback callback) override;
void Ping(PingCallback callback) override;
void SetIdleTimerDelayToZero() override;
@@ -382,6 +396,11 @@ class CONTENT_EXPORT ServiceWorkerContextClient
// process. It does this due to idle timeout.
bool RequestedTermination() const;
+ // Keeps the mapping from version id to ServiceWorker object.
+ void AddServiceWorkerObject(int64_t version_id, WebServiceWorkerImpl* worker);
+ void RemoveServiceWorkerObject(int64_t version_id);
+ bool ContainsServiceWorkerObjectForTesting(int64_t version_id);
+
base::WeakPtr<ServiceWorkerContextClient> GetWeakPtr();
static void ResetThreadSpecificInstanceForTesting();
@@ -394,7 +413,6 @@ class CONTENT_EXPORT ServiceWorkerContextClient
const GURL script_url_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
scoped_refptr<base::TaskRunner> worker_task_runner_;
scoped_refptr<ServiceWorkerProviderContext> provider_context_;
@@ -405,7 +423,6 @@ class CONTENT_EXPORT ServiceWorkerContextClient
// These Mojo objects are bound on the worker thread.
mojom::ServiceWorkerEventDispatcherRequest pending_dispatcher_request_;
mojom::ControllerServiceWorkerRequest pending_controller_request_;
- blink::mojom::ServiceWorkerHostAssociatedPtrInfo pending_service_worker_host_;
// This is bound on the main thread.
scoped_refptr<mojom::ThreadSafeEmbeddedWorkerInstanceHostAssociatedPtr>
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc b/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc
index 83f769be740..d9fbfee4759 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client_unittest.cc
@@ -16,9 +16,10 @@
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "content/renderer/service_worker/service_worker_timeout_timer.h"
+#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/worker_thread_registry.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request.h"
@@ -61,6 +62,7 @@ class MockWebServiceWorkerContextProxy
public:
~MockWebServiceWorkerContextProxy() override = default;
+ void ReadyToEvaluateScript() override {}
void SetRegistration(
std::unique_ptr<blink::WebServiceWorkerRegistration::Handle> handle)
override {
@@ -76,7 +78,10 @@ class MockWebServiceWorkerContextProxy
void DispatchActivateEvent(int event_id) override { NOTREACHED(); }
void DispatchBackgroundFetchAbortEvent(
int event_id,
- const blink::WebString& developer_id) override {
+ const blink::WebString& developer_id,
+ const blink::WebString& unique_id,
+ const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
+ override {
NOTREACHED();
}
void DispatchBackgroundFetchClickEvent(int event_id,
@@ -87,6 +92,7 @@ class MockWebServiceWorkerContextProxy
void DispatchBackgroundFetchFailEvent(
int event_id,
const blink::WebString& developer_id,
+ const blink::WebString& unique_id,
const blink::WebVector<blink::WebBackgroundFetchSettledFetch>& fetches)
override {
NOTREACHED();
@@ -99,6 +105,12 @@ class MockWebServiceWorkerContextProxy
override {
NOTREACHED();
}
+ void DispatchCookieChangeEvent(int event_id,
+ const blink::WebString& name,
+ const blink::WebString& value,
+ bool is_deleted) override {
+ NOTREACHED();
+ }
void DispatchExtendableMessageEvent(
int event_id,
blink::TransferableMessage message,
@@ -158,7 +170,7 @@ class MockWebServiceWorkerContextProxy
NOTREACHED();
}
void OnNavigationPreloadComplete(int fetch_event_id,
- double completion_time,
+ base::TimeTicks completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) override {
@@ -183,6 +195,38 @@ base::RepeatingClosure CreateCallbackWithCalledFlag(bool* out_is_called) {
out_is_called);
}
+class MockServiceWorkerObjectHost
+ : public blink::mojom::ServiceWorkerObjectHost {
+ public:
+ explicit MockServiceWorkerObjectHost(int64_t version_id)
+ : version_id_(version_id) {}
+ ~MockServiceWorkerObjectHost() override = default;
+
+ blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo() {
+ auto info = blink::mojom::ServiceWorkerObjectInfo::New();
+ info->version_id = version_id_;
+ bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
+ info->request = mojo::MakeRequest(&remote_object_);
+ return info;
+ }
+
+ int GetBindingCount() const { return bindings_.size(); }
+
+ private:
+ // Implements blink::mojom::ServiceWorkerObjectHost.
+ void PostMessageToServiceWorker(
+ ::blink::TransferableMessage message) override {
+ NOTREACHED();
+ }
+ void TerminateForTesting(TerminateForTestingCallback callback) override {
+ NOTREACHED();
+ }
+
+ const int64_t version_id_;
+ mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
+ blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object_;
+};
+
} // namespace
class ServiceWorkerContextClientTest : public testing::Test {
@@ -199,8 +243,6 @@ class ServiceWorkerContextClientTest : public testing::Test {
void TearDown() override {
ServiceWorkerContextClient::ResetThreadSpecificInstanceForTesting();
- ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance()
- ->AllowReinstantiationForTesting();
// Unregister this thread from worker threads.
WorkerThreadRegistry::Instance()->WillStopCurrentWorkerThread();
}
@@ -211,58 +253,64 @@ class ServiceWorkerContextClientTest : public testing::Test {
}
// Creates an empty struct to initialize ServiceWorkerProviderContext.
- mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfo(
- blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedRequest*
- out_request,
- blink::mojom::ServiceWorkerRegistrationObjectAssociatedPtr* out_ptr) {
+ mojom::ServiceWorkerProviderInfoForStartWorkerPtr CreateProviderInfo() {
auto info = mojom::ServiceWorkerProviderInfoForStartWorker::New();
- info->registration =
- blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
- blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedPtr host_ptr;
- *out_request = mojo::MakeRequestAssociatedWithDedicatedPipe(&host_ptr);
- info->registration->host_ptr_info = host_ptr.PassInterface();
- info->registration->request =
- mojo::MakeRequestAssociatedWithDedicatedPipe(out_ptr);
- info->registration->registration_id = 100; // dummy
+ info->provider_id = 10; // dummy
return info;
}
- // Creates an ContextClient, whose pipes are connected to |out_pipes|.
+ // Creates an ContextClient, whose pipes are connected to |out_pipes|, then
+ // simulates that the service worker thread has started with |proxy|.
std::unique_ptr<ServiceWorkerContextClient> CreateContextClient(
- ContextClientPipes* out_pipes) {
+ ContextClientPipes* out_pipes,
+ blink::WebServiceWorkerContextProxy* proxy) {
auto event_dispatcher_request =
mojo::MakeRequest(&out_pipes->event_dispatcher);
auto controller_request = mojo::MakeRequest(&out_pipes->controller);
- blink::mojom::ServiceWorkerHostAssociatedPtr sw_host_ptr;
- out_pipes->service_worker_host_request =
- mojo::MakeRequestAssociatedWithDedicatedPipe(&sw_host_ptr);
mojom::EmbeddedWorkerInstanceHostAssociatedPtr embedded_worker_host_ptr;
out_pipes->embedded_worker_host_request =
mojo::MakeRequestAssociatedWithDedicatedPipe(&embedded_worker_host_ptr);
- return std::make_unique<ServiceWorkerContextClient>(
- 1 /* embeded_worker_id */, 1 /* service_worker_version_id */,
- GURL("https://example.com") /* scope */,
- GURL("https://example.com/SW.js") /* script_URL */,
- false /* is_script_streaming */, std::move(event_dispatcher_request),
- std::move(controller_request), sw_host_ptr.PassInterface(),
- embedded_worker_host_ptr.PassInterface(),
- CreateProviderInfo(&out_pipes->registration_host_request,
- &out_pipes->registration),
- nullptr /* embedded_worker_client */,
- blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
- io_task_runner());
+ const GURL kScope("https://example.com");
+ const GURL kScript("https://example.com/SW.js");
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ std::make_unique<ServiceWorkerContextClient>(
+ 1 /* embedded_worker_id */, 1 /* service_worker_version_id */,
+ kScope, kScript, false /* is_script_streaming */,
+ std::move(event_dispatcher_request), std::move(controller_request),
+ embedded_worker_host_ptr.PassInterface(), CreateProviderInfo(),
+ nullptr /* embedded_worker_client */,
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+
+ context_client->WorkerContextStarted(proxy);
+
+ blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host;
+ out_pipes->service_worker_host_request =
+ mojo::MakeRequest(&service_worker_host);
+ auto registration_info =
+ blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
+ registration_info->registration_id = 100; // dummy
+ registration_info->options =
+ blink::mojom::ServiceWorkerRegistrationOptions::New(
+ kScope, blink::mojom::ServiceWorkerUpdateViaCache::kAll);
+ out_pipes->registration_host_request =
+ mojo::MakeRequest(&registration_info->host_ptr_info);
+ registration_info->request = mojo::MakeRequest(&out_pipes->registration);
+ out_pipes->event_dispatcher->InitializeGlobalScope(
+ std::move(service_worker_host), std::move(registration_info));
+ task_runner()->RunUntilIdle();
+ return context_client;
}
- scoped_refptr<base::TestMockTimeTaskRunner> task_runner() const {
- return task_runner_;
+ bool ContainsServiceWorkerObject(ServiceWorkerContextClient* context_client,
+ int64_t version_id) {
+ return context_client->ContainsServiceWorkerObjectForTesting(version_id);
}
- private:
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() {
- // Use this thread as the IO thread.
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner() const {
return task_runner_;
}
+ private:
base::MessageLoop message_loop_;
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
base::test::ScopedFeatureList feature_list_;
@@ -270,10 +318,9 @@ class ServiceWorkerContextClientTest : public testing::Test {
TEST_F(ServiceWorkerContextClientTest, Ping) {
ContextClientPipes pipes;
- std::unique_ptr<ServiceWorkerContextClient> context_client =
- CreateContextClient(&pipes);
MockWebServiceWorkerContextProxy mock_proxy;
- context_client->WorkerContextStarted(&mock_proxy);
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ CreateContextClient(&pipes, &mock_proxy);
bool is_called = false;
pipes.event_dispatcher->Ping(CreateCallbackWithCalledFlag(&is_called));
@@ -284,9 +331,8 @@ TEST_F(ServiceWorkerContextClientTest, Ping) {
TEST_F(ServiceWorkerContextClientTest, DispatchFetchEvent) {
ContextClientPipes pipes;
MockWebServiceWorkerContextProxy mock_proxy;
- std::unique_ptr<ServiceWorkerContextClient> context_client;
- context_client = CreateContextClient(&pipes);
- context_client->WorkerContextStarted(&mock_proxy);
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ CreateContextClient(&pipes, &mock_proxy);
context_client->DidEvaluateClassicScript(true /* success */);
task_runner()->RunUntilIdle();
EXPECT_TRUE(mock_proxy.fetch_events().empty());
@@ -314,10 +360,9 @@ TEST_F(ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_NotRequestedTermination) {
EnableServicification();
ContextClientPipes pipes;
- std::unique_ptr<ServiceWorkerContextClient> context_client =
- CreateContextClient(&pipes);
MockWebServiceWorkerContextProxy mock_proxy;
- context_client->WorkerContextStarted(&mock_proxy);
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ CreateContextClient(&pipes, &mock_proxy);
context_client->DidEvaluateClassicScript(true /* success */);
task_runner()->RunUntilIdle();
EXPECT_TRUE(mock_proxy.fetch_events().empty());
@@ -353,10 +398,9 @@ TEST_F(ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_RequestedTerminationAndDie) {
EnableServicification();
ContextClientPipes pipes;
- std::unique_ptr<ServiceWorkerContextClient> context_client =
- CreateContextClient(&pipes);
MockWebServiceWorkerContextProxy mock_proxy;
- context_client->WorkerContextStarted(&mock_proxy);
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ CreateContextClient(&pipes, &mock_proxy);
context_client->DidEvaluateClassicScript(true /* success */);
task_runner()->RunUntilIdle();
EXPECT_TRUE(mock_proxy.fetch_events().empty());
@@ -402,10 +446,9 @@ TEST_F(ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_RequestedTerminationAndWakeUp) {
EnableServicification();
ContextClientPipes pipes;
- std::unique_ptr<ServiceWorkerContextClient> context_client =
- CreateContextClient(&pipes);
MockWebServiceWorkerContextProxy mock_proxy;
- context_client->WorkerContextStarted(&mock_proxy);
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ CreateContextClient(&pipes, &mock_proxy);
context_client->DidEvaluateClassicScript(true /* success */);
task_runner()->RunUntilIdle();
EXPECT_TRUE(mock_proxy.fetch_events().empty());
@@ -469,4 +512,58 @@ TEST_F(ServiceWorkerContextClientTest,
static_cast<GURL>(mock_proxy.fetch_events()[1].second.Url()));
}
+TEST_F(ServiceWorkerContextClientTest, GetOrCreateServiceWorkerObject) {
+ ContextClientPipes pipes;
+ MockWebServiceWorkerContextProxy mock_proxy;
+ std::unique_ptr<ServiceWorkerContextClient> context_client =
+ CreateContextClient(&pipes, &mock_proxy);
+ scoped_refptr<WebServiceWorkerImpl> worker1;
+ scoped_refptr<WebServiceWorkerImpl> worker2;
+ const int64_t version_id = 200;
+ auto mock_service_worker_object_host =
+ std::make_unique<MockServiceWorkerObjectHost>(version_id);
+ ASSERT_EQ(0, mock_service_worker_object_host->GetBindingCount());
+
+ // Should return a worker object newly created with the 1st given |info|.
+ {
+ blink::mojom::ServiceWorkerObjectInfoPtr info =
+ mock_service_worker_object_host->CreateObjectInfo();
+ // ServiceWorkerObjectHost Mojo connection has been added.
+ EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
+ EXPECT_FALSE(ContainsServiceWorkerObject(context_client.get(), version_id));
+ worker1 = context_client->GetOrCreateServiceWorkerObject(std::move(info));
+ EXPECT_TRUE(worker1);
+ EXPECT_TRUE(ContainsServiceWorkerObject(context_client.get(), version_id));
+ // |worker1| is holding the 1st blink::mojom::ServiceWorkerObjectHost Mojo
+ // connection to |mock_service_worker_object_host|.
+ EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
+ }
+
+ // Should return the same worker object and release the 2nd given |info|.
+ {
+ blink::mojom::ServiceWorkerObjectInfoPtr info =
+ mock_service_worker_object_host->CreateObjectInfo();
+ EXPECT_EQ(2, mock_service_worker_object_host->GetBindingCount());
+ worker2 = context_client->GetOrCreateServiceWorkerObject(std::move(info));
+ EXPECT_EQ(worker1, worker2);
+ task_runner()->RunUntilIdle();
+ // The 2nd ServiceWorkerObjectHost Mojo connection in |info| has been
+ // dropped.
+ EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
+ }
+
+ // The dtor decrements the refcounts.
+ worker1 = nullptr;
+ worker2 = nullptr;
+ task_runner()->RunUntilIdle();
+ EXPECT_FALSE(ContainsServiceWorkerObject(context_client.get(), version_id));
+ // The 1st ServiceWorkerObjectHost Mojo connection got broken.
+ EXPECT_EQ(0, mock_service_worker_object_host->GetBindingCount());
+
+ // Should return nullptr when given nullptr.
+ scoped_refptr<WebServiceWorkerImpl> invalid_worker =
+ context_client->GetOrCreateServiceWorkerObject(nullptr);
+ EXPECT_FALSE(invalid_worker);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_dispatcher.cc b/chromium/content/renderer/service_worker/service_worker_dispatcher.cc
deleted file mode 100644
index 24f00cae4e8..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_dispatcher.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2013 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/renderer/service_worker/service_worker_dispatcher.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/stl_util.h"
-#include "base/threading/thread_local.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/service_worker/service_worker_messages.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/common/content_constants.h"
-#include "content/renderer/service_worker/service_worker_provider_context.h"
-#include "content/renderer/service_worker/web_service_worker_impl.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "url/url_constants.h"
-
-using blink::WebServiceWorkerError;
-using blink::WebServiceWorkerProvider;
-using base::ThreadLocalPointer;
-
-namespace content {
-
-namespace {
-
-base::LazyInstance<ThreadLocalPointer<void>>::Leaky g_dispatcher_tls =
- LAZY_INSTANCE_INITIALIZER;
-
-void* const kDeletedServiceWorkerDispatcherMarker =
- reinterpret_cast<void*>(0x1);
-
-} // namespace
-
-ServiceWorkerDispatcher::ServiceWorkerDispatcher() {
- g_dispatcher_tls.Pointer()->Set(static_cast<void*>(this));
-}
-
-ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
- if (allow_reinstantiation_) {
- g_dispatcher_tls.Pointer()->Set(nullptr);
- return;
- }
- g_dispatcher_tls.Pointer()->Set(kDeletedServiceWorkerDispatcherMarker);
-}
-
-void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
-
- // When you add a new message handler, you should consider adding a similar
- // handler in ServiceWorkerMessageFilter to release references passed from
- // the browser process in case we fail to post task to the thread.
- IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
- IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
- OnServiceWorkerStateChanged)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled) << "Unhandled message:" << msg.type();
-}
-
-ServiceWorkerDispatcher*
-ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance() {
- if (g_dispatcher_tls.Pointer()->Get() ==
- kDeletedServiceWorkerDispatcherMarker) {
- NOTREACHED() << "Re-instantiating TLS ServiceWorkerDispatcher.";
- g_dispatcher_tls.Pointer()->Set(nullptr);
- }
- if (g_dispatcher_tls.Pointer()->Get())
- return static_cast<ServiceWorkerDispatcher*>(
- g_dispatcher_tls.Pointer()->Get());
-
- ServiceWorkerDispatcher* dispatcher = new ServiceWorkerDispatcher();
- if (WorkerThread::GetCurrentId())
- WorkerThread::AddObserver(dispatcher);
- return dispatcher;
-}
-
-ServiceWorkerDispatcher* ServiceWorkerDispatcher::GetThreadSpecificInstance() {
- if (g_dispatcher_tls.Pointer()->Get() ==
- kDeletedServiceWorkerDispatcherMarker)
- return nullptr;
- return static_cast<ServiceWorkerDispatcher*>(
- g_dispatcher_tls.Pointer()->Get());
-}
-
-void ServiceWorkerDispatcher::AllowReinstantiationForTesting() {
- allow_reinstantiation_ = true;
-}
-
-void ServiceWorkerDispatcher::WillStopCurrentWorkerThread() {
- delete this;
-}
-
-scoped_refptr<WebServiceWorkerImpl>
-ServiceWorkerDispatcher::GetOrCreateServiceWorker(
- blink::mojom::ServiceWorkerObjectInfoPtr info) {
- if (!info)
- return nullptr;
- DCHECK_NE(blink::mojom::kInvalidServiceWorkerHandleId, info->handle_id);
- DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId, info->version_id);
-
- WorkerObjectMap::iterator found = service_workers_.find(info->handle_id);
- if (found != service_workers_.end())
- return found->second;
-
- if (WorkerThread::GetCurrentId()) {
- // Because we do not support navigator.serviceWorker in
- // WorkerNavigator (see https://crbug.com/371690), both dedicated worker and
- // shared worker context can never have a ServiceWorker object, but service
- // worker execution context is different as it can have some ServiceWorker
- // objects via the ServiceWorkerGlobalScope#registration object.
- // So, if we're on a worker thread here we know it's definitely a service
- // worker thread.
- DCHECK(io_thread_task_runner_);
- return WebServiceWorkerImpl::CreateForServiceWorkerGlobalScope(
- std::move(info), io_thread_task_runner_);
- }
- return WebServiceWorkerImpl::CreateForServiceWorkerClient(std::move(info));
-}
-
-void ServiceWorkerDispatcher::SetIOThreadTaskRunner(
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner) {
- io_thread_task_runner_ = std::move(io_thread_task_runner);
-}
-
-void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
- int thread_id,
- int handle_id,
- blink::mojom::ServiceWorkerState state) {
- TRACE_EVENT2("ServiceWorker",
- "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
- "Thread ID", thread_id,
- "State", static_cast<int>(state));
- WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
- if (worker != service_workers_.end())
- worker->second->OnStateChanged(state);
-}
-
-void ServiceWorkerDispatcher::AddServiceWorker(
- int handle_id, WebServiceWorkerImpl* worker) {
- DCHECK(!base::ContainsKey(service_workers_, handle_id));
- service_workers_[handle_id] = worker;
-}
-
-void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
- DCHECK(base::ContainsKey(service_workers_, handle_id));
- service_workers_.erase(handle_id);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_dispatcher.h b/chromium/content/renderer/service_worker/service_worker_dispatcher.h
deleted file mode 100644
index 79d2a6f53e9..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_dispatcher.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2013 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_RENDERER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_H_
-#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/containers/id_map.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string16.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/public/renderer/worker_thread.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_state.mojom.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-
-class WebServiceWorkerImpl;
-
-// This class manages communication with the browser process about
-// registration of the service worker, exposed to renderer and worker
-// scripts through methods like navigator.registerServiceWorker().
-class CONTENT_EXPORT ServiceWorkerDispatcher : public WorkerThread::Observer {
- public:
- explicit ServiceWorkerDispatcher();
- ~ServiceWorkerDispatcher() override;
-
- void OnMessageReceived(const IPC::Message& msg);
-
- // Returns the existing service worker or a newly created one with the given
- // object info.
- scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorker(
- blink::mojom::ServiceWorkerObjectInfoPtr info);
-
- // Sets the IO thread task runner. This is only called for a
- // ServiceWorkerDispatcher instance on a service worker thread when the thread
- // has just started, and the provided IO thread task runner will be used only
- // for creating WebServiceWorkerImpl later.
- // TODO(leonhsl): Remove this function once we addressed the TODO in
- // WebServiceWorkerImpl about the legacy IPC channel-associated interface.
- void SetIOThreadTaskRunner(
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner);
-
- static ServiceWorkerDispatcher* GetOrCreateThreadSpecificInstance();
-
- // Unlike GetOrCreateThreadSpecificInstance() this doesn't create a new
- // instance if thread-local instance doesn't exist.
- static ServiceWorkerDispatcher* GetThreadSpecificInstance();
-
- private:
- using WorkerObjectMap = std::map<int, WebServiceWorkerImpl*>;
-
- friend class ServiceWorkerContextClientTest;
- friend class ServiceWorkerDispatcherTest;
- friend class WebServiceWorkerImpl;
-
- void AllowReinstantiationForTesting();
-
- // WorkerThread::Observer implementation.
- void WillStopCurrentWorkerThread() override;
-
- void OnServiceWorkerStateChanged(int thread_id,
- int handle_id,
- blink::mojom::ServiceWorkerState state);
-
- // Keeps map from handle_id to ServiceWorker object.
- void AddServiceWorker(int handle_id, WebServiceWorkerImpl* worker);
- void RemoveServiceWorker(int handle_id);
-
- // True if another dispatcher is allowed to be created on the same thread
- // after this instance is destructed.
- bool allow_reinstantiation_ = false;
-
- WorkerObjectMap service_workers_;
-
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_H_
diff --git a/chromium/content/renderer/service_worker/service_worker_dispatcher_unittest.cc b/chromium/content/renderer/service_worker/service_worker_dispatcher_unittest.cc
deleted file mode 100644
index ecf73fcddbe..00000000000
--- a/chromium/content/renderer/service_worker/service_worker_dispatcher_unittest.cc
+++ /dev/null
@@ -1,117 +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.
-
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "content/common/service_worker/service_worker_container.mojom.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "content/renderer/service_worker/service_worker_provider_context.h"
-#include "content/renderer/service_worker/web_service_worker_impl.h"
-#include "mojo/public/cpp/bindings/associated_binding_set.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
-
-namespace content {
-
-namespace {
-
-class MockServiceWorkerObjectHost
- : public blink::mojom::ServiceWorkerObjectHost {
- public:
- MockServiceWorkerObjectHost(int32_t handle_id, int64_t version_id)
- : handle_id_(handle_id), version_id_(version_id) {}
- ~MockServiceWorkerObjectHost() override = default;
-
- blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo() {
- auto info = blink::mojom::ServiceWorkerObjectInfo::New();
- info->handle_id = handle_id_;
- info->version_id = version_id_;
- bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
- return info;
- }
-
- int GetBindingCount() const { return bindings_.size(); }
-
- private:
- // Implements blink::mojom::ServiceWorkerObjectHost.
- void PostMessageToServiceWorker(
- ::blink::TransferableMessage message) override {
- NOTREACHED();
- }
- void TerminateForTesting(TerminateForTestingCallback callback) override {
- NOTREACHED();
- }
-
- int32_t handle_id_;
- int64_t version_id_;
- mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
-};
-
-} // namespace
-
-class ServiceWorkerDispatcherTest : public testing::Test {
- public:
- ServiceWorkerDispatcherTest() {}
-
- void SetUp() override {
- dispatcher_ = std::make_unique<ServiceWorkerDispatcher>();
- }
-
- bool ContainsServiceWorker(int handle_id) {
- return ContainsKey(dispatcher_->service_workers_, handle_id);
- }
-
- ServiceWorkerDispatcher* dispatcher() { return dispatcher_.get(); }
-
- private:
- base::MessageLoop message_loop_;
- std::unique_ptr<ServiceWorkerDispatcher> dispatcher_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherTest);
-};
-
-TEST_F(ServiceWorkerDispatcherTest, GetServiceWorker) {
- scoped_refptr<WebServiceWorkerImpl> worker1;
- scoped_refptr<WebServiceWorkerImpl> worker2;
- auto mock_service_worker_object_host =
- std::make_unique<MockServiceWorkerObjectHost>(100 /* handle_id */,
- 200 /* version_id */);
- ASSERT_EQ(0, mock_service_worker_object_host->GetBindingCount());
-
- // Should return a worker object newly created with the 1st given |info|.
- {
- blink::mojom::ServiceWorkerObjectInfoPtr info =
- mock_service_worker_object_host->CreateObjectInfo();
- EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
- int handle_id = info->handle_id;
- worker1 = dispatcher()->GetOrCreateServiceWorker(std::move(info));
- EXPECT_TRUE(worker1);
- EXPECT_TRUE(ContainsServiceWorker(handle_id));
- // |worker1| is holding the 1st blink::mojom::ServiceWorkerObjectHost Mojo
- // connection to |mock_service_worker_object_host|.
- EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
- }
-
- // Should return the same worker object and release the 2nd given |info|.
- {
- blink::mojom::ServiceWorkerObjectInfoPtr info =
- mock_service_worker_object_host->CreateObjectInfo();
- EXPECT_EQ(2, mock_service_worker_object_host->GetBindingCount());
- worker2 = dispatcher()->GetOrCreateServiceWorker(std::move(info));
- EXPECT_EQ(worker1, worker2);
- base::RunLoop().RunUntilIdle();
- // The Mojo connection kept by |info| should be released.
- EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
- }
-
- // Should return nullptr when given nullptr.
- scoped_refptr<WebServiceWorkerImpl> invalid_worker =
- dispatcher()->GetOrCreateServiceWorker(nullptr);
- EXPECT_FALSE(invalid_worker);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index 36a43de7375..f432fa6d2e4 100644
--- a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -5,14 +5,15 @@
#include "content/renderer/service_worker/service_worker_fetch_context_impl.h"
#include "base/feature_list.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/content_features.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
+#include "content/public/renderer/websocket_handshake_throttle_provider.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "content/renderer/loader/web_url_loader_impl.h"
#include "content/renderer/loader/web_url_request_util.h"
#include "ipc/ipc_message.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
namespace content {
@@ -21,11 +22,15 @@ ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl(
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
url_loader_factory_info,
int service_worker_provider_id,
- std::unique_ptr<URLLoaderThrottleProvider> throttle_provider)
+ std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
+ std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ websocket_handshake_throttle_provider)
: worker_script_url_(worker_script_url),
url_loader_factory_info_(std::move(url_loader_factory_info)),
service_worker_provider_id_(service_worker_provider_id),
- throttle_provider_(std::move(throttle_provider)) {}
+ throttle_provider_(std::move(throttle_provider)),
+ websocket_handshake_throttle_provider_(
+ std::move(websocket_handshake_throttle_provider)) {}
ServiceWorkerFetchContextImpl::~ServiceWorkerFetchContextImpl() {}
@@ -47,16 +52,16 @@ void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread() {
std::unique_ptr<blink::WebURLLoaderFactory>
ServiceWorkerFetchContextImpl::CreateURLLoaderFactory() {
DCHECK(url_loader_factory_);
- return std::make_unique<content::WebURLLoaderFactoryImpl>(
+ return std::make_unique<WebURLLoaderFactoryImpl>(
resource_dispatcher_->GetWeakPtr(), std::move(url_loader_factory_));
}
std::unique_ptr<blink::WebURLLoaderFactory>
ServiceWorkerFetchContextImpl::WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) {
- return std::make_unique<content::WebURLLoaderFactoryImpl>(
+ return std::make_unique<WebURLLoaderFactoryImpl>(
resource_dispatcher_->GetWeakPtr(),
- base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
network::mojom::URLLoaderFactoryPtrInfo(
std::move(url_loader_factory_handle),
network::mojom::URLLoaderFactory::Version_)));
@@ -87,4 +92,12 @@ blink::WebURL ServiceWorkerFetchContextImpl::SiteForCookies() const {
return worker_script_url_;
}
+std::unique_ptr<blink::WebSocketHandshakeThrottle>
+ServiceWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle() {
+ if (!websocket_handshake_throttle_provider_)
+ return nullptr;
+ return websocket_handshake_throttle_provider_->CreateThrottle(
+ MSG_ROUTING_NONE);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h
index c231cdb09d4..8ccd9817f40 100644
--- a/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/chromium/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -12,6 +12,7 @@
namespace content {
class ResourceDispatcher;
class URLLoaderThrottleProvider;
+class WebSocketHandshakeThrottleProvider;
class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
public:
@@ -20,7 +21,9 @@ class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
url_loader_factory_info,
int service_worker_provider_id,
- std::unique_ptr<URLLoaderThrottleProvider> throttle_provider);
+ std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
+ std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ websocket_handshake_throttle_provider);
~ServiceWorkerFetchContextImpl() override;
// blink::WebWorkerFetchContext implementation:
@@ -32,6 +35,8 @@ class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
void WillSendRequest(blink::WebURLRequest&) override;
bool IsControlledByServiceWorker() const override;
blink::WebURL SiteForCookies() const override;
+ std::unique_ptr<blink::WebSocketHandshakeThrottle>
+ CreateWebSocketHandshakeThrottle() override;
private:
const GURL worker_script_url_;
@@ -45,6 +50,8 @@ class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<URLLoaderThrottleProvider> throttle_provider_;
+ std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ websocket_handshake_throttle_provider_;
// This is owned by ThreadedMessagingProxyBase on the main thread.
base::WaitableEvent* terminate_sync_load_event_ = nullptr;
diff --git a/chromium/content/renderer/service_worker/service_worker_message_filter.cc b/chromium/content/renderer/service_worker/service_worker_message_filter.cc
index 7d52fcc83dd..1e99e493c4c 100644
--- a/chromium/content/renderer/service_worker/service_worker_message_filter.cc
+++ b/chromium/content/renderer/service_worker/service_worker_message_filter.cc
@@ -7,7 +7,6 @@
#include <stddef.h>
#include "content/common/service_worker/service_worker_messages.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "ipc/ipc_message_macros.h"
namespace content {
@@ -26,8 +25,6 @@ bool ServiceWorkerMessageFilter::ShouldHandleMessage(
void ServiceWorkerMessageFilter::OnFilteredMessageReceived(
const IPC::Message& msg) {
- ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance()
- ->OnMessageReceived(msg);
}
bool ServiceWorkerMessageFilter::GetWorkerThreadIdForMessage(
diff --git a/chromium/content/renderer/service_worker/service_worker_message_filter.h b/chromium/content/renderer/service_worker/service_worker_message_filter.h
index 6b89375e2c2..52cc42b69d5 100644
--- a/chromium/content/renderer/service_worker/service_worker_message_filter.h
+++ b/chromium/content/renderer/service_worker/service_worker_message_filter.h
@@ -6,11 +6,14 @@
#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_MESSAGE_FILTER_H_
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/renderer/worker_thread_message_filter.h"
namespace content {
+// TODO(leonhsl): Eliminate this class since we're in a pure Mojo world now, no
+// longer need to handle any legacy IPCs.
class CONTENT_EXPORT ServiceWorkerMessageFilter
: public WorkerThreadMessageFilter {
public:
diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider.cc b/chromium/content/renderer/service_worker/service_worker_network_provider.cc
index a81f33440e7..7b64c4750ff 100644
--- a/chromium/content/renderer/service_worker/service_worker_network_provider.cc
+++ b/chromium/content/renderer/service_worker/service_worker_network_provider.cc
@@ -5,20 +5,21 @@
#include "content/renderer/service_worker/service_worker_network_provider.h"
#include "base/atomic_sequence_num.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/navigation_params.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_provider_host_info.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/browser_side_navigation_policy.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
+#include "content/public/common/origin_util.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "ipc/ipc_sync_channel.h"
#include "mojo/public/cpp/bindings/associated_group.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
@@ -110,8 +111,14 @@ class WebServiceWorkerNetworkProviderForFrame
!provider_->context()->GetSubresourceLoaderFactory())
return nullptr;
- // If it's not for HTTP or HTTPS, no need to intercept the request.
- if (!GURL(request.Url()).SchemeIsHTTPOrHTTPS())
+ // If the URL is not http(s) or otherwise whitelisted, do not intercept the
+ // request. Schemes like 'blob' and 'file' are not eligible to be
+ // intercepted by service workers.
+ // TODO(falken): Let ServiceWorkerSubresourceLoaderFactory handle the
+ // request and move this check there (i.e., for such URLs, it should use
+ // its fallback factory).
+ const GURL gurl(request.Url());
+ if (!gurl.SchemeIsHTTPOrHTTPS() && !OriginCanAccessServiceWorkers(gurl))
return nullptr;
// If GetSkipServiceWorker() returns true, do not intercept the request.
@@ -125,7 +132,7 @@ class WebServiceWorkerNetworkProviderForFrame
return std::make_unique<WebURLLoaderImpl>(
RenderThreadImpl::current()->resource_dispatcher(),
std::move(task_runner),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
provider_->context()->GetSubresourceLoaderFactory()));
}
@@ -143,7 +150,7 @@ ServiceWorkerNetworkProvider::CreateForNavigation(
blink::WebLocalFrame* frame,
bool content_initiated,
mojom::ControllerServiceWorkerInfoPtr controller_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory) {
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) {
// Determine if a ServiceWorkerNetworkProvider should be created and properly
// initialized for the navigation. A default ServiceWorkerNetworkProvider
// will always be created since it is expected in a certain number of places,
@@ -185,7 +192,7 @@ ServiceWorkerNetworkProvider::CreateForNavigation(
auto provider = base::WrapUnique(new ServiceWorkerNetworkProvider(
route_id, blink::mojom::ServiceWorkerProviderType::kForWindow,
provider_id, is_parent_frame_secure, std::move(controller_info),
- std::move(default_loader_factory)));
+ std::move(fallback_loader_factory)));
return std::make_unique<WebServiceWorkerNetworkProviderForFrame>(
std::move(provider));
}
@@ -196,13 +203,13 @@ ServiceWorkerNetworkProvider::CreateForSharedWorker(
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory) {
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) {
// S13nServiceWorker: |info| holds info about the precreated provider host.
if (info) {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
return base::WrapUnique(new ServiceWorkerNetworkProvider(
std::move(info), std::move(script_loader_factory_info),
- std::move(default_loader_factory)));
+ std::move(fallback_loader_factory)));
}
return base::WrapUnique(new ServiceWorkerNetworkProvider(
@@ -210,7 +217,7 @@ ServiceWorkerNetworkProvider::CreateForSharedWorker(
blink::mojom::ServiceWorkerProviderType::kForSharedWorker,
GetNextProviderId(), true /* is_parent_frame_secure */,
nullptr /* controller_service_worker */,
- std::move(default_loader_factory)));
+ std::move(fallback_loader_factory)));
}
// static
@@ -260,7 +267,7 @@ ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
int provider_id,
bool is_parent_frame_secure,
mojom::ControllerServiceWorkerInfoPtr controller_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory) {
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) {
DCHECK_NE(provider_id, kInvalidServiceWorkerProviderId);
DCHECK(provider_type == blink::mojom::ServiceWorkerProviderType::kForWindow ||
provider_type ==
@@ -277,11 +284,10 @@ ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
// current() may be null in tests.
if (ChildThreadImpl::current()) {
- ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance();
context_ = base::MakeRefCounted<ServiceWorkerProviderContext>(
provider_id, provider_type, std::move(client_request),
std::move(host_ptr_info), std::move(controller_info),
- std::move(default_loader_factory));
+ std::move(fallback_loader_factory));
ChildThreadImpl::current()->channel()->GetRemoteAssociatedInterface(
&dispatcher_host_);
dispatcher_host_->OnProviderCreated(std::move(host_info));
@@ -289,7 +295,7 @@ ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
context_ = base::MakeRefCounted<ServiceWorkerProviderContext>(
provider_id, provider_type, std::move(client_request),
std::move(host_ptr_info), std::move(controller_info),
- std::move(default_loader_factory));
+ std::move(fallback_loader_factory));
}
}
@@ -298,13 +304,12 @@ ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory) {
- ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance();
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) {
context_ = base::MakeRefCounted<ServiceWorkerProviderContext>(
info->provider_id,
blink::mojom::ServiceWorkerProviderType::kForSharedWorker,
std::move(info->client_request), std::move(info->host_ptr_info),
- nullptr /* controller */, std::move(default_loader_factory));
+ nullptr /* controller */, std::move(fallback_loader_factory));
if (script_loader_factory_info.is_valid())
script_loader_factory_.Bind(std::move(script_loader_factory_info));
}
@@ -312,14 +317,9 @@ ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
// Constructor for service worker execution contexts.
ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
mojom::ServiceWorkerProviderInfoForStartWorkerPtr info) {
- // Initialize the provider context with info for
- // ServiceWorkerGlobalScope#registration.
- ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance();
context_ = base::MakeRefCounted<ServiceWorkerProviderContext>(
info->provider_id, std::move(info->client_request),
std::move(info->host_ptr_info));
- context_->SetRegistrationForServiceWorkerGlobalScope(
- std::move(info->registration));
if (info->script_loader_factory_ptr_info.is_valid()) {
script_loader_factory_.Bind(
diff --git a/chromium/content/renderer/service_worker/service_worker_network_provider.h b/chromium/content/renderer/service_worker/service_worker_network_provider.h
index 35e76fba855..120b71cbdf9 100644
--- a/chromium/content/renderer/service_worker/service_worker_network_provider.h
+++ b/chromium/content/renderer/service_worker/service_worker_network_provider.h
@@ -63,10 +63,10 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider {
// For S13nServiceWorker:
// |controller_info| contains the endpoint and object info that is needed to
// set up the controller service worker for the client.
- // |default_loader_factory| is a default loader factory for network requests,
- // and is used when we create a subresource loader for controllees. This is
- // non-null only if the provider is created for controllees, and if the
- // loading context, e.g. a frame, provides it.
+ // |fallback_loader_factory| is a default loader factory for fallback
+ // requests, and is used when we create a subresource loader for controllees.
+ // This is non-null only if the provider is created for controllees, and if
+ // the loading context, e.g. a frame, provides it.
static std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
CreateForNavigation(
int route_id,
@@ -74,7 +74,7 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider {
blink::WebLocalFrame* frame,
bool content_initiated,
mojom::ControllerServiceWorkerInfoPtr controller_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
// Creates a ServiceWorkerNetworkProvider for a shared worker (as a
// non-document service worker client).
@@ -82,7 +82,7 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider {
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
// Creates a ServiceWorkerNetworkProvider for a "controller" (i.e.
// a service worker execution context).
@@ -116,20 +116,20 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider {
//
// For S13nServiceWorker:
// See the comment at CreateForNavigation() for |controller_info| and
- // |default_loader_factory|.
+ // |fallback_loader_factory|.
ServiceWorkerNetworkProvider(
int route_id,
blink::mojom::ServiceWorkerProviderType type,
int provider_id,
bool is_parent_frame_secure,
mojom::ControllerServiceWorkerInfoPtr controller_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
ServiceWorkerNetworkProvider(
mojom::ServiceWorkerProviderInfoForSharedWorkerPtr info,
network::mojom::URLLoaderFactoryAssociatedPtrInfo
script_loader_factory_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
// This is for controllers, used in CreateForController.
explicit ServiceWorkerNetworkProvider(
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_context.cc b/chromium/content/renderer/service_worker/service_worker_provider_context.cc
index 04c6639807d..e63e68b8ae2 100644
--- a/chromium/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/chromium/content/renderer/service_worker/service_worker_provider_context.cc
@@ -15,10 +15,8 @@
#include "content/child/child_thread_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/service_names.mojom.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "content/renderer/service_worker/service_worker_subresource_loader.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
@@ -37,8 +35,8 @@ namespace content {
// Holds state for service worker clients.
struct ServiceWorkerProviderContext::ProviderStateForClient {
explicit ProviderStateForClient(
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory)
- : default_loader_factory(std::move(default_loader_factory)) {}
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory)
+ : fallback_loader_factory(std::move(fallback_loader_factory)) {}
~ProviderStateForClient() = default;
// |controller| will be set by SetController() and taken by TakeController().
@@ -53,7 +51,11 @@ struct ServiceWorkerProviderContext::ProviderStateForClient {
// S13nServiceWorker:
// Used when we create |subresource_loader_factory|.
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory;
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory;
+
+ // S13nServiceWorker:
+ // The Client#id value of the client.
+ std::string client_id;
// Tracks feature usage for UseCounter.
std::set<blink::mojom::WebFeature> used_features;
@@ -82,15 +84,10 @@ struct ServiceWorkerProviderContext::ProviderStateForClient {
// For service worker clients. Map from registration id to JavaScript
// ServiceWorkerRegistration object.
std::map<int64_t, WebServiceWorkerRegistrationImpl*> registrations_;
-};
-// Holds state for service worker execution contexts.
-struct ServiceWorkerProviderContext::ProviderStateForServiceWorker {
- ProviderStateForServiceWorker() = default;
- ~ProviderStateForServiceWorker() = default;
- // |registration| is set by SetRegistrationForServiceWorkerGlobalScope() and
- // taken by TakeRegistrationForServiceWorkerGlobalScope().
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration;
+ // For service worker clients. Map from version id to JavaScript ServiceWorker
+ // object.
+ std::map<int64_t, WebServiceWorkerImpl*> workers_;
};
// For service worker clients.
@@ -100,7 +97,7 @@ ServiceWorkerProviderContext::ServiceWorkerProviderContext(
mojom::ServiceWorkerContainerAssociatedRequest request,
mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info,
mojom::ControllerServiceWorkerInfoPtr controller_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory)
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory)
: provider_type_(provider_type),
provider_id_(provider_id),
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
@@ -108,18 +105,10 @@ ServiceWorkerProviderContext::ServiceWorkerProviderContext(
weak_factory_(this) {
container_host_.Bind(std::move(host_ptr_info));
state_for_client_ = std::make_unique<ProviderStateForClient>(
- std::move(default_loader_factory));
-
- if (!CanCreateSubresourceLoaderFactory() &&
- !IsNavigationMojoResponseEnabled()) {
- return;
- }
+ std::move(fallback_loader_factory));
- // S13nServiceWorker/NavigationMojoResponse:
// Set up the URL loader factory for sending subresource requests to
// the controller.
- DCHECK(ServiceWorkerUtils::IsServicificationEnabled() ||
- IsNavigationMojoResponseEnabled());
if (controller_info) {
SetController(std::move(controller_info),
std::vector<blink::mojom::WebFeature>(),
@@ -138,42 +127,11 @@ ServiceWorkerProviderContext::ServiceWorkerProviderContext(
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
binding_(this, std::move(request)),
weak_factory_(this) {
- state_for_service_worker_ = std::make_unique<ProviderStateForServiceWorker>();
-
container_host_.Bind(std::move(host_ptr_info));
}
ServiceWorkerProviderContext::~ServiceWorkerProviderContext() = default;
-void ServiceWorkerProviderContext::SetRegistrationForServiceWorkerGlobalScope(
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration) {
- DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
- ProviderStateForServiceWorker* state = state_for_service_worker_.get();
- DCHECK(state);
- DCHECK(!state->registration);
-
- state->registration = std::move(registration);
-}
-
-scoped_refptr<WebServiceWorkerRegistrationImpl>
-ServiceWorkerProviderContext::TakeRegistrationForServiceWorkerGlobalScope(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
- DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
- provider_type_);
- ProviderStateForServiceWorker* state = state_for_service_worker_.get();
- DCHECK(state);
- DCHECK(state->registration);
- DCHECK(state->registration->host_ptr_info.is_valid());
- DCHECK_NE(state->registration->registration_id,
- blink::mojom::kInvalidServiceWorkerRegistrationId);
-
- DCHECK(state->registration->request.is_pending());
- scoped_refptr<WebServiceWorkerRegistrationImpl> registration =
- WebServiceWorkerRegistrationImpl::CreateForServiceWorkerGlobalScope(
- std::move(state->registration), std::move(io_task_runner));
- return registration;
-}
-
blink::mojom::ServiceWorkerObjectInfoPtr
ServiceWorkerProviderContext::TakeController() {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
@@ -200,7 +158,7 @@ ServiceWorkerProviderContext::GetSubresourceLoaderFactory() {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
if (!state->subresource_loader_factory) {
ServiceWorkerSubresourceLoaderFactory::Create(
- state->controller_connector, state->default_loader_factory,
+ state->controller_connector, state->fallback_loader_factory,
mojo::MakeRequest(&state->subresource_loader_factory));
}
return state->subresource_loader_factory.get();
@@ -219,6 +177,11 @@ ServiceWorkerProviderContext::used_features() const {
return state_for_client_->used_features;
}
+const std::string& ServiceWorkerProviderContext::client_id() const {
+ DCHECK(state_for_client_);
+ return state_for_client_->client_id;
+}
+
void ServiceWorkerProviderContext::SetWebServiceWorkerProvider(
base::WeakPtr<WebServiceWorkerProviderImpl> provider) {
DCHECK(state_for_client_);
@@ -249,30 +212,38 @@ ServiceWorkerProviderContext::CloneContainerHostPtrInfo() {
}
scoped_refptr<WebServiceWorkerRegistrationImpl>
-ServiceWorkerProviderContext::GetOrCreateRegistrationForServiceWorkerClient(
+ServiceWorkerProviderContext::GetOrCreateServiceWorkerRegistrationObject(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info) {
DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForWindow,
provider_type_);
DCHECK(state_for_client_);
- ServiceWorkerDispatcher* dispatcher =
- ServiceWorkerDispatcher::GetThreadSpecificInstance();
- DCHECK(dispatcher);
auto found = state_for_client_->registrations_.find(info->registration_id);
if (found != state_for_client_->registrations_.end()) {
- DCHECK(!info->request.is_pending());
found->second->AttachForServiceWorkerClient(std::move(info));
return found->second;
}
- DCHECK(info->request.is_pending());
- // WebServiceWorkerRegistrationImpl constructor calls
- // AddServiceWorkerRegistration to add itself into
- // |state_for_client_->registrations_|.
- scoped_refptr<WebServiceWorkerRegistrationImpl> registration =
- WebServiceWorkerRegistrationImpl::CreateForServiceWorkerClient(
- std::move(info), weak_factory_.GetWeakPtr());
- return registration;
+ return WebServiceWorkerRegistrationImpl::CreateForServiceWorkerClient(
+ std::move(info), weak_factory_.GetWeakPtr());
+}
+
+scoped_refptr<WebServiceWorkerImpl>
+ServiceWorkerProviderContext::GetOrCreateServiceWorkerObject(
+ blink::mojom::ServiceWorkerObjectInfoPtr info) {
+ DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForWindow,
+ provider_type_);
+ DCHECK(state_for_client_);
+ if (!info)
+ return nullptr;
+
+ auto found = state_for_client_->workers_.find(info->version_id);
+ if (found != state_for_client_->workers_.end()) {
+ return found->second;
+ }
+
+ return WebServiceWorkerImpl::CreateForServiceWorkerClient(
+ std::move(info), weak_factory_.GetWeakPtr());
}
void ServiceWorkerProviderContext::OnNetworkProviderDestroyed() {
@@ -310,11 +281,13 @@ void ServiceWorkerProviderContext::SetController(
state->controller_version_id =
state->controller ? state->controller->version_id
: blink::mojom::kInvalidServiceWorkerVersionId;
+ // The client id should never change once set.
+ DCHECK(state->client_id.empty() ||
+ state->client_id == controller_info->client_id);
+ state->client_id = controller_info->client_id;
// Propagate the controller to workers related to this provider.
if (state->controller) {
- DCHECK_NE(blink::mojom::kInvalidServiceWorkerHandleId,
- state->controller->handle_id);
DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId,
state->controller->version_id);
for (const auto& worker : state->worker_clients) {
@@ -346,8 +319,7 @@ void ServiceWorkerProviderContext::SetController(
// factory (this part is inherently racy).
state->controller_connector->ResetControllerConnection(
mojom::ControllerServiceWorkerPtr(
- std::move(controller_info->endpoint)),
- controller_info->client_id);
+ std::move(controller_info->endpoint)));
} else if (state->controller) {
// Case (C): never had a controller, but got a new one now.
// Set a new |state->controller_connector| so that subsequent resource
@@ -385,7 +357,7 @@ void ServiceWorkerProviderContext::PostMessageToClient(
}
}
-void ServiceWorkerProviderContext::AddServiceWorkerRegistration(
+void ServiceWorkerProviderContext::AddServiceWorkerRegistrationObject(
int64_t registration_id,
WebServiceWorkerRegistrationImpl* registration) {
DCHECK(state_for_client_);
@@ -394,19 +366,40 @@ void ServiceWorkerProviderContext::AddServiceWorkerRegistration(
state_for_client_->registrations_[registration_id] = registration;
}
-void ServiceWorkerProviderContext::RemoveServiceWorkerRegistration(
+void ServiceWorkerProviderContext::RemoveServiceWorkerRegistrationObject(
int64_t registration_id) {
DCHECK(state_for_client_);
DCHECK(base::ContainsKey(state_for_client_->registrations_, registration_id));
state_for_client_->registrations_.erase(registration_id);
}
-bool ServiceWorkerProviderContext::ContainsServiceWorkerRegistrationForTesting(
- int64_t registration_id) {
+bool ServiceWorkerProviderContext::
+ ContainsServiceWorkerRegistrationObjectForTesting(int64_t registration_id) {
DCHECK(state_for_client_);
return base::ContainsKey(state_for_client_->registrations_, registration_id);
}
+void ServiceWorkerProviderContext::AddServiceWorkerObject(
+ int64_t version_id,
+ WebServiceWorkerImpl* worker) {
+ DCHECK(state_for_client_);
+ DCHECK(!base::ContainsKey(state_for_client_->workers_, version_id));
+ state_for_client_->workers_[version_id] = worker;
+}
+
+void ServiceWorkerProviderContext::RemoveServiceWorkerObject(
+ int64_t version_id) {
+ DCHECK(state_for_client_);
+ DCHECK(base::ContainsKey(state_for_client_->workers_, version_id));
+ state_for_client_->workers_.erase(version_id);
+}
+
+bool ServiceWorkerProviderContext::ContainsServiceWorkerObjectForTesting(
+ int64_t version_id) {
+ DCHECK(state_for_client_);
+ return base::ContainsKey(state_for_client_->workers_, version_id);
+}
+
void ServiceWorkerProviderContext::CountFeature(
blink::mojom::WebFeature feature) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
@@ -425,10 +418,9 @@ void ServiceWorkerProviderContext::CountFeature(
bool ServiceWorkerProviderContext::CanCreateSubresourceLoaderFactory() const {
// Expected that it is called only for clients.
DCHECK(state_for_client_);
- // |state_for_client_->default_loader_factory| could be null
- // in unit tests.
+ // |state_for_client_->fallback_loader_factory| could be null in unit tests.
return (ServiceWorkerUtils::IsServicificationEnabled() &&
- state_for_client_->default_loader_factory);
+ state_for_client_->fallback_loader_factory);
}
void ServiceWorkerProviderContext::DestructOnMainThread() const {
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_context.h b/chromium/content/renderer/service_worker/service_worker_provider_context.h
index aa6858d76a9..19fec07789a 100644
--- a/chromium/content/renderer/service_worker/service_worker_provider_context.h
+++ b/chromium/content/renderer/service_worker/service_worker_provider_context.h
@@ -37,6 +37,7 @@ namespace service_worker_provider_context_unittest {
class ServiceWorkerProviderContextTest;
} // namespace service_worker_provider_context_unittest
+class WebServiceWorkerImpl;
class WebServiceWorkerRegistrationImpl;
struct ServiceWorkerProviderContextDeleter;
@@ -46,11 +47,6 @@ struct ServiceWorkerProviderContextDeleter;
// the same underlying entity hold strong references to a shared instance of
// this class.
//
-// A service worker provider may exist for either a service worker client or a
-// service worker itself. Therefore, this class has different roles depending on
-// its provider type. See the implementation of ProviderStateForClient and
-// ProviderStateForServiceWorker for details.
-//
// Created and destructed on the main thread. Unless otherwise noted, all
// methods are called on the main thread.
class CONTENT_EXPORT ServiceWorkerProviderContext
@@ -65,22 +61,21 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
// the content::ServiceWorkerProviderHost that notifies of changes to the
// registration's and workers' status. |request| is bound with |binding_|.
//
- // For S13nServiceWorker/NavigationMojoResponse:
// |controller_info| contains the endpoint (which is non-null only when
// S13nServiceWorker is enabled) and object info that is needed to set up the
// controller service worker for the client.
// For S13nServiceWorker:
- // |default_loader_factory| is a default loader factory for network requests,
- // and is used when we create a subresource loader for controllees. This is
- // non-null only if the provider is created for controllees, and if the
- // loading context, e.g. a frame, provides it.
+ // |fallback_loader_factory| is a default loader factory for fallback
+ // requests, and is used when we create a subresource loader for controllees.
+ // This is non-null only if the provider is created for controllees, and if
+ // the loading context, e.g. a frame, provides it.
ServiceWorkerProviderContext(
int provider_id,
blink::mojom::ServiceWorkerProviderType provider_type,
mojom::ServiceWorkerContainerAssociatedRequest request,
mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info,
mojom::ControllerServiceWorkerInfoPtr controller_info,
- scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
// Constructor for service worker execution contexts.
ServiceWorkerProviderContext(
@@ -107,11 +102,9 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
// ServiceWorkerGlobalScope#registration. Called on the worker thread.
// This takes the registration that was passed to
// SetRegistrationForServiceWorkerScope(), then creates a new
- // WebServiceWorkerRegistrationImpl instance and returns it. |io_task_runner|
- // is used to initialize WebServiceWorkerRegistrationImpl.
+ // WebServiceWorkerRegistrationImpl instance and returns it.
scoped_refptr<WebServiceWorkerRegistrationImpl>
- TakeRegistrationForServiceWorkerGlobalScope(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+ TakeRegistrationForServiceWorkerGlobalScope();
// For service worker clients. Returns version id of the controller service
// worker object (ServiceWorkerContainer#controller).
@@ -130,6 +123,10 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
// For service worker clients. Returns the feature usage of its controller.
const std::set<blink::mojom::WebFeature>& used_features() const;
+ // S13nServiceWorker:
+ // The Client#id value of the client.
+ const std::string& client_id() const;
+
// For service worker clients. Sets a weak pointer back to the
// WebServiceWorkerProviderImpl (which corresponds to ServiceWorkerContainer
// in JavaScript) which has a strong reference to |this|. This allows us to
@@ -159,9 +156,14 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
// For service worker clients. Returns the registration object described by
// |info|. Creates a new object if needed, or else returns the existing one.
scoped_refptr<WebServiceWorkerRegistrationImpl>
- GetOrCreateRegistrationForServiceWorkerClient(
+ GetOrCreateServiceWorkerRegistrationObject(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info);
+ // For service worker clients. Returns the service worker object described by
+ // |info|. Creates a new object if needed, or else returns the existing one.
+ scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorkerObject(
+ blink::mojom::ServiceWorkerObjectInfoPtr info);
+
// Called when ServiceWorkerNetworkProvider is destructed. This function
// severs the Mojo binding to the browser-side ServiceWorkerProviderHost. The
// reason ServiceWorkerNetworkProvider is special compared to the other
@@ -189,10 +191,10 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
ServiceWorkerProviderContextDeleter>;
friend class service_worker_provider_context_unittest::
ServiceWorkerProviderContextTest;
+ friend class WebServiceWorkerImpl;
friend class WebServiceWorkerRegistrationImpl;
friend struct ServiceWorkerProviderContextDeleter;
struct ProviderStateForClient;
- struct ProviderStateForServiceWorker;
~ServiceWorkerProviderContext() override;
void DestructOnMainThread() const;
@@ -211,11 +213,18 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
// For service worker clients. Keeps the mapping from registration_id to
// ServiceWorkerRegistration object.
- void AddServiceWorkerRegistration(
+ void AddServiceWorkerRegistrationObject(
int64_t registration_id,
WebServiceWorkerRegistrationImpl* registration);
- void RemoveServiceWorkerRegistration(int64_t registration_id);
- bool ContainsServiceWorkerRegistrationForTesting(int64_t registration_id);
+ void RemoveServiceWorkerRegistrationObject(int64_t registration_id);
+ bool ContainsServiceWorkerRegistrationObjectForTesting(
+ int64_t registration_id);
+
+ // For service worker clients. Keeps the mapping from version id to
+ // ServiceWorker object.
+ void AddServiceWorkerObject(int64_t version_id, WebServiceWorkerImpl* worker);
+ void RemoveServiceWorkerObject(int64_t version_id);
+ bool ContainsServiceWorkerObjectForTesting(int64_t version_id);
// S13nServiceWorker:
// For service worker clients.
@@ -243,14 +252,11 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
// Note: Currently this is always bound on main thread.
mojom::ServiceWorkerContainerHostAssociatedPtr container_host_;
- // Either |state_for_client_| or |state_for_service_worker_| is non-null.
// State for service worker clients.
std::unique_ptr<ProviderStateForClient> state_for_client_;
- // State for service workers.
- std::unique_ptr<ProviderStateForServiceWorker> state_for_service_worker_;
- // NOTE: New members should usually be added to either
- // |state_for_service_worker_| or |state_for_client_|. Not here!
+ // NOTE: Add new members to |state_for_client_| if they are relevant only for
+ // service worker clients. Not here!
base::WeakPtrFactory<ServiceWorkerProviderContext> weak_factory_;
diff --git a/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc
index 8f4a26f9865..7c73ae07a8a 100644
--- a/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc
+++ b/chromium/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -14,11 +14,9 @@
#include "content/common/service_worker/service_worker_container.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/content_features.h"
#include "content/public/common/resource_type.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
@@ -26,6 +24,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -34,7 +33,6 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_feature.mojom.h"
namespace content {
@@ -43,15 +41,15 @@ namespace service_worker_provider_context_unittest {
class MockServiceWorkerObjectHost
: public blink::mojom::ServiceWorkerObjectHost {
public:
- MockServiceWorkerObjectHost(int32_t handle_id, int64_t version_id)
- : handle_id_(handle_id), version_id_(version_id) {}
+ explicit MockServiceWorkerObjectHost(int64_t version_id)
+ : version_id_(version_id) {}
~MockServiceWorkerObjectHost() override = default;
blink::mojom::ServiceWorkerObjectInfoPtr CreateObjectInfo() {
auto info = blink::mojom::ServiceWorkerObjectInfo::New();
- info->handle_id = handle_id_;
info->version_id = version_id_;
bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
+ info->request = mojo::MakeRequest(&remote_object_);
return info;
}
@@ -67,9 +65,9 @@ class MockServiceWorkerObjectHost
NOTREACHED();
}
- int32_t handle_id_;
- int64_t version_id_;
+ const int64_t version_id_;
mojo::AssociatedBindingSet<blink::mojom::ServiceWorkerObjectHost> bindings_;
+ blink::mojom::ServiceWorkerObjectAssociatedPtr remote_object_;
};
class MockServiceWorkerRegistrationObjectHost
@@ -90,9 +88,7 @@ class MockServiceWorkerRegistrationObjectHost
auto info = blink::mojom::ServiceWorkerRegistrationObjectInfo::New();
info->registration_id = registration_id_;
bindings_.AddBinding(this, mojo::MakeRequest(&info->host_ptr_info));
- info->request = remote_registration_
- ? nullptr
- : mojo::MakeRequest(&remote_registration_);
+ info->request = mojo::MakeRequest(&remote_registration_);
info->active = active->CreateObjectInfo();
info->waiting = waiting->CreateObjectInfo();
@@ -263,17 +259,14 @@ class ServiceWorkerProviderContextTest : public testing::Test {
public:
ServiceWorkerProviderContextTest() = default;
- void SetUp() override {
- dispatcher_ = std::make_unique<ServiceWorkerDispatcher>();
- }
-
void EnableS13nServiceWorker() {
scoped_feature_list_.InitAndEnableFeature(
network::features::kNetworkService);
network::mojom::URLLoaderFactoryPtr fake_loader_factory;
fake_loader_factory_.AddBinding(MakeRequest(&fake_loader_factory));
- loader_factory_ = base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
- std::move(fake_loader_factory));
+ loader_factory_ =
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(fake_loader_factory));
}
void StartRequest(network::mojom::URLLoaderFactory* factory,
@@ -293,13 +286,17 @@ class ServiceWorkerProviderContextTest : public testing::Test {
bool ContainsRegistration(ServiceWorkerProviderContext* provider_context,
int64_t registration_id) {
- return provider_context->ContainsServiceWorkerRegistrationForTesting(
+ return provider_context->ContainsServiceWorkerRegistrationObjectForTesting(
registration_id);
}
+ bool ContainsServiceWorker(ServiceWorkerProviderContext* provider_context,
+ int64_t version_id) {
+ return provider_context->ContainsServiceWorkerObjectForTesting(version_id);
+ }
+
protected:
base::MessageLoop message_loop_;
- std::unique_ptr<ServiceWorkerDispatcher> dispatcher_;
// S13nServiceWorker:
base::test::ScopedFeatureList scoped_feature_list_;
@@ -309,60 +306,12 @@ class ServiceWorkerProviderContextTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderContextTest);
};
-TEST_F(ServiceWorkerProviderContextTest,
- CreateForServiceWorkerExecutionContext) {
- auto active_host = std::make_unique<MockServiceWorkerObjectHost>(
- 100 /* handle_id */, 200 /* version_id */);
- auto waiting_host = std::make_unique<MockServiceWorkerObjectHost>(
- 101 /* handle_id */, 201 /* version_id */);
- auto installing_host = std::make_unique<MockServiceWorkerObjectHost>(
- 102 /* handle_id */, 202 /* version_id */);
- ASSERT_EQ(0, active_host->GetBindingCount());
- ASSERT_EQ(0, waiting_host->GetBindingCount());
- ASSERT_EQ(0, installing_host->GetBindingCount());
- auto mock_registration_object_host =
- std::make_unique<MockServiceWorkerRegistrationObjectHost>(
- 10 /* registration_id */);
- ASSERT_EQ(0, mock_registration_object_host->GetBindingCount());
-
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info =
- mock_registration_object_host->CreateObjectInfo(
- active_host.get(), waiting_host.get(), installing_host.get());
- // ServiceWorkerRegistrationObjectHost Mojo connection has been added.
- EXPECT_EQ(1, mock_registration_object_host->GetBindingCount());
- // ServiceWorkerObjectHost Mojo connections have been added.
- EXPECT_EQ(1, active_host->GetBindingCount());
- EXPECT_EQ(1, waiting_host->GetBindingCount());
- EXPECT_EQ(1, installing_host->GetBindingCount());
-
- // Set up ServiceWorkerProviderContext for ServiceWorkerGlobalScope.
- const int kProviderId = 10;
- auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
- kProviderId, nullptr, nullptr);
-
- // The passed references should be adopted and owned by the provider context.
- provider_context->SetRegistrationForServiceWorkerGlobalScope(
- std::move(registration_info));
-
- // Destruction of the provider context should release references to the
- // associated registration and its versions.
- provider_context = nullptr;
- base::RunLoop().RunUntilIdle();
- // ServiceWorkerRegistrationObjectHost Mojo connection got broken.
- EXPECT_EQ(0, mock_registration_object_host->GetBindingCount());
- // ServiceWorkerObjectHost Mojo connections got broken.
- EXPECT_EQ(0, active_host->GetBindingCount());
- EXPECT_EQ(0, waiting_host->GetBindingCount());
- EXPECT_EQ(0, installing_host->GetBindingCount());
-}
-
TEST_F(ServiceWorkerProviderContextTest, SetController) {
const int kProviderId = 10;
{
auto mock_service_worker_object_host =
- std::make_unique<MockServiceWorkerObjectHost>(100 /* handle_id */,
- 200 /* version_id */);
+ std::make_unique<MockServiceWorkerObjectHost>(200 /* version_id */);
ASSERT_EQ(0, mock_service_worker_object_host->GetBindingCount());
blink::mojom::ServiceWorkerObjectInfoPtr object_info =
mock_service_worker_object_host->CreateObjectInfo();
@@ -395,8 +344,7 @@ TEST_F(ServiceWorkerProviderContextTest, SetController) {
{
auto mock_service_worker_object_host =
- std::make_unique<MockServiceWorkerObjectHost>(101 /* handle_id */,
- 201 /* version_id */);
+ std::make_unique<MockServiceWorkerObjectHost>(201 /* version_id */);
ASSERT_EQ(0, mock_service_worker_object_host->GetBindingCount());
blink::mojom::ServiceWorkerObjectInfoPtr object_info =
mock_service_worker_object_host->CreateObjectInfo();
@@ -472,8 +420,8 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
const int kProviderId = 10;
// (1) Test if setting the controller via the CTOR works.
- auto object_host1 = std::make_unique<MockServiceWorkerObjectHost>(
- 100 /* handle_id */, 200 /* version_id */);
+ auto object_host1 =
+ std::make_unique<MockServiceWorkerObjectHost>(200 /* version_id */);
ASSERT_EQ(0, object_host1->GetBindingCount());
blink::mojom::ServiceWorkerObjectInfoPtr object_info1 =
object_host1->CreateObjectInfo();
@@ -507,8 +455,8 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
// (2) Test if resetting the controller to a new one via SetController
// works.
- auto object_host2 = std::make_unique<MockServiceWorkerObjectHost>(
- 101 /* handle_id */, 201 /* version_id */);
+ auto object_host2 =
+ std::make_unique<MockServiceWorkerObjectHost>(201 /* version_id */);
ASSERT_EQ(0, object_host2->GetBindingCount());
blink::mojom::ServiceWorkerObjectInfoPtr object_info2 =
object_host2->CreateObjectInfo();
@@ -568,8 +516,8 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) {
// (4) Test if resetting the controller to yet another one via SetController
// works.
- auto object_host4 = std::make_unique<MockServiceWorkerObjectHost>(
- 102 /* handle_id */, 202 /* version_id */);
+ auto object_host4 =
+ std::make_unique<MockServiceWorkerObjectHost>(202 /* version_id */);
ASSERT_EQ(0, object_host4->GetBindingCount());
blink::mojom::ServiceWorkerObjectInfoPtr object_info4 =
object_host4->CreateObjectInfo();
@@ -606,8 +554,7 @@ TEST_F(ServiceWorkerProviderContextTest, PostMessageToClient) {
const int kProviderId = 10;
auto mock_service_worker_object_host =
- std::make_unique<MockServiceWorkerObjectHost>(100 /* handle_id */,
- 200 /* version_id */);
+ std::make_unique<MockServiceWorkerObjectHost>(200 /* version_id */);
ASSERT_EQ(0, mock_service_worker_object_host->GetBindingCount());
blink::mojom::ServiceWorkerObjectInfoPtr object_info =
mock_service_worker_object_host->CreateObjectInfo();
@@ -675,77 +622,21 @@ TEST_F(ServiceWorkerProviderContextTest, CountFeature) {
*(++(client->used_features().begin())));
}
-TEST_F(ServiceWorkerProviderContextTest,
- SetAndTakeRegistrationForServiceWorkerGlobalScope) {
- // Set up ServiceWorkerProviderContext for ServiceWorkerGlobalScope.
- const int kProviderId = 10;
- auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
- kProviderId, nullptr, nullptr);
-
- auto active_host = std::make_unique<MockServiceWorkerObjectHost>(
- 100 /* handle_id */, 200 /* version_id */);
- auto waiting_host = std::make_unique<MockServiceWorkerObjectHost>(
- 101 /* handle_id */, 201 /* version_id */);
- auto installing_host = std::make_unique<MockServiceWorkerObjectHost>(
- 102 /* handle_id */, 202 /* version_id */);
- ASSERT_EQ(0, active_host->GetBindingCount());
- ASSERT_EQ(0, waiting_host->GetBindingCount());
- ASSERT_EQ(0, installing_host->GetBindingCount());
- const int64_t registration_id = 10;
- auto mock_registration_object_host =
- std::make_unique<MockServiceWorkerRegistrationObjectHost>(
- registration_id);
- ASSERT_EQ(0, mock_registration_object_host->GetBindingCount());
-
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info =
- mock_registration_object_host->CreateObjectInfo(
- active_host.get(), waiting_host.get(), installing_host.get());
- // ServiceWorkerRegistrationObjectHost Mojo connection has been added.
- EXPECT_EQ(1, mock_registration_object_host->GetBindingCount());
- // ServiceWorkerObjectHost Mojo connections have been added.
- EXPECT_EQ(1, active_host->GetBindingCount());
- EXPECT_EQ(1, waiting_host->GetBindingCount());
- EXPECT_EQ(1, installing_host->GetBindingCount());
-
- provider_context->SetRegistrationForServiceWorkerGlobalScope(
- std::move(registration_info));
-
- // Should return a newly created registration object which adopts all
- // references to the remote instances of ServiceWorkerRegistrationObjectHost
- // and ServiceWorkerHandle in the browser process.
- scoped_refptr<WebServiceWorkerRegistrationImpl> registration =
- provider_context->TakeRegistrationForServiceWorkerGlobalScope(
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- EXPECT_TRUE(registration);
- EXPECT_EQ(registration_id, registration->RegistrationId());
- EXPECT_EQ(1, mock_registration_object_host->GetBindingCount());
-
- // The registration dtor decrements the refcounts.
- registration = nullptr;
- base::RunLoop().RunUntilIdle();
- // ServiceWorkerRegistrationObjectHost Mojo connection got broken.
- EXPECT_EQ(0, mock_registration_object_host->GetBindingCount());
- // ServiceWorkerObjectHost Mojo connections got broken.
- EXPECT_EQ(0, active_host->GetBindingCount());
- EXPECT_EQ(0, waiting_host->GetBindingCount());
- EXPECT_EQ(0, installing_host->GetBindingCount());
-}
-
-TEST_F(ServiceWorkerProviderContextTest, GetOrAdoptRegistration) {
+TEST_F(ServiceWorkerProviderContextTest, GetOrCreateRegistration) {
scoped_refptr<WebServiceWorkerRegistrationImpl> registration1;
scoped_refptr<WebServiceWorkerRegistrationImpl> registration2;
- // Set up ServiceWorkerProviderContext for ServiceWorkerGlobalScope.
+ // Set up ServiceWorkerProviderContext for client contexts.
const int kProviderId = 10;
auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
kProviderId, blink::mojom::ServiceWorkerProviderType::kForWindow, nullptr,
nullptr, nullptr /* controller_info */, nullptr /* loader_factory*/);
- auto active_host = std::make_unique<MockServiceWorkerObjectHost>(
- 100 /* handle_id */, 200 /* version_id */);
- auto waiting_host = std::make_unique<MockServiceWorkerObjectHost>(
- 101 /* handle_id */, 201 /* version_id */);
- auto installing_host = std::make_unique<MockServiceWorkerObjectHost>(
- 102 /* handle_id */, 202 /* version_id */);
+ auto active_host =
+ std::make_unique<MockServiceWorkerObjectHost>(200 /* version_id */);
+ auto waiting_host =
+ std::make_unique<MockServiceWorkerObjectHost>(201 /* version_id */);
+ auto installing_host =
+ std::make_unique<MockServiceWorkerObjectHost>(202 /* version_id */);
ASSERT_EQ(0, active_host->GetBindingCount());
ASSERT_EQ(0, waiting_host->GetBindingCount());
ASSERT_EQ(0, installing_host->GetBindingCount());
@@ -770,7 +661,7 @@ TEST_F(ServiceWorkerProviderContextTest, GetOrAdoptRegistration) {
// Should return a registration object newly created with adopting the
// refcounts.
registration1 =
- provider_context->GetOrCreateRegistrationForServiceWorkerClient(
+ provider_context->GetOrCreateServiceWorkerRegistrationObject(
std::move(registration_info));
EXPECT_TRUE(registration1);
EXPECT_TRUE(ContainsRegistration(provider_context.get(), registration_id));
@@ -792,7 +683,7 @@ TEST_F(ServiceWorkerProviderContextTest, GetOrAdoptRegistration) {
// Should return the same registration object without incrementing the
// refcounts.
registration2 =
- provider_context->GetOrCreateRegistrationForServiceWorkerClient(
+ provider_context->GetOrCreateServiceWorkerRegistrationObject(
std::move(registration_info));
EXPECT_TRUE(registration2);
EXPECT_EQ(registration1, registration2);
@@ -820,5 +711,60 @@ TEST_F(ServiceWorkerProviderContextTest, GetOrAdoptRegistration) {
EXPECT_EQ(0, installing_host->GetBindingCount());
}
+TEST_F(ServiceWorkerProviderContextTest, GetOrCreateServiceWorker) {
+ scoped_refptr<WebServiceWorkerImpl> worker1;
+ scoped_refptr<WebServiceWorkerImpl> worker2;
+ // Set up ServiceWorkerProviderContext for client contexts.
+ const int kProviderId = 10;
+ auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
+ kProviderId, blink::mojom::ServiceWorkerProviderType::kForWindow, nullptr,
+ nullptr, nullptr /* controller_info */, nullptr /* loader_factory*/);
+ const int64_t version_id = 200;
+ auto mock_service_worker_object_host =
+ std::make_unique<MockServiceWorkerObjectHost>(version_id);
+ ASSERT_EQ(0, mock_service_worker_object_host->GetBindingCount());
+
+ // Should return a worker object newly created with the 1st given |info|.
+ {
+ blink::mojom::ServiceWorkerObjectInfoPtr info =
+ mock_service_worker_object_host->CreateObjectInfo();
+ // ServiceWorkerObjectHost Mojo connection has been added.
+ EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
+ ASSERT_FALSE(ContainsServiceWorker(provider_context.get(), version_id));
+ worker1 = provider_context->GetOrCreateServiceWorkerObject(std::move(info));
+ EXPECT_TRUE(worker1);
+ EXPECT_TRUE(ContainsServiceWorker(provider_context.get(), version_id));
+ // |worker1| is holding the 1st blink::mojom::ServiceWorkerObjectHost Mojo
+ // connection to |mock_service_worker_object_host|.
+ EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
+ }
+
+ // Should return the same worker object and release the 2nd given |info|.
+ {
+ blink::mojom::ServiceWorkerObjectInfoPtr info =
+ mock_service_worker_object_host->CreateObjectInfo();
+ EXPECT_EQ(2, mock_service_worker_object_host->GetBindingCount());
+ worker2 = provider_context->GetOrCreateServiceWorkerObject(std::move(info));
+ EXPECT_EQ(worker1, worker2);
+ base::RunLoop().RunUntilIdle();
+ // The 2nd ServiceWorkerObjectHost Mojo connection in |info| has been
+ // dropped.
+ EXPECT_EQ(1, mock_service_worker_object_host->GetBindingCount());
+ }
+
+ // The dtor decrements the refcounts.
+ worker1 = nullptr;
+ worker2 = nullptr;
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(ContainsServiceWorker(provider_context.get(), version_id));
+ // The 1st ServiceWorkerObjectHost Mojo connection got broken.
+ EXPECT_EQ(0, mock_service_worker_object_host->GetBindingCount());
+
+ // Should return nullptr when given nullptr.
+ scoped_refptr<WebServiceWorkerImpl> invalid_worker =
+ provider_context->GetOrCreateServiceWorkerObject(nullptr);
+ EXPECT_FALSE(invalid_worker);
+}
+
} // namespace service_worker_provider_context_unittest
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
index ee599353680..07c74494a64 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -6,17 +6,27 @@
#include "base/atomic_sequence_num.h"
#include "base/callback.h"
+#include "base/feature_list.h"
#include "base/optional.h"
#include "content/common/service_worker/service_worker_loader_helpers.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_features.h"
+#include "content/renderer/loader/web_url_request_util.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/service_worker/controller_service_worker_connector.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/url_request.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/web_http_body.h"
+#include "third_party/blink/public/platform/web_string.h"
#include "ui/base/page_transition_types.h"
namespace content {
@@ -142,7 +152,7 @@ ServiceWorkerSubresourceLoader::ServiceWorkerSubresourceLoader(
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory)
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory)
: redirect_limit_(net::URLRequest::kMaxRedirects),
url_loader_client_(std::move(client)),
url_loader_binding_(this, std::move(request)),
@@ -154,7 +164,7 @@ ServiceWorkerSubresourceLoader::ServiceWorkerSubresourceLoader(
options_(options),
traffic_annotation_(traffic_annotation),
resource_request_(resource_request),
- network_loader_factory_(std::move(network_loader_factory)),
+ fallback_factory_(std::move(fallback_factory)),
weak_factory_(this) {
DCHECK(controller_connector_);
response_head_.request_start = base::TimeTicks::Now();
@@ -214,7 +224,7 @@ void ServiceWorkerSubresourceLoader::DispatchFetchEvent() {
ControllerServiceWorkerConnector::State::kNoController) {
// The controller was lost after this loader or its loader factory was
// created.
- network_loader_factory_->CreateLoaderAndStart(
+ fallback_factory_->CreateLoaderAndStart(
url_loader_binding_.Unbind(), routing_id_, request_id_, options_,
resource_request_, std::move(url_loader_client_),
traffic_annotation_);
@@ -227,31 +237,23 @@ void ServiceWorkerSubresourceLoader::DispatchFetchEvent() {
return;
}
- // TODO(kinuko): Implement request timeout and ask the browser to kill
- // the controller if it takes too long. (crbug.com/774374)
-
- // Passing the request body over Mojo moves it out. But the request body
- // may be needed later, in the case where the service worker doesn't provide a
- // response in the fetch event. So instead send a cloned body. (Note that
- // we can't do the reverse, i.e., send the original and restore the clone
- // later. By always sending the clone, we ensure the original ResourceRequest
- // passed into the constructor always points to a valid ResourceRequestBody,
- // even if this loader gets destructed.)
- if (resource_request_.request_body) {
- inflight_fetch_request_->request_body =
- ServiceWorkerLoaderHelpers::CloneResourceRequestBody(
- resource_request_.request_body.get());
- }
-
auto params = mojom::DispatchFetchEventParams::New();
params->request = *inflight_fetch_request_;
params->client_id = controller_connector_->client_id();
+
+ // S13nServiceWorker without NetworkService:
+ // BlobPtr for each blob data element in the request body needs to be created
+ // before dispatching the fetch event for keeping the blob alive.
+ if (resource_request_.request_body &&
+ !base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+ params->request_body_blob_ptrs =
+ GetBlobPtrsForRequestBody(*resource_request_.request_body);
+ }
+
controller->DispatchFetchEvent(
std::move(params), std::move(response_callback_ptr),
base::BindOnce(&ServiceWorkerSubresourceLoader::OnFetchEventFinished,
weak_factory_.GetWeakPtr()));
- // |inflight_fetch_request_->request_body| should not be used after this
- // point.
}
void ServiceWorkerSubresourceLoader::OnFetchEventFinished(
@@ -342,8 +344,6 @@ void ServiceWorkerSubresourceLoader::OnResponseStream(
void ServiceWorkerSubresourceLoader::OnFallback(
base::Time dispatch_event_time) {
SettleInflightFetchRequestIfNeeded();
- DCHECK(network_loader_factory_);
-
// When the request mode is CORS or CORS-with-forced-preflight and the origin
// of the request URL is different from the security origin of the document,
// we can't simply fallback to the network here. It is because the CORS
@@ -372,11 +372,17 @@ void ServiceWorkerSubresourceLoader::OnFallback(
response_head_.service_worker_ready_time));
mojo::MakeStrongBinding(std::move(client_impl), mojo::MakeRequest(&client));
- network_loader_factory_->CreateLoaderAndStart(
+ fallback_factory_->CreateLoaderAndStart(
url_loader_binding_.Unbind(), routing_id_, request_id_, options_,
resource_request_, std::move(client), traffic_annotation_);
// Per spec, redirects after this point are not intercepted by the service
// worker again (https://crbug.com/517364). So this loader is done.
+ //
+ // Assume ServiceWorkerSubresourceLoaderFactory is still alive and also
+ // has a ref to fallback_factory_, so it's OK to destruct here. If that
+ // factory dies, the web context that made the request is dead so the request
+ // is moot.
+ DCHECK(!fallback_factory_->HasOneRef());
delete this;
}
@@ -472,7 +478,11 @@ void ServiceWorkerSubresourceLoader::CommitCompleted(int error_code) {
// ServiceWorkerSubresourceLoader: URLLoader implementation -----------------
-void ServiceWorkerSubresourceLoader::FollowRedirect() {
+void ServiceWorkerSubresourceLoader::FollowRedirect(
+ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
+ DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
+ "headers was not supported "
+ "yet. crbug.com/845683";
DCHECK(redirect_info_);
bool should_clear_upload = false;
@@ -518,20 +528,20 @@ void ServiceWorkerSubresourceLoader::OnBlobReadingComplete(int net_error) {
// static
void ServiceWorkerSubresourceLoaderFactory::Create(
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
network::mojom::URLLoaderFactoryRequest request) {
new ServiceWorkerSubresourceLoaderFactory(std::move(controller_connector),
- std::move(network_loader_factory),
+ std::move(fallback_factory),
std::move(request));
}
ServiceWorkerSubresourceLoaderFactory::ServiceWorkerSubresourceLoaderFactory(
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
network::mojom::URLLoaderFactoryRequest request)
: controller_connector_(std::move(controller_connector)),
- network_loader_factory_(std::move(network_loader_factory)) {
- DCHECK(network_loader_factory_);
+ fallback_factory_(std::move(fallback_factory)) {
+ DCHECK(fallback_factory_);
bindings_.AddBinding(this, std::move(request));
bindings_.set_connection_error_handler(base::BindRepeating(
&ServiceWorkerSubresourceLoaderFactory::OnConnectionError,
@@ -551,12 +561,12 @@ void ServiceWorkerSubresourceLoaderFactory::CreateLoaderAndStart(
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
// This loader destructs itself, as we want to transparently switch to the
// network loader when fallback happens. When that happens the loader unbinds
- // the request, passes the request to the Network Loader Factory, and
+ // the request, passes the request to the fallback factory, and
// destructs itself (while the loader client continues to work).
- new ServiceWorkerSubresourceLoader(
- std::move(request), routing_id, request_id, options, resource_request,
- std::move(client), traffic_annotation, controller_connector_,
- network_loader_factory_);
+ new ServiceWorkerSubresourceLoader(std::move(request), routing_id, request_id,
+ options, resource_request,
+ std::move(client), traffic_annotation,
+ controller_connector_, fallback_factory_);
}
void ServiceWorkerSubresourceLoaderFactory::Clone(
diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader.h b/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
index c232636340b..f209a0cd3b0 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -51,7 +51,7 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory);
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory);
~ServiceWorkerSubresourceLoader() override;
@@ -89,7 +89,8 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
// network::mojom::URLLoader overrides:
- void FollowRedirect() override;
+ void FollowRedirect(const base::Optional<net::HttpRequestHeaders>&
+ modified_request_headers) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int intra_priority_value) override;
@@ -138,7 +139,7 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
std::unique_ptr<StreamWaiter> stream_waiter_;
// For network fallback.
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory_;
enum class Status {
kNotStarted,
@@ -160,7 +161,7 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader
class CONTENT_EXPORT ServiceWorkerSubresourceLoaderFactory
: public network::mojom::URLLoaderFactory {
public:
- // |controller_connector_| is used to get a connection to the controller
+ // |controller_connector| is used to get a connection to the controller
// ServiceWorker.
// |network_loader_factory| is used to get the associated loading context's
// default URLLoaderFactory for network fallback. This should be the
@@ -168,7 +169,7 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoaderFactory
// any custom URLLoader factories.
static void Create(
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
network::mojom::URLLoaderFactoryRequest request);
~ServiceWorkerSubresourceLoaderFactory() override;
@@ -187,16 +188,15 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoaderFactory
private:
ServiceWorkerSubresourceLoaderFactory(
scoped_refptr<ControllerServiceWorkerConnector> controller_connector,
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory,
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
network::mojom::URLLoaderFactoryRequest request);
void OnConnectionError();
scoped_refptr<ControllerServiceWorkerConnector> controller_connector_;
- // A URLLoaderFactory that directly goes to network, used when a request
- // falls back to network.
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
+ // Used when a request falls back to network.
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory_;
mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
diff --git a/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
index 0c04458d6ad..1dd21ee8447 100644
--- a/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
+++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -9,7 +9,6 @@
#include "base/test/scoped_feature_list.h"
#include "content/common/service_worker/service_worker_container.mojom.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/content_features.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/test_browser_thread_bundle.h"
@@ -22,6 +21,7 @@
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_data_pipe_getter.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -354,14 +354,15 @@ class ServiceWorkerSubresourceLoaderTest : public ::testing::Test {
network::mojom::URLLoaderFactoryPtr fake_loader_factory;
mojo::MakeStrongBinding(std::make_unique<FakeNetworkURLLoaderFactory>(),
MakeRequest(&fake_loader_factory));
- loader_factory_ = base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
- std::move(fake_loader_factory));
+ loader_factory_ =
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(fake_loader_factory));
}
network::mojom::URLLoaderFactoryPtr CreateSubresourceLoaderFactory() {
if (!connector_) {
connector_ = base::MakeRefCounted<ControllerServiceWorkerConnector>(
- &fake_container_host_);
+ &fake_container_host_, nullptr /*controller_ptr*/, "" /*client_id*/);
}
network::mojom::URLLoaderFactoryPtr service_worker_url_loader_factory;
ServiceWorkerSubresourceLoaderFactory::Create(
@@ -569,7 +570,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, NoController) {
}
// Make the connector have no controller.
- connector_->ResetControllerConnection(nullptr, "" /*client_id*/);
+ connector_->ResetControllerConnection(nullptr);
base::RunLoop().RunUntilIdle();
{
@@ -812,7 +813,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) {
// Redirect once more.
fake_controller_.RespondWithRedirect("https://other.example.com/baz.png");
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt);
client->RunUntilRedirectReceived();
EXPECT_EQ(net::OK, client->completion_status().error_code);
@@ -831,7 +832,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) {
mojo::DataPipe data_pipe;
fake_controller_.RespondWithStream(mojo::MakeRequest(&stream_callback),
std::move(data_pipe.consumer_handle));
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt);
client->RunUntilResponseReceived();
const network::ResourceResponseHead& info = client->response_head();
@@ -896,7 +897,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, TooManyRedirects) {
redirect_location = std::string("https://www.example.com/redirect_") +
base::IntToString(count);
fake_controller_.RespondWithRedirect(redirect_location);
- loader->FollowRedirect();
+ loader->FollowRedirect(base::nullopt);
}
client->RunUntilComplete();
diff --git a/chromium/content/renderer/service_worker/service_worker_type_converters.cc b/chromium/content/renderer/service_worker/service_worker_type_converters.cc
index 4832ec4467d..3065d0e543e 100644
--- a/chromium/content/renderer/service_worker/service_worker_type_converters.cc
+++ b/chromium/content/renderer/service_worker/service_worker_type_converters.cc
@@ -14,8 +14,7 @@ TypeConverter<blink::WebCanMakePaymentEventData,
Convert(const payments::mojom::CanMakePaymentEventDataPtr& input) {
blink::WebCanMakePaymentEventData output;
- output.top_level_origin =
- blink::WebString::FromUTF8(input->top_level_origin.spec());
+ output.top_origin = blink::WebString::FromUTF8(input->top_origin.spec());
output.payment_request_origin =
blink::WebString::FromUTF8(input->payment_request_origin.spec());
@@ -42,8 +41,7 @@ TypeConverter<blink::WebPaymentRequestEventData,
Convert(const payments::mojom::PaymentRequestEventDataPtr& input) {
blink::WebPaymentRequestEventData output;
- output.top_level_origin =
- blink::WebString::FromUTF8(input->top_level_origin.spec());
+ output.top_origin = blink::WebString::FromUTF8(input->top_origin.spec());
output.payment_request_origin =
blink::WebString::FromUTF8(input->payment_request_origin.spec());
output.payment_request_id =
@@ -106,7 +104,6 @@ TypeConverter<blink::WebPaymentCurrencyAmount,
blink::WebPaymentCurrencyAmount output;
output.currency = blink::WebString::FromUTF8(input->currency);
output.value = blink::WebString::FromUTF8(input->value);
- output.currency_system = blink::WebString::FromUTF8(input->currency_system);
return output;
}
diff --git a/chromium/content/renderer/service_worker/web_service_worker_impl.cc b/chromium/content/renderer/service_worker/web_service_worker_impl.cc
index 268a705f45a..2d3322a6f44 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_impl.cc
+++ b/chromium/content/renderer/service_worker/web_service_worker_impl.cc
@@ -8,7 +8,8 @@
#include "base/macros.h"
#include "content/common/service_worker/service_worker_messages.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
+#include "content/renderer/service_worker/service_worker_context_client.h"
+#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_proxy.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
@@ -45,27 +46,24 @@ void OnTerminated(
// static
scoped_refptr<WebServiceWorkerImpl>
WebServiceWorkerImpl::CreateForServiceWorkerGlobalScope(
- blink::mojom::ServiceWorkerObjectInfoPtr info,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+ blink::mojom::ServiceWorkerObjectInfoPtr info) {
scoped_refptr<WebServiceWorkerImpl> impl =
- new WebServiceWorkerImpl(std::move(info));
- impl->host_for_global_scope_ =
- blink::mojom::ThreadSafeServiceWorkerObjectHostAssociatedPtr::Create(
- std::move(impl->info_->host_ptr_info), io_task_runner);
+ new WebServiceWorkerImpl(std::move(info), nullptr /* provider_context */);
return impl;
}
// static
scoped_refptr<WebServiceWorkerImpl>
WebServiceWorkerImpl::CreateForServiceWorkerClient(
- blink::mojom::ServiceWorkerObjectInfoPtr info) {
+ blink::mojom::ServiceWorkerObjectInfoPtr info,
+ base::WeakPtr<ServiceWorkerProviderContext> provider_context) {
+ DCHECK(provider_context);
scoped_refptr<WebServiceWorkerImpl> impl =
- new WebServiceWorkerImpl(std::move(info));
- impl->host_for_client_.Bind(std::move(impl->info_->host_ptr_info));
+ new WebServiceWorkerImpl(std::move(info), std::move(provider_context));
return impl;
}
-void WebServiceWorkerImpl::OnStateChanged(
+void WebServiceWorkerImpl::StateChanged(
blink::mojom::ServiceWorkerState new_state) {
state_ = new_state;
@@ -93,12 +91,12 @@ blink::mojom::ServiceWorkerState WebServiceWorkerImpl::GetState() const {
void WebServiceWorkerImpl::PostMessageToServiceWorker(
blink::TransferableMessage message) {
- GetObjectHost()->PostMessageToServiceWorker(std::move(message));
+ host_->PostMessageToServiceWorker(std::move(message));
}
void WebServiceWorkerImpl::TerminateForTesting(
std::unique_ptr<TerminateForTestingCallback> callback) {
- GetObjectHost()->TerminateForTesting(
+ host_->TerminateForTesting(
base::BindOnce(&OnTerminated, std::move(callback)));
}
@@ -111,29 +109,37 @@ WebServiceWorkerImpl::CreateHandle(scoped_refptr<WebServiceWorkerImpl> worker) {
}
WebServiceWorkerImpl::WebServiceWorkerImpl(
- blink::mojom::ServiceWorkerObjectInfoPtr info)
- : info_(std::move(info)), state_(info_->state), proxy_(nullptr) {
- DCHECK_NE(blink::mojom::kInvalidServiceWorkerHandleId, info_->handle_id);
- ServiceWorkerDispatcher* dispatcher =
- ServiceWorkerDispatcher::GetThreadSpecificInstance();
- DCHECK(dispatcher);
- dispatcher->AddServiceWorker(info_->handle_id, this);
+ blink::mojom::ServiceWorkerObjectInfoPtr info,
+ base::WeakPtr<ServiceWorkerProviderContext> provider_context)
+ : binding_(this),
+ info_(std::move(info)),
+ state_(info_->state),
+ proxy_(nullptr),
+ is_for_client_(provider_context),
+ context_for_client_(std::move(provider_context)) {
+ DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId, info_->version_id);
+ host_.Bind(std::move(info_->host_ptr_info));
+ binding_.Bind(std::move(info_->request));
+
+ if (is_for_client_) {
+ context_for_client_->AddServiceWorkerObject(info_->version_id, this);
+ } else {
+ ServiceWorkerContextClient::ThreadSpecificInstance()
+ ->AddServiceWorkerObject(info_->version_id, this);
+ }
}
WebServiceWorkerImpl::~WebServiceWorkerImpl() {
- ServiceWorkerDispatcher* dispatcher =
- ServiceWorkerDispatcher::GetThreadSpecificInstance();
- if (dispatcher)
- dispatcher->RemoveServiceWorker(info_->handle_id);
-}
-
-blink::mojom::ServiceWorkerObjectHost* WebServiceWorkerImpl::GetObjectHost() {
- if (host_for_client_)
- return host_for_client_.get();
- if (host_for_global_scope_)
- return host_for_global_scope_->get();
- NOTREACHED();
- return nullptr;
+ if (is_for_client_) {
+ if (context_for_client_) {
+ context_for_client_->RemoveServiceWorkerObject(info_->version_id);
+ }
+ } else {
+ if (ServiceWorkerContextClient::ThreadSpecificInstance()) {
+ ServiceWorkerContextClient::ThreadSpecificInstance()
+ ->RemoveServiceWorkerObject(info_->version_id);
+ }
+ }
}
} // namespace content
diff --git a/chromium/content/renderer/service_worker/web_service_worker_impl.h b/chromium/content/renderer/service_worker/web_service_worker_impl.h
index cbfbfce0c2b..60e7f7e8584 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_impl.h
+++ b/chromium/content/renderer/service_worker/web_service_worker_impl.h
@@ -13,42 +13,59 @@
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker.h"
#include "third_party/blink/public/web/web_frame.h"
-namespace base {
-class SingleThreadTaskRunner;
-}
-
namespace blink {
class WebServiceWorkerProxy;
}
namespace content {
-// Each instance corresponds to one ServiceWorker object in JS context, and
-// is held by ServiceWorker object in Blink's C++ layer via
-// WebServiceWorker::Handle.
+class ServiceWorkerProviderContext;
+
+// WebServiceWorkerImpl represents a ServiceWorker object in JavaScript.
+// https://w3c.github.io/ServiceWorker/#serviceworker-interface
+//
+// Only one WebServiceWorkerImpl can exist at a time to represent a given
+// service worker in a given execution context. This is because the standard
+// requires JavaScript equality between ServiceWorker objects in the same
+// execution context that represent the same service worker.
//
-// Each instance holds one Mojo connection (|host_for_global_scope_| or
-// |host_for_client_|) for interface blink::mojom::ServiceWorkerObjectHost, so
-// the corresponding ServiceWorkerHandle doesn't go away in the browser process
-// while the ServiceWorker object is alive.
+// This class is ref counted and owned by WebServiceWorker::Handle, which is
+// passed to Blink. Generally, Blink keeps only one Handle to an instance of
+// this class. However, since //content can't know if Blink already has a
+// Handle, it passes a new Handle whenever passing this class to Blink. Blink
+// discards the new Handle if it already has one.
+// Also, this class is referred but not owned by ServiceWorkerProviderContext
+// (for service worker client contexts) and ServiceWorkerContextClient (for
+// service worker execution contexts). These are tracking WebServiceWorker to
+// ensure the uniqueness of ServiceWorker objects, and this class adds/removes
+// the reference in the ctor/dtor.
+//
+// When a blink::mojom::ServiceWorkerObjectInfo arrives at the renderer,
+// if there is no WebServiceWorkerImpl which represents the ServiceWorker, a
+// new WebServiceWorkerImpl is created using the
+// blink::mojom::ServiceWorkerObjectInfo, otherwise reuse the existing one.
+//
+// WebServiceWorkerImpl holds a Mojo connection (|host_|). The connection keeps
+// the ServiceWorkerHandle in the browser process alive, which in turn keeps the
+// relevant ServiceWorkerVersion alive.
class CONTENT_EXPORT WebServiceWorkerImpl
- : public blink::WebServiceWorker,
+ : public blink::mojom::ServiceWorkerObject,
+ public blink::WebServiceWorker,
public base::RefCounted<WebServiceWorkerImpl> {
public:
- // |io_task_runner| is used to bind |host_for_global_scope_| for service
- // worker execution context, as ServiceWorkerObjectHost is Channel-associated
- // interface and needs to be bound on either the main or IO thread.
static scoped_refptr<WebServiceWorkerImpl> CreateForServiceWorkerGlobalScope(
- blink::mojom::ServiceWorkerObjectInfoPtr info,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
- static scoped_refptr<WebServiceWorkerImpl> CreateForServiceWorkerClient(
blink::mojom::ServiceWorkerObjectInfoPtr info);
+ static scoped_refptr<WebServiceWorkerImpl> CreateForServiceWorkerClient(
+ blink::mojom::ServiceWorkerObjectInfoPtr info,
+ base::WeakPtr<ServiceWorkerProviderContext> provider_context);
- void OnStateChanged(blink::mojom::ServiceWorkerState new_state);
+ // Implements blink::mojom::ServiceWorkerObject.
+ void StateChanged(blink::mojom::ServiceWorkerState new_state) override;
// blink::WebServiceWorker overrides.
void SetProxy(blink::WebServiceWorkerProxy* proxy) override;
@@ -66,31 +83,38 @@ class CONTENT_EXPORT WebServiceWorkerImpl
private:
friend class base::RefCounted<WebServiceWorkerImpl>;
- explicit WebServiceWorkerImpl(blink::mojom::ServiceWorkerObjectInfoPtr info);
+ WebServiceWorkerImpl(
+ blink::mojom::ServiceWorkerObjectInfoPtr info,
+ base::WeakPtr<ServiceWorkerProviderContext> provider_context);
~WebServiceWorkerImpl() override;
- blink::mojom::ServiceWorkerObjectHost* GetObjectHost();
-
- // Either |host_for_global_scope_| or |host_for_client_| is non-null.
+ // Both |host_| and |binding_| are bound on the main
+ // thread for service worker clients (document), and are bound on the service
+ // worker thread for service worker execution contexts.
//
- // |host_for_global_scope_| is for service worker execution contexts. It is
- // used on the worker thread but bound on the IO thread, because it's a
- // channel-associated interface which can be bound only on the main or IO
- // thread.
- // TODO(leonhsl): Once we can detach this interface out from the legacy IPC
- // channel-associated interfaces world, we should bind it always on the worker
- // thread on which |this| lives.
- // Although it is a scoped_refptr, the only one owner is |this|.
- scoped_refptr<blink::mojom::ThreadSafeServiceWorkerObjectHostAssociatedPtr>
- host_for_global_scope_;
- // |host_for_client_| is for service worker clients (document).
- // It is bound and used on the main thread.
- blink::mojom::ServiceWorkerObjectHostAssociatedPtr host_for_client_;
+ // |host_| keeps the Mojo connection to the
+ // browser-side ServiceWorkerHandle, whose lifetime is bound
+ // to |host_| via the Mojo connection.
+ blink::mojom::ServiceWorkerObjectHostAssociatedPtr host_;
+ // |binding_| keeps the Mojo binding to serve its other Mojo endpoint (i.e.
+ // the caller end) held by the content::ServiceWorkerHandle in the browser
+ // process.
+ mojo::AssociatedBinding<blink::mojom::ServiceWorkerObject> binding_;
blink::mojom::ServiceWorkerObjectInfoPtr info_;
blink::mojom::ServiceWorkerState state_;
blink::WebServiceWorkerProxy* proxy_;
+ // True means |this| is for service worker client contexts, otherwise |this|
+ // is for service worker execution contexts.
+ const bool is_for_client_;
+ // For service worker client contexts, |this| is tracked (not owned) in
+ // |context_for_client_->controllee_state_->workers_|.
+ // For service worker execution contexts, |context_for_client_| is
+ // null and |this| is tracked (not owned) in
+ // |ServiceWorkerContextClient::ThreadSpecificInstance()->context_->workers_|.
+ base::WeakPtr<ServiceWorkerProviderContext> context_for_client_;
+
DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerImpl);
};
diff --git a/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h b/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
index 0f3fdcc6aef..d9e7d0abe4c 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
+++ b/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
@@ -8,6 +8,7 @@
#include <set>
#include <vector>
+#include "base/single_thread_task_runner.h"
#include "content/renderer/service_worker/thread_safe_script_container.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_installed_scripts_manager.h"
diff --git a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc
index be48fadaaed..2813f6b69f4 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc
+++ b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc
@@ -10,7 +10,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
@@ -62,7 +61,6 @@ void WebServiceWorkerProviderImpl::SetClient(
context_->TakeController();
if (!controller)
return;
- DCHECK_NE(blink::mojom::kInvalidServiceWorkerHandleId, controller->handle_id);
DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId,
controller->version_id);
SetController(std::move(controller), context_->used_features(),
@@ -197,7 +195,7 @@ void WebServiceWorkerProviderImpl::SetController(
provider_client_->CountFeature(feature);
provider_client_->SetController(
WebServiceWorkerImpl::CreateHandle(
- GetDispatcher()->GetOrCreateServiceWorker(std::move(controller))),
+ context_->GetOrCreateServiceWorkerObject(std::move(controller))),
should_notify_controller_change);
}
@@ -208,7 +206,7 @@ void WebServiceWorkerProviderImpl::PostMessageToClient(
return;
scoped_refptr<WebServiceWorkerImpl> source_worker =
- GetDispatcher()->GetOrCreateServiceWorker(std::move(source));
+ context_->GetOrCreateServiceWorkerObject(std::move(source));
provider_client_->DispatchMessageEvent(
WebServiceWorkerImpl::CreateHandle(std::move(source_worker)),
std::move(message));
@@ -225,10 +223,6 @@ int WebServiceWorkerProviderImpl::provider_id() const {
return context_->provider_id();
}
-ServiceWorkerDispatcher* WebServiceWorkerProviderImpl::GetDispatcher() {
- return ServiceWorkerDispatcher::GetThreadSpecificInstance();
-}
-
void WebServiceWorkerProviderImpl::OnRegistered(
std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks,
blink::mojom::ServiceWorkerErrorType error,
@@ -251,7 +245,7 @@ void WebServiceWorkerProviderImpl::OnRegistered(
DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
registration->registration_id);
callbacks->OnSuccess(WebServiceWorkerRegistrationImpl::CreateHandle(
- context_->GetOrCreateRegistrationForServiceWorkerClient(
+ context_->GetOrCreateServiceWorkerRegistrationObject(
std::move(registration))));
}
@@ -282,7 +276,7 @@ void WebServiceWorkerProviderImpl::OnDidGetRegistration(
DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
registration->registration_id);
scoped_refptr<WebServiceWorkerRegistrationImpl> impl =
- context_->GetOrCreateRegistrationForServiceWorkerClient(
+ context_->GetOrCreateServiceWorkerRegistrationObject(
std::move(registration));
DCHECK(impl);
callbacks->OnSuccess(
@@ -318,7 +312,7 @@ void WebServiceWorkerProviderImpl::OnDidGetRegistrations(
DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
(*infos)[i]->registration_id);
(*registrations)[i] = WebServiceWorkerRegistrationImpl::CreateHandle(
- context_->GetOrCreateRegistrationForServiceWorkerClient(
+ context_->GetOrCreateServiceWorkerRegistrationObject(
std::move((*infos)[i])));
}
callbacks->OnSuccess(std::move(registrations));
@@ -343,7 +337,7 @@ void WebServiceWorkerProviderImpl::OnDidGetRegistrationForReady(
DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
registration->registration_id);
callbacks->OnSuccess(WebServiceWorkerRegistrationImpl::CreateHandle(
- context_->GetOrCreateRegistrationForServiceWorkerClient(
+ context_->GetOrCreateServiceWorkerRegistrationObject(
std::move(registration))));
}
diff --git a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h
index dd4ae8b5a63..b496a3f2f1a 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h
+++ b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h
@@ -25,7 +25,6 @@ class WebServiceWorkerProviderClient;
namespace content {
-class ServiceWorkerDispatcher;
class ServiceWorkerProviderContext;
// This class corresponds to one ServiceWorkerContainer interface in
@@ -71,8 +70,6 @@ class CONTENT_EXPORT WebServiceWorkerProviderImpl
int provider_id() const;
private:
- ServiceWorkerDispatcher* GetDispatcher();
-
void OnRegistered(
std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks,
blink::mojom::ServiceWorkerErrorType error,
diff --git a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc
index 553d4967a0e..8c78ad3263a 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc
+++ b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc
@@ -4,15 +4,12 @@
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
-#include <map>
#include <utility>
-#include "base/containers/id_map.h"
#include "base/macros.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "content/child/child_process.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/renderer/service_worker/service_worker_dispatcher.h"
+#include "content/renderer/service_worker/service_worker_context_client.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
@@ -42,78 +39,24 @@ class ServiceWorkerRegistrationHandleImpl
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationHandleImpl);
};
-} // namespace
-
-class WebServiceWorkerRegistrationImpl::WebCallbacksHolder {
- public:
- WebCallbacksHolder() : weak_ptr_factory_(this){};
- ~WebCallbacksHolder() = default;
-
- WebServiceWorkerRegistrationImpl::ResponseCallback WrapResponseCallback(
- WebServiceWorkerRegistrationImpl::ResponseCallback callback) {
- const uint64_t callback_id = next_callback_id_++;
- callback_map_[callback_id] = std::move(callback);
- return base::BindOnce(&WebCallbacksHolder::OnRegistrationObjectHostResponse,
- weak_ptr_factory_.GetWeakPtr(), callback_id);
- }
-
- blink::mojom::ServiceWorkerRegistrationObjectHost::
- GetNavigationPreloadStateCallback
- WrapWebGetNavigationPreloadStateCallbacks(
- std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks) {
- const int web_callbacks_id =
- get_navigation_preload_state_callbacks_map_.Add(std::move(callbacks));
- return base::BindOnce(
- &WebCallbacksHolder::OnGetNavigationPreloadStateResponse,
- weak_ptr_factory_.GetWeakPtr(), web_callbacks_id);
- }
-
- // Gets the response callback from |callback_map_| with the key |callback_id|,
- // then runs it.
- void OnRegistrationObjectHostResponse(
- uint64_t callback_id,
- blink::mojom::ServiceWorkerErrorType error,
- const base::Optional<std::string>& error_msg) {
- auto it = callback_map_.find(callback_id);
- DCHECK(it != callback_map_.end());
- std::move(it->second).Run(error, error_msg);
- callback_map_.erase(it);
- }
-
- void OnGetNavigationPreloadStateResponse(
- int web_callbacks_id,
- blink::mojom::ServiceWorkerErrorType error,
- const base::Optional<std::string>& error_msg,
- blink::mojom::NavigationPreloadStatePtr state) {
- WebGetNavigationPreloadStateCallbacks* callbacks =
- get_navigation_preload_state_callbacks_map_.Lookup(web_callbacks_id);
- DCHECK(callbacks);
-
- if (error == blink::mojom::ServiceWorkerErrorType::kNone) {
- callbacks->OnSuccess(blink::WebNavigationPreloadState(
- state->enabled, blink::WebString::FromUTF8(state->header)));
- } else {
- DCHECK(error_msg);
- callbacks->OnError(blink::WebServiceWorkerError(
- error, blink::WebString::FromUTF8(*error_msg)));
- }
- get_navigation_preload_state_callbacks_map_.Remove(web_callbacks_id);
+void DidGetNavigationPreloadState(
+ std::unique_ptr<
+ WebServiceWorkerRegistrationImpl::WebGetNavigationPreloadStateCallbacks>
+ callbacks,
+ blink::mojom::ServiceWorkerErrorType error,
+ const base::Optional<std::string>& error_msg,
+ blink::mojom::NavigationPreloadStatePtr state) {
+ if (error != blink::mojom::ServiceWorkerErrorType::kNone) {
+ DCHECK(error_msg);
+ callbacks->OnError(blink::WebServiceWorkerError(
+ error, blink::WebString::FromUTF8(*error_msg)));
+ return;
}
+ callbacks->OnSuccess(blink::WebNavigationPreloadState(
+ state->enabled, blink::WebString::FromUTF8(state->header)));
+}
- private:
- std::map<uint64_t, WebServiceWorkerRegistrationImpl::ResponseCallback>
- callback_map_;
- uint64_t next_callback_id_ = 0;
- // Because the response callback of GetNavigationPreloadState() has different
- // prototype with other methods of ServiceWorkerRegistrationObjectHost
- // interface, we have to create this separate map for it.
- base::IDMap<std::unique_ptr<WebGetNavigationPreloadStateCallbacks>>
- get_navigation_preload_state_callbacks_map_;
-
- base::WeakPtrFactory<WebCallbacksHolder> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(WebCallbacksHolder);
-};
+} // namespace
WebServiceWorkerRegistrationImpl::QueuedTask::QueuedTask(
QueuedTaskType type,
@@ -128,25 +71,10 @@ WebServiceWorkerRegistrationImpl::QueuedTask::~QueuedTask() {}
// static
scoped_refptr<WebServiceWorkerRegistrationImpl>
WebServiceWorkerRegistrationImpl::CreateForServiceWorkerGlobalScope(
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
- DCHECK(info->request.is_pending());
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info) {
scoped_refptr<WebServiceWorkerRegistrationImpl> impl =
new WebServiceWorkerRegistrationImpl(std::move(info),
nullptr /* provider_context */);
- impl->host_for_global_scope_ =
- blink::mojom::ThreadSafeServiceWorkerRegistrationObjectHostAssociatedPtr::
- Create(std::move(impl->info_->host_ptr_info), io_task_runner);
- // |impl|'s destruction needs both DetachAndMaybeDestroy() and
- // OnConnectionError() to be called (see comments at LifecycleState enum), and
- // OnConnectionError() cannot happen before BindRequest(), therefore using
- // base::Unretained() here is safe.
- io_task_runner->PostTask(
- FROM_HERE, base::BindOnce(&WebServiceWorkerRegistrationImpl::BindRequest,
- base::Unretained(impl.get()),
- std::move(impl->info_->request)));
- impl->state_ = LifecycleState::kAttachedAndBound;
- impl->RefreshVersionAttributes();
return impl;
}
@@ -155,45 +83,21 @@ scoped_refptr<WebServiceWorkerRegistrationImpl>
WebServiceWorkerRegistrationImpl::CreateForServiceWorkerClient(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
base::WeakPtr<ServiceWorkerProviderContext> provider_context) {
- DCHECK(info->request.is_pending());
+ DCHECK(provider_context);
scoped_refptr<WebServiceWorkerRegistrationImpl> impl =
new WebServiceWorkerRegistrationImpl(std::move(info),
std::move(provider_context));
- impl->host_for_client_.Bind(std::move(impl->info_->host_ptr_info));
- impl->BindRequest(std::move(impl->info_->request));
- impl->state_ = LifecycleState::kAttachedAndBound;
- impl->RefreshVersionAttributes();
return impl;
}
void WebServiceWorkerRegistrationImpl::AttachForServiceWorkerClient(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info) {
- if (state_ == LifecycleState::kAttachedAndBound) {
- // |update_via_cache| is handled specifically here as it is the only mutable
- // property when the browser process sends |info| for an existing
- // registration. The installing/waiting/active properties are changed by the
- // SetVersionAttributes method instead.
- if (info_->options && info->options) {
- info_->options->update_via_cache = info->options->update_via_cache;
- }
- return;
- }
- DCHECK_EQ(LifecycleState::kDetached, state_);
- DCHECK(!info->request.is_pending());
+ DCHECK_EQ(info_->registration_id, info->registration_id);
Attach(std::move(info));
-
- DCHECK(!host_for_global_scope_);
- DCHECK(!host_for_client_);
- host_for_client_.Bind(std::move(info_->host_ptr_info));
- state_ = LifecycleState::kAttachedAndBound;
- RefreshVersionAttributes();
}
void WebServiceWorkerRegistrationImpl::SetProxy(
blink::WebServiceWorkerRegistrationProxy* proxy) {
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
- DCHECK(info_);
- DCHECK(host_for_global_scope_ || host_for_client_);
proxy_ = proxy;
RunQueuedTasks();
}
@@ -213,81 +117,21 @@ void WebServiceWorkerRegistrationImpl::RunQueuedTasks() {
queued_tasks_.clear();
}
-blink::mojom::ServiceWorkerRegistrationObjectHost*
-WebServiceWorkerRegistrationImpl::GetRegistrationObjectHost() {
- if (host_for_client_)
- return host_for_client_.get();
- if (host_for_global_scope_)
- return host_for_global_scope_->get();
- NOTREACHED();
- return nullptr;
-}
-
void WebServiceWorkerRegistrationImpl::Attach(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info) {
- DCHECK(!info_);
- DCHECK(info);
DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
info->registration_id);
- DCHECK_EQ(registration_id_, info->registration_id);
DCHECK(info->host_ptr_info.is_valid());
- info_ = std::move(info);
-}
-
-void WebServiceWorkerRegistrationImpl::DetachAndMaybeDestroy() {
- DCHECK(creation_task_runner_->RunsTasksInCurrentSequence());
- proxy_ = nullptr;
- queued_tasks_.clear();
- host_for_client_.reset();
- host_for_global_scope_ = nullptr;
- info_ = nullptr;
- web_callbacks_holder_.reset();
- if (state_ == LifecycleState::kUnbound) {
- state_ = LifecycleState::kDead;
- delete this;
- return;
- }
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
- state_ = LifecycleState::kDetached;
- // We will continue in OnConnectionError() triggered by destruction of the
- // content::ServiceWorkerRegistrationObjectHost in the browser process, or
- // else in Attach*() if |this| is reused.
-}
-
-void WebServiceWorkerRegistrationImpl::BindRequest(
- blink::mojom::ServiceWorkerRegistrationObjectAssociatedRequest request) {
- DCHECK(request.is_pending());
- binding_.Bind(std::move(request));
- binding_.set_connection_error_handler(
- base::BindOnce(&WebServiceWorkerRegistrationImpl::OnConnectionError,
- base::Unretained(this)));
-}
+ DCHECK(info->request.is_pending());
+ if (!host_)
+ host_.Bind(std::move(info->host_ptr_info));
+ else
+ info->host_ptr_info = nullptr;
+ binding_.Close();
+ binding_.Bind(std::move(info->request));
-void WebServiceWorkerRegistrationImpl::OnConnectionError() {
- if (!creation_task_runner_->RunsTasksInCurrentSequence()) {
- // If this registration impl is for a service worker execution context,
- // |this| lives on the worker thread but |binding_| is bound on the IO
- // thread due to limitations of channel-associated interfaces. Close
- // |binding_| here since this is the thread it was bound on, then hop to the
- // worker thread to handle lifetime of |this|. In the case of a service
- // worker client, both |this| and |binding_| live on the main thread, so the
- // binding can be closed normally during destruction.
- binding_.Close();
- creation_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&WebServiceWorkerRegistrationImpl::OnConnectionError,
- base::Unretained(this)));
- return;
- }
- if (state_ == LifecycleState::kDetached) {
- state_ = LifecycleState::kDead;
- delete this;
- return;
- }
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
- state_ = LifecycleState::kUnbound;
- // We will continue in DetachAndMaybeDestroy() when all references of |this|
- // have been released by Blink.
+ info_ = std::move(info);
+ RefreshVersionAttributes();
}
blink::WebServiceWorkerRegistrationProxy*
@@ -306,9 +150,7 @@ WebServiceWorkerRegistrationImpl::UpdateViaCache() const {
void WebServiceWorkerRegistrationImpl::Update(
std::unique_ptr<WebServiceWorkerUpdateCallbacks> callbacks) {
- DCHECK(state_ == LifecycleState::kAttachedAndBound ||
- state_ == LifecycleState::kUnbound);
- GetRegistrationObjectHost()->Update(WrapResponseCallback(base::BindOnce(
+ host_->Update(base::BindOnce(
[](std::unique_ptr<WebServiceWorkerUpdateCallbacks> callbacks,
blink::mojom::ServiceWorkerErrorType error,
const base::Optional<std::string>& error_msg) {
@@ -322,14 +164,12 @@ void WebServiceWorkerRegistrationImpl::Update(
DCHECK(!error_msg);
callbacks->OnSuccess();
},
- std::move(callbacks))));
+ std::move(callbacks)));
}
void WebServiceWorkerRegistrationImpl::Unregister(
std::unique_ptr<WebServiceWorkerUnregistrationCallbacks> callbacks) {
- DCHECK(state_ == LifecycleState::kAttachedAndBound ||
- state_ == LifecycleState::kUnbound);
- GetRegistrationObjectHost()->Unregister(WrapResponseCallback(base::BindOnce(
+ host_->Unregister(base::BindOnce(
[](std::unique_ptr<WebServiceWorkerUnregistrationCallbacks> callbacks,
blink::mojom::ServiceWorkerErrorType error,
const base::Optional<std::string>& error_msg) {
@@ -344,17 +184,15 @@ void WebServiceWorkerRegistrationImpl::Unregister(
callbacks->OnSuccess(error ==
blink::mojom::ServiceWorkerErrorType::kNone);
},
- std::move(callbacks))));
+ std::move(callbacks)));
}
void WebServiceWorkerRegistrationImpl::EnableNavigationPreload(
bool enable,
std::unique_ptr<WebEnableNavigationPreloadCallbacks> callbacks) {
- DCHECK(state_ == LifecycleState::kAttachedAndBound ||
- state_ == LifecycleState::kUnbound);
- GetRegistrationObjectHost()->EnableNavigationPreload(
+ host_->EnableNavigationPreload(
enable,
- WrapResponseCallback(base::BindOnce(
+ base::BindOnce(
[](std::unique_ptr<WebEnableNavigationPreloadCallbacks> callbacks,
blink::mojom::ServiceWorkerErrorType error,
const base::Optional<std::string>& error_msg) {
@@ -366,25 +204,21 @@ void WebServiceWorkerRegistrationImpl::EnableNavigationPreload(
}
callbacks->OnSuccess();
},
- std::move(callbacks))));
+ std::move(callbacks)));
}
void WebServiceWorkerRegistrationImpl::GetNavigationPreloadState(
std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks) {
- DCHECK(state_ == LifecycleState::kAttachedAndBound ||
- state_ == LifecycleState::kUnbound);
- GetRegistrationObjectHost()->GetNavigationPreloadState(
- WrapWebGetNavigationPreloadStateCallbacks(std::move(callbacks)));
+ host_->GetNavigationPreloadState(
+ base::BindOnce(&DidGetNavigationPreloadState, std::move(callbacks)));
}
void WebServiceWorkerRegistrationImpl::SetNavigationPreloadHeader(
const blink::WebString& value,
std::unique_ptr<WebSetNavigationPreloadHeaderCallbacks> callbacks) {
- DCHECK(state_ == LifecycleState::kAttachedAndBound ||
- state_ == LifecycleState::kUnbound);
- GetRegistrationObjectHost()->SetNavigationPreloadHeader(
+ host_->SetNavigationPreloadHeader(
value.Utf8(),
- WrapResponseCallback(base::BindOnce(
+ base::BindOnce(
[](std::unique_ptr<WebSetNavigationPreloadHeaderCallbacks> callbacks,
blink::mojom::ServiceWorkerErrorType error,
const base::Optional<std::string>& error_msg) {
@@ -396,7 +230,7 @@ void WebServiceWorkerRegistrationImpl::SetNavigationPreloadHeader(
}
callbacks->OnSuccess();
},
- std::move(callbacks))));
+ std::move(callbacks)));
}
int64_t WebServiceWorkerRegistrationImpl::RegistrationId() const {
@@ -413,46 +247,31 @@ WebServiceWorkerRegistrationImpl::CreateHandle(
std::move(registration));
}
-// static
-void WebServiceWorkerRegistrationImpl::Destruct(
- const WebServiceWorkerRegistrationImpl* impl) {
- const_cast<WebServiceWorkerRegistrationImpl*>(impl)->DetachAndMaybeDestroy();
-}
-
WebServiceWorkerRegistrationImpl::WebServiceWorkerRegistrationImpl(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
base::WeakPtr<ServiceWorkerProviderContext> provider_context)
- : registration_id_(info->registration_id),
- proxy_(nullptr),
+ : proxy_(nullptr),
binding_(this),
- creation_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- state_(LifecycleState::kInitial),
+ is_for_client_(provider_context),
provider_context_for_client_(std::move(provider_context)) {
Attach(std::move(info));
-
- if (provider_context_for_client_)
- provider_context_for_client_->AddServiceWorkerRegistration(registration_id_,
- this);
+ if (is_for_client_) {
+ provider_context_for_client_->AddServiceWorkerRegistrationObject(
+ info_->registration_id, this);
+ }
}
WebServiceWorkerRegistrationImpl::~WebServiceWorkerRegistrationImpl() {
- DCHECK_EQ(LifecycleState::kDead, state_);
- if (provider_context_for_client_)
- provider_context_for_client_->RemoveServiceWorkerRegistration(
- registration_id_);
+ if (provider_context_for_client_) {
+ provider_context_for_client_->RemoveServiceWorkerRegistrationObject(
+ info_->registration_id);
+ }
}
void WebServiceWorkerRegistrationImpl::SetInstalling(
blink::mojom::ServiceWorkerObjectInfoPtr info) {
- if (state_ == LifecycleState::kDetached)
- return;
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
-
- ServiceWorkerDispatcher* dispatcher =
- ServiceWorkerDispatcher::GetThreadSpecificInstance();
- DCHECK(dispatcher);
scoped_refptr<WebServiceWorkerImpl> service_worker =
- dispatcher->GetOrCreateServiceWorker(std::move(info));
+ GetOrCreateServiceWorkerObject(std::move(info));
if (proxy_)
proxy_->SetInstalling(WebServiceWorkerImpl::CreateHandle(service_worker));
else
@@ -461,15 +280,8 @@ void WebServiceWorkerRegistrationImpl::SetInstalling(
void WebServiceWorkerRegistrationImpl::SetWaiting(
blink::mojom::ServiceWorkerObjectInfoPtr info) {
- if (state_ == LifecycleState::kDetached)
- return;
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
-
- ServiceWorkerDispatcher* dispatcher =
- ServiceWorkerDispatcher::GetThreadSpecificInstance();
- DCHECK(dispatcher);
scoped_refptr<WebServiceWorkerImpl> service_worker =
- dispatcher->GetOrCreateServiceWorker(std::move(info));
+ GetOrCreateServiceWorkerObject(std::move(info));
if (proxy_)
proxy_->SetWaiting(WebServiceWorkerImpl::CreateHandle(service_worker));
else
@@ -478,15 +290,8 @@ void WebServiceWorkerRegistrationImpl::SetWaiting(
void WebServiceWorkerRegistrationImpl::SetActive(
blink::mojom::ServiceWorkerObjectInfoPtr info) {
- if (state_ == LifecycleState::kDetached)
- return;
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
-
- ServiceWorkerDispatcher* dispatcher =
- ServiceWorkerDispatcher::GetThreadSpecificInstance();
- DCHECK(dispatcher);
scoped_refptr<WebServiceWorkerImpl> service_worker =
- dispatcher->GetOrCreateServiceWorker(std::move(info));
+ GetOrCreateServiceWorkerObject(std::move(info));
if (proxy_)
proxy_->SetActive(WebServiceWorkerImpl::CreateHandle(service_worker));
else
@@ -499,29 +304,28 @@ void WebServiceWorkerRegistrationImpl::RefreshVersionAttributes() {
SetActive(std::move(info_->active));
}
+scoped_refptr<WebServiceWorkerImpl>
+WebServiceWorkerRegistrationImpl::GetOrCreateServiceWorkerObject(
+ blink::mojom::ServiceWorkerObjectInfoPtr info) {
+ scoped_refptr<WebServiceWorkerImpl> service_worker;
+ if (is_for_client_) {
+ if (provider_context_for_client_) {
+ service_worker =
+ provider_context_for_client_->GetOrCreateServiceWorkerObject(
+ std::move(info));
+ }
+ } else if (ServiceWorkerContextClient::ThreadSpecificInstance()) {
+ service_worker = ServiceWorkerContextClient::ThreadSpecificInstance()
+ ->GetOrCreateServiceWorkerObject(std::move(info));
+ }
+ return service_worker;
+}
+
void WebServiceWorkerRegistrationImpl::SetVersionAttributes(
int changed_mask,
blink::mojom::ServiceWorkerObjectInfoPtr installing,
blink::mojom::ServiceWorkerObjectInfoPtr waiting,
blink::mojom::ServiceWorkerObjectInfoPtr active) {
- if (!creation_task_runner_->RunsTasksInCurrentSequence()) {
- // As this posted task will definitely run before OnConnectionError() on the
- // |creation_task_runner_|, using base::Unretained() here is safe.
- creation_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&WebServiceWorkerRegistrationImpl::SetVersionAttributes,
- base::Unretained(this), changed_mask,
- std::move(installing), std::move(waiting),
- std::move(active)));
- return;
- }
-
- if (state_ == LifecycleState::kDetached)
- return;
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
- ServiceWorkerDispatcher* dispatcher =
- ServiceWorkerDispatcher::GetThreadSpecificInstance();
- DCHECK(dispatcher);
ChangedVersionAttributesMask mask(changed_mask);
DCHECK(mask.installing_changed() || !installing);
if (mask.installing_changed()) {
@@ -537,44 +341,16 @@ void WebServiceWorkerRegistrationImpl::SetVersionAttributes(
}
}
-void WebServiceWorkerRegistrationImpl::UpdateFound() {
- if (!creation_task_runner_->RunsTasksInCurrentSequence()) {
- // As this posted task will definitely run before OnConnectionError() on the
- // |creation_task_runner_|, using base::Unretained() here is safe.
- creation_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&WebServiceWorkerRegistrationImpl::UpdateFound,
- base::Unretained(this)));
- return;
- }
+void WebServiceWorkerRegistrationImpl::SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache) {
+ info_->options->update_via_cache = update_via_cache;
+}
- if (state_ == LifecycleState::kDetached)
- return;
- DCHECK_EQ(LifecycleState::kAttachedAndBound, state_);
+void WebServiceWorkerRegistrationImpl::UpdateFound() {
if (proxy_)
proxy_->DispatchUpdateFoundEvent();
else
queued_tasks_.push_back(QueuedTask(UPDATE_FOUND, nullptr));
}
-WebServiceWorkerRegistrationImpl::ResponseCallback
-WebServiceWorkerRegistrationImpl::WrapResponseCallback(
- ResponseCallback callback) {
- if (!web_callbacks_holder_) {
- web_callbacks_holder_ = std::make_unique<WebCallbacksHolder>();
- }
- return web_callbacks_holder_->WrapResponseCallback(std::move(callback));
-}
-
-blink::mojom::ServiceWorkerRegistrationObjectHost::
- GetNavigationPreloadStateCallback
- WebServiceWorkerRegistrationImpl::WrapWebGetNavigationPreloadStateCallbacks(
- std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks) {
- if (!web_callbacks_holder_) {
- web_callbacks_holder_ = std::make_unique<WebCallbacksHolder>();
- }
- return web_callbacks_holder_->WrapWebGetNavigationPreloadStateCallbacks(
- std::move(callbacks));
-}
-
} // namespace content
diff --git a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h
index 3ea61a3a6bf..4405d0415b7 100644
--- a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h
+++ b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h
@@ -21,10 +21,6 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
-namespace base {
-class SingleThreadTaskRunner;
-}
-
namespace blink {
class WebServiceWorkerRegistrationProxy;
}
@@ -34,64 +30,53 @@ namespace content {
class WebServiceWorkerImpl;
class ServiceWorkerProviderContext;
-// WebServiceWorkerRegistrationImpl corresponds to one ServiceWorkerRegistration
-// object in JavaScript. It is owned by
-// content::ServiceWorkerRegistrationObjectHost in the browser process, but also
-// is refcounted by WebServiceWorkerRegistration::Handles in the renderer
-// process. See the detailed lifecycle explanation below.
+// WebServiceWorkerRegistrationImpl represents a ServiceWorkerRegistration
+// object in JavaScript.
+// https://w3c.github.io/ServiceWorker/#serviceworkerregistration-interface
//
-// A WebServiceWorkerRegistrationImpl is created when the browser process sends
-// the first ServiceWorkerRegistrationObjectInfo to the renderer process that
-// describes the desired JavaScript object. The instance is created and takes
-// ownership of the object info. The object info has a Mojo connection to a
-// ServiceWorkerRegistrationObjectHost in the browser process
-// ((|this->info_.host_ptr_info|) . In addition, The
-// WebServiceWorkerRegistrationImpl itself is connected with the
-// ServiceWorkerRegistrationObjectHost (|this->binding_|). Creation always
-// happens in order to create a ServiceWorkerRegistration JavaScript object in
-// Blink. The instance is shared with Blink via
-// WebServiceWorkerRegistration::Handle. As long as a handle is alive in Blink,
-// this instance should not die.
+// Only one WebServiceWorkerRegistrationImpl can exist at a time to represent a
+// given service worker registration in a given execution context. This is
+// because the standard requires JavaScript equality between
+// ServiceWorkerRegistration objects in the same execution context that
+// represent the same service worker registration.
//
-// During the lifetime of WebServiceWorkerRegistrationImpl, multiple
-// WebServiceWorkerRegistration::Handles may be created and held by Blink. If
-// the browser process sends another ServiceWorkerRegistrationObjectInfo to the
-// renderer process for this same JavaScript object, the renderer reuses the
-// existing WebServiceWorkerRegistrationImpl instance and creates a new
-// WebServiceWorkerRegistration::Handle to share with Blink.
+// This class is ref counted and owned by WebServiceWorkerRegistration::Handle,
+// which is passed to Blink. Generally, Blink keeps only one Handle to an
+// instance of this class. However, since //content can't know if Blink already
+// has a Handle, it passes a new Handle whenever passing this class to Blink.
+// Blink discards the new Handle if it already has one.
//
-// If all WebServiceWorkerRegistration::Handles are destroyed, the
-// WebServiceWorkerRegistrationImpl clears |info_|, which informs the
-// ServiceWorkerRegistrationObjectHost in the browser process that this instance
-// is ready to be destroyed. If there was no ServiceWorkerRegistrationObjectInfo
-// inflight, the browser process destroys the Mojo connection to this instance,
-// which finally destroys it.
+// When a blink::mojom::ServiceWorkerRegistrationObjectInfo arrives at the
+// renderer, there are two ways to handle it.
+// 1) If there is no WebServiceWorkerRegistrationImpl which represents the
+// ServiceWorkerRegistration, a new WebServiceWorkerRegistrationImpl is
+// created using the blink::mojom::ServiceWorkerRegistrationObjectInfo.
+// 2) If there is a WebServiceWorkerRegistrationImpl which represents the
+// ServiceWorkerRegistration, the WebServiceWorkerRegistrationImpl starts to use
+// the new browser->renderer connection
+// (blink::mojom::ServiceWorkerRegistrationObject interface) and the information
+// about the registration.
//
-// Another destruction scenario is that the browser process destroys the
-// ServiceWorkerRegistrationObject Mojo connection while some
-// WebServiceWorkerRegistration::Handles are still held by Blink. In such a case
-// this instance will finally be destroyed after all Blink destroys all the
-// WebServiceWorkerRegistration::Handles.
+// WebServiceWorkerRegistrationImpl holds a Mojo connection (|host_|). The
+// connection keeps the ServiceWorkerRegistrationObjectHost in the browser
+// process alive, which in turn keeps the relevant
+// content::ServiceWorkerRegistration alive.
class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
: public blink::mojom::ServiceWorkerRegistrationObject,
public blink::WebServiceWorkerRegistration,
- public base::RefCounted<WebServiceWorkerRegistrationImpl,
- WebServiceWorkerRegistrationImpl> {
+ public base::RefCounted<WebServiceWorkerRegistrationImpl> {
public:
- // |io_task_runner| is used to bind |host_for_global_scope_| and |binding_|
- // for service worker execution context, as both of
- // ServiceWorkerRegistrationObjectHost and ServiceWorkerRegistrationObject are
- // Channel-associated interfaces and need to be bound on either the main or IO
- // thread.
static scoped_refptr<WebServiceWorkerRegistrationImpl>
CreateForServiceWorkerGlobalScope(
- blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+ blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info);
static scoped_refptr<WebServiceWorkerRegistrationImpl>
CreateForServiceWorkerClient(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
base::WeakPtr<ServiceWorkerProviderContext> provider_context);
+ // Called when the browser process sends a new
+ // blink::mojom::ServiceWorkerRegistrationObjectInfo and |this| already exists
+ // for the described ServiceWorkerRegistration (see the class comment).
void AttachForServiceWorkerClient(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info);
@@ -122,9 +107,7 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
CreateHandle(scoped_refptr<WebServiceWorkerRegistrationImpl> registration);
private:
- class WebCallbacksHolder;
- friend class base::RefCounted<WebServiceWorkerRegistrationImpl,
- WebServiceWorkerRegistrationImpl>;
+ friend class base::RefCounted<WebServiceWorkerRegistrationImpl>;
WebServiceWorkerRegistrationImpl(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info,
base::WeakPtr<ServiceWorkerProviderContext> provider_context);
@@ -137,81 +120,19 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
// the {installing,waiting,active} service worker object infos from |info_|.
void RefreshVersionAttributes();
+ scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorkerObject(
+ blink::mojom::ServiceWorkerObjectInfoPtr info);
+
// Implements blink::mojom::ServiceWorkerRegistrationObject.
void SetVersionAttributes(
int changed_mask,
blink::mojom::ServiceWorkerObjectInfoPtr installing,
blink::mojom::ServiceWorkerObjectInfoPtr waiting,
blink::mojom::ServiceWorkerObjectInfoPtr active) override;
+ void SetUpdateViaCache(
+ blink::mojom::ServiceWorkerUpdateViaCache update_via_cache) override;
void UpdateFound() override;
- using ResponseCallback =
- base::OnceCallback<void(blink::mojom::ServiceWorkerErrorType,
- const base::Optional<std::string>&)>;
- // |callback| owns a Web*Callbacks instance which constrains itself to be
- // destroyed on the same thread that created it (the worker thread).
- //
- // But our |host_for_global_scope_| is a Mojo thread safe ptr, which is used
- // to make Mojo calls on the worker thread but its underlying Mojo connection
- // is bound on the IO thread. Currently when we call |host_for_global_scope_|
- // methods, we're moving |callback| along the way from the worker thread to
- // the IO thread, then waiting until |callback| is posted back to the worker
- // thread. However, the post back operation will fail if the worker thread has
- // already been destroyed for some reasons, in such a case the poster on the
- // IO thread has to destroy |callback| there, then causing a crash.
- //
- // To solve the above problem, this function creates a wrapper response
- // callback adapting to run |callback|, since the Web*Callbacks are stored
- // separately outside it, this wrapper callback is thread-safe and can be
- // destroyed on any thread, thus, we can pass this wrapper callback to
- // |host_for_global_scope_| which can move this wrapper between the worker
- // thread and IO thread freely.
- //
- // TODO(leonhsl): Once we can avoid using Mojo thread safe ptr for
- // |host_for_global_scope_|, we can eliminate this wrapping mechanism.
- ResponseCallback WrapResponseCallback(ResponseCallback callback);
- blink::mojom::ServiceWorkerRegistrationObjectHost::
- GetNavigationPreloadStateCallback
- WrapWebGetNavigationPreloadStateCallbacks(
- std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks);
-
- // RefCounted traits implementation, rather than delete |impl| directly, calls
- // |impl->DetachAndMaybeDestroy()| to notify that the last reference to it has
- // gone away.
- static void Destruct(const WebServiceWorkerRegistrationImpl* impl);
-
- // Enumeration of the possible |state_| during lifetime of this class.
- // - |kInitial| --> |kAttachedAndBound|
- // |this| is initialized with |kInitial| state by the ctor then it is
- // set to |kAttachedAndBound| state soon in the factory methods
- // (CreateForServiceWorkerGlobalScope() or CreateForServiceWorkerClient()).
- // From the beginning |this| is referenced by
- // blink::WebServiceWorkerRegistration::Handle impl and the |binding_| Mojo
- // connection has been established.
- // - |kAttachedAndBound| --> |kDetached|
- // When all references to |this| have been released by Blink,
- // DetachAndMaybeDestroy() will be triggered to change |state_| from
- // |kAttachedAndBound| to |kDetached|.
- // - |kAttachedAndBound| --> |kUnbound|
- // When |binding_| Mojo connection gets broken, OnConnectionError() will be
- // triggered to change |state_| from |kAttachedAndBound| to |kUnbound|.
- // - {|kUnbound|, |kDetached|} --> |kDead|
- // But if DetachAndMaybeDestroy() saw that |state_| is already |kUnbound| or
- // OnConnectionError() saw that |state_| is already |kDetached|, they will
- // just set |state_| to |kDead| and delete |this| immediately.
- // - |kDetached| --> |kAttachedAndBound|
- // When |this| is in |kDetached| state, if an inflight
- // ServiceWorkerRegistrationObjectInfo for the same JavaScript registration
- // object arrived, |this| is reused to be provided to Blink. In such a case
- // AttachForServiceWorkerClient() sets |state_| to |kAttachedAndBound|.
- enum class LifecycleState {
- kInitial,
- kAttachedAndBound,
- kUnbound,
- kDetached,
- kDead
- };
-
enum QueuedTaskType {
INSTALLING,
WAITING,
@@ -229,76 +150,38 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
};
void RunQueuedTasks();
- blink::mojom::ServiceWorkerRegistrationObjectHost*
- GetRegistrationObjectHost();
void Attach(blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info);
void DetachAndMaybeDestroy();
- void BindRequest(
- blink::mojom::ServiceWorkerRegistrationObjectAssociatedRequest request);
void OnConnectionError();
- // |registration_id_| is the id of the corresponding
- // content::ServiceWorkerRegistration in the browser process.
- const int64_t registration_id_;
// |info_| is initialized by the contructor with |info| passed from the remote
// content::ServiceWorkerRegistrationObjectHost just created in the browser
- // process. It will be reset to nullptr by DetachAndMaybeDestroy() when
- // there is no any blink::WebServiceWorkerRegistration::Handle referencing
- // |this|. After that if another Mojo connection from the same remote
- // content::ServiceWorkerRegistrationObjectHost is passed here again (e.g.
- // WebServiceWorkerProviderImpl::OnDidGetRegistration()), |info_| will be set
- // to the valid value again by Attach().
- // |info_->host_ptr_info| is taken/bound by |host_for_global_scope_| or
- // |host_for_client_| which holds the Mojo connection caller end point
- // retaining an reference to the remote
- // content::ServiceWorkerRegistrationObjectHost to control its lifetime.
+ // process, and may be updated by AttachForServiceWorkerClient().
+ // |info_->host_ptr_info| is taken/bound by |host_|.
// |info_->request| is bound on |binding_|.
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info_;
blink::WebServiceWorkerRegistrationProxy* proxy_;
- // Either |host_for_global_scope_| or |host_for_client_| is non-null.
- //
- // |host_for_global_scope_| is for service worker execution contexts. It is
- // used on the worker thread but bound on the IO thread, because it's a
- // channel- associated interface which can be bound only on the main or IO
- // thread.
- // TODO(leonhsl): Once we can detach this interface out from the legacy IPC
- // channel-associated interfaces world, we should bind it always on the worker
- // thread on which |this| lives.
- // Although it is a scoped_refptr, the only one owner is |this|.
- scoped_refptr<
- blink::mojom::ThreadSafeServiceWorkerRegistrationObjectHostAssociatedPtr>
- host_for_global_scope_;
- // |host_for_client_| is for service worker clients (document, shared worker).
- // It is bound and used on the main thread.
- blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedPtr
- host_for_client_;
-
+ // |host_| keeps the Mojo connection to the
+ // browser-side ServiceWorkerRegistrationObjectHost, whose lifetime is bound
+ // to the Mojo connection. It is bound on the
+ // main thread for service worker clients (document), and is bound on the
+ // service worker thread for service worker execution contexts.
+ blink::mojom::ServiceWorkerRegistrationObjectHostAssociatedPtr host_;
// |binding_| keeps the Mojo binding to serve its other Mojo endpoint (i.e.
- // the caller end) held by the content::ServiceWorkerRegistrationObjectHost in
- // the browser process, is bound with |info_->request| by BindRequest()
- // function. This also controls lifetime of |this|, its connection error
- // handler will delete |this|. It is bound on the main thread for service
- // worker clients (document, shared worker). It is bound on the IO thread for
- // service worker execution contexts, but always uses PostTask to handle
- // received messages actually on the worker thread, because it's a
- // channel-associated interface which can be bound only on the main or IO
- // thread.
- // TODO(leonhsl): Once we can detach this interface out from the legacy IPC
- // channel-associated interfaces world, for service worker execution context
- // we should bind it always on the worker thread on which |this| lives.
+ // the caller end) held by the ServiceWorkerRegistrationObjectHost in
+ // the browser process.
+ // It is bound on the main thread for service
+ // worker clients (document), and is bound on the service worker thread for
+ // service worker execution contexts.
mojo::AssociatedBinding<blink::mojom::ServiceWorkerRegistrationObject>
binding_;
- scoped_refptr<base::SingleThreadTaskRunner> creation_task_runner_;
- LifecycleState state_;
std::vector<QueuedTask> queued_tasks_;
- // Owns all WebServiceWorkerXXXCallbacks provided from Blink when calling
- // ServiceWorkerRegistrationObjectHost interface methods. Please see comments
- // of WrapResponseCallback() for details.
- std::unique_ptr<WebCallbacksHolder> web_callbacks_holder_;
-
+ // True means |this| is for service worker client contexts, otherwise |this|
+ // is for service worker execution contexts.
+ const bool is_for_client_;
// For service worker client contexts, |this| is tracked (not owned) in
// |provider_context_for_client_->controllee_state_->registrations_|.
// For service worker execution contexts, |provider_context_for_client_| is
diff --git a/chromium/content/renderer/service_worker/worker_fetch_context_impl.cc b/chromium/content/renderer/service_worker/worker_fetch_context_impl.cc
index ed9a4c4dcd0..bc16217cbdc 100644
--- a/chromium/content/renderer/service_worker/worker_fetch_context_impl.cc
+++ b/chromium/content/renderer/service_worker/worker_fetch_context_impl.cc
@@ -5,14 +5,16 @@
#include "content/renderer/service_worker/worker_fetch_context_impl.h"
#include "base/feature_list.h"
+#include "base/single_thread_task_runner.h"
#include "content/child/child_thread_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/frame_messages.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/content_features.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
+#include "content/public/renderer/websocket_handshake_throttle_provider.h"
#include "content/renderer/loader/request_extra_data.h"
#include "content/renderer/loader/resource_dispatcher.h"
#include "content/renderer/loader/web_url_loader_impl.h"
@@ -21,21 +23,51 @@
#include "content/renderer/service_worker/service_worker_subresource_loader.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
namespace content {
-class WorkerFetchContextImpl::URLLoaderFactoryImpl
- : public blink::WebURLLoaderFactory {
+WorkerFetchContextImpl::RewriteURLFunction g_rewrite_url = nullptr;
+
+namespace {
+
+// Runs on IO thread.
+void CreateSubresourceLoaderFactory(
+ mojom::ServiceWorkerContainerHostPtrInfo container_host_info,
+ const std::string& client_id,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory,
+ network::mojom::URLLoaderFactoryRequest request) {
+ ServiceWorkerSubresourceLoaderFactory::Create(
+ base::MakeRefCounted<ControllerServiceWorkerConnector>(
+ std::move(container_host_info), client_id),
+ network::SharedURLLoaderFactory::Create(std::move(fallback_factory)),
+ std::move(request));
+}
+
+} // namespace
+
+// static
+void WorkerFetchContextImpl::InstallRewriteURLFunction(
+ RewriteURLFunction rewrite_url) {
+ CHECK(!g_rewrite_url);
+ g_rewrite_url = rewrite_url;
+}
+
+// An implementation of WebURLLoaderFactory that is aware of service workers. In
+// the usual case, it creates a loader that uses |loader_factory_|. But if the
+// worker fetch context is controlled by a service worker, it creates a loader
+// that uses |service_worker_loader_factory_| for requests that should be
+// intercepted by the service worker.
+class WorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory {
public:
- URLLoaderFactoryImpl(
- base::WeakPtr<ResourceDispatcher> resource_dispatcher,
- scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
+ Factory(base::WeakPtr<ResourceDispatcher> resource_dispatcher,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
: resource_dispatcher_(std::move(resource_dispatcher)),
loader_factory_(std::move(loader_factory)),
weak_ptr_factory_(this) {}
- ~URLLoaderFactoryImpl() override = default;
+ ~Factory() override = default;
std::unique_ptr<blink::WebURLLoader> CreateURLLoader(
const blink::WebURLRequest& request,
@@ -49,15 +81,13 @@ class WorkerFetchContextImpl::URLLoaderFactoryImpl
}
void SetServiceWorkerURLLoaderFactory(
- network::mojom::URLLoaderFactoryPtr service_worker_url_loader_factory) {
- service_worker_url_loader_factory_ =
- base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
- std::move(service_worker_url_loader_factory));
+ network::mojom::URLLoaderFactoryPtr service_worker_loader_factory) {
+ service_worker_loader_factory_ =
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(service_worker_loader_factory));
}
- base::WeakPtr<URLLoaderFactoryImpl> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
+ base::WeakPtr<Factory> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
private:
std::unique_ptr<blink::WebURLLoader> CreateServiceWorkerURLLoader(
@@ -67,9 +97,9 @@ class WorkerFetchContextImpl::URLLoaderFactoryImpl
// ServiceWorkerNetworkProvider::CreateURLLoader that is used for document
// cases.
- // We need URLLoaderFactory populated in order to create our own URLLoader
- // for subresource loading via a service worker.
- if (!service_worker_url_loader_factory_)
+ // We need the service worker loader factory populated in order to create
+ // our own URLLoader for subresource loading via a service worker.
+ if (!service_worker_loader_factory_)
return nullptr;
// If it's not for HTTP or HTTPS no need to intercept the request.
@@ -82,36 +112,39 @@ class WorkerFetchContextImpl::URLLoaderFactoryImpl
// Create our own URLLoader to route the request to the controller service
// worker.
- return std::make_unique<WebURLLoaderImpl>(
- resource_dispatcher_.get(), std::move(task_runner),
- service_worker_url_loader_factory_);
+ return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(),
+ std::move(task_runner),
+ service_worker_loader_factory_);
}
base::WeakPtr<ResourceDispatcher> resource_dispatcher_;
scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
- scoped_refptr<network::SharedURLLoaderFactory>
- service_worker_url_loader_factory_;
- base::WeakPtrFactory<URLLoaderFactoryImpl> weak_ptr_factory_;
- DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryImpl);
+ scoped_refptr<network::SharedURLLoaderFactory> service_worker_loader_factory_;
+ base::WeakPtrFactory<Factory> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(Factory);
};
WorkerFetchContextImpl::WorkerFetchContextImpl(
mojom::ServiceWorkerWorkerClientRequest service_worker_client_request,
mojom::ServiceWorkerContainerHostPtrInfo service_worker_container_host_info,
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- url_loader_factory_info,
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- direct_network_factory_info,
- std::unique_ptr<URLLoaderThrottleProvider> throttle_provider)
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info,
+ std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
+ std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ websocket_handshake_throttle_provider,
+ ThreadSafeSender* thread_safe_sender,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: binding_(this),
service_worker_client_request_(std::move(service_worker_client_request)),
service_worker_container_host_info_(
std::move(service_worker_container_host_info)),
- url_loader_factory_info_(std::move(url_loader_factory_info)),
- direct_network_loader_factory_info_(
- std::move(direct_network_factory_info)),
- thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()),
- throttle_provider_(std::move(throttle_provider)) {
+ loader_factory_info_(std::move(loader_factory_info)),
+ fallback_factory_info_(std::move(fallback_factory_info)),
+ thread_safe_sender_(thread_safe_sender),
+ throttle_provider_(std::move(throttle_provider)),
+ websocket_handshake_throttle_provider_(
+ std::move(websocket_handshake_throttle_provider)),
+ io_task_runner_(std::move(io_task_runner)) {
if (ServiceWorkerUtils::IsServicificationEnabled()) {
ChildThreadImpl::current()->GetConnector()->BindInterface(
mojom::kBrowserServiceName,
@@ -127,6 +160,26 @@ void WorkerFetchContextImpl::SetTerminateSyncLoadEvent(
terminate_sync_load_event_ = terminate_sync_load_event;
}
+std::unique_ptr<blink::WebWorkerFetchContext>
+WorkerFetchContextImpl::CloneForNestedWorker() {
+ // TODO(japhet?): This doens't plumb service worker state to nested workers,
+ // because dedicated workers in service worker-controlled documents are
+ // currently not spec compliant and we don't want to propagate the wrong
+ // behavior. See https://crbug.com/731604
+ auto new_context = std::make_unique<WorkerFetchContextImpl>(
+ mojom::ServiceWorkerWorkerClientRequest(),
+ mojom::ServiceWorkerContainerHostPtrInfo(), loader_factory_->Clone(),
+ fallback_factory_->Clone(),
+ throttle_provider_ ? throttle_provider_->Clone() : nullptr,
+ websocket_handshake_throttle_provider_
+ ? websocket_handshake_throttle_provider_->Clone()
+ : nullptr,
+ thread_safe_sender_.get(), io_task_runner_);
+ new_context->is_on_sub_frame_ = is_on_sub_frame_;
+ new_context->appcache_host_id_ = appcache_host_id_;
+ return new_context;
+}
+
void WorkerFetchContextImpl::InitializeOnWorkerThread() {
DCHECK(!resource_dispatcher_);
DCHECK(!binding_.is_bound());
@@ -134,10 +187,10 @@ void WorkerFetchContextImpl::InitializeOnWorkerThread() {
resource_dispatcher_->set_terminate_sync_load_event(
terminate_sync_load_event_);
- shared_url_loader_factory_ = network::SharedURLLoaderFactory::Create(
- std::move(url_loader_factory_info_));
- direct_network_loader_factory_ = network::SharedURLLoaderFactory::Create(
- std::move(direct_network_loader_factory_info_));
+ loader_factory_ =
+ network::SharedURLLoaderFactory::Create(std::move(loader_factory_info_));
+ fallback_factory_ = network::SharedURLLoaderFactory::Create(
+ std::move(fallback_factory_info_));
if (service_worker_client_request_.is_pending())
binding_.Bind(std::move(service_worker_client_request_));
@@ -155,11 +208,11 @@ void WorkerFetchContextImpl::InitializeOnWorkerThread() {
std::unique_ptr<blink::WebURLLoaderFactory>
WorkerFetchContextImpl::CreateURLLoaderFactory() {
- DCHECK(shared_url_loader_factory_);
- DCHECK(!url_loader_factory_);
- auto factory = std::make_unique<URLLoaderFactoryImpl>(
- resource_dispatcher_->GetWeakPtr(), shared_url_loader_factory_);
- url_loader_factory_ = factory->GetWeakPtr();
+ DCHECK(loader_factory_);
+ DCHECK(!web_loader_factory_);
+ auto factory = std::make_unique<Factory>(resource_dispatcher_->GetWeakPtr(),
+ loader_factory_);
+ web_loader_factory_ = factory->GetWeakPtr();
if (ServiceWorkerUtils::IsServicificationEnabled())
ResetServiceWorkerURLLoaderFactory();
@@ -170,9 +223,9 @@ WorkerFetchContextImpl::CreateURLLoaderFactory() {
std::unique_ptr<blink::WebURLLoaderFactory>
WorkerFetchContextImpl::WrapURLLoaderFactory(
mojo::ScopedMessagePipeHandle url_loader_factory_handle) {
- return std::make_unique<content::WebURLLoaderFactoryImpl>(
+ return std::make_unique<WebURLLoaderFactoryImpl>(
resource_dispatcher_->GetWeakPtr(),
- base::MakeRefCounted<WrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
network::mojom::URLLoaderFactoryPtrInfo(
std::move(url_loader_factory_handle),
network::mojom::URLLoaderFactory::Version_)));
@@ -195,6 +248,9 @@ void WorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) {
// fetch.
request.SetSkipServiceWorker(true);
}
+
+ if (g_rewrite_url)
+ request.SetURL(g_rewrite_url(request.Url().GetString().Utf8(), false));
}
bool WorkerFetchContextImpl::IsControlledByServiceWorker() const {
@@ -244,6 +300,14 @@ WorkerFetchContextImpl::TakeSubresourceFilter() {
return std::move(subresource_filter_builder_)->Build();
}
+std::unique_ptr<blink::WebSocketHandshakeThrottle>
+WorkerFetchContextImpl::CreateWebSocketHandshakeThrottle() {
+ if (!websocket_handshake_throttle_provider_)
+ return nullptr;
+ return websocket_handshake_throttle_provider_->CreateThrottle(
+ parent_frame_id_);
+}
+
void WorkerFetchContextImpl::set_service_worker_provider_id(int id) {
service_worker_provider_id_ = id;
}
@@ -269,6 +333,10 @@ void WorkerFetchContextImpl::set_origin_url(const GURL& origin_url) {
origin_url_ = origin_url;
}
+void WorkerFetchContextImpl::set_client_id(const std::string& client_id) {
+ client_id_ = client_id;
+}
+
void WorkerFetchContextImpl::SetApplicationCacheHostID(int id) {
appcache_host_id_ = id;
}
@@ -290,19 +358,25 @@ bool WorkerFetchContextImpl::Send(IPC::Message* message) {
void WorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() {
DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
- if (!url_loader_factory_)
+ if (!web_loader_factory_)
return;
if (!IsControlledByServiceWorker()) {
- url_loader_factory_->SetServiceWorkerURLLoaderFactory(nullptr);
+ web_loader_factory_->SetServiceWorkerURLLoaderFactory(nullptr);
return;
}
+
network::mojom::URLLoaderFactoryPtr service_worker_url_loader_factory;
- ServiceWorkerSubresourceLoaderFactory::Create(
- base::MakeRefCounted<ControllerServiceWorkerConnector>(
- service_worker_container_host_.get()),
- direct_network_loader_factory_,
- mojo::MakeRequest(&service_worker_url_loader_factory));
- url_loader_factory_->SetServiceWorkerURLLoaderFactory(
+ mojom::ServiceWorkerContainerHostPtrInfo host_ptr_info;
+ service_worker_container_host_->CloneForWorker(
+ mojo::MakeRequest(&host_ptr_info));
+ // To avoid potential dead-lock while synchronous loading, create the
+ // SubresourceLoaderFactory on the IO thread.
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CreateSubresourceLoaderFactory, std::move(host_ptr_info),
+ client_id_, fallback_factory_->Clone(),
+ mojo::MakeRequest(&service_worker_url_loader_factory)));
+ web_loader_factory_->SetServiceWorkerURLLoaderFactory(
std::move(service_worker_url_loader_factory));
}
diff --git a/chromium/content/renderer/service_worker/worker_fetch_context_impl.h b/chromium/content/renderer/service_worker/worker_fetch_context_impl.h
index 7983e5f6631..82217aa61f7 100644
--- a/chromium/content/renderer/service_worker/worker_fetch_context_impl.h
+++ b/chromium/content/renderer/service_worker/worker_fetch_context_impl.h
@@ -27,33 +27,46 @@ namespace content {
class ResourceDispatcher;
class ThreadSafeSender;
class URLLoaderThrottleProvider;
+class WebSocketHandshakeThrottleProvider;
// This class is used while fetching resource requests on workers (dedicated
// worker and shared worker). This class is created on the main thread and
// passed to the worker thread. This class is not used for service workers. For
// service workers, ServiceWorkerFetchContextImpl class is used instead.
-class WorkerFetchContextImpl : public blink::WebWorkerFetchContext,
- public mojom::ServiceWorkerWorkerClient {
+class CONTENT_EXPORT WorkerFetchContextImpl
+ : public blink::WebWorkerFetchContext,
+ public mojom::ServiceWorkerWorkerClient {
public:
- // |url_loader_factory_info| is a generic URLLoaderFactory that may
- // contain multiple URLLoader factories for different schemes internally,
- // and used for regular resource loading from the worker context.
- // |direct_network_factory_info| is a URLLoader factory that directly
- // goes to the network, used when this context creates a
- // ServiceWorkerSubresourceLoader because it is controlled by a service
- // worker.
+ // |loader_factory_info| is used for regular loading by the worker.
+ //
+ // S13nServiceWorker:
+ // If the worker is controlled by a service worker, this class makes another
+ // loader factory which sends requests to the service worker, and passes
+ // |fallback_factory_info| to that factory to use for network fallback.
+ //
+ // |loader_factory_info| and |fallback_factory_info| are different because
+ // |loader_factory_info| can possibly include a default factory like AppCache,
+ // while |fallback_factory_info| should not have such a default factory and
+ // instead go directly to network for http(s) requests.
+ // |fallback_factory_info| might not be simply the direct network factory,
+ // because it might additionally support non-NetworkService schemes (e.g.,
+ // chrome-extension://).
WorkerFetchContextImpl(
mojom::ServiceWorkerWorkerClientRequest service_worker_client_request,
mojom::ServiceWorkerContainerHostPtrInfo
service_worker_container_host_info,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info,
std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- url_loader_factory_info,
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- direct_network_factory_info,
- std::unique_ptr<URLLoaderThrottleProvider> throttle_provider);
+ fallback_factory_info,
+ std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
+ std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ websocket_handshake_throttle_provider,
+ ThreadSafeSender* thread_safe_sender,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~WorkerFetchContextImpl() override;
// blink::WebWorkerFetchContext implementation:
+ std::unique_ptr<blink::WebWorkerFetchContext> CloneForNestedWorker() override;
void SetTerminateSyncLoadEvent(base::WaitableEvent*) override;
void InitializeOnWorkerThread() override;
std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override;
@@ -74,6 +87,8 @@ class WorkerFetchContextImpl : public blink::WebWorkerFetchContext,
std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder>) override;
std::unique_ptr<blink::WebDocumentSubresourceFilter> TakeSubresourceFilter()
override;
+ std::unique_ptr<blink::WebSocketHandshakeThrottle>
+ CreateWebSocketHandshakeThrottle() override;
// mojom::ServiceWorkerWorkerClient implementation:
void SetControllerServiceWorker(int64_t controller_version_id) override;
@@ -88,9 +103,13 @@ class WorkerFetchContextImpl : public blink::WebWorkerFetchContext,
// https://w3c.github.io/webappsec-secure-contexts/
void set_is_secure_context(bool flag);
void set_origin_url(const GURL& origin_url);
+ void set_client_id(const std::string& client_id);
+
+ using RewriteURLFunction = blink::WebURL (*)(const std::string&, bool);
+ static void InstallRewriteURLFunction(RewriteURLFunction rewrite_url);
private:
- class URLLoaderFactoryImpl;
+ class Factory;
bool Send(IPC::Message* message);
@@ -107,11 +126,10 @@ class WorkerFetchContextImpl : public blink::WebWorkerFetchContext,
mojom::ServiceWorkerWorkerClientRequest service_worker_client_request_;
// Consumed on the worker thread to create |service_worker_container_host_|.
mojom::ServiceWorkerContainerHostPtrInfo service_worker_container_host_info_;
- // Consumed on the worker thread to create |shared_url_loader_factory_|.
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info_;
- // Consumed on the worker thread to create |direct_network_loader_factory_|.
- std::unique_ptr<network::SharedURLLoaderFactoryInfo>
- direct_network_loader_factory_info_;
+ // Consumed on the worker thread to create |loader_factory_|.
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info_;
+ // Consumed on the worker thread to create |fallback_factory_|.
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info_;
// Consumed on the worker thread to create |blob_registry_|.
blink::mojom::BlobRegistryPtrInfo blob_registry_ptr_info_;
@@ -121,18 +139,26 @@ class WorkerFetchContextImpl : public blink::WebWorkerFetchContext,
// Initialized on the worker thread when InitializeOnWorkerThread() is called.
mojom::ServiceWorkerContainerHostPtr service_worker_container_host_;
+ // S13nServiceWorker:
+ // The Client#id value of the shared worker or dedicated worker (since
+ // dedicated workers are not yet service worker clients, it is the parent
+ // document's id in that case). Passed to ControllerServiceWorkerConnector.
+ std::string client_id_;
+
// Initialized on the worker thread when InitializeOnWorkerThread() is called.
std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
// Initialized on the worker thread when InitializeOnWorkerThread() is called.
- // |shared_url_loader_factory_| may be a bundled factory that contains
- // multiple factories for different schemes and to be used for regular
- // loading by the worker, while |direct_network_loader_factory_| is used
- // specifically to initialize ServiceWorkerSubresourceLoader for network
- // load that is controlled by a service worker (when this worker is a
- // client of the service worker).
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
- scoped_refptr<network::SharedURLLoaderFactory> direct_network_loader_factory_;
+ // |loader_factory_| is used for regular loading by the worker. In
+ // S13nServiceWorker, if the worker is controlled by a service worker, it
+ // creates a ServiceWorkerSubresourceLoaderFactory instead.
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
+
+ // Initialized on the worker thread when InitializeOnWorkerThread() is called.
+ // S13nServiceWorker: If the worker is controlled by a service worker, it
+ // passes this factory to ServiceWorkerSubresourceLoaderFactory to use for
+ // network fallback.
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory_;
// S13nServiceWorker:
// Initialized on the worker thread when InitializeOnWorkerThread() is called.
@@ -156,11 +182,15 @@ class WorkerFetchContextImpl : public blink::WebWorkerFetchContext,
// This is owned by ThreadedMessagingProxyBase on the main thread.
base::WaitableEvent* terminate_sync_load_event_ = nullptr;
- // A weak ptr to blink::WebURLLoaderFactory which was created and passed to
+ // The blink::WebURLLoaderFactory which was created and passed to
// Blink by CreateURLLoaderFactory().
- base::WeakPtr<URLLoaderFactoryImpl> url_loader_factory_;
+ base::WeakPtr<Factory> web_loader_factory_;
std::unique_ptr<URLLoaderThrottleProvider> throttle_provider_;
+ std::unique_ptr<WebSocketHandshakeThrottleProvider>
+ websocket_handshake_throttle_provider_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
};
} // namespace content
diff --git a/chromium/content/renderer/shared_memory_seqlock_reader.cc b/chromium/content/renderer/shared_memory_seqlock_reader.cc
deleted file mode 100644
index 0f06c393127..00000000000
--- a/chromium/content/renderer/shared_memory_seqlock_reader.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 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/renderer/shared_memory_seqlock_reader.h"
-
-namespace content {
-namespace internal {
-
-SharedMemorySeqLockReaderBase::SharedMemorySeqLockReaderBase() { }
-
-SharedMemorySeqLockReaderBase::~SharedMemorySeqLockReaderBase() { }
-
-void*
-SharedMemorySeqLockReaderBase::InitializeSharedMemory(
- base::SharedMemoryHandle shared_memory_handle, size_t buffer_size) {
- renderer_shared_memory_handle_ = shared_memory_handle;
- if (!base::SharedMemory::IsHandleValid(renderer_shared_memory_handle_))
- return nullptr;
- renderer_shared_memory_.reset(new base::SharedMemory(
- renderer_shared_memory_handle_, true));
-
- return (renderer_shared_memory_->Map(buffer_size))
- ? renderer_shared_memory_->memory()
- : nullptr;
-}
-
-bool SharedMemorySeqLockReaderBase::FetchFromBuffer(
- device::OneWriterSeqLock* seqlock,
- void* final,
- void* temp,
- void* from,
- size_t size) {
- if (!base::SharedMemory::IsHandleValid(renderer_shared_memory_handle_))
- return false;
-
- // Only try to read this many times before failing to avoid waiting here
- // very long in case of contention with the writer.
- int contention_count = -1;
- base::subtle::Atomic32 version;
- do {
- version = seqlock->ReadBegin();
- memcpy(temp, from, size);
- ++contention_count;
- if (contention_count == kMaximumContentionCount)
- break;
- } while (seqlock->ReadRetry(version));
-
- if (contention_count >= kMaximumContentionCount) {
- // We failed to successfully read, presumably because the hardware
- // thread was taking unusually long. Don't copy the data to the output
- // buffer, and simply leave what was there before.
- return false;
- }
-
- // New data was read successfully, copy it into the output buffer.
- memcpy(final, temp, size);
- return true;
-}
-
-} // namespace internal
-} // namespace content
diff --git a/chromium/content/renderer/shared_memory_seqlock_reader.h b/chromium/content/renderer/shared_memory_seqlock_reader.h
deleted file mode 100644
index a849e3470bc..00000000000
--- a/chromium/content/renderer/shared_memory_seqlock_reader.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2013 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_RENDERER_SHARED_MEMORY_SEQLOCK_READER_H_
-#define CONTENT_RENDERER_SHARED_MEMORY_SEQLOCK_READER_H_
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory.h"
-#include "device/base/synchronization/shared_memory_seqlock_buffer.h"
-
-namespace content {
-namespace internal {
-
-class SharedMemorySeqLockReaderBase {
- protected:
- SharedMemorySeqLockReaderBase();
- virtual ~SharedMemorySeqLockReaderBase();
-
- void* InitializeSharedMemory(
- base::SharedMemoryHandle shared_memory_handle,
- size_t buffer_size);
-
- bool FetchFromBuffer(device::OneWriterSeqLock* seqlock,
- void* final,
- void* temp,
- void* from,
- size_t size);
-
- static const int kMaximumContentionCount = 10;
- base::SharedMemoryHandle renderer_shared_memory_handle_;
- std::unique_ptr<base::SharedMemory> renderer_shared_memory_;
-};
-
-} // namespace internal
-
-// Template argument Data should be a pod-like structure only containing
-// data fields, such that it is copyable by memcpy method.
-template<typename Data>
-class SharedMemorySeqLockReader
- : private internal::SharedMemorySeqLockReaderBase {
- public:
- SharedMemorySeqLockReader() : buffer_(0) { }
- virtual ~SharedMemorySeqLockReader() { }
-
- bool GetLatestData(Data* data) {
- DCHECK(buffer_);
- DCHECK(sizeof(*data) == sizeof(*temp_buffer_));
- return FetchFromBuffer(&buffer_->seqlock, data, temp_buffer_.get(),
- &buffer_->data, sizeof(*temp_buffer_));
- }
-
- bool Initialize(base::SharedMemoryHandle shared_memory_handle) {
- if (void* memory = InitializeSharedMemory(
- shared_memory_handle,
- sizeof(device::SharedMemorySeqLockBuffer<Data>))) {
- buffer_ = static_cast<device::SharedMemorySeqLockBuffer<Data>*>(memory);
- temp_buffer_.reset(new Data);
- return true;
- }
- return false;
- }
-
- private:
- device::SharedMemorySeqLockBuffer<Data>* buffer_;
- std::unique_ptr<Data> temp_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedMemorySeqLockReader);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SHARED_MEMORY_SEQLOCK_READER_H_
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 56478f058ec..edf1d066262 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -8,15 +8,15 @@
#include <utility>
#include "base/feature_list.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/child/scoped_child_process_reference.h"
+#include "content/common/possibly_associated_wrapper_shared_url_loader_factory.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/appcache_info.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/origin_util.h"
-#include "content/public/common/weak_wrapper_shared_url_loader_factory.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/appcache/appcache_dispatcher.h"
#include "content/renderer/appcache/web_application_cache_host_impl.h"
@@ -28,6 +28,7 @@
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/worker_fetch_context_impl.h"
#include "ipc/ipc_message_macros.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/platform/interface_provider.h"
@@ -137,7 +138,7 @@ class WebServiceWorkerNetworkProviderForSharedWorker
// mojom::URLLoaderFactory pointer into SharedURLLoaderFactory.
return std::make_unique<WebURLLoaderImpl>(
render_thread->resource_dispatcher(), std::move(task_runner),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
provider_->script_loader_factory()));
}
@@ -162,7 +163,7 @@ class WebServiceWorkerNetworkProviderForSharedWorker
return std::make_unique<WebURLLoaderImpl>(
RenderThreadImpl::current()->resource_dispatcher(),
std::move(task_runner),
- base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
provider_->context()->GetSubresourceLoaderFactory()));
}
@@ -274,20 +275,20 @@ EmbeddedSharedWorkerStub::CreateApplicationCacheHost(
std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
EmbeddedSharedWorkerStub::CreateServiceWorkerNetworkProvider() {
- scoped_refptr<network::SharedURLLoaderFactory> direct_network_loader_factory;
+ scoped_refptr<network::SharedURLLoaderFactory> fallback_factory;
// current() may be null in tests.
if (RenderThreadImpl* render_thread = RenderThreadImpl::current()) {
- direct_network_loader_factory =
- base::MakeRefCounted<PossiblyAssociatedWrapperSharedURLLoaderFactory>(
- render_thread->blink_platform_impl()
- ->CreateNetworkURLLoaderFactory());
+ scoped_refptr<ChildURLLoaderFactoryBundle> bundle =
+ render_thread->blink_platform_impl()
+ ->CreateDefaultURLLoaderFactoryBundle();
+ fallback_factory = network::SharedURLLoaderFactory::Create(
+ bundle->CloneWithoutDefaultFactory());
}
std::unique_ptr<ServiceWorkerNetworkProvider> provider =
ServiceWorkerNetworkProvider::CreateForSharedWorker(
std::move(service_worker_provider_info_),
- std::move(script_loader_factory_info_),
- std::move(direct_network_loader_factory));
+ std::move(script_loader_factory_info_), std::move(fallback_factory));
return std::make_unique<WebServiceWorkerNetworkProviderForSharedWorker>(
std::move(provider), IsOriginSecure(url_));
}
@@ -328,22 +329,17 @@ EmbeddedSharedWorkerStub::CreateWorkerFetchContext(
RenderThreadImpl::current()
->blink_platform_impl()
->CreateDefaultURLLoaderFactoryBundle();
-
- auto direct_network_loader_factory =
- base::MakeRefCounted<PossiblyAssociatedWrapperSharedURLLoaderFactory>(
- RenderThreadImpl::current()
- ->blink_platform_impl()
- ->CreateNetworkURLLoaderFactory());
-
- DCHECK(url_loader_factory_bundle);
- DCHECK(direct_network_loader_factory);
-
auto worker_fetch_context = std::make_unique<WorkerFetchContextImpl>(
std::move(request), std::move(container_host_ptr_info),
url_loader_factory_bundle->Clone(),
- direct_network_loader_factory->Clone(),
+ url_loader_factory_bundle->CloneWithoutDefaultFactory(),
GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
- URLLoaderThrottleProviderType::kWorker));
+ URLLoaderThrottleProviderType::kWorker),
+ GetContentClient()
+ ->renderer()
+ ->CreateWebSocketHandshakeThrottleProvider(),
+ ChildThreadImpl::current()->thread_safe_sender(),
+ RenderThreadImpl::current()->GetIOTaskRunner());
// TODO(horo): To get the correct first_party_to_cookies for the shared
// worker, we need to check the all documents bounded by the shared worker.
@@ -363,6 +359,7 @@ EmbeddedSharedWorkerStub::CreateWorkerFetchContext(
worker_fetch_context->set_is_controlled_by_service_worker(
web_network_provider->HasControllerServiceWorker());
}
+ worker_fetch_context->set_client_id(context->client_id());
return std::move(worker_fetch_context);
}
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.cc b/chromium/content/renderer/speech_recognition_dispatcher.cc
index e69f9e5e5aa..248a3f1d117 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.cc
+++ b/chromium/content/renderer/speech_recognition_dispatcher.cc
@@ -12,8 +12,10 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "content/common/speech_recognition_messages.h"
+#include "content/public/common/service_names.mojom.h"
+#include "content/public/renderer/render_thread.h"
#include "content/renderer/render_frame_impl.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_speech_grammar.h"
@@ -32,36 +34,19 @@ namespace content {
SpeechRecognitionDispatcher::SpeechRecognitionDispatcher(
RenderFrame* render_frame)
- : RenderFrameObserver(render_frame),
- next_id_(1) {}
+ : RenderFrameObserver(render_frame) {}
SpeechRecognitionDispatcher::~SpeechRecognitionDispatcher() = default;
-bool SpeechRecognitionDispatcher::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SpeechRecognitionDispatcher, message)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_Started, OnRecognitionStarted)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_AudioStarted, OnAudioStarted)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_SoundStarted, OnSoundStarted)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_SoundEnded, OnSoundEnded)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_AudioEnded, OnAudioEnded)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_ErrorOccurred, OnErrorOccurred)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_Ended, OnRecognitionEnded)
- IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_ResultRetrieved,
- OnResultsRetrieved)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
void SpeechRecognitionDispatcher::OnDestruct() {
delete this;
}
void SpeechRecognitionDispatcher::WasHidden() {
-#if defined(OS_ANDROID) && BUILDFLAG(ENABLE_WEBRTC)
- Send(new SpeechRecognitionHostMsg_AbortAllRequests(routing_id()));
+#if defined(OS_ANDROID)
+ for (const auto& it : session_map_) {
+ it.second->Abort();
+ }
#endif
}
@@ -73,21 +58,35 @@ void SpeechRecognitionDispatcher::Start(
recognizer_client_ == recognizer_client);
recognizer_client_ = recognizer_client;
- SpeechRecognitionHostMsg_StartRequest_Params msg_params;
+ mojom::StartSpeechRecognitionRequestParamsPtr msg_params =
+ mojom::StartSpeechRecognitionRequestParams::New();
for (const WebSpeechGrammar& grammar : params.Grammars()) {
- msg_params.grammars.push_back(SpeechRecognitionGrammar(
- grammar.Src().GetString().Utf8(), grammar.Weight()));
+ msg_params->grammars.push_back(
+ mojom::SpeechRecognitionGrammar::New(grammar.Src(), grammar.Weight()));
}
- msg_params.language = params.Language().Utf8();
- msg_params.max_hypotheses = static_cast<uint32_t>(params.MaxAlternatives());
- msg_params.continuous = params.Continuous();
- msg_params.interim_results = params.InterimResults();
- msg_params.origin_url = params.Origin().ToString().Utf8();
- msg_params.render_frame_id = routing_id();
- msg_params.request_id = GetOrCreateIDForHandle(handle);
-
- // The handle mapping will be removed in |OnRecognitionEnd|.
- Send(new SpeechRecognitionHostMsg_StartRequest(msg_params));
+ msg_params->language = params.Language().Utf8();
+ msg_params->max_hypotheses = static_cast<uint32_t>(params.MaxAlternatives());
+ msg_params->continuous = params.Continuous();
+ msg_params->interim_results = params.InterimResults();
+ msg_params->origin = params.Origin();
+
+ mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info;
+ mojom::SpeechRecognitionSessionClientRequest client_request =
+ mojo::MakeRequest(&client_ptr_info);
+ bindings_.AddBinding(std::make_unique<SpeechRecognitionSessionClientImpl>(
+ this, handle, recognizer_client_),
+ std::move(client_request));
+
+ mojom::SpeechRecognitionSessionPtr session_client;
+ mojom::SpeechRecognitionSessionRequest request =
+ mojo::MakeRequest(&session_client);
+
+ AddHandle(handle, std::move(session_client));
+
+ msg_params->client = std::move(client_ptr_info);
+ msg_params->session_request = std::move(request);
+
+ GetSpeechRecognitionHost().Start(std::move(msg_params));
}
void SpeechRecognitionDispatcher::Stop(
@@ -96,8 +95,7 @@ void SpeechRecognitionDispatcher::Stop(
// Ignore a |stop| issued without a matching |start|.
if (recognizer_client_ != recognizer_client || !HandleExists(handle))
return;
- Send(new SpeechRecognitionHostMsg_StopCaptureRequest(
- routing_id(), GetOrCreateIDForHandle(handle)));
+ GetSession(handle)->StopCapture();
}
void SpeechRecognitionDispatcher::Abort(
@@ -106,28 +104,7 @@ void SpeechRecognitionDispatcher::Abort(
// Ignore an |abort| issued without a matching |start|.
if (recognizer_client_ != recognizer_client || !HandleExists(handle))
return;
- Send(new SpeechRecognitionHostMsg_AbortRequest(
- routing_id(), GetOrCreateIDForHandle(handle)));
-}
-
-void SpeechRecognitionDispatcher::OnRecognitionStarted(int request_id) {
- recognizer_client_.DidStart(GetHandleFromID(request_id));
-}
-
-void SpeechRecognitionDispatcher::OnAudioStarted(int request_id) {
- recognizer_client_.DidStartAudio(GetHandleFromID(request_id));
-}
-
-void SpeechRecognitionDispatcher::OnSoundStarted(int request_id) {
- recognizer_client_.DidStartSound(GetHandleFromID(request_id));
-}
-
-void SpeechRecognitionDispatcher::OnSoundEnded(int request_id) {
- recognizer_client_.DidEndSound(GetHandleFromID(request_id));
-}
-
-void SpeechRecognitionDispatcher::OnAudioEnded(int request_id) {
- recognizer_client_.DidEndAudio(GetHandleFromID(request_id));
+ GetSession(handle)->Abort();
}
static WebSpeechRecognizerClient::ErrorCode WebKitErrorCode(
@@ -160,37 +137,85 @@ static WebSpeechRecognizerClient::ErrorCode WebKitErrorCode(
return WebSpeechRecognizerClient::kOtherError;
}
-void SpeechRecognitionDispatcher::OnErrorOccurred(
- int request_id, const SpeechRecognitionError& error) {
- if (error.code == SPEECH_RECOGNITION_ERROR_NO_MATCH) {
- recognizer_client_.DidReceiveNoMatch(GetHandleFromID(request_id),
- WebSpeechRecognitionResult());
- } else {
- recognizer_client_.DidReceiveError(GetHandleFromID(request_id),
- WebString(), // TODO(primiano): message?
- WebKitErrorCode(error.code));
+void SpeechRecognitionDispatcher::AddHandle(
+ const blink::WebSpeechRecognitionHandle& handle,
+ mojom::SpeechRecognitionSessionPtr session) {
+ DCHECK(!HandleExists(handle));
+ session_map_[handle] = std::move(session);
+}
+
+bool SpeechRecognitionDispatcher::HandleExists(
+ const WebSpeechRecognitionHandle& handle) {
+ return session_map_.find(handle) != session_map_.end();
+}
+
+void SpeechRecognitionDispatcher::RemoveHandle(
+ const blink::WebSpeechRecognitionHandle& handle) {
+ session_map_.erase(handle);
+}
+
+mojom::SpeechRecognitionSession* SpeechRecognitionDispatcher::GetSession(
+ const blink::WebSpeechRecognitionHandle& handle) {
+ DCHECK(HandleExists(handle));
+ return session_map_[handle].get();
+}
+
+mojom::SpeechRecognizer&
+SpeechRecognitionDispatcher::GetSpeechRecognitionHost() {
+ if (!speech_recognition_host_) {
+ render_frame()->GetRemoteInterfaces()->GetInterface(
+ mojo::MakeRequest(&speech_recognition_host_));
}
+ return *speech_recognition_host_;
+}
+
+// ------------ SpeechRecognitionSessionClientImpl
+// ------------------------------------
+
+SpeechRecognitionSessionClientImpl::SpeechRecognitionSessionClientImpl(
+ SpeechRecognitionDispatcher* dispatcher,
+ const blink::WebSpeechRecognitionHandle& handle,
+ const blink::WebSpeechRecognizerClient& client)
+ : parent_dispatcher_(dispatcher), handle_(handle), web_client_(client) {}
+
+void SpeechRecognitionSessionClientImpl::Started() {
+ web_client_.DidStart(handle_);
+}
+
+void SpeechRecognitionSessionClientImpl::AudioStarted() {
+ web_client_.DidStartAudio(handle_);
}
-void SpeechRecognitionDispatcher::OnRecognitionEnded(int request_id) {
- // TODO(tommi): It is possible that the handle isn't found in the array if
- // the user just refreshed the page. It seems that we then get a notification
- // for the previously loaded instance of the page.
- auto iter = handle_map_.find(request_id);
- if (iter == handle_map_.end()) {
- DLOG(ERROR) << "OnRecognitionEnded called for a handle that doesn't exist";
+void SpeechRecognitionSessionClientImpl::SoundStarted() {
+ web_client_.DidStartSound(handle_);
+}
+
+void SpeechRecognitionSessionClientImpl::SoundEnded() {
+ web_client_.DidEndSound(handle_);
+}
+
+void SpeechRecognitionSessionClientImpl::AudioEnded() {
+ web_client_.DidEndAudio(handle_);
+}
+
+void SpeechRecognitionSessionClientImpl::ErrorOccurred(
+ const content::SpeechRecognitionError& error) {
+ if (error.code == SPEECH_RECOGNITION_ERROR_NO_MATCH) {
+ web_client_.DidReceiveNoMatch(handle_, WebSpeechRecognitionResult());
} else {
- WebSpeechRecognitionHandle handle = iter->second;
- // Note: we need to erase the handle from the map *before* calling didEnd.
- // didEnd may call back synchronously to start a new recognition session,
- // and we don't want to delete the handle from the map after that happens.
- handle_map_.erase(request_id);
- recognizer_client_.DidEnd(handle);
+ web_client_.DidReceiveError(handle_,
+ WebString(), // TODO(primiano): message?
+ WebKitErrorCode(error.code));
}
}
-void SpeechRecognitionDispatcher::OnResultsRetrieved(
- int request_id, const SpeechRecognitionResults& results) {
+void SpeechRecognitionSessionClientImpl::Ended() {
+ parent_dispatcher_->RemoveHandle(handle_);
+ web_client_.DidEnd(handle_);
+}
+
+void SpeechRecognitionSessionClientImpl::ResultRetrieved(
+ const std::vector<content::SpeechRecognitionResult>& results) {
size_t provisional_count =
std::count_if(results.begin(), results.end(),
[](const SpeechRecognitionResult& result) {
@@ -198,13 +223,14 @@ void SpeechRecognitionDispatcher::OnResultsRetrieved(
});
WebVector<WebSpeechRecognitionResult> provisional(provisional_count);
- WebVector<WebSpeechRecognitionResult> final(
- results.size() - provisional_count);
+ WebVector<WebSpeechRecognitionResult> final(results.size() -
+ provisional_count);
int provisional_index = 0, final_index = 0;
for (const SpeechRecognitionResult& result : results) {
- WebSpeechRecognitionResult* webkit_result = result.is_provisional ?
- &provisional[provisional_index++] : &final[final_index++];
+ WebSpeechRecognitionResult* webkit_result =
+ result.is_provisional ? &provisional[provisional_index++]
+ : &final[final_index++];
const size_t num_hypotheses = result.hypotheses.size();
WebVector<WebString> transcripts(num_hypotheses);
@@ -216,45 +242,7 @@ void SpeechRecognitionDispatcher::OnResultsRetrieved(
webkit_result->Assign(transcripts, confidences, !result.is_provisional);
}
- recognizer_client_.DidReceiveResults(GetHandleFromID(request_id), final,
- provisional);
-}
-
-int SpeechRecognitionDispatcher::GetOrCreateIDForHandle(
- const WebSpeechRecognitionHandle& handle) {
- // Search first for an existing mapping.
- auto iter = FindHandleInMap(handle);
- if (iter != handle_map_.end())
- return iter->first;
-
- // If no existing mapping found, create a new one.
- const int new_id = next_id_;
- handle_map_[new_id] = handle;
- ++next_id_;
- return new_id;
-}
-
-bool SpeechRecognitionDispatcher::HandleExists(
- const WebSpeechRecognitionHandle& handle) {
- return FindHandleInMap(handle) != handle_map_.end();
-}
-
-SpeechRecognitionDispatcher::HandleMap::iterator
-SpeechRecognitionDispatcher::FindHandleInMap(
- const blink::WebSpeechRecognitionHandle& handle) {
- return std::find_if(
- handle_map_.begin(), handle_map_.end(),
- [handle](const std::pair<const int, blink::WebSpeechRecognitionHandle>&
- mapping_pair) {
- return mapping_pair.second.Equals(handle);
- });
-}
-
-const WebSpeechRecognitionHandle& SpeechRecognitionDispatcher::GetHandleFromID(
- int request_id) {
- auto iter = handle_map_.find(request_id);
- CHECK(iter != handle_map_.end());
- return iter->second;
+ web_client_.DidReceiveResults(handle_, final, provisional);
}
} // namespace content
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.h b/chromium/content/renderer/speech_recognition_dispatcher.h
index d9055e769bf..eb261b705f0 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.h
+++ b/chromium/content/renderer/speech_recognition_dispatcher.h
@@ -9,8 +9,10 @@
#include <memory>
#include "base/macros.h"
+#include "content/common/speech_recognizer.mojom.h"
#include "content/public/common/speech_recognition_result.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "third_party/blink/public/web/web_speech_recognition_handle.h"
#include "third_party/blink/public/web/web_speech_recognizer.h"
#include "third_party/blink/public/web/web_speech_recognizer_client.h"
@@ -20,7 +22,9 @@ struct SpeechRecognitionError;
// SpeechRecognitionDispatcher is a delegate for methods used by WebKit for
// scripted JS speech APIs. It's the complement of
-// SpeechRecognitionDispatcherHost (owned by RenderFrameHost).
+// SpeechRecognitionDispatcherHost (owned by RenderFrameHost), and communicates
+// with it using two mojo interfaces (SpeechRecognizer and
+// SpeechRecognitionSession).
class SpeechRecognitionDispatcher : public RenderFrameObserver,
public blink::WebSpeechRecognizer {
public:
@@ -28,10 +32,7 @@ class SpeechRecognitionDispatcher : public RenderFrameObserver,
~SpeechRecognitionDispatcher() override;
private:
- using HandleMap = std::map<int, blink::WebSpeechRecognitionHandle>;
-
// RenderFrameObserver implementation.
- bool OnMessageReceived(const IPC::Message& message) override;
void OnDestruct() override;
void WasHidden() override;
@@ -44,30 +45,74 @@ class SpeechRecognitionDispatcher : public RenderFrameObserver,
void Abort(const blink::WebSpeechRecognitionHandle&,
const blink::WebSpeechRecognizerClient&) override;
- void OnRecognitionStarted(int request_id);
- void OnAudioStarted(int request_id);
- void OnSoundStarted(int request_id);
- void OnSoundEnded(int request_id);
- void OnAudioEnded(int request_id);
- void OnErrorOccurred(int request_id, const SpeechRecognitionError& error);
- void OnRecognitionEnded(int request_id);
- void OnResultsRetrieved(int request_id,
- const SpeechRecognitionResults& result);
-
- int GetOrCreateIDForHandle(const blink::WebSpeechRecognitionHandle& handle);
+ // Methods to interact with |session_map_|
+ void AddHandle(const blink::WebSpeechRecognitionHandle& handle,
+ mojom::SpeechRecognitionSessionPtr session);
bool HandleExists(const blink::WebSpeechRecognitionHandle& handle);
- HandleMap::iterator FindHandleInMap(
+ void RemoveHandle(const blink::WebSpeechRecognitionHandle& handle);
+ mojom::SpeechRecognitionSession* GetSession(
const blink::WebSpeechRecognitionHandle& handle);
- const blink::WebSpeechRecognitionHandle& GetHandleFromID(int handle_id);
+
+ mojom::SpeechRecognizer& GetSpeechRecognitionHost();
+
+ // InterfacePtr used to communicate with SpeechRecognitionDispatcherHost to
+ // start a session for each WebSpeechRecognitionHandle.
+ mojom::SpeechRecognizerPtr speech_recognition_host_;
// The Blink client class that we use to send events back to the JS world.
+ // This is passed to each SpeechRecognitionSessionClientImpl instance.
blink::WebSpeechRecognizerClient recognizer_client_;
- // This maps between request id values and the Blink handle values.
- HandleMap handle_map_;
- int next_id_;
+ // Owns a SpeechRecognitionSessionClientImpl for each session created. The
+ // bindings are automatically cleaned up when the connection is closed by the
+ // browser process. We use mojo::StrongBindingSet instead of using
+ // mojo::MakeStrongBinding for each individual binding as
+ // SpeechRecognitionSessionClientImpl holds a pointer to its parent
+ // SpeechRecognitionDispatcher, and we need to clean up the
+ // SpeechRecognitionSessionClientImpl objects when |this| is deleted.
+ mojo::StrongBindingSet<mojom::SpeechRecognitionSessionClient> bindings_;
+
+ // Owns a SpeechRecognitionSessionPtr per session created. Each
+ // WebSpeechRecognitionHandle has its own speech recognition session, and is
+ // used as a key for the map.
+ using SessionMap = std::map<blink::WebSpeechRecognitionHandle,
+ mojom::SpeechRecognitionSessionPtr>;
+ SessionMap session_map_;
DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionDispatcher);
+ friend class SpeechRecognitionSessionClientImpl;
+};
+
+// SpeechRecognitionSessionClientImpl is owned by SpeechRecognitionDispatcher
+// and is cleaned up either when the end point is closed by the browser process,
+// or if SpeechRecognitionDispatcher is deleted.
+class SpeechRecognitionSessionClientImpl
+ : public mojom::SpeechRecognitionSessionClient {
+ public:
+ SpeechRecognitionSessionClientImpl(
+ SpeechRecognitionDispatcher* dispatcher,
+ const blink::WebSpeechRecognitionHandle& handle,
+ const blink::WebSpeechRecognizerClient& client);
+ ~SpeechRecognitionSessionClientImpl() override = default;
+
+ // mojom::SpeechRecognitionSessionClient implementation
+ void Started() override;
+ void AudioStarted() override;
+ void SoundStarted() override;
+ void SoundEnded() override;
+ void AudioEnded() override;
+ void ErrorOccurred(const content::SpeechRecognitionError& error) override;
+ void Ended() override;
+ void ResultRetrieved(
+ const std::vector<content::SpeechRecognitionResult>& results) override;
+
+ private:
+ // Not owned, |parent_dispatcher_| owns |this|.
+ SpeechRecognitionDispatcher* parent_dispatcher_;
+ // WebSpeechRecognitionHandle that this instance is associated with.
+ blink::WebSpeechRecognitionHandle handle_;
+ // The Blink client class that we use to send events back to the JS world.
+ blink::WebSpeechRecognizerClient web_client_;
};
} // namespace content
diff --git a/chromium/content/renderer/visual_state_browsertest.cc b/chromium/content/renderer/visual_state_browsertest.cc
index 2b819e5565f..e01ae0c286e 100644
--- a/chromium/content/renderer/visual_state_browsertest.cc
+++ b/chromium/content/renderer/visual_state_browsertest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/run_loop.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
@@ -73,7 +73,7 @@ class VisualStateTest : public ContentBrowserTest {
}
void AssertIsIdle() {
- ASSERT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
+ ASSERT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
}
void InvokeVisualStateCallback(bool result) {
diff --git a/chromium/content/renderer/web_ui_extension.cc b/chromium/content/renderer/web_ui_extension.cc
index eb05e6c365b..dd7b5fd5880 100644
--- a/chromium/content/renderer/web_ui_extension.cc
+++ b/chromium/content/renderer/web_ui_extension.cc
@@ -122,7 +122,6 @@ void WebUIExtension::Send(gin::Arguments* args) {
// Send the message up to the browser.
render_frame->Send(new FrameHostMsg_WebUISend(render_frame->GetRoutingID(),
- frame->GetDocument().Url(),
message, *content));
}
diff --git a/chromium/content/renderer/webfileutilities_impl.cc b/chromium/content/renderer/webfileutilities_impl.cc
deleted file mode 100644
index c3cab39e2e0..00000000000
--- a/chromium/content/renderer/webfileutilities_impl.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 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/renderer/webfileutilities_impl.h"
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "content/renderer/file_info_util.h"
-#include "net/base/filename_util.h"
-#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/web_file_info.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-
-using blink::WebString;
-
-namespace content {
-
-WebFileUtilitiesImpl::WebFileUtilitiesImpl()
- : sandbox_enabled_(true) {
-}
-
-WebFileUtilitiesImpl::~WebFileUtilitiesImpl() = default;
-
-bool WebFileUtilitiesImpl::GetFileInfo(const WebString& path,
- blink::WebFileInfo& web_file_info) {
- if (sandbox_enabled_) {
- NOTREACHED();
- return false;
- }
- base::File::Info file_info;
- if (!base::GetFileInfo(blink::WebStringToFilePath(path), &file_info))
- return false;
-
- FileInfoToWebFileInfo(file_info, &web_file_info);
- web_file_info.platform_path = path;
- return true;
-}
-
-WebString WebFileUtilitiesImpl::DirectoryName(const WebString& path) {
- return blink::FilePathToWebString(blink::WebStringToFilePath(path).DirName());
-}
-
-WebString WebFileUtilitiesImpl::BaseName(const WebString& path) {
- return blink::FilePathToWebString(
- blink::WebStringToFilePath(path).BaseName());
-}
-
-blink::WebURL WebFileUtilitiesImpl::FilePathToURL(const WebString& path) {
- return net::FilePathToFileURL(blink::WebStringToFilePath(path));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/webfileutilities_impl.h b/chromium/content/renderer/webfileutilities_impl.h
deleted file mode 100644
index 00c573d758d..00000000000
--- a/chromium/content/renderer/webfileutilities_impl.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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_RENDERER_WEBFILEUTILITIES_IMPL_H_
-#define CONTENT_RENDERER_WEBFILEUTILITIES_IMPL_H_
-
-#include "content/common/content_export.h"
-#include "third_party/blink/public/platform/web_file_info.h"
-#include "third_party/blink/public/platform/web_file_utilities.h"
-
-namespace content {
-
-class CONTENT_EXPORT WebFileUtilitiesImpl : public blink::WebFileUtilities {
- public:
- WebFileUtilitiesImpl();
- virtual ~WebFileUtilitiesImpl();
-
- // WebFileUtilities methods:
- bool GetFileInfo(const blink::WebString& path,
- blink::WebFileInfo& result) override;
- blink::WebString DirectoryName(const blink::WebString& path) override;
- blink::WebString BaseName(const blink::WebString& path) override;
- blink::WebURL FilePathToURL(const blink::WebString& path) override;
-
- void set_sandbox_enabled(bool sandbox_enabled) {
- sandbox_enabled_ = sandbox_enabled;
- }
-
- protected:
- bool sandbox_enabled_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_WEBFILEUTILITIES_IMPL_H_
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
index db9fcf58a91..ad82d6cfea9 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -70,11 +70,6 @@ void WebGraphicsContext3DProviderImpl::SetErrorMessageCallback(
provider_->ContextSupport()->SetErrorMessageCallback(std::move(c));
}
-void WebGraphicsContext3DProviderImpl::SignalQuery(uint32_t query,
- base::OnceClosure callback) {
- provider_->ContextSupport()->SignalQuery(query, std::move(callback));
-}
-
void WebGraphicsContext3DProviderImpl::OnContextLost() {
if (!context_lost_callback_.is_null())
context_lost_callback_.Run();
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
index 13742b62686..97d65fcdcf0 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -51,7 +51,6 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
void SetLostContextCallback(base::RepeatingClosure) override;
void SetErrorMessageCallback(
base::RepeatingCallback<void(const char*, int32_t)>) override;
- void SignalQuery(uint32_t, base::OnceClosure) override;
cc::ImageDecodeCache* ImageDecodeCache() override;
ui::ContextProviderCommandBuffer* context_provider() const {
diff --git a/chromium/content/renderer/worker_thread_message_filter.cc b/chromium/content/renderer/worker_thread_message_filter.cc
index 081764da7f4..f1f259f7c15 100644
--- a/chromium/content/renderer/worker_thread_message_filter.cc
+++ b/chromium/content/renderer/worker_thread_message_filter.cc
@@ -4,6 +4,7 @@
#include "content/renderer/worker_thread_message_filter.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/child/thread_safe_sender.h"
#include "content/renderer/worker_thread_registry.h"
diff --git a/chromium/content/shell/BUILD.gn b/chromium/content/shell/BUILD.gn
index 744a78e7aa5..bd604be447c 100644
--- a/chromium/content/shell/BUILD.gn
+++ b/chromium/content/shell/BUILD.gn
@@ -19,6 +19,7 @@ if (is_android) {
} else if (is_mac) {
import("//build/config/mac/rules.gni")
import("//build/mac/tweak_info_plist.gni")
+ import("//ui/gl/features.gni")
import("//third_party/icu/config.gni")
import("//v8/gni/v8.gni")
}
@@ -45,6 +46,14 @@ source_set("android_shell_descriptors") {
]
}
+source_set("layout_test_switches") {
+ testonly = true
+ sources = [
+ "common/layout_test/layout_test_switches.cc",
+ "common/layout_test/layout_test_switches.h",
+ ]
+}
+
static_library("content_shell_lib") {
testonly = true
sources = [
@@ -101,6 +110,8 @@ static_library("content_shell_lib") {
"browser/layout_test/layout_test_push_messaging_service.h",
"browser/layout_test/layout_test_url_request_context_getter.cc",
"browser/layout_test/layout_test_url_request_context_getter.h",
+ "browser/layout_test/leak_detector.cc",
+ "browser/layout_test/leak_detector.h",
"browser/layout_test/mojo_layout_test_helper.cc",
"browser/layout_test/mojo_layout_test_helper.h",
"browser/layout_test/secondary_test_window_observer.cc",
@@ -164,9 +175,6 @@ static_library("content_shell_lib") {
"common/layout_test/layout_test_content_client.h",
"common/layout_test/layout_test_messages.cc",
"common/layout_test/layout_test_messages.h",
- "common/layout_test/layout_test_switches.cc",
- "common/layout_test/layout_test_switches.h",
- "common/leak_detection_result.h",
"common/power_monitor_test_impl.cc",
"common/power_monitor_test_impl.h",
"common/shell_content_client.cc",
@@ -189,14 +197,12 @@ static_library("content_shell_lib") {
"renderer/layout_test/layout_test_render_frame_observer.h",
"renderer/layout_test/layout_test_render_thread_observer.cc",
"renderer/layout_test/layout_test_render_thread_observer.h",
- "renderer/layout_test/leak_detector.cc",
- "renderer/layout_test/leak_detector.h",
"renderer/layout_test/test_media_stream_renderer_factory.cc",
"renderer/layout_test/test_media_stream_renderer_factory.h",
"renderer/layout_test/test_media_stream_video_renderer.cc",
"renderer/layout_test/test_media_stream_video_renderer.h",
- "renderer/layout_test/test_websocket_handshake_throttle.cc",
- "renderer/layout_test/test_websocket_handshake_throttle.h",
+ "renderer/layout_test/test_websocket_handshake_throttle_provider.cc",
+ "renderer/layout_test/test_websocket_handshake_throttle_provider.h",
"renderer/shell_content_renderer_client.cc",
"renderer/shell_content_renderer_client.h",
"renderer/shell_render_view_observer.cc",
@@ -231,6 +237,7 @@ static_library("content_shell_lib") {
]
deps = [
":content_shell_packaged_services_manifest_overlay",
+ ":layout_test_switches",
":mojo_bindings",
":resources",
"//base",
@@ -275,6 +282,7 @@ static_library("content_shell_lib") {
"//sandbox",
"//services/device/public/mojom",
"//services/network/public/cpp",
+ "//services/service_manager/embedder:embedder_result_codes",
"//services/service_manager/public/cpp",
"//services/test/echo:lib",
"//services/test/echo/public/mojom",
@@ -725,9 +733,11 @@ if (is_mac) {
":content_shell_lib",
]
deps = [
+ ":content_shell_angle_library",
":content_shell_framework_helpers",
":content_shell_framework_resources",
":content_shell_framework_xibs",
+ ":content_shell_swiftshader_library",
"//third_party/icu:icudata",
]
@@ -816,6 +826,52 @@ if (is_mac) {
"{{bundle_resources_dir}}/{{source_file_part}}",
]
}
+
+ if (use_egl) {
+ # Add the ANGLE .dylibs in the MODULE_DIR of Chromium.app
+ bundle_data("content_shell_angle_binaries") {
+ sources = [
+ "$root_out_dir/egl_intermediates/libEGL.dylib",
+ "$root_out_dir/egl_intermediates/libGLESv2.dylib",
+ ]
+ outputs = [
+ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}",
+ ]
+ public_deps = [
+ "//ui/gl:angle_library_copy",
+ ]
+ }
+
+ # Add the SwiftShader .dylibs in the MODULE_DIR of Chromium.app
+ bundle_data("content_shell_swiftshader_binaries") {
+ sources = [
+ "$root_out_dir/egl_intermediates/libswiftshader_libEGL.dylib",
+ "$root_out_dir/egl_intermediates/libswiftshader_libGLESv2.dylib",
+ ]
+ outputs = [
+ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}",
+ ]
+ public_deps = [
+ "//ui/gl:swiftshader_library_copy",
+ ]
+ }
+ }
+
+ group("content_shell_angle_library") {
+ if (use_egl) {
+ deps = [
+ ":content_shell_angle_binaries",
+ ]
+ }
+ }
+
+ group("content_shell_swiftshader_library") {
+ if (use_egl) {
+ deps = [
+ ":content_shell_swiftshader_binaries",
+ ]
+ }
+ }
}
mojom("mojo_bindings") {
diff --git a/chromium/content/shell/android/BUILD.gn b/chromium/content/shell/android/BUILD.gn
index 89dd771d675..a0560dde21a 100644
--- a/chromium/content/shell/android/BUILD.gn
+++ b/chromium/content/shell/android/BUILD.gn
@@ -52,6 +52,20 @@ shared_library("libcontent_shell_content_view") {
]
}
+shared_library("libcontent_native_test") {
+ testonly = true
+ deps = [
+ ":content_test_jni_registration",
+ "//base",
+ "//content/public/test/android:content_native_test_support",
+ "//content/shell:content_shell_lib",
+ ]
+
+ sources = [
+ "shell_test_library_loader.cc",
+ ]
+}
+
android_resources("content_shell_java_resources") {
testonly = true
resource_dirs = [ "java/res" ]
@@ -197,6 +211,13 @@ android_library("content_shell_test_java") {
]
}
+generate_jni_registration("content_test_jni_registration") {
+ testonly = true
+ target = ":content_shell_test_apk__apk"
+ output = "$root_gen_dir/content/shell/android/${target_name}.h"
+ exception_files = jni_exception_files
+}
+
instrumentation_test_apk("content_shell_test_apk") {
deps = [
"//base:base_java_test_support",
@@ -207,6 +228,7 @@ instrumentation_test_apk("content_shell_test_apk") {
]
apk_under_test = ":content_shell_apk"
apk_name = "ContentShellTest"
+ shared_libraries = [ ":libcontent_native_test" ]
android_manifest = "javatests/AndroidManifest.xml"
}
diff --git a/chromium/content/shell/common/layout_test.mojom b/chromium/content/shell/common/layout_test.mojom
index edf929138da..5b4599b13cf 100644
--- a/chromium/content/shell/common/layout_test.mojom
+++ b/chromium/content/shell/common/layout_test.mojom
@@ -16,9 +16,6 @@ struct ShellTestConfiguration {
// The temporary directory of the system.
mojo_base.mojom.FilePath temp_path;
- // The build directory.
- mojo_base.mojom.FilePath build_directory;
-
// The URL of the current layout test.
url.mojom.Url test_url;
@@ -51,6 +48,8 @@ struct LayoutTestDump {
interface LayoutTestControl {
CaptureDump() => (LayoutTestDump result);
+ [Sync] CompositeWithRaster() => ();
+
// Dumps the frame's contents into a string.
DumpFrameLayout() => (string frame_layout_dump);
diff --git a/chromium/content/shell/common/layout_test/layout_test_messages.h b/chromium/content/shell/common/layout_test/layout_test_messages.h
index 8ea62b62aa2..bb578680743 100644
--- a/chromium/content/shell/common/layout_test/layout_test_messages.h
+++ b/chromium/content/shell/common/layout_test/layout_test_messages.h
@@ -44,8 +44,9 @@ IPC_MESSAGE_ROUTED4(LayoutTestHostMsg_SetPermission,
GURL /* embedding_origin */)
IPC_MESSAGE_ROUTED0(LayoutTestHostMsg_ResetPermissions)
IPC_MESSAGE_ROUTED0(LayoutTestHostMsg_InspectSecondaryWindow)
-IPC_MESSAGE_ROUTED1(LayoutTestHostMsg_InitiateCaptureDump,
- bool /* should dump navigation history */)
+IPC_MESSAGE_ROUTED2(LayoutTestHostMsg_InitiateCaptureDump,
+ bool /* should dump navigation history */,
+ bool /* should dump pixels */)
// Notifies the browser that one of renderers has changed layout test runtime
// flags (i.e. has set dump_as_text).
diff --git a/chromium/content/shell/common/layout_test/layout_test_switches.cc b/chromium/content/shell/common/layout_test/layout_test_switches.cc
index 33d22938d07..8aa83ee7444 100644
--- a/chromium/content/shell/common/layout_test/layout_test_switches.cc
+++ b/chromium/content/shell/common/layout_test/layout_test_switches.cc
@@ -4,9 +4,6 @@
#include "content/shell/common/layout_test/layout_test_switches.h"
-#include "base/command_line.h"
-#include "base/strings/string_split.h"
-
namespace switches {
// Allow access to external pages during layout tests.
@@ -24,6 +21,7 @@ const char kAndroidStdoutPort[] = "android-stdout-port";
#endif // defined(OS_ANDROID)
// Check whether all system dependencies for running layout tests are met.
+// TODO(tkent): Rename this to "check-web-test-sys-deps".
const char kCheckLayoutTestSysDeps[] = "check-layout-test-sys-deps";
// When specified to "enable-leak-detection" command-line option,
@@ -54,7 +52,7 @@ const char kEncodeBinary[] = "encode-binary";
// Request the render trees of pages to be dumped as text once they have
// finished loading.
-const char kRunLayoutTest[] = "run-layout-test";
+const char kRunWebTests[] = "run-web-tests";
// This makes us disable some web-platform runtime features so that we test
// content_shell as if it was a stable release. It is only followed when
@@ -62,4 +60,9 @@ const char kRunLayoutTest[] = "run-layout-test";
// http://dev.chromium.org/blink/runtime-enabled-features.
const char kStableReleaseMode[] = "stable-release-mode";
+// Enable pixel dumps via "real" surface readbacks, instead of synchronously
+// compositing and reading back pixels.
+const char kEnableDisplayCompositorPixelDump[] =
+ "enable-display-compositor-pixel-dump";
+
} // namespace switches
diff --git a/chromium/content/shell/common/layout_test/layout_test_switches.h b/chromium/content/shell/common/layout_test/layout_test_switches.h
index 11f3b295d0c..6fb69476b73 100644
--- a/chromium/content/shell/common/layout_test/layout_test_switches.h
+++ b/chromium/content/shell/common/layout_test/layout_test_switches.h
@@ -29,8 +29,9 @@ extern const char kEnableFontAntialiasing[];
extern const char kAlwaysUseComplexText[];
extern const char kEnableLeakDetection[];
extern const char kEncodeBinary[];
-extern const char kRunLayoutTest[];
+extern const char kRunWebTests[];
extern const char kStableReleaseMode[];
+extern const char kEnableDisplayCompositorPixelDump[];
} // namespace switches
diff --git a/chromium/content/shell/common/leak_detection_result.h b/chromium/content/shell/common/leak_detection_result.h
deleted file mode 100644
index 873a172a592..00000000000
--- a/chromium/content/shell/common/leak_detection_result.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 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_SHELL_COMMON_LEAK_DETECTION_RESULT_H_
-#define CONTENT_SHELL_COMMON_LEAK_DETECTION_RESULT_H_
-
-#include <string>
-
-namespace content {
-
-struct LeakDetectionResult {
- bool leaked;
- std::string detail;
-};
-
-} // namespace content
-
-#endif // CONTENT_SHELL_COMMON_LEAK_DETECTION_RESULT_H_
diff --git a/chromium/content/shell/common/shell_content_client.cc b/chromium/content/shell/common/shell_content_client.cc
index c73f4985237..5042ed84fa8 100644
--- a/chromium/content/shell/common/shell_content_client.cc
+++ b/chromium/content/shell/common/shell_content_client.cc
@@ -37,7 +37,7 @@ std::string ShellContentClient::GetUserAgent() const {
}
base::string16 ShellContentClient::GetLocalizedString(int message_id) const {
- if (switches::IsRunLayoutTestSwitchPresent()) {
+ if (switches::IsRunWebTestsSwitchPresent()) {
switch (message_id) {
case IDS_FORM_OTHER_DATE_LABEL:
return base::ASCIIToUTF16("<<OtherDateLabel>>");
@@ -61,7 +61,7 @@ base::string16 ShellContentClient::GetLocalizedString(int message_id) const {
base::StringPiece ShellContentClient::GetDataResource(
int resource_id,
ui::ScaleFactor scale_factor) const {
- if (switches::IsRunLayoutTestSwitchPresent()) {
+ if (switches::IsRunWebTestsSwitchPresent()) {
switch (resource_id) {
case IDR_BROKENIMAGE:
#if defined(OS_MACOSX)
@@ -87,7 +87,7 @@ gfx::Image& ShellContentClient::GetNativeImageNamed(int resource_id) const {
resource_id);
}
-OriginTrialPolicy* ShellContentClient::GetOriginTrialPolicy() {
+blink::OriginTrialPolicy* ShellContentClient::GetOriginTrialPolicy() {
return &origin_trial_policy_;
}
diff --git a/chromium/content/shell/common/shell_content_client.h b/chromium/content/shell/common/shell_content_client.h
index c3334355664..635f4931283 100644
--- a/chromium/content/shell/common/shell_content_client.h
+++ b/chromium/content/shell/common/shell_content_client.h
@@ -10,7 +10,6 @@
#include "base/compiler_specific.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/origin_trial_policy.h"
#include "content/shell/common/shell_origin_trial_policy.h"
namespace content {
@@ -30,7 +29,7 @@ class ShellContentClient : public ContentClient {
base::RefCountedMemory* GetDataResourceBytes(
int resource_id) const override;
gfx::Image& GetNativeImageNamed(int resource_id) const override;
- OriginTrialPolicy* GetOriginTrialPolicy() override;
+ blink::OriginTrialPolicy* GetOriginTrialPolicy() override;
private:
ShellOriginTrialPolicy origin_trial_policy_;
diff --git a/chromium/content/shell/common/shell_messages.h b/chromium/content/shell/common/shell_messages.h
index be22d21a605..ab7755403b2 100644
--- a/chromium/content/shell/common/shell_messages.h
+++ b/chromium/content/shell/common/shell_messages.h
@@ -9,7 +9,6 @@
#include "base/values.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/page_state.h"
-#include "content/shell/common/leak_detection_result.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -21,16 +20,10 @@
// Tells the renderer to reset all test runners.
IPC_MESSAGE_ROUTED0(ShellViewMsg_Reset)
-// Sets the path to the WebKit checkout.
-IPC_MESSAGE_CONTROL1(ShellViewMsg_SetWebKitSourceDir,
- base::FilePath /* webkit source dir */)
-
// Tells the main window that a secondary renderer in a different process asked
// to finish the test.
IPC_MESSAGE_ROUTED0(ShellViewMsg_TestFinishedInSecondaryRenderer)
-IPC_MESSAGE_ROUTED0(ShellViewMsg_TryLeakDetection)
-
// Notifies BlinkTestRunner that the layout dump has completed
// (and that it can proceed with finishing up the test).
IPC_MESSAGE_ROUTED1(ShellViewMsg_LayoutDumpCompleted,
@@ -67,14 +60,6 @@ IPC_MESSAGE_ROUTED2(ShellViewHostMsg_LoadURLForFrame,
std::string /* frame_name */)
IPC_MESSAGE_ROUTED0(ShellViewHostMsg_CloseRemainingWindows)
-IPC_STRUCT_TRAITS_BEGIN(content::LeakDetectionResult)
-IPC_STRUCT_TRAITS_MEMBER(leaked)
-IPC_STRUCT_TRAITS_MEMBER(detail)
-IPC_STRUCT_TRAITS_END()
-
-IPC_MESSAGE_ROUTED1(ShellViewHostMsg_LeakDetectionDone,
- content::LeakDetectionResult /* result */)
-
IPC_MESSAGE_ROUTED1(ShellViewHostMsg_SetBluetoothManualChooser,
bool /* enable */)
IPC_MESSAGE_ROUTED0(ShellViewHostMsg_GetBluetoothManualChooserEvents)
diff --git a/chromium/content/shell/common/shell_origin_trial_policy.cc b/chromium/content/shell/common/shell_origin_trial_policy.cc
index a90ea358146..7654e8a9f0d 100644
--- a/chromium/content/shell/common/shell_origin_trial_policy.cc
+++ b/chromium/content/shell/common/shell_origin_trial_policy.cc
@@ -4,6 +4,10 @@
#include "content/shell/common/shell_origin_trial_policy.h"
+#include "base/feature_list.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/origin_util.h"
+
namespace content {
namespace {
@@ -17,6 +21,7 @@ static const uint8_t kOriginTrialPublicKey[] = {
0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
};
+
} // namespace
ShellOriginTrialPolicy::ShellOriginTrialPolicy()
@@ -26,8 +31,16 @@ ShellOriginTrialPolicy::ShellOriginTrialPolicy()
ShellOriginTrialPolicy::~ShellOriginTrialPolicy() {}
+bool ShellOriginTrialPolicy::IsOriginTrialsSupported() const {
+ return base::FeatureList::IsEnabled(features::kOriginTrials);
+}
+
base::StringPiece ShellOriginTrialPolicy::GetPublicKey() const {
return public_key_;
}
+bool ShellOriginTrialPolicy::IsOriginSecure(const GURL& url) const {
+ return content::IsOriginSecure(url);
+}
+
} // namespace content
diff --git a/chromium/content/shell/common/shell_origin_trial_policy.h b/chromium/content/shell/common/shell_origin_trial_policy.h
index c55584fe761..08b8e3ff28c 100644
--- a/chromium/content/shell/common/shell_origin_trial_policy.h
+++ b/chromium/content/shell/common/shell_origin_trial_policy.h
@@ -7,17 +7,19 @@
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "content/public/common/origin_trial_policy.h"
+#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
namespace content {
-class ShellOriginTrialPolicy : public OriginTrialPolicy {
+class ShellOriginTrialPolicy : public blink::OriginTrialPolicy {
public:
ShellOriginTrialPolicy();
~ShellOriginTrialPolicy() override;
- // OriginTrialPolicy interface
+ // blink::OriginTrialPolicy interface
+ bool IsOriginTrialsSupported() const override;
base::StringPiece GetPublicKey() const override;
+ bool IsOriginSecure(const GURL& url) const override;
private:
base::StringPiece public_key_;
diff --git a/chromium/content/shell/common/shell_switches.cc b/chromium/content/shell/common/shell_switches.cc
index d196d3c6b22..de877107f61 100644
--- a/chromium/content/shell/common/shell_switches.cc
+++ b/chromium/content/shell/common/shell_switches.cc
@@ -58,9 +58,9 @@ std::vector<std::string> GetSideloadFontFiles() {
return files;
}
-bool IsRunLayoutTestSwitchPresent() {
+bool IsRunWebTestsSwitchPresent() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kRunLayoutTest);
+ switches::kRunWebTests);
}
} // namespace switches
diff --git a/chromium/content/shell/common/shell_switches.h b/chromium/content/shell/common/shell_switches.h
index a06d39e9d55..0215d011f15 100644
--- a/chromium/content/shell/common/shell_switches.h
+++ b/chromium/content/shell/common/shell_switches.h
@@ -25,11 +25,11 @@ extern const char kContentShellAlwaysFork[];
// Returns list of extra font files to be made accessible to the renderer.
std::vector<std::string> GetSideloadFontFiles();
-// Tells if content shell is running layout tests.
+// Tells if content shell is running web_tests.
// TODO(lukasza): The function below somewhat violates the layering (by
// enabling shell -> layout_tests dependency) but at least narrows the extent of
// the dependency to a single switch...
-bool IsRunLayoutTestSwitchPresent();
+bool IsRunWebTestsSwitchPresent();
} // namespace switches
diff --git a/chromium/content/shell/test_runner/BUILD.gn b/chromium/content/shell/test_runner/BUILD.gn
index 1beed186f2d..33d550d2b6e 100644
--- a/chromium/content/shell/test_runner/BUILD.gn
+++ b/chromium/content/shell/test_runner/BUILD.gn
@@ -38,8 +38,6 @@ component("test_runner") {
"mock_screen_orientation_client.h",
"mock_spell_check.cc",
"mock_spell_check.h",
- "mock_web_audio_device.cc",
- "mock_web_audio_device.h",
"mock_web_document_subresource_filter.cc",
"mock_web_document_subresource_filter.h",
"mock_web_midi_accessor.cc",
@@ -97,11 +95,11 @@ component("test_runner") {
"//base:base",
"//base:i18n",
"//cc",
- "//cc/blink",
"//cc/paint",
"//components/viz/common",
"//content/public/common",
"//content/public/renderer",
+ "//content/shell:layout_test_switches",
"//content/test:test_runner_support",
"//device/gamepad/public/cpp:shared_with_blink",
"//gin",
@@ -134,30 +132,6 @@ component("test_runner") {
}
# Font copies.
-if (!is_mac) {
- copy("copy_ahem") {
- visibility = [ ":*" ]
- sources = [
- "resources/fonts/AHEM____.TTF",
- ]
- outputs = [
- "$root_out_dir/AHEM____.TTF",
- ]
- }
-}
-if (use_x11) {
- copy("copy_x11_fonts") {
- # TODO(sergeyu): Move these fonts to third_party/test_fonts .
- visibility = [ ":*" ]
- sources = [
- "//third_party/gardiner_mod/GardinerModBug.ttf",
- "//third_party/gardiner_mod/GardinerModCat.ttf",
- ]
- outputs = [
- "$root_out_dir/{{source_file_part}}",
- ]
- }
-}
if (is_android || is_fuchsia) {
copy("copy_android_fonts_config") {
visibility = [ ":*" ]
@@ -172,8 +146,12 @@ if (is_android || is_fuchsia) {
}
if (is_mac) {
bundle_data("test_runner_bundle_data") {
+ public_deps = [
+ "//third_party/test_fonts",
+ ]
+
sources = [
- "resources/fonts/AHEM____.TTF",
+ "$root_out_dir/test_fonts/Ahem.ttf",
"resources/fonts/ChromiumAATTest.ttf",
]
@@ -191,20 +169,12 @@ group("resources") {
deps += [ ":test_runner_bundle_data" ]
data_deps += [ ":test_runner_bundle_data" ]
} else {
- deps += [ ":copy_ahem" ]
- data_deps += [ ":copy_ahem" ]
+ deps += [ "//third_party/test_fonts" ]
+ data_deps += [ "//third_party/test_fonts" ]
}
- if (use_x11) {
- deps += [ ":copy_x11_fonts" ]
- data_deps += [ ":copy_x11_fonts" ]
- }
if (is_android || is_fuchsia) {
deps += [ ":copy_android_fonts_config" ]
data_deps += [ ":copy_android_fonts_config" ]
}
- if (is_android || is_linux || is_fuchsia) {
- deps += [ "//third_party/test_fonts" ]
- data_deps += [ "//third_party/test_fonts" ]
- }
}
diff --git a/chromium/content/test/BUILD.gn b/chromium/content/test/BUILD.gn
index f8a43bd3ff1..c1d0124e86f 100644
--- a/chromium/content/test/BUILD.gn
+++ b/chromium/content/test/BUILD.gn
@@ -174,6 +174,18 @@ jumbo_static_library("test_support") {
"../public/test/web_contents_binding_set_test_binder.h",
"../public/test/web_contents_tester.cc",
"../public/test/web_contents_tester.h",
+ "../renderer/media/stream/mock_mojo_media_stream_dispatcher_host.cc",
+ "../renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h",
+ "../renderer/media/webrtc/mock_data_channel_impl.cc",
+ "../renderer/media/webrtc/mock_data_channel_impl.h",
+ "../renderer/media/webrtc/mock_peer_connection_dependency_factory.cc",
+ "../renderer/media/webrtc/mock_peer_connection_dependency_factory.h",
+ "../renderer/media/webrtc/mock_peer_connection_impl.cc",
+ "../renderer/media/webrtc/mock_peer_connection_impl.h",
+ "../renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc",
+ "../renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h",
+ "../renderer/media/webrtc/test/webrtc_stats_report_obtainer.cc",
+ "../renderer/media/webrtc/test/webrtc_stats_report_obtainer.h",
"accessibility_browser_test_utils.cc",
"accessibility_browser_test_utils.h",
"appcache_test_helper.cc",
@@ -194,10 +206,15 @@ jumbo_static_library("test_support") {
"fake_plugin_service.h",
"fake_renderer_compositor_frame_sink.cc",
"fake_renderer_compositor_frame_sink.h",
+ "gmock_util.h",
"gpu_browsertest_helpers.cc",
"gpu_browsertest_helpers.h",
+ "leveldb_wrapper_test_util.cc",
+ "leveldb_wrapper_test_util.h",
"mock_background_sync_controller.cc",
"mock_background_sync_controller.h",
+ "mock_clipboard_host.cc",
+ "mock_clipboard_host.h",
"mock_keyboard.cc",
"mock_keyboard.h",
"mock_keyboard_driver_win.cc",
@@ -213,8 +230,6 @@ jumbo_static_library("test_support") {
"mock_ssl_host_state_delegate.h",
"mock_webblob_registry_impl.cc",
"mock_webblob_registry_impl.h",
- "mock_webclipboard_impl.cc",
- "mock_webclipboard_impl.h",
"mock_widget_impl.cc",
"mock_widget_impl.h",
"mock_widget_input_handler.cc",
@@ -223,6 +238,8 @@ jumbo_static_library("test_support") {
"net/url_request_abort_on_end_job.h",
"ppapi_unittest.cc",
"ppapi_unittest.h",
+ "storage_partition_test_utils.cc",
+ "storage_partition_test_utils.h",
"test_background_sync_context.cc",
"test_background_sync_context.h",
"test_background_sync_manager.cc",
@@ -289,8 +306,6 @@ jumbo_static_library("test_support") {
":content_test_mojo_bindings",
"//base/third_party/dynamic_annotations",
"//cc:test_support",
- "//cc/blink",
- "//cc/ipc",
"//components/services/leveldb/public/interfaces",
"//components/viz/host",
"//components/viz/service",
@@ -335,6 +350,14 @@ jumbo_static_library("test_support") {
"//storage/common",
"//testing/gmock",
"//testing/gtest",
+ "//third_party/webrtc/api:libjingle_peerconnection_api",
+ "//third_party/webrtc/api:rtc_stats_api",
+ "//third_party/webrtc/media:rtc_media_base",
+ "//third_party/webrtc/modules/video_capture",
+ "//third_party/webrtc/pc:libjingle_peerconnection",
+ "//third_party/webrtc/rtc_base:rtc_base_approved",
+ "//third_party/webrtc/stats:rtc_stats",
+ "//third_party/webrtc_overrides:init_webrtc",
"//tools/v8_context_snapshot:v8_context_snapshot",
"//ui/accessibility:ax_enums_mojo",
"//ui/base",
@@ -385,34 +408,6 @@ jumbo_static_library("test_support") {
]
}
- if (enable_webrtc) {
- sources += [
- "../renderer/media/stream/mock_mojo_media_stream_dispatcher_host.cc",
- "../renderer/media/stream/mock_mojo_media_stream_dispatcher_host.h",
- "../renderer/media/webrtc/mock_data_channel_impl.cc",
- "../renderer/media/webrtc/mock_data_channel_impl.h",
- "../renderer/media/webrtc/mock_peer_connection_dependency_factory.cc",
- "../renderer/media/webrtc/mock_peer_connection_dependency_factory.h",
- "../renderer/media/webrtc/mock_peer_connection_impl.cc",
- "../renderer/media/webrtc/mock_peer_connection_impl.h",
- "../renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc",
- "../renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h",
- "../renderer/media/webrtc/test/webrtc_stats_report_obtainer.cc",
- "../renderer/media/webrtc/test/webrtc_stats_report_obtainer.h",
- ]
-
- deps += [
- "//third_party/webrtc/api:libjingle_peerconnection_api",
- "//third_party/webrtc/api:rtc_stats_api",
- "//third_party/webrtc/media:rtc_media_base",
- "//third_party/webrtc/modules/video_capture",
- "//third_party/webrtc/pc:libjingle_peerconnection",
- "//third_party/webrtc/rtc_base:rtc_base_approved",
- "//third_party/webrtc/stats:rtc_stats",
- "//third_party/webrtc_overrides:init_webrtc",
- ]
- }
-
if (use_glib) {
configs += [ "//build/config/linux:glib" ]
}
@@ -602,6 +597,7 @@ static_library("layouttest_support") {
"//content/public/common",
"//content/public/renderer",
"//content/renderer:for_content_tests",
+ "//content/shell:layout_test_switches",
"//content/shell/test_runner:test_runner",
"//device/bluetooth",
"//device/gamepad/public/cpp:shared_with_blink",
@@ -727,9 +723,10 @@ test("content_browsertests") {
"../browser/download/mhtml_generation_browsertest.cc",
"../browser/download/save_package_browsertest.cc",
"../browser/fileapi/file_system_browsertest.cc",
+ "../browser/fileapi/file_system_url_loader_factory_browsertest.cc",
"../browser/fileapi/fileapi_browsertest.cc",
"../browser/find_request_manager_browsertest.cc",
- "../browser/frame_host/data_url_navigation_browsertest.cc",
+ "../browser/frame_host/blocked_scheme_navigation_browsertest.cc",
"../browser/frame_host/form_submission_throttle_browsertest.cc",
"../browser/frame_host/frame_tree_browsertest.cc",
"../browser/frame_host/interstitial_page_impl_browsertest.cc",
@@ -738,6 +735,7 @@ test("content_browsertests") {
"../browser/frame_host/render_frame_host_impl_browsertest.cc",
"../browser/frame_host/render_frame_host_manager_browsertest.cc",
"../browser/frame_host/render_frame_message_filter_browsertest.cc",
+ "../browser/frame_host/webui_navigation_browsertest.cc",
"../browser/generic_sensor/generic_sensor_browsertest.cc",
"../browser/gpu/gpu_ipc_browsertests.cc",
"../browser/gpu/in_process_gpu_thread_browsertests.cc",
@@ -746,11 +744,13 @@ test("content_browsertests") {
"../browser/indexed_db/mock_browsertest_indexed_db_class_factory.h",
"../browser/isolated_origin_browsertest.cc",
"../browser/keyboard_lock_browsertest.cc",
+ "../browser/keyboard_lock_browsertest.h",
+ "../browser/keyboard_lock_browsertest_mac.mm",
"../browser/loader/cors_file_origin_browsertest.cc",
"../browser/loader/cross_site_document_blocking_browsertest.cc",
+ "../browser/loader/loader_browsertest.cc",
"../browser/loader/prefetch_browsertest.cc",
"../browser/loader/reload_cache_control_browsertest.cc",
- "../browser/loader/resource_dispatcher_host_browsertest.cc",
"../browser/loader/resource_scheduler_browsertest.cc",
"../browser/manifest/manifest_browsertest.cc",
"../browser/media/encrypted_media_browsertest.cc",
@@ -830,6 +830,27 @@ test("content_browsertests") {
"../browser/web_contents_binding_set_browsertest.cc",
"../browser/web_package/web_package_request_handler_browsertest.cc",
"../browser/webkit_browsertest.cc",
+ "../browser/webrtc/webrtc_audio_browsertest.cc",
+ "../browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc",
+ "../browser/webrtc/webrtc_browsertest.cc",
+ "../browser/webrtc/webrtc_capture_from_element_browsertest.cc",
+ "../browser/webrtc/webrtc_constraints_browsertest.cc",
+ "../browser/webrtc/webrtc_content_browsertest_base.cc",
+ "../browser/webrtc/webrtc_content_browsertest_base.h",
+ "../browser/webrtc/webrtc_data_browsertest.cc",
+ "../browser/webrtc/webrtc_datachannel_browsertest.cc",
+ "../browser/webrtc/webrtc_depth_capture_browsertest.cc",
+ "../browser/webrtc/webrtc_getusermedia_browsertest.cc",
+ "../browser/webrtc/webrtc_image_capture_browsertest.cc",
+ "../browser/webrtc/webrtc_internals_browsertest.cc",
+ "../browser/webrtc/webrtc_ip_permissions_browsertest.cc",
+ "../browser/webrtc/webrtc_media_recorder_browsertest.cc",
+ "../browser/webrtc/webrtc_stress_pause_browsertest.cc",
+ "../browser/webrtc/webrtc_stress_resolution_switch_browsertest.cc",
+ "../browser/webrtc/webrtc_stress_source_switch_browsertest.cc",
+ "../browser/webrtc/webrtc_video_capture_browsertest.cc",
+ "../browser/webrtc/webrtc_webcam_browsertest.cc",
+ "../browser/webrtc/webrtc_webcam_browsertest.h",
"../browser/webui/web_ui_mojo_browsertest.cc",
"../renderer/accessibility/render_accessibility_impl_browsertest.cc",
"../renderer/blink_platform_audio_hardware_browsertest.cc",
@@ -883,6 +904,7 @@ test("content_browsertests") {
"//content/public/browser",
"//content/public/child",
"//content/public/common",
+ "//content/public/common:buildflags",
"//content/public/gpu",
"//content/public/renderer",
"//content/renderer:for_content_tests",
@@ -916,11 +938,12 @@ test("content_browsertests") {
"//services/video_capture/public/mojom:constants",
"//services/viz/privileged/interfaces",
"//storage/browser",
+ "//storage/browser:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/blink/public:blink",
"//third_party/leveldatabase",
- "//third_party/libaom:av1_features",
+ "//third_party/libaom:av1_buildflags",
"//third_party/mesa:osmesa",
"//third_party/zlib",
"//ui/accessibility",
@@ -972,7 +995,21 @@ test("content_browsertests") {
}
if (is_linux || is_mac || is_win) {
- sources += [ "../browser/media/capture/web_contents_video_capture_device_browsertest.cc" ]
+ sources += [
+ "../browser/media/capture/content_capture_device_browsertest_base.cc",
+ "../browser/media/capture/content_capture_device_browsertest_base.h",
+ "../browser/media/capture/fake_video_capture_stack.cc",
+ "../browser/media/capture/fake_video_capture_stack.h",
+ "../browser/media/capture/frame_test_util.cc",
+ "../browser/media/capture/frame_test_util.h",
+ "../browser/media/capture/web_contents_video_capture_device_browsertest.cc",
+ ]
+
+ # For chromecast, content_browsertests does not provide a shell window.
+ if (use_aura && !is_chromecast) {
+ sources += [ "../browser/media/capture/aura_window_video_capture_device_browsertest.cc" ]
+ }
+
deps += [ "//third_party/libyuv" ]
data += [
"//net/tools/testserver/",
@@ -1086,36 +1123,6 @@ test("content_browsertests") {
[ "../browser/compositor/image_transport_factory_browsertest.cc" ]
}
- if (enable_webrtc) {
- sources += [
- "../browser/webrtc/webrtc_audio_browsertest.cc",
- "../browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc",
- "../browser/webrtc/webrtc_browsertest.cc",
- "../browser/webrtc/webrtc_capture_from_element_browsertest.cc",
- "../browser/webrtc/webrtc_constraints_browsertest.cc",
- "../browser/webrtc/webrtc_content_browsertest_base.cc",
- "../browser/webrtc/webrtc_content_browsertest_base.h",
- "../browser/webrtc/webrtc_data_browsertest.cc",
- "../browser/webrtc/webrtc_datachannel_browsertest.cc",
- "../browser/webrtc/webrtc_depth_capture_browsertest.cc",
- "../browser/webrtc/webrtc_getusermedia_browsertest.cc",
- "../browser/webrtc/webrtc_image_capture_browsertest.cc",
- "../browser/webrtc/webrtc_internals_browsertest.cc",
- "../browser/webrtc/webrtc_ip_permissions_browsertest.cc",
- "../browser/webrtc/webrtc_media_recorder_browsertest.cc",
- "../browser/webrtc/webrtc_stress_pause_browsertest.cc",
- "../browser/webrtc/webrtc_stress_resolution_switch_browsertest.cc",
- "../browser/webrtc/webrtc_stress_source_switch_browsertest.cc",
- "../browser/webrtc/webrtc_video_capture_browsertest.cc",
- "../browser/webrtc/webrtc_webcam_browsertest.cc",
- "../browser/webrtc/webrtc_webcam_browsertest.h",
- ]
- deps += [
- "//content/public/common:buildflags",
- "//testing/perf",
- ]
- }
-
if (enable_plugins) {
sources += [
"../browser/plugin_service_impl_browsertest.cc",
@@ -1177,9 +1184,9 @@ test("content_browsertests") {
# can inspect.
"../browser/media/media_color_browsertest.cc",
- # The cast shell has plugin support but no pdf, causing data URL PDF tests
- # to fail.
- "../browser/frame_host/data_url_navigation_browsertest.cc",
+ # The cast shell has plugin support but no pdf, causing blocked scheme PDF
+ # tests to fail.
+ "../browser/frame_host/blocked_scheme_navigation_browsertest.cc",
# The multi-window tests don't work on cast_shell. Since there's little
# added value in running the single-window test on this platform, just
@@ -1263,6 +1270,7 @@ test("content_unittests") {
"../browser/compositor/gpu_vsync_begin_frame_source_unittest.cc",
"../browser/compositor/reflector_impl_unittest.cc",
"../browser/compositor/software_browser_compositor_output_surface_unittest.cc",
+ "../browser/cookie_store/cookie_store_manager_unittest.cc",
"../browser/devtools/devtools_http_handler_unittest.cc",
"../browser/devtools/devtools_manager_unittest.cc",
"../browser/devtools/devtools_video_consumer_unittest.cc",
@@ -1271,7 +1279,18 @@ test("content_unittests") {
"../browser/dom_storage/dom_storage_context_impl_unittest.cc",
"../browser/dom_storage/dom_storage_database_unittest.cc",
"../browser/dom_storage/local_storage_context_mojo_unittest.cc",
+ "../browser/dom_storage/session_storage_context_mojo_unittest.cc",
+ "../browser/dom_storage/session_storage_data_map_unittest.cc",
"../browser/dom_storage/session_storage_database_unittest.cc",
+ "../browser/dom_storage/session_storage_leveldb_wrapper_unittest.cc",
+ "../browser/dom_storage/session_storage_metadata_unittest.cc",
+ "../browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc",
+ "../browser/dom_storage/test/fake_leveldb_database_error_on_write.cc",
+ "../browser/dom_storage/test/fake_leveldb_database_error_on_write.h",
+ "../browser/dom_storage/test/fake_leveldb_service.cc",
+ "../browser/dom_storage/test/fake_leveldb_service.h",
+ "../browser/dom_storage/test/mojo_test_with_file_service.cc",
+ "../browser/dom_storage/test/mojo_test_with_file_service.h",
"../browser/download/download_manager_impl_unittest.cc",
"../browser/download/download_request_core_unittest.cc",
"../browser/download/save_package_unittest.cc",
@@ -1340,7 +1359,7 @@ test("content_unittests") {
"../browser/loader/mock_resource_loader.cc",
"../browser/loader/mock_resource_loader.h",
"../browser/loader/mojo_async_resource_handler_unittest.cc",
- "../browser/loader/navigation_url_loader_network_service_unittest.cc",
+ "../browser/loader/navigation_url_loader_impl_unittest.cc",
"../browser/loader/navigation_url_loader_unittest.cc",
"../browser/loader/redirect_to_file_resource_handler_unittest.cc",
"../browser/loader/resource_buffer_unittest.cc",
@@ -1357,10 +1376,15 @@ test("content_unittests") {
"../browser/manifest/manifest_icon_downloader_unittest.cc",
"../browser/manifest/manifest_icon_selector_unittest.cc",
"../browser/media/audible_metrics_unittest.cc",
+ "../browser/media/audio_input_stream_broker_unittest.cc",
+ "../browser/media/audio_loopback_stream_broker_unittest.cc",
+ "../browser/media/audio_output_stream_broker_unittest.cc",
"../browser/media/audio_stream_monitor_unittest.cc",
"../browser/media/capture/audio_mirroring_manager_unittest.cc",
"../browser/media/capture/web_contents_audio_input_stream_unittest.cc",
"../browser/media/cdm_registry_impl_unittest.cc",
+ "../browser/media/flinging_renderer_unittest.cc",
+ "../browser/media/forwarding_audio_stream_factory_unittest.cc",
"../browser/media/media_devices_permission_checker_unittest.cc",
"../browser/media/media_internals_unittest.cc",
"../browser/media/midi_host_unittest.cc",
@@ -1392,14 +1416,14 @@ test("content_unittests") {
"../browser/payments/payment_manager_unittest.cc",
"../browser/presentation/presentation_service_impl_unittest.cc",
"../browser/renderer_host/clipboard_host_impl_unittest.cc",
- "../browser/renderer_host/compositor_resize_lock_unittest.cc",
"../browser/renderer_host/cursor_manager_unittest.cc",
"../browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc",
+ "../browser/renderer_host/embedded_frame_sink_provider_impl_unittest.cc",
"../browser/renderer_host/frame_token_message_queue_unittest.cc",
"../browser/renderer_host/input/fling_controller_unittest.cc",
+ "../browser/renderer_host/input/fling_scheduler_unittest.cc",
"../browser/renderer_host/input/gesture_event_queue_unittest.cc",
"../browser/renderer_host/input/input_router_impl_unittest.cc",
- "../browser/renderer_host/input/legacy_input_router_impl_unittest.cc",
"../browser/renderer_host/input/mock_input_disposition_handler.cc",
"../browser/renderer_host/input/mock_input_disposition_handler.h",
"../browser/renderer_host/input/mock_input_router_client.cc",
@@ -1420,11 +1444,10 @@ test("content_unittests") {
"../browser/renderer_host/input/web_input_event_util_unittest.cc",
"../browser/renderer_host/media/audio_input_delegate_impl_unittest.cc",
"../browser/renderer_host/media/audio_input_device_manager_unittest.cc",
- "../browser/renderer_host/media/audio_input_renderer_host_unittest.cc",
"../browser/renderer_host/media/audio_input_stream_handle_unittest.cc",
"../browser/renderer_host/media/audio_output_authorization_handler_unittest.cc",
"../browser/renderer_host/media/audio_output_delegate_impl_unittest.cc",
- "../browser/renderer_host/media/audio_renderer_host_unittest.cc",
+ "../browser/renderer_host/media/audio_service_listener_unittest.cc",
"../browser/renderer_host/media/fake_video_capture_device_launcher.cc",
"../browser/renderer_host/media/fake_video_capture_device_launcher.h",
"../browser/renderer_host/media/fake_video_capture_provider.cc",
@@ -1436,6 +1459,8 @@ test("content_unittests") {
"../browser/renderer_host/media/media_stream_ui_proxy_unittest.cc",
"../browser/renderer_host/media/mock_video_capture_provider.cc",
"../browser/renderer_host/media/mock_video_capture_provider.h",
+ "../browser/renderer_host/media/old_render_frame_audio_input_stream_factory_unittest.cc",
+ "../browser/renderer_host/media/old_render_frame_audio_output_stream_factory_unittest.cc",
"../browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc",
"../browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc",
"../browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc",
@@ -1444,8 +1469,12 @@ test("content_unittests") {
"../browser/renderer_host/media/video_capture_controller_unittest.cc",
"../browser/renderer_host/media/video_capture_manager_unittest.cc",
"../browser/renderer_host/media/video_capture_unittest.cc",
- "../browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc",
"../browser/renderer_host/overscroll_controller_unittest.cc",
+ "../browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc",
+ "../browser/renderer_host/p2p/socket_host_tcp_unittest.cc",
+ "../browser/renderer_host/p2p/socket_host_test_utils.cc",
+ "../browser/renderer_host/p2p/socket_host_test_utils.h",
+ "../browser/renderer_host/p2p/socket_host_udp_unittest.cc",
"../browser/renderer_host/render_process_host_unittest.cc",
"../browser/renderer_host/render_view_host_unittest.cc",
"../browser/renderer_host/render_widget_host_input_event_router_unittest.cc",
@@ -1485,6 +1514,9 @@ test("content_unittests") {
"../browser/service_worker/service_worker_version_unittest.cc",
"../browser/service_worker/service_worker_write_to_cache_job_unittest.cc",
"../browser/shareable_file_reference_unittest.cc",
+ "../browser/shared_worker/mock_shared_worker.cc",
+ "../browser/shared_worker/mock_shared_worker.h",
+ "../browser/shared_worker/shared_worker_host_unittest.cc",
"../browser/shared_worker/shared_worker_instance_unittest.cc",
"../browser/shared_worker/shared_worker_service_impl_unittest.cc",
"../browser/site_instance_impl_unittest.cc",
@@ -1513,6 +1545,8 @@ test("content_unittests") {
"../browser/web_package/signed_exchange_header_parser_unittest.cc",
"../browser/web_package/signed_exchange_header_unittest.cc",
"../browser/web_package/signed_exchange_signature_verifier_unittest.cc",
+ "../browser/webrtc/webrtc_internals_message_handler_unittest.cc",
+ "../browser/webrtc/webrtc_internals_unittest.cc",
"../browser/websockets/websocket_manager_unittest.cc",
"../browser/webui/url_data_manager_backend_unittest.cc",
"../browser/webui/web_ui_data_source_unittest.cc",
@@ -1536,11 +1570,9 @@ test("content_unittests") {
"../common/indexed_db/indexed_db_key_unittest.cc",
"../common/input/event_with_latency_info_unittest.cc",
"../common/input/gesture_event_stream_validator_unittest.cc",
- "../common/input/input_param_traits_unittest.cc",
"../common/input/touch_event_stream_validator_unittest.cc",
"../common/inter_process_time_ticks_converter_unittest.cc",
"../common/mac/attributed_string_coder_unittest.mm",
- "../common/manifest_share_target_util_unittest.cc",
"../common/manifest_util_unittest.cc",
"../common/media/media_devices_unittest.cc",
"../common/notifications/notification_struct_traits_unittest.cc",
@@ -1587,7 +1619,7 @@ test("content_unittests") {
"../renderer/indexed_db/mock_webidbcallbacks.h",
"../renderer/indexed_db/webidbcursor_impl_unittest.cc",
"../renderer/indexed_db/webidbdatabase_impl_unittest.cc",
- "../renderer/input/input_event_filter_unittest.cc",
+ "../renderer/input/input_event_prediction_unittest.cc",
"../renderer/input/main_thread_event_queue_unittest.cc",
"../renderer/loader/resource_dispatcher_unittest.cc",
"../renderer/loader/shared_memory_data_consumer_handle_unittest.cc",
@@ -1598,7 +1630,6 @@ test("content_unittests") {
"../renderer/loader/web_data_consumer_handle_impl_unittest.cc",
"../renderer/loader/web_url_loader_impl_unittest.cc",
"../renderer/manifest/manifest_parser_unittest.cc",
- "../renderer/media/audio_message_filter_unittest.cc",
"../renderer/media/audio_output_ipc_factory_unittest.cc",
"../renderer/media/audio_renderer_mixer_manager_unittest.cc",
"../renderer/media/audio_renderer_sink_cache_unittest.cc",
@@ -1608,14 +1639,68 @@ test("content_unittests") {
"../renderer/media/mojo_audio_output_ipc_unittest.cc",
"../renderer/media/render_media_log_unittest.cc",
"../renderer/media/renderer_webaudiodevice_impl_unittest.cc",
+ "../renderer/media/stream/media_stream_audio_processor_unittest.cc",
+ "../renderer/media/stream/media_stream_audio_unittest.cc",
+ "../renderer/media/stream/media_stream_constraints_util_audio_unittest.cc",
+ "../renderer/media/stream/media_stream_constraints_util_sets_unittest.cc",
+ "../renderer/media/stream/media_stream_constraints_util_unittest.cc",
+ "../renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc",
+ "../renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc",
+ "../renderer/media/stream/media_stream_device_observer_unittest.cc",
+ "../renderer/media/stream/media_stream_video_capturer_source_unittest.cc",
+ "../renderer/media/stream/media_stream_video_renderer_sink_unittest.cc",
+ "../renderer/media/stream/media_stream_video_source_unittest.cc",
+ "../renderer/media/stream/media_stream_video_track_unittest.cc",
+ "../renderer/media/stream/mock_constraint_factory.cc",
+ "../renderer/media/stream/mock_constraint_factory.h",
+ "../renderer/media/stream/mock_media_stream_registry.cc",
+ "../renderer/media/stream/mock_media_stream_registry.h",
+ "../renderer/media/stream/mock_media_stream_video_sink.cc",
+ "../renderer/media/stream/mock_media_stream_video_sink.h",
+ "../renderer/media/stream/mock_media_stream_video_source.cc",
+ "../renderer/media/stream/mock_media_stream_video_source.h",
+ "../renderer/media/stream/processed_local_audio_source_unittest.cc",
+ "../renderer/media/stream/user_media_client_impl_unittest.cc",
+ "../renderer/media/stream/video_track_adapter_unittest.cc",
+ "../renderer/media/stream/webmediaplayer_ms_unittest.cc",
"../renderer/media/video_capture_impl_manager_unittest.cc",
"../renderer/media/video_capture_impl_unittest.cc",
+ "../renderer/media/webrtc/media_stream_remote_video_source_unittest.cc",
+ "../renderer/media/webrtc/media_stream_track_metrics_unittest.cc",
+ "../renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc",
+ "../renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc",
+ "../renderer/media/webrtc/peer_connection_tracker_unittest.cc",
+ "../renderer/media/webrtc/rtc_data_channel_handler_unittest.cc",
+ "../renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc",
+ "../renderer/media/webrtc/rtc_rtp_receiver_unittest.cc",
+ "../renderer/media/webrtc/rtc_rtp_sender_unittest.cc",
+ "../renderer/media/webrtc/rtc_stats_unittest.cc",
+ "../renderer/media/webrtc/rtc_video_decoder_unittest.cc",
+ "../renderer/media/webrtc/rtc_video_encoder_unittest.cc",
+ "../renderer/media/webrtc/stun_field_trial_unittest.cc",
+ "../renderer/media/webrtc/two_keys_adapter_map_unittest.cc",
+ "../renderer/media/webrtc/webrtc_audio_renderer_unittest.cc",
+ "../renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc",
+ "../renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc",
+ "../renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc",
+ "../renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc",
+ "../renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc",
+ "../renderer/media/webrtc/webrtc_uma_histograms_unittest.cc",
+ "../renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc",
+ "../renderer/media/webrtc_local_audio_source_provider_unittest.cc",
+ "../renderer/media_capture_from_element/canvas_capture_handler_unittest.cc",
+ "../renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc",
+ "../renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc",
+ "../renderer/media_recorder/audio_track_recorder_unittest.cc",
+ "../renderer/media_recorder/media_recorder_handler_unittest.cc",
+ "../renderer/media_recorder/video_track_recorder_unittest.cc",
"../renderer/notifications/notification_data_conversions_unittest.cc",
+ "../renderer/p2p/filtering_network_manager_unittest.cc",
+ "../renderer/p2p/ipc_network_manager_unittest.cc",
"../renderer/peripheral_content_heuristic_unittest.cc",
"../renderer/render_thread_impl_unittest.cc",
"../renderer/render_widget_unittest.cc",
"../renderer/service_worker/service_worker_context_client_unittest.cc",
- "../renderer/service_worker/service_worker_dispatcher_unittest.cc",
"../renderer/service_worker/service_worker_provider_context_unittest.cc",
"../renderer/service_worker/service_worker_subresource_loader_unittest.cc",
"../renderer/service_worker/service_worker_timeout_timer_unittest.cc",
@@ -1664,13 +1749,13 @@ test("content_unittests") {
"//base/third_party/dynamic_annotations",
"//cc",
"//cc:test_support",
- "//cc/ipc",
"//components/cbor",
"//components/network_session_configurator/browser",
"//components/network_session_configurator/common",
"//components/offline_pages/buildflags",
"//components/payments/mojom",
"//components/rappor:test_support",
+ "//components/services/leveldb:lib",
"//components/services/leveldb/public/cpp",
"//components/ukm:test_support",
"//components/viz/client",
@@ -1707,6 +1792,7 @@ test("content_unittests") {
"//gpu/ipc/host",
"//gpu/ipc/service",
"//ipc:test_support",
+ "//jingle:jingle_glue",
"//media:test_support",
"//media/blink",
"//media/capture",
@@ -1720,10 +1806,13 @@ test("content_unittests") {
"//ppapi/buildflags",
"//ppapi/c",
"//printing",
+ "//services/audio/public/cpp:test_support",
+ "//services/audio/public/mojom",
"//services/catalog:lib",
"//services/device/public/cpp/generic_sensor",
"//services/device/public/cpp/test:test_support",
"//services/device/public/mojom",
+ "//services/device/public/mojom",
"//services/file:lib",
"//services/file/public/mojom",
"//services/metrics/public/cpp:ukm_builders",
@@ -1734,6 +1823,7 @@ test("content_unittests") {
"//services/network/public/mojom",
"//services/proxy_resolver/:lib",
"//services/service_manager/public/cpp:service_test_support",
+ "//services/service_manager/public/cpp/test:test_support",
"//services/video_capture/public/mojom",
"//skia",
"//sql",
@@ -1746,8 +1836,24 @@ test("content_unittests") {
"//third_party/blink/public:blink",
"//third_party/icu",
"//third_party/leveldatabase",
+ "//third_party/libyuv",
"//third_party/metrics_proto",
+ "//third_party/opus",
"//third_party/re2",
+ "//third_party/webrtc/api:libjingle_peerconnection_api",
+ "//third_party/webrtc/api:rtc_stats_api",
+ "//third_party/webrtc/api/video:video_frame",
+ "//third_party/webrtc/api/video:video_frame_i420",
+ "//third_party/webrtc/api/video_codecs:video_codecs_api",
+ "//third_party/webrtc/media:rtc_media",
+ "//third_party/webrtc/modules/desktop_capture:primitives",
+ "//third_party/webrtc/modules/video_capture",
+ "//third_party/webrtc/modules/video_coding:video_codec_interface",
+ "//third_party/webrtc/pc:libjingle_peerconnection",
+ "//third_party/webrtc/rtc_base:rtc_base",
+ "//third_party/webrtc/stats:rtc_stats_test_utils",
+ "//third_party/webrtc_overrides",
+ "//third_party/webrtc_overrides:init_webrtc",
"//third_party/widevine/cdm:headers",
"//ui/accessibility",
"//ui/base:test_support",
@@ -1765,6 +1871,7 @@ test("content_unittests") {
"//ui/gl",
"//ui/gl:test_support",
"//ui/latency:test_support",
+ "//ui/shell_dialogs:shell_dialogs",
]
data_deps = [
@@ -1782,8 +1889,6 @@ test("content_unittests") {
}
if (enable_plugins) {
- # Put WebRTC-related plugins sources in the "enable_webrtc &&
- # enable_plugins" section below.
sources += [
"../browser/plugin_service_impl_unittest.cc",
"../browser/renderer_host/pepper/browser_ppapi_host_test.cc",
@@ -1792,6 +1897,8 @@ test("content_unittests") {
"../browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc",
"../browser/renderer_host/pepper/pepper_printing_host_unittest.cc",
"../browser/renderer_host/pepper/quota_reservation_unittest.cc",
+ "../renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc",
+ "../renderer/media/pepper/video_track_to_pepper_adapter_unittest.cc",
"../renderer/pepper/event_conversion_unittest.cc",
"../renderer/pepper/host_var_tracker_unittest.cc",
"../renderer/pepper/mock_resource.h",
@@ -1813,121 +1920,22 @@ test("content_unittests") {
]
}
- if (enable_webrtc) {
- # Put WebRTC-related plugins sources in the "enable_webrtc &&
- # enable_plugins" section below.
- sources += [
- "../browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc",
- "../browser/renderer_host/p2p/socket_host_tcp_unittest.cc",
- "../browser/renderer_host/p2p/socket_host_test_utils.cc",
- "../browser/renderer_host/p2p/socket_host_test_utils.h",
- "../browser/renderer_host/p2p/socket_host_udp_unittest.cc",
- "../browser/webrtc/webrtc_internals_message_handler_unittest.cc",
- "../browser/webrtc/webrtc_internals_unittest.cc",
- "../renderer/media/stream/media_stream_audio_processor_unittest.cc",
- "../renderer/media/stream/media_stream_audio_unittest.cc",
- "../renderer/media/stream/media_stream_constraints_util_audio_unittest.cc",
- "../renderer/media/stream/media_stream_constraints_util_sets_unittest.cc",
- "../renderer/media/stream/media_stream_constraints_util_unittest.cc",
- "../renderer/media/stream/media_stream_constraints_util_video_content_unittest.cc",
- "../renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc",
- "../renderer/media/stream/media_stream_device_observer_unittest.cc",
- "../renderer/media/stream/media_stream_video_capturer_source_unittest.cc",
- "../renderer/media/stream/media_stream_video_renderer_sink_unittest.cc",
- "../renderer/media/stream/media_stream_video_source_unittest.cc",
- "../renderer/media/stream/media_stream_video_track_unittest.cc",
- "../renderer/media/stream/mock_constraint_factory.cc",
- "../renderer/media/stream/mock_constraint_factory.h",
- "../renderer/media/stream/mock_media_stream_registry.cc",
- "../renderer/media/stream/mock_media_stream_registry.h",
- "../renderer/media/stream/mock_media_stream_video_sink.cc",
- "../renderer/media/stream/mock_media_stream_video_sink.h",
- "../renderer/media/stream/mock_media_stream_video_source.cc",
- "../renderer/media/stream/mock_media_stream_video_source.h",
- "../renderer/media/stream/processed_local_audio_source_unittest.cc",
- "../renderer/media/stream/user_media_client_impl_unittest.cc",
- "../renderer/media/stream/video_track_adapter_unittest.cc",
- "../renderer/media/stream/webmediaplayer_ms_unittest.cc",
- "../renderer/media/webrtc/media_stream_remote_video_source_unittest.cc",
- "../renderer/media/webrtc/media_stream_track_metrics_unittest.cc",
- "../renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc",
- "../renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc",
- "../renderer/media/webrtc/peer_connection_tracker_unittest.cc",
- "../renderer/media/webrtc/rtc_data_channel_handler_unittest.cc",
- "../renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc",
- "../renderer/media/webrtc/rtc_rtp_parameters_unittest.cc",
- "../renderer/media/webrtc/rtc_rtp_receiver_unittest.cc",
- "../renderer/media/webrtc/rtc_rtp_sender_unittest.cc",
- "../renderer/media/webrtc/rtc_stats_unittest.cc",
- "../renderer/media/webrtc/rtc_video_decoder_unittest.cc",
- "../renderer/media/webrtc/rtc_video_encoder_unittest.cc",
- "../renderer/media/webrtc/stun_field_trial_unittest.cc",
- "../renderer/media/webrtc/two_keys_adapter_map_unittest.cc",
- "../renderer/media/webrtc/webrtc_audio_renderer_unittest.cc",
- "../renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc",
- "../renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc",
- "../renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc",
- "../renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc",
- "../renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc",
- "../renderer/media/webrtc/webrtc_uma_histograms_unittest.cc",
- "../renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc",
- "../renderer/media/webrtc_local_audio_source_provider_unittest.cc",
- "../renderer/media_capture_from_element/canvas_capture_handler_unittest.cc",
- "../renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc",
- "../renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc",
+ if (is_chromecast) {
+ sources -= [
"../renderer/media_recorder/audio_track_recorder_unittest.cc",
"../renderer/media_recorder/media_recorder_handler_unittest.cc",
"../renderer/media_recorder/video_track_recorder_unittest.cc",
- "../renderer/p2p/filtering_network_manager_unittest.cc",
- "../renderer/p2p/ipc_network_manager_unittest.cc",
- ]
- deps += [
- "//services/device/public/mojom",
- "//third_party/libyuv",
- "//third_party/opus",
- "//third_party/webrtc/api:libjingle_peerconnection_api",
- "//third_party/webrtc/api:rtc_stats_api",
- "//third_party/webrtc/api:video_frame_api",
- "//third_party/webrtc/api:video_frame_api_i420",
- "//third_party/webrtc/api/video_codecs:video_codecs_api",
- "//third_party/webrtc/media:rtc_media",
- "//third_party/webrtc/modules/desktop_capture:primitives",
- "//third_party/webrtc/modules/video_capture",
- "//third_party/webrtc/modules/video_coding:video_codec_interface",
- "//third_party/webrtc/pc:libjingle_peerconnection",
- "//third_party/webrtc/rtc_base:rtc_base",
- "//third_party/webrtc/stats:rtc_stats_test_utils",
- "//third_party/webrtc_overrides",
- "//third_party/webrtc_overrides:init_webrtc",
- "//ui/shell_dialogs:shell_dialogs",
- ]
-
- if (is_linux || is_mac || is_win) {
- sources +=
- [ "../browser/media/capture/desktop_capture_device_unittest.cc" ]
- deps += [ "//third_party/webrtc/modules/desktop_capture" ]
- }
-
- if (is_chromecast) {
- sources -= [
- "../renderer/media_recorder/audio_track_recorder_unittest.cc",
- "../renderer/media_recorder/media_recorder_handler_unittest.cc",
- "../renderer/media_recorder/video_track_recorder_unittest.cc",
- ]
- }
- }
-
- if (enable_webrtc && enable_plugins) {
- sources += [
- "../renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc",
- "../renderer/media/pepper/video_track_to_pepper_adapter_unittest.cc",
]
}
# Screen capture unit tests.
if (is_linux || is_mac || is_win) {
- deps += [ "//third_party/libyuv" ]
+ deps += [
+ "//third_party/libyuv",
+ "//third_party/webrtc/modules/desktop_capture",
+ ]
sources += [
+ "../browser/media/capture/desktop_capture_device_unittest.cc",
"../browser/media/capture/frame_sink_video_capture_device_unittest.cc",
]
if (use_aura) {
@@ -1970,7 +1978,6 @@ test("content_unittests") {
"../browser/android/java/java_type_unittest.cc",
"../browser/android/overscroll_controller_android_unittest.cc",
"../browser/android/scoped_surface_request_manager_unittest.cc",
- "../browser/android/string_message_codec_unittest.cc",
"../browser/android/url_request_content_job_unittest.cc",
"../browser/media/capture/screen_capture_device_android_unittest.cc",
"../renderer/java/gin_java_bridge_value_converter_unittest.cc",
@@ -2047,7 +2054,6 @@ test("content_unittests") {
"../browser/compositor/gpu_vsync_begin_frame_source_unittest.cc",
"../browser/compositor/reflector_impl_unittest.cc",
"../browser/compositor/software_browser_compositor_output_surface_unittest.cc",
- "../browser/renderer_host/compositor_resize_lock_unittest.cc",
]
}
@@ -2091,13 +2097,11 @@ test("content_perftests") {
}
sources = [
- "../browser/renderer_host/input/legacy_input_router_impl_perftest.cc",
"../test/run_all_perftests.cc",
]
deps = [
"//base/test:test_support",
"//cc",
- "//cc/ipc",
"//content/browser:for_content_tests",
"//content/public/browser",
"//content/public/common",
diff --git a/chromium/content/utility/BUILD.gn b/chromium/content/utility/BUILD.gn
index 1385f37f994..610106e74b7 100644
--- a/chromium/content/utility/BUILD.gn
+++ b/chromium/content/utility/BUILD.gn
@@ -37,10 +37,11 @@ jumbo_source_set("utility") {
"//content/public/child:child_sources",
"//content/public/common:common_sources",
"//media:media_buildflags",
- "//mojo/common",
"//mojo/public/cpp/bindings",
"//net:net_with_v8",
"//sandbox",
+ "//services/audio:lib",
+ "//services/audio/public/mojom:constants",
"//services/data_decoder:lib",
"//services/data_decoder/public/cpp",
"//services/network:network_service",
diff --git a/chromium/content/utility/DEPS b/chromium/content/utility/DEPS
index a77eeb601b3..51f92f362e2 100644
--- a/chromium/content/utility/DEPS
+++ b/chromium/content/utility/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+content/child",
"+content/public/utility",
+ "+services/audio",
"+services/data_decoder",
"+services/network",
"+services/service_manager",
diff --git a/chromium/content/utility/utility_service_factory.cc b/chromium/content/utility/utility_service_factory.cc
index 290428ee04e..b7fd74830e8 100644
--- a/chromium/content/utility/utility_service_factory.cc
+++ b/chromium/content/utility/utility_service_factory.cc
@@ -19,6 +19,8 @@
#include "content/public/utility/utility_thread.h"
#include "content/utility/utility_thread_impl.h"
#include "media/media_buildflags.h"
+#include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/service_factory.h"
#include "services/data_decoder/data_decoder_service.h"
#include "services/data_decoder/public/mojom/constants.mojom.h"
#include "services/network/network_service.h"
@@ -129,6 +131,10 @@ void UtilityServiceFactory::RegisterServices(ServiceMap* services) {
services->insert(
std::make_pair(video_capture::mojom::kServiceName, video_capture_info));
+ service_manager::EmbeddedServiceInfo audio_info;
+ audio_info.factory = base::BindRepeating(&audio::CreateStandaloneService);
+ services->insert(std::make_pair(audio::mojom::kServiceName, audio_info));
+
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
service_manager::EmbeddedServiceInfo info;
info.factory = base::Bind(&CreateCdmService);
diff --git a/chromium/content/zygote/OWNERS b/chromium/content/zygote/OWNERS
index d38314f3fdd..c8300293c2c 100644
--- a/chromium/content/zygote/OWNERS
+++ b/chromium/content/zygote/OWNERS
@@ -1,7 +1 @@
-jln@chromium.org
-palmer@chromium.org
-rsesek@chromium.org
-tsepez@chromium.org
-
-# TEAM: security-dev@chromium.org
-# COMPONENT: Internals>Sandbox
+file://services/service_manager/zygote/OWNERS \ No newline at end of file
diff --git a/chromium/content/zygote/zygote_browsertest.cc b/chromium/content/zygote/zygote_browsertest.cc
index 5376445fba5..48ffdd2f084 100644
--- a/chromium/content/zygote/zygote_browsertest.cc
+++ b/chromium/content/zygote/zygote_browsertest.cc
@@ -12,6 +12,8 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
+#include "services/service_manager/embedder/switches.h"
+#include "services/service_manager/sandbox/switches.h"
namespace content {
@@ -49,7 +51,7 @@ class LinuxZygoteDisabledBrowserTest : public ContentBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kNoZygote);
- command_line->AppendSwitch(switches::kNoSandbox);
+ command_line->AppendSwitch(service_manager::switches::kNoSandbox);
}
private:
diff --git a/chromium/content/zygote/zygote_linux.cc b/chromium/content/zygote/zygote_linux.cc
deleted file mode 100644
index 0f6710226f7..00000000000
--- a/chromium/content/zygote/zygote_linux.cc
+++ /dev/null
@@ -1,668 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/zygote/zygote_linux.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/linux_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/pickle.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/global_descriptors.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/process/process.h"
-#include "base/process/process_handle.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/common/zygote_commands_linux.h"
-#include "content/public/common/content_descriptors.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/mojo_channel_switches.h"
-#include "content/public/common/result_codes.h"
-#include "content/public/common/send_zygote_child_ping_linux.h"
-#include "content/public/common/zygote_fork_delegate_linux.h"
-#include "ipc/ipc_channel.h"
-#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "services/service_manager/embedder/set_process_title.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/sandbox.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-// See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
-
-namespace content {
-
-namespace {
-
-// NOP function. See below where this handler is installed.
-void SIGCHLDHandler(int signal) {
-}
-
-int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
- for (size_t index = 0; index < fd_mapping.size(); ++index) {
- if (fd_mapping[index].key == key)
- return fd_mapping[index].fd;
- }
- return -1;
-}
-
-void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) {
- int raw_pipe[2];
- PCHECK(0 == pipe(raw_pipe));
- read_pipe->reset(raw_pipe[0]);
- write_pipe->reset(raw_pipe[1]);
-}
-
-void KillAndReap(pid_t pid, ZygoteForkDelegate* helper) {
- if (helper) {
- // Helper children may be forked in another PID namespace, so |pid| might
- // be meaningless to us; or we just might not be able to directly send it
- // signals. So we can't kill it.
- // Additionally, we're not its parent, so we can't reap it anyway.
- // TODO(mdempsky): Extend the ZygoteForkDelegate API to handle this.
- LOG(WARNING) << "Unable to kill or reap helper children";
- return;
- }
-
- // Kill the child process in case it's not already dead, so we can safely
- // perform a blocking wait.
- PCHECK(0 == kill(pid, SIGKILL));
- PCHECK(pid == HANDLE_EINTR(waitpid(pid, nullptr, 0)));
-}
-
-} // namespace
-
-Zygote::Zygote(int sandbox_flags,
- std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers,
- const base::GlobalDescriptors::Descriptor& ipc_backchannel)
- : sandbox_flags_(sandbox_flags),
- helpers_(std::move(helpers)),
- initial_uma_index_(0),
- to_reap_(),
- ipc_backchannel_(ipc_backchannel) {}
-
-Zygote::~Zygote() {}
-
-bool Zygote::ProcessRequests() {
- // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
- // browser on it.
- // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
- // See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
-
- // We need to accept SIGCHLD, even though our handler is a no-op because
- // otherwise we cannot wait on children. (According to POSIX 2001.)
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = &SIGCHLDHandler;
- PCHECK(sigaction(SIGCHLD, &action, nullptr) == 0);
-
- // Block SIGCHLD until a child might be ready to reap.
- sigset_t sigset;
- sigset_t orig_sigmask;
- PCHECK(sigemptyset(&sigset) == 0);
- PCHECK(sigaddset(&sigset, SIGCHLD) == 0);
- PCHECK(sigprocmask(SIG_BLOCK, &sigset, &orig_sigmask) == 0);
-
- if (UsingSUIDSandbox() || UsingNSSandbox()) {
- // Let the ZygoteHost know we are ready to go.
- // The receiving code is in
- // content/browser/zygote_host/zygote_host_impl_linux.cc.
- bool r = base::UnixDomainSocket::SendMsg(kZygoteSocketPairFd,
- kZygoteHelloMessage,
- sizeof(kZygoteHelloMessage),
- std::vector<int>());
-#if defined(OS_CHROMEOS)
- LOG_IF(WARNING, !r) << "Sending zygote magic failed";
- // Exit normally on chromeos because session manager may send SIGTERM
- // right after the process starts and it may fail to send zygote magic
- // number to browser process.
- if (!r)
- _exit(RESULT_CODE_NORMAL_EXIT);
-#else
- CHECK(r) << "Sending zygote magic failed";
-#endif
- }
-
- sigset_t ppoll_sigmask = orig_sigmask;
- PCHECK(sigdelset(&ppoll_sigmask, SIGCHLD) == 0);
- struct pollfd pfd;
- pfd.fd = kZygoteSocketPairFd;
- pfd.events = POLLIN;
-
- struct timespec timeout;
- timeout.tv_sec = 2;
- timeout.tv_nsec = 0;
-
- for (;;) {
- struct timespec* timeout_ptr = nullptr;
- if (!to_reap_.empty())
- timeout_ptr = &timeout;
- int rc = ppoll(&pfd, 1, timeout_ptr, &ppoll_sigmask);
- PCHECK(rc >= 0 || errno == EINTR);
- ReapChildren();
-
- if (pfd.revents & POLLIN) {
- // This function call can return multiple times, once per fork().
- if (HandleRequestFromBrowser(kZygoteSocketPairFd)) {
- PCHECK(sigprocmask(SIG_SETMASK, &orig_sigmask, nullptr) == 0);
- return true;
- }
- }
- }
- // The loop should not be exited unless a request was successfully processed.
- NOTREACHED();
- return false;
-}
-
-bool Zygote::ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child) {
- pid_t pid = child->internal_pid;
- pid_t r = HANDLE_EINTR(waitpid(pid, nullptr, WNOHANG));
- if (r > 0) {
- if (r != pid) {
- DLOG(ERROR) << "While waiting for " << pid << " to terminate, "
- "waitpid returned "
- << r;
- }
- return r == pid;
- }
- if ((now - child->time_of_reap_request).InSeconds() < 2) {
- return false;
- }
- // If the process has been requested reaped >= 2 seconds ago, kill it.
- if (!child->sent_sigkill) {
- if (kill(pid, SIGKILL) != 0)
- DPLOG(ERROR) << "Sending SIGKILL to process " << pid << " failed";
-
- child->sent_sigkill = true;
- }
- return false;
-}
-
-void Zygote::ReapChildren() {
- base::TimeTicks now = base::TimeTicks::Now();
- std::vector<ZygoteProcessInfo>::iterator it = to_reap_.begin();
- while (it != to_reap_.end()) {
- if (ReapChild(now, &(*it))) {
- it = to_reap_.erase(it);
- } else {
- it++;
- }
- }
-}
-
-bool Zygote::GetProcessInfo(base::ProcessHandle pid,
- ZygoteProcessInfo* process_info) {
- DCHECK(process_info);
- const ZygoteProcessMap::const_iterator it = process_info_map_.find(pid);
- if (it == process_info_map_.end()) {
- return false;
- }
- *process_info = it->second;
- return true;
-}
-
-bool Zygote::UsingSUIDSandbox() const {
- return sandbox_flags_ & service_manager::SandboxLinux::kSUID;
-}
-
-bool Zygote::UsingNSSandbox() const {
- return sandbox_flags_ & service_manager::SandboxLinux::kUserNS;
-}
-
-bool Zygote::HandleRequestFromBrowser(int fd) {
- std::vector<base::ScopedFD> fds;
- char buf[kZygoteMaxMessageLength];
- const ssize_t len = base::UnixDomainSocket::RecvMsg(
- fd, buf, sizeof(buf), &fds);
-
- if (len == 0 || (len == -1 && errno == ECONNRESET)) {
- // EOF from the browser. We should die.
- // TODO(eugenis): call __sanititizer_cov_dump() here to obtain code
- // coverage for the Zygote. Currently it's not possible because of
- // confusion over who is responsible for closing the file descriptor.
- _exit(0);
- return false;
- }
-
- if (len == -1) {
- PLOG(ERROR) << "Error reading message from browser";
- return false;
- }
-
- base::Pickle pickle(buf, len);
- base::PickleIterator iter(pickle);
-
- int kind;
- if (iter.ReadInt(&kind)) {
- switch (kind) {
- case kZygoteCommandFork:
- // This function call can return multiple times, once per fork().
- return HandleForkRequest(fd, iter, std::move(fds));
-
- case kZygoteCommandReap:
- if (!fds.empty())
- break;
- HandleReapRequest(fd, iter);
- return false;
- case kZygoteCommandGetTerminationStatus:
- if (!fds.empty())
- break;
- HandleGetTerminationStatus(fd, iter);
- return false;
- case kZygoteCommandGetSandboxStatus:
- HandleGetSandboxStatus(fd, iter);
- return false;
- case kZygoteCommandForkRealPID:
- // This shouldn't happen in practice, but some failure paths in
- // HandleForkRequest (e.g., if ReadArgsAndFork fails during depickling)
- // could leave this command pending on the socket.
- LOG(ERROR) << "Unexpected real PID message from browser";
- NOTREACHED();
- return false;
- default:
- NOTREACHED();
- break;
- }
- }
-
- LOG(WARNING) << "Error parsing message from browser";
- return false;
-}
-
-void Zygote::HandleReapRequest(int fd, base::PickleIterator iter) {
- base::ProcessId child;
-
- if (!iter.ReadInt(&child)) {
- LOG(WARNING) << "Error parsing reap request from browser";
- return;
- }
-
- ZygoteProcessInfo child_info;
- if (!GetProcessInfo(child, &child_info)) {
- LOG(ERROR) << "Child not found!";
- NOTREACHED();
- return;
- }
- child_info.time_of_reap_request = base::TimeTicks::Now();
-
- if (!child_info.started_from_helper) {
- to_reap_.push_back(child_info);
- } else {
- // For processes from the helper, send a GetTerminationStatus request
- // with known_dead set to true.
- // This is not perfect, as the process may be killed instantly, but is
- // better than ignoring the request.
- base::TerminationStatus status;
- int exit_code;
- bool got_termination_status =
- GetTerminationStatus(child, true /* known_dead */, &status, &exit_code);
- DCHECK(got_termination_status);
- }
- process_info_map_.erase(child);
-}
-
-bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid,
- bool known_dead,
- base::TerminationStatus* status,
- int* exit_code) {
-
- ZygoteProcessInfo child_info;
- if (!GetProcessInfo(real_pid, &child_info)) {
- LOG(ERROR) << "Zygote::GetTerminationStatus for unknown PID "
- << real_pid;
- NOTREACHED();
- return false;
- }
- // We know about |real_pid|.
- const base::ProcessHandle child = child_info.internal_pid;
- if (child_info.started_from_helper) {
- if (!child_info.started_from_helper->GetTerminationStatus(
- child, known_dead, status, exit_code)) {
- return false;
- }
- } else {
- // Handle the request directly.
- if (known_dead) {
- *status = base::GetKnownDeadTerminationStatus(child, exit_code);
- } else {
- // We don't know if the process is dying, so get its status but don't
- // wait.
- *status = base::GetTerminationStatus(child, exit_code);
- }
- }
- // Successfully got a status for |real_pid|.
- if (*status != base::TERMINATION_STATUS_STILL_RUNNING) {
- // Time to forget about this process.
- process_info_map_.erase(real_pid);
- }
-
- if (WIFEXITED(*exit_code)) {
- const int exit_status = WEXITSTATUS(*exit_code);
- if (exit_status == sandbox::NamespaceSandbox::SignalExitCode(SIGINT) ||
- exit_status == sandbox::NamespaceSandbox::SignalExitCode(SIGTERM)) {
- *status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED;
- }
- }
-
- return true;
-}
-
-void Zygote::HandleGetTerminationStatus(int fd, base::PickleIterator iter) {
- bool known_dead;
- base::ProcessHandle child_requested;
-
- if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) {
- LOG(WARNING) << "Error parsing GetTerminationStatus request "
- << "from browser";
- return;
- }
-
- base::TerminationStatus status;
- int exit_code;
-
- bool got_termination_status =
- GetTerminationStatus(child_requested, known_dead, &status, &exit_code);
- if (!got_termination_status) {
- // Assume that if we can't find the child in the sandbox, then
- // it terminated normally.
- NOTREACHED();
- status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
- exit_code = RESULT_CODE_NORMAL_EXIT;
- }
-
- base::Pickle write_pickle;
- write_pickle.WriteInt(static_cast<int>(status));
- write_pickle.WriteInt(exit_code);
- ssize_t written =
- HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
- if (written != static_cast<ssize_t>(write_pickle.size()))
- PLOG(ERROR) << "write";
-}
-
-int Zygote::ForkWithRealPid(const std::string& process_type,
- const base::GlobalDescriptors::Mapping& fd_mapping,
- const std::string& channel_id,
- base::ScopedFD pid_oracle,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value) {
- ZygoteForkDelegate* helper = nullptr;
- for (auto i = helpers_.begin(); i != helpers_.end(); ++i) {
- if ((*i)->CanHelp(process_type, uma_name, uma_sample, uma_boundary_value)) {
- helper = i->get();
- break;
- }
- }
-
- base::ScopedFD read_pipe, write_pipe;
- base::ProcessId pid = 0;
- if (helper) {
- int mojo_channel_fd = LookUpFd(fd_mapping, kMojoIPCChannel);
- if (mojo_channel_fd < 0) {
- DLOG(ERROR) << "Failed to find kMojoIPCChannel in FD mapping";
- return -1;
- }
- std::vector<int> fds;
- fds.push_back(mojo_channel_fd); // kBrowserFDIndex
- fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex
- pid = helper->Fork(process_type, fds, channel_id);
-
- // Helpers should never return in the child process.
- CHECK_NE(pid, 0);
- } else {
- CreatePipe(&read_pipe, &write_pipe);
- if (sandbox_flags_ & service_manager::SandboxLinux::kPIDNS &&
- sandbox_flags_ & service_manager::SandboxLinux::kUserNS) {
- pid = sandbox::NamespaceSandbox::ForkInNewPidNamespace(
- /*drop_capabilities_in_child=*/true);
- } else {
- pid = sandbox::Credentials::ForkAndDropCapabilitiesInChild();
- }
- }
-
- if (pid == 0) {
- // If the process is the init process inside a PID namespace, it must have
- // explicit signal handlers.
- if (getpid() == 1) {
- static const int kTerminationSignals[] = {
- SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, SIGUSR1, SIGUSR2};
- for (const int sig : kTerminationSignals) {
- sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
- sig, sandbox::NamespaceSandbox::SignalExitCode(sig));
- }
- }
-
- // In the child process.
- write_pipe.reset();
-
- // Ping the PID oracle socket so the browser can find our PID.
- CHECK(SendZygoteChildPing(pid_oracle.get()));
-
- // Now read back our real PID from the zygote.
- base::ProcessId real_pid;
- if (!base::ReadFromFD(read_pipe.get(),
- reinterpret_cast<char*>(&real_pid),
- sizeof(real_pid))) {
- LOG(FATAL) << "Failed to synchronise with parent zygote process";
- }
- if (real_pid <= 0) {
- LOG(FATAL) << "Invalid pid from parent zygote";
- }
- // Sandboxed processes need to send the global, non-namespaced PID when
- // setting up an IPC channel to their parent.
- IPC::Channel::SetGlobalPid(real_pid);
- // Force the real PID so chrome event data have a PID that corresponds
- // to system trace event data.
- base::trace_event::TraceLog::GetInstance()->SetProcessID(
- static_cast<int>(real_pid));
- base::InitUniqueIdForProcessInPidNamespace(real_pid);
- return 0;
- }
-
- // In the parent process.
- read_pipe.reset();
- pid_oracle.reset();
-
- // Always receive a real PID from the zygote host, though it might
- // be invalid (see below).
- base::ProcessId real_pid;
- {
- std::vector<base::ScopedFD> recv_fds;
- char buf[kZygoteMaxMessageLength];
- const ssize_t len = base::UnixDomainSocket::RecvMsg(
- kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds);
- CHECK_GT(len, 0);
- CHECK(recv_fds.empty());
-
- base::Pickle pickle(buf, len);
- base::PickleIterator iter(pickle);
-
- int kind;
- CHECK(iter.ReadInt(&kind));
- CHECK(kind == kZygoteCommandForkRealPID);
- CHECK(iter.ReadInt(&real_pid));
- }
-
- // Fork failed.
- if (pid < 0) {
- return -1;
- }
-
- // If we successfully forked a child, but it crashed without sending
- // a message to the browser, the browser won't have found its PID.
- if (real_pid < 0) {
- KillAndReap(pid, helper);
- return -1;
- }
-
- // If we're not using a helper, send the PID back to the child process.
- if (!helper) {
- ssize_t written =
- HANDLE_EINTR(write(write_pipe.get(), &real_pid, sizeof(real_pid)));
- if (written != sizeof(real_pid)) {
- KillAndReap(pid, helper);
- return -1;
- }
- }
-
- // Now set-up this process to be tracked by the Zygote.
- if (process_info_map_.find(real_pid) != process_info_map_.end()) {
- LOG(ERROR) << "Already tracking PID " << real_pid;
- NOTREACHED();
- }
- process_info_map_[real_pid].internal_pid = pid;
- process_info_map_[real_pid].started_from_helper = helper;
-
- return real_pid;
-}
-
-base::ProcessId Zygote::ReadArgsAndFork(base::PickleIterator iter,
- std::vector<base::ScopedFD> fds,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value) {
- std::vector<std::string> args;
- int argc = 0;
- int numfds = 0;
- base::GlobalDescriptors::Mapping mapping;
- std::string process_type;
- std::string channel_id;
- const std::string channel_id_prefix = std::string("--") +
- switches::kServiceRequestChannelToken +
- std::string("=");
-
- if (!iter.ReadString(&process_type))
- return -1;
- if (!iter.ReadInt(&argc))
- return -1;
-
- for (int i = 0; i < argc; ++i) {
- std::string arg;
- if (!iter.ReadString(&arg))
- return -1;
- args.push_back(arg);
- if (arg.compare(0, channel_id_prefix.length(), channel_id_prefix) == 0)
- channel_id = arg.substr(channel_id_prefix.length());
- }
-
- if (process_type == switches::kRendererProcess) {
- // timezone_id is obtained from ICU in zygote host so that it can't be
- // invalid. For an unknown reason, if an invalid ID is passed down here,
- // the worst result would be that timezone would be set to Etc/Unknown.
- base::string16 timezone_id;
- if (!iter.ReadString16(&timezone_id))
- return -1;
- icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(
- icu::UnicodeString(FALSE, timezone_id.data(), timezone_id.length())));
- }
-
- if (!iter.ReadInt(&numfds))
- return -1;
- if (numfds != static_cast<int>(fds.size()))
- return -1;
-
- // First FD is the PID oracle socket.
- if (fds.size() < 1)
- return -1;
- base::ScopedFD pid_oracle(std::move(fds[0]));
-
- // Remaining FDs are for the global descriptor mapping.
- for (int i = 1; i < numfds; ++i) {
- base::GlobalDescriptors::Key key;
- if (!iter.ReadUInt32(&key))
- return -1;
- mapping.push_back(base::GlobalDescriptors::Descriptor(key, fds[i].get()));
- }
-
- mapping.push_back(ipc_backchannel_);
-
- // Returns twice, once per process.
- base::ProcessId child_pid =
- ForkWithRealPid(process_type, mapping, channel_id, std::move(pid_oracle),
- uma_name, uma_sample, uma_boundary_value);
- if (!child_pid) {
- // This is the child process.
-
- // Our socket from the browser.
- PCHECK(0 == IGNORE_EINTR(close(kZygoteSocketPairFd)));
-
- // Pass ownership of file descriptors from fds to GlobalDescriptors.
- for (base::ScopedFD& fd : fds)
- ignore_result(fd.release());
- base::GlobalDescriptors::GetInstance()->Reset(mapping);
-
- // Reset the process-wide command line to our new command line.
- base::CommandLine::Reset();
- base::CommandLine::Init(0, nullptr);
- base::CommandLine::ForCurrentProcess()->InitFromArgv(args);
-
- // Update the process title. The argv was already cached by the call to
- // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here
- // (we don't have the original argv at this point).
- service_manager::SetProcessTitleFromCommandLine(nullptr);
- } else if (child_pid < 0) {
- LOG(ERROR) << "Zygote could not fork: process_type " << process_type
- << " numfds " << numfds << " child_pid " << child_pid;
- }
- return child_pid;
-}
-
-bool Zygote::HandleForkRequest(int fd,
- base::PickleIterator iter,
- std::vector<base::ScopedFD> fds) {
- std::string uma_name;
- int uma_sample;
- int uma_boundary_value;
- base::ProcessId child_pid = ReadArgsAndFork(iter, std::move(fds), &uma_name,
- &uma_sample, &uma_boundary_value);
- if (child_pid == 0)
- return true;
- // If there's no UMA report for this particular fork, then check if any
- // helpers have an initial UMA report for us to send instead.
- while (uma_name.empty() && initial_uma_index_ < helpers_.size()) {
- helpers_[initial_uma_index_++]->InitialUMA(
- &uma_name, &uma_sample, &uma_boundary_value);
- }
- // Must always send reply, as ZygoteHost blocks while waiting for it.
- base::Pickle reply_pickle;
- reply_pickle.WriteInt(child_pid);
- reply_pickle.WriteString(uma_name);
- if (!uma_name.empty()) {
- reply_pickle.WriteInt(uma_sample);
- reply_pickle.WriteInt(uma_boundary_value);
- }
- if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) !=
- static_cast<ssize_t> (reply_pickle.size()))
- PLOG(ERROR) << "write";
- return false;
-}
-
-bool Zygote::HandleGetSandboxStatus(int fd, base::PickleIterator iter) {
- if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
- sizeof(sandbox_flags_)) {
- PLOG(ERROR) << "write";
- }
-
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/zygote/zygote_linux.h b/chromium/content/zygote/zygote_linux.h
deleted file mode 100644
index c86fed2a5db..00000000000
--- a/chromium/content/zygote/zygote_linux.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_ZYGOTE_ZYGOTE_LINUX_H_
-#define CONTENT_ZYGOTE_ZYGOTE_LINUX_H_
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/containers/small_map.h"
-#include "base/files/scoped_file.h"
-#include "base/posix/global_descriptors.h"
-#include "base/process/kill.h"
-#include "base/process/process.h"
-#include "base/process/process_handle.h"
-#include "base/time/time.h"
-
-namespace base {
-class PickleIterator;
-}
-
-namespace content {
-
-class ZygoteForkDelegate;
-
-// This is the object which implements the zygote. The ZygoteMain function,
-// which is called from ChromeMain, simply constructs one of these objects and
-// runs it.
-class Zygote {
- public:
- Zygote(int sandbox_flags,
- std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers,
- const base::GlobalDescriptors::Descriptor& ipc_backchannel);
- ~Zygote();
-
- bool ProcessRequests();
-
- private:
- struct ZygoteProcessInfo {
- // Pid from inside the Zygote's PID namespace.
- base::ProcessHandle internal_pid;
- // Keeps track of which fork delegate helper the process was started from.
- ZygoteForkDelegate* started_from_helper;
- // Records when the browser requested the zygote to reap this process.
- base::TimeTicks time_of_reap_request;
- // Notes whether the zygote has sent SIGKILL to this process.
- bool sent_sigkill;
- };
- using ZygoteProcessMap =
- base::small_map<std::map<base::ProcessHandle, ZygoteProcessInfo>>;
-
- // Retrieve a ZygoteProcessInfo from the process_info_map_.
- // Returns true and write to process_info if |pid| can be found, return
- // false otherwise.
- bool GetProcessInfo(base::ProcessHandle pid, ZygoteProcessInfo* process_info);
-
- // Returns true if the SUID sandbox is active.
- bool UsingSUIDSandbox() const;
- // Returns true if the NS sandbox is active.
- bool UsingNSSandbox() const;
-
- // ---------------------------------------------------------------------------
- // Requests from the browser...
-
- // Read and process a request from the browser. Returns true if we are in a
- // new process and thus need to unwind back into ChromeMain.
- bool HandleRequestFromBrowser(int fd);
-
- void HandleReapRequest(int fd, base::PickleIterator iter);
-
- // Get the termination status of |real_pid|. |real_pid| is the PID as it
- // appears outside of the sandbox.
- // Return true if it managed to get the termination status and return the
- // status in |status| and the exit code in |exit_code|.
- bool GetTerminationStatus(base::ProcessHandle real_pid, bool known_dead,
- base::TerminationStatus* status,
- int* exit_code);
-
- void HandleGetTerminationStatus(int fd,
- base::PickleIterator iter);
-
- // This is equivalent to fork(), except that, when using the SUID sandbox, it
- // returns the real PID of the child process as it appears outside the
- // sandbox, rather than returning the PID inside the sandbox. The child's
- // real PID is determined by having it call content::SendZygoteChildPing(int)
- // using the |pid_oracle| descriptor.
- // Finally, when using a ZygoteForkDelegate helper, |uma_name|, |uma_sample|,
- // and |uma_boundary_value| may be set if the helper wants to make a UMA
- // report via UMA_HISTOGRAM_ENUMERATION.
- int ForkWithRealPid(const std::string& process_type,
- const base::GlobalDescriptors::Mapping& fd_mapping,
- const std::string& channel_id,
- base::ScopedFD pid_oracle,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value);
-
- // Unpacks process type and arguments from |iter| and forks a new process.
- // Returns -1 on error, otherwise returns twice, returning 0 to the child
- // process and the child process ID to the parent process, like fork().
- base::ProcessId ReadArgsAndFork(base::PickleIterator iter,
- std::vector<base::ScopedFD> fds,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value);
-
- // Handle a 'fork' request from the browser: this means that the browser
- // wishes to start a new renderer. Returns true if we are in a new process,
- // otherwise writes the child_pid back to the browser via |fd|. Writes a
- // child_pid of -1 on error.
- bool HandleForkRequest(int fd,
- base::PickleIterator iter,
- std::vector<base::ScopedFD> fds);
-
- bool HandleGetSandboxStatus(int fd,
- base::PickleIterator iter);
-
- // Attempt to reap the child process by calling waitpid, and return
- // whether successful. If the process has not terminated within
- // 2 seconds of its reap request, send it SIGKILL.
- bool ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child);
-
- // Attempt to reap all outstanding children in |to_reap_|.
- void ReapChildren();
-
- // The Zygote needs to keep some information about each process. Most
- // notably what the PID of the process is inside the PID namespace of
- // the Zygote and whether or not a process was started by the
- // ZygoteForkDelegate helper.
- ZygoteProcessMap process_info_map_;
-
- const int sandbox_flags_;
- std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers_;
-
- // Count of how many fork delegates for which we've invoked InitialUMA().
- size_t initial_uma_index_;
-
- // The vector contains the child processes that need to be reaped.
- std::vector<ZygoteProcessInfo> to_reap_;
-
- // Sandbox IPC channel for renderers to invoke services from the browser. See
- // https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
- base::GlobalDescriptors::Descriptor ipc_backchannel_;
-};
-
-} // namespace content
-
-#endif // CONTENT_ZYGOTE_ZYGOTE_LINUX_H_
diff --git a/chromium/content/zygote/zygote_main.h b/chromium/content/zygote/zygote_main.h
deleted file mode 100644
index dc0aa17d805..00000000000
--- a/chromium/content/zygote/zygote_main.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2013 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_ZYGOTE_ZYGOTE_MAIN_H_
-#define CONTENT_ZYGOTE_ZYGOTE_MAIN_H_
-
-#include <memory>
-#include <vector>
-
-#include "build/build_config.h"
-
-namespace content {
-
-class ZygoteForkDelegate;
-
-bool ZygoteMain(
- std::vector<std::unique_ptr<ZygoteForkDelegate>> fork_delegates);
-
-} // namespace content
-
-#endif // CONTENT_ZYGOTE_ZYGOTE_MAIN_H_
diff --git a/chromium/content/zygote/zygote_main_linux.cc b/chromium/content/zygote/zygote_main_linux.cc
deleted file mode 100644
index 12447a0daa2..00000000000
--- a/chromium/content/zygote/zygote_main_linux.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/zygote/zygote_main.h"
-
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/memory/protected_memory.h"
-#include "base/memory/protected_memory_cfi.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/rand_util.h"
-#include "base/strings/safe_sprintf.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/sys_info.h"
-#include "build/build_config.h"
-#include "content/common/zygote_commands_linux.h"
-#include "content/public/common/common_sandbox_support_linux.h"
-#include "content/public/common/content_descriptors.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/zygote_fork_delegate_linux.h"
-#include "content/zygote/zygote_linux.h"
-#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/init_process_reaper.h"
-#include "sandbox/linux/services/libc_interceptor.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "sandbox/linux/services/thread_helpers.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
-#include "services/service_manager/sandbox/linux/sandbox_debug_handling_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/sandbox.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-namespace content {
-
-namespace {
-
-void CloseFds(const std::vector<int>& fds) {
- for (const auto& it : fds) {
- PCHECK(0 == IGNORE_EINTR(close(it)));
- }
-}
-
-base::OnceClosure ClosureFromTwoClosures(base::OnceClosure one,
- base::OnceClosure two) {
- return base::BindOnce(
- [](base::OnceClosure one, base::OnceClosure two) {
- if (!one.is_null())
- std::move(one).Run();
- if (!two.is_null())
- std::move(two).Run();
- },
- std::move(one), std::move(two));
-}
-
-} // namespace
-
-// This function triggers the static and lazy construction of objects that need
-// to be created before imposing the sandbox.
-static void ZygotePreSandboxInit() {
- base::RandUint64();
-
- base::SysInfo::AmountOfPhysicalMemory();
- base::SysInfo::NumberOfProcessors();
-
- // ICU DateFormat class (used in base/time_format.cc) needs to get the
- // Olson timezone ID by accessing the zoneinfo files on disk. After
- // TimeZone::createDefault is called once here, the timezone ID is
- // cached and there's no more need to access the file system.
- std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
-}
-
-static bool CreateInitProcessReaper(
- base::OnceClosure post_fork_parent_callback) {
- // The current process becomes init(1), this function returns from a
- // newly created process.
- if (!sandbox::CreateInitProcessReaper(std::move(post_fork_parent_callback))) {
- LOG(ERROR) << "Error creating an init process to reap zombies";
- return false;
- }
- return true;
-}
-
-// Enter the setuid sandbox. This requires the current process to have been
-// created through the setuid sandbox.
-static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
- base::OnceClosure post_fork_parent_callback) {
- DCHECK(setuid_sandbox);
- DCHECK(setuid_sandbox->IsSuidSandboxChild());
-
- // Use the SUID sandbox. This still allows the seccomp sandbox to
- // be enabled by the process later.
-
- if (!setuid_sandbox->IsSuidSandboxUpToDate()) {
- LOG(WARNING) <<
- "You are using a wrong version of the setuid binary!\n"
- "Please read "
- "https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md."
- "\n\n";
- }
-
- if (!setuid_sandbox->ChrootMe())
- return false;
-
- if (setuid_sandbox->IsInNewPIDNamespace()) {
- CHECK_EQ(1, getpid())
- << "The SUID sandbox created a new PID namespace but Zygote "
- "is not the init process. Please, make sure the SUID "
- "binary is up to date.";
- }
-
- if (getpid() == 1) {
- // The setuid sandbox has created a new PID namespace and we need
- // to assume the role of init.
- CHECK(CreateInitProcessReaper(std::move(post_fork_parent_callback)));
- }
-
- CHECK(service_manager::SandboxDebugHandling::SetDumpableStatusAndHandlers());
- return true;
-}
-
-static void DropAllCapabilities(int proc_fd) {
- CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd));
-}
-
-static void EnterNamespaceSandbox(service_manager::SandboxLinux* linux_sandbox,
- base::OnceClosure post_fork_parent_callback) {
- linux_sandbox->EngageNamespaceSandbox(true /* from_zygote */);
- if (getpid() == 1) {
- CHECK(CreateInitProcessReaper(ClosureFromTwoClosures(
- base::BindOnce(DropAllCapabilities, linux_sandbox->proc_fd()),
- std::move(post_fork_parent_callback))));
- }
-}
-
-static void EnterLayerOneSandbox(service_manager::SandboxLinux* linux_sandbox,
- const bool using_layer1_sandbox,
- base::OnceClosure post_fork_parent_callback) {
- DCHECK(linux_sandbox);
-
- ZygotePreSandboxInit();
-
-// Check that the pre-sandbox initialization didn't spawn threads.
-// It's not just our code which may do so - some system-installed libraries
-// are known to be culprits, e.g. lttng.
-#if !defined(THREAD_SANITIZER)
- CHECK(sandbox::ThreadHelpers::IsSingleThreaded());
-#endif
-
- sandbox::SetuidSandboxClient* setuid_sandbox =
- linux_sandbox->setuid_sandbox_client();
- if (setuid_sandbox->IsSuidSandboxChild()) {
- CHECK(
- EnterSuidSandbox(setuid_sandbox, std::move(post_fork_parent_callback)))
- << "Failed to enter setuid sandbox";
- } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) {
- EnterNamespaceSandbox(linux_sandbox, std::move(post_fork_parent_callback));
- } else {
- CHECK(!using_layer1_sandbox);
- }
-}
-
-bool ZygoteMain(
- std::vector<std::unique_ptr<ZygoteForkDelegate>> fork_delegates) {
- sandbox::SetAmZygoteOrRenderer(true, GetSandboxFD());
-
- auto* linux_sandbox = service_manager::SandboxLinux::GetInstance();
-
- // Skip pre-initializing sandbox under --no-sandbox for crbug.com/444900.
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kNoSandbox)) {
- // This will pre-initialize the various sandboxes that need it.
- linux_sandbox->PreinitializeSandbox();
- }
-
- const bool using_setuid_sandbox =
- linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild();
- const bool using_namespace_sandbox =
- sandbox::NamespaceSandbox::InNewUserNamespace();
- const bool using_layer1_sandbox =
- using_setuid_sandbox || using_namespace_sandbox;
-
- if (using_setuid_sandbox) {
- linux_sandbox->setuid_sandbox_client()->CloseDummyFile();
- }
-
- if (using_layer1_sandbox) {
- // Let the ZygoteHost know we're booting up.
- if (!base::UnixDomainSocket::SendMsg(
- kZygoteSocketPairFd, kZygoteBootMessage, sizeof(kZygoteBootMessage),
- std::vector<int>())) {
- // This is not a CHECK failure because the browser process could either
- // crash or quickly exit while the zygote is starting. In either case a
- // zygote crash is not useful. http://crbug.com/692227
- PLOG(ERROR) << "Failed sending zygote boot message";
- _exit(1);
- }
- }
-
- VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size()
- << " fork delegates";
- for (const auto& fork_delegate : fork_delegates) {
- fork_delegate->Init(GetSandboxFD(), using_layer1_sandbox);
- }
-
- // Turn on the first layer of the sandbox if the configuration warrants it.
- EnterLayerOneSandbox(
- linux_sandbox, using_layer1_sandbox,
- base::BindOnce(CloseFds, linux_sandbox->GetFileDescriptorsToClose()));
-
- const int sandbox_flags = linux_sandbox->GetStatus();
- const bool setuid_sandbox_engaged =
- !!(sandbox_flags & service_manager::SandboxLinux::kSUID);
- CHECK_EQ(using_setuid_sandbox, setuid_sandbox_engaged);
-
- const bool namespace_sandbox_engaged =
- !!(sandbox_flags & service_manager::SandboxLinux::kUserNS);
- CHECK_EQ(using_namespace_sandbox, namespace_sandbox_engaged);
-
- Zygote zygote(sandbox_flags, std::move(fork_delegates),
- base::GlobalDescriptors::Descriptor(
- static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
-
- // This function call can return multiple times, once per fork().
- return zygote.ProcessRequests();
-}
-
-} // namespace content